import { computed, watchEffect, type Ref } from "vue"; import type { MagicDeviceInfo, IphoneDeviceState } from "./useTauri"; export type DeviceStatus = "active" | "cooldown" | "revoked" | "pending" | "unprotected"; export interface ComputedDevice { deviceId: string; name: string; platform: "mac" | "windows" | "ios" | "android" | "unknown"; model: string | null; osVersion: string | null; status: DeviceStatus; isCurrent: boolean; cooldownUntil: string | null; lastSeenAt: string | null; enrolledAt: string | null; } const ENROLLMENT_PROFILE_ID = "org.rebreak.mdm.enrollment"; const LOCK_PROFILE_ID = "org.rebreak.protection.contentfilter.sideload"; const APP_BUNDLE_ID = "org.rebreak.app"; function normalizePlatform(value: string | null | undefined): ComputedDevice["platform"] { const n = (value ?? "").toLowerCase(); if (n.startsWith("mac") || n === "darwin") return "mac"; if (n.startsWith("ios") || n.startsWith("iphone") || n.startsWith("ipad")) return "ios"; if (n.startsWith("android")) return "android"; if (n.startsWith("win")) return "windows"; return "unknown"; } function normalizeHostname(value: string): string { return (value.toLowerCase().split(".")[0] ?? "").replace(/[^a-z0-9]/g, ""); } export function useDeviceStatus( devices: Ref, localHostname: Ref, iphone: Ref, currentDeviceId?: Ref, ) { function isCurrentDevice(d: MagicDeviceInfo): boolean { if (currentDeviceId?.value) { return d.deviceId === currentDeviceId.value; } if (!localHostname.value) return false; const local = normalizeHostname(localHostname.value); return normalizeHostname(d.hostname) === local; } const currentBackendDevice = computed(() => { const found = devices.value.find(isCurrentDevice); if (!found) return null; return { deviceId: found.deviceId, name: found.model ?? found.hostname, platform: normalizePlatform(found.model ?? found.hostname), model: found.model, osVersion: found.osVersion, status: found.status, isCurrent: true, cooldownUntil: found.cooldownUntil, lastSeenAt: found.lastSeenAt, enrolledAt: found.magicEnrolledAt, }; }); const otherDevices = computed(() => { const currentId = currentBackendDevice.value?.deviceId; return devices.value .filter((d) => d.deviceId !== currentId) .map((d) => ({ deviceId: d.deviceId, name: d.model ?? d.hostname, platform: normalizePlatform(d.model ?? d.hostname), model: d.model, osVersion: d.osVersion, status: d.status, isCurrent: false, cooldownUntil: d.cooldownUntil, lastSeenAt: d.lastSeenAt, enrolledAt: d.magicEnrolledAt, })); }); const iosStars = computed(() => { if (!iphone.value) return null; return { enrollment: iphone.value.installedProfileIDs?.includes(ENROLLMENT_PROFILE_ID) ?? false, sideload: iphone.value.installedProfileIDs?.includes(LOCK_PROFILE_ID) ?? false, app: iphone.value.installedAppBundleIDs?.includes(APP_BUNDLE_ID) ?? false, isSupervised: iphone.value.isSupervised, }; }); // DEBUG: log current device matching details watchEffect(() => { const ids = devices.value.map((d) => ({ deviceId: d.deviceId, hostname: d.hostname, platform: d.model ?? d.hostname })); console.log("[useDeviceStatus] local deviceId:", currentDeviceId?.value ?? "(none)", "hostname:", localHostname.value ?? "(none)", "backend ids:", ids, "matched:", currentBackendDevice.value?.deviceId ?? "(none)"); }); return { currentBackendDevice, otherDevices, iosStars, }; }