Work on #587: revamped templates

This commit is contained in:
Zef Hemel
2023-12-21 18:38:02 +01:00
parent c38e6cfc25
commit 70ef6ed9da
42 changed files with 664 additions and 486 deletions
+18 -13
View File
@@ -7,7 +7,7 @@ import {
SyntaxNode,
syntaxTree,
} from "../common/deps.ts";
import { fileMetaToPageMeta, Space } from "./space.ts";
import { Space } from "./space.ts";
import { FilterOption } from "./types.ts";
import { ensureSettingsAndIndex } from "../common/util.ts";
import { EventHook } from "../plugos/hooks/event.ts";
@@ -44,7 +44,6 @@ import { IndexedDBKvPrimitives } from "../plugos/lib/indexeddb_kv_primitives.ts"
import { DataStoreMQ } from "../plugos/lib/mq.datastore.ts";
import { DataStoreSpacePrimitives } from "../common/spaces/datastore_space_primitives.ts";
import {
encryptedFileExt,
EncryptedSpacePrimitives,
} from "../common/spaces/encrypted_space_primitives.ts";
const frontMatterRegex = /^---\n(([^\n]|\n)*?)---\n/;
@@ -63,7 +62,6 @@ declare global {
}
}
// TODO: Oh my god, need to refactor this
export class Client {
system!: ClientSystem;
editorView!: EditorView;
@@ -501,14 +499,14 @@ export class Client {
},
);
this.eventHook.addLocalListener("file:listed", (fileList: FileMeta[]) => {
this.ui.viewDispatch({
type: "pages-listed",
pages: fileList.filter(this.space.isListedPage).map(
fileMetaToPageMeta,
),
});
});
// this.eventHook.addLocalListener("file:listed", (fileList: FileMeta[]) => {
// this.ui.viewDispatch({
// type: "update-all-pages",
// pages: fileList.filter(this.space.isListedPage).map(
// fileMetaToPageMeta,
// ),
// });
// });
this.space.watch();
@@ -593,6 +591,13 @@ export class Client {
);
}
async startPageNavigate() {
// Fetch all pages from the index
const pages = await this.system.queryObjects<PageMeta>("page", {});
// Then show the page navigator
this.ui.viewDispatch({ type: "start-navigate", pages });
}
private progressTimeout?: number;
showProgress(progressPerc: number) {
this.ui.viewDispatch({
@@ -719,9 +724,9 @@ export class Client {
if (currentNode) {
let node: SyntaxNode | null = currentNode;
do {
if (node.name === "FencedCode") {
if (node.name === "FencedCode" || node.name === "FrontMatter") {
const body = editorState.sliceDoc(node.from + 3, node.to - 3);
parentNodes.push(`FencedCode:${body}`);
parentNodes.push(`${node.name}:${body}`);
} else {
parentNodes.push(node.name);
}
+10 -1
View File
@@ -40,6 +40,7 @@ import { codeWidgetSyscalls } from "./syscalls/code_widget.ts";
import { clientCodeWidgetSyscalls } from "./syscalls/client_code_widget.ts";
import { KVPrimitivesManifestCache } from "../plugos/manifest_cache.ts";
import { deepObjectMerge } from "$sb/lib/json.ts";
import { Query } from "$sb/types.ts";
const plugNameExtractRegex = /\/(.+)\.plug\.js$/;
@@ -238,6 +239,14 @@ export class ClientSystem {
}
localSyscall(name: string, args: any[]) {
return this.system.localSyscall("[local]", name, args);
return this.system.localSyscall("editor", name, args);
}
queryObjects<T>(tag: string, query: Query): Promise<T[]> {
return this.system.localSyscall(
"index",
"system.invokeFunction",
["queryObjects", tag, query],
);
}
}
+2 -6
View File
@@ -186,15 +186,11 @@ export function FilterList({
<Icon width={16} height={16} />
</span>
)}
<span className="sb-name" // dangerouslySetInnerHTML={{
// __html: option?.result?.indexes
// ? fuzzysort.highlight(option.result, "<b>", "</b>")!
// : escapeHtml(option.name),
// }}
>
<span className="sb-name">
{option.name}
</span>
{option.hint && <span className="sb-hint">{option.hint}</span>}
<div className="sb-description">{option.description}</div>
</div>
))
: null}
+15 -2
View File
@@ -14,7 +14,12 @@ export const fuzzySearchAndSort = (
return arr.sort((a, b) => (a.orderId || 0) - (b.orderId || 0));
}
const enrichedArr: FuseOption[] = arr.map((item) => {
return { ...item, baseName: item.name.split("/").pop()! };
return {
...item,
baseName: item.name.split("/").pop()!,
tags: item.tags?.join(" "),
aliases: item.aliases?.join(" "),
};
});
const fuse = new Fuse(enrichedArr, {
keys: [{
@@ -23,13 +28,21 @@ export const fuzzySearchAndSort = (
}, {
name: "baseName",
weight: 0.7,
}, {
name: "displayName",
weight: 0.3,
}, {
name: "tags",
weight: 0.1,
}, {
name: "aliases",
weight: 0.7,
}],
includeScore: true,
shouldSort: true,
isCaseSensitive: false,
threshold: 0.6,
sortFn: (a, b): number => {
// console.log(a, b);
if (a.score === b.score) {
const aOrder = enrichedArr[a.idx].orderId || 0;
const bOrder = enrichedArr[b.idx].orderId || 0;
+18
View File
@@ -36,8 +36,26 @@ export function PageNavigator({
if (isFederationPath(pageMeta.name)) {
orderId = Math.round(orderId / 10); // Just 10x lower the timestamp to push them down, should work
}
let description: string | undefined;
let aliases: string[] = [];
if (pageMeta.displayName) {
aliases.push(pageMeta.displayName);
}
if (Array.isArray(pageMeta.aliases)) {
aliases = aliases.concat(pageMeta.aliases);
}
if (aliases.length > 0) {
description = "(a.k.a. " + aliases.join(", ") + ") ";
}
if (pageMeta.tags.length > 1) {
// Every page has the "page" tag, so it only gets interesting beyond that
const interestingTags = pageMeta.tags.filter((tag) => tag !== "page");
description = (description || "") +
interestingTags.map((tag) => `#${tag}`).join(" ");
}
options.push({
...pageMeta,
description,
orderId: orderId,
});
}
+1 -3
View File
@@ -178,9 +178,7 @@ export function createEditorState(
key: "Ctrl-k",
mac: "Cmd-k",
run: (): boolean => {
client.ui.viewDispatch({ type: "start-navigate" });
client.space.updatePageList();
client.startPageNavigate().catch(console.error);
return true;
},
},
+27 -28
View File
@@ -44,7 +44,7 @@ export class MainUI {
if (ev.touches.length === 2) {
ev.stopPropagation();
ev.preventDefault();
this.viewDispatch({ type: "start-navigate" });
client.startPageNavigate().catch(console.error);
}
// Launch the command palette using a three-finger tap
if (ev.touches.length === 3) {
@@ -63,7 +63,7 @@ export class MainUI {
this.viewState = viewState;
this.viewDispatch = dispatch;
const editor = this.client;
const client = this.client;
useEffect(() => {
if (viewState.currentPage) {
@@ -72,8 +72,8 @@ export class MainUI {
}, [viewState.currentPage]);
useEffect(() => {
editor.tweakEditorDOM(
editor.editorView.contentDOM,
client.tweakEditorDOM(
client.editorView.contentDOM,
);
}, [viewState.uiOptions.forcedROMode]);
@@ -98,18 +98,18 @@ export class MainUI {
{viewState.showPageNavigator && (
<PageNavigator
allPages={viewState.allPages}
currentPage={editor.currentPage}
completer={editor.miniEditorComplete.bind(editor)}
currentPage={client.currentPage}
completer={client.miniEditorComplete.bind(client)}
vimMode={viewState.uiOptions.vimMode}
darkMode={viewState.uiOptions.darkMode}
onNavigate={(page) => {
dispatch({ type: "stop-navigate" });
setTimeout(() => {
editor.focus();
client.focus();
});
if (page) {
safeRun(async () => {
await editor.navigate(page);
await client.navigate(page);
});
}
}}
@@ -120,7 +120,7 @@ export class MainUI {
onTrigger={(cmd) => {
dispatch({ type: "hide-palette" });
setTimeout(() => {
editor.focus();
client.focus();
});
if (cmd) {
dispatch({ type: "command-run", command: cmd.command.name });
@@ -131,14 +131,14 @@ export class MainUI {
})
.then(() => {
// Always be focusing the editor after running a command
editor.focus();
client.focus();
});
}
}}
commands={editor.getCommandsByContext(viewState)}
commands={client.getCommandsByContext(viewState)}
vimMode={viewState.uiOptions.vimMode}
darkMode={viewState.uiOptions.darkMode}
completer={editor.miniEditorComplete.bind(editor)}
completer={client.miniEditorComplete.bind(client)}
recentCommands={viewState.recentCommands}
/>
)}
@@ -150,7 +150,7 @@ export class MainUI {
vimMode={viewState.uiOptions.vimMode}
darkMode={viewState.uiOptions.darkMode}
allowNew={false}
completer={editor.miniEditorComplete.bind(editor)}
completer={client.miniEditorComplete.bind(client)}
helpText={viewState.filterBoxHelpText}
onSelect={viewState.filterBoxOnSelect}
/>
@@ -161,7 +161,7 @@ export class MainUI {
defaultValue={viewState.promptDefaultValue}
vimMode={viewState.uiOptions.vimMode}
darkMode={viewState.uiOptions.darkMode}
completer={editor.miniEditorComplete.bind(editor)}
completer={client.miniEditorComplete.bind(client)}
callback={(value) => {
dispatch({ type: "hide-prompt" });
viewState.promptCallback!(value);
@@ -186,25 +186,25 @@ export class MainUI {
vimMode={viewState.uiOptions.vimMode}
darkMode={viewState.uiOptions.darkMode}
progressPerc={viewState.progressPerc}
completer={editor.miniEditorComplete.bind(editor)}
completer={client.miniEditorComplete.bind(client)}
onClick={() => {
editor.editorView.scrollDOM.scrollTop = 0;
client.editorView.scrollDOM.scrollTop = 0;
}}
onRename={async (newName) => {
if (!newName) {
// Always move cursor to the start of the page
editor.editorView.dispatch({
client.editorView.dispatch({
selection: { anchor: 0 },
});
editor.focus();
client.focus();
return;
}
console.log("Now renaming page to...", newName);
await editor.system.system.loadedPlugs.get("index")!.invoke(
await client.system.system.loadedPlugs.get("index")!.invoke(
"renamePageCommand",
[{ page: newName }],
);
editor.focus();
client.focus();
}}
actionButtons={[
...!window.silverBulletConfig.syncOnly
@@ -242,7 +242,7 @@ export class MainUI {
icon: HomeIcon,
description: `Go to the index page (Alt-h)`,
callback: () => {
editor.navigate("");
client.navigate("");
},
href: "",
},
@@ -250,8 +250,7 @@ export class MainUI {
icon: BookIcon,
description: `Open page (${isMacLike() ? "Cmd-k" : "Ctrl-k"})`,
callback: () => {
dispatch({ type: "start-navigate" });
editor.space.updatePageList();
client.startPageNavigate().catch(console.error);
},
},
{
@@ -260,7 +259,7 @@ export class MainUI {
callback: () => {
dispatch({
type: "show-palette",
context: editor.getContext(),
context: client.getContext(),
});
},
},
@@ -280,11 +279,11 @@ export class MainUI {
/>
<div id="sb-main">
{!!viewState.panels.lhs.mode && (
<Panel config={viewState.panels.lhs} editor={editor} />
<Panel config={viewState.panels.lhs} editor={client} />
)}
<div id="sb-editor" />
{!!viewState.panels.rhs.mode && (
<Panel config={viewState.panels.rhs} editor={editor} />
<Panel config={viewState.panels.rhs} editor={client} />
)}
</div>
{!!viewState.panels.modal.mode && (
@@ -292,12 +291,12 @@ export class MainUI {
className="sb-modal"
style={{ inset: `${viewState.panels.modal.mode}px` }}
>
<Panel config={viewState.panels.modal} editor={editor} />
<Panel config={viewState.panels.modal} editor={client} />
</div>
)}
{!!viewState.panels.bhs.mode && (
<div className="sb-bhs">
<Panel config={viewState.panels.bhs} editor={editor} />
<Panel config={viewState.panels.bhs} editor={client} />
</div>
)}
</>
+11 -14
View File
@@ -11,7 +11,7 @@ export default function reducer(
...state,
isLoading: true,
currentPage: action.name,
panels: {
panels: state.currentPage === action.name ? state.panels : {
...state.panels,
// Hide these by default to avoid flickering
top: {},
@@ -45,19 +45,7 @@ export default function reducer(
...state,
syncFailures: action.syncSuccess ? 0 : state.syncFailures + 1,
};
case "start-navigate":
return {
...state,
showPageNavigator: true,
showCommandPalette: false,
showFilterBox: false,
};
case "stop-navigate":
return {
...state,
showPageNavigator: false,
};
case "pages-listed": {
case "start-navigate": {
// Let's move over any "lastOpened" times to the "allPages" list
const oldPageMeta = new Map(
[...state.allPages].map((pm) => [pm.name, pm]),
@@ -71,8 +59,17 @@ export default function reducer(
return {
...state,
allPages: action.pages,
showPageNavigator: true,
showCommandPalette: false,
showFilterBox: false,
};
}
case "stop-navigate":
return {
...state,
showPageNavigator: false,
};
case "show-palette": {
return {
...state,
+9 -3
View File
@@ -114,9 +114,15 @@
color: var(--modal-selected-option-color);
}
.sb-result-list .sb-hint {
color: var(--modal-hint-color);
background-color: var(--modal-hint-background-color);
.sb-result-list {
.sb-hint {
color: var(--modal-hint-color);
background-color: var(--modal-hint-background-color);
}
.sb-description {
color: var(--modal-description-color);
}
}
}
+5 -1
View File
@@ -61,6 +61,10 @@
position: relative;
top: 3px;
}
.sb-description {
font-size: 75%;
}
}
.sb-option,
@@ -81,4 +85,4 @@
padding-bottom: 3px;
border-radius: 5px;
}
}
}
+2
View File
@@ -36,6 +36,7 @@ html {
--modal-selected-option-color: #eee;
--modal-hint-background-color: #212476;
--modal-hint-color: #eee;
--modal-description-color: #aaa;
--notifications-background-color: inherit;
--notifications-border-color: rgb(41, 41, 41);
@@ -153,6 +154,7 @@ html[data-theme="dark"] {
--modal-selected-option-color: #eee;
--modal-hint-background-color: #212476;
--modal-hint-color: #eee;
--modal-description-color: #aaa;
--notifications-background-color: #333;
--notifications-border-color: rgb(197, 197, 197);
+2 -2
View File
@@ -5,6 +5,7 @@ import { AppCommand } from "./hooks/command.ts";
// Used by FilterBox
export type FilterOption = {
name: string;
description?: string;
orderId?: number;
hint?: string;
} & Record<string, any>;
@@ -111,11 +112,10 @@ export const initialViewState: AppViewState = {
export type Action =
| { type: "page-loaded"; meta: PageMeta }
| { type: "page-loading"; name: string }
| { type: "pages-listed"; pages: PageMeta[] }
| { type: "page-changed" }
| { type: "page-saved" }
| { type: "sync-change"; syncSuccess: boolean }
| { type: "start-navigate" }
| { type: "start-navigate"; pages: PageMeta[] }
| { type: "stop-navigate" }
| {
type: "update-commands";