Hide pages from auto complete with Page Decorations (#962)

pull/969/head
Marek S. Łukasiewicz 2024-07-19 17:06:40 +02:00 committed by GitHub
parent 5fe77083ae
commit 75cd4b1383
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 65 additions and 20 deletions

View File

@ -48,7 +48,7 @@ export function navigate(
} }
export function openPageNavigator( export function openPageNavigator(
mode: "page" | "meta" = "page", mode: "page" | "meta" | "all" = "page",
): Promise<void> { ): Promise<void> {
return syscall("editor.openPageNavigator", mode); return syscall("editor.openPageNavigator", mode);
} }

View File

@ -29,6 +29,7 @@ export type PageDecoration = {
where?: string; where?: string;
whereParsed?: QueryExpression; whereParsed?: QueryExpression;
prefix: string; prefix: string;
hide?: boolean;
}; };
export type AttachmentMeta = ObjectValue< export type AttachmentMeta = ObjectValue<

View File

@ -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("!")) { if (prefix.startsWith("!")) {
// Federation! // Federation!
// Let's see if this URI is complete enough to try to fetch index.json // Let's see if this URI is complete enough to try to fetch index.json

View File

@ -32,6 +32,11 @@ functions:
key: "Ctrl-Shift-k" key: "Ctrl-Shift-k"
mac: "Cmd-Shift-k" mac: "Cmd-Shift-k"
openAllNavigator:
path: editor.ts:openAllNavigator
command:
name: "Navigate: All Pages Picker"
# Page operations # Page operations
deletePage: deletePage:
path: "./page.ts:deletePage" path: "./page.ts:deletePage"
@ -201,7 +206,6 @@ functions:
events: events:
- unfurl:title-unfurl - unfurl:title-unfurl
# Title-based link unfurl # Title-based link unfurl
youtubeUnfurlOptions: youtubeUnfurlOptions:
path: ./link.ts:youtubeUnfurlOptions path: ./link.ts:youtubeUnfurlOptions
@ -213,7 +217,6 @@ functions:
events: events:
- unfurl:youtube-unfurl - unfurl:youtube-unfurl
embedWidget: embedWidget:
path: ./embed.ts:embedWidget path: ./embed.ts:embedWidget
codeWidget: embed codeWidget: embed

View File

@ -22,6 +22,10 @@ export async function openMetaNavigator() {
await editor.openPageNavigator("meta"); await editor.openPageNavigator("meta");
} }
export async function openAllNavigator() {
await editor.openPageNavigator("all");
}
export async function toggleDarkMode() { export async function toggleDarkMode() {
let darkMode = await clientStore.get("darkMode"); let darkMode = await clientStore.get("darkMode");
darkMode = !darkMode; darkMode = !darkMode;

View File

@ -61,7 +61,7 @@ export type AppViewState = {
}; };
// Page navigator mode // Page navigator mode
pageNavigatorMode: "page" | "meta"; pageNavigatorMode: "page" | "meta" | "all";
// Filter box // Filter box
showFilterBox: boolean; showFilterBox: boolean;
@ -127,7 +127,7 @@ export type Action =
| { type: "update-current-page-meta"; meta: PageMeta } | { type: "update-current-page-meta"; meta: PageMeta }
| { type: "update-page-list"; allPages: PageMeta[] } | { type: "update-page-list"; allPages: PageMeta[] }
| { type: "settings-loaded"; settings: BuiltinSettings } | { type: "settings-loaded"; settings: BuiltinSettings }
| { type: "start-navigate"; mode: "page" | "meta" } | { type: "start-navigate"; mode: "page" | "meta" | "all" }
| { type: "stop-navigate" } | { type: "stop-navigate" }
| { | {
type: "update-commands"; type: "update-commands";

View File

@ -774,7 +774,7 @@ export class Client {
); );
} }
startPageNavigate(mode: "page" | "meta") { startPageNavigate(mode: "page" | "meta" | "all") {
// Then show the page navigator // Then show the page navigator
this.ui.viewDispatch({ type: "start-navigate", mode }); this.ui.viewDispatch({ type: "start-navigate", mode });
this.updatePageListCache().catch(console.error); this.updatePageListCache().catch(console.error);

View File

@ -19,9 +19,9 @@ export function PageNavigator({
allPages: PageMeta[]; allPages: PageMeta[];
vimMode: boolean; vimMode: boolean;
darkMode: boolean; darkMode: boolean;
mode: "page" | "meta"; mode: "page" | "meta" | "all";
onNavigate: (page: string | undefined) => void; onNavigate: (page: string | undefined) => void;
onModeSwitch: (mode: "page" | "meta") => void; onModeSwitch: (mode: "page" | "meta" | "all") => void;
completer: (context: CompletionContext) => Promise<CompletionResult | null>; completer: (context: CompletionContext) => Promise<CompletionResult | null>;
currentPage?: string; currentPage?: string;
}) { }) {
@ -66,7 +66,7 @@ export function PageNavigator({
description, description,
orderId: orderId, orderId: orderId,
}); });
} else { } else if (mode === "meta") {
// Special behavior for #template and #meta pages // Special behavior for #template and #meta pages
options.push({ options.push({
...pageMeta, ...pageMeta,
@ -77,6 +77,19 @@ export function PageNavigator({
hint: pageMeta.tags![0], hint: pageMeta.tags![0],
orderId: orderId, 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 + "/"; let completePrefix = currentPage + "/";
@ -86,9 +99,11 @@ export function PageNavigator({
} else if (currentPage && currentPage.includes(" ")) { } else if (currentPage && currentPage.includes(" ")) {
completePrefix = currentPage.split(" ")[0] + " "; completePrefix = currentPage.split(" ")[0] + " ";
} }
const pageNoun = mode === "meta" ? mode : "page";
return ( return (
<FilterList <FilterList
placeholder={mode === "page" ? "Page" : "#template or #meta page"} placeholder={mode === "page" ? "Page" : (mode === "meta" ? "#template or #meta page" : "Any page, also hidden")}
label="Open" label="Open"
options={options} options={options}
vimMode={vimMode} vimMode={vimMode}
@ -99,8 +114,19 @@ export function PageNavigator({
return phrase; return phrase;
}} }}
onKeyPress={(key, text) => { onKeyPress={(key, text) => {
if (mode === "page" && key === "^" && text === "^") { // Pages cannot start with ^, as documented in Page Name Rules
if (key === "^" && text === "^") {
switch(mode) {
case "page":
onModeSwitch("meta"); onModeSwitch("meta");
break;
case "meta":
onModeSwitch("all");
break;
case "all":
onModeSwitch("page");
break;
}
} }
}} }}
preFilter={(options, phrase) => { preFilter={(options, phrase) => {
@ -123,19 +149,23 @@ export function PageNavigator({
return !pageMeta.tags?.includes("template") && return !pageMeta.tags?.includes("template") &&
!pageMeta.tags?.includes("meta"); !pageMeta.tags?.includes("meta");
}); });
return options; } else if (mode === "meta") {
} else {
// Filter on pages tagged with "template" or "meta" // Filter on pages tagged with "template" or "meta"
options = options.filter((pageMeta) => { options = options.filter((pageMeta) => {
return pageMeta.tags?.includes("template") || return pageMeta.tags?.includes("template") ||
pageMeta.tags?.includes("meta"); 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} allowNew={true}
helpText={`Press <code>Enter</code> to open the selected ${mode}, or <code>Shift-Enter</code> to create a new ${mode} with this exact name.`} helpText={`Press <code>Enter</code> to open the selected ${pageNoun}, or <code>Shift-Enter</code> to create a new ${pageNoun} with this exact name.`}
newHint={`Create ${mode}`} newHint={`Create ${pageNoun}`}
completePrefix={completePrefix} completePrefix={completePrefix}
onSelect={(opt) => { onSelect={(opt) => {
onNavigate(opt?.ref || opt?.name); onNavigate(opt?.ref || opt?.name);

View File

@ -263,7 +263,7 @@ export function editorSyscalls(client: Client): SysCallMapping {
const cm = vimGetCm(client.editorView)!; const cm = vimGetCm(client.editorView)!;
return Vim.handleEx(cm, exCommand); return Vim.handleEx(cm, exCommand);
}, },
"editor.openPageNavigator": (_ctx, mode: "page" | "meta" = "page") => { "editor.openPageNavigator": (_ctx, mode: "page" | "meta" | "all" = "page") => {
client.startPageNavigate(mode); client.startPageNavigate(mode);
}, },
"editor.openCommandPalette": () => { "editor.openCommandPalette": () => {

View File

@ -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 its 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 `^`.

View File

@ -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. Here on silverbullet.md, we have a decoration like this for pages tagged with #plug: [[Plugs/Emoji]] and [[Plugs/Git]] for instance.
# Supported decorations # Supported decorations
For now theres 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, youll see its prefixed with a 🎄: [[Page Decorations]] * `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, youll see its 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. Later, more such decorations may be added.

View File

@ -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 * `Home`: moves to the start of the list
* `End`: moves to the end of the list * `End`: moves to the end of the list
* `Escape`: closes the page picker UI * `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 # 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. 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.