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.
111 lines
4.7 KiB
JavaScript
111 lines
4.7 KiB
JavaScript
// MNote filetree keyboard 运行时外置模块。
|
|
// 承接 filetree keydown 处理和 clipboard 状态管理。
|
|
// inline script 保留完整 fallback。
|
|
|
|
// ─── Clipboard 状态 ─────────────────────────────────────
|
|
|
|
var sidebarFileTreeClipboard = null;
|
|
|
|
function getSidebarFileTreeClipboard() {
|
|
return sidebarFileTreeClipboard;
|
|
}
|
|
|
|
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(options) {
|
|
sidebarFileTreeClipboard = null;
|
|
document.documentElement.removeAttribute('data-mnote-filetree-clipboard-action');
|
|
if (options && typeof options.onClipboardChange === 'function') {
|
|
options.onClipboardChange(null);
|
|
}
|
|
}
|
|
|
|
// ─── Keyboard handler ───────────────────────────────────
|
|
|
|
function handleFileTreeKeyDown(event, deps) {
|
|
deps = deps || {};
|
|
var closestAction = deps.closestAction || function() { return null; };
|
|
var beginFileTreeInlineRename = deps.beginFileTreeInlineRename || function() {};
|
|
var selectedSidebarFileTreeRows = deps.selectedSidebarFileTreeRows || function() { return []; };
|
|
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');
|
|
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) return false;
|
|
|
|
if (event.key === 'F2') {
|
|
event.preventDefault();
|
|
var renameCtx = buildSidebarFileTreeContext('filetree', { targetRow: fileTreeRowForKey });
|
|
if (!evaluateSidebarFileTreeWhen(renameCtx, '!workspace.readonly && !editor.dirty')) {
|
|
return true;
|
|
}
|
|
beginFileTreeInlineRename(fileTreeRowForKey);
|
|
return true;
|
|
}
|
|
|
|
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();
|
|
setSidebarFileTreeClipboard(shortcutKey === 'x' ? 'cut' : 'copy', selectedRowIds, {
|
|
onClipboardChange: onClipboardChange,
|
|
});
|
|
}
|
|
return true;
|
|
}
|
|
if (shortcutKey === 'v') {
|
|
event.preventDefault();
|
|
var pasteCtx = buildSidebarFileTreeContext('filetree', { targetRow: fileTreeRowForKey });
|
|
if (!evaluateSidebarFileTreeWhen(pasteCtx, '!workspace.readonly')) {
|
|
return true;
|
|
}
|
|
if (typeof deps.pasteSidebarFileTreeClipboard === 'function') {
|
|
void deps.pasteSidebarFileTreeClipboard(fileTreeRowForKey);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (event.key === 'Delete' || event.key === 'Backspace') {
|
|
event.preventDefault();
|
|
var delCtx = buildSidebarFileTreeContext('filetree', { targetRow: fileTreeRowForKey });
|
|
if (!evaluateSidebarFileTreeWhen(delCtx, '!workspace.readonly && !editor.dirty')) {
|
|
return true;
|
|
}
|
|
void deleteSelectedSidebarFileTreeRows(fileTreeRowForKey);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// ─── 导出 ───────────────────────────────────────────────
|
|
|
|
window.__mnoteFileTreeKeyboardRuntime = {
|
|
get sidebarFileTreeClipboard() { return sidebarFileTreeClipboard; },
|
|
getSidebarFileTreeClipboard: getSidebarFileTreeClipboard,
|
|
setSidebarFileTreeClipboard: setSidebarFileTreeClipboard,
|
|
clearSidebarFileTreeClipboard: clearSidebarFileTreeClipboard,
|
|
handleFileTreeKeyDown: handleFileTreeKeyDown,
|
|
};
|