fix: limit resource preview watches to active tab
Root cause: every local resource preview tab kept its own /api/local-folder/events EventSource alive. Hidden PDF and Office tabs consumed browser same-origin connection slots, so later preview iframes/file reads stalled and rendered as blank pages. Changes: - keep passive resource file watching active-tab only - close inactive resource-tab EventSources on tab activation and release - update the bug record with the PDF fifth-open and XLSX fourth-open repro and verification Verification: - node --check rust/crates/mnote-web/browser/document-resource-tab-runtime.js - cargo test -p mnote-web --manifest-path rust/Cargo.toml pdf_preview_page_does_not_render_visible_toolbar - cargo test -p mnote-web --manifest-path rust/Cargo.toml document_shell_returns_page_aggregate_snapshot - cargo build -p mnote-web --manifest-path rust/Cargo.toml - browser smoke: opened 5 XLSX previews; #4 and #5 completed with tableCount=1 - browser smoke: opened 5 DHA PDFs; #5 rendered 8/8 canvases, iframeCount=0, browser errors=0
This commit is contained in:
@@ -708,6 +708,7 @@ export const createResourceTabRuntime = (dependencies = {}) => {
|
||||
if (!activeEntry && window.__mnoteIntendedSlashRoot instanceof HTMLElement) window.__mnoteIntendedSlashRoot = null;
|
||||
if (role === 'primary') syncActiveResourceFileTreeRow(activeResource);
|
||||
syncActiveResourceUrlState(activeResource, role);
|
||||
syncActivePassiveResourceWatch(role, activeResource);
|
||||
syncOpenEditorsSnapshot();
|
||||
};
|
||||
|
||||
@@ -898,12 +899,7 @@ export const createResourceTabRuntime = (dependencies = {}) => {
|
||||
}
|
||||
entry.mindmapRuntime = null;
|
||||
}
|
||||
if (entry.resourceWatchEventSource) {
|
||||
try {
|
||||
entry.resourceWatchEventSource.close();
|
||||
} catch (_) {}
|
||||
entry.resourceWatchEventSource = null;
|
||||
}
|
||||
closePassiveResourceWatch(entry);
|
||||
if (entry.panel instanceof HTMLElement) entry.panel.replaceChildren();
|
||||
};
|
||||
|
||||
@@ -1092,11 +1088,40 @@ export const createResourceTabRuntime = (dependencies = {}) => {
|
||||
}
|
||||
};
|
||||
|
||||
const closePassiveResourceWatch = (entry) => {
|
||||
if (!entry?.resourceWatchEventSource) return;
|
||||
try {
|
||||
entry.resourceWatchEventSource.close();
|
||||
} catch (_) {}
|
||||
entry.resourceWatchEventSource = null;
|
||||
if (entry.panel instanceof HTMLElement) entry.panel.removeAttribute('data-mnote-resource-watch-ready');
|
||||
};
|
||||
|
||||
const isActiveResourceTabEntry = (entry) => {
|
||||
if (!(entry?.panel instanceof HTMLElement)) return false;
|
||||
if (entry.panel.hidden === false) return true;
|
||||
return entry.tab instanceof HTMLElement && entry.tab.getAttribute('aria-selected') === 'true';
|
||||
};
|
||||
|
||||
const closeInactivePassiveResourceWatches = (activeEntry) => {
|
||||
const role = normalizePaneRole(activeEntry?.paneRole || 'primary');
|
||||
resourceTabRegistry.forEach((entry) => {
|
||||
if (entry === activeEntry) return;
|
||||
if (normalizePaneRole(entry?.paneRole) !== role) return;
|
||||
closePassiveResourceWatch(entry);
|
||||
});
|
||||
};
|
||||
|
||||
const installPassiveResourceWatch = (entry) => {
|
||||
if (!entry || entry.session || typeof window.EventSource !== 'function') return;
|
||||
const rootUri = String(entry.rootUri || '').trim();
|
||||
const path = String(entry.path || '').trim();
|
||||
if (!rootUri || !path) return;
|
||||
if (!isActiveResourceTabEntry(entry)) {
|
||||
closePassiveResourceWatch(entry);
|
||||
return;
|
||||
}
|
||||
closeInactivePassiveResourceWatches(entry);
|
||||
if (entry.resourceWatchEventSource) {
|
||||
try {
|
||||
entry.resourceWatchEventSource.close();
|
||||
@@ -1130,6 +1155,17 @@ export const createResourceTabRuntime = (dependencies = {}) => {
|
||||
});
|
||||
};
|
||||
|
||||
const syncActivePassiveResourceWatch = (paneRole, activeResource) => {
|
||||
const activeEntry = activeResource ? resourceTabRegistry.get(activeResource) : null;
|
||||
if (!activeEntry) {
|
||||
resourceTabRegistry.forEach((entry) => {
|
||||
if (normalizePaneRole(entry?.paneRole) === normalizePaneRole(paneRole)) closePassiveResourceWatch(entry);
|
||||
});
|
||||
return;
|
||||
}
|
||||
installPassiveResourceWatch(activeEntry);
|
||||
};
|
||||
|
||||
const releaseInlinePdfResource = (entry) => {
|
||||
if (!entry) return;
|
||||
const pdf = entry.inlinePdfDocument;
|
||||
|
||||
Reference in New Issue
Block a user