import { isMacLike, safeRun } from "../common/util.ts"; import { Confirm, Prompt } from "./components/basic_modals.tsx"; import { CommandPalette } from "./components/command_palette.tsx"; import { FilterList } from "./components/filter.tsx"; import { PageNavigator } from "./components/page_navigator.tsx"; import { TopBar } from "./components/top_bar.tsx"; import reducer from "./reducer.ts"; import { Action, AppViewState, initialViewState } from "./types.ts"; import { BookIcon, HomeIcon, preactRender, RefreshCwIcon, runScopeHandlers, TerminalIcon, useEffect, useReducer, } from "./deps.ts"; import type { Client } from "./client.ts"; import { Panel } from "./components/panel.tsx"; import { h } from "./deps.ts"; import { async } from "https://cdn.skypack.dev/-/regenerator-runtime@v0.13.9-4Dxus9nU31cBsHxnWq2H/dist=es2020,mode=imports/optimized/regenerator-runtime.js"; export class MainUI { viewState: AppViewState = initialViewState; viewDispatch: (action: Action) => void = () => {}; constructor(private editor: Client) { // Make keyboard shortcuts work even when the editor is in read only mode or not focused globalThis.addEventListener("keydown", (ev) => { if (!editor.editorView.hasFocus) { if ((ev.target as any).closest(".cm-editor")) { // In some cm element, let's back out return; } if (runScopeHandlers(editor.editorView, ev, "editor")) { ev.preventDefault(); } } }); globalThis.addEventListener("touchstart", (ev) => { // Launch the page picker on a two-finger tap if (ev.touches.length === 2) { ev.stopPropagation(); ev.preventDefault(); this.viewDispatch({ type: "start-navigate" }); } // Launch the command palette using a three-finger tap if (ev.touches.length === 3) { ev.stopPropagation(); ev.preventDefault(); this.viewDispatch({ type: "show-palette", context: editor.getContext(), }); } }); } ViewComponent() { const [viewState, dispatch] = useReducer(reducer, initialViewState); this.viewState = viewState; this.viewDispatch = dispatch; const editor = this.editor; useEffect(() => { if (viewState.currentPage) { document.title = viewState.currentPage; } }, [viewState.currentPage]); useEffect(() => { editor.tweakEditorDOM( editor.editorView.contentDOM, ); }, [viewState.uiOptions.forcedROMode]); useEffect(() => { this.editor.rebuildEditorState(); this.editor.dispatchAppEvent("editor:modeswitch"); }, [viewState.uiOptions.vimMode]); useEffect(() => { document.documentElement.dataset.theme = viewState.uiOptions.darkMode ? "dark" : "light"; }, [viewState.uiOptions.darkMode]); useEffect(() => { // Need to dispatch a resize event so that the top_bar can pick it up globalThis.dispatchEvent(new Event("resize")); }, [viewState.panels]); return ( <> {viewState.showPageNavigator && ( { dispatch({ type: "stop-navigate" }); setTimeout(() => { editor.focus(); }); if (page) { safeRun(async () => { await editor.navigate(page); }); } }} /> )} {viewState.showCommandPalette && ( { dispatch({ type: "hide-palette" }); setTimeout(() => { editor.focus(); }); if (cmd) { dispatch({ type: "command-run", command: cmd.command.name }); cmd .run() .catch((e: any) => { console.error("Error running command", e.message); }) .then(() => { // Always be focusing the editor after running a command editor.focus(); }); } }} commands={editor.getCommandsByContext(viewState)} vimMode={viewState.uiOptions.vimMode} darkMode={viewState.uiOptions.darkMode} completer={editor.miniEditorComplete.bind(editor)} recentCommands={viewState.recentCommands} /> )} {viewState.showFilterBox && ( )} {viewState.showPrompt && ( { dispatch({ type: "hide-prompt" }); viewState.promptCallback!(value); }} /> )} {viewState.showConfirm && ( { dispatch({ type: "hide-confirm" }); viewState.confirmCallback!(value); }} /> )} { if (!newName) { // Always move cursor to the start of the page editor.editorView.dispatch({ selection: { anchor: 0 }, }); editor.focus(); return; } console.log("Now renaming page to...", newName); await editor.system.system.loadedPlugs.get("index")!.invoke( "renamePageCommand", [{ page: newName }], ); editor.focus(); }} actionButtons={[ ...window.silverBulletConfig.supportOnlineMode === "true" ? [{ icon: RefreshCwIcon, description: this.editor.syncMode ? "Currently in sync mode: switch to online mode" : "Currently in online mode: switch to sync mode", class: this.editor.syncMode ? "sb-enabled" : undefined, callback: () => { (async () => { const newValue = !this.editor.syncMode; if (newValue) { if ( await this.editor.confirm( "This will enable local sync. Are you sure?", ) ) { localStorage.setItem("syncMode", "true"); location.reload(); } } else { if ( await this.editor.confirm( "This will disable local sync. Are you sure?", ) ) { localStorage.removeItem("syncMode"); location.reload(); } } })().catch(console.error); }, }] : [], { icon: HomeIcon, description: `Go home (Alt-h)`, callback: () => { editor.navigate(""); }, href: "", }, { icon: BookIcon, description: `Open page (${isMacLike() ? "Cmd-k" : "Ctrl-k"})`, callback: () => { dispatch({ type: "start-navigate" }); editor.space.updatePageList(); }, }, { icon: TerminalIcon, description: `Run command (${isMacLike() ? "Cmd-/" : "Ctrl-/"})`, callback: () => { dispatch({ type: "show-palette", context: editor.getContext(), }); }, }, ]} rhs={!!viewState.panels.rhs.mode && (
)} lhs={!!viewState.panels.lhs.mode && (
)} />
{!!viewState.panels.lhs.mode && ( )}
{!!viewState.panels.rhs.mode && ( )}
{!!viewState.panels.modal.mode && (
)} {!!viewState.panels.bhs.mode && (
)} ); } render(container: Element) { // const ViewComponent = this.ui.ViewComponent.bind(this.ui); preactRender(h(this.ViewComponent.bind(this), {}), container); } }