diff --git a/plug-api/silverbullet-syscall/editor.ts b/plug-api/silverbullet-syscall/editor.ts index c80bb0c1..eb2e081d 100644 --- a/plug-api/silverbullet-syscall/editor.ts +++ b/plug-api/silverbullet-syscall/editor.ts @@ -73,6 +73,15 @@ export function openUrl(url: string, existingWindow = false): Promise { return syscall("editor.openUrl", url, existingWindow); } +/** + * This is calling the `go()` method from the History Web API. + * @param delta Position in history to move to relative to the current page, + * where a negative value moves backwards, and positive forwards + */ +export function goHistory(delta: number): Promise { + return syscall("editor.goHistory", delta); +} + // Force the client to download the file in dataUrl with filename as file name export function downloadFile(filename: string, dataUrl: string): Promise { return syscall("editor.downloadFile", filename, dataUrl); diff --git a/plugs/editor/editor.plug.yaml b/plugs/editor/editor.plug.yaml index d68af11f..b7f473b2 100644 --- a/plugs/editor/editor.plug.yaml +++ b/plugs/editor/editor.plug.yaml @@ -89,6 +89,14 @@ functions: command: name: "Navigate: To URL" hide: true + navigateBack: + path: "./navigate.ts:navigateBack" + command: + name: "Navigate: Back in History" + navigateForward: + path: "./navigate.ts:navigateForward" + command: + name: "Navigate: Forward in History" # Text editing commands quoteSelectionCommand: @@ -185,7 +193,6 @@ functions: path: ./embed.ts:embedWidget codeWidget: embed - # Vim toggleVimMode: path: "./vim.ts:toggleVimMode" @@ -302,4 +309,4 @@ functions: name: "Flash: Custom Message" hide: true contexts: - - internal \ No newline at end of file + - internal diff --git a/plugs/editor/navigate.ts b/plugs/editor/navigate.ts index c03ccce1..4aa7d877 100644 --- a/plugs/editor/navigate.ts +++ b/plugs/editor/navigate.ts @@ -140,3 +140,11 @@ export async function navigateToPage(_cmdDef: any, pageName: string) { export async function navigateToURL(_cmdDef: any, url: string) { await editor.openUrl(url, false); } + +export async function navigateBack() { + await editor.goHistory(-1); +} + +export async function navigateForward() { + await editor.goHistory(1); +} diff --git a/web/components/top_bar.tsx b/web/components/top_bar.tsx index 7f4f8cdc..3674bfd5 100644 --- a/web/components/top_bar.tsx +++ b/web/components/top_bar.tsx @@ -10,6 +10,7 @@ export type ActionButton = { class?: string; callback: () => void; href?: string; + mobile?: boolean; }; export function TopBar({ @@ -17,6 +18,7 @@ export function TopBar({ unsavedChanges, syncFailures, isLoading, + isMobile, notifications, onRename, actionButtons, @@ -32,6 +34,7 @@ export function TopBar({ unsavedChanges: boolean; syncFailures: number; isLoading: boolean; + isMobile: boolean; notifications: Notification[]; darkMode: boolean; vimMode: boolean; diff --git a/web/editor_ui.tsx b/web/editor_ui.tsx index 742707eb..79f2d3a4 100644 --- a/web/editor_ui.tsx +++ b/web/editor_ui.tsx @@ -192,6 +192,7 @@ export class MainUI { syncFailures={viewState.syncFailures} unsavedChanges={viewState.unsavedChanges} isLoading={viewState.isLoading} + isMobile={viewState.isMobile} vimMode={viewState.uiOptions.vimMode} darkMode={viewState.uiOptions.darkMode} progressPerc={viewState.progressPerc} @@ -248,7 +249,9 @@ export class MainUI { }, }] : [], - ...viewState.settings.actionButtons.map((button) => { + ...viewState.settings.actionButtons + .filter((button) => (typeof button.mobile === "undefined") || (button.mobile === viewState.isMobile)) + .map((button) => { const parsedCommand = parseCommand(button.command); let featherIcon = (featherIcons as any)[kebabToCamel(button.icon)]; diff --git a/web/reducer.ts b/web/reducer.ts index 8aba3751..78048389 100644 --- a/web/reducer.ts +++ b/web/reducer.ts @@ -18,10 +18,12 @@ export default function reducer( bottom: {}, }, }; - case "page-loaded": + case "page-loaded": { + const mouseDetected = window.matchMedia("(any-pointer:fine)").matches; return { ...state, isLoading: false, + isMobile: !mouseDetected, allPages: state.allPages.map((pageMeta) => pageMeta.name === action.meta.name ? { ...pageMeta, lastOpened: Date.now() } @@ -30,6 +32,7 @@ export default function reducer( currentPage: action.meta.name, currentPageMeta: action.meta, }; + } case "page-changed": return { ...state, diff --git a/web/syscalls/editor.ts b/web/syscalls/editor.ts index 24f92a29..31fa0f76 100644 --- a/web/syscalls/editor.ts +++ b/web/syscalls/editor.ts @@ -73,6 +73,9 @@ export function editorSyscalls(client: Client): SysCallMapping { location.href = url; } }, + "editor.goHistory": (_ctx, delta: number) => { + window.history.go(delta); + }, "editor.downloadFile": (_ctx, filename: string, dataUrl: string) => { const link = document.createElement("a"); link.href = dataUrl; diff --git a/web/types.ts b/web/types.ts index 0bea4fd0..ef498c0f 100644 --- a/web/types.ts +++ b/web/types.ts @@ -32,6 +32,7 @@ export type ActionButton = { description?: string; command: string; args?: any[]; + mobile?: boolean; }; export type EmojiConfig = { @@ -62,6 +63,7 @@ export type AppViewState = { allPages: PageMeta[]; isLoading: boolean; + isMobile: boolean; showPageNavigator: boolean; showCommandPalette: boolean; showCommandPaletteContext?: string; @@ -116,6 +118,7 @@ export const initialViewState: AppViewState = { darkMode: false, forcedROMode: false, }, + isMobile: false, panels: { lhs: {}, rhs: {}, diff --git a/website/SETTINGS.md b/website/SETTINGS.md index 260e2396..1d87d1fb 100644 --- a/website/SETTINGS.md +++ b/website/SETTINGS.md @@ -27,6 +27,10 @@ actionButtons: - icon: terminal command: "{[Open Command Palette]}" description: Run command +- icon: arrow-left + command: "{[Navigate: Back in History]}" + description: "Go to the previous page" + mobile: true # Only show on mobile devices, set to false to show only on desktop # Override keyboard shortcuts and command priority shortcuts: