mirror of
https://github.com/MengMengCode/VoCat.git
synced 2026-08-19 06:13:42 +08:00
feat: add home carrier information to ModemSummary interface
This commit is contained in:
@@ -4,7 +4,7 @@ import { FieldRow } from "./FieldRow";
|
||||
import { useShowSensitive } from "./shared";
|
||||
import type { DeviceDetail } from "./types";
|
||||
import { useI18n } from "../../lib/i18n";
|
||||
import { carrierBrandIso } from "../../lib/carrier";
|
||||
import { carrierIso } from "../../lib/carrier";
|
||||
import { CountryFlag } from "../CountryFlag";
|
||||
|
||||
export interface OverviewSimPanelProps {
|
||||
@@ -22,7 +22,7 @@ export function OverviewSimPanel({ device, simOperatorDisplay, customPhoneNumber
|
||||
const sensitive = !showSensitive;
|
||||
const activeEsim = (device.activeEsimProfileName || "").trim();
|
||||
const flightOn = device.vowifiActive || modem?.operatingMode === 0 || modem?.operatingMode === 4;
|
||||
const carrierCountryCode = carrierBrandIso(modem?.nativeSpn, modem?.imsi);
|
||||
const carrierCountryCode = String(modem?.homeCarrierCountryCode ?? "").trim() || carrierIso(modem?.imsi);
|
||||
const displayedPhoneNumber = customPhoneNumber?.trim() || device.localPhone || "--";
|
||||
const backendLabel =
|
||||
device.backendMode === "qmi" ? "QMI" : device.backendMode === "mbim" ? "MBIM" : device.backendMode === "at" ? "AT" : "Auto";
|
||||
|
||||
@@ -259,20 +259,18 @@ export function simOperatorDisplay(device?: DeviceDetail | null): string {
|
||||
const spn = String(modem?.nativeSpn ?? "").trim();
|
||||
const name = oplPnnName(modem) || firstPnnName(modem?.pnn);
|
||||
const plmn = plmnOf(modem);
|
||||
// EF_SPN is the SIM's customer-facing brand. Do not append the currently
|
||||
// visited PLMN: a roaming Lebara UK SIM on a Chinese network would otherwise
|
||||
// be mislabeled as "Lebara (460xx)". Append the home/authentication PLMN
|
||||
// resolved from IMSI instead, so GigSky on 222-01 renders as
|
||||
// "GigSky (22201)" even while roaming.
|
||||
if (spn) {
|
||||
const home = lookupCarrier(modem?.imsi);
|
||||
return withPlmn(spn, home ? home.mcc + home.mnc : cardPlmnOf(modem));
|
||||
}
|
||||
if (name) return withPlmn(name, plmn);
|
||||
// Home ("original") carrier resolved from the SIM's IMSI via the MCC/MNC table.
|
||||
// Readable even when the modem isn't camped (VoWiFi RF-off / flight mode).
|
||||
// "Original Carrier" means the IMSI home/authentication network. EF_SPN is
|
||||
// only a profile-supplied display brand (travel eSIMs and MVNOs may put their
|
||||
// storefront name there), so it must not override a known home PLMN.
|
||||
const resolvedName = String(modem?.homeCarrierName ?? "").trim();
|
||||
const resolvedPLMN = String(modem?.homeCarrierPlmn ?? "").trim();
|
||||
if (resolvedName) return withPlmn(resolvedName, resolvedPLMN);
|
||||
const carrier = lookupCarrier(modem?.imsi);
|
||||
if (carrier) return withPlmn(carrier.name, carrier.mcc + carrier.mnc);
|
||||
// If the bundled carrier database cannot resolve the home PLMN, retain the
|
||||
// card's own labels as graceful, data-driven fallbacks.
|
||||
if (spn) return withPlmn(spn, cardPlmnOf(modem));
|
||||
if (name) return withPlmn(name, plmn);
|
||||
if (plmn) return plmn;
|
||||
const cardPlmn = cardPlmnOf(modem);
|
||||
if (cardPlmn) return cardPlmn;
|
||||
|
||||
@@ -21,6 +21,10 @@ function profileLabel(profile: { name?: string; serviceProviderName?: string; ic
|
||||
return String(profile.name || profile.serviceProviderName || profile.iccid).trim();
|
||||
}
|
||||
|
||||
function currentDeviceICCID(device: DeviceListItem) {
|
||||
return String(device.modem?.iccid || device.vowifiRuntime?.iccid || "").trim();
|
||||
}
|
||||
|
||||
export function DeviceBindingsDialog(props: DeviceBindingsDialogProps) {
|
||||
const { t } = useI18n();
|
||||
const { open, proxy, proxies, devices, bindings, busy, onAdd, onDelete, onClose } = props;
|
||||
@@ -30,7 +34,7 @@ export function DeviceBindingsDialog(props: DeviceBindingsDialogProps) {
|
||||
const [selected, setSelected] = useState<string[]>([]);
|
||||
const proxyName = proxy?.name || proxy?.id || "";
|
||||
const deviceKey = devices
|
||||
.map((device) => `${device.id}:${String(device.modem?.iccid || "").trim()}`)
|
||||
.map((device) => `${device.id}:${currentDeviceICCID(device)}`)
|
||||
.sort()
|
||||
.join("|");
|
||||
const current = useMemo(
|
||||
@@ -53,7 +57,7 @@ export function DeviceBindingsDialog(props: DeviceBindingsDialogProps) {
|
||||
let active = true;
|
||||
setLoadingProfiles(true);
|
||||
Promise.allSettled(devices.map(async (device) => {
|
||||
const currentICCID = String(device.modem?.iccid || "").trim();
|
||||
const currentICCID = currentDeviceICCID(device);
|
||||
let installed: ProfileProxyCandidate[] = [];
|
||||
try {
|
||||
const data = await api<EsimOverview>(`/devices/${encodeURIComponent(device.id)}/esim`);
|
||||
|
||||
@@ -101,7 +101,7 @@ export function NetworkAccessCard({
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-[10px] text-gray-400">
|
||||
{t("在内置内网网段之外始终放行的 CIDR 或单个 IP(例如 203.0.113.0/24)。")}
|
||||
{t("在内置内网网段之外始终放行的 CIDR 或单个 IP;也允许通知推送访问这些目标地址(例如 198.18.0.0/15)。")}
|
||||
</p>
|
||||
{cidrs.length === 0 ? (
|
||||
<div className="rounded-lg border border-dashed border-gray-200 bg-gray-50/30 py-2 text-center text-xs text-gray-400 dark:border-white/10 dark:bg-white/5">
|
||||
|
||||
@@ -47,13 +47,3 @@ export function carrierIso(imsi?: string): string {
|
||||
if (hit) return hit.iso;
|
||||
return data.i[imsiDigits(imsi).slice(0, 3)] ?? "";
|
||||
}
|
||||
|
||||
// carrierBrandIso keeps the normal IMSI country flag for branded/MVNO SIMs.
|
||||
// Lebara UK's Vodafone-NL-hosted 204-04 eSIM is the one known exception: its
|
||||
// customer-facing country is GB even though AKA must continue using 204-04.
|
||||
export function carrierBrandIso(spn?: string, imsi?: string): string {
|
||||
const brand = String(spn ?? "").trim().toLowerCase();
|
||||
const digits = imsiDigits(imsi);
|
||||
if (brand.includes("lebara") && digits.startsWith("20404")) return "gb";
|
||||
return carrierIso(imsi);
|
||||
}
|
||||
|
||||
@@ -352,8 +352,8 @@ export const EN_DICT: Record<string, string> = {
|
||||
"Opening to the public internet greatly expands the attack surface. Use a strong password and switch back to Internal Only as soon as possible.",
|
||||
额外放行网段: "Additional Allowed Ranges",
|
||||
添加网段: "Add Range",
|
||||
"在内置内网网段之外始终放行的 CIDR 或单个 IP(例如 203.0.113.0/24)。":
|
||||
"CIDRs or single IPs always allowed in addition to the built-in internal ranges (e.g. 203.0.113.0/24).",
|
||||
"在内置内网网段之外始终放行的 CIDR 或单个 IP;也允许通知推送访问这些目标地址(例如 198.18.0.0/15)。":
|
||||
"CIDRs or single IPs always allowed in addition to the built-in internal ranges; notification delivery may also access these destinations (e.g. 198.18.0.0/15).",
|
||||
暂无额外放行网段: "No additional allowed ranges",
|
||||
信任代理请求头: "Trust Proxy Headers",
|
||||
"仅在系统位于可信反向代理之后时开启,按 X-Forwarded-For 判定来源;否则客户端可伪造该头绕过内网限制。":
|
||||
|
||||
+5247
-2
File diff suppressed because it is too large
Load Diff
@@ -64,6 +64,9 @@ export interface ModemSummary {
|
||||
cardMcc?: string;
|
||||
cardMnc?: string;
|
||||
cardCountry?: string;
|
||||
homeCarrierName?: string;
|
||||
homeCarrierPlmn?: string;
|
||||
homeCarrierCountryCode?: string;
|
||||
serviceBlocked?: boolean;
|
||||
blockedReason?: string;
|
||||
networkMode: string;
|
||||
|
||||
Reference in New Issue
Block a user