fix: stabilize local attachment icons and office proxy urls

This commit is contained in:
lix-2026
2026-05-26 09:44:35 +08:00
parent 0a15595066
commit 8cd8b44db3
11 changed files with 564 additions and 14 deletions
@@ -2,6 +2,10 @@
// 当前先承接 SIDEBAR_TREE_JS 中的纯辅助函数。
// SIDEBAR_TREE_JS 会优先委托到 window.__mnoteLocalUploadRuntime
// 模块未加载时,inline fallback 保持旧行为。
import {
editorDocumentFromTiptapDocument,
legacyBlocksFromEditorDocument,
} from './document-tiptap-conversion-runtime.js';
function uploadedAssetTitle(asset) {
return String(asset && (asset.file_name || asset.title || asset.name) || '未命名附件').trim() || '未命名附件';
@@ -11,6 +15,117 @@ function uploadedAssetUrl(asset) {
return String(asset && (asset.sourcePath || asset.file_url || asset.signedUrl || asset.signed_url || asset.thumbnail_url) || '').trim();
}
function dispatchUploadedEditorChange(editorRoot, editor, deps) {
deps = deps || {};
if (!(editorRoot instanceof HTMLElement) || !editor || typeof editor.getJSON !== 'function') return;
var runtimeRoot = editorRoot.closest('[data-testid="mnote-leptos-tiptap-island-editor-root"]');
if (!(runtimeRoot instanceof HTMLElement) || typeof CustomEvent !== 'function') return;
try {
editorRoot.dispatchEvent(new Event('input', { bubbles: true }));
} catch (_) {
// ignore
}
var currentDocumentId = typeof deps.currentDocumentId === 'function' ? deps.currentDocumentId() : '';
var payload = {
protocol: 'mnote.leptos_tiptap.bridge.v1',
runtime: '8123-leptos-tiptap-runtime',
version: '1.1.0',
source: 'mnote:leptos-tiptap-spike',
event: 'mnote:leptos-tiptap-spike:change',
payload: {
documentId: String(currentDocumentId || '').trim() || null,
workspaceId: null,
title: '',
content: editor.getJSON(),
meta: {
dirtyCount: Date.now(),
editorFocused: document.activeElement === editorRoot || editorRoot.contains(document.activeElement),
slashOpen: false,
toolbarOpen: false,
selectedBlockIndex: null,
revision: null,
conflictDetectionKey: null,
readOnly: false
}
}
};
runtimeRoot.dispatchEvent(new CustomEvent('mnote:leptos-tiptap-spike:change', {
detail: payload,
bubbles: true
}));
}
function currentConflictDetectionKey() {
var script = document.getElementById('__MNOTE_PAGE_AGGREGATE__');
if (!script) return '';
try {
var body = JSON.parse(script.textContent || 'null');
return String(body && (body.conflictDetectionKey || body.conflict_detection_key || body.fileVersion || body.file_version) || '').trim();
} catch (_) {
return '';
}
}
function persistLocalFolderSelfChangeSuppression(documentId, expiresAt) {
var doc = String(documentId || '').trim();
if (!doc) return;
window.__mnoteLocalFolderSelfChangeSuppressions = window.__mnoteLocalFolderSelfChangeSuppressions || new Map();
window.__mnoteLocalFolderSelfChangeSuppressions.set(doc, expiresAt);
try {
var key = 'mnote.localFolder.selfChangeSuppressions.v1';
var existing = JSON.parse(window.sessionStorage.getItem(key) || '{}');
existing[doc] = expiresAt;
window.sessionStorage.setItem(key, JSON.stringify(existing));
} catch (_) {}
}
async function persistUploadedEditorChange(editor, asset, deps) {
deps = deps || {};
var isLocalAsset = typeof deps.isLocalUploadedAsset === 'function' ? deps.isLocalUploadedAsset(asset) : isLocalUploadedAsset(asset);
if (!isLocalAsset || !editor || typeof editor.getJSON !== 'function') return;
var documentId = String(
asset && (asset.document_id || asset.documentId)
|| (typeof deps.currentDocumentId === 'function' ? deps.currentDocumentId() : '')
|| ''
).trim();
var rootUri = String(
asset && (asset.root_uri || asset.rootUri)
|| (typeof deps.currentRootUri === 'function' ? deps.currentRootUri() : currentRootUri())
|| ''
).trim();
if (!documentId || !rootUri) return;
var tiptapDocument = editor.getJSON();
var editorDocument = editorDocumentFromTiptapDocument({ documentId: documentId }, tiptapDocument);
var content = legacyBlocksFromEditorDocument(editorDocument);
var savePayload = {
documentId: documentId,
sourceKind: 'local_folder',
rootUri: rootUri,
expectedFileVersion: currentConflictDetectionKey(),
contentFormat: 'editorBlocks',
editorSource: 'local-upload-runtime',
editorDocument: editorDocument,
content: content,
tiptapDocument: tiptapDocument,
blockCount: Array.isArray(editorDocument.blocks) ? editorDocument.blocks.length : 0
};
persistLocalFolderSelfChangeSuppression(documentId, Date.now() + 5000);
var response = await fetch('/api/documents/save', {
method: 'POST',
credentials: 'include',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(savePayload)
});
var result = await response.json().catch(function() { return null; });
if (!response.ok || !result || result.ok !== true) {
var message = result && (result.message || (result.error && result.error.message)) || ('save_failed_' + response.status);
document.documentElement.setAttribute('data-mnote-last-upload-save-error', message);
throw new Error(message);
}
document.documentElement.setAttribute('data-mnote-last-upload-saved', 'true');
document.documentElement.removeAttribute('data-mnote-last-upload-save-error');
}
function currentRootUri() {
var params = new URLSearchParams(window.location.search);
var fromUrl = (params.get('rootUri') || '').trim();
@@ -270,6 +385,8 @@ async function insertUploadedAssetIntoEditor(asset, targetRoot, deps) {
document.documentElement.setAttribute('data-mnote-last-upload-inserted', 'true');
document.documentElement.setAttribute('data-mnote-last-upload-asset-id', assetId || '');
document.documentElement.removeAttribute('data-mnote-last-upload-insert-error');
dispatchUploadedEditorChange(editorRoot, editor, deps);
await persistUploadedEditorChange(editor, asset, deps);
} else {
document.documentElement.setAttribute('data-mnote-last-upload-inserted', 'false');
document.documentElement.setAttribute('data-mnote-last-upload-insert-error', 'insert_content_failed');