Improve workspace UX flows

This commit is contained in:
2026-06-30 17:38:18 +08:00
parent 46f754cc2d
commit 268e79d2f0
12 changed files with 1173 additions and 33 deletions
+98 -6
View File
@@ -12,6 +12,17 @@
let statusType = '';
const inactiveStatuses = new Set(['disabled', 'failed', 'incompatible', 'missing-required-capability']);
const shellCommands = [
{ id: 'verstak.shell.open-today', title: 'Open Today', pluginId: 'verstak.shell', pluginName: 'Verstak', priority: 10, shellAction: 'today' },
{ id: 'verstak.shell.open-files', title: 'Open Files', pluginId: 'verstak.shell', pluginName: 'Verstak', priority: 20, shellAction: 'files' },
{ id: 'verstak.shell.open-activity', title: 'Open Activity', pluginId: 'verstak.shell', pluginName: 'Verstak', priority: 30, shellAction: 'activity' },
{ id: 'verstak.shell.open-browser-inbox', title: 'Open Browser Inbox', pluginId: 'verstak.shell', pluginName: 'Verstak', priority: 40, shellAction: 'browser-inbox' },
{ id: 'verstak.shell.create-markdown', title: 'Create Markdown File', pluginId: 'verstak.shell', pluginName: 'Verstak', priority: 50, shellAction: 'create-markdown' },
{ id: 'verstak.shell.create-text', title: 'Create Text File', pluginId: 'verstak.shell', pluginName: 'Verstak', priority: 60, shellAction: 'create-text' },
{ id: 'verstak.shell.sync-now', title: 'Sync Now', pluginId: 'verstak.shell', pluginName: 'Verstak', priority: 70, shellAction: 'sync-now' },
{ id: 'verstak.shell.open-sync-settings', title: 'Open Sync Settings', pluginId: 'verstak.shell', pluginName: 'Verstak', priority: 80, shellAction: 'sync-settings' },
{ id: 'verstak.shell.open-plugin-manager', title: 'Open Plugin Manager', pluginId: 'verstak.shell', pluginName: 'Verstak', priority: 90, shellAction: 'plugin-manager' },
];
$: normalizedQuery = query.trim().toLowerCase();
$: filteredCommands = commands.filter((command) => {
@@ -33,7 +44,7 @@
App.GetContributions().catch(() => ({})),
]);
const pluginById = new Map((plugins || []).map((plugin) => [plugin.manifest?.id, plugin]));
commands = (contributions.commands || [])
const pluginCommands = (contributions.commands || [])
.filter((command) => {
const plugin = pluginById.get(command.pluginId);
if (!plugin) return false;
@@ -44,13 +55,16 @@
return {
...command,
pluginName: plugin?.manifest?.name || command.pluginId,
priority: 1000,
};
})
.sort((a, b) => {
const title = String(a.title || a.id).localeCompare(String(b.title || b.id));
if (title) return title;
return String(a.pluginId).localeCompare(String(b.pluginId));
});
commands = [...shellCommands, ...pluginCommands].sort((a, b) => {
const priority = (a.priority || 1000) - (b.priority || 1000);
if (priority) return priority;
const title = String(a.title || a.id).localeCompare(String(b.title || b.id));
if (title) return title;
return String(a.pluginId).localeCompare(String(b.pluginId));
});
}
async function openPalette() {
@@ -78,9 +92,87 @@
}, 4000);
}
function clickWorkspaceTool(label) {
const tabs = Array.from(document.querySelectorAll('.workspace-tabs [role="tab"]'));
const tab = tabs.find((node) => String(node.textContent || '').trim().toLowerCase() === label);
if (tab) {
tab.click();
return true;
}
return false;
}
async function openWorkspaceTool(label) {
if (clickWorkspaceTool(label)) return;
const selectedWorkspace = document.querySelector('.wt-node.selected .wt-label');
const firstWorkspace = document.querySelector('.wt-label');
const workspaceButton = selectedWorkspace || firstWorkspace;
if (workspaceButton) {
workspaceButton.click();
await tick();
await new Promise((resolve) => requestAnimationFrame(resolve));
}
clickWorkspaceTool(label);
}
async function startFilesCreate(action) {
await openWorkspaceTool('files');
await tick();
await new Promise((resolve) => requestAnimationFrame(resolve));
const button = document.querySelector(`[data-files-action="${action}"]`);
if (!button) {
throw new Error(`Files action not available: ${action}`);
}
button.click();
}
async function runShellCommand(command) {
if (command.shellAction === 'plugin-manager') {
window.dispatchEvent(new CustomEvent('verstak:open-settings', { detail: {} }));
return;
}
if (command.shellAction === 'sync-settings') {
window.dispatchEvent(new CustomEvent('verstak:open-settings', {
detail: { pluginId: 'verstak.sync', panelId: 'verstak.sync.settings' }
}));
return;
}
if (command.shellAction === 'sync-now') {
const result = await App.PluginSyncNow('verstak.sync');
if (typeof result === 'string' && result) {
throw new Error(result);
}
if (Array.isArray(result) && result[1]) {
throw new Error(result[1]);
}
return;
}
if (command.shellAction === 'create-markdown') {
await startFilesCreate('new-markdown');
return;
}
if (command.shellAction === 'create-text') {
await startFilesCreate('new-text');
return;
}
const actionToTab = {
today: 'today',
files: 'files',
activity: 'activity',
'browser-inbox': 'browser inbox',
};
await openWorkspaceTool(actionToTab[command.shellAction] || command.shellAction);
}
async function runCommand(command) {
if (!command) return;
try {
if (command.shellAction) {
await runShellCommand(command);
closePalette();
setStatus('success', `${command.title || command.id} handled`);
return;
}
const result = await executePluginCommand(command.pluginId, command.id, {
source: 'command-palette',
});