feat: consolidate local-first mnote web runtime
This commit is contained in:
@@ -70,6 +70,57 @@ function fileTreeRowLocalUploadTargetRelativePath(row, deps) {
|
||||
return lastSlash >= 0 ? relativePath.slice(0, lastSlash) : '';
|
||||
}
|
||||
|
||||
function parseObjectIdentityAttr(value) {
|
||||
var raw = String(value || '').trim();
|
||||
if (!raw) return null;
|
||||
try {
|
||||
var parsed = JSON.parse(raw);
|
||||
return parsed && typeof parsed === 'object' ? parsed : { raw: raw };
|
||||
} catch (_) {
|
||||
return { raw: raw };
|
||||
}
|
||||
}
|
||||
|
||||
function readWorkspacePathFromRow(row, deps) {
|
||||
if (!(row instanceof HTMLElement)) return null;
|
||||
deps = deps || {};
|
||||
var currentSourceKind = typeof deps.currentSourceKind === 'function' ? deps.currentSourceKind : function() { return ''; };
|
||||
var currentRootUri = typeof deps.currentRootUri === 'function' ? deps.currentRootUri : function() { return ''; };
|
||||
var resolveWorkspaceId = typeof deps.resolveWorkspaceId === 'function' ? deps.resolveWorkspaceId : function() { return ''; };
|
||||
var rowTitle = typeof deps.rowTitle === 'function' ? deps.rowTitle : function(target) {
|
||||
return String(target && target.textContent || '').trim();
|
||||
};
|
||||
var objectIdentityRaw = String(row.getAttribute('data-object-identity') || '').trim();
|
||||
var objectIdentity = parseObjectIdentityAttr(objectIdentityRaw);
|
||||
var objectKind = String(row.getAttribute('data-object-kind') || (objectIdentity && objectIdentity.objectKind) || '').trim();
|
||||
var relativePath = fileTreeRowLocalRelativePath(row, deps);
|
||||
var assetId = fileTreeRowAssetId(row, deps);
|
||||
var documentId = fileTreeRowDocumentId(row);
|
||||
var rowId = String(row.getAttribute('data-row-id') || '').trim();
|
||||
var rowKind = fileTreeRowKind(row);
|
||||
var sourceKind = String(row.getAttribute('data-source-kind') || currentSourceKind() || '').trim();
|
||||
var rootUri = String(row.getAttribute('data-root-uri') || currentRootUri() || '').trim();
|
||||
return {
|
||||
schema: 'mnote.workspace_path.v1',
|
||||
workspaceId: String(row.getAttribute('data-workspace-id') || resolveWorkspaceId(row) || '').trim(),
|
||||
sourceKind: sourceKind,
|
||||
rootUri: rootUri,
|
||||
relativePath: relativePath,
|
||||
localRelativePath: relativePath,
|
||||
objectIdentity: objectIdentity,
|
||||
objectIdentityRaw: objectIdentityRaw,
|
||||
objectKind: objectKind,
|
||||
resourceKind: objectKind || rowKind,
|
||||
rowId: rowId,
|
||||
rowKind: rowKind,
|
||||
documentId: documentId,
|
||||
assetId: assetId,
|
||||
title: rowTitle(row),
|
||||
href: String(row.querySelector?.('.tree-link')?.getAttribute?.('href') || '').trim(),
|
||||
isLocalFolder: sourceKind === 'local_folder' || (!sourceKind && (rowId.indexOf('local:') === 0 || documentId.indexOf('local-md:') === 0 || documentId.indexOf('local-dir:') === 0))
|
||||
};
|
||||
}
|
||||
|
||||
function isFileTreeDownloadableAssetRow(row, deps) {
|
||||
if (!(row instanceof HTMLElement)) return false;
|
||||
var kind = fileTreeRowKind(row);
|
||||
@@ -98,6 +149,7 @@ function fileTreeAssetDownloadDetail(row, deps) {
|
||||
rowKind: fileTreeRowKind(row),
|
||||
assetId: assetId,
|
||||
localRelativePath: relativePath,
|
||||
workspacePath: readWorkspacePathFromRow(row, deps),
|
||||
title: title,
|
||||
fileName: title,
|
||||
workspaceId: resolveWorkspaceId(row)
|
||||
@@ -274,6 +326,49 @@ function revealFileTreeAssetRow(assetId, deps) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function localUploadedAssetRelativePath(asset, deps) {
|
||||
deps = deps || {};
|
||||
var direct = String(asset && (asset.rootRelativePath || asset.root_relative_path || asset.relativePath || asset.relative_path) || '').trim();
|
||||
if (direct) return direct;
|
||||
var localFilePathFromAssetId = typeof deps.localFilePathFromAssetId === 'function'
|
||||
? deps.localFilePathFromAssetId
|
||||
: function(assetId) {
|
||||
var value = String(assetId || '').trim();
|
||||
return value.indexOf('local-file:') === 0
|
||||
? value.slice('local-file:'.length)
|
||||
: value.indexOf('local:asset:') === 0
|
||||
? value.slice('local:asset:'.length)
|
||||
: '';
|
||||
};
|
||||
return localFilePathFromAssetId(String(asset && asset.id || '').trim());
|
||||
}
|
||||
|
||||
function parentRelativePathForUploadedAsset(asset, relativePath) {
|
||||
var target = String(asset && (asset.targetRelativePath || asset.target_relative_path) || '').trim();
|
||||
if (target || Object.prototype.hasOwnProperty.call(asset || {}, 'targetRelativePath')) return target;
|
||||
var normalized = String(relativePath || '').trim().replace(/^\/+|\/+$/g, '');
|
||||
var lastSlash = normalized.lastIndexOf('/');
|
||||
return lastSlash >= 0 ? normalized.slice(0, lastSlash) : '';
|
||||
}
|
||||
|
||||
function findLocalFileTreeParentRowForAsset(asset, relativePath, deps) {
|
||||
deps = deps || {};
|
||||
var cssEscape = typeof deps.cssEscape === 'function' ? deps.cssEscape : function(value) { return String(value).replace(/["\\]/g, '\\$&'); };
|
||||
var currentSourceKind = typeof deps.currentSourceKind === 'function' ? deps.currentSourceKind : function() { return ''; };
|
||||
if (currentSourceKind() !== 'local_folder') return null;
|
||||
var parentRelativePath = parentRelativePathForUploadedAsset(asset, relativePath);
|
||||
var selector = '#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-local-relative-path="' + cssEscape(parentRelativePath) + '"]';
|
||||
if (parentRelativePath) {
|
||||
var parentRow = document.querySelector(selector);
|
||||
if (parentRow instanceof HTMLElement) return parentRow;
|
||||
}
|
||||
if (!parentRelativePath) {
|
||||
var root = document.querySelector('#sidebar-file-tree-root .tree-root');
|
||||
return root instanceof HTMLElement ? null : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function appendUploadedAssetRow(asset, documentId, deps) {
|
||||
deps = deps || {};
|
||||
var cssEscape = typeof deps.cssEscape === 'function' ? deps.cssEscape : function(value) { return String(value).replace(/["\\]/g, '\\$&'); };
|
||||
@@ -295,8 +390,10 @@ function appendUploadedAssetRow(asset, documentId, deps) {
|
||||
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
|
||||
var localRelativePath = localUploadedAssetRelativePath(asset, deps);
|
||||
var targetDocumentId = String(documentId || asset.document_id || asset.documentId || asset.ownerDocumentId || currentDocumentId() || '').trim();
|
||||
var parentRow = findLocalFileTreeParentRowForAsset(asset, localRelativePath, deps);
|
||||
if (!parentRow) 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;
|
||||
@@ -325,16 +422,20 @@ function appendUploadedAssetRow(asset, documentId, deps) {
|
||||
objectKind: objectKind || 'attachment',
|
||||
documentId: targetDocumentId || null,
|
||||
blockId: null,
|
||||
assetId: assetId
|
||||
assetId: assetId,
|
||||
rootUri: String(asset && (asset.rootUri || asset.root_uri) || '').trim() || null,
|
||||
relativePath: localRelativePath || null
|
||||
};
|
||||
li.setAttribute('data-node-id', 'asset:' + assetId);
|
||||
var title = uploadedAssetTitle(asset);
|
||||
var iconKind = fileTreeIconKindForFileName(title) || uploadedAssetType(asset) || 'file';
|
||||
if (objectKind === 'mindmap') iconKind = 'mindmap';
|
||||
var ownerDocumentId = String(asset && (asset.ownerDocumentId || asset.owner_document_id) || targetDocumentId || '').trim();
|
||||
var rootUri = String(asset && (asset.rootUri || asset.root_uri) || '').trim();
|
||||
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">' +
|
||||
'<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-owner-document-id="' + escapeHtml(ownerDocumentId) + '" data-asset-id="' + escapeHtml(assetId) + '" data-local-relative-path="' + escapeHtml(localRelativePath) + '" data-root-uri="' + escapeHtml(rootUri) + '" data-source-kind="' + escapeHtml(rootUri ? 'local_folder' : '') + '" 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>' +
|
||||
'<button type="button" class="tree-link" data-rust-action="open" data-row-id="' + escapeHtml('asset:' + assetId) + '" data-document-id="' + escapeHtml(targetDocumentId) + '" data-owner-document-id="' + escapeHtml(ownerDocumentId) + '" data-asset-id="' + escapeHtml(assetId) + '" data-local-relative-path="' + escapeHtml(localRelativePath) + '"><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'));
|
||||
@@ -584,6 +685,7 @@ window.__mnoteFileTreeRuntime = {
|
||||
decodeLocalEncodedPath: decodeLocalEncodedPath,
|
||||
fileTreeRowLocalRelativePath: fileTreeRowLocalRelativePath,
|
||||
fileTreeRowLocalUploadTargetRelativePath: fileTreeRowLocalUploadTargetRelativePath,
|
||||
readWorkspacePathFromRow: readWorkspacePathFromRow,
|
||||
isFileTreeDownloadableAssetRow: isFileTreeDownloadableAssetRow,
|
||||
isFileTreeDownloadableRow: isFileTreeDownloadableRow,
|
||||
fileTreeAssetDownloadDetail: fileTreeAssetDownloadDetail,
|
||||
|
||||
Reference in New Issue
Block a user