From 5e1582fc391ce453cb364d942d5c0801bcfa6b2e Mon Sep 17 00:00:00 2001 From: PJ Date: Sat, 20 Jun 2026 14:30:07 -0400 Subject: [PATCH] feat(ui): guard desktop-only actions with a clear browser-preview message --- src/App.tsx | 16 ++++++++++++++++ src/components/Dock.tsx | 6 ++---- src/ipc.ts | 2 ++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 4a61e4c..eefb22a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,10 @@ import { useBook } from "./store/useBook"; import type { Book } from "./model/book"; import { chooseSavePath, openBook, writeBook } from "./project"; import { exportEpub, exportPdf } from "./export/exporters"; +import { isDesktop } from "./ipc"; + +const DESKTOP_ONLY = + 'This runs in the desktop app only — open the window from "pnpm tauri dev" (you are viewing the browser preview).'; function App() { const [dock, setDock] = useState(true); @@ -31,6 +35,10 @@ function App() { const chapter = chapters[idx]; const handleSave = useCallback(async () => { + if (!isDesktop) { + setNotice(DESKTOP_ONLY); + return; + } try { const { book, path } = useBook.getState(); const target = path ?? (await chooseSavePath(book)); @@ -44,6 +52,10 @@ function App() { }, [markSaved]); const handleOpen = useCallback(async () => { + if (!isDesktop) { + setNotice(DESKTOP_ONLY); + return; + } try { const result = await openBook(); if (result) replaceBook(result.book, result.path); @@ -54,6 +66,10 @@ function App() { const runExport = async (label: string, fn: (book: Book) => Promise) => { setExportOpen(false); + if (!isDesktop) { + setNotice(DESKTOP_ONLY); + return; + } try { await fn(useBook.getState().book); } catch (e) { diff --git a/src/components/Dock.tsx b/src/components/Dock.tsx index 79a9a69..aa9f6f9 100644 --- a/src/components/Dock.tsx +++ b/src/components/Dock.tsx @@ -3,7 +3,7 @@ import { generateHTML } from "@tiptap/core"; import { useBook } from "../store/useBook"; import { editorExtensions } from "../editor/extensions"; import { bookToPdfInputs } from "../export/typst"; -import { compilePdf } from "../ipc"; +import { compilePdf, isDesktop } from "../ipc"; import { PdfPreview } from "./PdfPreview"; const TRIM_LABEL: Record = { @@ -13,10 +13,8 @@ const TRIM_LABEL: Record = { a5: "A5", }; -const inTauri = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window; - export function Dock() { - return inTauri ? : ; + return isDesktop ? : ; } function PdfDock() { diff --git a/src/ipc.ts b/src/ipc.ts index 4bd4088..09cd2e6 100644 --- a/src/ipc.ts +++ b/src/ipc.ts @@ -1,5 +1,7 @@ import { invoke } from "@tauri-apps/api/core"; +export const isDesktop = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window; + export interface ImageInput { path: string; data: string;