feat: add global trash plugin
This commit is contained in:
@@ -361,8 +361,6 @@
|
||||
var disposed = false;
|
||||
var fileActions = [];
|
||||
var contextMenuEntries = [];
|
||||
var showingTrash = false;
|
||||
var trashEntries = [];
|
||||
var historyStack = Array.isArray(savedHistory.stack) && savedHistory.stack.length ? savedHistory.stack.map(cleanPath) : [currentPath];
|
||||
var historyIndex = Math.max(0, Math.min(Number(savedHistory.index) || 0, historyStack.length - 1));
|
||||
if (historyStack[historyIndex] !== currentPath) {
|
||||
@@ -395,14 +393,13 @@
|
||||
var backBtn = iconButton('back', 'Back', 'back', goBack);
|
||||
var forwardBtn = iconButton('forward', 'Forward', 'forward', goForward);
|
||||
var upBtn = iconButton('up', 'Up', 'up', goUp);
|
||||
var refreshBtn = iconButton('refresh', 'Refresh', 'refresh', function () { if (showingTrash) loadTrashEntries(); else loadEntries(); });
|
||||
var refreshBtn = iconButton('refresh', 'Refresh', 'refresh', loadEntries);
|
||||
var newFolderBtn = iconButton('new-folder', 'New folder', 'folderAdd', function () { startCreate('folder'); });
|
||||
var newMdBtn = iconButton('new-markdown', 'New markdown file', 'markdownAdd', function () { startCreate('markdown'); });
|
||||
var newTextBtn = iconButton('new-text', 'New text file', 'textAdd', function () { startCreate('text'); });
|
||||
var openBtn = iconButton('open', 'Open', 'open', function () { openEntry(selectedEntry()); });
|
||||
var renameBtn = iconButton('rename', 'Rename', 'rename', function () { beginRename(); });
|
||||
var trashBtn = iconButton('trash', 'Move to trash', 'trash', function () { trashEntry(); });
|
||||
var trashViewBtn = iconButton('trash-view', 'Trash metadata', 'trashView', function () { loadTrashEntries(); });
|
||||
var cutBtn = iconButton('cut', 'Cut', 'cut', function () { cutSelection(); });
|
||||
var copyBtn = iconButton('copy', 'Copy', 'copy', function () { copySelection(); });
|
||||
var pasteBtn = iconButton('paste', 'Paste', 'paste', function () { pasteEntry(); });
|
||||
@@ -420,7 +417,7 @@
|
||||
el('div', { className: 'files-toolbar-group', 'aria-label': 'Navigation' }, [backBtn, forwardBtn, upBtn, refreshBtn]),
|
||||
el('div', { className: 'files-toolbar-group', 'aria-label': 'Create' }, [newFolderBtn, newMdBtn, newTextBtn]),
|
||||
el('div', { className: 'files-toolbar-group', 'aria-label': 'Selection actions' }, [openBtn, renameBtn, trashBtn]),
|
||||
el('div', { className: 'files-toolbar-group', 'aria-label': 'Clipboard and trash' }, [trashViewBtn, cutBtn, copyBtn, pasteBtn]),
|
||||
el('div', { className: 'files-toolbar-group', 'aria-label': 'Clipboard' }, [cutBtn, copyBtn, pasteBtn]),
|
||||
el('span', { className: 'files-toolbar-spacer' }),
|
||||
el('div', { className: 'files-toolbar-group', 'aria-label': 'Filter and sort' }, [filterInput, sortSelect])
|
||||
].forEach(function (node) { toolbar.appendChild(node); });
|
||||
@@ -473,16 +470,16 @@
|
||||
|
||||
function updateButtons() {
|
||||
var count = selectedCount();
|
||||
upBtn.disabled = showingTrash || !currentPath;
|
||||
newFolderBtn.disabled = showingTrash;
|
||||
newMdBtn.disabled = showingTrash;
|
||||
newTextBtn.disabled = showingTrash;
|
||||
openBtn.disabled = showingTrash || count !== 1;
|
||||
renameBtn.disabled = showingTrash || count !== 1;
|
||||
trashBtn.disabled = showingTrash || count === 0;
|
||||
cutBtn.disabled = showingTrash || count === 0;
|
||||
copyBtn.disabled = showingTrash || count === 0;
|
||||
pasteBtn.disabled = showingTrash || !(window.__filesClipboard && window.__filesClipboard.items && window.__filesClipboard.items.length);
|
||||
upBtn.disabled = !currentPath;
|
||||
newFolderBtn.disabled = false;
|
||||
newMdBtn.disabled = false;
|
||||
newTextBtn.disabled = false;
|
||||
openBtn.disabled = count !== 1;
|
||||
renameBtn.disabled = count !== 1;
|
||||
trashBtn.disabled = count === 0;
|
||||
cutBtn.disabled = count === 0;
|
||||
copyBtn.disabled = count === 0;
|
||||
pasteBtn.disabled = !(window.__filesClipboard && window.__filesClipboard.items && window.__filesClipboard.items.length);
|
||||
}
|
||||
|
||||
function updateHistoryButtons() {
|
||||
@@ -634,7 +631,6 @@
|
||||
}
|
||||
|
||||
function renderList() {
|
||||
showingTrash = false;
|
||||
listContainer.innerHTML = '';
|
||||
var header = el('div', { className: 'files-header' }, [
|
||||
el('span', {}, ['Name']),
|
||||
@@ -701,55 +697,7 @@
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
function renderTrashList() {
|
||||
listContainer.innerHTML = '';
|
||||
breadcrumb.innerHTML = '';
|
||||
breadcrumb.appendChild(el('span', { className: 'files-breadcrumb-current' }, ['Trash metadata']));
|
||||
selectedPaths = {};
|
||||
lastClickedPath = '';
|
||||
|
||||
var header = el('div', { className: 'files-header' }, [
|
||||
el('span', {}, ['Original path']),
|
||||
el('span', {}, ['Type']),
|
||||
el('span', {}, ['Deleted']),
|
||||
el('span', {}, ['Trash path']),
|
||||
el('span', {}, ['Actions'])
|
||||
]);
|
||||
listContainer.appendChild(header);
|
||||
|
||||
if (!trashEntries || trashEntries.length === 0) {
|
||||
listContainer.appendChild(el('div', { className: 'files-empty' }, ['Trash is empty']));
|
||||
updateButtons();
|
||||
return;
|
||||
}
|
||||
|
||||
trashEntries.forEach(function (entry) {
|
||||
listContainer.appendChild(el('div', {
|
||||
className: 'files-item',
|
||||
'data-files-trash-id': entry.trashId || ''
|
||||
}, [
|
||||
el('span', { className: 'files-item-name', textContent: entry.originalPath || entry.basename || '', title: entry.originalPath || '' }),
|
||||
el('span', { className: 'files-item-meta' }, [entry.originalType || '']),
|
||||
el('span', { className: 'files-item-meta hide-narrow' }, [formatDate(entry.deletedAt)]),
|
||||
el('span', { className: 'files-item-meta hide-narrow', title: entry.trashId || '' }, [entry.trashPath || '']),
|
||||
el('div', { className: 'files-row-actions' }, [
|
||||
el('button', {
|
||||
className: 'files-row-btn',
|
||||
'data-files-action': 'restore-trash',
|
||||
'data-files-restore-trash': entry.trashId || '',
|
||||
title: 'Restore',
|
||||
'aria-label': 'Restore',
|
||||
innerHTML: svgIcon(ACTION_ICONS.restore),
|
||||
onClick: function (event) { event.stopPropagation(); restoreTrashEntry(entry); }
|
||||
})
|
||||
])
|
||||
]));
|
||||
});
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
function loadEntries() {
|
||||
showingTrash = false;
|
||||
selectedPaths = {};
|
||||
lastClickedPath = '';
|
||||
listContainer.innerHTML = '';
|
||||
@@ -769,36 +717,6 @@
|
||||
});
|
||||
}
|
||||
|
||||
function loadTrashEntries() {
|
||||
showingTrash = true;
|
||||
selectedPaths = {};
|
||||
lastClickedPath = '';
|
||||
listContainer.innerHTML = '';
|
||||
listContainer.appendChild(el('div', { className: 'files-loading' }, ['Loading...']));
|
||||
if (!api.files || typeof api.files.listTrash !== 'function') {
|
||||
trashEntries = [];
|
||||
listContainer.innerHTML = '';
|
||||
listContainer.appendChild(el('div', { className: 'files-error' }, [
|
||||
el('div', {}, ['Trash metadata is unavailable'])
|
||||
]));
|
||||
updateButtons();
|
||||
return;
|
||||
}
|
||||
api.files.listTrash().then(function (result) {
|
||||
if (disposed) return;
|
||||
trashEntries = result || [];
|
||||
renderTrashList();
|
||||
}).catch(function (err) {
|
||||
if (disposed) return;
|
||||
listContainer.innerHTML = '';
|
||||
listContainer.appendChild(el('div', { className: 'files-error' }, [
|
||||
el('div', {}, ['Failed to load trash metadata']),
|
||||
el('div', { className: 'files-error-msg' }, [(err && err.message) ? err.message : String(err)])
|
||||
]));
|
||||
updateButtons();
|
||||
});
|
||||
}
|
||||
|
||||
function contributionContextMatches(item, entry) {
|
||||
var context = String(item && item.context || '').toLowerCase();
|
||||
if (!context || context === '*' || context === 'files' || context === 'vault-entry') return true;
|
||||
@@ -1029,19 +947,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
function restoreTrashEntry(entry) {
|
||||
if (!entry || !entry.trashId) return;
|
||||
if (!api.files || typeof api.files.restoreTrash !== 'function') {
|
||||
window.alert('Restore is unavailable');
|
||||
return;
|
||||
}
|
||||
api.files.restoreTrash(entry.trashId, { overwrite: false }).then(function () {
|
||||
loadEntries();
|
||||
}).catch(function (err) {
|
||||
window.alert((err && err.message) ? err.message : String(err));
|
||||
});
|
||||
}
|
||||
|
||||
filterInput.addEventListener('input', function () { filterText = filterInput.value; renderList(); });
|
||||
sortSelect.addEventListener('change', function () { sortMode = sortSelect.value; renderList(); });
|
||||
createConfirm.addEventListener('click', confirmCreate);
|
||||
@@ -1577,8 +1482,7 @@
|
||||
if (api.events && typeof api.events.subscribe === 'function') {
|
||||
api.events.subscribe('file.changed', function (event) {
|
||||
if (disposed || !isWorkspaceEvent(event)) return;
|
||||
if (showingTrash) loadTrashEntries();
|
||||
else loadEntries();
|
||||
loadEntries();
|
||||
}).then(function (unsubscribe) {
|
||||
fileChangedUnsubscribe = unsubscribe;
|
||||
}).catch(function (err) {
|
||||
|
||||
Reference in New Issue
Block a user