Files
controller-v2/client/src/components/ConnectionPlaceholder.tsx
T
2026-10-22 13:50:22 +08:00

63 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useMemo } from "react";
import { useDevice } from "@/contexts/DeviceContext";
import { isLikelyNetworkFetchError } from "@/lib/networkError";
import { Loader2, Wifi } from "lucide-react";
import BottomNav from "@/components/BottomNav";
import localeZh from "@/locales/data-zh.json";
import { getUiLanguageOverride, isKnownLanguage, resolveLocalePack } from "@/locales/resolveLocale";
type ConnectLocale = (typeof localeZh)["connect"];
function pickConnectLocale(effectiveLanguage: number): ConnectLocale {
// 前端语言覆盖(de/es/fr)优先;否则沿用 URL ?lang=(设备语言);最后回退到生效语言。
const override = getUiLanguageOverride();
if (override != null) return resolveLocalePack(override).connect as ConnectLocale;
const params = new URLSearchParams(window.location.search);
const langParam = Number(params.get("lang"));
const lang = isKnownLanguage(langParam) ? langParam : effectiveLanguage;
return resolveLocalePack(lang).connect as ConnectLocale;
}
function fmt(template: string, vars: Record<string, string>): string {
let s = template;
for (const [k, v] of Object.entries(vars)) {
s = s.split(`{${k}}`).join(v);
}
return s;
}
/** 自动连接设备时的占位(替代原 ConnectScreen) */
export default function ConnectionPlaceholder() {
const { ip, isConnecting, error, ipMissing, effectiveLanguage } = useDevice();
const text = useMemo(() => pickConnectLocale(effectiveLanguage), [effectiveLanguage]);
return (
<div className="min-h-screen bg-black flex flex-col items-center justify-center px-6 pb-24">
<div className="mb-6 flex size-[4.5rem] items-center justify-center rounded-[16px] border border-white/15">
<Wifi size={28} className="text-[#00FFF6]/80" />
</div>
{ipMissing ? (
<>
<p className="text-[15px] text-white/80 mb-2">{text.ipMissingTitle}</p>
<p className="text-[13px] text-white/45 text-center max-w-xs">{text.ipMissingDesc}</p>
<p className="text-[13px] text-[#00FFF6]/80 mt-3 font-mono">?ip=</p>
</>
) : isConnecting ? (
<>
<Loader2 size={28} className="animate-spin text-[#00FFF6] mb-3" />
<p className="text-[15px] text-white/70">{fmt(text.connecting, { ip })}</p>
</>
) : (
<>
<p className="text-[15px] text-white/80 mb-2">{text.failedTitle}</p>
<p className="text-[13px] text-white/45 text-center max-w-xs">
{error && !isLikelyNetworkFetchError(error) ? error : text.failedDesc}
</p>
<p className="text-[12px] text-white/30 mt-3 text-center max-w-xs">{fmt(text.failedHint, { ip })}</p>
</>
)}
<BottomNav />
</div>
);
}