Fix local folder title option refresh race

This commit is contained in:
lix-2026
2026-05-26 17:24:05 +08:00
parent 2c7a91e1fb
commit 58e2fdb5d8
6 changed files with 52 additions and 1 deletions
@@ -160,6 +160,21 @@ import {
titleEndpoint: '/api/documents/title',
editorHostKind: 'leptos_tiptap_island',
});
const aggregateDocumentId = (aggregate) => {
return String(aggregate?.identity?.documentId || aggregate?.identity?.document_id || aggregate?.pageId || aggregate?.page_id || '').trim();
};
const aggregatePageOptions = (aggregate) => {
return aggregate?.layout?.pageOptions || aggregate?.layout?.page_options || aggregate?.layoutOptions || aggregate?.layout_options || null;
};
const withPageOptions = (aggregate, pageOptions) => {
if (!aggregate || !pageOptions) return aggregate;
const next = { ...aggregate };
next.layout = next.layout && typeof next.layout === 'object' ? { ...next.layout } : {};
next.layout.pageOptions = { ...pageOptions };
next.layout_options = { ...pageOptions };
next.layoutOptions = { ...pageOptions };
return next;
};
const syncPageAggregateScript = (session, aggregate) => {
if (!session || !aggregate) return;
const scriptId = session.pageAggregateScriptId || '__MNOTE_PAGE_AGGREGATE__';
@@ -171,8 +186,24 @@ import {
document.body.appendChild(node);
}
try {
node.textContent = JSON.stringify(aggregate);
let existingAggregate = null;
try {
existingAggregate = JSON.parse(node.textContent || 'null');
} catch (_) {
existingAggregate = null;
}
const localWriteAt = Number(node.getAttribute('data-mnote-page-options-local-write-at') || 0);
const preserveRecentLocalOptions = localWriteAt > 0
&& Date.now() - localWriteAt < 15000
&& aggregateDocumentId(existingAggregate) === aggregateDocumentId(aggregate);
const nextAggregate = preserveRecentLocalOptions
? withPageOptions(aggregate, aggregatePageOptions(existingAggregate))
: aggregate;
node.textContent = JSON.stringify(nextAggregate);
node.setAttribute('data-mnote-page-aggregate-synced-at', String(Date.now()));
window.dispatchEvent(new CustomEvent('mnote:page-aggregate-synced', {
detail: { scriptId, documentId: aggregateDocumentId(nextAggregate) }
}));
} catch (error) {
console.warn('mnote Page Aggregate script 同步失败', error);
}
@@ -988,6 +988,8 @@ export const createDocumentSessionRuntime = (dependencies = {}) => {
return;
}
}
session.latestAggregate = nextAggregate;
syncPageAggregateScript(session, nextAggregate);
const nextBody = nextAggregate?.body || {};
const nextPermissions = nextAggregate?.head?.permissions || {};
const nextConflictKey = conflictDetectionKeyFromBody(nextBody);
@@ -648,6 +648,7 @@ export function createSidebarPageSettingsRuntime(context) {
aggregate.layout_options = Object.assign({}, nextOptions);
script.textContent = JSON.stringify(aggregate);
script.setAttribute('data-mnote-page-options-synced-at', String(Date.now()));
script.setAttribute('data-mnote-page-options-local-write-at', String(Date.now()));
}
} catch (_) {}
}
@@ -2769,6 +2769,15 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
if (isPageSettingsOpen()) renderPageSettingsPopover();
selectSidebarFileTreeDocument(detail.documentId, { scrollIntoView: false });
});
window.addEventListener('mnote:page-aggregate-synced', function(event) {
var detail = event && event.detail ? event.detail : {};
if (detail.scriptId && detail.scriptId !== '__MNOTE_PAGE_AGGREGATE__') return;
var documentId = searchText(detail.documentId || '');
if (documentId && currentDocumentId() && documentId !== currentDocumentId()) return;
pageUiState.pageOptions = null;
applyPageOptionsToShell();
if (isPageSettingsOpen()) renderPageSettingsPopover();
});
restoreSidebarTreeTab();
startLocalFolderSidebarWatch();
})();
@@ -2412,6 +2412,13 @@ mod tests {
assert!(DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("document.createElement('script')"));
assert!(DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS
.contains("syncPageAggregateScript({ pageAggregateScriptId"));
assert!(
DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("data-mnote-page-options-local-write-at")
);
assert!(DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("mnote:page-aggregate-synced"));
assert!(
DOCUMENT_SESSION_RUNTIME_JS.contains("syncPageAggregateScript(session, nextAggregate)")
);
assert!(DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("document-slash-position-runtime.js"));
assert!(DOCUMENT_SLASH_POSITION_RUNTIME_JS.contains("observeSlashMenuPosition"));
assert!(DOCUMENT_SLASH_POSITION_RUNTIME_JS.contains("scheduleSlashMenuPosition"));
@@ -908,6 +908,7 @@ mod tests {
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("data-mnote-dev-hot-reload"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("window.clearInterval(timer)"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("mnote:primary-document-activated"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("mnote:page-aggregate-synced"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("pageUiState.pageOptions = null"));
}