import { useCallback, useEffect, useRef, useState } from "react"; import { ArrowSyncRegular } from "@fluentui/react-icons"; import { apiMessage } from "../../api"; import { Tag, type TagType } from "../ui/Tag"; import { message } from "../ui"; import { cx } from "../../lib/utils"; import { useI18n } from "../../lib/i18n"; import { getCellularIMS, type CellularIMSStatus } from "./deviceActions"; import { isDeviceOnline, isVoWiFiInUse } from "./shared"; import type { DeviceDetail } from "./types"; interface SMSChannelStatusRowProps { device: DeviceDetail; onRefreshOverview: () => void | Promise; } interface DisplayStatus { label: string; tone: TagType; } export function SMSChannelStatusRow({ device, onRefreshOverview }: SMSChannelStatusRowProps) { const { t } = useI18n(); const [cellular, setCellular] = useState(null); const [loading, setLoading] = useState(false); const requestSequence = useRef(0); const iccid = (device.modem?.iccid || "").trim(); const usesVoWiFi = isVoWiFiInUse(device) && !(device.modem?.imei && device.modem?.simInserted === false); const canProbeCellular = !usesVoWiFi && isDeviceOnline(device) && !!iccid && device.modem?.simInserted !== false; const probeCellular = useCallback(async () => { if (!canProbeCellular) return; const sequence = ++requestSequence.current; setLoading(true); try { const next = await getCellularIMS(device.id); if (sequence === requestSequence.current) setCellular(next); } catch { if (sequence === requestSequence.current) setCellular(null); } finally { if (sequence === requestSequence.current) setLoading(false); } }, [canProbeCellular, device.id]); // The overview tab is conditionally mounted, so this runs once when users // return to it and again when the active device/SIM/profile changes. useEffect(() => { requestSequence.current += 1; setCellular(null); setLoading(false); if (canProbeCellular) void probeCellular(); return () => { requestSequence.current += 1; }; }, [canProbeCellular, device.id, iccid, device.activeEsimProfileName, usesVoWiFi, probeCellular]); const refresh = async () => { if (loading) return; if (usesVoWiFi) { const sequence = ++requestSequence.current; setLoading(true); try { await onRefreshOverview(); } catch (error) { if (sequence === requestSequence.current) { message.error(apiMessage(error) || t("刷新短信通道状态失败")); } } finally { if (sequence === requestSequence.current) setLoading(false); } return; } await probeCellular(); }; let display: DisplayStatus; if (usesVoWiFi) { if (device.vowifiRuntime?.smsReady) display = { label: t("已就绪(VoWiFi)"), tone: "success" }; else if (device.vowifiRuntime?.imsReady) display = { label: t("已注册(IMS)"), tone: "success" }; else if (device.vowifiRuntime?.enabled) display = { label: t("未注册短信域"), tone: "warning" }; else display = { label: t("状态未知"), tone: "info" }; } else if (!canProbeCellular || !cellular) { display = { label: t("状态未知"), tone: "info" }; } else if (cellular.registered && cellular.csRegistered) { display = { label: t("已注册(CS, IMS)"), tone: "success" }; } else if (cellular.registered) { display = { label: t("已注册(IMS)"), tone: "success" }; } else if (cellular.csRegistered) { display = { label: t("已注册(CS)"), tone: "success" }; } else if (cellular.csKnown && cellular.supported) { display = { label: t("未注册短信域"), tone: "warning" }; } else { display = { label: t("状态未知"), tone: "info" }; } return (
{t("短信通道")}
{display.label}
); }