Files
Hearth/app/src/main/assets/h5/js/webapp/topbar.js
T

87 lines
4.1 KiB
JavaScript
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.
// webAPP 顶栏:回退/前进/重载 + 标题 + 标签面板(切换/关闭)
// webapp topbar: back/forward/reload + title + tab panel (switch/close)
// 原生方法(webGoBack/webGoForward/webReload/switchTab/closeWebAppTask 13 才实现,
// 此处仅作为调用方,点击会静默 reject(符合预期)。
// Native methods (webGoBack/webGoForward/webReload/switchTab/closeWebApp) land in Task 13;
// this topbar is only a caller, clicks silently reject (expected).
// 展示/刷新顶栏:tabs 为标签数组(含 active 标记)
// Show/refresh the topbar: tabs is the tab array (with active flag)
window.showTopbar = function (tabs) {
let bar = document.getElementById('web-topbar');
if (!bar) {
bar = document.createElement('div');
bar.id = 'web-topbar';
const back = document.createElement('button');
back.id = 'tb-back'; back.title = '回退'; back.textContent = '←';
const fwd = document.createElement('button');
fwd.id = 'tb-fwd'; fwd.title = '前进'; fwd.textContent = '→';
const reload = document.createElement('button');
reload.id = 'tb-reload'; reload.title = '重载'; reload.textContent = '⟳';
const title = document.createElement('span');
title.className = 'tb-title'; title.id = 'tb-title';
const tabsBtn = document.createElement('button');
tabsBtn.id = 'tb-tabs';
bar.append(back, fwd, reload, title, tabsBtn);
document.body.appendChild(bar);
back.onclick = () => bridge.call('webGoBack');
fwd.onclick = () => bridge.call('webGoForward');
reload.onclick = () => bridge.call('webReload');
}
// 标签按钮:调原生弹出标签面板(PopupWindow 在内容 WebView 之上)
// Tab button: show the native tab panel (PopupWindow above the content WebView)
document.getElementById('tb-tabs').onclick = () => bridge.call('showTabPanel');
document.getElementById('tb-tabs').textContent = `标签 (${tabs.length})`;
const active = tabs.find(t => t.active);
document.getElementById('tb-title').textContent = active ? active.name : '';
// 无标签时隐藏顶栏与标签面板(回到桌面)
// Hide the topbar and tab panel when no tabs remain (back to desktop)
bar.style.display = tabs.length ? 'flex' : 'none';
const panel = document.getElementById('tab-panel');
if (panel && !tabs.length) panel.style.display = 'none';
// 有 webapp 时隐藏 webapplist 页面内容(避免半透明顶栏透出列表控件),无 webapp 时恢复
// Hide the webapp list content while a webapp is open (so the translucent topbar
// doesn't show the list controls through it); restore when none are open
document.body.classList.toggle('webapp-active', tabs.length > 0);
};
// 标签面板:列出所有标签,点击切换,× 关闭
// Tab panel: list all tabs, click to switch, × to close
// 用 createElement + textContent/dataset 渲染,避免 innerHTML 拼接用户数据(XSS
// Render with createElement + textContent/dataset to avoid innerHTML user data (XSS)
function showTabPanel(tabs) {
let panel = document.getElementById('tab-panel');
if (!panel) {
panel = document.createElement('div');
panel.id = 'tab-panel';
document.body.appendChild(panel);
}
panel.textContent = '';
tabs.forEach(t => {
const row = document.createElement('div');
row.className = 'tab-row' + (t.active ? ' active' : '');
row.dataset.id = t.id;
const name = document.createElement('span');
name.className = 'tab-name';
name.textContent = t.name;
const close = document.createElement('button');
close.className = 'tab-close';
close.title = '关闭';
close.textContent = '×';
name.onclick = () => { bridge.call('switchTab', t.id); closeTabPanel(); };
close.onclick = () => bridge.call('closeWebApp', t.id);
row.append(name, close);
panel.appendChild(row);
});
// 横向展开(CSS flex-direction: row
// Expand horizontally (CSS flex-direction: row)
panel.style.display = 'flex';
}
// 收起标签面板
// Collapse the tab panel
function closeTabPanel() {
const panel = document.getElementById('tab-panel');
if (panel) panel.style.display = 'none';
}