收口工作台资源 tab 与本地文件树 P1
This commit is contained in:
@@ -664,28 +664,52 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
|
||||
};
|
||||
if (panesBootstrap.secondaryInvalid === true) clearSecondaryParams();
|
||||
|
||||
const secondaryUrlForDocument = (documentId, detail = {}) => {
|
||||
const url = currentUrl();
|
||||
url.searchParams.set(paneRouteConfig.secondary.documentIdParam, documentId);
|
||||
const detailSourceKind = typeof detail.sourceKind === 'string' ? detail.sourceKind.trim() : '';
|
||||
const detailRootUri = typeof detail.rootUri === 'string' ? detail.rootUri.trim() : '';
|
||||
const primarySourceKind = (url.searchParams.get(paneRouteConfig.primary.sourceKindParam) || '').trim();
|
||||
const primaryRootUri = (url.searchParams.get(paneRouteConfig.primary.rootUriParam) || '').trim();
|
||||
const secondarySourceKind = detailSourceKind || primarySourceKind;
|
||||
const secondaryRootUri = detailRootUri || primaryRootUri;
|
||||
if (secondarySourceKind) url.searchParams.set(paneRouteConfig.secondary.sourceKindParam, secondarySourceKind);
|
||||
else url.searchParams.delete(paneRouteConfig.secondary.sourceKindParam);
|
||||
if (secondaryRootUri) url.searchParams.set(paneRouteConfig.secondary.rootUriParam, secondaryRootUri);
|
||||
else url.searchParams.delete(paneRouteConfig.secondary.rootUriParam);
|
||||
return { url, sourceKind: secondarySourceKind, rootUri: secondaryRootUri };
|
||||
};
|
||||
|
||||
const openDocumentInSecondaryPane = (documentId, detail = {}) => {
|
||||
const id = typeof documentId === 'string' ? documentId.trim() : '';
|
||||
if (!id) return false;
|
||||
const target = secondaryUrlForDocument(id, detail);
|
||||
if (typeof window.__mnoteDocumentPaneRuntime?.openSecondaryDocument === 'function') {
|
||||
void window.__mnoteDocumentPaneRuntime.openSecondaryDocument({
|
||||
documentId: id,
|
||||
workspaceId: typeof detail.workspaceId === 'string' ? detail.workspaceId.trim() : '',
|
||||
sourceKind: target.sourceKind || null,
|
||||
rootUri: target.rootUri || null,
|
||||
url: target.url,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
window.location.assign(target.url.pathname + target.url.search + target.url.hash);
|
||||
return true;
|
||||
};
|
||||
|
||||
window.addEventListener('tree.page.open-right', (event) => {
|
||||
const detail = event?.detail && typeof event.detail === 'object' ? event.detail : {};
|
||||
const documentId = typeof detail.documentId === 'string' ? detail.documentId.trim() : '';
|
||||
if (!documentId) return;
|
||||
const url = currentUrl();
|
||||
url.searchParams.set(paneRouteConfig.secondary.documentIdParam, documentId);
|
||||
const primarySourceKind = (url.searchParams.get(paneRouteConfig.primary.sourceKindParam) || '').trim();
|
||||
const primaryRootUri = (url.searchParams.get(paneRouteConfig.primary.rootUriParam) || '').trim();
|
||||
if (primarySourceKind) url.searchParams.set(paneRouteConfig.secondary.sourceKindParam, primarySourceKind);
|
||||
else url.searchParams.delete(paneRouteConfig.secondary.sourceKindParam);
|
||||
if (primaryRootUri) url.searchParams.set(paneRouteConfig.secondary.rootUriParam, primaryRootUri);
|
||||
else url.searchParams.delete(paneRouteConfig.secondary.rootUriParam);
|
||||
if (typeof window.__mnoteDocumentPaneRuntime?.openSecondaryDocument === 'function') {
|
||||
void window.__mnoteDocumentPaneRuntime.openSecondaryDocument({
|
||||
documentId,
|
||||
sourceKind: primarySourceKind || null,
|
||||
rootUri: primaryRootUri || null,
|
||||
url,
|
||||
});
|
||||
return;
|
||||
}
|
||||
window.location.assign(url.pathname + url.search + url.hash);
|
||||
openDocumentInSecondaryPane(documentId, detail);
|
||||
});
|
||||
|
||||
window.addEventListener('tree.page.open', (event) => {
|
||||
const detail = event?.detail && typeof event.detail === 'object' ? event.detail : {};
|
||||
const openTarget = typeof detail.openTarget === 'string' ? detail.openTarget.trim().toLowerCase() : '';
|
||||
if (openTarget !== 'side') return;
|
||||
const documentId = typeof detail.documentId === 'string' ? detail.documentId.trim() : '';
|
||||
openDocumentInSecondaryPane(documentId, detail);
|
||||
});
|
||||
|
||||
document.querySelectorAll('[data-mnote-pane-close="secondary"]').forEach((button) => {
|
||||
@@ -2559,6 +2583,7 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
|
||||
pane.setAttribute('data-pane-document-id', documentId);
|
||||
pane.setAttribute('data-pane-workspace-id', workspaceId);
|
||||
pane.setAttribute('data-pane-visible', 'true');
|
||||
pane.removeAttribute('data-mnote-side-target');
|
||||
pane.hidden = false;
|
||||
const shell = pane.querySelector('.document-shell');
|
||||
if (shell instanceof HTMLElement) {
|
||||
@@ -2591,6 +2616,8 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
|
||||
document.title = title;
|
||||
const topbarCurrent = document.querySelector('.wolai-breadcrumb-current [data-page-title-current]');
|
||||
if (topbarCurrent instanceof HTMLElement) topbarCurrent.textContent = title;
|
||||
document.documentElement.removeAttribute('data-mnote-side-target-unsupported');
|
||||
document.documentElement.removeAttribute('data-mnote-side-target-asset-id');
|
||||
document.querySelectorAll('.tree-row[data-active="true"], .tree-row[data-selected="true"]').forEach((row) => {
|
||||
if (row instanceof HTMLElement) {
|
||||
row.setAttribute('data-active', 'false');
|
||||
@@ -2610,6 +2637,8 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
|
||||
runtimeDescriptor.root.removeAttribute('data-mnote-object-editor');
|
||||
runtimeDescriptor.root.removeAttribute('data-mnote-object-identity');
|
||||
runtimeDescriptor.root.removeAttribute('data-mnote-mindmap-id');
|
||||
runtimeDescriptor.root.removeAttribute('data-mnote-side-target-unsupported');
|
||||
runtimeDescriptor.root.removeAttribute('data-mnote-side-target-asset-id');
|
||||
};
|
||||
|
||||
const fetchPageAggregateForPane = async (descriptor) => {
|
||||
@@ -2711,15 +2740,24 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
|
||||
if (pane instanceof HTMLElement) {
|
||||
pane.hidden = true;
|
||||
pane.setAttribute('data-pane-visible', 'false');
|
||||
pane.removeAttribute('data-mnote-side-target');
|
||||
pane.removeAttribute('data-pane-document-id');
|
||||
pane.removeAttribute('data-pane-workspace-id');
|
||||
}
|
||||
const root = document.querySelector(`${ROOT_SELECTOR}[data-pane-role="secondary"]`);
|
||||
if (root instanceof HTMLElement) root.replaceChildren();
|
||||
if (root instanceof HTMLElement) {
|
||||
root.replaceChildren();
|
||||
root.removeAttribute('data-mnote-side-target-unsupported');
|
||||
root.removeAttribute('data-mnote-side-target-asset-id');
|
||||
}
|
||||
if (workspace instanceof HTMLElement) {
|
||||
workspace.setAttribute('data-has-secondary-pane', 'false');
|
||||
workspace.style.removeProperty('grid-template-columns');
|
||||
}
|
||||
const resizerNode = document.querySelector('[data-document-pane-resizer="true"]');
|
||||
if (resizerNode instanceof HTMLElement) resizerNode.hidden = true;
|
||||
document.documentElement.removeAttribute('data-mnote-side-target-unsupported');
|
||||
document.documentElement.removeAttribute('data-mnote-side-target-asset-id');
|
||||
replaceUrlState(url);
|
||||
};
|
||||
|
||||
@@ -3152,6 +3190,7 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
|
||||
|
||||
const resourceTabBadgeKind = (input, kind) => {
|
||||
const title = String(input?.title || input?.fileName || input?.path || '').trim().toLowerCase();
|
||||
if (kind === 'mindmap') return 'mindmap';
|
||||
if (kind === 'office') {
|
||||
if (/\.(ppt|pptx|odp)$/i.test(title)) return 'ppt';
|
||||
if (/\.(xls|xlsx|ods|csv)$/i.test(title)) return 'sheet';
|
||||
@@ -3174,7 +3213,7 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
|
||||
const normalizeResourceTabKind = (input) => {
|
||||
const kind = String(input?.kind || '').trim().toLowerCase();
|
||||
const title = String(input?.title || input?.fileName || input?.path || '').trim().toLowerCase();
|
||||
if (kind === 'office' || kind === 'pdf' || kind === 'image' || kind === 'markdown' || kind === 'text' || kind === 'code') return kind;
|
||||
if (kind === 'mindmap' || kind === 'office' || kind === 'pdf' || kind === 'image' || kind === 'markdown' || kind === 'text' || kind === 'code') return kind;
|
||||
if (/\.(doc|docx|ppt|pptx|xls|xlsx|odt|odp|ods)$/i.test(title)) return 'office';
|
||||
if (/\.pdf$/i.test(title)) return 'pdf';
|
||||
if (/\.(png|jpg|jpeg|gif|webp|svg)$/i.test(title)) return 'image';
|
||||
@@ -3382,6 +3421,13 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
|
||||
}
|
||||
removeFromResourceTabMru(key);
|
||||
if (entry.view) unmountEditorViewBinding(entry.view, { releaseSession: true });
|
||||
if (entry.mindmapRuntime?.runtime && entry.mindmapRuntime?.mountId != null) {
|
||||
try {
|
||||
entry.mindmapRuntime.runtime.unmount(entry.mindmapRuntime.mountId);
|
||||
} catch (error) {
|
||||
console.warn('mnote mindmap resource tab unmount failed', error);
|
||||
}
|
||||
}
|
||||
if (entry.tab instanceof HTMLElement) entry.tab.remove();
|
||||
if (entry.panel instanceof HTMLElement) entry.panel.remove();
|
||||
resourceTabRegistry.delete(key);
|
||||
@@ -3565,6 +3611,80 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
|
||||
}
|
||||
};
|
||||
|
||||
const openMindmapResourceTab = async (entry, input) => {
|
||||
const documentId = String(input.documentId || currentDocumentId() || '').trim();
|
||||
const mindmapId = String(input.mindmapId || input.assetId || '').trim();
|
||||
if (!documentId || !mindmapId) throw new Error('mindmap_resource_identity_missing');
|
||||
const targetUrl = new URL(`/mindmap/${encodeURIComponent(documentId)}/${encodeURIComponent(mindmapId)}`, window.location.origin);
|
||||
const runtime = await loadRuntime();
|
||||
const { bootstrap, title } = await fetchMindmapShellBootstrap(targetUrl);
|
||||
entry.title = String(input.title || title || '思维导图').trim() || '思维导图';
|
||||
const titleNode = entry.tab?.querySelector?.('.mnote-main-tab-title');
|
||||
if (titleNode) titleNode.textContent = entry.title;
|
||||
entry.panel.innerHTML = '<main class="document-shell mnote-resource-tab-mindmap-shell" data-editor-host="mindmap_resource_tab"><div class="mnote-resource-tab-mindmap-root" data-testid="mnote-mindmap-editor-root" data-editor-host-kind="mindmap_resource_tab" data-runtime-editor-status="booting" data-pane-role="resource"></div></main>';
|
||||
entry.panel.setAttribute('data-mnote-object-editor', 'mindmap');
|
||||
entry.panel.setAttribute('data-mnote-object-identity', entry.objectIdentity);
|
||||
entry.panel.setAttribute('data-mnote-mindmap-id', mindmapId);
|
||||
const root = entry.panel.querySelector('[data-testid="mnote-mindmap-editor-root"]');
|
||||
if (!(root instanceof HTMLElement)) throw new Error('mindmap_resource_root_missing');
|
||||
root.setAttribute('data-mnote-object-editor', 'mindmap');
|
||||
root.setAttribute('data-mnote-object-identity', entry.objectIdentity);
|
||||
root.setAttribute('data-mnote-mindmap-id', mindmapId);
|
||||
root.setAttribute('data-document-id', documentId);
|
||||
const mountId = runtime.mount(root, bootstrap);
|
||||
root.setAttribute('data-runtime-mount-id', String(mountId));
|
||||
root.setAttribute('data-editor-host-kind', 'mindmap_resource_tab');
|
||||
root.setAttribute('data-runtime-editor-status', 'mounted');
|
||||
entry.view = null;
|
||||
entry.session = null;
|
||||
entry.mindmapRuntime = { runtime, mountId, root };
|
||||
};
|
||||
|
||||
const openUnsupportedSideTarget = (input = {}) => {
|
||||
const url = currentUrl();
|
||||
secondaryQueryParamNames.forEach((name) => url.searchParams.delete(name));
|
||||
const previousView = paneViewRegistry.get('secondary');
|
||||
if (previousView) {
|
||||
unmountEditorViewBinding(previousView);
|
||||
paneViewRegistry.delete('secondary');
|
||||
}
|
||||
unmountMindmapPane('secondary');
|
||||
const workspace = document.querySelector('.mnote-document-workspace');
|
||||
if (workspace instanceof HTMLElement) {
|
||||
workspace.setAttribute('data-has-secondary-pane', 'true');
|
||||
applyStoredSecondaryWidth();
|
||||
}
|
||||
const resizerNode = document.querySelector('[data-document-pane-resizer="true"]');
|
||||
if (resizerNode instanceof HTMLElement) resizerNode.hidden = false;
|
||||
const pane = document.querySelector('[data-document-pane="true"][data-pane-role="secondary"]');
|
||||
if (pane instanceof HTMLElement) {
|
||||
pane.hidden = false;
|
||||
pane.setAttribute('data-pane-visible', 'true');
|
||||
pane.setAttribute('data-mnote-side-target', 'unsupported-resource');
|
||||
pane.removeAttribute('data-pane-document-id');
|
||||
pane.removeAttribute('data-pane-workspace-id');
|
||||
}
|
||||
const root = document.querySelector(`${ROOT_SELECTOR}[data-pane-role="secondary"]`);
|
||||
const title = String(input.title || input.fileName || input.assetId || '资源').trim() || '资源';
|
||||
if (root instanceof HTMLElement) {
|
||||
root.replaceChildren();
|
||||
root.setAttribute('data-editor-host-kind', 'unsupported_resource_side_target');
|
||||
root.setAttribute('data-mnote-side-target-unsupported', 'true');
|
||||
root.setAttribute('data-mnote-side-target-asset-id', String(input.assetId || ''));
|
||||
const placeholder = document.createElement('div');
|
||||
placeholder.className = 'mnote-resource-tab-error';
|
||||
placeholder.setAttribute('data-mnote-side-target-placeholder', 'true');
|
||||
placeholder.innerHTML = '<div class="mnote-resource-tab-error-inner"><h1>暂不支持在侧栏打开此资源</h1><p></p></div>';
|
||||
const text = placeholder.querySelector('p');
|
||||
if (text) text.textContent = title;
|
||||
root.append(placeholder);
|
||||
}
|
||||
document.documentElement.setAttribute('data-mnote-side-target-unsupported', 'true');
|
||||
document.documentElement.setAttribute('data-mnote-side-target-asset-id', String(input.assetId || ''));
|
||||
replaceUrlState(url);
|
||||
return true;
|
||||
};
|
||||
|
||||
const openResourceInActiveTab = async (input = {}) => {
|
||||
bindMainEditorPageTab();
|
||||
const objectIdentity = String(input.objectIdentity || input.assetId || input.href || '').trim();
|
||||
@@ -3579,7 +3699,9 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
|
||||
resourceTabRegistry.set(objectIdentity, entry);
|
||||
activateMainEditorTab(objectIdentity);
|
||||
try {
|
||||
if (entry.kind === 'markdown' || entry.kind === 'text' || entry.kind === 'code') {
|
||||
if (entry.kind === 'mindmap') {
|
||||
await openMindmapResourceTab(entry, input);
|
||||
} else if (entry.kind === 'markdown' || entry.kind === 'text' || entry.kind === 'code') {
|
||||
await openTiptapResourceTab(entry, input);
|
||||
} else {
|
||||
openPassiveResourceTab(entry, input);
|
||||
@@ -3656,6 +3778,13 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
|
||||
},
|
||||
resolveResourceOpen: (input) => resolveResourceOpen(input),
|
||||
openResourceInActiveTab: openResourceInActiveTab,
|
||||
openResourceAsSideTarget: async (input = {}) => {
|
||||
const resolved = resolveResourceOpen({ ...input, openTarget: 'side' });
|
||||
if (resolved.editorKind === 'markdown' || resolved.editorKind === 'text' || resolved.editorKind === 'code') {
|
||||
return openUnsupportedSideTarget(input);
|
||||
}
|
||||
return openUnsupportedSideTarget(input);
|
||||
},
|
||||
closeSecondaryDocument: ({ url } = {}) => {
|
||||
closeSecondaryPane(url instanceof URL ? url : currentUrl());
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user