60 lines
4.8 KiB
JavaScript
60 lines
4.8 KiB
JavaScript
// 桌面路由:侧边栏 5 页 + 页面切换 + 顶部时间
|
||
// Launcher router: 5 sidebar pages + page switching + top clock
|
||
// 侧边栏图标:内联 SVG(stroke=currentColor,跟随主题色),替代 emoji
|
||
// Sidebar icons: inline SVG (stroke=currentColor, follows theme color), replacing emoji
|
||
const SVG_ICONS = {
|
||
home: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M3 11l9-8 9 8"/><path d="M5 9.5V21h14V9.5"/><path d="M10 21v-6h4v6"/></svg>',
|
||
immersive: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M5 11l1.5-4.5A2 2 0 018.4 5h7.2a2 2 0 011.9 1.5L19 11"/><path d="M3 11v5a1 1 0 001 1h1a1 1 0 001-1v-1h12v1a1 1 0 001 1h1a1 1 0 001-1v-5"/><circle cx="7.5" cy="16" r="1.6"/><circle cx="16.5" cy="16" r="1.6"/></svg>',
|
||
webapp: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M3 12h18"/><path d="M12 3a15 15 0 010 18a15 15 0 010-18"/></svg>',
|
||
app: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="8" height="8" rx="2"/><rect x="13" y="3" width="8" height="8" rx="2"/><rect x="3" y="13" width="8" height="8" rx="2"/><rect x="13" y="13" width="8" height="8" rx="2"/></svg>',
|
||
settings: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 11-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33a1.65 1.65 0 00-1 1.51V21a2 2 0 11-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 11-2.83-2.83l.06-.06a1.65 1.65 0 00.33-1.82a1.65 1.65 0 00-1.51-1H3a2 2 0 110-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 112.83-2.83l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 114 0v.09a1.65 1.65 0 001 1.51a1.65 1.65 0 001.82-.33l.06-.06a2 2 0 112.83 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 110 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>',
|
||
};
|
||
|
||
const PAGES = [
|
||
{ id: 'home', label: '首页', icon: SVG_ICONS.home },
|
||
{ id: 'immersive', label: '沉浸首页', icon: SVG_ICONS.immersive },
|
||
{ id: 'webapplist', label: 'H5 应用', icon: SVG_ICONS.webapp },
|
||
{ id: 'applist', label: '安卓 APP', icon: SVG_ICONS.app },
|
||
{ id: 'settings', label: '设置', icon: SVG_ICONS.settings },
|
||
];
|
||
|
||
const router = {
|
||
current: 'home',
|
||
navigate(id) {
|
||
this.current = id;
|
||
document.querySelectorAll('[data-page]').forEach(el =>
|
||
el.classList.toggle('active', el.dataset.page === id));
|
||
// 切页时把前台 webapp 丢到后台(隐藏内容 WebView,标签状态保留)
|
||
// Hide the foreground webapp when switching pages (keep tab state)
|
||
bridge.call('hideWebApps').catch(() => {});
|
||
// 同时隐藏 webapp 顶栏与标签面板(离开 webapp 场景)
|
||
// Also hide the webapp topbar and tab panel (leaving the webapp context)
|
||
const topbar = document.getElementById('web-topbar');
|
||
if (topbar) topbar.style.display = 'none';
|
||
const tabPanel = document.getElementById('tab-panel');
|
||
if (tabPanel) tabPanel.style.display = 'none';
|
||
// 移除 webapp-active:webapp 已丢后台,恢复 webapp 列表显示
|
||
// Remove webapp-active: the webapp is backgrounded, restore the list display
|
||
document.body.classList.remove('webapp-active');
|
||
// 关闭长按菜单(切页时)
|
||
// Close the long-press menu on page switch
|
||
document.querySelectorAll('.wapp-menu').forEach((m) => m.remove());
|
||
// 非首页时侧边栏顶部显示小时间(容器始终占位,仅切换可见性避免撑动图标)
|
||
// Show the small clock at the sidebar top when not on home (the container
|
||
// always occupies space; only toggle visibility to avoid shifting icons)
|
||
const clock = document.getElementById('rail-clock');
|
||
if (clock) clock.style.visibility = (id === 'home') ? 'hidden' : 'visible';
|
||
// 延迟内容加载到下一帧:让切换动画先流畅播放,避免加载重活(查应用/拉清单)
|
||
// 在动画帧内阻塞导致卡顿
|
||
// Defer content loading to the next frame: let the switch animation play
|
||
// smoothly first, avoiding jank from heavy loads (app query / manifest fetch)
|
||
// blocking within the animation frame
|
||
requestAnimationFrame(() => {
|
||
if (id === 'home') window.updateHomeCards && window.updateHomeCards();
|
||
if (id === 'applist') window.loadAppList && window.loadAppList();
|
||
if (id === 'webapplist') window.loadWebAppList && window.loadWebAppList();
|
||
if (id === 'settings') window.loadSettings && window.loadSettings();
|
||
});
|
||
}
|
||
};
|