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

2772 lines
129 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { createSidebarWorkspaceRuntime } from './sidebar-workspace-runtime.js';
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';
(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,
historySnapshots: [],
pageSettingsOpen: false,
pageAiOpen: false,
pageAiBusy: false,
pageAiMessages: [],
pageAiSuggestionIndex: 0,
pageAiProvider: 'hermes',
pageAiPage: 'chat',
pageAiRunStatus: 'idle',
pageAiCurrentRunId: '',
pageAiAcpRuntime: 'reasonix',
pageAiAcpRuntimes: [],
pageAiQueueLength: 0,
pageAiQueuedItems: [],
pageAiStoppedRunIds: {},
pageAiAbortController: null,
pageAiContextScope: 'page',
pageAiTools: [],
pageAiToolsError: '',
pageAiGatewayHealth: null,
pageAiGatewayHealthError: '',
pageAiLastToolCall: null,
pageAiProfiles: [],
pageAiActiveProfileName: 'mnoteai',
pageAiProfileError: '',
pageAiProfileMemory: { memory: '', user: '', soul: '' },
pageAiProfileMemoryDrafts: { memory: '', user: '', soul: '' },
pageAiProfileMemoryError: '',
pageAiSkills: { categories: [], archived: [] },
pageAiSkillQuery: '',
pageAiSkillError: '',
pageAiSessions: [],
pageAiActiveSessionId: '',
pageAiSessionSearchQuery: '',
pageAiSessionSearchResults: [],
pageAiSessionSearchTimer: 0,
pageAiSessionError: '',
pageAiPermissionRequests: [],
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;
}
function sidebarShellRuntimeFunction(name) {
var runtime = window.__mnoteSidebarShellRuntime;
return runtime && typeof runtime[name] === 'function' ? runtime[name] : null;
}
function toggleWorkspaceSidebar(trigger) {
var runtimeFn = sidebarShellRuntimeFunction('toggleWorkspaceSidebar');
if (runtimeFn) return runtimeFn(trigger);
}
function installWorkspaceSidebarResizer() {
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__') || {};
}
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 closePageSettingsPopover = (...args) => sidebarPageSettings.closePageSettingsPopover(...args);
const closePageShareDialog = (...args) => sidebarPageSettings.closePageShareDialog(...args);
const currentPageOptions = (...args) => sidebarPageSettings.currentPageOptions(...args);
const ensureHistorySnapshotsSeeded = (...args) => sidebarPageSettings.ensureHistorySnapshotsSeeded(...args);
const isPageSettingsOpen = (...args) => sidebarPageSettings.isPageSettingsOpen(...args);
const openPageHistoryDrawer = (...args) => sidebarPageSettings.openPageHistoryDrawer(...args);
const openPageShareDialog = (...args) => sidebarPageSettings.openPageShareDialog(...args);
const pageOptionIsSupported = (...args) => sidebarPageSettings.pageOptionIsSupported(...args);
const persistPageOptionsPatch = (...args) => sidebarPageSettings.persistPageOptionsPatch(...args);
const recordPageHistorySnapshot = (...args) => sidebarPageSettings.recordPageHistorySnapshot(...args);
const renderPageSettingsPopover = (...args) => sidebarPageSettings.renderPageSettingsPopover(...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);
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;
}
}
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 title = window.prompt('新建文件夹', '新建文件夹');
if (!title || !title.trim()) return false;
var result = await dispatchTreeCommand(trigger || document.body, {
action: 'create_folder',
workspaceId: workspaceId,
parentId: effectiveParentId || null,
title: title.trim()
});
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) {
var runtimeFn = sidebarShellRuntimeFunction('applySidebarTreeTab');
if (runtimeFn) return runtimeFn(mode, shell);
}
function switchSidebarTreeTab(trigger) {
var runtimeFn = sidebarShellRuntimeFunction('switchSidebarTreeTab');
if (runtimeFn) return runtimeFn(trigger);
}
function restoreSidebarTreeTab() {
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);
const commandDocumentId = (...args) => sidebarTreeLiveApply.commandDocumentId(...args);
sidebarPageTree = createSidebarPageTreeRuntime({
activeSidebarTreeMode,
commandDocumentId,
copyWorkspaceSourceParams,
cssEscape,
currentDocumentId,
currentSourceKind,
dispatchTreeCommand,
normalizeSidebarTreeMode,
persistLocalFolderSelfChangeSuppression,
persistSidebarTreeMode,
refreshLocalFolderSidebarSnapshot: (...args) => refreshLocalFolderSidebarSnapshot(...args),
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 applyMoveDocumentDelta = (...args) => sidebarTreeLiveApply.applyMoveDocumentDelta(...args);
const applyRemoveDocumentDelta = (...args) => sidebarTreeLiveApply.applyRemoveDocumentDelta(...args);
const setTreeLiveApplyError = (...args) => sidebarTreeLiveApply.setTreeLiveApplyError(...args);
const objectIdentityAttr = (...args) => sidebarTreeLiveApply.objectIdentityAttr(...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);
function dispatchSidebarEvent(name, detail) {
document.documentElement.setAttribute('data-mnote-last-tree-action', name);
window.dispatchEvent(new CustomEvent(name, { detail: detail }));
}
const sidebarFileTreeOpen = createSidebarFileTreeOpenRuntime({
copyWorkspaceSourceParams,
currentDocumentId,
currentRootUri,
fileTreeIconKindForFileName: (...args) => fileTreeIconKindForFileName(...args),
getNavigationInFlight: () => mnoteNavigationInFlight,
isCodeAttachmentFileName: (...args) => isCodeAttachmentFileName(...args),
isNonOfficeAttachmentName: (...args) => isNonOfficeAttachmentName(...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 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,
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();
}
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';
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 index = await fetchLegacyOfficeAttachmentIndex();
var paragraphs = Array.from(editor.querySelectorAll('p'));
paragraphs.forEach(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;
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-mnote-attachment-link', 'true');
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;
}
attachmentMetaPending[assetId] = fetch('/api/media/sign?assetId=' + encodeURIComponent(assetId), {
method: 'GET',
credentials: 'include',
cache: 'no-store'
}).then(function(response) {
return response.json().catch(function() { return null; }).then(function(payload) {
if (!response.ok || !payload) return null;
var asset = payload.asset && typeof payload.asset === 'object' ? payload.asset : {};
var meta = {
assetId: assetId,
fileSize: uploadedFileSize(asset)
};
attachmentMetaCache[assetId] = meta;
return meta;
});
}).catch(function() {
return 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;
try {
if (controller) {
timer = window.setTimeout(function() {
controller.abort();
}, Math.max(1000, Number(timeoutMs) || 15000));
}
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);
}
}
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);
var url = localAssetOpenUrl(asset, false) || uploadedAssetUrl(asset);
var type = uploadedAssetType(asset);
var assetId = String(asset && asset.id || '').trim();
var sizeLabel = uploadedFileSize(asset);
try {
if (type === 'image' && url) {
return editor.chain().focus().setImage({ src: url, alt: title, title: title }).run() === true;
}
var isLocalAsset = isLocalUploadedAsset(asset);
var userId = '';
var onlyOfficeUrl = buildOnlyOfficeAssetOpenUrl(asset, userId);
if (onlyOfficeUrl && assetId) {
userId = await fetchCurrentOnlyOfficeUserId();
onlyOfficeUrl = buildOnlyOfficeAssetOpenUrl(asset, userId);
}
var href = onlyOfficeUrl || url;
if (href) {
var storedHref = onlyOfficeUrl
? (isLocalAsset ? onlyOfficeUrl : buildOnlyOfficeOpenPath({
fileUrl: '',
fileName: title,
fileType: inferOnlyOfficeFileType(title, asset && asset.mime_type) || 'docx',
assetId: assetId,
documentId: String(asset && (asset.document_id || asset.documentId) || currentDocumentId() || '').trim(),
userId: userId || '',
mode: 'view'
}))
: href;
var inserted = editor.chain().focus().insertContent([
{
type: 'paragraph',
content: [{
type: 'text',
text: title,
marks: [{
type: 'link',
attrs: {
href: storedHref,
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() {
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) {
link.setAttribute('data-mnote-attachment-link', 'true');
if (assetId) link.setAttribute('data-asset-id', assetId);
if (sizeLabel) link.setAttribute('data-file-size', sizeLabel);
}
}, 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: 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
}, 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));
}
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 {
var form = new FormData();
form.append('file', file);
form.append('workspaceId', plan.workspaceId);
form.append('documentId', plan.targetDocumentId);
if (plan.targetMindmapId) form.append('mindmapId', plan.targetMindmapId);
var response = await fetchWithTimeout('/api/media/upload', {
method: 'POST',
credentials: 'include',
body: form
}, 15000, '上传');
payload = await response.json().catch(function() { return null; });
if (!response.ok || !payload || !payload.asset) {
throw new Error(payload && payload.error ? payload.error : '上传失败');
}
}
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 || {});
});
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,
currentSourceKind,
deleteSingleFileTreeAsset,
dispatchSidebarEvent,
dispatchTreeCommand,
ensureFileTreeWritableTarget,
fileTreeRuntimeDeps,
fileTreeRuntimeFunction,
fileTreeSelectionRuntimeDeps,
fileTreeSelectionRuntimeFunction,
isFileTreePageRow,
localFilePathFromAssetId,
normalizeFileTreePageRenameTitle,
openConvexAssetFromFileTree,
openEditorAttachmentDetail: (...args) => openEditorAttachmentDetail(...args),
openEditorAttachmentDownload: (...args) => openEditorAttachmentDownload(...args),
openEditorAttachmentEditTab: (...args) => openEditorAttachmentEditTab(...args),
openEditorAttachmentNewWindow: (...args) => openEditorAttachmentNewWindow(...args),
refreshLocalFolderSidebarSnapshot,
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 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 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><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" data-search-switch="page" role="switch" aria-checked="false" 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"]');
if (input) input.addEventListener('input', scheduleSearchResultsRender);
overlay.querySelectorAll('[data-search-switch]').forEach(function(button) {
button.addEventListener('click', function() {
var isOn = button.getAttribute('aria-checked') !== 'true';
button.setAttribute('aria-checked', isOn ? 'true' : 'false');
button.classList.toggle('is-on', isOn);
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;
function searchText(value) {
return String(value == null ? '' : value).replace(/\s+/g, ' ').trim();
}
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 searchSwitchValue(overlay, name) {
var button = overlay.querySelector('[data-search-switch="' + name + '"]');
return button instanceof HTMLElement && button.getAttribute('aria-checked') === 'true';
}
function highlightedHtml(value) {
return escapeHtml(value)
.replace(/&lt;mark&gt;/g, '<mark>')
.replace(/&lt;\/mark&gt;/g, '</mark>');
}
function highlightSearchTitle(title, query) {
var cleanTitle = searchText(title);
var cleanQuery = searchText(query);
if (!cleanQuery) return escapeHtml(cleanTitle);
var index = cleanTitle.toLowerCase().indexOf(cleanQuery.toLowerCase());
if (index < 0) return escapeHtml(cleanTitle);
return escapeHtml(cleanTitle.slice(0, index)) +
'<mark>' + escapeHtml(cleanTitle.slice(index, index + cleanQuery.length)) + '</mark>' +
escapeHtml(cleanTitle.slice(index + cleanQuery.length));
}
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>';
}
}
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 requestId = ++activeSearchRequestId;
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('/api/search/documents', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
workspaceId: resolveWorkspaceId(document.body),
sourceKind: currentSourceKind() || null,
rootUri: currentRootUri() || null,
documentId: 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 : [];
meta.innerHTML = '<span>共 ' + items.length + ' 条匹配结果</span><span>Ctrl + Enter 新窗口打开 / Alt + Enter 右侧边栏打开</span>';
if (!items.length) {
results.innerHTML = '<div class="wolai-search-empty" data-search-empty="true">没有搜索结果</div>';
return;
}
results.innerHTML = items.map(function(item) {
var title = searchText(item.title || item.name || item.documentTitle || '无标题');
var snippet = searchText(item.snippet || (Array.isArray(item.evidence) && item.evidence[0] && item.evidence[0].snippet) || '');
var path = searchText(item.path || item.parentTitle || item.workspaceName || currentWorkspaceName());
var resourceType = searchText(item.resourceType || item.resourceKind || 'page');
return '<button type="button" class="wolai-search-result-row" data-testid="wolai-search-result-row" data-search-result-owner="rust-kernel" data-document-id="' + escapeHtml(item.documentId || item.nodeId || item.id || '') + '" data-resource-type="' + escapeHtml(resourceType) + '">' +
'<span class="material-symbols-outlined wolai-search-result-icon" data-icon="article" aria-hidden="true"></span>' +
'<span class="wolai-search-result-main"><span class="wolai-search-result-title">' + highlightSearchTitle(title, query) + '</span>' +
'<span class="wolai-search-result-snippet">' + (snippet ? highlightedHtml(snippet) : escapeHtml(path)) + '</span>' +
'<span class="wolai-search-result-path"><span>' + escapeHtml(path) + '</span><span class="wolai-search-result-type">' + escapeHtml(resourceType) + '</span></span></span>' +
'</button>';
}).join('');
} 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>';
}
}
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 input = overlay.querySelector('[data-testid="wolai-search-input"]');
if (input) input.setAttribute('placeholder', '在 ' + currentWorkspaceName() + ' 中搜索');
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) overlay.hidden = true;
document.documentElement.removeAttribute('data-mnote-search-modal-open');
}
function toggleSearchModal() {
if (isSearchModalOpen()) closeSearchModal();
else openSearchModal();
}
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);
const pageAiSetContextScope = (...args) => sidebarPageAi.pageAiSetContextScope(...args);
const updatePageAiTriggerState = (...args) => sidebarPageAi.updatePageAiTriggerState(...args);
const sidebarAttachmentOpen = createSidebarAttachmentOpenRuntime({
attachmentClassForFileName: (...args) => attachmentClassForFileName(...args),
buildLocalFileOpenUrl,
buildLocalOnlyOfficeOpenUrl,
buildOnlyOfficeOpenPath,
buildOnlyOfficeOpenUrl,
currentDocumentId,
currentRootUri,
currentWorkspaceSourcePayload,
fileTreeIconKindForFileName,
healLegacyOfficeAttachmentParagraphs,
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;
}
var editorAttachmentLink = closestAction(e.target, '.editor-surface .ProseMirror a[data-mnote-attachment-link="true"], .editor-surface .ProseMirror a.mnote-uploaded-attachment-row, .editor-surface .ProseMirror a[href*="/api/local-folder/files/open"]');
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 pageSettingsPanel = closestAction(e.target, '.wolai-page-settings-panel');
if (isPageSettingsOpen() && !pageSettingsPanel) {
closePageSettingsPopover();
}
var pageSettingsTab = closestAction(e.target, '[data-page-settings-tab]');
if (pageSettingsTab) {
e.preventDefault();
setActivePageSettingsTab(pageSettingsTab.getAttribute('data-page-settings-tab') || 'page');
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 pageAiClose = closestAction(e.target, '[data-page-ai-action="close"]');
if (pageAiClose) {
e.preventDefault();
closePageAiDrawer();
return;
}
var pageAiSettings = closestAction(e.target, '[data-page-ai-action="open-hermes-settings"]');
if (pageAiSettings) {
e.preventDefault();
pageAiOpenHermesSettings();
return;
}
var pageAiStop = closestAction(e.target, '[data-page-ai-action="stop-run"]');
if (pageAiStop) {
e.preventDefault();
void pageAiStopRun();
return;
}
var pageAiRotate = closestAction(e.target, '[data-page-ai-action="rotate"]');
if (pageAiRotate) {
e.preventDefault();
pageUiState.pageAiSuggestionIndex += 1;
renderPageAiSuggestions();
return;
}
var pageAiIntent = closestAction(e.target, '[data-page-ai-intent]');
if (pageAiIntent) {
e.preventDefault();
var intentName = pageAiIntent.getAttribute('data-page-ai-intent') || '';
if (intentName === 'create-summary') {
void sendPageAiMessage('请通过 Hermes 调用 mnote.artifact.create_summary,为当前页面创建或更新 AI Summary。');
return;
}
if (intentName === 'create-ai-note') {
void sendPageAiMessage('请通过 Hermes 调用 mnote.artifact.create_ai_note,基于当前页面创建一篇新的 AI Note。');
return;
}
}
var pageAiTab = closestAction(e.target, '[data-page-ai-tab]');
if (pageAiTab) {
e.preventDefault();
pageUiState.pageAiPage = pageAiTab.getAttribute('data-page-ai-tab') || 'chat';
if (pageUiState.pageAiPage === 'runtime') void pageAiLoadGatewayHealth();
renderPageAiControls();
renderPageAiConversation();
return;
}
var pageAiProvider = closestAction(e.target, '[data-page-ai-provider]');
if (pageAiProvider) {
e.preventDefault();
pageUiState.pageAiProvider = pageAiProvider.getAttribute('data-page-ai-provider') || 'hermes';
renderPageAiProviderButtons();
return;
}
var pageAiMemorySave = closestAction(e.target, '[data-page-ai-memory-save]');
if (pageAiMemorySave) {
e.preventDefault();
void pageAiSaveProfileMemory(pageAiMemorySave.getAttribute('data-page-ai-memory-save') || '');
return;
}
var pageAiSkillToggle = closestAction(e.target, '[data-page-ai-skill-toggle]');
if (pageAiSkillToggle) {
e.preventDefault();
var skillName = pageAiSkillToggle.getAttribute('data-page-ai-skill-toggle') || '';
var nextEnabled = pageAiSkillToggle.getAttribute('aria-pressed') !== 'true';
void pageAiToggleSkill(skillName, nextEnabled);
return;
}
var pageAiToolToggle = closestAction(e.target, '[data-page-ai-tool-toggle]');
if (pageAiToolToggle) {
e.preventDefault();
var toolName = pageAiToolToggle.getAttribute('data-page-ai-tool-toggle') || '';
var nextToolEnabled = pageAiToolToggle.getAttribute('aria-pressed') !== 'true';
void pageAiToggleTool(toolName, nextToolEnabled);
return;
}
var pageAiSessionResume = closestAction(e.target, '[data-page-ai-session-resume]');
if (pageAiSessionResume) {
e.preventDefault();
void pageAiResumeBackendSession(pageAiSessionResume.getAttribute('data-page-ai-session-resume') || '').catch(function(error) {
pageUiState.pageAiSessionError = error instanceof Error ? error.message : String(error);
renderPageAiControls();
});
return;
}
var pageAiSessionRename = closestAction(e.target, '[data-page-ai-session-rename]');
if (pageAiSessionRename) {
e.preventDefault();
void pageAiRenameBackendSession(pageAiSessionRename.getAttribute('data-page-ai-session-rename') || '').catch(function(error) {
pageUiState.pageAiSessionError = error instanceof Error ? error.message : String(error);
renderPageAiControls();
});
return;
}
var pageAiSessionDelete = closestAction(e.target, '[data-page-ai-session-delete]');
if (pageAiSessionDelete) {
e.preventDefault();
void pageAiDeleteBackendSession(pageAiSessionDelete.getAttribute('data-page-ai-session-delete') || '').catch(function(error) {
pageUiState.pageAiSessionError = error instanceof Error ? error.message : String(error);
renderPageAiControls();
});
return;
}
var pageAiPermissionAction = closestAction(e.target, '[data-page-ai-permission-action]');
if (pageAiPermissionAction) {
e.preventDefault();
pageAiResolvePermission(
pageAiPermissionAction.getAttribute('data-page-ai-permission-id') || '',
pageAiPermissionAction.getAttribute('data-page-ai-permission-action') || 'deny'
);
return;
}
var pageAiOpenLocationAction = closestAction(e.target, '[data-page-ai-open-location]');
if (pageAiOpenLocationAction) {
e.preventDefault();
var loc = String(pageAiOpenLocationAction.getAttribute('data-page-ai-open-location') || '').trim();
if (loc) pageAiOpenLocation(loc);
return;
}
var pageAiSession = closestAction(e.target, '[data-page-ai-session]');
if (pageAiSession) {
e.preventDefault();
pageAiSetActiveSession(pageAiSession.getAttribute('data-page-ai-session') || '');
return;
}
var pageAiSuggestion = closestAction(e.target, '[data-page-ai-suggestion]');
if (pageAiSuggestion) {
e.preventDefault();
var text = pageAiSuggestion.getAttribute('data-page-ai-suggestion') || '';
var inputNode = ensurePageAiDrawer().querySelector('[data-page-ai-input]');
if (inputNode instanceof HTMLTextAreaElement) {
inputNode.value = text;
inputNode.focus();
}
return;
}
var pageAiNewSession = closestAction(e.target, '[data-page-ai-action="new-session"]');
if (pageAiNewSession) {
e.preventDefault();
pageUiState.pageAiPage = 'chat';
pageAiStartNewSession();
return;
}
var pageAiHistory = closestAction(e.target, '[data-page-ai-action="history"]');
if (pageAiHistory) {
e.preventDefault();
pageAiLoadSessions();
pageUiState.pageAiPage = pageUiState.pageAiPage === 'history' ? 'chat' : 'history';
renderPageAiControls();
renderPageAiConversation();
if (pageUiState.pageAiPage === 'history') {
void pageAiLoadBackendSessions().catch(function(error) {
pageUiState.pageAiSessionError = error instanceof Error ? error.message : String(error);
renderPageAiControls();
});
}
return;
}
var pageAiSend = closestAction(e.target, '[data-page-ai-action="send"]');
if (pageAiSend) {
e.preventDefault();
var input = ensurePageAiDrawer().querySelector('[data-page-ai-input]');
if (input instanceof HTMLTextAreaElement) {
var message = input.value;
input.value = '';
void sendPageAiMessage(message);
}
return;
}
var cancelQueuedRun = closestAction(e.target, '[data-page-ai-action="cancel-queued-run"]');
if (cancelQueuedRun) {
e.preventDefault();
void pageAiCancelQueuedRun(cancelQueuedRun.getAttribute('data-page-ai-queue-id'));
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 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 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 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);
dispatchSidebarEvent('tree.filetree.open', { rowId: rowId, rowKind: rowKind, documentId: ownerDocumentId || null, assetId: assetId || null, assetType: assetType || null, objectIdentity: objectIdentity, workspaceId: resolveWorkspaceId(fileRow) });
if (e.shiftKey || e.ctrlKey || e.metaKey) {
return;
}
if ((rowKind === 'document' || rowKind === 'index' || rowKind === 'markdown') && documentId) {
navigateToDocument(documentId, resolveWorkspaceId(fileRow), { treeView: 'filetree' });
} else if (assetId) {
dispatchSidebarEvent('tree.asset.open', { rowId: rowId, rowKind: rowKind, documentId: ownerDocumentId || null, assetId: assetId, assetType: assetType || null, objectIdentity: objectIdentity, workspaceId: resolveWorkspaceId(fileRow), openTarget: e.shiftKey || e.ctrlKey || e.metaKey ? 'new-window' : 'active-tab' });
}
return;
}
if (sidebarPageTree.handlePageTreeClick(e, { closestAction: closestAction })) return;
});
document.addEventListener('contextmenu', function(event) {
var editorAttachmentLink = closestAction(event.target, '.editor-surface .ProseMirror a[data-mnote-attachment-link="true"], .editor-surface .ProseMirror a.mnote-uploaded-attachment-row, .editor-surface .ProseMirror a[href*="/api/local-folder/files/open"]');
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;
}
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();
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();
void pasteSidebarFileTreeClipboard(fileTreeRowForKey);
return;
}
}
if (event.key === 'Delete' || event.key === 'Backspace') {
event.preventDefault();
var delCtx = buildSidebarFileTreeContext('filetree');
if (!evaluateSidebarFileTreeWhen(delCtx, '!workspace.readonly')) {
return;
}
void deleteSelectedSidebarFileTreeRows(fileTreeRowForKey);
return;
}
}
}
if (event.key === 'Escape' && isPageSettingsOpen()) {
event.preventDefault();
closePageSettingsPopover();
return;
}
if ((event.metaKey || event.ctrlKey) && !event.shiftKey && event.key && event.key.toLowerCase() === 'p') {
event.preventDefault();
toggleSearchModal();
return;
}
if (event.key === 'Escape') {
closeTrashModal();
closeSearchModal();
closeTreeContextMenu();
}
if (event.key === 'Enter' && !event.shiftKey) {
var aiInput = closestAction(event.target, '[data-page-ai-input]');
if (aiInput instanceof HTMLTextAreaElement) {
event.preventDefault();
var text = aiInput.value;
aiInput.value = '';
void sendPageAiMessage(text);
}
}
});
document.addEventListener('input', function(event) {
var skillSearch = closestAction(event.target, '[data-page-ai-skill-search]');
if (skillSearch instanceof HTMLInputElement) {
pageUiState.pageAiSkillQuery = skillSearch.value;
renderPageAiControls();
return;
}
var sessionSearch = closestAction(event.target, '[data-page-ai-session-search]');
if (sessionSearch instanceof HTMLInputElement) {
var sessionQuery = sessionSearch.value;
window.clearTimeout(pageUiState.pageAiSessionSearchTimer || 0);
pageUiState.pageAiSessionSearchTimer = window.setTimeout(function() {
void pageAiSearchBackendSessions(sessionQuery).catch(function(error) {
pageUiState.pageAiSessionError = error instanceof Error ? error.message : String(error);
renderPageAiControls();
});
}, 200);
return;
}
var memoryEditor = closestAction(event.target, '[data-page-ai-memory-editor]');
if (memoryEditor instanceof HTMLTextAreaElement) {
var section = memoryEditor.getAttribute('data-page-ai-memory-editor') || '';
if (['memory', 'user', 'soul'].indexOf(section) >= 0) {
pageUiState.pageAiProfileMemoryDrafts[section] = memoryEditor.value;
}
}
});
document.addEventListener('change', function(event) {
var pageAiAcpRuntimeSelect = closestAction(event.target, '[data-page-ai-acp-runtime]');
if (pageAiAcpRuntimeSelect instanceof HTMLSelectElement) {
var next = String(pageAiAcpRuntimeSelect.value || 'reasonix').trim() || 'reasonix';
pageUiState.pageAiAcpRuntime = next;
pageUiState.pageAiSkills = { categories: [], archived: [] };
pageUiState.pageAiSkillError = '';
pageAiPersistSessions();
void pageAiLoadProfiles();
if (next !== 'reasonix') void pageAiLoadProfileMemory();
void pageAiLoadSkills();
void pageAiLoadBackendSessions().catch(function(error) {
pageUiState.pageAiSessionError = error instanceof Error ? error.message : String(error);
});
renderPageAiControls();
renderPageAiProviderButtons();
return;
}
var pageAiProfileSelect = closestAction(event.target, '[data-page-ai-profile-select]');
if (pageAiProfileSelect instanceof HTMLSelectElement) {
void pageAiSwitchProfile(pageAiProfileSelect.value);
return;
}
var pageAiContextSelect = closestAction(event.target, '[data-page-ai-context-scope]');
if (pageAiContextSelect instanceof HTMLSelectElement) {
pageAiSetContextScope(pageAiContextSelect.value);
renderPageAiControls();
return;
}
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);
}
}
});
function initializePageUiSurfaces() {
pageUiState.pageOptions = null;
applyPageOptionsToShell();
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();
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);
}
installMnoteDevHotReload();
document.addEventListener('dragstart', function(event) {
var pageRow = closestAction(event.target, '.tree-row[data-shell-mode="page"][draggable="true"]');
if (pageRow) {
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));
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);
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() {
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 : {};
selectSidebarFileTreeDocument(detail.documentId, { scrollIntoView: false });
});
restoreSidebarTreeTab();
startLocalFolderSidebarWatch();
})();