feat: vault core/CLI/workbench, vaultd token path, filetree view-state cleanup

Land password-vault dedicated workbench and mnote-vault-core/CLI, agent token
read path design, vault transport split, and retire obsolete filetree smokes.
Ignore local vault reimport scripts that trip secret scanners.
This commit is contained in:
Agent Board
2026-07-24 11:36:06 +08:00
parent b798f628ee
commit bc6f8488ee
41 changed files with 13072 additions and 2316 deletions
@@ -11,6 +11,7 @@ var FILETREE_DRAG_MIME = 'application/x-mnote-file-tree';
var draggingFileTreeRowIds = [];
var activeFileTreeDropRow = null;
var activeFileTreeDropPosition = null;
// ─── 纯 helper ─────────────────────────────────────────
@@ -22,10 +23,34 @@ function filetreeDragPayload(rowIds) {
});
}
/**
* Wolai-style drop zones on a row:
* - top 25% → before (sibling reorder line)
* - bottom 25% → after
* - middle → inside folders/dirs; leaf rows treat middle as after
*/
function fileTreeDropPosition(event, row) {
if (!(row instanceof HTMLElement) || !event) return 'inside';
var rect = row.getBoundingClientRect();
var ratio = rect.height > 0 ? (event.clientY - rect.top) / rect.height : 0.5;
if (ratio < 0.25) return 'before';
if (ratio > 0.75) return 'after';
var kind = String(row.getAttribute('data-row-kind') || '').trim();
if (kind === 'folder' || kind === 'directory' || kind === 'doc' || kind === 'document') {
// documents can host children in page/file tree hybrid; folders always accept inside
if (kind === 'folder' || kind === 'directory') return 'inside';
// expandable document rows also accept nest-into
if (row.getAttribute('aria-expanded') != null && row.querySelector('.tree-toggle')) return 'inside';
}
// non-container leaf: middle zone still sorts after the row
return 'after';
}
function filetreeDropDetail(targetRow, fileTree, deps) {
deps = deps || {};
var resolveWorkspaceId = deps.resolveWorkspaceId || function() { return ''; };
var fileTreeRowLocalUploadTargetRelativePath = deps.fileTreeRowLocalUploadTargetRelativePath || function() { return ''; };
var dropPosition = deps.dropPosition || null;
return {
workspaceId: resolveWorkspaceId(targetRow || fileTree),
targetRowId: targetRow ? targetRow.getAttribute('data-row-id') : null,
@@ -36,6 +61,7 @@ function filetreeDropDetail(targetRow, fileTree, deps) {
assetId: targetRow ? targetRow.getAttribute('data-asset-id') : null,
targetRelativePath: targetRow ? fileTreeRowLocalUploadTargetRelativePath(targetRow) : '',
uploadIntent: 'filetree.folder.drop',
dropPosition: dropPosition || (targetRow ? 'inside' : 'inside'),
};
}
@@ -59,8 +85,21 @@ function parseFileTreeDragPayload(raw) {
function clearFileTreeDropFeedback() {
if (activeFileTreeDropRow instanceof HTMLElement) {
activeFileTreeDropRow.setAttribute('data-drop-target', 'false');
activeFileTreeDropRow.removeAttribute('data-drop-position');
activeFileTreeDropRow.setAttribute('data-drop-feedback', 'false');
}
activeFileTreeDropRow = null;
activeFileTreeDropPosition = null;
}
function setFileTreeDropFeedback(row, position) {
clearFileTreeDropFeedback();
if (!(row instanceof HTMLElement)) return;
activeFileTreeDropRow = row;
activeFileTreeDropPosition = position || 'inside';
activeFileTreeDropRow.setAttribute('data-drop-target', 'true');
activeFileTreeDropRow.setAttribute('data-drop-feedback', 'true');
activeFileTreeDropRow.setAttribute('data-drop-position', activeFileTreeDropPosition);
}
function resetFileTreeDragState() {
@@ -95,10 +134,27 @@ function handleFileTreeDragOver(event, deps) {
if (!hasFiles && !hasInternal && draggingFileTreeRowIds.length === 0) return false;
event.preventDefault();
clearFileTreeDropFeedback();
activeFileTreeDropRow = closestAction(event.target, '.tree-row[data-shell-mode="filetree"]') || fileTree;
if (activeFileTreeDropRow instanceof HTMLElement) {
activeFileTreeDropRow.setAttribute('data-drop-target', 'true');
var row = closestAction(event.target, '.tree-row[data-shell-mode="filetree"]');
if (row instanceof HTMLElement) {
var position = hasFiles ? 'inside' : fileTreeDropPosition(event, row);
// external file drops only nest into containers
if (hasFiles) {
var kind = String(row.getAttribute('data-row-kind') || '').trim();
if (kind !== 'folder' && kind !== 'directory' && kind !== 'doc' && kind !== 'document') {
// drop onto leaf file → treat as after (parent folder context resolved at drop)
position = 'after';
} else if (kind === 'folder' || kind === 'directory') {
position = 'inside';
}
}
setFileTreeDropFeedback(row, position);
} else {
clearFileTreeDropFeedback();
activeFileTreeDropRow = fileTree;
if (activeFileTreeDropRow instanceof HTMLElement) {
activeFileTreeDropRow.setAttribute('data-drop-target', 'true');
}
activeFileTreeDropPosition = 'inside';
}
if (event.dataTransfer) {
var copyModifier = event.altKey || event.ctrlKey || event.metaKey;
@@ -134,9 +190,16 @@ function handleFileTreeDrop(event, deps) {
if (!files.length && !rowIds.length) return;
event.preventDefault();
var dropPosition = activeFileTreeDropPosition
|| (targetRow ? fileTreeDropPosition(event, targetRow) : 'inside');
if (files.length) {
var fileKind = targetRow ? String(targetRow.getAttribute('data-row-kind') || '').trim() : '';
if (fileKind === 'folder' || fileKind === 'directory') dropPosition = 'inside';
}
var detail = filetreeDropDetail(targetRow, fileTree, {
resolveWorkspaceId: resolveWorkspaceId,
fileTreeRowLocalUploadTargetRelativePath: fileTreeRowLocalUploadTargetRelativePath,
dropPosition: dropPosition,
});
clearFileTreeDropFeedback();
if (files.length) {
@@ -149,6 +212,7 @@ function handleFileTreeDrop(event, deps) {
dispatchSidebarEvent('tree.filetree.internal-drop', Object.assign({}, detail, {
rowIds: rowIds,
copy: copyModifier,
dropPosition: dropPosition,
}));
});
}
@@ -159,14 +223,18 @@ function handleFileTreeDrop(event, deps) {
window.__mnoteFileTreeDndRuntime = {
FILETREE_DRAG_MIME: FILETREE_DRAG_MIME,
draggingFileTreeRowIds: draggingFileTreeRowIds,
activeFileTreeDropRow: activeFileTreeDropRow,
get draggingFileTreeRowIds() { return draggingFileTreeRowIds; },
set draggingFileTreeRowIds(value) { draggingFileTreeRowIds = value; },
get activeFileTreeDropRow() { return activeFileTreeDropRow; },
get activeFileTreeDropPosition() { return activeFileTreeDropPosition; },
filetreeDragPayload: filetreeDragPayload,
filetreeDropDetail: filetreeDropDetail,
fileTreeDropPosition: fileTreeDropPosition,
filetreeHasFiles: filetreeHasFiles,
filetreeHasInternalDrag: filetreeHasInternalDrag,
parseFileTreeDragPayload: parseFileTreeDragPayload,
clearFileTreeDropFeedback: clearFileTreeDropFeedback,
setFileTreeDropFeedback: setFileTreeDropFeedback,
resetFileTreeDragState: resetFileTreeDragState,
startFileTreeDrag: startFileTreeDrag,
handleFileTreeDragOver: handleFileTreeDragOver,
@@ -10,15 +10,22 @@ function getSidebarFileTreeClipboard() {
return sidebarFileTreeClipboard;
}
function setSidebarFileTreeClipboard(action, rowIds) {
function setSidebarFileTreeClipboard(action, rowIds, options) {
sidebarFileTreeClipboard = { action: action, rowIds: rowIds };
document.documentElement.setAttribute('data-mnote-filetree-clipboard-action', action);
// Keep product runtimeState / host clipboard in sync (menu paste reads runtimeState).
if (options && typeof options.onClipboardChange === 'function') {
options.onClipboardChange(sidebarFileTreeClipboard);
}
return sidebarFileTreeClipboard;
}
function clearSidebarFileTreeClipboard() {
function clearSidebarFileTreeClipboard(options) {
sidebarFileTreeClipboard = null;
document.documentElement.removeAttribute('data-mnote-filetree-clipboard-action');
if (options && typeof options.onClipboardChange === 'function') {
options.onClipboardChange(null);
}
}
// ─── Keyboard handler ───────────────────────────────────
@@ -31,6 +38,7 @@ function handleFileTreeKeyDown(event, deps) {
var buildSidebarFileTreeContext = deps.buildSidebarFileTreeContext || function() { return {}; };
var evaluateSidebarFileTreeWhen = deps.evaluateSidebarFileTreeWhen || function() { return false; };
var deleteSelectedSidebarFileTreeRows = deps.deleteSelectedSidebarFileTreeRows || function() { return Promise.resolve(); };
var onClipboardChange = deps.onClipboardChange || null;
var keyTarget = event.target;
var fileTreeRootForKey = document.getElementById('sidebar-file-tree-root');
@@ -59,7 +67,9 @@ function handleFileTreeKeyDown(event, deps) {
}).filter(Boolean);
if (selectedRowIds.length > 0) {
event.preventDefault();
setSidebarFileTreeClipboard(shortcutKey === 'x' ? 'cut' : 'copy', selectedRowIds);
setSidebarFileTreeClipboard(shortcutKey === 'x' ? 'cut' : 'copy', selectedRowIds, {
onClipboardChange: onClipboardChange,
});
}
return true;
}
@@ -92,7 +102,7 @@ function handleFileTreeKeyDown(event, deps) {
// ─── 导出 ───────────────────────────────────────────────
window.__mnoteFileTreeKeyboardRuntime = {
sidebarFileTreeClipboard: sidebarFileTreeClipboard,
get sidebarFileTreeClipboard() { return sidebarFileTreeClipboard; },
getSidebarFileTreeClipboard: getSidebarFileTreeClipboard,
setSidebarFileTreeClipboard: setSidebarFileTreeClipboard,
clearSidebarFileTreeClipboard: clearSidebarFileTreeClipboard,
@@ -183,6 +183,49 @@ export const createSidebarFileTreeCommandRuntime = (dependencies = {}) => {
runtimeState.activeTreeContextMenu = null;
}
/**
* Product clipboard used by menu paste + keyboard paste.
* Keep keyboard-module clipboard and runtimeState in lockstep so
* 「粘贴到此处」enables after either Ctrl+C/X or menu cut/copy.
*/
function currentSidebarFileTreeClipboard() {
if (runtimeState.sidebarFileTreeClipboard
&& Array.isArray(runtimeState.sidebarFileTreeClipboard.rowIds)
&& runtimeState.sidebarFileTreeClipboard.rowIds.length) {
return runtimeState.sidebarFileTreeClipboard;
}
var kb = window.__mnoteFileTreeKeyboardRuntime;
var fromKb = kb && typeof kb.getSidebarFileTreeClipboard === 'function'
? kb.getSidebarFileTreeClipboard()
: (kb && kb.sidebarFileTreeClipboard) || null;
if (fromKb && Array.isArray(fromKb.rowIds) && fromKb.rowIds.length) {
// Heal dual-clipboard drift (keyboard module wrote first).
runtimeState.sidebarFileTreeClipboard = fromKb;
return fromKb;
}
return null;
}
function setSidebarFileTreeClipboard(action, rowIds) {
var next = action && Array.isArray(rowIds) && rowIds.length
? { action: action, rowIds: rowIds.slice() }
: null;
runtimeState.sidebarFileTreeClipboard = next;
var kb = window.__mnoteFileTreeKeyboardRuntime;
if (kb && typeof kb.setSidebarFileTreeClipboard === 'function') {
if (next) {
kb.setSidebarFileTreeClipboard(next.action, next.rowIds);
} else if (typeof kb.clearSidebarFileTreeClipboard === 'function') {
kb.clearSidebarFileTreeClipboard();
}
} else if (next) {
document.documentElement.setAttribute('data-mnote-filetree-clipboard-action', next.action);
} else {
document.documentElement.removeAttribute('data-mnote-filetree-clipboard-action');
}
return next;
}
function copyTreeContextValue(value, actionName) {
var text = String(value || '');
var done = function() {
@@ -618,6 +661,30 @@ export const createSidebarFileTreeCommandRuntime = (dependencies = {}) => {
});
return;
}
if (action === 'cut' || action === 'copy') {
var clipboardRows = selectedSidebarFileTreeRows();
if (!clipboardRows.length && trigger && trigger.closest) {
var single = trigger.closest('.tree-row[data-shell-mode="filetree"]');
if (single instanceof HTMLElement) clipboardRows = [single];
}
var clipboardRowIds = clipboardRows.map(function(row) {
return String(row.getAttribute('data-row-id') || '').trim();
}).filter(Boolean);
if (!clipboardRowIds.length) {
recordFileTreeActionStatus('skipped', Object.assign({}, detail, { reason: 'empty-selection' }));
return;
}
setSidebarFileTreeClipboard(action, clipboardRowIds);
recordFileTreeAction(action, Object.assign({}, detail, {
sourceRowIds: clipboardRowIds,
clipboardAction: action,
}));
recordFileTreeActionStatus('applied', Object.assign({}, detail, {
sourceRowIds: clipboardRowIds,
clipboardAction: action,
}));
return;
}
if (action === 'paste-into') {
var pasteRow = trigger && trigger.closest ? trigger.closest('.tree-row[data-shell-mode="filetree"]') : trigger;
recordFileTreeAction('paste-into', detail);
@@ -1228,7 +1295,10 @@ export const createSidebarFileTreeCommandRuntime = (dependencies = {}) => {
{ action: 'new-file', icon: 'note_add', label: 'New File', when: '!workspace.readonly' },
{ action: 'new-folder', icon: 'create_new_folder', label: 'New Folder', disabled: currentSourceKind() !== 'local_folder', title: currentSourceKind() === 'local_folder' ? '在当前目录下创建子文件夹' : '仅 local folder 支持创建文件夹', when: '!workspace.readonly' },
{ action: 'toggle-sidebar-folder-shortcut', icon: 'star', label: '加入/取消星标置顶', disabled: currentSourceKind() !== 'local_folder' || (detail.rowKind !== 'folder' && detail.rowKind !== 'directory'), title: currentSourceKind() === 'local_folder' ? '把当前文件夹加入或移出星标置顶' : '仅 local folder 文件夹支持星标置顶' },
{ action: 'paste-into', icon: 'content_paste', label: '粘贴到此处', disabled: !runtimeState.sidebarFileTreeClipboard, title: runtimeState.sidebarFileTreeClipboard ? '粘贴到当前文件树目标' : '剪贴板为空', when: '!workspace.readonly' },
{ separator: true },
{ action: 'cut', icon: 'content_cut', label: '剪切', shortcut: 'Ctrl+X', when: '!workspace.readonly' },
{ action: 'copy', icon: 'content_copy', label: '复制', shortcut: 'Ctrl+C' },
{ action: 'paste-into', icon: 'content_paste', label: '粘贴到此处', shortcut: 'Ctrl+V', disabled: !currentSidebarFileTreeClipboard(), title: currentSidebarFileTreeClipboard() ? '粘贴到当前文件树目标' : '剪贴板为空', when: '!workspace.readonly' },
{ action: 'refresh', icon: 'refresh', label: 'Refresh' },
{ action: 'collapse-all', icon: 'unfold_less', label: 'Collapse All' },
{ action: 'reveal', icon: 'my_location', label: 'Reveal' },
@@ -1929,9 +1999,16 @@ export const createSidebarFileTreeCommandRuntime = (dependencies = {}) => {
var runtimeFn = fileTreeRuntimeFunction('fileTreeChildCount');
if (runtimeFn) return runtimeFn(documentId, fileTreeRuntimeDeps());
if (!documentId) return 0;
var row = document.querySelector('#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape('doc:' + documentId) + '"]');
var row = document.querySelector(
'#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape('doc:' + documentId) + '"],'
+ '#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape(documentId) + '"],'
+ '#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-document-id="' + cssEscape(documentId) + '"],'
+ '#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-node-id="' + cssEscape(documentId) + '"]'
);
var node = row ? row.closest('.tree-node') : null;
var children = node ? node.querySelectorAll(':scope > .tree-children > .tree-node > .tree-row[data-shell-mode="filetree"][data-row-kind="document"], :scope > .tree-children > .tree-node > .tree-row[data-shell-mode="filetree"][data-row-kind="doc"]') : [];
var children = node
? node.querySelectorAll(':scope > .tree-children > .tree-node > .tree-row[data-shell-mode="filetree"]')
: [];
return children.length;
}
@@ -1944,6 +2021,45 @@ export const createSidebarFileTreeCommandRuntime = (dependencies = {}) => {
}, targetRow) || null;
}
function fileTreeParentIdFromAttr(parentAttr) {
var raw = String(parentAttr || '').trim();
if (!raw) return null;
if (raw.indexOf('doc:') === 0) return raw.slice(4);
return raw;
}
/**
* Wolai-style move target:
* - inside → nest under target (folder/dir/doc)
* - before/after → same parent as target, sortOrder = sibling index (+1 for after)
*/
function resolveFileTreeMoveTarget(targetRow, position) {
if (!(targetRow instanceof HTMLElement)) {
return { parentId: null, sortOrder: 0 };
}
var pos = position || 'inside';
if (pos === 'inside') {
var nestParentId = fileTreeMoveTargetParentId(targetRow);
return {
parentId: nestParentId,
sortOrder: nestParentId ? fileTreeChildCount(nestParentId) : 0,
};
}
var parentAttr = targetRow.getAttribute('data-parent-id') || '';
var parentId = fileTreeParentIdFromAttr(parentAttr);
var siblings = Array.from(
document.querySelectorAll('#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"]')
).filter(function(row) {
return (row.getAttribute('data-parent-id') || '') === parentAttr;
});
var index = siblings.indexOf(targetRow);
if (index < 0) index = 0;
return {
parentId: parentId,
sortOrder: Math.max(0, index + (pos === 'after' ? 1 : 0)),
};
}
function fileTreeMoveSourceId(row) {
if (!(row instanceof HTMLElement)) return '';
return fileTreeRowDocumentId(row)
@@ -1956,7 +2072,10 @@ export const createSidebarFileTreeCommandRuntime = (dependencies = {}) => {
var rows = fileTreeRowsByRowIds(rowIds || []);
if (rows.length === 0) return false;
var copy = Boolean(options && options.copy);
var targetParentId = fileTreeMoveTargetParentId(targetRow);
var dropPosition = (options && options.dropPosition) || 'inside';
var resolved = resolveFileTreeMoveTarget(targetRow, dropPosition);
var targetParentId = resolved.parentId;
var baseSortOrder = typeof resolved.sortOrder === 'number' ? resolved.sortOrder : 0;
var workspaceId = resolveWorkspaceId(targetRow || document.body);
var writable = await ensureFileTreeWritableTarget('move', targetRow, rowIds || [], copy);
if (!writable) return false;
@@ -1983,7 +2102,7 @@ export const createSidebarFileTreeCommandRuntime = (dependencies = {}) => {
workspaceId: workspaceId,
documentId: sourceId,
parentId: targetParentId,
sortOrder: targetParentId ? fileTreeChildCount(targetParentId) + i : i
sortOrder: baseSortOrder + i
});
} catch (error) {
failures.push(sourceId + ': ' + (error && error.message ? error.message : '移动失败'));
@@ -2014,21 +2133,24 @@ export const createSidebarFileTreeCommandRuntime = (dependencies = {}) => {
}
async function pasteSidebarFileTreeClipboard(trigger) {
if (!runtimeState.sidebarFileTreeClipboard || !Array.isArray(runtimeState.sidebarFileTreeClipboard.rowIds) || runtimeState.sidebarFileTreeClipboard.rowIds.length === 0) return false;
var clipboard = currentSidebarFileTreeClipboard();
if (!clipboard) return false;
var targetRow = trigger instanceof HTMLElement ? trigger : null;
if (!targetRow && sidebarFileTreeSelection.focusedRowId) {
targetRow = document.querySelector('#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape(sidebarFileTreeSelection.focusedRowId) + '"]');
}
var targetDocumentId = fileTreeMoveTargetParentId(targetRow) || currentDocumentId();
var action = runtimeState.sidebarFileTreeClipboard.action === 'cut' ? 'move' : 'copy';
var action = clipboard.action === 'cut' ? 'move' : 'copy';
recordFileTreeAction('paste', {
rowId: targetRow ? targetRow.getAttribute('data-row-id') || '' : '',
documentId: targetDocumentId,
sourceRowIds: runtimeState.sidebarFileTreeClipboard.rowIds,
clipboardAction: runtimeState.sidebarFileTreeClipboard.action
sourceRowIds: clipboard.rowIds,
clipboardAction: clipboard.action
});
var ok = await moveSidebarFileTreeRows(runtimeState.sidebarFileTreeClipboard.rowIds, targetRow, { copy: action === 'copy' });
if (ok && action === 'move') runtimeState.sidebarFileTreeClipboard = null;
var ok = await moveSidebarFileTreeRows(clipboard.rowIds, targetRow, { copy: action === 'copy' });
if (ok && action === 'move') {
setSidebarFileTreeClipboard(null, []);
}
return ok;
}
@@ -2206,6 +2328,7 @@ export const createSidebarFileTreeCommandRuntime = (dependencies = {}) => {
postSidebarFileTreeJson,
fileTreeRowsByRowIds,
fileTreeChildCount,
resolveFileTreeMoveTarget,
moveSidebarFileTreeRows,
pasteSidebarFileTreeClipboard,
deleteSelectedSidebarFileTreeRows,
@@ -186,12 +186,29 @@ export const createSidebarPageTreeRuntime = (dependencies = {}) => {
function clearPageDropFeedback() {
if (activePageDropRow instanceof HTMLElement) {
activePageDropRow.setAttribute('data-drop-feedback', 'false');
activePageDropRow.setAttribute('data-drop-target', 'false');
activePageDropRow.removeAttribute('data-drop-position');
}
activePageDropRow = null;
}
function setActivePageDropRow(row) {
activePageDropRow = row instanceof HTMLElement ? row : null;
function setActivePageDropRow(row, position) {
if (!(row instanceof HTMLElement)) {
clearPageDropFeedback();
return;
}
if (activePageDropRow && activePageDropRow !== row) {
clearPageDropFeedback();
}
activePageDropRow = row;
activePageDropRow.setAttribute('data-drop-feedback', 'true');
activePageDropRow.setAttribute('data-drop-target', 'true');
// Always refresh position so before↔after on the same row updates the edge line.
if (position) {
activePageDropRow.setAttribute('data-drop-position', position);
} else {
activePageDropRow.removeAttribute('data-drop-position');
}
}
function clearPageDragState() {
@@ -522,6 +522,11 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
'<div class="mnote-vault-header-actions">' +
'<button type="button" data-vault-create data-testid="vault-create">新建</button>' +
'<button type="button" data-vault-cipher-book data-testid="vault-cipher-book">密文簿</button>' +
'<label class="mnote-vault-insert-cipher" title="在当前焦点字段光标处插入 [Key]" hidden aria-hidden="true">' +
'<span class="mnote-vault-sr-only">插入密文</span>' +
'<select data-vault-insert-cipher data-testid="vault-insert-cipher" aria-label="插入密文">' +
'<option value="">插入密文…</option>' +
'</select></label>' +
'<input type="search" data-vault-search data-testid="vault-search" placeholder="搜索标题、用户名、标签、分组…" aria-label="搜索密码条目" />' +
'<div class="mnote-vault-tabs" role="tablist">' +
'<button type="button" role="tab" data-vault-tab="active" class="is-active" aria-selected="true">在用</button>' +
@@ -3698,12 +3703,17 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
var targetRow = detail.targetRowId
? document.querySelector('#sidebar-file-tree-root .tree-row[data-shell-mode="filetree"][data-row-id="' + cssEscape(detail.targetRowId) + '"]')
: null;
var dropPosition = detail.dropPosition || 'inside';
recordFileTreeAction('internal-drop', {
rowId: detail.targetRowId || '',
sourceRowIds: rowIds,
copy: Boolean(detail.copy)
copy: Boolean(detail.copy),
dropPosition: dropPosition
});
void moveSidebarFileTreeRows(rowIds, targetRow, {
copy: Boolean(detail.copy),
dropPosition: dropPosition,
});
void moveSidebarFileTreeRows(rowIds, targetRow, { copy: Boolean(detail.copy) });
});
document.addEventListener('contextmenu', function(event) {
@@ -3746,6 +3756,9 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
evaluateSidebarFileTreeWhen: evaluateSidebarFileTreeWhen,
deleteSelectedSidebarFileTreeRows: deleteSelectedSidebarFileTreeRows,
pasteSidebarFileTreeClipboard: pasteSidebarFileTreeClipboard,
onClipboardChange: function(nextClipboard) {
sidebarFileTreeClipboard = nextClipboard;
},
});
if (handled) return;
} else {
@@ -3953,10 +3966,8 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
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);
var pagePosition = pageDropPosition(event, pageRow);
setActivePageDropRow(pageRow, pagePosition);
if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';
return;
}
File diff suppressed because it is too large Load Diff