Compare commits

...
2 Commits
Author SHA1 Message Date
xiaoqidun 3634a6125c feat(前端界面): 优化WebUI系统字体权限请求
build.yaml / build (push) Successful in 35s
2026-07-07 15:30:18 +08:00
xiaoqidun ebfe7b5d17 feat(前端界面): OFDGo WebUI优化系统字体权限请求 2026-07-07 15:14:25 +08:00
3 changed files with 84 additions and 8 deletions
+1
View File
@@ -101,6 +101,7 @@
<button id="fontAddButton" class="small-button" type="button">添加</button> <button id="fontAddButton" class="small-button" type="button">添加</button>
</div> </div>
</div> </div>
<div id="fontPermissionHint" class="font-permission-hint" hidden>需授权读取系统字体</div>
<div id="fontList" class="font-list"></div> <div id="fontList" class="font-list"></div>
</section> </section>
</aside> </aside>
+10
View File
@@ -652,6 +652,16 @@ body[data-hide-meta] .meta-panel {
gap: 8px; gap: 8px;
} }
.font-permission-hint {
margin: 0 0 8px;
padding: 7px 8px;
border: 1px solid var(--line);
background: #ffffff;
color: var(--text-muted);
font-size: 12px;
line-height: 1.35;
}
.font-row { .font-row {
display: grid; display: grid;
grid-template-columns: minmax(0, 1fr) auto; grid-template-columns: minmax(0, 1fr) auto;
+73 -8
View File
@@ -53,6 +53,8 @@ const state = {
localFonts: [], localFonts: [],
userFonts: [], userFonts: [],
systemFontCatalog: [], systemFontCatalog: [],
systemFontCatalogLoaded: false,
systemFontPermission: "prompt",
doc: null, doc: null,
pageIndex: 0, pageIndex: 0,
scale: 1, scale: 1,
@@ -108,11 +110,12 @@ const el = {
docFontList: document.querySelector("#docFontList"), docFontList: document.querySelector("#docFontList"),
docFontSummary: document.querySelector("#docFontSummary"), docFontSummary: document.querySelector("#docFontSummary"),
availableFontSummary: document.querySelector("#availableFontSummary"), availableFontSummary: document.querySelector("#availableFontSummary"),
fontPermissionHint: document.querySelector("#fontPermissionHint"),
fontList: document.querySelector("#fontList"), fontList: document.querySelector("#fontList"),
statusText: document.querySelector("#statusText"), statusText: document.querySelector("#statusText"),
}; };
el.ofdButton.addEventListener("click", () => el.ofdInput.click()); el.ofdButton.addEventListener("click", openOFDFile);
el.togglePagesButton.addEventListener("click", () => toggleSidebar("pages")); el.togglePagesButton.addEventListener("click", () => toggleSidebar("pages"));
el.toggleMetaButton.addEventListener("click", () => toggleSidebar("meta")); el.toggleMetaButton.addEventListener("click", () => toggleSidebar("meta"));
el.fontAddButton.addEventListener("click", () => el.fontInput.click()); el.fontAddButton.addEventListener("click", () => el.fontInput.click());
@@ -148,11 +151,19 @@ el.viewerPanel.addEventListener("dblclick", openOFDFromViewer);
updateSidebarState(); updateSidebarState();
boot(); boot();
function openOFDFromViewer() { async function openOFDFile() {
if (document.body.hasAttribute("aria-busy")) {
return;
}
await requestLocalFontsBeforeOpen();
el.ofdInput.click();
}
async function openOFDFromViewer() {
if (state.doc || document.body.hasAttribute("aria-busy")) { if (state.doc || document.body.hasAttribute("aria-busy")) {
return; return;
} }
el.ofdInput.click(); await openOFDFile();
} }
function toggleSidebar(side) { function toggleSidebar(side) {
@@ -194,6 +205,7 @@ async function boot() {
renderFontList(); renderFontList();
updateControls(); updateControls();
updateLocalFontButton(); updateLocalFontButton();
await refreshLocalFontPermission();
setStatus(STATUS.ready); setStatus(STATUS.ready);
setBusy(false); setBusy(false);
} catch (err) { } catch (err) {
@@ -394,19 +406,49 @@ async function loadLocalFonts() {
} }
} }
async function requestLocalFontsBeforeOpen() {
if (!canReadLocalFonts() || state.systemFontCatalogLoaded || state.systemFontPermission === "denied") {
return;
}
setBusy(true, "正在请求授权", 12, "正在请求授权");
try {
const available = await queryLocalFonts();
setStatus(available.length ? `已授权 ${available.length} 个系统字体` : "未读取到系统字体");
} catch (err) {
if (err && err.name === "NotAllowedError") {
setStatus("未授权读取系统字体");
return;
}
setStatus(String(err.message || err));
} finally {
setBusy(false);
}
}
async function queryLocalFonts() { async function queryLocalFonts() {
const available = await window.queryLocalFonts(); try {
state.systemFontCatalog = available; const available = await window.queryLocalFonts();
return available; state.systemFontCatalog = available;
state.systemFontCatalogLoaded = true;
state.systemFontPermission = "granted";
updateFontPermissionHint();
return available;
} catch (err) {
if (err && err.name === "NotAllowedError") {
state.systemFontPermission = "denied";
updateFontPermissionHint();
}
throw err;
}
} }
async function autoLoadDocumentLocalFonts(openSeq) { async function autoLoadDocumentLocalFonts(openSeq) {
if (!externalDocumentFontNames().length || !canReadLocalFonts()) { if (!externalDocumentFontNames().length || !canReadLocalFonts() || state.systemFontPermission === "denied") {
return false; return false;
} }
setProgress("正在匹配字体", 62, STATUS.fonts); setProgress("正在匹配字体", 62, STATUS.fonts);
try { try {
const available = state.systemFontCatalog.length ? state.systemFontCatalog : await queryLocalFonts(); const available = state.systemFontCatalogLoaded ? state.systemFontCatalog : await queryLocalFonts();
if (openSeq !== state.openSeq) { if (openSeq !== state.openSeq) {
return false; return false;
} }
@@ -765,12 +807,35 @@ function updateLocalFontButton() {
const supported = canReadLocalFonts(); const supported = canReadLocalFonts();
el.localFontButton.disabled = !supported; el.localFontButton.disabled = !supported;
el.localFontButton.title = supported ? "授权读取浏览器可访问的系统字体" : "当前浏览器不支持读取系统字体"; el.localFontButton.title = supported ? "授权读取浏览器可访问的系统字体" : "当前浏览器不支持读取系统字体";
updateFontPermissionHint();
}
function updateFontPermissionHint() {
el.fontPermissionHint.hidden = !canReadLocalFonts() || state.systemFontPermission === "granted";
} }
function canReadLocalFonts() { function canReadLocalFonts() {
return typeof window.queryLocalFonts === "function"; return typeof window.queryLocalFonts === "function";
} }
async function refreshLocalFontPermission() {
if (!canReadLocalFonts() || !navigator.permissions?.query) {
updateFontPermissionHint();
return;
}
try {
const permission = await navigator.permissions.query({ name: "local-fonts" });
state.systemFontPermission = permission.state;
permission.onchange = () => {
state.systemFontPermission = permission.state;
updateFontPermissionHint();
};
} catch {
state.systemFontPermission = "prompt";
}
updateFontPermissionHint();
}
async function openDocument(options = {}) { async function openDocument(options = {}) {
if (!state.ofdBytes) { if (!state.ofdBytes) {
return; return;