From 8989f27159ca99b60b6bbf74fe1be56ec69d70f3 Mon Sep 17 00:00:00 2001 From: gitgrahamdunn Date: Mon, 9 Mar 2026 16:02:20 -0600 Subject: [PATCH] Refine viewer adapter boundary and stabilize desktop tests --- apps/desktop/src/App.tsx | 2 ++ .../desktop/src/components/PdfViewer.test.tsx | 3 +++ apps/desktop/src/components/PdfViewer.tsx | 17 ++++++++------- apps/desktop/src/lib/viewerRenderer.ts | 6 ++++++ apps/desktop/tsconfig.json | 21 ++++++++++++++++--- apps/desktop/vite.config.ts | 7 +++++-- apps/desktop/vitest.setup.ts | 2 +- 7 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 apps/desktop/src/lib/viewerRenderer.ts diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx index f5a8dd3..0df7de1 100644 --- a/apps/desktop/src/App.tsx +++ b/apps/desktop/src/App.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'; import { tauriGateway } from './lib/tauriGateway'; import { PdfViewer } from './components/PdfViewer'; import { ErrorBoundary } from './components/ErrorBoundary'; +import { createViewerRenderer } from './lib/viewerRenderer'; import type { ExtractedPageTextRecord, RecentDocumentView } from '@gitplant/shared-types'; export function App() { @@ -90,6 +91,7 @@ export function App() { bytes={bytes} overlayBytes={overlayBytes} title={title} + rendererFactory={createViewerRenderer} onPageCount={(n) => { if (currentRevisionId) void tauriGateway.updatePageCount(currentRevisionId, n); }} diff --git a/apps/desktop/src/components/PdfViewer.test.tsx b/apps/desktop/src/components/PdfViewer.test.tsx index 399128c..bee157e 100644 --- a/apps/desktop/src/components/PdfViewer.test.tsx +++ b/apps/desktop/src/components/PdfViewer.test.tsx @@ -21,7 +21,10 @@ describe('PdfViewer states', () => { it('ui-level code avoids direct pdfjs imports', () => { const appSource = fs.readFileSync(path.resolve(__dirname, '../App.tsx'), 'utf8'); + const viewerSource = fs.readFileSync(path.resolve(__dirname, './PdfViewer.tsx'), 'utf8'); expect(appSource).not.toContain('pdfjs-dist'); expect(appSource).not.toContain('@gitplant/viewer-pdfjs'); + expect(viewerSource).not.toContain('pdfjs-dist'); + expect(viewerSource).not.toContain('@gitplant/viewer-pdfjs'); }); }); diff --git a/apps/desktop/src/components/PdfViewer.tsx b/apps/desktop/src/components/PdfViewer.tsx index b378949..b0d0301 100644 --- a/apps/desktop/src/components/PdfViewer.tsx +++ b/apps/desktop/src/components/PdfViewer.tsx @@ -1,16 +1,16 @@ import { useEffect, useMemo, useState } from 'react'; -import { createBaseRenderScene, withOverlayPdfLayer } from '@gitplant/viewer-core'; -import { PdfjsRendererAdapter } from '@gitplant/viewer-pdfjs'; +import { createBaseRenderScene, withOverlayPdfLayer, type ViewerRenderer } from '@gitplant/viewer-core'; type Props = { bytes: Uint8Array | null; title: string; overlayBytes?: Uint8Array | null; onPageCount?: (n: number) => void; + rendererFactory?: () => ViewerRenderer; }; -export function PdfViewer({ bytes, title, overlayBytes, onPageCount }: Props) { - const renderer = useMemo(() => new PdfjsRendererAdapter(), []); +export function PdfViewer({ bytes, title, overlayBytes, onPageCount, rendererFactory }: Props) { + const renderer = useMemo(() => (rendererFactory ? rendererFactory() : null), [rendererFactory]); const [page, setPage] = useState(1); const [pageCount, setPageCount] = useState(0); const [zoom, setZoom] = useState(1); @@ -20,7 +20,7 @@ export function PdfViewer({ bytes, title, overlayBytes, onPageCount }: Props) { useEffect(() => { void (async () => { - if (!bytes) return; + if (!bytes || !renderer) return; setState('loading'); try { await renderer.openDocument(bytes); @@ -38,13 +38,13 @@ export function PdfViewer({ bytes, title, overlayBytes, onPageCount }: Props) { } })(); return () => { - void renderer.closeDocument(); + if (renderer) void renderer.closeDocument(); }; - }, [bytes, overlayBytes]); + }, [bytes, overlayBytes, renderer]); useEffect(() => { void (async () => { - if (!bytes || state === 'error' || pageCount === 0) return; + if (!bytes || !renderer || state === 'error' || pageCount === 0) return; setState('loading'); try { const nextScene = { @@ -63,6 +63,7 @@ export function PdfViewer({ bytes, title, overlayBytes, onPageCount }: Props) { }, [page, zoom]); if (!bytes) return
Select a PDF to view.
; + if (!renderer) return
Viewer renderer unavailable.
; if (state === 'error') return
Failed to render document.
; return (
diff --git a/apps/desktop/src/lib/viewerRenderer.ts b/apps/desktop/src/lib/viewerRenderer.ts new file mode 100644 index 0000000..6f28e48 --- /dev/null +++ b/apps/desktop/src/lib/viewerRenderer.ts @@ -0,0 +1,6 @@ +import type { ViewerRenderer } from '@gitplant/viewer-core'; +import { PdfjsRendererAdapter } from '@gitplant/viewer-pdfjs'; + +export function createViewerRenderer(): ViewerRenderer { + return new PdfjsRendererAdapter(); +} diff --git a/apps/desktop/tsconfig.json b/apps/desktop/tsconfig.json index e1c9c78..3de9018 100644 --- a/apps/desktop/tsconfig.json +++ b/apps/desktop/tsconfig.json @@ -7,9 +7,24 @@ "strict": true, "baseUrl": ".", "paths": { - "@gitplant/*": ["../../packages/*/src"] + "@gitplant/*": [ + "../../packages/*/src" + ] }, - "types": ["vitest/globals", "@testing-library/jest-dom"] + "types": [ + "vite/client" + ], + "skipLibCheck": true, + "lib": [ + "ES2023", + "DOM" + ] }, - "include": ["src", "vite.config.ts", "vitest.setup.ts"] + "include": [ + "src" + ], + "exclude": [ + "src/**/*.test.ts", + "src/**/*.test.tsx" + ] } diff --git a/apps/desktop/vite.config.ts b/apps/desktop/vite.config.ts index ecc16e2..997711c 100644 --- a/apps/desktop/vite.config.ts +++ b/apps/desktop/vite.config.ts @@ -1,4 +1,7 @@ -import { defineConfig } from 'vite'; +import { defineConfig } from 'vitest/config'; import react from '@vitejs/plugin-react'; -export default defineConfig({ plugins: [react()], test: { environment: 'jsdom', setupFiles: './vitest.setup.ts' } }); +export default defineConfig({ + plugins: [react()], + test: { environment: 'jsdom', setupFiles: './vitest.setup.ts', globals: true } +}); diff --git a/apps/desktop/vitest.setup.ts b/apps/desktop/vitest.setup.ts index 7b0828b..bb02c60 100644 --- a/apps/desktop/vitest.setup.ts +++ b/apps/desktop/vitest.setup.ts @@ -1 +1 @@ -import '@testing-library/jest-dom'; +import '@testing-library/jest-dom/vitest';