From 75cd4b138376058392efb40b2db50bd96879e31f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20S=2E=20=C5=81ukasiewicz?= Date: Fri, 19 Jul 2024 17:06:40 +0200 Subject: [PATCH] Hide pages from auto complete with Page Decorations (#962) --- plug-api/syscalls/editor.ts | 2 +- plug-api/types.ts | 1 + plugs/editor/complete.ts | 3 ++ plugs/editor/editor.plug.yaml | 7 +++-- plugs/editor/editor.ts | 4 +++ type/web.ts | 4 +-- web/client.ts | 2 +- web/components/page_navigator.tsx | 52 ++++++++++++++++++++++++------- web/syscalls/editor.ts | 2 +- website/All Pages Picker.md | 3 ++ website/Page Decorations.md | 4 +-- website/Page Picker.md | 1 + 12 files changed, 65 insertions(+), 20 deletions(-) create mode 100644 website/All Pages Picker.md diff --git a/plug-api/syscalls/editor.ts b/plug-api/syscalls/editor.ts index 0d761729..17e3d413 100644 --- a/plug-api/syscalls/editor.ts +++ b/plug-api/syscalls/editor.ts @@ -48,7 +48,7 @@ export function navigate( } export function openPageNavigator( - mode: "page" | "meta" = "page", + mode: "page" | "meta" | "all" = "page", ): Promise { return syscall("editor.openPageNavigator", mode); } diff --git a/plug-api/types.ts b/plug-api/types.ts index bdfa3e90..f273d4b3 100644 --- a/plug-api/types.ts +++ b/plug-api/types.ts @@ -29,6 +29,7 @@ export type PageDecoration = { where?: string; whereParsed?: QueryExpression; prefix: string; + hide?: boolean; }; export type AttachmentMeta = ObjectValue< diff --git a/plugs/editor/complete.ts b/plugs/editor/complete.ts index 60f51939..717385f1 100644 --- a/plugs/editor/complete.ts +++ b/plugs/editor/complete.ts @@ -76,6 +76,9 @@ export async function pageComplete(completeEvent: CompleteEvent) { ); } + // Don't complete hidden pages + allPages = allPages.filter((page) => !(page.pageDecoration?.hide === true)); + if (prefix.startsWith("!")) { // Federation! // Let's see if this URI is complete enough to try to fetch index.json diff --git a/plugs/editor/editor.plug.yaml b/plugs/editor/editor.plug.yaml index 278cbdee..67b92117 100644 --- a/plugs/editor/editor.plug.yaml +++ b/plugs/editor/editor.plug.yaml @@ -32,6 +32,11 @@ functions: key: "Ctrl-Shift-k" mac: "Cmd-Shift-k" + openAllNavigator: + path: editor.ts:openAllNavigator + command: + name: "Navigate: All Pages Picker" + # Page operations deletePage: path: "./page.ts:deletePage" @@ -201,7 +206,6 @@ functions: events: - unfurl:title-unfurl - # Title-based link unfurl youtubeUnfurlOptions: path: ./link.ts:youtubeUnfurlOptions @@ -213,7 +217,6 @@ functions: events: - unfurl:youtube-unfurl - embedWidget: path: ./embed.ts:embedWidget codeWidget: embed diff --git a/plugs/editor/editor.ts b/plugs/editor/editor.ts index 900c57ba..50dd5a92 100644 --- a/plugs/editor/editor.ts +++ b/plugs/editor/editor.ts @@ -22,6 +22,10 @@ export async function openMetaNavigator() { await editor.openPageNavigator("meta"); } +export async function openAllNavigator() { + await editor.openPageNavigator("all"); +} + export async function toggleDarkMode() { let darkMode = await clientStore.get("darkMode"); darkMode = !darkMode; diff --git a/type/web.ts b/type/web.ts index 8f705316..5181c204 100644 --- a/type/web.ts +++ b/type/web.ts @@ -61,7 +61,7 @@ export type AppViewState = { }; // Page navigator mode - pageNavigatorMode: "page" | "meta"; + pageNavigatorMode: "page" | "meta" | "all"; // Filter box showFilterBox: boolean; @@ -127,7 +127,7 @@ export type Action = | { type: "update-current-page-meta"; meta: PageMeta } | { type: "update-page-list"; allPages: PageMeta[] } | { type: "settings-loaded"; settings: BuiltinSettings } - | { type: "start-navigate"; mode: "page" | "meta" } + | { type: "start-navigate"; mode: "page" | "meta" | "all" } | { type: "stop-navigate" } | { type: "update-commands"; diff --git a/web/client.ts b/web/client.ts index 6d7b0afc..2e7f3498 100644 --- a/web/client.ts +++ b/web/client.ts @@ -774,7 +774,7 @@ export class Client { ); } - startPageNavigate(mode: "page" | "meta") { + startPageNavigate(mode: "page" | "meta" | "all") { // Then show the page navigator this.ui.viewDispatch({ type: "start-navigate", mode }); this.updatePageListCache().catch(console.error); diff --git a/web/components/page_navigator.tsx b/web/components/page_navigator.tsx index 1cdde69c..262f3d10 100644 --- a/web/components/page_navigator.tsx +++ b/web/components/page_navigator.tsx @@ -19,9 +19,9 @@ export function PageNavigator({ allPages: PageMeta[]; vimMode: boolean; darkMode: boolean; - mode: "page" | "meta"; + mode: "page" | "meta" | "all"; onNavigate: (page: string | undefined) => void; - onModeSwitch: (mode: "page" | "meta") => void; + onModeSwitch: (mode: "page" | "meta" | "all") => void; completer: (context: CompletionContext) => Promise; currentPage?: string; }) { @@ -66,7 +66,7 @@ export function PageNavigator({ description, orderId: orderId, }); - } else { + } else if (mode === "meta") { // Special behavior for #template and #meta pages options.push({ ...pageMeta, @@ -77,6 +77,19 @@ export function PageNavigator({ hint: pageMeta.tags![0], orderId: orderId, }); + } else { + // In mode "all" just show the full path and all tags + let description: string | undefined; + if (pageMeta.tags) { + description = (description || "") + + pageMeta.tags.map((tag) => `#${tag}`).join(" "); + } + options.push({ + ...pageMeta, + name: pageMeta.name, + description, + orderId: orderId, + }); } } let completePrefix = currentPage + "/"; @@ -86,9 +99,11 @@ export function PageNavigator({ } else if (currentPage && currentPage.includes(" ")) { completePrefix = currentPage.split(" ")[0] + " "; } + + const pageNoun = mode === "meta" ? mode : "page"; return ( { - if (mode === "page" && key === "^" && text === "^") { - onModeSwitch("meta"); + // Pages cannot start with ^, as documented in Page Name Rules + if (key === "^" && text === "^") { + switch(mode) { + case "page": + onModeSwitch("meta"); + break; + case "meta": + onModeSwitch("all"); + break; + case "all": + onModeSwitch("page"); + break; + } } }} preFilter={(options, phrase) => { @@ -123,19 +149,23 @@ export function PageNavigator({ return !pageMeta.tags?.includes("template") && !pageMeta.tags?.includes("meta"); }); - return options; - } else { + } else if (mode === "meta") { // Filter on pages tagged with "template" or "meta" options = options.filter((pageMeta) => { return pageMeta.tags?.includes("template") || pageMeta.tags?.includes("meta"); }); - return options; } + + if (mode !== "all") { + // Filter out hidden pages + options = options.filter((page) => !(page.pageDecoration?.hide === true)); + } + return options; }} allowNew={true} - helpText={`Press Enter to open the selected ${mode}, or Shift-Enter to create a new ${mode} with this exact name.`} - newHint={`Create ${mode}`} + helpText={`Press Enter to open the selected ${pageNoun}, or Shift-Enter to create a new ${pageNoun} with this exact name.`} + newHint={`Create ${pageNoun}`} completePrefix={completePrefix} onSelect={(opt) => { onNavigate(opt?.ref || opt?.name); diff --git a/web/syscalls/editor.ts b/web/syscalls/editor.ts index decfbf28..21327afd 100644 --- a/web/syscalls/editor.ts +++ b/web/syscalls/editor.ts @@ -263,7 +263,7 @@ export function editorSyscalls(client: Client): SysCallMapping { const cm = vimGetCm(client.editorView)!; return Vim.handleEx(cm, exCommand); }, - "editor.openPageNavigator": (_ctx, mode: "page" | "meta" = "page") => { + "editor.openPageNavigator": (_ctx, mode: "page" | "meta" | "all" = "page") => { client.startPageNavigate(mode); }, "editor.openCommandPalette": () => { diff --git a/website/All Pages Picker.md b/website/All Pages Picker.md new file mode 100644 index 00000000..8df743c8 --- /dev/null +++ b/website/All Pages Picker.md @@ -0,0 +1,3 @@ +The all pages picker can be used to open any page, including [[Meta Pages]] and pages hidden with [[Page Decorations]]. Otherwise it’s equivalent to the [[Page Picker]]. + +To open, run the command {[Navigate: All Pages Picker]} using this button or [[Command Palette]]. Alternatively cycle from any other Picker by typing `^`. diff --git a/website/Page Decorations.md b/website/Page Decorations.md index b312f439..f0c1336f 100644 --- a/website/Page Decorations.md +++ b/website/Page Decorations.md @@ -29,8 +29,8 @@ This will prefix all pages tagged with `#person` with a 🧑 emoji. Here on silverbullet.md, we have a decoration like this for pages tagged with #plug: [[Plugs/Emoji]] and [[Plugs/Git]] for instance. # Supported decorations -For now there’s just one: * `prefix`: A (visual) string prefix (often an emoji) to add to all page names. This prefix will appear in the top bar as well as in (live preview) links to this page. For example, the name of this page is actually “Page Decorations”, but when you link to it, you’ll see it’s prefixed with a 🎄: [[Page Decorations]] +* `hide` When this is set to `true`, the page will not be shown in [[Page Picker]], [[Meta Picker]], or suggested for completion of [[Links]]. It will otherwise behave as normal - will be [[Plugs/Index|indexed]] and found in [[Live Queries]]. The page can be opened through [[All Pages Picker]], or linked normally when the full name is typed out without completion. -Again — later, more such decorations may be added. \ No newline at end of file +Later, more such decorations may be added. \ No newline at end of file diff --git a/website/Page Picker.md b/website/Page Picker.md index 4a8d057f..3c018d5c 100644 --- a/website/Page Picker.md +++ b/website/Page Picker.md @@ -28,6 +28,7 @@ When entering a filter phrase, the best matches should appear closer to the top, * `Home`: moves to the start of the list * `End`: moves to the end of the list * `Escape`: closes the page picker UI +* Typing `^` when filter phrase is empty will cycle to the next picker, first [[Meta Picker]], then [[All Pages Picker]] # Mouse/touch operation You can obviously scroll and select an item from the list by clicking with the mouse, as well as close the page picker by clicking outside of it.