Files
xiaobai-review/frontend/m/js/boot.js
T
f0a1adf52f 施工(HEL-226): 实现登录门户与本机免密切换账号
用设备 Cookie 和授权表记住本机已验证账号,登录页按确认样图做成门户,不再把密码写进浏览器。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-08-29 11:24:39 +08:00

92 lines
2.7 KiB
JavaScript

(function (global) {
"use strict";
const THEME_KEY = "xiaobaiTheme";
function readTheme() {
try {
const stored = global.localStorage.getItem(THEME_KEY);
if (stored === "dark" || stored === "light") return stored;
} catch (_error) {
return "light";
}
if (global.matchMedia && global.matchMedia("(prefers-color-scheme: dark)").matches) {
return "dark";
}
return "light";
}
function applyTheme(theme) {
const normalized = theme === "dark" ? "dark" : "light";
const app = document.getElementById("m-app");
app.dataset.theme = normalized;
app.style.colorScheme = normalized;
document.body.style.backgroundColor = normalized === "dark" ? "#141519" : "#f4f5f7";
return normalized;
}
function toggle() {
const next = readTheme() === "dark" ? "light" : "dark";
try {
global.localStorage.setItem(THEME_KEY, next);
} catch (_error) {
// Theme still applies for the current page when storage is unavailable.
}
applyTheme(next);
}
global.MobileTheme = { readTheme: readTheme, applyTheme: applyTheme, toggle: toggle };
function syncKeyboardInset() {
const app = document.getElementById("m-app");
const visual = global.visualViewport;
if (!visual) {
app.style.setProperty("--m-keyboard-inset", "0px");
return;
}
// 键盘高度 = 布局视口高度 - 可视视口高度。iOS 弹键盘时会同时抬升 offsetTop,
// 若再扣 offsetTop 会把 inset 算成 0,导致输入区/底栏不避让,故只按高度差计算。
const inset = Math.max(0, global.innerHeight - visual.height);
app.style.setProperty("--m-keyboard-inset", inset + "px");
}
function bindViewport() {
const visual = global.visualViewport;
if (visual) {
visual.addEventListener("resize", syncKeyboardInset);
visual.addEventListener("scroll", syncKeyboardInset);
}
syncKeyboardInset();
}
async function boot() {
applyTheme(readTheme());
bindViewport();
let session = { authenticated: false };
try {
session = await global.MobileSession.me();
} catch (_error) {
session = { authenticated: false };
}
const hash = global.location.hash || "";
if (!session.authenticated) {
if (!/^#\/?auth/.test(hash)) global.location.replace("#/auth");
} else if (/^#\/?auth/.test(hash)) {
global.location.replace("#/hub/market");
}
removeBootSplash();
global.MobileRouter.init();
}
function removeBootSplash() {
const splash = document.getElementById("m-boot-splash");
if (splash) splash.remove();
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", boot, { once: true });
} else {
boot();
}
})(window);