Files
mnote/rust/crates/mnote-web/browser/sidebar-tree-runtime.js
T

3871 lines
190 KiB
JavaScript
Raw Normal View History

2026-05-26 01:31:28 +08:00
import { createSidebarWorkspaceRuntime } from './sidebar-workspace-runtime.js';
2026-05-26 02:35:08 +08:00
import { createSidebarPageTreeRuntime } from './sidebar-page-tree-runtime.js';
import { createSidebarTreeLiveApplyRuntime } from './sidebar-tree-live-apply-runtime.js';
import { createSidebarFileTreeOpenRuntime } from './sidebar-filetree-open-runtime.js';
import { createSidebarAttachmentOpenRuntime } from './sidebar-attachment-open-runtime.js';
import { createSidebarFileTreeCommandRuntime } from './sidebar-filetree-command-runtime.js';
import { createSidebarFileTreeUploadRuntime } from './sidebar-filetree-upload-runtime.js';
import { createSidebarPageAiRuntime } from './sidebar-page-ai-runtime.js';
import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtime.js';
2026-05-26 01:31:28 +08:00
(function(){
if (window.__mnoteSidebarTreeRuntimeStarted) return;
window.__mnoteSidebarTreeRuntimeStarted = true;
var FILETREE_DRAG_MIME = 'application/x-mnote-filetree-row-ids';
var MNOTE_SIDEBAR_TREE_MODE_KEY = 'mnote.sidebar.tree.mode';
var MNOTE_RECENT_LOCAL_ROOTS_KEY_PREFIX = 'mnote.localFolder.recentRoots:';
var MNOTE_LAST_CLOUD_WORKSPACE_KEY = 'mnote.workspace.lastCloudWorkspaceId';
var MNOTE_GLOBAL_SHOW_HEADING_NUMBERS_KEY = 'mnote.global.showHeadingNumbers';
var mnoteNavigationInFlight = '';
var draggingFileTreeRowIds = [];
var activeFileTreeDropRow = null;
var sidebarFileTreeClipboard = null;
var sidebarFileTreeSelection = {
selectedRowIds: new Set(),
anchorRowId: null,
focusedRowId: null
};
var activeTreeContextMenu = null;
var pageUiState = {
pageOptions: null,
pageWidthPreferences: null,
historySnapshots: [],
pageSettingsOpen: false,
localIndexSummary: {
scopeKey: '',
loading: false,
error: '',
backlinks: null,
tags: null
}
};
function closestAction(target, selector) {
var node = target && target.nodeType === Node.TEXT_NODE ? target.parentElement : target;
return node && typeof node.closest === 'function' ? node.closest(selector) : null;
}
2026-05-25 22:53:15 +08:00
function sidebarShellRuntimeFunction(name) {
var runtime = window.__mnoteSidebarShellRuntime;
return runtime && typeof runtime[name] === 'function' ? runtime[name] : null;
}
function toggleWorkspaceSidebar(trigger) {
2026-05-25 22:53:15 +08:00
var runtimeFn = sidebarShellRuntimeFunction('toggleWorkspaceSidebar');
if (runtimeFn) return runtimeFn(trigger);
}
function installWorkspaceSidebarResizer() {
2026-05-25 22:53:15 +08:00
var runtimeFn = sidebarShellRuntimeFunction('installWorkspaceSidebarResizer');
if (runtimeFn) return runtimeFn();
}
function escapeHtml(value) {
return String(value == null ? '' : value)
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
function cssEscape(value) {
if (window.CSS && typeof window.CSS.escape === 'function') return window.CSS.escape(value);
return String(value).replace(/["\\]/g, '\\$&');
}
function parseJsonScript(id) {
var node = document.getElementById(id);
if (!node) return null;
try {
return JSON.parse(node.textContent || 'null');
} catch (_) {
return null;
}
}
function currentDocumentId() {
var match = window.location.pathname.match(/^\/documents\/([^\/]+)/);
if (!match) match = window.location.pathname.match(/^\/mindmap\/([^\/]+)\/([^\/]+)/);
if (match) return decodeURIComponent(match[1]);
var params = new URLSearchParams(window.location.search);
var fromQuery = (params.get('documentId') || params.get('pageId') || '').trim();
if (fromQuery) return fromQuery;
var activePane = document.querySelector('.document-pane[data-pane-role="primary"][data-pane-document-id], .document-pane[data-pane-visible="true"][data-pane-document-id]');
if (activePane instanceof HTMLElement) {
var paneDocumentId = (activePane.getAttribute('data-pane-document-id') || '').trim();
if (paneDocumentId) return paneDocumentId;
}
var shell = document.querySelector('.document-shell[data-document-id]');
if (shell instanceof HTMLElement) return (shell.getAttribute('data-document-id') || '').trim();
return '';
}
function localFolderSelfChangeSuppressions() {
window.__mnoteLocalFolderSelfChangeSuppressions = window.__mnoteLocalFolderSelfChangeSuppressions || new Map();
return window.__mnoteLocalFolderSelfChangeSuppressions;
}
function persistLocalFolderSelfChangeSuppression(documentId, expiresAt) {
var doc = String(documentId || '').trim();
if (!doc) return;
localFolderSelfChangeSuppressions().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 (_) {}
}
var EDITOR_UPLOAD_ROOT_SELECTOR = '[data-editor-host-kind="leptos_tiptap_island"], [data-editor-host-kind="leptos_tiptap_resource"]';
function editorUploadRootFromElement(target) {
if (!(target instanceof Element)) return null;
var root = target.closest(EDITOR_UPLOAD_ROOT_SELECTOR);
return root instanceof HTMLElement ? root : null;
}
function rememberEditorUploadRootFromTarget(target) {
var root = editorUploadRootFromElement(target);
if (root instanceof HTMLElement) {
window.__mnoteLastEditorUploadRoot = root;
return root;
}
return null;
}
document.addEventListener('pointerdown', function(event) {
rememberEditorUploadRootFromTarget(event.target);
}, true);
document.addEventListener('focusin', function(event) {
rememberEditorUploadRootFromTarget(event.target);
}, true);
function currentFileTreeActiveRowId() {
var explicitRowId = new URL(window.location.href).searchParams.get('restoreFocusRowId') || '';
if (explicitRowId) return explicitRowId;
var mindmapMatch = window.location.pathname.match(/^\/mindmap\/([^\/]+)\/([^\/]+)/);
if (mindmapMatch) return 'asset:' + decodeURIComponent(mindmapMatch[2]);
var documentId = currentDocumentId();
return documentId ? 'doc:' + documentId : '';
}
function currentPageAggregate() {
return parseJsonScript('__MNOTE_PAGE_AGGREGATE__') || {};
}
2026-05-26 01:31:28 +08:00
const sidebarWorkspace = createSidebarWorkspaceRuntime({
cssEscape,
currentDocumentId,
escapeHtml,
parseJsonScript,
setCommandPending: (...args) => setCommandPending(...args),
sidebarShellRuntimeFunction,
});
const normalizeSidebarTreeMode = (...args) => sidebarWorkspace.normalizeSidebarTreeMode(...args);
const readStoredSidebarTreeMode = (...args) => sidebarWorkspace.readStoredSidebarTreeMode(...args);
const persistSidebarTreeMode = (...args) => sidebarWorkspace.persistSidebarTreeMode(...args);
const activeSidebarTreeMode = (...args) => sidebarWorkspace.activeSidebarTreeMode(...args);
const resolveWorkspaceId = (...args) => sidebarWorkspace.resolveWorkspaceId(...args);
const currentWorkspaceId = (...args) => sidebarWorkspace.currentWorkspaceId(...args);
const currentSourceKind = (...args) => sidebarWorkspace.currentSourceKind(...args);
const currentRootUri = (...args) => sidebarWorkspace.currentRootUri(...args);
const copyWorkspaceSourceParams = (...args) => sidebarWorkspace.copyWorkspaceSourceParams(...args);
const currentWorkspaceSourcePayload = (...args) => sidebarWorkspace.currentWorkspaceSourcePayload(...args);
const openTrashModal = (...args) => sidebarWorkspace.openTrashModal(...args);
const closeTrashModal = (...args) => sidebarWorkspace.closeTrashModal(...args);
const closeLocalFolderDialog = (...args) => sidebarWorkspace.closeLocalFolderDialog(...args);
const requestOpenLocalFolder = (...args) => sidebarWorkspace.requestOpenLocalFolder(...args);
const createDefaultLocalWorkspace = (...args) => sidebarWorkspace.createDefaultLocalWorkspace(...args);
const closeWorkspaceSourceMenu = (...args) => sidebarWorkspace.closeWorkspaceSourceMenu(...args);
const openWorkspaceSourceMenu = (...args) => sidebarWorkspace.openWorkspaceSourceMenu(...args);
const closeAccountMenu = (...args) => sidebarWorkspace.closeAccountMenu(...args);
const openAccountMenu = (...args) => sidebarWorkspace.openAccountMenu(...args);
sidebarWorkspace.autoOpenRecentLocalRootOnHome();
const sidebarPageSettings = createSidebarPageSettingsRuntime({
currentDocumentId,
currentPageAggregate,
currentRootUri,
currentSourceKind,
currentWorkspaceSourcePayload,
escapeHtml,
globalShowHeadingNumbersKey: MNOTE_GLOBAL_SHOW_HEADING_NUMBERS_KEY,
pageUiState,
resolveWorkspaceId,
searchText,
});
const applyPageOptionsToShell = (...args) => sidebarPageSettings.applyPageOptionsToShell(...args);
const closePageHistoryDrawer = (...args) => sidebarPageSettings.closePageHistoryDrawer(...args);
const closeAllSettingsPopovers = (...args) => sidebarPageSettings.closeAllSettingsPopovers(...args);
const closePageSettingsPopover = (...args) => sidebarPageSettings.closePageSettingsPopover(...args);
const closePageShareDialog = (...args) => sidebarPageSettings.closePageShareDialog(...args);
const currentPageOptions = (...args) => sidebarPageSettings.currentPageOptions(...args);
const ensureHistorySnapshotsSeeded = (...args) => sidebarPageSettings.ensureHistorySnapshotsSeeded(...args);
const isAnySettingsOpen = (...args) => sidebarPageSettings.isAnySettingsOpen(...args);
const isPageSettingsOpen = (...args) => sidebarPageSettings.isPageSettingsOpen(...args);
const openPageHistoryDrawer = (...args) => sidebarPageSettings.openPageHistoryDrawer(...args);
const openPageIndexSettingsPopover = (...args) => sidebarPageSettings.openPageIndexSettingsPopover(...args);
const openKnowledgeRagSettingsPopover = (...args) => sidebarPageSettings.openKnowledgeRagSettingsPopover(...args);
2026-06-26 20:01:02 +08:00
const openKnowledgeRagSourceReference = (...args) => sidebarPageSettings.openKnowledgeRagSourceReference(...args);
const openPageShareDialog = (...args) => sidebarPageSettings.openPageShareDialog(...args);
const pageOptionIsSupported = (...args) => sidebarPageSettings.pageOptionIsSupported(...args);
const addLocalIndexRange = (...args) => sidebarPageSettings.addLocalIndexRange(...args);
const addKnowledgeRagSourceInput = (...args) => sidebarPageSettings.addKnowledgeRagSourceInput(...args);
const deleteKnowledgeRagSource = (...args) => sidebarPageSettings.deleteKnowledgeRagSource(...args);
const ingestKnowledgeRagSources = (...args) => sidebarPageSettings.ingestKnowledgeRagSources(...args);
const ingestSingleKnowledgeRagSource = (...args) => sidebarPageSettings.ingestSingleKnowledgeRagSource(...args);
const loadKnowledgeRagStatus = (...args) => sidebarPageSettings.loadKnowledgeRagStatus(...args);
const openKnowledgeRagDashboard = (...args) => sidebarPageSettings.openKnowledgeRagDashboard(...args);
2026-06-26 20:01:02 +08:00
const createKnowledgeRagKnowledgeBase = (...args) => sidebarPageSettings.createKnowledgeRagKnowledgeBase(...args);
const setActiveKnowledgeRagDetailTab = (...args) => sidebarPageSettings.setActiveKnowledgeRagDetailTab(...args);
const performKnowledgeRagSearch = (...args) => sidebarPageSettings.performKnowledgeRagSearch(...args);
const saveKnowledgeRagSearchParams = (...args) => sidebarPageSettings.saveKnowledgeRagSearchParams(...args);
const loadKnowledgeRagSearchParamsToForm = (...args) => sidebarPageSettings.loadKnowledgeRagSearchParamsToForm(...args);
const syncKnowledgeRagThresholdDisplay = (...args) => sidebarPageSettings.syncKnowledgeRagThresholdDisplay(...args);
const refreshDashboardPanel = (...args) => sidebarPageSettings.refreshDashboardPanel(...args);
const pruneKnowledgeRagRegistry = (...args) => sidebarPageSettings.pruneKnowledgeRagRegistry(...args);
2026-06-26 20:01:02 +08:00
const setKnowledgeRagSelectedProviderKnowledgeBaseId = (...args) => sidebarPageSettings.setKnowledgeRagSelectedProviderKnowledgeBaseId(...args);
const setKnowledgeRagSourceFilter = (...args) => sidebarPageSettings.setKnowledgeRagSourceFilter(...args);
const useKnowledgeRagFileTreeSelection = (...args) => sidebarPageSettings.useKnowledgeRagFileTreeSelection(...args);
const persistLocalIndexSettings = (...args) => sidebarPageSettings.persistLocalIndexSettings(...args);
const persistPageOptionsPatch = (...args) => sidebarPageSettings.persistPageOptionsPatch(...args);
const persistPageWidthPreference = (...args) => sidebarPageSettings.persistPageWidthPreference(...args);
const refreshLocalIndex = (...args) => sidebarPageSettings.refreshLocalIndex(...args);
const removeKnowledgeRagSourceInput = (...args) => sidebarPageSettings.removeKnowledgeRagSourceInput(...args);
const removeLocalIndexRange = (...args) => sidebarPageSettings.removeLocalIndexRange(...args);
const recordPageHistorySnapshot = (...args) => sidebarPageSettings.recordPageHistorySnapshot(...args);
const renderPageSettingsPopover = (...args) => sidebarPageSettings.renderPageSettingsPopover(...args);
const setActiveExtensionsSubtab = (...args) => sidebarPageSettings.setActiveExtensionsSubtab(...args);
const setActivePageSettingsTab = (...args) => sidebarPageSettings.setActivePageSettingsTab(...args);
const togglePageSettingsPopover = (...args) => sidebarPageSettings.togglePageSettingsPopover(...args);
const updatePageSettingsTriggerState = (...args) => sidebarPageSettings.updatePageSettingsTriggerState(...args);
const writeGlobalShowHeadingNumbers = (...args) => sidebarPageSettings.writeGlobalShowHeadingNumbers(...args);
const loadPageWidthPreferences = (...args) => sidebarPageSettings.loadPageWidthPreferences(...args);
function setCommandPending(trigger, pending) {
if (!(trigger instanceof HTMLElement)) return;
trigger.setAttribute('data-pending', pending ? 'true' : 'false');
if ('disabled' in trigger) {
if (pending) trigger.setAttribute('disabled', 'disabled');
else trigger.removeAttribute('disabled');
}
}
async function dispatchTreeCommand(trigger, body) {
setCommandPending(trigger, true);
var commandBody = Object.assign({}, currentWorkspaceSourcePayload(), body || {});
try {
var response = await fetch('/api/tree/commands', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(commandBody)
});
var payload = await response.json().catch(function(){ return null; });
if (!response.ok || !payload || !payload.result) {
throw new Error((payload && payload.message) || 'tree_command_failed_' + response.status);
}
window.dispatchEvent(new CustomEvent('tree:local-command', { detail: { body: commandBody, result: payload.result } }));
setCommandPending(trigger, false);
return payload.result;
} catch (error) {
setCommandPending(trigger, false);
if (trigger instanceof HTMLElement) {
trigger.setAttribute('data-error', error instanceof Error ? error.message : String(error));
}
throw error;
}
}
2026-05-26 02:35:08 +08:00
var sidebarPageTree = null;
const navigateToDocument = (...args) => sidebarPageTree.navigateToDocument(...args);
const createPage = (...args) => sidebarPageTree.createPage(...args);
const startPageDrag = (...args) => sidebarPageTree.startPageDrag(...args);
const readPageDragNodeId = (...args) => sidebarPageTree.readPageDragNodeId(...args);
const clearPageDropFeedback = (...args) => sidebarPageTree.clearPageDropFeedback(...args);
const setActivePageDropRow = (...args) => sidebarPageTree.setActivePageDropRow(...args);
const clearPageDragState = (...args) => sidebarPageTree.clearPageDragState(...args);
const canDropPage = (...args) => sidebarPageTree.canDropPage(...args);
const pageDropPosition = (...args) => sidebarPageTree.pageDropPosition(...args);
const resolvePageMoveTarget = (...args) => sidebarPageTree.resolvePageMoveTarget(...args);
async function createFileTreeFolder(trigger, parentId) {
if (currentSourceKind() !== 'local_folder') return false;
var workspaceId = resolveWorkspaceId(trigger || document.body);
var effectiveParentId = String(parentId || '').trim();
var result = await dispatchTreeCommand(trigger || document.body, {
action: 'create_folder',
workspaceId: workspaceId,
parentId: effectiveParentId || null,
title: '新建文件夹'
});
document.documentElement.setAttribute('data-mnote-filetree-folder-created', 'true');
document.documentElement.setAttribute('data-mnote-filetree-folder-created-id', commandDocumentId(result, result.id || ''));
void refreshLocalFolderSidebarSnapshot();
return true;
}
function applySidebarTreeTab(mode, shell) {
2026-05-25 22:53:15 +08:00
var runtimeFn = sidebarShellRuntimeFunction('applySidebarTreeTab');
if (runtimeFn) return runtimeFn(mode, shell);
}
function switchSidebarTreeTab(trigger) {
2026-05-25 22:53:15 +08:00
var runtimeFn = sidebarShellRuntimeFunction('switchSidebarTreeTab');
if (runtimeFn) return runtimeFn(trigger);
}
function restoreSidebarTreeTab() {
2026-05-25 22:53:15 +08:00
var runtimeFn = sidebarShellRuntimeFunction('restoreSidebarTreeTab');
if (runtimeFn) return runtimeFn();
}
const sidebarTreeLiveApply = createSidebarTreeLiveApplyRuntime({
activeSidebarTreeMode,
cssEscape,
currentDocumentId: (...args) => currentDocumentId(...args),
currentFileTreeActiveRowId: (...args) => currentFileTreeActiveRowId(...args),
currentRootUri,
currentSourceKind,
currentWorkspaceId,
escapeHtml,
fileTreeRuntimeFunction: (...args) => fileTreeRuntimeFunction(...args),
localFilePathFromAssetId: (...args) => localFilePathFromAssetId(...args),
navigateToDocument,
refreshEditorLocalAttachmentExistence: (...args) => refreshEditorLocalAttachmentExistence(...args),
restoreSidebarTreeTab,
rowTitle: (...args) => rowTitle(...args),
schedulePendingLocalFolderRestoreFocus: (...args) => schedulePendingLocalFolderRestoreFocus(...args),
shortMindmapFileName: (...args) => shortMindmapFileName(...args),
syncSidebarFileTreeSelection: (...args) => syncSidebarFileTreeSelection(...args),
});
const updateTitleEverywhere = (...args) => sidebarTreeLiveApply.updateTitleEverywhere(...args);
2026-05-26 07:08:26 +08:00
const commandDocumentId = (...args) => sidebarTreeLiveApply.commandDocumentId(...args);
2026-05-26 02:35:08 +08:00
sidebarPageTree = createSidebarPageTreeRuntime({
activeSidebarTreeMode,
commandDocumentId,
copyWorkspaceSourceParams,
cssEscape,
currentDocumentId,
currentRootUri,
2026-05-26 02:35:08 +08:00
currentSourceKind,
dispatchTreeCommand,
normalizeSidebarTreeMode,
persistLocalFolderSelfChangeSuppression,
persistSidebarTreeMode,
refreshLocalFolderSidebarSnapshot: (...args) => refreshLocalFolderSidebarSnapshot(...args),
refreshLocalFolderAfterCommand: (...args) => refreshLocalFolderAfterCommand(...args),
2026-05-26 02:35:08 +08:00
resolveWorkspaceId,
rowCenter: (...args) => rowCenter(...args),
selectSidebarFileTreeDocument: (...args) => selectSidebarFileTreeDocument(...args),
toggleChildren: (...args) => toggleChildren(...args),
dispatchSidebarEvent: (...args) => dispatchSidebarEvent(...args),
openPageTreeContextMenu: (...args) => openPageTreeContextMenu(...args),
updateTitleEverywhere: (...args) => updateTitleEverywhere(...args),
});
const fileTreePageTitle = (...args) => sidebarTreeLiveApply.fileTreePageTitle(...args);
const isFileTreePageRow = (...args) => sidebarTreeLiveApply.isFileTreePageRow(...args);
const normalizeFileTreePageRenameTitle = (...args) => sidebarTreeLiveApply.normalizeFileTreePageRenameTitle(...args);
const validateFileTreeRename = (...args) => sidebarTreeLiveApply.validateFileTreeRename(...args);
const removeDocumentRowForMode = (...args) => sidebarTreeLiveApply.removeDocumentRowForMode(...args);
const applyCreatedDocumentLocally = (...args) => sidebarTreeLiveApply.applyCreatedDocumentLocally(...args);
const localCommandNeedsProjectionRefresh = (...args) => sidebarTreeLiveApply.localCommandNeedsProjectionRefresh(...args);
const refreshLocalFolderAfterCommand = (...args) => sidebarTreeLiveApply.refreshLocalFolderAfterCommand(...args);
const applyMoveDocumentDelta = (...args) => sidebarTreeLiveApply.applyMoveDocumentDelta(...args);
const applyRemoveDocumentDelta = (...args) => sidebarTreeLiveApply.applyRemoveDocumentDelta(...args);
const setTreeLiveApplyError = (...args) => sidebarTreeLiveApply.setTreeLiveApplyError(...args);
const objectIdentityAttr = (...args) => sidebarTreeLiveApply.objectIdentityAttr(...args);
const renderPageProjection = (...args) => sidebarTreeLiveApply.renderPageProjection(...args);
const renderSidebarSnapshot = (...args) => sidebarTreeLiveApply.renderSidebarSnapshot(...args);
const refreshLocalFolderSidebarSnapshot = (...args) => sidebarTreeLiveApply.refreshLocalFolderSidebarSnapshot(...args);
const startLocalFolderSidebarWatch = (...args) => sidebarTreeLiveApply.startLocalFolderSidebarWatch(...args);
const deltaNeedsProjectionRefresh = (...args) => sidebarTreeLiveApply.deltaNeedsProjectionRefresh(...args);
const toggleChildren = (...args) => sidebarTreeLiveApply.toggleChildren(...args);
const revealFileTreeResource = (...args) => sidebarTreeLiveApply.revealFileTreeResource(...args);
function dispatchSidebarEvent(name, detail) {
document.documentElement.setAttribute('data-mnote-last-tree-action', name);
window.dispatchEvent(new CustomEvent(name, { detail: detail }));
}
function sidebarShortcutWorkspaceId() {
return currentWorkspaceId()
|| (document.getElementById('sidebar-file-tree-root') && document.getElementById('sidebar-file-tree-root').getAttribute('data-workspace-id') || '')
|| (document.getElementById('sidebar-tree-root') && document.getElementById('sidebar-tree-root').getAttribute('data-workspace-id') || '');
}
function sidebarShortcutSourceKind() {
return currentSourceKind() || 'workspace';
}
function currentFileTreeScope() {
var params = new URLSearchParams(window.location.search);
var fromUrl = String(params.get('fileTreeScope') || '').trim();
if (fromUrl) return fromUrl;
var root = document.getElementById('sidebar-file-tree-root');
return root instanceof HTMLElement ? String(root.getAttribute('data-mnote-filetree-scope') || '').trim() : '';
}
function recordNavigationRecent(payload) {
var body = Object.assign({
sourceKind: currentSourceKind() || 'local_folder',
rootUri: currentRootUri() || '',
}, payload || {});
if (!body.kind || !body.rootUri || !body.title) return Promise.resolve(false);
return fetch('/api/navigation/recent', {
method: 'POST',
credentials: 'include',
headers: {
accept: 'application/json',
'content-type': 'application/json'
},
body: JSON.stringify(body)
}).then(function(response) {
return response.ok;
}).catch(function(error) {
console.warn('[mnote navigation] record recent failed', error);
return false;
});
}
function openNavigationPageForFolder(rootUri, relativePath, workspaceId, title, options) {
rootUri = String(rootUri || '').trim();
relativePath = String(relativePath || '').trim().replace(/^\/+|\/+$/g, '');
workspaceId = String(workspaceId || '').trim();
title = String(title || relativePath || '本地文件夹').trim();
if (!rootUri) return false;
void recordNavigationRecent({
kind: 'folder',
sourceKind: 'local_folder',
rootUri: rootUri,
relativePath: relativePath,
title: title,
workspaceId: workspaceId
});
var targetUrl = new URL('/', window.location.origin);
if (workspaceId) targetUrl.searchParams.set('workspaceId', workspaceId);
targetUrl.searchParams.set('sourceKind', 'local_folder');
targetUrl.searchParams.set('rootUri', rootUri);
targetUrl.searchParams.set('treeView', 'filetree');
if (relativePath) targetUrl.searchParams.set('fileTreeScope', relativePath);
var url = targetUrl.pathname + targetUrl.search;
if (options && options.newTab) {
window.open(url, '_blank', 'noopener');
} else {
window.location.assign(url);
}
return true;
}
function openCurrentNavigationPage(trigger) {
if (currentSourceKind() === 'local_folder') {
var rootUri = currentRootUri();
var scope = currentFileTreeScope();
var workspaceId = currentWorkspaceId() || sidebarShortcutWorkspaceId() || resolveWorkspaceId(trigger || document.body);
var title = scope ? scope.split('/').filter(Boolean).pop() : '本地文件夹';
return openNavigationPageForFolder(rootUri, scope, workspaceId, title || scope || '本地文件夹');
}
var targetUrl = new URL('/', window.location.origin);
var workspaceId = currentWorkspaceId() || resolveWorkspaceId(trigger || document.body);
if (workspaceId) targetUrl.searchParams.set('workspaceId', workspaceId);
window.location.assign(targetUrl.pathname + targetUrl.search);
return true;
}
function currentTopbarTitle() {
var title = document.querySelector('[data-page-title-current="true"]');
return title && title.textContent ? title.textContent.trim() : '无标题';
}
function fileTreeRowTitleForShortcut(row, fallback) {
var title = row && row.querySelector ? row.querySelector(':scope > .tree-link > .tree-link-title') : null;
return title && title.textContent ? title.textContent.trim() : (fallback || '文件夹');
}
2026-06-07 10:35:21 +08:00
function isRetiredOcrSidecarMarkdownPath(relativePath) {
var normalized = String(relativePath || '').trim().replace(/\\/g, '/').replace(/^\/+/, '');
return /(^|\/)[^/]+\.ocr\/[^/]+\.ocr\.md$/i.test(normalized);
}
function sidebarShortcutRows() {
return Array.from(document.querySelectorAll('.wolai-starred-section [data-mnote-shortcut-kind]'));
}
function shortcutMatches(row, kind, targetId, relativePath, documentId) {
if (!(row instanceof HTMLElement)) return false;
if ((row.getAttribute('data-mnote-shortcut-kind') || '') !== kind) return false;
if (documentId && (row.getAttribute('data-mnote-shortcut-document-id') || row.getAttribute('data-document-id') || '') === documentId) return true;
if (relativePath && (row.getAttribute('data-mnote-shortcut-relative-path') || '') === relativePath) return true;
return Boolean(targetId && (row.getAttribute('data-mnote-shortcut-target-id') || row.getAttribute('data-node-id') || '') === targetId);
}
async function listSidebarShortcuts(workspaceId) {
var url = new URL('/api/sidebar/shortcuts', window.location.origin);
url.searchParams.set('workspaceId', workspaceId);
var response = await fetch(url.toString(), {
method: 'GET',
credentials: 'include',
headers: { accept: 'application/json' },
cache: 'no-store'
});
var payload = await response.json().catch(function() { return null; });
if (!response.ok) throw new Error(payload && (payload.error || payload.message) || 'sidebar_shortcuts_list_failed_' + response.status);
return payload && Array.isArray(payload.shortcuts) ? payload.shortcuts : [];
}
function shortcutRecordMatches(shortcut, kind, targetId, relativePath, documentId) {
if (!shortcut || shortcut.kind !== kind) return false;
var shortcutMetadata = shortcut && shortcut.metadata && typeof shortcut.metadata === 'object' ? shortcut.metadata : {};
var shortcutRootUri = String(shortcut.rootUri || shortcut.root_uri || shortcutMetadata.rootUri || shortcutMetadata.root_uri || '').trim();
var currentShortcutRootUri = currentRootUri();
if (shortcutRootUri && currentShortcutRootUri && shortcutRootUri !== currentShortcutRootUri) return false;
if (documentId && String(shortcut.documentId || shortcut.document_id || '') === documentId) return true;
if (relativePath && String(shortcut.relativePath || shortcut.relative_path || '') === relativePath) return true;
return Boolean(targetId && String(shortcut.targetId || shortcut.target_id || '') === targetId);
}
async function findSidebarShortcut(payload) {
var workspaceId = payload.workspaceId || sidebarShortcutWorkspaceId();
if (!workspaceId) return null;
var shortcuts = await listSidebarShortcuts(workspaceId);
return shortcuts.find(function(shortcut) {
return shortcutRecordMatches(shortcut, payload.kind, payload.targetId, payload.relativePath, payload.documentId);
}) || null;
}
async function upsertSidebarShortcut(payload) {
var response = await fetch('/api/sidebar/shortcuts', {
method: 'POST',
credentials: 'include',
headers: { accept: 'application/json', 'content-type': 'application/json' },
body: JSON.stringify(payload)
});
var result = await response.json().catch(function() { return null; });
if (!response.ok) throw new Error(result && (result.error || result.message) || 'sidebar_shortcut_upsert_failed_' + response.status);
return result && result.shortcut ? result.shortcut : null;
}
async function deleteSidebarShortcut(shortcutId) {
if (!shortcutId) return false;
var response = await fetch('/api/sidebar/shortcuts/' + encodeURIComponent(shortcutId), {
method: 'DELETE',
credentials: 'include',
headers: { accept: 'application/json' }
});
var result = await response.json().catch(function() { return null; });
if (!response.ok) throw new Error(result && (result.error || result.message) || 'sidebar_shortcut_delete_failed_' + response.status);
return true;
}
function closeSidebarShortcutMenu() {
var existing = document.querySelector('[data-testid="mnote-sidebar-shortcut-menu"]');
if (existing && existing.parentElement) existing.parentElement.removeChild(existing);
document.querySelectorAll('[data-mnote-shortcut-action="menu"][aria-expanded="true"]').forEach(function(button) {
button.setAttribute('aria-expanded', 'false');
});
}
async function removeSidebarShortcutByRow(row) {
if (!(row instanceof HTMLElement)) return false;
var shortcutId = String(row.getAttribute('data-mnote-shortcut-id') || '').trim();
if (!shortcutId) return false;
row.setAttribute('data-mnote-shortcut-pending', 'true');
try {
await deleteSidebarShortcut(shortcutId);
row.remove();
closeSidebarShortcutMenu();
document.documentElement.setAttribute('data-mnote-sidebar-shortcut-last-action', 'remove');
return true;
} finally {
if (row.isConnected) row.removeAttribute('data-mnote-shortcut-pending');
}
}
function openSidebarShortcutMenu(row, trigger) {
if (!(row instanceof HTMLElement)) return;
closeSidebarShortcutMenu();
if (trigger instanceof HTMLElement) trigger.setAttribute('aria-expanded', 'true');
var rect = trigger && trigger.getBoundingClientRect ? trigger.getBoundingClientRect() : row.getBoundingClientRect();
var menu = document.createElement('div');
menu.className = 'mnote-tree-context-menu';
menu.setAttribute('role', 'menu');
menu.setAttribute('data-testid', 'mnote-sidebar-shortcut-menu');
menu.innerHTML = '<button type="button" class="mnote-tree-context-menu__item" role="menuitem" data-mnote-sidebar-shortcut-menu-action="open"><span class="material-symbols-outlined mnote-tree-context-menu__icon" data-icon="login" aria-hidden="true"></span><span class="mnote-tree-context-menu__label">在右侧边栏打开</span></button><div class="mnote-tree-context-menu__separator" role="separator"></div><button type="button" class="mnote-tree-context-menu__item" role="menuitem" data-mnote-sidebar-shortcut-menu-action="copy-link"><span class="material-symbols-outlined mnote-tree-context-menu__icon" data-icon="link" aria-hidden="true"></span><span class="mnote-tree-context-menu__label">复制访问链接</span></button><button type="button" class="mnote-tree-context-menu__item mnote-tree-context-menu__item--danger" role="menuitem" data-mnote-sidebar-shortcut-menu-action="remove"><span class="material-symbols-outlined mnote-tree-context-menu__icon" data-icon="star_off" aria-hidden="true"></span><span class="mnote-tree-context-menu__label">取消星标</span></button>';
menu.__mnoteShortcutRow = row;
document.body.appendChild(menu);
var width = menu.offsetWidth || 220;
var left = Math.min(Math.max(8, rect.right - width), Math.max(8, window.innerWidth - width - 8));
var top = Math.min(Math.max(8, rect.bottom + 4), Math.max(8, window.innerHeight - (menu.offsetHeight || 120) - 8));
menu.style.left = left + 'px';
menu.style.top = top + 'px';
}
function removeSidebarShortcutRow(shortcut) {
sidebarShortcutRows().forEach(function(row) {
if (shortcutMatches(
row,
shortcut.kind,
String(shortcut.targetId || shortcut.target_id || ''),
String(shortcut.relativePath || shortcut.relative_path || ''),
String(shortcut.documentId || shortcut.document_id || '')
)) {
row.remove();
}
});
}
function renderSidebarShortcutRow(shortcut) {
if (!shortcut) return;
var section = document.querySelector('.wolai-starred-section');
if (!(section instanceof HTMLElement)) return;
removeSidebarShortcutRow(shortcut);
var kind = String(shortcut.kind || '').trim();
var shortcutId = String(shortcut.id || shortcut.targetId || shortcut.target_id || '').trim();
var targetId = String(shortcut.targetId || shortcut.target_id || '').trim();
var relativePath = String(shortcut.relativePath || shortcut.relative_path || '').trim();
var documentId = String(shortcut.documentId || shortcut.document_id || '').trim();
var sourceKind = String(shortcut.sourceKind || shortcut.source_kind || '').trim();
var metadata = shortcut.metadata && typeof shortcut.metadata === 'object' ? shortcut.metadata : {};
var rootUri = String(shortcut.rootUri || shortcut.root_uri || metadata.rootUri || metadata.root_uri || '').trim();
var workspaceId = String(shortcut.workspaceId || shortcut.workspace_id || sidebarShortcutWorkspaceId() || '').trim();
var title = String(shortcut.title || (kind === 'folder' ? '文件夹' : '无标题')).trim();
var href = '';
if (documentId) {
var targetUrl = new URL('/documents/' + encodeURIComponent(documentId), window.location.origin);
if (workspaceId) targetUrl.searchParams.set('workspaceId', workspaceId);
if (sourceKind) targetUrl.searchParams.set('sourceKind', sourceKind);
if (rootUri) targetUrl.searchParams.set('rootUri', rootUri);
href = targetUrl.pathname + targetUrl.search;
}
var row = document.createElement(href ? 'a' : 'div');
row.className = 'wolai-page-row';
if (href) row.setAttribute('href', href);
else {
row.setAttribute('role', 'button');
row.setAttribute('tabindex', '0');
}
row.setAttribute('data-testid', 'wolai-sidebar-row');
row.setAttribute('data-node-id', shortcutId || targetId);
row.setAttribute('data-document-id', documentId || shortcutId || targetId);
if (shortcutId) row.setAttribute('data-mnote-shortcut-id', shortcutId);
if (workspaceId) row.setAttribute('data-workspace-id', workspaceId);
row.setAttribute('data-mnote-shortcut-kind', kind);
if (sourceKind) row.setAttribute('data-mnote-shortcut-source-kind', sourceKind);
row.setAttribute('data-mnote-shortcut-target-id', targetId);
if (relativePath) row.setAttribute('data-mnote-shortcut-relative-path', relativePath);
if (rootUri) row.setAttribute('data-mnote-shortcut-root-uri', rootUri);
if (documentId) row.setAttribute('data-mnote-shortcut-document-id', documentId);
row.setAttribute('data-depth', '0');
row.setAttribute('data-active', String(documentId && documentId === currentDocumentId()));
row.innerHTML = '<span class="wolai-row-caret" aria-hidden="true"></span><span class="wolai-row-icon"><span class="material-symbols-outlined wolai-row-symbol" data-icon="' + (kind === 'folder' ? 'folder_open' : 'home') + '" aria-hidden="true"></span></span><span class="wolai-row-title">' + escapeHtml(title) + '</span><button type="button" class="wolai-row-more" data-mnote-shortcut-action="menu" aria-label="更多操作" title="更多操作"><span class="material-symbols-outlined" data-icon="more_horiz" aria-hidden="true"></span></button>';
section.appendChild(row);
}
async function toggleSidebarShortcut(payload) {
var workspaceId = payload.workspaceId || sidebarShortcutWorkspaceId();
if (!workspaceId) return false;
var normalized = Object.assign({}, payload, { workspaceId: workspaceId });
var existing = await findSidebarShortcut(normalized);
if (existing && existing.id) {
await deleteSidebarShortcut(existing.id);
removeSidebarShortcutRow(existing);
document.documentElement.setAttribute('data-mnote-sidebar-shortcut-last-action', 'remove');
return true;
}
var shortcut = await upsertSidebarShortcut(normalized);
renderSidebarShortcutRow(shortcut);
document.documentElement.setAttribute('data-mnote-sidebar-shortcut-last-action', 'upsert');
return true;
}
function currentPageShortcutPayload() {
var documentId = currentDocumentId();
var workspaceId = sidebarShortcutWorkspaceId();
if (!documentId || !workspaceId) return null;
return {
workspaceId: workspaceId,
kind: 'page',
sourceKind: sidebarShortcutSourceKind(),
targetId: documentId,
documentId: documentId,
title: currentTopbarTitle(),
icon: 'star',
rootUri: currentRootUri(),
metadataJson: JSON.stringify({ rootUri: currentRootUri() })
};
}
function folderShortcutPayload(detail, trigger) {
detail = detail || {};
var row = trigger && trigger.closest ? trigger.closest('.tree-row[data-shell-mode="filetree"]') : trigger;
var rowKind = String(detail.rowKind || (row && row.getAttribute('data-row-kind')) || '').trim();
if (rowKind !== 'folder' && rowKind !== 'directory') return null;
var relativePath = String(detail.localRelativePath || (row && row.getAttribute('data-local-relative-path')) || '').trim();
if (!relativePath) return null;
var workspaceId = String(detail.workspaceId || sidebarShortcutWorkspaceId() || '').trim();
if (!workspaceId) return null;
var rowId = String(detail.rowId || (row && row.getAttribute('data-row-id')) || '').trim();
return {
workspaceId: workspaceId,
kind: 'folder',
sourceKind: 'local_folder',
targetId: rowId || ('folder:' + relativePath),
relativePath: relativePath,
title: detail.title || fileTreeRowTitleForShortcut(row, relativePath),
icon: 'folder_open',
rootUri: currentRootUri(),
metadataJson: JSON.stringify({ rootUri: currentRootUri() })
};
}
async function toggleCurrentPageSidebarShortcut(trigger) {
var payload = currentPageShortcutPayload();
if (!payload) return;
if (trigger instanceof HTMLElement) trigger.setAttribute('data-mnote-shortcut-pending', 'true');
try {
await toggleSidebarShortcut(payload);
} finally {
if (trigger instanceof HTMLElement) trigger.removeAttribute('data-mnote-shortcut-pending');
}
}
async function toggleFolderSidebarShortcut(detail, trigger) {
var payload = folderShortcutPayload(detail, trigger);
if (!payload) return false;
await toggleSidebarShortcut(payload);
return true;
}
function ensureStarredFolderFileTreeHost(workspaceId) {
var root = document.getElementById('sidebar-file-tree-root');
if (root instanceof HTMLElement) return root;
var panel = document.getElementById('wolai-sidebar-file-tree-panel');
if (!(panel instanceof HTMLElement)) return null;
var section = document.createElement('div');
section.className = 'sidebar-tree-section sidebar-file-tree-section';
root = document.createElement('div');
root.id = 'sidebar-file-tree-root';
root.className = 'sidebar-tree';
root.setAttribute('data-tree-shell-mode', 'filetree');
if (workspaceId) root.setAttribute('data-workspace-id', workspaceId);
section.appendChild(root);
panel.appendChild(section);
return root;
}
function ensureStarredFolderPageTreeHost(workspaceId) {
var root = document.getElementById('sidebar-tree-root');
if (root instanceof HTMLElement) return root;
var panel = document.getElementById('wolai-sidebar-page-tree-panel') || document.querySelector('[data-mnote-sidebar-tree-panel="page"]');
if (!(panel instanceof HTMLElement)) return null;
var section = document.createElement('div');
section.className = 'sidebar-tree-section';
root = document.createElement('div');
root.id = 'sidebar-tree-root';
root.className = 'sidebar-tree';
root.setAttribute('data-tree-shell-mode', 'page');
if (workspaceId) root.setAttribute('data-workspace-id', workspaceId);
section.appendChild(root);
panel.appendChild(section);
return root;
}
function persistStarredFolderScope(workspaceId, rootUri, relativePath) {
var targetUrl = new URL(window.location.href);
if (workspaceId) targetUrl.searchParams.set('workspaceId', workspaceId);
targetUrl.searchParams.set('sourceKind', 'local_folder');
targetUrl.searchParams.set('rootUri', rootUri);
targetUrl.searchParams.set('treeView', 'filetree');
targetUrl.searchParams.set('fileTreeScope', relativePath);
window.history.replaceState(window.history.state, '', targetUrl.pathname + targetUrl.search + targetUrl.hash);
if (document.body instanceof HTMLElement) {
document.body.setAttribute('data-mnote-source-kind', 'local_folder');
document.body.setAttribute('data-mnote-root-uri', rootUri);
}
}
function readShortcutRootUri(row) {
if (!(row instanceof HTMLElement)) return '';
return String(row.getAttribute('data-mnote-shortcut-root-uri') || '').trim();
}
async function openStarredFolderShortcut(row) {
if (!(row instanceof HTMLElement)) return false;
var relativePath = String(row.getAttribute('data-mnote-shortcut-relative-path') || '').trim();
var workspaceId = String(row.getAttribute('data-workspace-id') || '').trim() || sidebarShortcutWorkspaceId();
var rootUri = readShortcutRootUri(row);
if (!relativePath || !rootUri || !workspaceId) {
document.documentElement.setAttribute('data-mnote-sidebar-shortcut-open-error', !rootUri ? 'missing_root_uri' : 'missing_target');
return false;
}
document.documentElement.removeAttribute('data-mnote-sidebar-shortcut-open-error');
var tab = document.querySelector('[data-mnote-sidebar-tree-tab="filetree"]');
if (tab instanceof HTMLElement) switchSidebarTreeTab(tab);
var root = ensureStarredFolderFileTreeHost(workspaceId);
var pageRoot = ensureStarredFolderPageTreeHost(workspaceId);
if (root instanceof HTMLElement) {
root.setAttribute('data-workspace-id', workspaceId);
root.setAttribute('data-mnote-filetree-scope', relativePath);
root.setAttribute('data-mnote-filetree-scope-title', row.textContent ? row.textContent.trim() : relativePath);
}
if (pageRoot instanceof HTMLElement) {
pageRoot.setAttribute('data-workspace-id', workspaceId);
pageRoot.setAttribute('data-mnote-page-tree-scope', relativePath);
}
persistStarredFolderScope(workspaceId, rootUri, relativePath);
void recordNavigationRecent({
kind: 'folder',
sourceKind: 'local_folder',
rootUri: rootUri,
relativePath: relativePath,
title: row.textContent ? row.textContent.trim() : relativePath,
workspaceId: workspaceId
});
document.documentElement.setAttribute('data-mnote-filetree-scope', relativePath);
var sidebarUrl = new URL('/api/tree/projections/sidebar', window.location.origin);
sidebarUrl.searchParams.set('workspaceId', workspaceId);
sidebarUrl.searchParams.set('sourceKind', 'local_folder');
sidebarUrl.searchParams.set('rootUri', rootUri);
sidebarUrl.searchParams.set('parentRelativePath', relativePath);
var url = new URL('/api/tree/projections/file', window.location.origin);
url.searchParams.set('workspaceId', workspaceId);
url.searchParams.set('sourceKind', 'local_folder');
url.searchParams.set('rootUri', rootUri);
url.searchParams.set('parentRelativePath', relativePath);
var sidebarRequest = fetch(sidebarUrl.toString(), {
method: 'GET',
credentials: 'include',
headers: { accept: 'application/json' },
cache: 'no-store'
});
var fileRequest = fetch(url.toString(), {
method: 'GET',
credentials: 'include',
headers: { accept: 'application/json' },
cache: 'no-store'
});
var response = await fileRequest;
var payload = await response.json().catch(function() { return null; });
if (!response.ok) throw new Error(payload && (payload.error || payload.message) || 'scoped_filetree_failed_' + response.status);
var fileProjection = payload && (payload.result || payload);
var renderedFile = renderSidebarSnapshot({
dataset: { kernel_file_tree_projection: fileProjection }
});
root = document.getElementById('sidebar-file-tree-root');
if (root instanceof HTMLElement) {
root.setAttribute('data-workspace-id', workspaceId);
root.setAttribute('data-mnote-filetree-scope', relativePath);
root.setAttribute('data-mnote-filetree-scope-title', row.textContent ? row.textContent.trim() : relativePath);
}
var sidebarResponse = await sidebarRequest;
var sidebarPayload = await sidebarResponse.json().catch(function() { return null; });
if (!sidebarResponse.ok) throw new Error(sidebarPayload && (sidebarPayload.error || sidebarPayload.message) || 'local_page_tree_failed_' + sidebarResponse.status);
var sidebarProjection = sidebarPayload && (sidebarPayload.result || sidebarPayload) || {};
var renderedPage = sidebarProjection ? await renderPageProjection(sidebarProjection) : false;
root = document.getElementById('sidebar-file-tree-root');
if (root instanceof HTMLElement) {
root.setAttribute('data-workspace-id', workspaceId);
root.setAttribute('data-mnote-filetree-scope', relativePath);
root.setAttribute('data-mnote-filetree-scope-title', row.textContent ? row.textContent.trim() : relativePath);
}
return renderedFile || renderedPage;
}
const sidebarFileTreeOpen = createSidebarFileTreeOpenRuntime({
copyWorkspaceSourceParams,
currentDocumentId,
currentRootUri,
currentSourceKind,
fileTreeIconKindForFileName: (...args) => fileTreeIconKindForFileName(...args),
getNavigationInFlight: () => mnoteNavigationInFlight,
isCodeAttachmentFileName: (...args) => isCodeAttachmentFileName(...args),
isNonOfficeAttachmentName: (...args) => isNonOfficeAttachmentName(...args),
isPdfAttachmentFileName: (...args) => isPdfAttachmentFileName(...args),
openCodeEditorAttachment: (...args) => openCodeEditorAttachment(...args),
resolveWorkspaceId,
setNavigationInFlight: (value) => { mnoteNavigationInFlight = String(value || ''); },
shouldOpenLocalResourceInNewWindow: (...args) => shouldOpenLocalResourceInNewWindow(...args),
uploadedFileSize: (...args) => uploadedFileSize(...args),
});
const inferOnlyOfficeFileType = (...args) => sidebarFileTreeOpen.inferOnlyOfficeFileType(...args);
const buildOnlyOfficeOpenUrl = (...args) => sidebarFileTreeOpen.buildOnlyOfficeOpenUrl(...args);
const buildOnlyOfficeOpenPath = (...args) => sidebarFileTreeOpen.buildOnlyOfficeOpenPath(...args);
const buildOfficePreviewOpenUrl = (...args) => sidebarFileTreeOpen.buildOfficePreviewOpenUrl(...args);
const buildPdfPreviewOpenUrl = (...args) => sidebarFileTreeOpen.buildPdfPreviewOpenUrl(...args);
const buildLocalOnlyOfficeOpenUrl = (...args) => sidebarFileTreeOpen.buildLocalOnlyOfficeOpenUrl(...args);
const openLocalOfficeFileInActiveTab = (...args) => sidebarFileTreeOpen.openLocalOfficeFileInActiveTab(...args);
const buildMindmapOpenPath = (...args) => sidebarFileTreeOpen.buildMindmapOpenPath(...args);
const navigateToMindmapObject = (...args) => sidebarFileTreeOpen.navigateToMindmapObject(...args);
const isMindmapAssetDetail = (...args) => sidebarFileTreeOpen.isMindmapAssetDetail(...args);
const localFilePathFromAssetId = (...args) => sidebarFileTreeOpen.localFilePathFromAssetId(...args);
const buildLocalFileOpenUrl = (...args) => sidebarFileTreeOpen.buildLocalFileOpenUrl(...args);
const openLocalResourceInActiveTab = (...args) => sidebarFileTreeOpen.openLocalResourceInActiveTab(...args);
const readFileTreeObjectIdentity = (...args) => sidebarFileTreeOpen.readFileTreeObjectIdentity(...args);
const fetchCurrentOnlyOfficeUserId = (...args) => sidebarFileTreeOpen.fetchCurrentOnlyOfficeUserId(...args);
const openConvexAssetFromFileTree = (...args) => sidebarFileTreeOpen.openConvexAssetFromFileTree(...args);
var sidebarFileTreeUpload = null;
const fileTreeRowsForUploadPreflight = (...args) => sidebarFileTreeUpload.fileTreeRowsForUploadPreflight(...args);
const fileTreeRowCapabilities = (...args) => sidebarFileTreeUpload.fileTreeRowCapabilities(...args);
const fileTreeRowIsReadonly = (...args) => sidebarFileTreeUpload.fileTreeRowIsReadonly(...args);
const blockReadonlyFileTreeAction = (...args) => sidebarFileTreeUpload.blockReadonlyFileTreeAction(...args);
const fileTreeDocumentParentsForPreflight = (...args) => sidebarFileTreeUpload.fileTreeDocumentParentsForPreflight(...args);
const fileTreeTargetChildrenForPreflight = (...args) => sidebarFileTreeUpload.fileTreeTargetChildrenForPreflight(...args);
const fileTreeDropPreflightRows = (...args) => sidebarFileTreeUpload.fileTreeDropPreflightRows(...args);
const ensureFileTreeWritableTarget = (...args) => sidebarFileTreeUpload.ensureFileTreeWritableTarget(...args);
const fileTreeDocumentWorkspacesForUploadPreflight = (...args) => sidebarFileTreeUpload.fileTreeDocumentWorkspacesForUploadPreflight(...args);
const preflightFileTreeUploadTarget = (...args) => sidebarFileTreeUpload.preflightFileTreeUploadTarget(...args);
const fallbackFileTreeUploadTarget = (...args) => sidebarFileTreeUpload.fallbackFileTreeUploadTarget(...args);
const resolveFileTreeUploadTarget = (...args) => sidebarFileTreeUpload.resolveFileTreeUploadTarget(...args);
function localUploadRuntimeFunction(name) {
var runtime = window.__mnoteLocalUploadRuntime;
var fn = runtime && runtime[name];
return typeof fn === 'function' ? fn : null;
}
function fileTreeRuntimeFunction(name) {
var runtime = window.__mnoteFileTreeRuntime;
var fn = runtime && runtime[name];
return typeof fn === 'function' ? fn : null;
}
function fileTreeRuntimeDeps() {
return {
currentSourceKind: currentSourceKind,
2026-06-01 09:29:12 +08:00
currentRootUri: currentRootUri,
currentDocumentId: currentDocumentId,
localFilePathFromAssetId: localFilePathFromAssetId,
rowTitle: rowTitle,
resolveWorkspaceId: resolveWorkspaceId,
cssEscape: cssEscape,
escapeHtml: escapeHtml,
objectIdentityAttr: objectIdentityAttr,
uploadedAssetTitle: uploadedAssetTitle,
uploadedAssetType: uploadedAssetType,
fileTreeIconKindForFileName: fileTreeIconKindForFileName
};
}
function fileTreeSelectionRuntimeFunction(name) {
var runtime = window.__mnoteFileTreeSelectionRuntime;
var fn = runtime && runtime[name];
return typeof fn === 'function' ? fn : null;
}
function fileTreeSelectionRuntimeDeps() {
return {
cssEscape: cssEscape
};
}
function uploadedAssetTitle(asset) {
var runtimeFn = localUploadRuntimeFunction('uploadedAssetTitle');
if (runtimeFn) return runtimeFn(asset);
return String(asset && (asset.file_name || asset.title || asset.name) || '未命名附件').trim() || '未命名附件';
}
function uploadedAssetUrl(asset) {
var runtimeFn = localUploadRuntimeFunction('uploadedAssetUrl');
if (runtimeFn) return runtimeFn(asset);
return String(asset && (asset.sourcePath || asset.file_url || asset.signedUrl || asset.signed_url || asset.thumbnail_url) || '').trim();
}
2026-05-29 11:13:05 +08:00
function uploadedAssetMarkdownHref(asset) {
var runtimeFn = localUploadRuntimeFunction('uploadedAssetMarkdownHref');
if (runtimeFn) return runtimeFn(asset);
var href = String(asset && (asset.markdownHref || asset.markdown_href) || '').trim();
if (href) {
var normalizedHref = href.replace(/\\/g, '/');
if (normalizedHref.indexOf('../') === 0 || normalizedHref.indexOf('/../') >= 0) return '';
return href;
}
var relativePath = String(asset && (asset.markdownRelativePath || asset.markdown_relative_path) || '').trim().replace(/\\/g, '/');
if (!relativePath) return '';
if (relativePath.indexOf('../') === 0 || relativePath.indexOf('/../') >= 0) return '';
if (relativePath.indexOf('./') === 0) return relativePath;
return './' + relativePath;
}
function localAssetOpenUrl(asset, download) {
var runtimeFn = localUploadRuntimeFunction('localAssetOpenUrl');
if (runtimeFn) return runtimeFn(asset, download, { rootUri: currentRootUri() });
if (!isLocalUploadedAsset(asset)) return '';
var rootUri = String(asset && (asset.rootUri || asset.root_uri) || '').trim() || currentRootUri();
var rootRelativePath = String(asset && (asset.rootRelativePath || asset.root_relative_path) || '').trim();
if (!rootUri || !rootRelativePath) return '';
var url = new URL('/api/local-folder/files/open', window.location.origin);
url.searchParams.set('rootUri', rootUri);
url.searchParams.set('path', rootRelativePath);
if (download) url.searchParams.set('download', 'true');
return url.toString();
}
function uploadedAssetType(asset) {
var runtimeFn = localUploadRuntimeFunction('uploadedAssetType');
if (runtimeFn) return runtimeFn(asset);
return String(asset && (asset.asset_type || asset.assetType || asset.mime_type || '') || '').trim();
}
function fileTreeIconKindForFileName(fileName) {
var runtimeFn = localUploadRuntimeFunction('fileTreeIconKindForFileName');
if (runtimeFn) return runtimeFn(fileName);
var name = String(fileName || '').trim().toLowerCase();
var ext = name.indexOf('.') >= 0 ? name.split('.').pop() : '';
if (['doc', 'docx', 'odt', 'rtf', 'ppt', 'pptx', 'odp', 'xls', 'xlsx', 'ods', 'csv'].indexOf(ext) >= 0) return 'office';
if (ext === 'md' || ext === 'markdown') return 'markdown';
if (ext === 'pdf') return 'pdf';
if (['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg', 'bmp'].indexOf(ext) >= 0) return 'image';
if (['html', 'htm', 'css', 'scss', 'less', 'js', 'jsx', 'ts', 'tsx', 'mjs', 'cjs', 'vue', 'svelte', 'astro'].indexOf(ext) >= 0) return 'web';
if (['json', 'jsonc', 'json5', 'toml', 'yaml', 'yml', 'ini', 'env', 'xml', 'lock', 'hcl', 'tf', 'tfvars', 'nix', 'properties', 'conf', 'cfg', 'config', 'service', 'desktop', 'gitignore', 'gitattributes', 'editorconfig', 'npmrc', 'prettierrc', 'eslintrc'].indexOf(ext) >= 0 || ['.dockerignore', '.editorconfig', '.env', '.eslintrc', '.gitattributes', '.gitignore', '.npmrc', '.prettierrc', 'dockerfile', 'containerfile', 'makefile', 'cmakelists.txt', 'gemfile', 'rakefile', 'procfile'].indexOf(name) >= 0) return 'config';
if (['rs', 'py', 'go', 'java', 'c', 'cpp', 'h', 'hpp', 'cs', 'php', 'rb', 'sh', 'bash', 'zsh', 'sql', 'lua', 'dart', 'kt', 'kts', 'swift', 'scala', 'gradle', 'groovy', 'clj', 'ex', 'exs', 'erl', 'hrl', 'fs', 'fsx', 'r', 'jl', 'm', 'mm', 'pl', 'pm', 'ps1', 'bat', 'cmd', 'psm1', 'psd1', 'proto', 'graphql', 'gql', 'prisma', 'cmake', 'bazel', 'bzl'].indexOf(ext) >= 0) return 'code';
return '';
}
function shouldOpenLocalResourceInNewWindow(fileName) {
return false;
}
function isLocalUploadedAsset(asset) {
var runtimeFn = localUploadRuntimeFunction('isLocalUploadedAsset');
if (runtimeFn) return runtimeFn(asset);
var id = String(asset && asset.id || '').trim();
return String(asset && asset.sourceKind || '').trim() === 'local_folder' || id.indexOf('local:asset:') === 0;
}
function uploadedAssetExtension(asset) {
var runtimeFn = localUploadRuntimeFunction('uploadedAssetExtension');
if (runtimeFn) return runtimeFn(asset);
var match = uploadedAssetTitle(asset).toLowerCase().match(/\.([a-z0-9]+)$/);
return match ? match[1] : '';
}
function isNonOfficeAttachmentName(name, ext) {
var runtimeFn = localUploadRuntimeFunction('isNonOfficeAttachmentName');
if (runtimeFn) return runtimeFn(name, ext);
var codeFileNames = [
'.dockerignore', '.editorconfig', '.env', '.eslintrc', '.gitattributes', '.gitignore', '.npmrc', '.prettierrc',
'dockerfile', 'makefile', 'cmakelists.txt', 'gemfile', 'rakefile', 'procfile'
];
return [
'pdf', 'toml', 'json', 'yaml', 'yml', 'md', 'markdown', 'txt', 'ini', 'env', 'xml', 'html', 'htm', 'css', 'scss',
'less', 'js', 'jsx', 'ts', 'tsx', 'mjs', 'cjs', 'py', 'rs', 'go', 'java', 'c', 'cpp', 'h', 'hpp', 'cs',
'php', 'rb', 'sh', 'bash', 'zsh', 'sql', 'lock', 'log', 'vue', 'svelte', 'astro', 'jsonc', 'json5',
'mts', 'cts', 'lua', 'dart', 'kt', 'kts', 'swift', 'scala', 'gradle', 'groovy', 'clj',
'ex', 'exs', 'erl', 'hrl', 'fs', 'fsx', 'r', 'jl', 'm', 'mm', 'pl', 'pm', 'ps1', 'bat', 'cmd',
'psm1', 'psd1', 'dockerfile', 'containerfile', 'proto', 'graphql', 'gql', 'prisma', 'tf', 'tfvars',
'hcl', 'nix', 'cmake', 'bazel', 'bzl', 'properties', 'conf', 'cfg', 'config', 'service', 'desktop',
'gitignore', 'gitattributes', 'editorconfig', 'npmrc', 'prettierrc', 'eslintrc'
].indexOf(ext) >= 0 || codeFileNames.indexOf(name) >= 0;
}
function attachmentExtensionFromFileName(fileName) {
var runtimeFn = localUploadRuntimeFunction('attachmentExtensionFromFileName');
if (runtimeFn) return runtimeFn(fileName);
var name = String(fileName || '').trim().toLowerCase();
return name.indexOf('.') >= 0 ? name.split('.').pop() : '';
}
function isPdfAttachmentFileName(fileName) {
var runtimeFn = localUploadRuntimeFunction('isPdfAttachmentFileName');
if (runtimeFn) return runtimeFn(fileName);
return attachmentExtensionFromFileName(fileName) === 'pdf';
}
function isCodeAttachmentFileName(fileName) {
var runtimeFn = localUploadRuntimeFunction('isCodeAttachmentFileName');
if (runtimeFn) return runtimeFn(fileName);
var name = String(fileName || '').trim().toLowerCase();
var ext = attachmentExtensionFromFileName(name);
return ext !== 'pdf' && isNonOfficeAttachmentName(name, ext);
}
function inferCodeAttachmentLanguage(fileName) {
var runtimeFn = localUploadRuntimeFunction('inferCodeAttachmentLanguage');
if (runtimeFn) return runtimeFn(fileName);
var name = String(fileName || '').trim().toLowerCase();
var ext = attachmentExtensionFromFileName(name);
var byName = {
'dockerfile': 'dockerfile',
'makefile': 'makefile',
'cmakelists.txt': 'cmake',
'.gitignore': 'gitignore',
'.gitattributes': 'gitattributes',
'.editorconfig': 'ini',
'.env': 'dotenv'
};
if (byName[name]) return byName[name];
var byExt = {
bash: 'bash', bat: 'batch', c: 'c', cjs: 'javascript', cmd: 'batch', conf: 'text', cpp: 'cpp',
cs: 'csharp', css: 'css', cts: 'typescript', dart: 'dart', dockerfile: 'dockerfile', env: 'dotenv',
go: 'go', gql: 'graphql', gradle: 'groovy', graphql: 'graphql', h: 'c', hcl: 'hcl', hpp: 'cpp',
htm: 'html', html: 'html', ini: 'ini', java: 'java', js: 'javascript', json: 'json', json5: 'json',
jsonc: 'jsonc', jsx: 'javascript', kt: 'kotlin', kts: 'kotlin', less: 'less', log: 'text',
lua: 'lua', m: 'objective-c', markdown: 'markdown', md: 'markdown', mjs: 'javascript',
mts: 'typescript', nix: 'nix', php: 'php', pl: 'perl', pm: 'perl', prisma: 'prisma',
proto: 'protobuf', ps1: 'powershell', py: 'python', r: 'r', rb: 'ruby', rs: 'rust',
scss: 'scss', sh: 'bash', sql: 'sql', svelte: 'svelte', swift: 'swift', tf: 'terraform',
tfvars: 'terraform', toml: 'toml', ts: 'typescript', tsx: 'typescript', txt: 'text',
vue: 'vue', xml: 'xml', yaml: 'yaml', yml: 'yaml', zsh: 'bash'
};
return byExt[ext] || 'text';
}
function attachmentClassForFileName(fileName) {
var runtimeFn = localUploadRuntimeFunction('attachmentClassForFileName');
if (runtimeFn) return runtimeFn(fileName);
var name = String(fileName || '').trim().toLowerCase();
var ext = name.indexOf('.') >= 0 ? name.split('.').pop() : '';
if (['doc', 'docx', 'odt', 'rtf'].indexOf(ext) >= 0) return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-word';
if (['ppt', 'pptx', 'odp'].indexOf(ext) >= 0) return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-ppt';
if (['xls', 'xlsx', 'ods', 'csv'].indexOf(ext) >= 0) return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-sheet';
if (ext === 'pdf') return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-pdf';
if (isNonOfficeAttachmentName(name, ext)) {
return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-code';
}
return 'mnote-uploaded-attachment-row mnote-uploaded-attachment-file';
}
function uploadedAttachmentClass(asset) {
var runtimeFn = localUploadRuntimeFunction('uploadedAttachmentClass');
if (runtimeFn) return runtimeFn(asset);
return attachmentClassForFileName(uploadedAssetTitle(asset));
}
function buildOnlyOfficeAssetOpenUrl(asset, userId) {
var title = uploadedAssetTitle(asset);
var fileType = inferOnlyOfficeFileType(title, asset && asset.mime_type);
if (!fileType) return '';
var assetId = String(asset && asset.id || '').trim();
if (isLocalUploadedAsset(asset)) {
var localUrl = localAssetOpenUrl(asset, false);
if (!localUrl) return '';
return buildOnlyOfficeOpenUrl({
fileUrl: localUrl,
fileName: title,
fileType: fileType,
assetId: assetId,
documentId: String(asset && (asset.document_id || asset.documentId) || currentDocumentId() || '').trim(),
userId: userId || '',
mode: 'view'
});
}
return buildOnlyOfficeOpenUrl({
fileUrl: assetId ? '' : uploadedAssetUrl(asset),
fileName: title,
fileType: fileType,
assetId: assetId,
documentId: String(asset && (asset.document_id || asset.documentId) || currentDocumentId() || '').trim(),
userId: userId || '',
mode: 'view'
});
}
function uploadedFileSize(asset) {
var runtimeFn = localUploadRuntimeFunction('uploadedFileSize');
if (runtimeFn) return runtimeFn(asset);
var size = Number(asset && (asset.file_size || asset.fileSize) || 0);
if (!Number.isFinite(size) || size <= 0) return '';
if (size >= 1024 * 1024) return (size / 1024 / 1024).toFixed(size >= 10 * 1024 * 1024 ? 1 : 2) + ' MB';
if (size >= 1024) return (size / 1024).toFixed(size >= 100 * 1024 ? 0 : 2) + ' KB';
return String(Math.round(size)) + ' B';
}
var attachmentMetaCache = Object.create(null);
var attachmentMetaPending = Object.create(null);
var legacyOfficeAttachmentIndex = null;
var legacyOfficeAttachmentIndexPending = null;
function parseCurrentWorkspaceId() {
return (new URLSearchParams(window.location.search).get('workspaceId') || '').trim();
}
async function fetchLegacyOfficeAttachmentIndex() {
if (legacyOfficeAttachmentIndex) return legacyOfficeAttachmentIndex;
if (legacyOfficeAttachmentIndexPending) return legacyOfficeAttachmentIndexPending;
var documentId = currentDocumentId();
var workspaceId = parseCurrentWorkspaceId();
if (!documentId || !workspaceId) {
legacyOfficeAttachmentIndex = Object.create(null);
return legacyOfficeAttachmentIndex;
}
var projectionUrl = new URL('/api/tree/projections/file', window.location.origin);
projectionUrl.searchParams.set('documentId', documentId);
projectionUrl.searchParams.set('workspaceId', workspaceId);
var sourcePayload = currentWorkspaceSourcePayload();
if (sourcePayload.sourceKind) projectionUrl.searchParams.set('sourceKind', sourcePayload.sourceKind);
if (sourcePayload.rootUri) projectionUrl.searchParams.set('rootUri', sourcePayload.rootUri);
legacyOfficeAttachmentIndexPending = fetch(projectionUrl.toString(), {
method: 'GET',
credentials: 'include',
cache: 'no-store'
}).then(function(response) {
return response.json().catch(function() { return null; }).then(function(payload) {
var items = payload && payload.ok && payload.result && Array.isArray(payload.result.items)
? payload.result.items
: [];
var index = Object.create(null);
items.forEach(function(item) {
if (!item || item.rowKind !== 'asset') return;
var title = String(item.title || '').trim();
if (!title || index[title]) return;
var fileType = inferOnlyOfficeFileType(title, '');
if (!fileType) return;
var rowId = String(item.rowId || '').trim();
var assetId = String(item.assetId || '').trim();
if (!assetId && rowId.indexOf('asset:') === 0) assetId = rowId.slice('asset:'.length);
if (!assetId) return;
index[title] = {
assetId: assetId,
fileName: title,
fileType: fileType,
documentId: documentId
};
});
legacyOfficeAttachmentIndex = index;
return index;
});
}).catch(function() {
var empty = Object.create(null);
legacyOfficeAttachmentIndex = empty;
return empty;
}).finally(function() {
legacyOfficeAttachmentIndexPending = null;
});
return legacyOfficeAttachmentIndexPending;
}
async function healLegacyOfficeAttachmentParagraphs() {
var editor = document.querySelector('.editor-surface .ProseMirror');
if (!(editor instanceof HTMLElement)) return;
var paragraphs = Array.from(editor.querySelectorAll('p'));
var candidates = paragraphs.filter(function(paragraph) {
if (!(paragraph instanceof HTMLParagraphElement)) return;
if (paragraph.querySelector('a, img, video, audio, table, iframe, canvas')) return;
if (paragraph.childNodes.length !== 1 || paragraph.firstChild?.nodeType !== Node.TEXT_NODE) return;
var fileName = String(paragraph.textContent || '').trim();
if (!fileName) return;
return Boolean(inferOnlyOfficeFileType(fileName, ''));
});
if (!candidates.length) return;
var index = await fetchLegacyOfficeAttachmentIndex();
candidates.forEach(function(paragraph) {
var fileName = String(paragraph.textContent || '').trim();
var detail = index[fileName];
if (!detail) return;
var link = document.createElement('a');
link.textContent = fileName;
link.setAttribute('href', buildOnlyOfficeOpenPath({
fileUrl: '',
fileName: detail.fileName,
fileType: detail.fileType,
assetId: detail.assetId,
documentId: detail.documentId || currentDocumentId() || '',
userId: '',
mode: 'view'
}));
link.setAttribute('data-asset-id', detail.assetId);
attachmentClassForFileName(fileName).split(/\s+/).forEach(function(name) {
if (name) link.classList.add(name);
});
paragraph.replaceChildren(link);
enhanceEditorAttachmentLink(link);
});
}
function applyEditorAttachmentMeta(link, meta) {
if (!(link instanceof HTMLAnchorElement) || !meta) return;
if (meta.assetId) link.setAttribute('data-asset-id', meta.assetId);
if (meta.fileSize) link.setAttribute('data-file-size', meta.fileSize);
}
async function hydrateEditorAttachmentMeta(link) {
if (!(link instanceof HTMLAnchorElement)) return;
var detail = detailFromEditorAttachmentLink(link);
var assetId = String(detail && detail.assetId || '').trim();
if (!assetId) return;
var localFilePath = localFilePathFromAssetId(assetId);
if (localFilePath) {
var localMeta = {
assetId: assetId,
fileSize: String(detail && detail.fileSize || '').trim()
};
attachmentMetaCache[assetId] = localMeta;
applyEditorAttachmentMeta(link, localMeta);
return;
}
if (attachmentMetaCache[assetId]) {
applyEditorAttachmentMeta(link, attachmentMetaCache[assetId]);
return;
}
if (attachmentMetaPending[assetId]) {
try { await attachmentMetaPending[assetId]; } catch (_) {}
applyEditorAttachmentMeta(link, attachmentMetaCache[assetId]);
return;
}
2026-06-07 10:35:21 +08:00
document.documentElement.setAttribute('data-mnote-media-sign-retired', 'true');
attachmentMetaPending[assetId] = Promise.resolve(null).finally(function() {
delete attachmentMetaPending[assetId];
});
try {
var meta = await attachmentMetaPending[assetId];
applyEditorAttachmentMeta(link, meta);
} catch (_) {}
}
function revealFileTreeRow(row) {
var runtimeFn = fileTreeRuntimeFunction('revealFileTreeRow');
if (runtimeFn) return runtimeFn(row, fileTreeRuntimeDeps());
if (!(row instanceof HTMLElement)) return;
var node = row.closest('.tree-node');
while (node && node.parentElement) {
if (node.parentElement.classList && node.parentElement.classList.contains('tree-children')) {
node.parentElement.classList.remove('tree-children--collapsed');
var parentNode = node.parentElement.closest('.tree-node');
var parentRow = parentNode ? parentNode.querySelector(':scope > .tree-row') : null;
if (parentRow instanceof HTMLElement) {
parentRow.setAttribute('aria-expanded', 'true');
var toggle = parentRow.querySelector('[data-rust-action="toggle"]');
if (toggle) toggle.setAttribute('aria-expanded', 'true');
}
}
node = node.parentElement.closest('.tree-node');
}
try { row.scrollIntoView({ block: 'nearest' }); } catch (_) {}
}
function revealFileTreeAssetRow(assetId) {
var runtimeFn = fileTreeRuntimeFunction('revealFileTreeAssetRow');
if (runtimeFn) return runtimeFn(assetId, fileTreeRuntimeDeps());
if (!assetId) return false;
var row = document.querySelector('.tree-row[data-shell-mode="filetree"][data-asset-id="' + cssEscape(assetId) + '"]');
if (!(row instanceof HTMLElement)) return false;
revealFileTreeRow(row);
return true;
}
function appendUploadedAssetRow(asset, documentId) {
var runtimeFn = fileTreeRuntimeFunction('appendUploadedAssetRow');
if (runtimeFn) return runtimeFn(asset, documentId, fileTreeRuntimeDeps());
var assetId = String(asset && asset.id || '').trim();
if (!assetId) return false;
if (revealFileTreeAssetRow(assetId)) return true;
var objectKind = String(asset && (asset.objectKind || asset.resourceKind || '') || '').trim();
if (!objectKind && (String(asset && (asset.asset_type || asset.assetType) || '').trim() === 'mindmap' || /\.mindmap\.json$/i.test(assetId))) {
objectKind = 'mindmap';
}
var targetDocumentId = String(documentId || asset.document_id || asset.documentId || currentDocumentId() || '').trim();
var parentRow = targetDocumentId
? document.querySelector('.tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape('doc:' + targetDocumentId) + '"]')
: null;
if (!parentRow && currentSourceKind() === 'local_folder' && objectKind === 'mindmap') return false;
if (!parentRow) parentRow = document.querySelector('.tree-row[data-shell-mode="filetree"][data-row-kind="document"]');
var root = document.querySelector('#sidebar-file-tree-root .tree-root');
if (!root && !parentRow) return false;
var parentLi = parentRow ? parentRow.closest('.tree-node') : null;
var children = parentLi ? parentLi.querySelector(':scope > .tree-children') : null;
if (parentLi && !children) {
children = document.createElement('ul');
children.className = 'tree-children';
parentLi.appendChild(children);
}
if (children) {
children.classList.remove('tree-children--collapsed');
if (parentRow) {
parentRow.setAttribute('aria-expanded', 'true');
var toggle = parentRow.querySelector('[data-rust-action="toggle"]');
if (toggle) toggle.setAttribute('aria-expanded', 'true');
}
}
var container = children || root;
var li = document.createElement('li');
li.className = 'tree-node';
var objectIdentity = {
objectKind: objectKind || 'attachment',
documentId: targetDocumentId || null,
blockId: null,
assetId: assetId
};
li.setAttribute('data-node-id', 'asset:' + assetId);
var title = uploadedAssetTitle(asset);
var iconKind = fileTreeIconKindForFileName(title) || uploadedAssetType(asset) || 'file';
if (objectKind === 'mindmap') iconKind = 'mindmap';
li.innerHTML =
'<div class="tree-row" role="treeitem" aria-level="' + (parentRow ? '2' : '1') + '" aria-expanded="false" data-rust-rendered-row="filetree" data-testid="filetree-asset-row" data-row-id="' + escapeHtml('asset:' + assetId) + '" data-row-kind="asset" data-node-id="' + escapeHtml('asset:' + assetId) + '" data-document-id="' + escapeHtml(targetDocumentId) + '" data-doc-id="' + escapeHtml(targetDocumentId) + '" data-asset-id="' + escapeHtml(assetId) + '" data-object-identity="' + escapeHtml(objectIdentityAttr(objectIdentity)) + '" data-object-kind="' + escapeHtml(objectKind || 'attachment') + '" data-shell-mode="filetree" data-selected="false" data-active="false" draggable="true">' +
'<span class="tree-spacer" aria-hidden="true"></span><span class="tree-kind-badge" data-kind="' + escapeHtml(iconKind) + '" aria-hidden="true"></span>' +
'<button type="button" class="tree-link" data-rust-action="open" data-row-id="' + escapeHtml('asset:' + assetId) + '" data-document-id="' + escapeHtml(targetDocumentId) + '" data-asset-id="' + escapeHtml(assetId) + '"><span class="tree-link-title">' + escapeHtml(title) + '</span></button>' +
'<div class="tree-actions"><button type="button" class="tree-action" data-testid="filetree-action-menu" data-rust-action="menu" data-row-id="' + escapeHtml('asset:' + assetId) + '" aria-label="更多操作">…</button></div></div>';
container.appendChild(li);
revealFileTreeRow(li.querySelector('.tree-row'));
document.documentElement.setAttribute('data-mnote-last-upload-asset-id', assetId);
return true;
}
function removeFileTreeAssetRow(assetId) {
var normalized = String(assetId || '').trim();
if (!normalized) return false;
var row = document.querySelector('.tree-row[data-shell-mode="filetree"][data-asset-id="' + cssEscape(normalized) + '"]');
var node = row ? row.closest('.tree-node') : null;
if (!node || !node.parentElement) return false;
node.parentElement.removeChild(node);
return true;
}
function applyAssetsChangedToFileTree(detail) {
detail = detail || {};
var docId = String(detail.docId || detail.documentId || currentDocumentId() || '').trim();
var changed = false;
var explicitAsset = detail.asset && typeof detail.asset === 'object' ? detail.asset : null;
if (explicitAsset) {
appendUploadedAssetRow(explicitAsset, docId);
changed = true;
}
var mindmapAssetIds = Array.isArray(detail.mindmapAssetIds) ? detail.mindmapAssetIds : [];
if (detail.mindmapDeleted === true) {
mindmapAssetIds.forEach(function(assetId) {
if (removeFileTreeAssetRow(assetId)) changed = true;
});
}
if (changed) {
document.documentElement.setAttribute('data-mnote-assets-local-applied', 'true');
}
}
function mindmapAssetFromTarget(documentId, mindmapId, writeResult) {
var docId = String(documentId || currentDocumentId() || '').trim();
var assetId = String(mindmapId || '').trim();
if (!docId || !assetId) return null;
var result = writeResult && typeof writeResult === 'object' ? writeResult : {};
var resultAssetId = String(result.assetId || result.id || '').trim();
var relativePath = String(result.relativePath || result.rootRelativePath || '').trim();
var fileName = String(result.fileName || '').trim() || shortMindmapFileName(assetId);
return {
id: resultAssetId || (relativePath ? 'local-file:' + relativePath : assetId),
document_id: docId,
asset_type: 'mindmap',
file_name: fileName,
file_url: relativePath || ('/documents/' + encodeURIComponent(docId) + '/' + encodeURIComponent(fileName)),
sourcePath: relativePath,
rootRelativePath: relativePath,
sourceKind: currentSourceKind(),
rootUri: currentRootUri(),
objectKind: 'mindmap'
};
}
function shortMindmapFileName(mindmapId) {
var runtimeFn = fileTreeRuntimeFunction('shortMindmapFileName');
if (runtimeFn) return runtimeFn(mindmapId);
var raw = String(mindmapId || '').trim();
var pathName = raw.indexOf('/') >= 0 ? raw.split('/').pop() : raw;
if (/\.json$/i.test(pathName)) return pathName;
var digits = raw.match(/(\d{4,})$/);
var suffix = digits ? digits[1].slice(-6) : '';
return suffix ? '思维导图' + suffix + '.json' : '思维导图.json';
}
function parseMindmapApiTarget(input) {
var runtimeFn = fileTreeRuntimeFunction('parseMindmapApiTarget');
if (runtimeFn) return runtimeFn(input);
try {
var rawUrl = typeof input === 'string'
? input
: input && typeof input.url === 'string'
? input.url
: '';
if (!rawUrl) return null;
var url = new URL(rawUrl, window.location.origin);
var match = /^\/api\/mindmap\/([^/]+)\/([^/]+)$/.exec(url.pathname);
if (!match) return null;
return {
documentId: decodeURIComponent(match[1]),
mindmapId: decodeURIComponent(match[2])
};
} catch (_) {
return null;
}
}
function withLocalMindmapSourceParams(input) {
var target = parseMindmapApiTarget(input);
if (!target || currentSourceKind() !== 'local_folder') return input;
var rootUri = currentRootUri();
if (!rootUri) return input;
var rawUrl = typeof input === 'string'
? input
: input && typeof input.url === 'string'
? input.url
: '';
if (!rawUrl) return input;
var url = new URL(rawUrl, window.location.origin);
url.searchParams.set('sourceKind', 'local_folder');
url.searchParams.set('rootUri', rootUri);
if (typeof input === 'string') return url.pathname + url.search;
if (typeof Request !== 'undefined' && input instanceof Request) {
return new Request(url.toString(), input);
}
return url.toString();
}
function requestMethod(input, init) {
var runtimeFn = fileTreeRuntimeFunction('requestMethod');
if (runtimeFn) return runtimeFn(input, init);
return String(
init && init.method
? init.method
: input && typeof input.method === 'string'
? input.method
: 'GET'
).toUpperCase();
}
function requestBodyHasMindmapCreateOnly(init) {
var runtimeFn = fileTreeRuntimeFunction('requestBodyHasMindmapCreateOnly');
if (runtimeFn) return runtimeFn(init);
var body = init && typeof init.body === 'string' ? init.body : '';
if (!body) return false;
try {
var payload = JSON.parse(body);
return payload && payload.createOnly === true;
} catch (_) {
return false;
}
}
function applyMindmapApiMutationToFileTree(target, payload) {
if (!target || !target.documentId || !target.mindmapId) return;
var asset = mindmapAssetFromTarget(target.documentId, target.mindmapId, payload && payload.writeResult);
if (!asset) return;
var appended = appendUploadedAssetRow(asset, target.documentId);
if (!appended && currentSourceKind() === 'local_folder') void refreshLocalFolderSidebarSnapshot();
document.documentElement.setAttribute('data-mnote-assets-local-applied', 'true');
document.documentElement.setAttribute('data-mnote-last-mindmap-asset-id', asset.id || target.mindmapId);
}
function installMindmapAssetFetchObserver() {
if (window.__mnoteMindmapAssetFetchObserverInstalled === true) return;
if (typeof window.fetch !== 'function') return;
window.__mnoteMindmapAssetFetchObserverInstalled = true;
var originalFetch = window.fetch.bind(window);
window.fetch = function(input, init) {
var nextInput = withLocalMindmapSourceParams(input);
var target = parseMindmapApiTarget(nextInput);
var method = requestMethod(input, init);
var createOnly = requestBodyHasMindmapCreateOnly(init || {});
return originalFetch(nextInput, init).then(function(response) {
if (target && method === 'POST' && response && response.ok) {
var cloned = response.clone();
void cloned.json().then(function(payload) {
if (createOnly || target.documentId === currentDocumentId()) {
applyMindmapApiMutationToFileTree(target, payload);
}
}).catch(function() {
if (createOnly || target.documentId === currentDocumentId()) {
applyMindmapApiMutationToFileTree(target, null);
}
});
}
return response;
});
};
}
async function archiveLocalFileTreeAsset(row, assetId) {
if (!assetId) return false;
await dispatchTreeCommand(row || document.body, {
action: 'archive',
workspaceId: resolveWorkspaceId(row || document.body),
documentId: assetId
});
removeFileTreeAssetRow(assetId);
return true;
}
async function deleteSingleFileTreeAsset(detail, trigger) {
var assetId = String(detail && detail.assetId || '').trim();
if (!assetId) return false;
var row = trigger && trigger.closest ? trigger.closest('.tree-row[data-shell-mode="filetree"]') : null;
if (!row) row = document.querySelector('.tree-row[data-shell-mode="filetree"][data-asset-id="' + cssEscape(assetId) + '"]');
if (currentSourceKind() === 'local_folder') {
return archiveLocalFileTreeAsset(row, assetId);
}
var documentId = String(detail && detail.documentId || '').trim();
var kind = classifySidebarFileTreeAsset(row);
if (kind === 'mindmap') {
var response = await fetch('/api/mindmap/' + encodeURIComponent(documentId) + '/' + encodeURIComponent(assetId), { method: 'DELETE' });
if (!response.ok) throw new Error('mindmap_delete_failed_' + response.status);
removeFileTreeAssetRow(assetId);
return true;
}
if (kind === 'table') {
var tableResponse = await fetch('/api/tables/' + encodeURIComponent(assetId), { method: 'DELETE' });
if (!tableResponse.ok) throw new Error('table_delete_failed_' + tableResponse.status);
removeFileTreeAssetRow(assetId);
return true;
}
await postSidebarFileTreeJson('/api/media/batch', { action: 'delete', assetIds: [assetId] });
removeFileTreeAssetRow(assetId);
return true;
}
function resolveEditorUploadContext(detail) {
var runtimeFn = localUploadRuntimeFunction('resolveEditorUploadContext');
if (runtimeFn) {
return runtimeFn(detail || {}, {
rootSelector: EDITOR_UPLOAD_ROOT_SELECTOR,
editorUploadRootFromElement: editorUploadRootFromElement,
currentDocumentId: currentDocumentId,
resolveWorkspaceId: resolveWorkspaceId
});
}
var root = null;
var selector = detail && detail.editorRootSelector ? String(detail.editorRootSelector) : '';
if (selector) {
try {
var selected = document.querySelector(selector);
if (selected instanceof HTMLElement) root = selected;
} catch (_) {}
}
if (!root && window.__mnoteIntendedSlashRoot instanceof HTMLElement && window.__mnoteIntendedSlashRoot.isConnected) {
root = window.__mnoteIntendedSlashRoot;
}
if (!root && window.__mnoteLastEditorUploadRoot instanceof HTMLElement && window.__mnoteLastEditorUploadRoot.isConnected) {
root = window.__mnoteLastEditorUploadRoot;
}
if (!root && document.activeElement instanceof Element) {
root = editorUploadRootFromElement(document.activeElement);
}
if (!root) {
var focused = document.querySelector(EDITOR_UPLOAD_ROOT_SELECTOR + ' .ProseMirror:focus-within');
root = editorUploadRootFromElement(focused);
}
if (!root) {
root = document.querySelector('[data-editor-host-kind="leptos_tiptap_island"][data-pane-role="primary"]');
}
var pane = root instanceof Element ? root.closest('.document-pane[data-pane-role]') : null;
var shell = root instanceof Element ? root.closest('.document-shell[data-document-id]') : null;
return {
root: root instanceof HTMLElement ? root : null,
documentId: String(
detail && detail.documentId
|| (root instanceof HTMLElement && root.getAttribute('data-document-id'))
|| (pane instanceof HTMLElement && pane.getAttribute('data-pane-document-id'))
|| (shell instanceof HTMLElement && shell.getAttribute('data-document-id'))
|| currentDocumentId()
|| ''
).trim(),
workspaceId: String(
detail && detail.workspaceId
|| (root instanceof HTMLElement && root.getAttribute('data-workspace-id'))
|| (pane instanceof HTMLElement && pane.getAttribute('data-pane-workspace-id'))
|| (shell instanceof HTMLElement && shell.getAttribute('data-workspace-id'))
|| resolveWorkspaceId(document.body)
|| ''
).trim()
};
}
function editorRootFromUploadOptions(options) {
var runtimeFn = localUploadRuntimeFunction('editorRootFromUploadOptions');
if (runtimeFn) {
return runtimeFn(options || {}, {
rootSelector: EDITOR_UPLOAD_ROOT_SELECTOR,
editorUploadRootFromElement: editorUploadRootFromElement
});
}
if (options && options.editorRoot instanceof HTMLElement) return options.editorRoot;
if (window.__mnoteIntendedSlashRoot instanceof HTMLElement && window.__mnoteIntendedSlashRoot.isConnected) {
return window.__mnoteIntendedSlashRoot;
}
if (window.__mnoteLastEditorUploadRoot instanceof HTMLElement && window.__mnoteLastEditorUploadRoot.isConnected) {
return window.__mnoteLastEditorUploadRoot;
}
var focused = document.querySelector(EDITOR_UPLOAD_ROOT_SELECTOR + ' .ProseMirror:focus-within');
return editorUploadRootFromElement(focused);
}
async function fetchWithTimeout(input, init, timeoutMs, label) {
var runtimeFn = localUploadRuntimeFunction('fetchWithTimeout');
if (runtimeFn) {
return await runtimeFn(input, init || {}, timeoutMs, label);
}
var controller = typeof AbortController === 'function' ? new AbortController() : null;
var timer = 0;
var timeout = Math.max(1000, Number(timeoutMs) || 15000);
try {
if (controller) {
timer = window.setTimeout(function() {
controller.abort();
}, timeout);
}
var nextInit = Object.assign({}, init || {});
if (controller) nextInit.signal = controller.signal;
return await fetch(input, nextInit);
} catch (error) {
if (error && error.name === 'AbortError') {
throw new Error((label || '请求') + '超时');
}
throw error;
} finally {
if (timer) window.clearTimeout(timer);
}
}
function uploadTimeoutMsForFile(file, requestedMs) {
var runtimeFn = localUploadRuntimeFunction('uploadTimeoutMsForFile');
if (runtimeFn) return runtimeFn(file, requestedMs);
var requested = Number(requestedMs) || 0;
var size = Number(file && file.size || 0);
if (!Number.isFinite(size) || size <= 0) return Math.max(requested, 15000);
var sizeBased = 15000 + Math.ceil(size / (1024 * 1024)) * 12000;
return Math.min(10 * 60 * 1000, Math.max(requested, 60000, sizeBased));
}
async function insertUploadedAssetIntoEditor(asset, targetRoot) {
var runtimeFn = localUploadRuntimeFunction('insertUploadedAssetIntoEditor');
if (runtimeFn) {
return await runtimeFn(asset, targetRoot, {
uploadedAssetTitle: uploadedAssetTitle,
localAssetOpenUrl: localAssetOpenUrl,
uploadedAssetUrl: uploadedAssetUrl,
uploadedAssetType: uploadedAssetType,
isLocalUploadedAsset: isLocalUploadedAsset,
buildOnlyOfficeAssetOpenUrl: buildOnlyOfficeAssetOpenUrl,
fetchCurrentOnlyOfficeUserId: fetchCurrentOnlyOfficeUserId,
buildOnlyOfficeOpenPath: buildOnlyOfficeOpenPath,
inferOnlyOfficeFileType: inferOnlyOfficeFileType,
currentDocumentId: currentDocumentId,
currentRootUri: currentRootUri,
uploadedAttachmentClass: uploadedAttachmentClass,
uploadedFileSize: uploadedFileSize,
cssEscape: cssEscape,
enhanceEditorAttachmentLinks: enhanceEditorAttachmentLinks
});
}
var editorRoot = targetRoot instanceof HTMLElement
? targetRoot.querySelector('.editor-surface .ProseMirror')
: document.querySelector('.editor-surface .ProseMirror');
if (targetRoot instanceof HTMLElement) window.__mnoteLastEditorUploadRoot = targetRoot;
var editor = editorRoot && editorRoot.editor;
if (!editor || !editor.chain) {
document.documentElement.setAttribute('data-mnote-last-upload-inserted', 'false');
document.documentElement.setAttribute('data-mnote-last-upload-insert-error', 'editor_unavailable');
return false;
}
var title = uploadedAssetTitle(asset);
2026-05-29 11:13:05 +08:00
var markdownHref = uploadedAssetMarkdownHref(asset);
var localOpenUrl = localAssetOpenUrl(asset, false);
var fallbackUrl = uploadedAssetUrl(asset);
var imageUrl = localOpenUrl || fallbackUrl || markdownHref;
var url = markdownHref || localOpenUrl || fallbackUrl;
var type = uploadedAssetType(asset);
var assetId = String(asset && asset.id || '').trim();
var sizeLabel = uploadedFileSize(asset);
try {
if (type === 'image' && imageUrl) {
return editor.chain().focus().setImage({ src: imageUrl, alt: title, title: title }).run() === true;
}
2026-05-29 11:13:05 +08:00
var href = markdownHref || url;
if (href) {
var inserted = editor.chain().focus().insertContent([
{
type: 'paragraph',
content: [{
type: 'text',
text: title,
marks: [{
type: 'link',
attrs: {
2026-05-29 11:13:05 +08:00
href: href,
target: '_blank',
rel: 'noopener noreferrer nofollow',
class: uploadedAttachmentClass(asset)
}
}]
}]
},
{ type: 'paragraph' }
]).focus('end').run() === true;
if (inserted) {
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');
} else {
document.documentElement.setAttribute('data-mnote-last-upload-inserted', 'false');
document.documentElement.setAttribute('data-mnote-last-upload-insert-error', 'insert_content_failed');
}
window.setTimeout(function annotateUploadedLink(attempt) {
if (targetRoot instanceof HTMLElement) window.__mnoteLastEditorUploadRoot = targetRoot;
enhanceEditorAttachmentLinks();
var selector = assetId
? '.editor-surface .ProseMirror a[href*="' + cssEscape(assetId) + '"]'
: '.editor-surface .ProseMirror a';
var link = targetRoot instanceof HTMLElement
? targetRoot.querySelector(selector)
: document.querySelector(selector);
if (!(link instanceof HTMLElement) && assetId) {
var scope = targetRoot instanceof HTMLElement ? targetRoot : document;
link = Array.from(scope.querySelectorAll('.editor-surface .ProseMirror a')).find(function(candidate) {
var href = String(candidate.getAttribute('href') || '');
try { href = decodeURIComponent(href); } catch (_) {}
return href.indexOf(assetId) >= 0;
}) || null;
}
if (link instanceof HTMLElement) {
if (assetId) link.setAttribute('data-asset-id', assetId);
if (sizeLabel) link.setAttribute('data-file-size', sizeLabel);
} else if (Number(attempt) < 20) {
window.setTimeout(function() { annotateUploadedLink(Number(attempt) + 1); }, 50);
}
}, 0, 0);
return inserted;
}
} catch (error) {
console.warn('[mnote upload] insert uploaded asset failed', error);
}
return false;
}
async function uploadFileToMediaAsset(file, plan, options) {
var runtimeFn = localUploadRuntimeFunction('uploadFileToMediaAsset');
if (runtimeFn) {
return await runtimeFn(file, plan, options || {}, {
currentSourceKind: currentSourceKind,
currentRootUri: currentRootUri,
currentDocumentId: currentDocumentId,
editorRootFromUploadOptions: editorRootFromUploadOptions,
appendUploadedAssetRow: appendUploadedAssetRow,
refreshLocalFolderSidebarSnapshot: refreshLocalFolderSidebarSnapshot,
dispatchEvent: function(event) { return window.dispatchEvent(event); },
CustomEvent: CustomEvent,
buildOnlyOfficeAssetOpenUrl: buildOnlyOfficeAssetOpenUrl,
fetchCurrentOnlyOfficeUserId: fetchCurrentOnlyOfficeUserId,
buildOnlyOfficeOpenPath: buildOnlyOfficeOpenPath,
inferOnlyOfficeFileType: inferOnlyOfficeFileType,
enhanceEditorAttachmentLinks: enhanceEditorAttachmentLinks,
cssEscape: cssEscape
});
}
if (currentSourceKind() === 'local_folder') {
var rootUri = currentRootUri();
var documentId = String(plan && plan.targetDocumentId || currentDocumentId() || '').trim();
var hasFolderTarget = plan && Object.prototype.hasOwnProperty.call(plan, 'targetRelativePath');
var uploadIntent = String(plan && plan.uploadIntent || (hasFolderTarget ? 'filetree.folder.drop' : 'editor.markdown.attach')).trim();
if (!rootUri || !uploadIntent) {
throw new Error('本地 Markdown 上传缺少 rootUri 或 documentId');
}
var localUploadRuntime = localUploadRuntimeFunction('uploadLocalFolderAsset');
var localPayload = null;
if (localUploadRuntime) {
var localResult = await localUploadRuntime(file, plan, {
rootUri: rootUri,
documentId: documentId,
timeoutMs: uploadTimeoutMsForFile(file, 15000)
});
localPayload = localResult && localResult.asset ? { asset: localResult.asset } : null;
} else {
var localForm = new FormData();
localForm.append('file', file);
localForm.append('rootUri', rootUri);
localForm.append('uploadIntent', uploadIntent);
if (documentId) localForm.append('documentId', documentId);
if (hasFolderTarget) localForm.append('targetRelativePath', String(plan.targetRelativePath || ''));
localForm.append('kind', file && String(file.type || '').indexOf('image/') === 0 ? 'image' : 'attachment');
var localResponse = await fetchWithTimeout('/api/local-folder/assets/upload', {
method: 'POST',
credentials: 'include',
body: localForm
}, uploadTimeoutMsForFile(file, 15000), '本地上传');
localPayload = await localResponse.json().catch(function() { return null; });
if (!localResponse.ok || !localPayload || !localPayload.asset) {
throw new Error(localPayload && localPayload.error ? localPayload.error : '上传失败');
}
}
if (options && options.insertIntoEditor) {
await insertUploadedAssetIntoEditor(localPayload.asset, editorRootFromUploadOptions(options));
}
if (!(options && options.insertIntoEditor)) void refreshLocalFolderSidebarSnapshot();
window.dispatchEvent(new CustomEvent('wolai:local-assets-changed', {
detail: { docId: documentId, asset: localPayload.asset, assetIds: [localPayload.asset.id] }
}));
return localPayload.asset;
}
var mediaUploadRuntime = localUploadRuntimeFunction('uploadMediaAsset');
var payload = null;
if (mediaUploadRuntime) {
var mediaResult = await mediaUploadRuntime(file, plan, { timeoutMs: 15000 });
payload = mediaResult && mediaResult.asset ? { asset: mediaResult.asset } : null;
if (!payload || !payload.asset) {
throw new Error('上传失败');
}
} else {
2026-06-07 10:35:21 +08:00
document.documentElement.setAttribute('data-mnote-media-upload-retired', 'true');
throw new Error('旧 Convex Files 上传链已退役;local-first 附件请使用本地文件夹上传目标。');
}
appendUploadedAssetRow(payload.asset, plan.targetDocumentId);
if (options && options.insertIntoEditor) {
await insertUploadedAssetIntoEditor(payload.asset, editorRootFromUploadOptions(options));
}
window.dispatchEvent(new CustomEvent('wolai:assets-changed', {
detail: { docId: plan.targetDocumentId, asset: payload.asset, assetIds: [payload.asset.id] }
}));
return payload.asset;
}
window.addEventListener('wolai:assets-changed', function(event) {
applyAssetsChangedToFileTree(event.detail || {});
});
window.addEventListener('wolai:local-assets-changed', function(event) {
applyAssetsChangedToFileTree(event.detail || {});
});
window.addEventListener('mnote:knowledge-rag-source-updated', function() {
if (currentSourceKind() === 'local_folder') void refreshLocalFolderSidebarSnapshot();
});
installMindmapAssetFetchObserver();
async function uploadFilesWithResolvedTarget(files, detail, options) {
var runtimeFn = localUploadRuntimeFunction('uploadFilesWithResolvedTarget');
if (runtimeFn) {
return await runtimeFn(files, detail || {}, options || {}, {
resolveFileTreeUploadTarget: resolveFileTreeUploadTarget,
uploadFileToMediaAsset: uploadFileToMediaAsset,
alert: function(message) { window.alert(message); }
});
}
var list = Array.from(files || []).filter(Boolean);
if (!list.length) return [];
var plan = await resolveFileTreeUploadTarget(detail || {});
var uploaded = [];
var errors = [];
for (var i = 0; i < list.length; i += 1) {
try {
uploaded.push(await uploadFileToMediaAsset(list[i], plan, options || {}));
} catch (error) {
errors.push(list[i].name + ': ' + (error && error.message ? error.message : '上传失败'));
}
}
if (errors.length) {
window.alert('部分文件上传失败:\n' + errors.slice(0, 6).join('\n') + (errors.length > 6 ? '\n...' : ''));
}
return uploaded;
}
function openEditorUploadFilePicker(detail) {
var runtimeFn = localUploadRuntimeFunction('openEditorUploadFilePicker');
if (runtimeFn) {
return runtimeFn(detail || {}, {
rootSelector: EDITOR_UPLOAD_ROOT_SELECTOR,
editorUploadRootFromElement: editorUploadRootFromElement,
currentDocumentId: currentDocumentId,
resolveWorkspaceId: resolveWorkspaceId,
uploadFilesWithResolvedTarget: uploadFilesWithResolvedTarget
});
}
var uploadContext = resolveEditorUploadContext(detail || {});
var input = document.createElement('input');
input.type = 'file';
input.multiple = detail && detail.multiple !== false;
if (detail && detail.accept) input.accept = String(detail.accept);
input.style.position = 'fixed';
input.style.left = '-9999px';
input.style.top = '-9999px';
document.body.appendChild(input);
input.addEventListener('change', function() {
var files = Array.from(input.files || []);
input.remove();
void uploadFilesWithResolvedTarget(files, {
workspaceId: uploadContext.workspaceId || resolveWorkspaceId(document.body),
documentId: uploadContext.documentId || currentDocumentId(),
targetRowId: null,
uploadIntent: 'editor.markdown.attach'
}, {
insertIntoEditor: detail && detail.insertIntoEditor !== false,
editorRoot: uploadContext.root
});
}, { once: true });
input.click();
}
window.addEventListener('mnote:editor-upload-request', function(event) {
openEditorUploadFilePicker(event.detail || {});
});
window.addEventListener('tree.filetree.external-drop', function(event) {
var detail = event.detail || {};
void uploadFilesWithResolvedTarget(detail.files || [], detail, {
insertIntoEditor: String(detail.documentId || '') === currentDocumentId()
});
});
document.addEventListener('dragover', function(event) {
var editorTarget = closestAction(event.target, '[data-testid="mnote-leptos-tiptap-editor-stage"], .editor-surface .ProseMirror');
var hasFiles = event.dataTransfer && Array.prototype.indexOf.call(event.dataTransfer.types || [], 'Files') >= 0;
if (!editorTarget || !hasFiles) return;
event.preventDefault();
event.stopPropagation();
if (event.dataTransfer) event.dataTransfer.dropEffect = 'copy';
}, true);
document.addEventListener('drop', function(event) {
var editorTarget = closestAction(event.target, '[data-testid="mnote-leptos-tiptap-editor-stage"], .editor-surface .ProseMirror');
var files = event.dataTransfer ? Array.from(event.dataTransfer.files || []) : [];
if (!editorTarget || !files.length) return;
event.preventDefault();
event.stopPropagation();
void uploadFilesWithResolvedTarget(files, {
workspaceId: resolveWorkspaceId(document.body),
documentId: currentDocumentId(),
targetRowId: null,
uploadIntent: 'editor.markdown.attach'
}, {
insertIntoEditor: true,
editorRoot: editorUploadRootFromElement(editorTarget)
});
}, true);
const sidebarFileTreeCommandState = {
get activeTreeContextMenu() { return activeTreeContextMenu; },
set activeTreeContextMenu(value) { activeTreeContextMenu = value; },
get sidebarFileTreeClipboard() { return sidebarFileTreeClipboard; },
set sidebarFileTreeClipboard(value) { sidebarFileTreeClipboard = value; },
};
const sidebarFileTreeCommand = createSidebarFileTreeCommandRuntime({
applyRemoveDocumentDelta,
createFileTreeFolder,
createPage,
cssEscape,
currentDocumentId,
currentRootUri,
currentSourceKind,
deleteSingleFileTreeAsset,
dispatchSidebarEvent,
dispatchTreeCommand,
ensureFileTreeWritableTarget,
fileTreeRuntimeDeps,
fileTreeRuntimeFunction,
fileTreeSelectionRuntimeDeps,
fileTreeSelectionRuntimeFunction,
isFileTreePageRow,
localFilePathFromAssetId,
normalizeFileTreePageRenameTitle,
openConvexAssetFromFileTree,
2026-05-26 07:08:26 +08:00
openEditorAttachmentDetail: (...args) => openEditorAttachmentDetail(...args),
openEditorAttachmentDownload: (...args) => openEditorAttachmentDownload(...args),
openEditorAttachmentEditTab: (...args) => openEditorAttachmentEditTab(...args),
openEditorAttachmentNewWindow: (...args) => openEditorAttachmentNewWindow(...args),
2026-06-01 10:07:42 +08:00
openLocalResourceInActiveTab: (...args) => openLocalResourceInActiveTab(...args),
refreshLocalFolderSidebarSnapshot,
removeFileTreeAssetRow,
revealFileTreeResource,
resolveWorkspaceId,
runtimeState: sidebarFileTreeCommandState,
selectedSidebarFileTreeSelection: sidebarFileTreeSelection,
updateTitleEverywhere,
validateFileTreeRename,
});
const rowTitle = (...args) => sidebarFileTreeCommand.rowTitle(...args);
const rowCenter = (...args) => sidebarFileTreeCommand.rowCenter(...args);
const renameFileTreeAsset = (...args) => sidebarFileTreeCommand.renameFileTreeAsset(...args);
const beginFileTreeInlineRename = (...args) => sidebarFileTreeCommand.beginFileTreeInlineRename(...args);
const closeTreeContextMenu = (...args) => sidebarFileTreeCommand.closeTreeContextMenu(...args);
const copyTreeContextValue = (...args) => sidebarFileTreeCommand.copyTreeContextValue(...args);
const triggerBrowserDownload = (...args) => sidebarFileTreeCommand.triggerBrowserDownload(...args);
const recordFileTreeAction = (...args) => sidebarFileTreeCommand.recordFileTreeAction(...args);
const recordFileTreeActionStatus = (...args) => sidebarFileTreeCommand.recordFileTreeActionStatus(...args);
const documentHref = (...args) => sidebarFileTreeCommand.documentHref(...args);
const convertToPreviousSiblingChild = (...args) => sidebarFileTreeCommand.convertToPreviousSiblingChild(...args);
const fileTreeCopyPath = (...args) => sidebarFileTreeCommand.fileTreeCopyPath(...args);
const fileTreeMenuTargetParentId = (...args) => sidebarFileTreeCommand.fileTreeMenuTargetParentId(...args);
const withOfficeEditModeGuard = (...args) => sidebarFileTreeCommand.withOfficeEditModeGuard(...args);
const handleTreeContextMenuAction = (...args) => sidebarFileTreeCommand.handleTreeContextMenuAction(...args);
const appendTreeContextMenuButton = (...args) => sidebarFileTreeCommand.appendTreeContextMenuButton(...args);
const buildSidebarFileTreeContext = (...args) => sidebarFileTreeCommand.buildSidebarFileTreeContext(...args);
const evaluateSidebarFileTreeWhen = (...args) => sidebarFileTreeCommand.evaluateSidebarFileTreeWhen(...args);
const openTreeContextMenu = (...args) => sidebarFileTreeCommand.openTreeContextMenu(...args);
const openPageTreeContextMenu = (...args) => sidebarFileTreeCommand.openPageTreeContextMenu(...args);
const openFileTreeContextMenu = (...args) => sidebarFileTreeCommand.openFileTreeContextMenu(...args);
const visibleFileTreeRows = (...args) => sidebarFileTreeCommand.visibleFileTreeRows(...args);
const syncSidebarFileTreeSelection = (...args) => sidebarFileTreeCommand.syncSidebarFileTreeSelection(...args);
const selectSidebarFileTreeRow = (...args) => sidebarFileTreeCommand.selectSidebarFileTreeRow(...args);
const selectSidebarFileTreeDocument = (...args) => sidebarFileTreeCommand.selectSidebarFileTreeDocument(...args);
const selectSidebarFileTreeRowById = (...args) => sidebarFileTreeCommand.selectSidebarFileTreeRowById(...args);
const pendingLocalFolderRestoreRowId = (...args) => sidebarFileTreeCommand.pendingLocalFolderRestoreRowId(...args);
const clearPendingLocalFolderRestoreRowId = (...args) => sidebarFileTreeCommand.clearPendingLocalFolderRestoreRowId(...args);
const applyPendingLocalFolderRestoreFocusOnce = (...args) => sidebarFileTreeCommand.applyPendingLocalFolderRestoreFocusOnce(...args);
const schedulePendingLocalFolderRestoreFocus = (...args) => sidebarFileTreeCommand.schedulePendingLocalFolderRestoreFocus(...args);
const selectedSidebarFileTreeRowIdsForDrag = (...args) => sidebarFileTreeCommand.selectedSidebarFileTreeRowIdsForDrag(...args);
const selectedSidebarFileTreeRows = (...args) => sidebarFileTreeCommand.selectedSidebarFileTreeRows(...args);
const fileTreeRowDocumentId = (...args) => sidebarFileTreeCommand.fileTreeRowDocumentId(...args);
const fileTreeRowAssetId = (...args) => sidebarFileTreeCommand.fileTreeRowAssetId(...args);
const decodeLocalEncodedPath = (...args) => sidebarFileTreeCommand.decodeLocalEncodedPath(...args);
const fileTreeRowLocalRelativePath = (...args) => sidebarFileTreeCommand.fileTreeRowLocalRelativePath(...args);
const fileTreeRowLocalUploadTargetRelativePath = (...args) => sidebarFileTreeCommand.fileTreeRowLocalUploadTargetRelativePath(...args);
const readWorkspacePathFromRow = (...args) => sidebarFileTreeCommand.readWorkspacePathFromRow(...args);
const fileTreeRowKind = (...args) => sidebarFileTreeCommand.fileTreeRowKind(...args);
const isFileTreeDownloadableAssetRow = (...args) => sidebarFileTreeCommand.isFileTreeDownloadableAssetRow(...args);
const isFileTreeDownloadableRow = (...args) => sidebarFileTreeCommand.isFileTreeDownloadableRow(...args);
const fileTreeAssetDownloadDetail = (...args) => sidebarFileTreeCommand.fileTreeAssetDownloadDetail(...args);
const selectedSidebarFileTreeRowsForDownload = (...args) => sidebarFileTreeCommand.selectedSidebarFileTreeRowsForDownload(...args);
const selectedSidebarFileTreeAssetRowsForDownload = (...args) => sidebarFileTreeCommand.selectedSidebarFileTreeAssetRowsForDownload(...args);
const downloadSelectedFileTreeAssetRows = (...args) => sidebarFileTreeCommand.downloadSelectedFileTreeAssetRows(...args);
const hasSelectedDocumentAncestor = (...args) => sidebarFileTreeCommand.hasSelectedDocumentAncestor(...args);
const classifySidebarFileTreeAsset = (...args) => sidebarFileTreeCommand.classifySidebarFileTreeAsset(...args);
const buildSidebarFileTreeDeletePlan = (...args) => sidebarFileTreeCommand.buildSidebarFileTreeDeletePlan(...args);
const sidebarFileTreeDeleteConfirmText = (...args) => sidebarFileTreeCommand.sidebarFileTreeDeleteConfirmText(...args);
const postSidebarFileTreeJson = (...args) => sidebarFileTreeCommand.postSidebarFileTreeJson(...args);
const fileTreeRowsByRowIds = (...args) => sidebarFileTreeCommand.fileTreeRowsByRowIds(...args);
const fileTreeChildCount = (...args) => sidebarFileTreeCommand.fileTreeChildCount(...args);
const moveSidebarFileTreeRows = (...args) => sidebarFileTreeCommand.moveSidebarFileTreeRows(...args);
const pasteSidebarFileTreeClipboard = (...args) => sidebarFileTreeCommand.pasteSidebarFileTreeClipboard(...args);
const deleteSelectedSidebarFileTreeRows = (...args) => sidebarFileTreeCommand.deleteSelectedSidebarFileTreeRows(...args);
sidebarFileTreeUpload = createSidebarFileTreeUploadRuntime({
cssEscape,
currentDocumentId,
fileTreeRuntimeDeps,
fileTreeRuntimeFunction,
recordFileTreeAction,
recordFileTreeActionStatus,
resolveWorkspaceId,
rowTitle,
selectedSidebarFileTreeSelection: sidebarFileTreeSelection,
});
function ensureSearchModal() {
var existing = document.querySelector('[data-testid="wolai-search-modal"]');
if (existing instanceof HTMLElement) return existing;
var overlay = document.createElement('div');
overlay.className = 'wolai-search-overlay';
overlay.setAttribute('data-testid', 'wolai-search-modal');
overlay.setAttribute('role', 'dialog');
overlay.setAttribute('aria-modal', 'true');
overlay.hidden = true;
overlay.innerHTML = '' +
'<div class="wolai-search-dialog">' +
'<div class="wolai-search-input-row">' +
'<span class="material-symbols-outlined wolai-search-input-icon" data-icon="search" aria-hidden="true"></span>' +
'<input data-testid="wolai-search-input" class="wolai-search-input" type="search" autocomplete="off" placeholder="在当前工作区中搜索" />' +
'<button type="button" class="wolai-search-close" data-testid="wolai-search-close" aria-label="关闭搜索">×</button>' +
'</div>' +
'<div class="wolai-search-options" data-testid="wolai-search-options" aria-label="搜索选项" hidden>' +
'<div class="wolai-search-options-left">' +
'<span class="wolai-search-switch-control"><span>仅匹配标题</span><button type="button" class="wolai-search-switch" data-search-switch="title" role="switch" aria-checked="false" aria-label="仅匹配标题"></button></span>' +
'<span class="wolai-search-switch-control"><span>精确匹配</span><button type="button" class="wolai-search-switch" data-search-switch="exact" role="switch" aria-checked="false" aria-label="精确匹配"></button></span>' +
'<span class="wolai-search-sort-control"><span>资料库模式</span><select class="wolai-search-sort-value" data-search-knowledge-mode aria-label="资料库检索模式"><option value="exact" selected>关键词</option><option value="mix">综合</option><option value="hybrid">图谱混合</option><option value="naive">向量</option><option value="local">实体</option><option value="global">关系</option></select></span>' +
'<span class="wolai-search-sort-control"><span>按编辑时间</span><button type="button" class="wolai-search-sort-value" data-search-sort="updated" aria-label="按编辑时间范围">所有</button></span>' +
'<span class="wolai-search-sort-control"><span>按创建时间</span><button type="button" class="wolai-search-sort-value" data-search-sort="created" aria-label="按创建时间范围">所有</button></span>' +
'</div>' +
'<div class="wolai-search-options-right">' +
'<span class="wolai-search-switch-control"><span>全盘资料库</span><button type="button" class="wolai-search-switch is-on" data-search-switch="knowledge" role="switch" aria-checked="true" aria-label="全盘资料库检索"></button></span>' +
'<span class="wolai-search-switch-control"><span>页面内搜索</span><button type="button" class="wolai-search-switch" data-search-switch="page" role="switch" aria-checked="false" aria-label="页面内搜索"></button></span>' +
'<span class="wolai-search-switch-control"><span>折叠同来源</span><button type="button" class="wolai-search-switch is-on" data-search-switch="collapseSource" role="switch" aria-checked="true" aria-label="默认折叠相同来源结果"></button></span>' +
'</div>' +
'</div>' +
'<div class="wolai-search-result-meta" data-testid="wolai-search-result-meta"></div>' +
'<div class="wolai-search-results" data-testid="wolai-search-results" data-search-results-owner="rust-kernel"></div>' +
'</div>';
document.body.appendChild(overlay);
var input = overlay.querySelector('[data-testid="wolai-search-input"]');
var closeButton = overlay.querySelector('[data-testid="wolai-search-close"]');
applySearchSwitchState(overlay, { knowledge: true, collapseSource: readSearchCollapseSourcesDefault() });
var initialKnowledgeModeSelect = overlay.querySelector('[data-search-knowledge-mode]');
if (initialKnowledgeModeSelect && 'value' in initialKnowledgeModeSelect) initialKnowledgeModeSelect.value = 'exact';
if (input) input.addEventListener('input', function() {
searchUiState.hasRendered = false;
scheduleSearchResultsRender();
});
overlay.querySelectorAll('[data-search-switch]').forEach(function(button) {
button.addEventListener('click', function() {
var switchName = searchText(button.getAttribute('data-search-switch'));
var isOn = button.getAttribute('aria-checked') !== 'true';
button.setAttribute('aria-checked', isOn ? 'true' : 'false');
button.classList.toggle('is-on', isOn);
if (switchName === 'collapseSource') {
writeSearchCollapseSourcesDefault(isOn);
searchUiState.sourceCollapsed = {};
}
searchUiState.hasRendered = false;
scheduleSearchResultsRender();
});
});
var knowledgeModeSelect = overlay.querySelector('[data-search-knowledge-mode]');
if (knowledgeModeSelect) {
knowledgeModeSelect.addEventListener('change', function() {
searchUiState.hasRendered = false;
scheduleSearchResultsRender();
});
}
if (closeButton) closeButton.addEventListener('click', closeSearchModal);
overlay.addEventListener('click', function(event) {
if (event.target === overlay) closeSearchModal();
});
return overlay;
}
var activeSearchRequestId = 0;
var searchRenderTimer = 0;
var SEARCH_COLLAPSE_SOURCES_KEY = 'mnote.search.collapseSourcesDefault.v1';
var searchUiState = {
query: '',
switches: {},
metaHtml: '',
resultsHtml: '',
items: [],
knowledgeMode: 'exact',
sourceCollapsed: {},
scrollTop: 0,
signature: '',
hasRendered: false
};
function searchText(value) {
return String(value == null ? '' : value).replace(/\s+/g, ' ').trim();
}
function searchNonWhitespaceCharCount(value) {
return String(value == null ? '' : value).replace(/\s+/g, '').length;
}
function currentWorkspaceName() {
var name = document.querySelector('.sidebar-workspace-name');
return searchText(name && name.textContent) || '当前工作区';
}
function currentDocumentId() {
var shell = document.querySelector('.document-shell[data-document-id]');
var bodyId = document.body && document.body.getAttribute('data-document-id');
return searchText(shell && shell.getAttribute('data-document-id')) || searchText(bodyId);
}
function localResourceDocumentIdFromPath(path) {
var normalized = searchText(path).replace(/\\/g, '/');
return normalized ? 'local-resource:' + normalized.replace(/\//g, '~2F') : '';
}
function currentSearchDocumentId() {
var activePanel = document.querySelector('[data-mnote-resource-tab-panel][data-pane-role="primary"]:not([hidden])');
if (activePanel instanceof HTMLElement) {
var resourceKind = searchText(activePanel.getAttribute('data-resource-kind')).toLowerCase();
var resourcePath = searchText(activePanel.getAttribute('data-resource-path'));
if (resourceKind && resourceKind !== 'markdown' && resourcePath) return localResourceDocumentIdFromPath(resourcePath);
try {
var locator = JSON.parse(activePanel.getAttribute('data-mnote-evidence-locator') || 'null');
var locatorDoc = searchText(locator && (locator.ownerDocumentId || locator.owner_document_id));
if (locatorDoc) return locatorDoc;
} catch (_) {}
}
return currentDocumentId();
}
function searchSwitchValue(overlay, name) {
var button = overlay.querySelector('[data-search-switch="' + name + '"]');
return button instanceof HTMLElement && button.getAttribute('aria-checked') === 'true';
}
function searchKnowledgeModeValue(overlay) {
var select = overlay.querySelector('[data-search-knowledge-mode]');
var value = select && 'value' in select ? searchText(select.value).toLowerCase() : '';
if (['mix', 'hybrid', 'naive', 'local', 'global', 'exact'].indexOf(value) >= 0) return value;
return 'mix';
}
function knowledgeSearchRequestMode(overlay) {
if (searchSwitchValue(overlay, 'exact')) return 'exact';
return searchKnowledgeModeValue(overlay);
}
function knowledgeSearchModeLabel(mode) {
if (mode === 'exact') return '关键词';
if (mode === 'naive') return '向量';
if (mode === 'local') return '实体';
if (mode === 'global') return '关系';
if (mode === 'hybrid') return '图谱混合';
return '综合';
}
function readSearchCollapseSourcesDefault() {
try {
var stored = window.localStorage && window.localStorage.getItem(SEARCH_COLLAPSE_SOURCES_KEY);
if (stored === '0') return false;
if (stored === '1') return true;
} catch (_) {}
return true;
}
function writeSearchCollapseSourcesDefault(value) {
try {
if (window.localStorage) window.localStorage.setItem(SEARCH_COLLAPSE_SOURCES_KEY, value ? '1' : '0');
} catch (_) {}
}
function collectSearchSwitchState(overlay) {
var state = {};
if (!(overlay instanceof HTMLElement)) return state;
overlay.querySelectorAll('[data-search-switch]').forEach(function(button) {
if (!(button instanceof HTMLElement)) return;
var name = searchText(button.getAttribute('data-search-switch'));
if (!name) return;
state[name] = button.getAttribute('aria-checked') === 'true';
});
return state;
}
function applySearchSwitchState(overlay, switches) {
if (!(overlay instanceof HTMLElement) || !switches || typeof switches !== 'object') return;
overlay.querySelectorAll('[data-search-switch]').forEach(function(button) {
if (!(button instanceof HTMLElement)) return;
var name = searchText(button.getAttribute('data-search-switch'));
if (!name || !Object.prototype.hasOwnProperty.call(switches, name)) return;
var isOn = Boolean(switches[name]);
button.setAttribute('aria-checked', isOn ? 'true' : 'false');
button.classList.toggle('is-on', isOn);
});
}
function searchRequestSignature(overlay, query) {
var switches = collectSearchSwitchState(overlay);
return JSON.stringify({
query: searchText(query),
knowledge: Boolean(switches.knowledge),
page: Boolean(switches.page),
title: Boolean(switches.title),
exact: Boolean(switches.exact),
collapseSource: Boolean(switches.collapseSource),
knowledgeMode: searchKnowledgeModeValue(overlay),
workspaceId: resolveWorkspaceId(document.body) || '',
rootUri: currentRootUri() || ''
});
}
function saveSearchUiState(overlay) {
if (!(overlay instanceof HTMLElement)) return;
var input = overlay.querySelector('[data-testid="wolai-search-input"]');
var meta = overlay.querySelector('[data-testid="wolai-search-result-meta"]');
var results = overlay.querySelector('[data-testid="wolai-search-results"]');
var query = input && 'value' in input ? searchText(input.value) : searchUiState.query;
searchUiState.query = query;
searchUiState.switches = collectSearchSwitchState(overlay);
searchUiState.knowledgeMode = searchKnowledgeModeValue(overlay);
searchUiState.metaHtml = meta ? meta.innerHTML : searchUiState.metaHtml;
searchUiState.resultsHtml = results ? results.innerHTML : searchUiState.resultsHtml;
searchUiState.items = Array.isArray(window.__mnoteSearchResults) ? window.__mnoteSearchResults.slice() : searchUiState.items;
searchUiState.scrollTop = results instanceof HTMLElement ? results.scrollTop : searchUiState.scrollTop;
searchUiState.signature = query ? searchRequestSignature(overlay, query) : '';
}
function restoreSearchUiState(overlay) {
if (!(overlay instanceof HTMLElement) || !searchUiState.hasRendered) return false;
var input = overlay.querySelector('[data-testid="wolai-search-input"]');
var options = overlay.querySelector('[data-testid="wolai-search-options"]');
var meta = overlay.querySelector('[data-testid="wolai-search-result-meta"]');
var results = overlay.querySelector('[data-testid="wolai-search-results"]');
if (input && 'value' in input) input.value = searchUiState.query || '';
applySearchSwitchState(overlay, searchUiState.switches);
var knowledgeModeSelect = overlay.querySelector('[data-search-knowledge-mode]');
if (knowledgeModeSelect && 'value' in knowledgeModeSelect) knowledgeModeSelect.value = searchUiState.knowledgeMode || 'exact';
if (options instanceof HTMLElement) options.hidden = !searchText(searchUiState.query);
if (meta && searchUiState.metaHtml) meta.innerHTML = searchUiState.metaHtml;
if (results && searchUiState.resultsHtml) {
results.innerHTML = searchUiState.resultsHtml;
results.scrollTop = Number(searchUiState.scrollTop || 0);
}
window.__mnoteSearchResults = Array.isArray(searchUiState.items) ? searchUiState.items.slice() : [];
return true;
}
function searchHighlightTerms(item, query) {
var info = item && item.matchInfo || item && item.evidence && item.evidence.matchInfo || null;
var terms = info && Array.isArray(info.matchedTerms) ? info.matchedTerms : [];
terms = terms.map(searchText).filter(Boolean);
if (!terms.length) {
terms = searchText(query).split(/[\s,;:,;:。、()[\]{}]+/).map(searchText).filter(Boolean);
}
terms.sort(function(left, right) { return right.length - left.length; });
return terms.filter(function(term, index) { return terms.indexOf(term) === index; });
}
function highlightSearchText(value, query, exact, terms) {
var text = searchText(value);
var cleanQuery = searchText(query);
if (!text || !cleanQuery) return escapeHtml(text);
var lower = text.toLowerCase();
var lowerQuery = cleanQuery.toLowerCase();
var exactIndex = lower.indexOf(lowerQuery);
if (exact || exactIndex >= 0) {
if (exactIndex < 0) return escapeHtml(text);
return escapeHtml(text.slice(0, exactIndex)) +
'<mark>' + escapeHtml(text.slice(exactIndex, exactIndex + cleanQuery.length)) + '</mark>' +
escapeHtml(text.slice(exactIndex + cleanQuery.length));
}
terms = Array.isArray(terms) ? terms.map(searchText).filter(Boolean) : [];
if (!terms.length) return escapeHtml(text);
var ranges = [];
terms.forEach(function(term) {
var lowerTerm = term.toLowerCase();
var start = lower.indexOf(lowerTerm);
while (start >= 0) {
var end = start + lowerTerm.length;
var overlaps = ranges.some(function(range) { return start < range.end && end > range.start; });
if (!overlaps) ranges.push({ start: start, end: end });
start = lower.indexOf(lowerTerm, end);
}
});
if (!ranges.length) return escapeHtml(text);
ranges.sort(function(left, right) { return left.start - right.start; });
var html = '';
var cursor = 0;
ranges.forEach(function(range) {
if (range.start > cursor) html += escapeHtml(text.slice(cursor, range.start));
html += '<mark>' + escapeHtml(text.slice(range.start, range.end)) + '</mark>';
cursor = range.end;
});
if (cursor < text.length) html += escapeHtml(text.slice(cursor));
return html;
}
function cleanSearchDisplayText(value) {
var text = String(value == null ? '' : value);
text = text.replace(/<drawing\b[^>]*\/?>/gi, ' ');
text = text.replace(/<equation\b[^>]*>([\s\S]*?)<\/equation>/gi, '$1');
text = text.replace(/<drawing\b[^<>]*$/gi, ' ');
text = text.replace(/<\/?equat[^<>]*$/gi, ' ');
text = text.replace(/<\/?e(?:q(?:uation)?)?[^<>]*$/gi, ' ');
text = text.replace(/<[^>]+>/g, ' ');
text = text
.replace(/\b(?:equation|latex|drawing)\b(?:\s+[a-z_-]+=(?:"[^"]*"|'[^']*'|[^\s<>]+))*/gi, ' ')
.replace(/\\left|\\right|\\mathrm|\\text|\\operatorname/g, '')
.replace(/\\gt/g, '>')
.replace(/\\lt/g, '<')
.replace(/\\sim/g, '')
.replace(/\\[a-zA-Z]+/g, ' ')
.replace(/\{([^{}]*)\}/g, '$1')
.replace(/\{([^{}]*)\}/g, '$1')
.replace(/[_^]/g, '')
.replace(/[<>]\/?(?:equation|eq)\b[^<>]*>?/gi, ' ')
.replace(/<\/?e(?:q(?:uation)?)?[^<>\s]*>?/gi, ' ')
.replace(/\s+(?:equation|latex|drawing)\s+/gi, ' ');
return searchText(text);
}
function searchResultEvidenceLocator(item) {
if (item && item.locator && typeof item.locator === 'object') return item.locator;
if (item && item.evidence && item.evidence.source && typeof item.evidence.source === 'object') return item.evidence.source;
if (item && item.source && item.source.locator && typeof item.source.locator === 'object') return item.source.locator;
if (item && Array.isArray(item.evidence) && item.evidence[0] && item.evidence[0].source && typeof item.evidence[0].source === 'object') return item.evidence[0].source;
return null;
}
function searchResultSourceKey(item) {
var locator = searchResultEvidenceLocator(item);
var locatorPath = locator ? searchText(locator.resourcePath || locator.resource_path || locator.ownerDocumentPath || locator.owner_document_path) : '';
return locatorPath || searchText(item && (item.path || item.documentId || item.nodeId || item.id)) || 'unknown-source';
}
function searchResultSourceTitle(item) {
var key = searchResultSourceKey(item);
var locator = searchResultEvidenceLocator(item);
var path = locator ? searchText(locator.resourcePath || locator.resource_path || locator.ownerDocumentPath || locator.owner_document_path) : '';
var sourcePath = path || searchText(item && item.path) || key;
var title = searchText(item && (item.title || item.name || item.documentTitle));
return title || sourcePath.split('/').filter(Boolean).pop() || sourcePath || '未知来源';
}
function renderSearchResultButton(item, index, query, exact, grouped) {
var title = searchText(item.title || item.name || item.documentTitle || '无标题');
var snippet = searchText(item.displayQuote || item.snippet || item.evidence && item.evidence.displayQuote || item.evidence && item.evidence.quote || (Array.isArray(item.evidence) && item.evidence[0] && (item.evidence[0].displayQuote || item.evidence[0].quote || item.evidence[0].snippet)) || '');
if (!item.displayQuote) snippet = cleanSearchDisplayText(snippet);
var path = searchText(item.path || item.parentTitle || item.workspaceName || currentWorkspaceName());
var resourceType = searchText(item.resourceType || item.resourceKind || 'page');
var locator = searchResultEvidenceLocator(item);
var locatorAttr = locator ? escapeHtml(JSON.stringify(locator)) : '';
var highlightTerms = searchHighlightTerms(item, query);
var titleHtml = grouped && snippet ? '' : '<span class="wolai-search-result-title">' + highlightSearchText(title, query, exact, highlightTerms) + '</span>';
var page = locator && locator.page != null && locator.page !== '' ? String(locator.page) : '';
var metaParts = grouped ? [] : [escapeHtml(path)];
if (page) metaParts.push('第 ' + escapeHtml(page) + ' 页');
if (!grouped) metaParts.push('<span class="wolai-search-result-type">' + escapeHtml(resourceType) + '</span>');
var metaHtml = metaParts.length ? '<span class="wolai-search-result-path"><span>' + metaParts.join('</span><span>') + '</span></span>' : '';
return '<button type="button" class="wolai-search-result-row" data-testid="wolai-search-result-row" data-search-result-owner="' + escapeHtml(item.provider || 'rust-kernel') + '" data-search-result-index="' + String(index) + '" data-document-id="' + escapeHtml(item.documentId || item.nodeId || item.id || '') + '" data-resource-type="' + escapeHtml(resourceType) + '"' + (locatorAttr ? ' data-evidence-locator="' + locatorAttr + '"' : '') + '>' +
'<span class="material-symbols-outlined wolai-search-result-icon" data-icon="article" aria-hidden="true"></span>' +
'<span class="wolai-search-result-main">' + titleHtml +
'<span class="wolai-search-result-snippet">' + (snippet ? highlightSearchText(snippet, query, exact, highlightTerms) : escapeHtml(path)) + '</span>' +
metaHtml + '</span>' +
'</button>';
}
function renderSearchResultsHtml(items, overlay, query) {
var exact = searchSwitchValue(overlay, 'exact');
if (!searchSwitchValue(overlay, 'collapseSource')) {
return items.map(function(item, index) {
return renderSearchResultButton(item, index, query, exact, false);
}).join('');
}
var groups = [];
var groupByKey = {};
items.forEach(function(item, index) {
var key = searchResultSourceKey(item);
var group = groupByKey[key];
if (!group) {
group = { key: key, title: searchResultSourceTitle(item), path: searchText(item.path || key), resourceType: searchText(item.resourceType || item.resourceKind || 'page'), rows: [] };
groupByKey[key] = group;
groups.push(group);
}
group.rows.push({ item: item, index: index });
});
return groups.map(function(group) {
var collapsed = Object.prototype.hasOwnProperty.call(searchUiState.sourceCollapsed, group.key)
? searchUiState.sourceCollapsed[group.key]
: true;
var children = group.rows.map(function(row) {
return renderSearchResultButton(row.item, row.index, query, exact, true);
}).join('');
return '<section class="wolai-search-source-group" data-search-source-key="' + escapeHtml(group.key) + '">' +
'<button type="button" class="wolai-search-source-header" data-search-source-toggle="true" aria-expanded="' + (collapsed ? 'false' : 'true') + '">' +
'<span class="material-symbols-outlined wolai-search-result-icon" data-icon="article" aria-hidden="true"></span>' +
'<span class="wolai-search-source-main"><span class="wolai-search-result-title">' + escapeHtml(group.title) + '</span>' +
'<span class="wolai-search-result-path"><span class="wolai-search-result-type">' + escapeHtml(group.resourceType) + '</span><span>' + String(group.rows.length) + ' 处</span></span></span>' +
'<span class="wolai-search-source-chevron" aria-hidden="true">' + (collapsed ? '展开' : '收起') + '</span>' +
'</button>' +
'<div class="wolai-search-source-results" data-search-source-results="true"' + (collapsed ? ' hidden' : '') + '>' + children + '</div>' +
'</section>';
}).join('');
}
function evidenceLocatorResourceKind(locator, fallback) {
return searchText(locator && (locator.resourceKind || locator.resource_kind) || fallback || '').toLowerCase();
}
function evidenceLocatorBbox(locator) {
var bbox = locator && locator.bbox;
if (Array.isArray(bbox)) return bbox.slice(0, 4).join(',');
if (bbox && typeof bbox === 'object') return [bbox.x0, bbox.y0, bbox.x1, bbox.y1].join(',');
return '';
}
function evidenceLocatorOpenUrl(locator) {
var action = locator && locator.openAction && typeof locator.openAction === 'object' ? locator.openAction : null;
return searchText(action && action.url);
}
function evidenceLocatorLineRange(locator) {
return locator && (locator.lineRange || locator.line_range) || null;
}
function evidenceLocatorCharRange(locator) {
return locator && (locator.charRange || locator.char_range) || null;
}
function evidenceLocatorBlockId(locator) {
return searchText(locator && (locator.blockId || locator.block_id));
}
function resourceHrefForEvidenceLocator(resourceKind, resourcePath, fileName, ownerDocumentId, locator) {
var localFileUrl = buildLocalFileOpenUrl(resourcePath, false);
if (!localFileUrl) return '';
if (resourceKind === 'pdf') return buildPdfPreviewOpenUrl(localFileUrl, fileName);
if (resourceKind === 'office') {
var fileType = inferOnlyOfficeFileType(fileName, '') || (fileName.indexOf('.') >= 0 ? fileName.split('.').pop() : 'docx');
return buildOfficePreviewOpenUrl({
fileUrl: localFileUrl,
fileName: fileName,
fileType: fileType,
assetId: 'local-file:' + resourcePath,
documentId: ownerDocumentId || currentDocumentId() || '',
workspaceId: resolveWorkspaceId(document.body) || '',
sourceKind: currentSourceKind() || 'local_folder',
rootUri: searchText(locator && (locator.rootUri || locator.root_uri) || currentRootUri())
});
}
return localFileUrl;
}
async function openEvidenceSearchResult(item, event) {
var locator = searchResultEvidenceLocator(item);
if (!locator) {
var citationUrl = searchText(item && (item.citationUrl || item.publicPath));
if (citationUrl) {
closeSearchModal();
window.location.assign(citationUrl);
return;
}
var fallbackId = searchText(item && (item.documentId || item.nodeId || item.id));
if (fallbackId) window.location.assign('/documents/' + encodeURIComponent(fallbackId));
return;
}
var resourcePath = searchText(locator.resourcePath || locator.resource_path || locator.ownerDocumentPath || locator.owner_document_path);
var ownerDocumentId = searchText(locator.ownerDocumentId || locator.owner_document_id || item.documentId || '');
var resourceKind = evidenceLocatorResourceKind(locator, item && item.resourceType);
var overlay = document.querySelector('[data-testid="wolai-search-modal"]');
var searchInput = overlay instanceof HTMLElement ? overlay.querySelector('[data-testid="wolai-search-input"]') : null;
var searchQueryText = searchText(item && (item.searchQuery || item.query) || locator && locator.openAction && locator.openAction.params && locator.openAction.params.searchQuery)
|| searchText(searchInput && 'value' in searchInput ? searchInput.value : '')
|| searchText(searchUiState.query);
var locatorEvidenceText = searchText(item && item.locatorEvidenceText || locator.evidenceText || locator.query || locator.openAction && locator.openAction.params && (locator.openAction.params.evidenceText || locator.openAction.params.query) || '');
var locatorParams = locator && locator.openAction && locator.openAction.params && typeof locator.openAction.params === 'object' ? locator.openAction.params : {};
var openTarget = event && event.altKey ? 'side' : 'active-tab';
if (resourcePath && resourceKind) {
var fileName = resourcePath.split('/').filter(Boolean).pop() || resourcePath;
var normalizedKind = resourceKind === 'raw_file' || resourceKind === 'resource' ? fileTreeIconKindForFileName(fileName) || 'file' : resourceKind;
var hostDocumentId = currentDocumentId() || ownerDocumentId || '';
var href = resourceHrefForEvidenceLocator(normalizedKind, resourcePath, fileName, hostDocumentId, locator);
var openedInResourceTab = await openLocalResourceInActiveTab({
path: resourcePath,
title: fileName,
kind: normalizedKind,
href: href,
officeUrl: normalizedKind === 'office' ? href : '',
assetId: 'local-file:' + resourcePath,
documentId: hostDocumentId,
ownerDocumentId: ownerDocumentId || hostDocumentId,
workspaceId: resolveWorkspaceId(document.body) || '',
sourceKind: currentSourceKind() || 'local_folder',
rootUri: searchText(locator.rootUri || locator.root_uri || currentRootUri()),
paneRole: openTarget === 'side' ? 'secondary' : 'primary',
evidenceLocator: locator,
page: locator.page,
bbox: locator.bbox,
sourceMapPath: searchText(locator.sourceMapPath || locator.source_map_path),
blockId: evidenceLocatorBlockId(locator),
paragraphOrdinal: searchText(locator.paragraphOrdinal || locatorParams.paragraphOrdinal),
paraIdStart: searchText(locator.paraIdStart || locatorParams.paraIdStart),
paraIdEnd: searchText(locator.paraIdEnd || locatorParams.paraIdEnd),
textFingerprint: searchText(locator.textFingerprint || locatorParams.textFingerprint),
evidenceText: locatorEvidenceText,
query: searchQueryText,
searchQuery: searchQueryText,
lineRange: evidenceLocatorLineRange(locator),
charRange: evidenceLocatorCharRange(locator)
});
if (!openedInResourceTab) console.warn('mnote evidence 搜索结果无法在当前页面资源标签打开', locator);
closeSearchModal();
return;
}
var url = evidenceLocatorOpenUrl(locator) || ('/documents/' + encodeURIComponent(ownerDocumentId || currentDocumentId() || ''));
try {
var target = new URL(url, window.location.origin);
var blockId = searchText(locator.blockId || locator.block_id);
var sourceMapPath = searchText(locator.sourceMapPath || locator.source_map_path);
if (blockId) target.searchParams.set('blockId', blockId);
if (locator.page) target.searchParams.set('page', String(locator.page));
var bbox = evidenceLocatorBbox(locator);
if (bbox) target.searchParams.set('bbox', bbox);
if (sourceMapPath) target.searchParams.set('sourceMapPath', sourceMapPath);
if (locatorParams.paragraphOrdinal != null) target.searchParams.set('paragraphOrdinal', searchText(locatorParams.paragraphOrdinal));
if (locatorParams.paraIdStart) target.searchParams.set('paraIdStart', searchText(locatorParams.paraIdStart));
if (locatorParams.paraIdEnd) target.searchParams.set('paraIdEnd', searchText(locatorParams.paraIdEnd));
if (locatorParams.textFingerprint) target.searchParams.set('textFingerprint', searchText(locatorParams.textFingerprint));
window.location.assign(target.pathname + target.search + target.hash);
} catch (_) {
window.location.assign(url);
}
}
function renderSearchRecentState(overlay) {
var options = overlay.querySelector('[data-testid="wolai-search-options"]');
var meta = overlay.querySelector('[data-testid="wolai-search-result-meta"]');
var results = overlay.querySelector('[data-testid="wolai-search-results"]');
if (options instanceof HTMLElement) options.hidden = true;
if (meta) meta.innerHTML = '<span>最近浏览</span><span>Ctrl + Enter 新窗口打开 / Alt + Enter 右侧边栏打开</span>';
if (results) {
results.innerHTML = '<div class="wolai-search-recent" data-testid="wolai-search-recent">暂无最近浏览</div>';
}
saveSearchUiState(overlay);
searchUiState.hasRendered = true;
}
function scheduleSearchResultsRender() {
window.clearTimeout(searchRenderTimer);
searchRenderTimer = window.setTimeout(function() { void renderSearchResults(); }, 120);
}
async function renderSearchResults() {
var overlay = document.querySelector('[data-testid="wolai-search-modal"]');
if (!(overlay instanceof HTMLElement)) return;
var input = overlay.querySelector('[data-testid="wolai-search-input"]');
var options = overlay.querySelector('[data-testid="wolai-search-options"]');
var meta = overlay.querySelector('[data-testid="wolai-search-result-meta"]');
var results = overlay.querySelector('[data-testid="wolai-search-results"]');
if (!input || !meta || !results) return;
var query = searchText(input.value);
if (!query) {
activeSearchRequestId += 1;
renderSearchRecentState(overlay);
return;
}
if (options instanceof HTMLElement) options.hidden = false;
var knowledgeMode = searchSwitchValue(overlay, 'knowledge');
if (knowledgeMode && searchNonWhitespaceCharCount(query) < 2) {
activeSearchRequestId += 1;
meta.innerHTML = '<span>资料库检索</span><span>请输入至少 2 个字再搜索</span>';
results.innerHTML = '<div class="wolai-search-empty" data-search-empty="true">请输入至少 2 个字再搜索</div>';
window.__mnoteSearchResults = [];
saveSearchUiState(overlay);
searchUiState.hasRendered = true;
return;
}
var requestId = ++activeSearchRequestId;
var knowledgeRequestMode = knowledgeMode ? knowledgeSearchRequestMode(overlay) : '';
meta.innerHTML = '<span>搜索中…</span><span>Ctrl + Enter 新窗口打开 / Alt + Enter 右侧边栏打开</span>';
results.innerHTML = '<div class="wolai-search-empty" data-search-loading="true">搜索中…</div>';
try {
var response = await fetch(knowledgeMode ? '/api/knowledge-rag/search' : '/api/search/documents', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(knowledgeMode ? {
workspaceId: resolveWorkspaceId(document.body),
rootUri: currentRootUri() || null,
query: query,
mode: knowledgeRequestMode,
topK: 12,
chunkTopK: 24,
includeChunkContent: true
} : {
workspaceId: resolveWorkspaceId(document.body),
sourceKind: currentSourceKind() || null,
rootUri: currentRootUri() || null,
documentId: searchSwitchValue(overlay, 'page') ? (currentSearchDocumentId() || null) : (currentDocumentId() || null),
query: query,
limit: 30,
filters: {
titleOnly: searchSwitchValue(overlay, 'title'),
exact: searchSwitchValue(overlay, 'exact'),
includeOcr: false,
onlyCurrentPage: searchSwitchValue(overlay, 'page'),
timeRange: 'any',
timeField: 'updated'
}
})
});
var payload = await response.json();
if (requestId !== activeSearchRequestId) return;
var items = Array.isArray(payload.results) ? payload.results : [];
var ownerLabel = knowledgeMode ? ('资料库检索 · ' + knowledgeSearchModeLabel(payload.retrievalMode || knowledgeRequestMode)) : '工作区搜索';
meta.innerHTML = '<span>' + ownerLabel + ' · 共 ' + items.length + ' 条匹配结果</span><span>Ctrl + Enter 新窗口打开 / Alt + Enter 右侧边栏打开</span>';
if (!items.length) {
results.innerHTML = '<div class="wolai-search-empty" data-search-empty="true">没有搜索结果</div>';
window.__mnoteSearchResults = [];
saveSearchUiState(overlay);
searchUiState.hasRendered = true;
return;
}
window.__mnoteSearchResults = items;
results.innerHTML = renderSearchResultsHtml(items, overlay, query);
saveSearchUiState(overlay);
searchUiState.hasRendered = true;
} catch (error) {
if (requestId !== activeSearchRequestId) return;
meta.innerHTML = '<span>共 0 条匹配结果</span><span>Ctrl + Enter 新窗口打开 / Alt + Enter 右侧边栏打开</span>';
results.innerHTML = '<div class="wolai-search-empty" data-search-empty="true">没有搜索结果</div>';
window.__mnoteSearchResults = [];
saveSearchUiState(overlay);
searchUiState.hasRendered = true;
}
}
function isSearchModalOpen() {
var overlay = document.querySelector('[data-testid="wolai-search-modal"]');
return overlay instanceof HTMLElement && !overlay.hidden;
}
function openSearchModal() {
var overlay = ensureSearchModal();
overlay.hidden = false;
document.documentElement.setAttribute('data-mnote-search-modal-open', 'true');
var restored = restoreSearchUiState(overlay);
var input = overlay.querySelector('[data-testid="wolai-search-input"]');
if (input) input.setAttribute('placeholder', '在 ' + currentWorkspaceName() + ' 中搜索');
var query = input && 'value' in input ? searchText(input.value) : '';
var signature = query ? searchRequestSignature(overlay, query) : '';
if (!restored || signature !== searchUiState.signature) void renderSearchResults();
if (input) {
setTimeout(function() { input.focus(); input.select(); }, 0);
}
}
function closeSearchModal() {
var overlay = document.querySelector('[data-testid="wolai-search-modal"]');
if (overlay instanceof HTMLElement) {
saveSearchUiState(overlay);
overlay.hidden = true;
}
document.documentElement.removeAttribute('data-mnote-search-modal-open');
}
function toggleSearchModal() {
if (isSearchModalOpen()) closeSearchModal();
else openSearchModal();
}
function isSearchShortcutEvent(event) {
return Boolean(event && (event.metaKey || event.ctrlKey) && !event.shiftKey && !event.altKey && event.key && event.key.toLowerCase() === 'p');
}
document.addEventListener('keydown', function(event) {
if (!isSearchShortcutEvent(event)) return;
event.preventDefault();
event.stopPropagation();
openSearchModal();
}, true);
const sidebarPageAi = createSidebarPageAiRuntime({
buildLocalFileOpenUrl,
currentDocumentId,
currentPageAggregate,
currentPageOptions,
currentRootUri,
currentSourceKind,
escapeHtml,
cssEscape,
openLocalResourceInActiveTab,
pageUiState,
resolveWorkspaceId,
searchText,
});
const openPageAiDrawer = (...args) => sidebarPageAi.openPageAiDrawer(...args);
const closePageAiDrawer = (...args) => sidebarPageAi.closePageAiDrawer(...args);
const isPageAiDrawerOpen = (...args) => sidebarPageAi.isPageAiDrawerOpen(...args);
const ensurePageAiDrawer = (...args) => sidebarPageAi.ensurePageAiDrawer(...args);
const sendPageAiMessage = (...args) => sidebarPageAi.sendPageAiMessage(...args);
const pageAiOpenHermesSettings = (...args) => sidebarPageAi.pageAiOpenHermesSettings(...args);
const pageAiStopRun = (...args) => sidebarPageAi.pageAiStopRun(...args);
const pageAiLoadGatewayHealth = (...args) => sidebarPageAi.pageAiLoadGatewayHealth(...args);
const renderPageAiControls = (...args) => sidebarPageAi.renderPageAiControls(...args);
const renderPageAiConversation = (...args) => sidebarPageAi.renderPageAiConversation(...args);
const renderPageAiProviderButtons = (...args) => sidebarPageAi.renderPageAiProviderButtons(...args);
const renderPageAiSuggestions = (...args) => sidebarPageAi.renderPageAiSuggestions(...args);
const pageAiSaveProfileMemory = (...args) => sidebarPageAi.pageAiSaveProfileMemory(...args);
const pageAiToggleSkill = (...args) => sidebarPageAi.pageAiToggleSkill(...args);
const pageAiToggleTool = (...args) => sidebarPageAi.pageAiToggleTool(...args);
const pageAiResumeBackendSession = (...args) => sidebarPageAi.pageAiResumeBackendSession(...args);
const pageAiRenameBackendSession = (...args) => sidebarPageAi.pageAiRenameBackendSession(...args);
const pageAiDeleteBackendSession = (...args) => sidebarPageAi.pageAiDeleteBackendSession(...args);
const pageAiResolvePermission = (...args) => sidebarPageAi.pageAiResolvePermission(...args);
const pageAiOpenLocation = (...args) => sidebarPageAi.pageAiOpenLocation(...args);
const pageAiSetActiveSession = (...args) => sidebarPageAi.pageAiSetActiveSession(...args);
const pageAiStartNewSession = (...args) => sidebarPageAi.pageAiStartNewSession(...args);
const pageAiLoadSessions = (...args) => sidebarPageAi.pageAiLoadSessions(...args);
const pageAiLoadBackendSessions = (...args) => sidebarPageAi.pageAiLoadBackendSessions(...args);
const pageAiCancelQueuedRun = (...args) => sidebarPageAi.pageAiCancelQueuedRun(...args);
const pageAiSearchBackendSessions = (...args) => sidebarPageAi.pageAiSearchBackendSessions(...args);
const pageAiPersistSessions = (...args) => sidebarPageAi.pageAiPersistSessions(...args);
const pageAiLoadProfiles = (...args) => sidebarPageAi.pageAiLoadProfiles(...args);
const pageAiLoadProfileMemory = (...args) => sidebarPageAi.pageAiLoadProfileMemory(...args);
const pageAiLoadSkills = (...args) => sidebarPageAi.pageAiLoadSkills(...args);
const pageAiSwitchProfile = (...args) => sidebarPageAi.pageAiSwitchProfile(...args);
2026-06-01 09:29:12 +08:00
const pageAiSetSkillSource = (...args) => sidebarPageAi.pageAiSetSkillSource(...args);
const pageAiToggleSkillGroup = (...args) => sidebarPageAi.pageAiToggleSkillGroup(...args);
2026-06-01 09:29:12 +08:00
const pageAiSetReasonixMemoryEnabled = (...args) => sidebarPageAi.pageAiSetReasonixMemoryEnabled(...args);
const pageAiSetHideHermesBuiltinSkills = (...args) => sidebarPageAi.pageAiSetHideHermesBuiltinSkills(...args);
const pageAiSetContextScope = (...args) => sidebarPageAi.pageAiSetContextScope(...args);
const pageAiSetAgentId = (...args) => sidebarPageAi.pageAiSetAgentId(...args);
const pageAiToggleContextRef = (...args) => sidebarPageAi.pageAiToggleContextRef(...args);
const pageAiSetAgentPopoverOpen = (...args) => sidebarPageAi.pageAiSetAgentPopoverOpen(...args);
2026-06-01 09:29:12 +08:00
const pageAiSetTargetPopoverOpen = (...args) => sidebarPageAi.pageAiSetTargetPopoverOpen(...args);
const pageAiSelectTarget = (...args) => sidebarPageAi.pageAiSelectTarget(...args);
const updatePageAiTriggerState = (...args) => sidebarPageAi.updatePageAiTriggerState(...args);
const sidebarAttachmentOpen = createSidebarAttachmentOpenRuntime({
attachmentClassForFileName: (...args) => attachmentClassForFileName(...args),
buildLocalFileOpenUrl,
buildLocalOnlyOfficeOpenUrl,
buildOnlyOfficeOpenPath,
buildOnlyOfficeOpenUrl,
buildPdfPreviewOpenUrl,
closestAction,
currentDocumentId,
currentRootUri,
currentWorkspaceSourcePayload,
fileTreeIconKindForFileName,
2026-05-26 07:08:26 +08:00
healLegacyOfficeAttachmentParagraphs,
hydrateEditorAttachmentMeta,
inferCodeAttachmentLanguage: (...args) => inferCodeAttachmentLanguage(...args),
inferOnlyOfficeFileType,
isCodeAttachmentFileName: (...args) => isCodeAttachmentFileName(...args),
isPdfAttachmentFileName: (...args) => isPdfAttachmentFileName(...args),
localFilePathFromAssetId,
openLocalOfficeFileInActiveTab,
openLocalResourceInActiveTab,
openTreeContextMenu: (...args) => openTreeContextMenu(...args),
resolveWorkspaceId,
triggerBrowserDownload: (...args) => triggerBrowserDownload(...args),
uploadedFileSize,
});
const refreshEditorLocalAttachmentExistence = (...args) => sidebarAttachmentOpen.refreshEditorLocalAttachmentExistence(...args);
const detailFromEditorAttachmentLink = (...args) => sidebarAttachmentOpen.detailFromEditorAttachmentLink(...args);
const enhanceEditorAttachmentLink = (...args) => sidebarAttachmentOpen.enhanceEditorAttachmentLink(...args);
const enhanceEditorAttachmentLinks = (...args) => sidebarAttachmentOpen.enhanceEditorAttachmentLinks(...args);
const openEditorAttachmentDetail = (...args) => sidebarAttachmentOpen.openEditorAttachmentDetail(...args);
const openEditorAttachmentNewWindow = (...args) => sidebarAttachmentOpen.openEditorAttachmentNewWindow(...args);
const openEditorAttachmentEditTab = (...args) => sidebarAttachmentOpen.openEditorAttachmentEditTab(...args);
const openCodeEditorAttachment = (...args) => sidebarAttachmentOpen.openCodeEditorAttachment(...args);
const openEditorAttachmentDownload = (...args) => sidebarAttachmentOpen.openEditorAttachmentDownload(...args);
document.addEventListener('click', function(e) {
if (activeTreeContextMenu && activeTreeContextMenu.contains(e.target)) return;
if (activeTreeContextMenu) closeTreeContextMenu();
var sidebarToggle = closestAction(e.target, '[data-mnote-action="toggle-sidebar"]');
if (sidebarToggle) {
e.preventDefault();
toggleWorkspaceSidebar(sidebarToggle);
return;
}
var attachmentAction = closestAction(e.target, '[data-attachment-action]');
if (attachmentAction) {
e.preventDefault();
e.stopPropagation();
var link = activeEditorAttachmentLink;
if (!(link instanceof HTMLAnchorElement)) return;
var attachmentDetail = detailFromEditorAttachmentLink(link);
var attachmentActionName = attachmentAction.getAttribute('data-attachment-action') || '';
if (attachmentActionName === 'download') {
openEditorAttachmentDownload(attachmentDetail);
return;
}
if (attachmentActionName === 'menu') {
openEditorAttachmentMenu(link, attachmentAction);
return;
}
return;
}
2026-05-29 11:13:05 +08:00
var editorAttachmentLink = closestAction(e.target, '.editor-surface .ProseMirror a.mnote-uploaded-attachment-row');
if (editorAttachmentLink instanceof HTMLAnchorElement) {
e.preventDefault();
openEditorAttachmentLink(editorAttachmentLink);
return;
}
var historyClose = closestAction(e.target, '[data-page-history-action="close"]');
if (historyClose) {
e.preventDefault();
closePageHistoryDrawer();
return;
}
var shareClose = closestAction(e.target, '[data-page-share-action="close"]');
if (shareClose) {
e.preventDefault();
closePageShareDialog();
return;
}
var shareCopy = closestAction(e.target, '[data-page-share-action="copy-link"]');
if (shareCopy) {
e.preventDefault();
void copyTreeContextValue(window.location.href, 'page-share-link');
return;
}
var pageHistoryTrigger = closestAction(e.target, '[data-mnote-action="open-page-history"]');
if (pageHistoryTrigger) {
e.preventDefault();
openPageHistoryDrawer();
return;
}
var pageSettingsTrigger = closestAction(e.target, '[data-mnote-action="open-page-settings"]');
if (pageSettingsTrigger) {
e.preventDefault();
togglePageSettingsPopover();
return;
}
var indexSettingsTrigger = closestAction(e.target, '[data-mnote-action="open-index-settings"]');
if (indexSettingsTrigger) {
e.preventDefault();
openKnowledgeRagSettingsPopover();
return;
}
var knowledgeRagSettingsTrigger = closestAction(e.target, '[data-mnote-action="open-knowledge-rag-settings"]');
if (knowledgeRagSettingsTrigger) {
e.preventDefault();
openKnowledgeRagSettingsPopover();
return;
}
var settingsClose = closestAction(e.target, '[data-settings-action="close"]');
if (settingsClose) {
e.preventDefault();
closeAllSettingsPopovers();
return;
}
var pageSettingsPanel = closestAction(e.target, '.wolai-page-settings-panel');
if (isAnySettingsOpen() && !pageSettingsPanel) {
closeAllSettingsPopovers();
}
var pageSettingsTab = closestAction(e.target, '[data-page-settings-tab]');
if (pageSettingsTab) {
e.preventDefault();
setActivePageSettingsTab(pageSettingsTab.getAttribute('data-page-settings-tab') || 'page');
return;
}
var extensionsSubtab = closestAction(e.target, '[data-extensions-subtab]');
if (extensionsSubtab) {
e.preventDefault();
setActiveExtensionsSubtab(extensionsSubtab.getAttribute('data-extensions-subtab') || 'knowledge');
return;
}
var localIndexAction = closestAction(e.target, '[data-local-index-action]');
if (localIndexAction) {
e.preventDefault();
var localIndexActionName = localIndexAction.getAttribute('data-local-index-action') || '';
if (localIndexActionName === 'save') {
void persistLocalIndexSettings();
return;
}
if (localIndexActionName === 'refresh') {
void refreshLocalIndex();
return;
}
if (localIndexActionName === 'add-path') {
addLocalIndexRange();
return;
}
if (localIndexActionName === 'remove-path') {
removeLocalIndexRange(localIndexAction.getAttribute('data-local-index-path-index') || '0');
return;
}
}
var knowledgeRagAction = closestAction(e.target, '[data-knowledge-rag-action]');
if (knowledgeRagAction) {
e.preventDefault();
var knowledgeRagActionName = knowledgeRagAction.getAttribute('data-knowledge-rag-action') || '';
if (knowledgeRagActionName === 'manage') {
void openKnowledgeRagSettingsPopover();
return;
}
if (knowledgeRagActionName === 'refresh-status') {
void refreshKnowledgeExtensionsPanel();
return;
}
if (knowledgeRagActionName === 'refresh') {
void loadKnowledgeRagStatus(true);
return;
}
2026-06-26 20:01:02 +08:00
if (knowledgeRagActionName === 'create-kb') {
void createKnowledgeRagKnowledgeBase();
return;
}
if (knowledgeRagActionName === 'focus-create-kb') {
var createKbInput = document.querySelector('[data-knowledge-rag-create-kb-name]');
if (createKbInput instanceof HTMLInputElement) createKbInput.focus();
return;
}
if (knowledgeRagActionName === 'select-kb') {
setKnowledgeRagSelectedProviderKnowledgeBaseId(knowledgeRagAction.getAttribute('data-knowledge-rag-kb-id') || '');
return;
}
if (knowledgeRagActionName === 'add-source') {
addKnowledgeRagSourceInput();
return;
}
if (knowledgeRagActionName === 'remove-source') {
removeKnowledgeRagSourceInput(knowledgeRagAction);
return;
}
if (knowledgeRagActionName === 'use-filetree-selection') {
useKnowledgeRagFileTreeSelection();
return;
}
if (knowledgeRagActionName === 'ingest') {
void ingestKnowledgeRagSources();
return;
}
if (knowledgeRagActionName === 'reindex-source') {
void ingestSingleKnowledgeRagSource(knowledgeRagAction.getAttribute('data-knowledge-rag-source-path') || '');
return;
}
if (knowledgeRagActionName === 'delete-source') {
void deleteKnowledgeRagSource(knowledgeRagAction.getAttribute('data-knowledge-rag-source-path') || '');
return;
}
2026-06-26 20:01:02 +08:00
if (knowledgeRagActionName === 'open-source-reference') {
openKnowledgeRagSourceReference(knowledgeRagAction.getAttribute('data-knowledge-rag-source-path') || '');
return;
}
if (knowledgeRagActionName === 'prune') {
void pruneKnowledgeRagRegistry();
return;
}
if (knowledgeRagActionName === 'filter-sources') {
setKnowledgeRagSourceFilter(knowledgeRagAction.getAttribute('data-knowledge-rag-filter') || 'attention');
return;
}
if (knowledgeRagActionName === 'open-dashboard') {
openKnowledgeRagDashboard();
return;
}
}
var kbRagDetailTab = closestAction(e.target, '[data-kb-rag-tab]');
if (kbRagDetailTab) {
e.preventDefault();
var tabName = kbRagDetailTab.getAttribute('data-kb-rag-tab') || 'sources';
setActiveKnowledgeRagDetailTab(tabName);
if (tabName === 'params') loadKnowledgeRagSearchParamsToForm();
return;
}
var kbRagAction = closestAction(e.target, '[data-kb-rag-action]');
if (kbRagAction) {
e.preventDefault();
var kbRagActionName = kbRagAction.getAttribute('data-kb-rag-action') || '';
if (kbRagActionName === 'search') {
void performKnowledgeRagSearch();
return;
}
if (kbRagActionName === 'save-params') {
saveKnowledgeRagSearchParams();
return;
}
}
var kbRagSearchInput = closestAction(e.target, '[data-kb-rag-search-input]');
if (kbRagSearchInput && e.key === 'Enter') {
e.preventDefault();
void performKnowledgeRagSearch();
return;
}
var kbRagThresholdRange = closestAction(e.target, '[data-kb-rag-param="similarity_threshold"]');
if (kbRagThresholdRange && e.type === 'input') {
syncKnowledgeRagThresholdDisplay();
return;
}
var dashboardAction = closestAction(e.target, '[data-dashboard-action="refresh"]');
if (dashboardAction) {
e.preventDefault();
refreshDashboardPanel();
return;
}
var pageSettingsAction = closestAction(e.target, '[data-page-settings-action]');
if (pageSettingsAction) {
e.preventDefault();
var actionName = pageSettingsAction.getAttribute('data-page-settings-action') || '';
if (actionName === 'history') {
openPageHistoryDrawer();
return;
}
if (actionName === 'share') {
openPageShareDialog();
return;
}
return;
}
var pageAiTrigger = closestAction(e.target, '[data-mnote-action="open-page-ai"]');
if (pageAiTrigger) {
e.preventDefault();
openPageAiDrawer();
return;
}
var navigationPageTrigger = closestAction(e.target, '[data-mnote-action="open-navigation-page"]');
if (navigationPageTrigger) {
e.preventDefault();
openCurrentNavigationPage(navigationPageTrigger);
return;
}
var searchTrigger = closestAction(e.target, '[data-mnote-action="open-search-modal"]');
if (searchTrigger) {
e.preventDefault();
toggleSearchModal();
return;
}
var searchDialog = closestAction(e.target, '.wolai-search-dialog');
if (isSearchModalOpen() && !searchDialog) {
closeSearchModal();
return;
}
var searchSourceToggle = closestAction(e.target, '[data-search-source-toggle]');
if (searchSourceToggle) {
e.preventDefault();
var sourceGroup = searchSourceToggle.closest('.wolai-search-source-group');
var sourceResults = sourceGroup && sourceGroup.querySelector('[data-search-source-results="true"]');
var sourceKey = sourceGroup ? searchText(sourceGroup.getAttribute('data-search-source-key')) : '';
var nextCollapsed = !(sourceResults instanceof HTMLElement && sourceResults.hidden);
if (sourceResults instanceof HTMLElement) sourceResults.hidden = nextCollapsed;
searchSourceToggle.setAttribute('aria-expanded', nextCollapsed ? 'false' : 'true');
var chevron = searchSourceToggle.querySelector('.wolai-search-source-chevron');
if (chevron) chevron.textContent = nextCollapsed ? '展开' : '收起';
if (sourceKey) searchUiState.sourceCollapsed[sourceKey] = nextCollapsed;
var overlay = document.querySelector('[data-testid="wolai-search-modal"]');
if (overlay instanceof HTMLElement) saveSearchUiState(overlay);
return;
}
var searchResultRow = closestAction(e.target, '[data-testid="wolai-search-result-row"]');
if (searchResultRow) {
e.preventDefault();
var index = Number(searchResultRow.getAttribute('data-search-result-index') || -1);
var item = Array.isArray(window.__mnoteSearchResults) && index >= 0 ? window.__mnoteSearchResults[index] : null;
if (!item) {
var locatorPayload = searchResultRow.getAttribute('data-evidence-locator') || '';
try {
var locator = locatorPayload ? JSON.parse(locatorPayload) : null;
item = locator ? { evidence: { source: locator }, documentId: searchResultRow.getAttribute('data-document-id') || '' } : null;
} catch (_) {
item = null;
}
}
void openEvidenceSearchResult(item || { documentId: searchResultRow.getAttribute('data-document-id') || '' }, e)
.catch(function(error) { console.warn('mnote evidence 搜索结果打开失败', error); });
return;
}
var sourceMenuTrigger = closestAction(e.target, '[data-mnote-action="open-workspace-source-menu"]');
if (sourceMenuTrigger) {
e.preventDefault();
var existingSourceMenu = document.querySelector('[data-testid="mnote-workspace-source-menu"]');
if (existingSourceMenu) closeWorkspaceSourceMenu();
else openWorkspaceSourceMenu(sourceMenuTrigger);
return;
}
var sourceMenu = closestAction(e.target, '[data-testid="mnote-workspace-source-menu"]');
if (!sourceMenu) closeWorkspaceSourceMenu();
var accountMenuTrigger = closestAction(e.target, '[data-mnote-action="open-account-menu"]');
if (accountMenuTrigger) {
e.preventDefault();
var existingAccountMenu = document.querySelector('[data-testid="mnote-account-menu"]');
if (existingAccountMenu) closeAccountMenu();
else openAccountMenu(accountMenuTrigger);
return;
}
var accountMenu = closestAction(e.target, '[data-testid="mnote-account-menu"]');
if (!accountMenu) closeAccountMenu();
var trashTrigger = closestAction(e.target, '[data-mnote-action="open-trash-modal"]');
if (trashTrigger) {
e.preventDefault();
openTrashModal(trashTrigger);
return;
}
var trashClose = closestAction(e.target, '[data-mnote-trash-modal-close]');
if (trashClose) {
e.preventDefault();
closeTrashModal();
return;
}
var tabTrigger = closestAction(e.target, '[data-mnote-sidebar-tree-tab]');
if (tabTrigger) {
e.preventDefault();
switchSidebarTreeTab(tabTrigger);
return;
}
var pageShortcutTrigger = closestAction(e.target, '[data-mnote-action="toggle-sidebar-shortcut"]');
if (pageShortcutTrigger) {
e.preventDefault();
void toggleCurrentPageSidebarShortcut(pageShortcutTrigger);
return;
}
var shortcutMenu = closestAction(e.target, '[data-testid="mnote-sidebar-shortcut-menu"]');
var shortcutMenuAction = closestAction(e.target, '[data-mnote-sidebar-shortcut-menu-action]');
if (shortcutMenuAction) {
e.preventDefault();
var action = String(shortcutMenuAction.getAttribute('data-mnote-sidebar-shortcut-menu-action') || '').trim();
var shortcutRowFromMenu = shortcutMenu && shortcutMenu.__mnoteShortcutRow instanceof HTMLElement
? shortcutMenu.__mnoteShortcutRow
: null;
if (action === 'remove') {
void removeSidebarShortcutByRow(shortcutRowFromMenu);
return;
}
if (action === 'open') {
closeSidebarShortcutMenu();
if (shortcutRowFromMenu && shortcutRowFromMenu.getAttribute('data-mnote-shortcut-kind') === 'folder') {
void openStarredFolderShortcut(shortcutRowFromMenu);
} else if (shortcutRowFromMenu && shortcutRowFromMenu.getAttribute('href')) {
window.location.assign(shortcutRowFromMenu.getAttribute('href'));
}
return;
}
if (action === 'copy-link') {
var href = shortcutRowFromMenu && shortcutRowFromMenu.getAttribute('href') || window.location.href;
if (navigator.clipboard && href) void navigator.clipboard.writeText(new URL(href, window.location.origin).toString());
closeSidebarShortcutMenu();
return;
}
}
if (!shortcutMenu) closeSidebarShortcutMenu();
var shortcutMenuTrigger = closestAction(e.target, '.wolai-starred-section [data-mnote-shortcut-action="menu"]');
if (shortcutMenuTrigger) {
e.preventDefault();
var shortcutRow = shortcutMenuTrigger.closest('[data-mnote-shortcut-id]');
openSidebarShortcutMenu(shortcutRow, shortcutMenuTrigger);
return;
}
var folderShortcutRow = closestAction(e.target, '.wolai-starred-section [data-mnote-shortcut-kind="folder"]');
if (folderShortcutRow) {
e.preventDefault();
void openStarredFolderShortcut(folderShortcutRow);
return;
}
var localFolderTrigger = closestAction(e.target, '[data-mnote-action="open-local-folder"]');
if (localFolderTrigger) {
e.preventDefault();
requestOpenLocalFolder();
return;
}
var createLocalWorkspaceTrigger = closestAction(e.target, '[data-mnote-action="create-local-workspace"]');
if (createLocalWorkspaceTrigger) {
e.preventDefault();
void createDefaultLocalWorkspace(createLocalWorkspaceTrigger);
return;
}
var createTrigger = closestAction(e.target, '[data-mnote-action="create-page"]');
if (createTrigger) {
e.preventDefault();
void createPage(createTrigger, null);
return;
}
var createFolderTrigger = closestAction(e.target, '[data-mnote-action="create-folder"]');
if (createFolderTrigger) {
e.preventDefault();
if (currentSourceKind() !== 'local_folder') return;
var scope = currentFileTreeScope();
var parentId = scope ? 'local:folder:' + scope : null;
void createFileTreeFolder(createFolderTrigger, parentId);
return;
}
var fileTree = document.getElementById('sidebar-file-tree-root');
if (fileTree && fileTree.contains(e.target)) {
var fileBtn = closestAction(e.target, '[data-rust-action]');
var fileRow = closestAction(e.target, '.tree-row[data-shell-mode="filetree"]');
if (!fileRow) return;
var fileAction = fileBtn ? fileBtn.getAttribute('data-rust-action') : 'open';
var rowId = fileRow.getAttribute('data-row-id') || '';
var rowKind = fileRow.getAttribute('data-row-kind') || '';
var documentId = fileRow.getAttribute('data-document-id') || fileRow.getAttribute('data-doc-id') || '';
var ownerDocumentId = fileRow.getAttribute('data-owner-document-id') || documentId;
var assetId = fileRow.getAttribute('data-asset-id') || '';
var assetType = '';
var kindBadge = fileRow.querySelector('.tree-kind-badge');
if (kindBadge instanceof HTMLElement) {
assetType = kindBadge.getAttribute('data-kind') || '';
}
if (fileAction === 'toggle') {
e.preventDefault();
toggleChildren(fileRow, fileBtn);
return;
}
if (fileAction === 'create') {
e.preventDefault();
void createPage(fileBtn || fileRow, documentId || fileRow.getAttribute('data-node-id'));
return;
}
if (fileAction === 'menu') {
e.preventDefault();
if (rowId && !sidebarFileTreeSelection.selectedRowIds.has(rowId)) {
selectSidebarFileTreeRow(fileRow, { ctrlKey: false, metaKey: false, shiftKey: false });
}
var point = rowCenter(fileBtn || fileRow);
dispatchSidebarEvent('tree.filetree.context-menu', { rowId: rowId, rowKind: rowKind, documentId: documentId || null, assetId: assetId || null });
openFileTreeContextMenu(fileRow, point.x, point.y, fileBtn || fileRow);
return;
}
if (fileAction === 'open' && rowKind === 'folder') {
e.preventDefault();
selectSidebarFileTreeRow(fileRow, { ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey });
toggleChildren(fileRow, fileRow.querySelector('[data-rust-action="toggle"]'));
return;
}
e.preventDefault();
selectSidebarFileTreeRow(fileRow, { ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey });
var objectIdentity = readFileTreeObjectIdentity(fileRow);
var workspacePath = readWorkspacePathFromRow(fileRow);
var localRelativePath = fileTreeRowLocalRelativePath(fileRow) || String(workspacePath && (workspacePath.relativePath || workspacePath.localRelativePath) || '').trim();
dispatchSidebarEvent('tree.filetree.open', { rowId: rowId, rowKind: rowKind, documentId: ownerDocumentId || null, assetId: assetId || null, assetType: assetType || null, objectIdentity: objectIdentity, workspacePath: workspacePath, workspaceId: resolveWorkspaceId(fileRow) });
if (e.shiftKey || e.ctrlKey || e.metaKey) {
return;
}
2026-06-07 10:35:21 +08:00
if ((rowKind === 'document' || rowKind === 'index' || rowKind === 'markdown') && isRetiredOcrSidecarMarkdownPath(localRelativePath)) {
document.documentElement.setAttribute('data-mnote-retired-ocr-sidecar-filetree-open', 'resource-tab');
var retiredOcrSidecarResourceInput = {
path: localRelativePath,
title: fileTreeRowTitleForShortcut(fileRow, localRelativePath),
kind: 'markdown',
2026-06-07 10:35:21 +08:00
objectIdentity: 'retired-ocr-sidecar:' + localRelativePath,
assetId: 'retired-ocr-sidecar:' + localRelativePath,
documentId: documentId || ownerDocumentId || null,
workspaceId: resolveWorkspaceId(fileRow),
sourceKind: 'local_folder',
rootUri: currentRootUri(),
resourceKind: 'markdown',
workspacePath: workspacePath,
paneRole: 'primary'
};
if (typeof window.__mnoteDocumentPaneRuntime?.openResourceInActiveTab === 'function') {
2026-06-07 10:35:21 +08:00
void window.__mnoteDocumentPaneRuntime.openResourceInActiveTab(retiredOcrSidecarResourceInput);
} else {
2026-06-07 10:35:21 +08:00
void openLocalResourceInActiveTab(retiredOcrSidecarResourceInput);
}
return;
}
if ((rowKind === 'document' || rowKind === 'index' || rowKind === 'markdown') && documentId) {
void recordNavigationRecent({
kind: 'page',
sourceKind: currentSourceKind() || 'local_folder',
rootUri: currentRootUri(),
relativePath: String(fileRow.getAttribute('data-local-relative-path') || '').trim(),
documentId: documentId,
title: fileTreeRowTitleForShortcut(fileRow, documentId),
workspaceId: resolveWorkspaceId(fileRow)
});
navigateToDocument(documentId, resolveWorkspaceId(fileRow), { treeView: 'filetree', fileTreeScope: currentFileTreeScope() });
} else if (assetId) {
dispatchSidebarEvent('tree.asset.open', { rowId: rowId, rowKind: rowKind, documentId: ownerDocumentId || null, assetId: assetId, assetType: assetType || null, objectIdentity: objectIdentity, workspacePath: workspacePath, workspaceId: resolveWorkspaceId(fileRow), openTarget: e.shiftKey || e.ctrlKey || e.metaKey ? 'new-window' : 'active-tab' });
}
return;
}
2026-05-26 02:35:08 +08:00
if (sidebarPageTree.handlePageTreeClick(e, { closestAction: closestAction })) return;
});
window.addEventListener('tree.sidebarShortcut.toggleFolder', function(event) {
var detail = event.detail || {};
var row = detail.rowId
? document.querySelector('#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape(detail.rowId) + '"]')
: null;
void toggleFolderSidebarShortcut(detail, row);
});
window.addEventListener('tree.filetree.internal-drop', function(event) {
var detail = event.detail || {};
var rowIds = Array.isArray(detail.rowIds) ? detail.rowIds : [];
if (!rowIds.length) return;
var targetRow = detail.targetRowId
? document.querySelector('#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape(detail.targetRowId) + '"]')
: null;
recordFileTreeAction('internal-drop', {
rowId: detail.targetRowId || '',
sourceRowIds: rowIds,
copy: Boolean(detail.copy)
});
void moveSidebarFileTreeRows(rowIds, targetRow, { copy: Boolean(detail.copy) });
});
document.addEventListener('contextmenu', function(event) {
2026-05-29 11:13:05 +08:00
var editorAttachmentLink = closestAction(event.target, '.editor-surface .ProseMirror a.mnote-uploaded-attachment-row');
if (editorAttachmentLink instanceof HTMLAnchorElement) {
event.preventDefault();
event.stopPropagation();
enhanceEditorAttachmentLink(editorAttachmentLink);
openEditorAttachmentMenu(editorAttachmentLink, editorAttachmentLink, { x: event.clientX, y: event.clientY });
return;
}
var fileRow = closestAction(event.target, '.tree-row[data-shell-mode="filetree"]');
if (fileRow) {
event.preventDefault();
var contextRowId = fileRow.getAttribute('data-row-id') || '';
if (contextRowId && !sidebarFileTreeSelection.selectedRowIds.has(contextRowId)) {
selectSidebarFileTreeRow(fileRow, { ctrlKey: false, metaKey: false, shiftKey: false });
}
openFileTreeContextMenu(fileRow, event.clientX, event.clientY, fileRow);
return;
}
2026-05-26 02:35:08 +08:00
if (sidebarPageTree.handlePageTreeContextMenu(event, { closestAction: closestAction })) return;
});
document.addEventListener('keydown', function(event) {
var keyTarget = event.target;
var fileTreeRootForKey = document.getElementById('sidebar-file-tree-root');
var fileTreeRowForKey = closestAction(keyTarget, '.tree-row[data-shell-mode="filetree"]');
if (!fileTreeRowForKey && fileTreeRootForKey && fileTreeRootForKey.contains(document.activeElement)) {
fileTreeRowForKey = closestAction(document.activeElement, '.tree-row[data-shell-mode="filetree"]');
}
if (fileTreeRowForKey) {
var _kbRT_ = window.__mnoteFileTreeKeyboardRuntime;
if (_kbRT_ && typeof _kbRT_.handleFileTreeKeyDown === 'function') {
var handled = _kbRT_.handleFileTreeKeyDown(event, {
closestAction: closestAction,
beginFileTreeInlineRename: beginFileTreeInlineRename,
selectedSidebarFileTreeRows: selectedSidebarFileTreeRows,
buildSidebarFileTreeContext: buildSidebarFileTreeContext,
evaluateSidebarFileTreeWhen: evaluateSidebarFileTreeWhen,
deleteSelectedSidebarFileTreeRows: deleteSelectedSidebarFileTreeRows,
pasteSidebarFileTreeClipboard: pasteSidebarFileTreeClipboard,
});
if (handled) return;
} else {
// inline fallback
if (event.key === 'F2') {
event.preventDefault();
var renameCtx = buildSidebarFileTreeContext('filetree', { targetRow: fileTreeRowForKey });
if (!evaluateSidebarFileTreeWhen(renameCtx, '!workspace.readonly && !editor.dirty')) {
return;
}
beginFileTreeInlineRename(fileTreeRowForKey);
return;
}
if ((event.ctrlKey || event.metaKey) && !event.altKey && event.key) {
var shortcutKey = event.key.toLowerCase();
if (shortcutKey === 'c' || shortcutKey === 'x') {
var selectedRows = selectedSidebarFileTreeRows();
var selectedRowIds = selectedRows.map(function(row) { return row.getAttribute('data-row-id') || ''; }).filter(Boolean);
if (selectedRowIds.length > 0) {
event.preventDefault();
sidebarFileTreeClipboard = { action: shortcutKey === 'x' ? 'cut' : 'copy', rowIds: selectedRowIds };
document.documentElement.setAttribute('data-mnote-filetree-clipboard-action', sidebarFileTreeClipboard.action);
}
return;
}
if (shortcutKey === 'v') {
event.preventDefault();
var pasteCtx = buildSidebarFileTreeContext('filetree', { targetRow: fileTreeRowForKey });
if (!evaluateSidebarFileTreeWhen(pasteCtx, '!workspace.readonly')) {
return;
}
void pasteSidebarFileTreeClipboard(fileTreeRowForKey);
return;
}
}
if (event.key === 'Delete' || event.key === 'Backspace') {
event.preventDefault();
var delCtx = buildSidebarFileTreeContext('filetree', { targetRow: fileTreeRowForKey });
if (!evaluateSidebarFileTreeWhen(delCtx, '!workspace.readonly && !editor.dirty')) {
return;
}
void deleteSelectedSidebarFileTreeRows(fileTreeRowForKey);
return;
}
}
}
if (event.key === 'Escape' && isAnySettingsOpen()) {
event.preventDefault();
closeAllSettingsPopovers();
return;
}
if (isSearchShortcutEvent(event)) {
event.preventDefault();
openSearchModal();
return;
}
if (event.key === 'Escape') {
closeTrashModal();
closeSearchModal();
closeTreeContextMenu();
}
});
document.addEventListener('change', function(event) {
var globalCheckbox = closestAction(event.target, '[data-global-option-checkbox="showHeadingNumbers"]');
if (globalCheckbox instanceof HTMLInputElement) {
writeGlobalShowHeadingNumbers(globalCheckbox.checked);
applyPageOptionsToShell();
renderPageSettingsPopover();
return;
}
var checkbox = closestAction(event.target, '[data-page-option-checkbox]');
if (checkbox instanceof HTMLInputElement) {
var key = checkbox.getAttribute('data-page-option-checkbox') || '';
if (!pageOptionIsSupported(key)) return;
var patch = {};
patch[key] = checkbox.checked;
void persistPageOptionsPatch(patch);
return;
}
var select = closestAction(event.target, '[data-page-option-select]');
if (select instanceof HTMLSelectElement) {
var selectKey = select.getAttribute('data-page-option-select') || '';
var next = {};
if (selectKey === 'layoutDensity') next.layoutDensity = select.value;
if (selectKey === 'pageFont') next.pageFont = select.value;
if (Object.keys(next).length) {
void persistPageOptionsPatch(next);
}
return;
}
var pageWidthSelect = closestAction(event.target, '[data-page-width-select]');
if (pageWidthSelect instanceof HTMLSelectElement) {
var pageWidthType = pageWidthSelect.getAttribute('data-page-width-select') || '';
void persistPageWidthPreference(pageWidthType, pageWidthSelect.value);
2026-06-26 20:01:02 +08:00
return;
}
var knowledgeRagKbSelect = closestAction(event.target, '[data-knowledge-rag-kb-select]');
if (knowledgeRagKbSelect instanceof HTMLSelectElement) {
setKnowledgeRagSelectedProviderKnowledgeBaseId(knowledgeRagKbSelect.value);
}
});
2026-06-01 09:29:12 +08:00
sidebarPageAi.installPageAiDelegates();
function initializePageUiSurfaces() {
pageUiState.pageOptions = null;
pageUiState.pageWidthPreferences = null;
applyPageOptionsToShell();
void loadPageWidthPreferences();
updatePageSettingsTriggerState();
updatePageAiTriggerState();
ensureHistorySnapshotsSeeded();
installWorkspaceSidebarResizer();
}
window.__mnoteRecordPageHistorySnapshot = recordPageHistorySnapshot;
window.__mnoteApplyPageOptionsToShell = applyPageOptionsToShell;
function scheduleInitializePageUiSurfaces() {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() {
setTimeout(initializePageUiSurfaces, 0);
}, { once: true });
return;
}
setTimeout(initializePageUiSurfaces, 0);
}
scheduleInitializePageUiSurfaces();
2026-06-01 09:29:12 +08:00
function mnoteDevHotReloadEnabled() {
try {
return new URL(import.meta.url).searchParams.has('devHot');
} catch (_) {
return false;
}
}
function installMnoteDevHotReload() {
var bootId = '';
var failedOnce = false;
var timer = 0;
function tick() {
fetch('/api/dev/hot-reload', { cache: 'no-store', headers: { accept: 'application/json' } })
.then(function(response) { return response.ok ? response.json() : null; })
.then(function(payload) {
if (!payload || payload.enabled !== true || !payload.bootId) {
if (!bootId && timer) window.clearInterval(timer);
return;
}
document.documentElement.setAttribute('data-mnote-dev-hot-reload', 'enabled');
if (!bootId) {
bootId = String(payload.bootId);
return;
}
if (failedOnce || String(payload.bootId) !== bootId) {
window.location.assign(window.location.href);
}
})
.catch(function() {
if (bootId) failedOnce = true;
});
}
tick();
timer = window.setInterval(tick, 1000);
}
2026-06-01 09:29:12 +08:00
if (mnoteDevHotReloadEnabled()) {
installMnoteDevHotReload();
}
document.addEventListener('dragstart', function(event) {
var pageRow = closestAction(event.target, '.tree-row[data-shell-mode="page"][draggable="true"]');
if (pageRow) {
2026-05-26 02:35:08 +08:00
startPageDrag(pageRow, event);
return;
}
var fileRow = closestAction(event.target, '.tree-row[data-shell-mode="filetree"][draggable="true"]');
if (fileRow) {
var _dndRT_ = window.__mnoteFileTreeDndRuntime;
if (_dndRT_ && typeof _dndRT_.startFileTreeDrag === 'function') {
var dragInfo = _dndRT_.startFileTreeDrag(fileRow, {
selectedSidebarFileTreeRowIdsForDrag: selectedSidebarFileTreeRowIdsForDrag,
});
draggingFileTreeRowIds = _dndRT_.draggingFileTreeRowIds;
if (event.dataTransfer && dragInfo) {
event.dataTransfer.effectAllowed = dragInfo.effectAllowed || 'copyMove';
event.dataTransfer.setData(_dndRT_.FILETREE_DRAG_MIME, dragInfo.payload);
event.dataTransfer.setData('application/x-mnote-file-tree', dragInfo.payload);
event.dataTransfer.setData('text/plain', dragInfo.payload);
}
} else {
// inline fallback
draggingFileTreeRowIds = selectedSidebarFileTreeRowIdsForDrag(fileRow);
if (event.dataTransfer) {
var payload = JSON.stringify({ type: 'mnote-file-tree-dnd', version: 1, rowIds: draggingFileTreeRowIds });
event.dataTransfer.effectAllowed = 'copyMove';
event.dataTransfer.setData(FILETREE_DRAG_MIME, payload);
event.dataTransfer.setData('application/x-mnote-file-tree', payload);
event.dataTransfer.setData('text/plain', payload);
}
}
}
});
document.addEventListener('dragover', function(event) {
var pageRow = closestAction(event.target, '.tree-row[data-shell-mode="page"]');
var sourceNodeId = readPageDragNodeId(event);
if (pageRow && canDropPage(sourceNodeId, pageRow)) {
event.preventDefault();
clearPageDropFeedback();
pageRow.setAttribute('data-drop-feedback', 'true');
pageRow.setAttribute('data-drop-position', pageDropPosition(event, pageRow));
2026-05-26 02:35:08 +08:00
setActivePageDropRow(pageRow);
if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';
return;
}
var _dndRT_ = window.__mnoteFileTreeDndRuntime;
if (_dndRT_ && typeof _dndRT_.handleFileTreeDragOver === 'function') {
if (_dndRT_.handleFileTreeDragOver(event, { closestAction: closestAction })) {
return;
}
} else {
// inline fallback
var fileTree = document.getElementById('sidebar-file-tree-root');
if (fileTree && fileTree.contains(event.target)) {
var hasFiles = event.dataTransfer && Array.prototype.indexOf.call(event.dataTransfer.types || [], 'Files') >= 0;
var hasInternal = event.dataTransfer && Array.prototype.indexOf.call(event.dataTransfer.types || [], FILETREE_DRAG_MIME) >= 0;
if (!hasFiles && !hasInternal && draggingFileTreeRowIds.length === 0) return;
event.preventDefault();
if (activeFileTreeDropRow instanceof HTMLElement) activeFileTreeDropRow.setAttribute('data-drop-target', 'false');
activeFileTreeDropRow = closestAction(event.target, '.tree-row[data-shell-mode="filetree"]') || fileTree;
if (activeFileTreeDropRow instanceof HTMLElement) activeFileTreeDropRow.setAttribute('data-drop-target', 'true');
var copyModifier = event.altKey || event.ctrlKey || event.metaKey;
if (event.dataTransfer) event.dataTransfer.dropEffect = hasFiles || copyModifier ? 'copy' : 'move';
}
}
});
document.addEventListener('drop', function(event) {
var pageRow = closestAction(event.target, '.tree-row[data-shell-mode="page"]');
var sourceNodeId = readPageDragNodeId(event);
if (pageRow && canDropPage(sourceNodeId, pageRow)) {
event.preventDefault();
var position = pageDropPosition(event, pageRow);
var target = resolvePageMoveTarget(pageRow, position);
2026-05-26 02:35:08 +08:00
clearPageDragState();
void dispatchTreeCommand(pageRow, {
action: 'move',
workspaceId: resolveWorkspaceId(pageRow),
documentId: sourceNodeId,
parentId: target.parentId,
sortOrder: target.sortOrder
});
return;
}
var _dndRT_ = window.__mnoteFileTreeDndRuntime;
if (_dndRT_ && typeof _dndRT_.handleFileTreeDrop === 'function') {
_dndRT_.handleFileTreeDrop(event, {
closestAction: closestAction,
resolveWorkspaceId: resolveWorkspaceId,
fileTreeRowLocalUploadTargetRelativePath: fileTreeRowLocalUploadTargetRelativePath,
ensureFileTreeWritableTarget: ensureFileTreeWritableTarget,
dispatchSidebarEvent: dispatchSidebarEvent,
});
} else {
// inline fallback
var fileTree = document.getElementById('sidebar-file-tree-root');
if (fileTree && fileTree.contains(event.target)) {
var targetRow = closestAction(event.target, '.tree-row[data-shell-mode="filetree"]');
var files = event.dataTransfer ? Array.from(event.dataTransfer.files || []) : [];
var raw = event.dataTransfer ? event.dataTransfer.getData(FILETREE_DRAG_MIME) || event.dataTransfer.getData('application/x-mnote-file-tree') || '' : '';
var rowIds = draggingFileTreeRowIds.slice();
if (raw) {
try {
var parsed = JSON.parse(raw);
if (Array.isArray(parsed.rowIds)) rowIds = parsed.rowIds;
} catch (_) {}
}
if (!files.length && !rowIds.length) return;
event.preventDefault();
var detail = {
workspaceId: resolveWorkspaceId(targetRow || fileTree),
targetRowId: targetRow ? targetRow.getAttribute('data-row-id') : null,
targetRowKind: targetRow ? targetRow.getAttribute('data-row-kind') : 'root',
documentId: targetRow ? targetRow.getAttribute('data-document-id') || targetRow.getAttribute('data-doc-id') : null,
assetId: targetRow ? targetRow.getAttribute('data-asset-id') : null,
targetRelativePath: targetRow ? fileTreeRowLocalUploadTargetRelativePath(targetRow) : '',
uploadIntent: 'filetree.folder.drop'
};
if (activeFileTreeDropRow instanceof HTMLElement) activeFileTreeDropRow.setAttribute('data-drop-target', 'false');
activeFileTreeDropRow = null;
if (files.length) {
dispatchSidebarEvent('tree.filetree.external-drop', Object.assign({}, detail, { files: files }));
} else {
void Promise.resolve(ensureFileTreeWritableTarget('drop', targetRow, rowIds, event.altKey === true || event.ctrlKey === true || event.metaKey === true)).then(function(writable) {
if (!writable) return;
dispatchSidebarEvent('tree.filetree.internal-drop', Object.assign({}, detail, { rowIds: rowIds, copy: event.altKey === true || event.ctrlKey === true || event.metaKey === true }));
});
}
draggingFileTreeRowIds = [];
}
}
});
document.addEventListener('dragend', function() {
2026-05-26 02:35:08 +08:00
clearPageDragState();
var _dndRT_ = window.__mnoteFileTreeDndRuntime;
if (_dndRT_ && typeof _dndRT_.resetFileTreeDragState === 'function') {
_dndRT_.resetFileTreeDragState();
} else {
draggingFileTreeRowIds = [];
clearPageDropFeedback();
if (activeFileTreeDropRow instanceof HTMLElement) activeFileTreeDropRow.setAttribute('data-drop-target', 'false');
activeFileTreeDropRow = null;
}
});
sidebarTreeLiveApply.installTreeLiveApplyEventListeners();
var tree = document.getElementById('sidebar-tree-root');
var activeId = currentDocumentId();
if (tree && activeId) {
var activeRow = tree.querySelector('.tree-row[data-node-id="' + cssEscape(activeId) + '"]');
if (activeRow instanceof HTMLElement) activeRow.setAttribute('data-active', 'true');
}
var initiallySelectedFileRows = document.querySelectorAll('#sidebar-file-tree-root .tree-row[data-selected="true"]');
initiallySelectedFileRows.forEach(function(row) {
if (!(row instanceof HTMLElement)) return;
var rowId = row.getAttribute('data-row-id') || '';
if (!rowId) return;
sidebarFileTreeSelection.selectedRowIds.add(rowId);
if (!sidebarFileTreeSelection.anchorRowId) sidebarFileTreeSelection.anchorRowId = rowId;
sidebarFileTreeSelection.focusedRowId = rowId;
});
syncSidebarFileTreeSelection();
schedulePendingLocalFolderRestoreFocus();
window.addEventListener('mnote:primary-document-activated', function(event) {
var detail = event && event.detail ? event.detail : {};
2026-05-26 16:47:03 +08:00
pageUiState.pageOptions = null;
applyPageOptionsToShell();
if (isPageSettingsOpen()) renderPageSettingsPopover();
selectSidebarFileTreeDocument(detail.documentId, { scrollIntoView: false });
});
2026-05-26 17:24:05 +08:00
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();
})();