feat: list plugin pages in the command palette's Go to commands

This commit is contained in:
Linus Rath
2026-10-28 04:24:05 +01:00
parent e33f95989d
commit 1de1d02f57
2 changed files with 26 additions and 1 deletions
@@ -211,3 +211,15 @@ describe('command palette on a phone', () => {
expect(screen.getByRole('option', { name: 'compose' })).toBeInTheDocument();
});
});
describe('command palette and plugin pages', () => {
it('goes to a plugin page like to the built-in apps', async () => {
const pages = await import('@/lib/plugin-sandbox/pages');
act(() => pages.setPluginPages('kanban', 'Kanban', [{ id: 'board', title: 'Board' }]));
render(<CommandPaletteHost />);
pressCtrlK();
act(() => { fireEvent.click(screen.getByRole('option', { name: /go_to\(Board\)/ })); });
expect(nav.push).toHaveBeenCalledWith('/apps/kanban/board');
pages.resetPages();
});
});
+14 -1
View File
@@ -28,6 +28,7 @@ import { useCalendarStore } from "@/stores/calendar-store";
import { usePolicyStore } from "@/stores/policy-store";
import { useThemeStore } from "@/stores/theme-store";
import { usePluginActions } from "@/components/plugins/plugin-actions";
import { usePluginPages, pluginPageHref } from "@/hooks/use-plugin-pages";
import { KeyboardShortcutsModal } from "@/components/keyboard-shortcuts-modal";
import { GlobalSearchPalette } from "@/components/global-search/global-search-palette";
import { isContextMenuOpen } from "@/components/ui/context-menu";
@@ -151,6 +152,7 @@ function CommandPalette({ onClose, onShowShortcuts }: { onClose: () => void; onS
const colorModeLocked = usePolicyStore((s) => s.getColorModePolicy().locked);
const resolvedTheme = useThemeStore((s) => s.resolvedTheme);
const pluginActions = usePluginActions(surface);
const pluginPages = usePluginPages();
const registeredGroups = useRegisteredCommandGroups();
const accounts = useAccountStore((s) => s.accounts);
const activeAccountId = useAuthStore((s) => s.activeAccountId);
@@ -193,6 +195,17 @@ function CommandPalette({ onClose, onShowShortcuts }: { onClose: () => void; onS
if ((client?.supportsFiles?.() ?? false) && isFeatureEnabled("filesEnabled")) {
list.push({ id: "go-files", group: navigation, icon: Folder, label: t("go_to", { name: tSidebar("files") }), run: go("/files") });
}
// Plugin pages sit next to the built-in apps in the rail and the tab bar.
for (const page of pluginPages) {
list.push({
id: `go-page:${page.pluginId}:${page.id}`,
group: navigation,
icon: iconForName(page.icon) ?? Puzzle,
label: t("go_to", { name: page.title }),
source: page.pluginName,
run: go(pluginPageHref(page)),
});
}
list.push(
{ id: "go-settings", group: navigation, icon: Settings, label: t("go_to", { name: tSidebar("settings") }), run: go("/settings") },
{ id: "compose", group: actions, icon: PenSquare, label: t("compose"), shortcut: "c", run: onMail("compose") },
@@ -244,7 +257,7 @@ function CommandPalette({ onClose, onShowShortcuts }: { onClose: () => void; onS
});
}
return list;
}, [client, supportsCalendar, isFeatureEnabled, colorModeLocked, resolvedTheme, pluginActions, registeredGroups, accounts, activeAccountId, router, t, tSidebar, tGlobalSearch, onShowShortcuts, touch]);
}, [client, supportsCalendar, isFeatureEnabled, colorModeLocked, resolvedTheme, pluginActions, pluginPages, registeredGroups, accounts, activeAccountId, router, t, tSidebar, tGlobalSearch, onShowShortcuts, touch]);
const needle = query.trim();
const visible = needle