Work on #587: revamped templates
This commit is contained in:
+18
-13
@@ -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
@@ -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],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user