Skip to content

Commit 581398d

Browse files
committed
feat!: change from annotation store to plugin store, and sync entire anno state
1 parent fddc3f0 commit 581398d

9 files changed

Lines changed: 219 additions & 190 deletions

File tree

app/page-client-side.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
"use client"
22

3-
import AnnotationStoreTable from "../components/annotation-store/annotation-store-table"
43
import PDFContainer from "../components/pdf-container/pdf-container-dynamic"
4+
import PluginStoreTable from "../components/plugin-store/components/plugin-store-table"
55

66
export default function ClientSideHomePage() {
77
return (
88
<div className="space-y-4">
9-
<AnnotationStoreTable />
9+
<PluginStoreTable />
1010
<PDFContainer url="https://snippet.embedpdf.com/ebook.pdf" />
1111
</div>
1212
)

components/annotation-store/annotation-store-sync.tsx

Lines changed: 0 additions & 41 deletions
This file was deleted.

components/annotation-store/annotation-store-table.tsx

Lines changed: 0 additions & 86 deletions
This file was deleted.

components/pdf-container/pdf-container.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@ import {
1010
} from "@embedpdf/plugin-interaction-manager/react"
1111
import { LoaderPluginPackage } from "@embedpdf/plugin-loader/react"
1212
import { RenderLayer, RenderPluginPackage } from "@embedpdf/plugin-render/react"
13-
import { Scroller, ScrollPluginPackage, ScrollStrategy } from "@embedpdf/plugin-scroll/react"
13+
import { ScrollPluginPackage, ScrollStrategy, Scroller } from "@embedpdf/plugin-scroll/react"
1414
import { SearchLayer, SearchPluginPackage } from "@embedpdf/plugin-search/react"
15-
import { SelectionLayer, SelectionPluginPackage } from "./plugin-selection-2"
15+
import { ThumbnailPluginPackage } from "@embedpdf/plugin-thumbnail/react"
1616
import { TilingLayer, TilingPluginPackage } from "@embedpdf/plugin-tiling/react"
1717
import { Viewport, ViewportPluginPackage } from "@embedpdf/plugin-viewport/react"
1818
import { PinchWrapper, ZoomMode, ZoomPluginPackage } from "@embedpdf/plugin-zoom/react"
1919
import { useRef } from "react"
20-
import AnnotationStoreSync from "../annotation-store/annotation-store-sync"
20+
import PluginStoreSync from "../plugin-store/components/plugin-store-sync"
2121
import { Spinner } from "../shadcn-ui/spinner"
2222
import { AnnotationLayer, AnnotationPluginPackage } from "./plugin-annotation-2"
23+
import { SelectionLayer, SelectionPluginPackage } from "./plugin-selection-2"
2324
import Toolbar from "./toolbar"
2425

2526
const logger = new ConsoleLogger()
@@ -78,6 +79,8 @@ export default function PDFContainer({ url }: PDFContainerProps) {
7879
overlapPx: 2.5,
7980
extraRings: 0,
8081
}),
82+
// register Thumbnail after Scroll, Render
83+
createPluginRegistration(ThumbnailPluginPackage, { width: 100 }),
8184
createPluginRegistration(SelectionPluginPackage),
8285
// register Annotation after InteractionManager, Seletion
8386
createPluginRegistration(AnnotationPluginPackage),
@@ -87,15 +90,16 @@ export default function PDFContainer({ url }: PDFContainerProps) {
8790
createPluginRegistration(ZoomPluginPackage, {
8891
defaultZoomLevel: ZoomMode.Automatic,
8992
}),
93+
// register Search after Scroll, Selection
9094
createPluginRegistration(SearchPluginPackage),
9195
]}
9296
>
9397
{({ pluginsReady }) => {
9498
return (
9599
<GlobalPointerProvider>
96-
<AnnotationStoreSync />
100+
<PluginStoreSync />
97101
<Toolbar data-testid="annotation-toolbar" />
98-
<Viewport className="h-full w-full flex-1 overflow-auto bg-gray-100 select-none">
102+
<Viewport className="h-full w-full flex-1 overflow-hidden bg-gray-100 select-none">
99103
{!pluginsReady && (
100104
<div className="flex h-full w-full items-center justify-center">
101105
<Spinner data-testid="spinner1" />

components/pdf-container/toolbar.tsx

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import useAnnotationStore from "@/hooks/annotation-store/use-annotation-store"
21
import { useExportCapability } from "@embedpdf/plugin-export/react"
3-
import { useZoom } from "@embedpdf/plugin-zoom/react"
2+
import { useZoomCapability } from "@embedpdf/plugin-zoom/react"
43
import {
54
Download,
65
Highlighter,
@@ -11,22 +10,17 @@ import {
1110
ZoomIn,
1211
ZoomOut,
1312
} from "lucide-react"
13+
import usePluginStore from "../plugin-store/hooks/use-plugin-store"
1414

1515
const Toolbar = () => {
16-
const { provides: exportApi } = useExportCapability()
17-
const { provides: zoom } = useZoom()
16+
const { provides: exportCapability } = useExportCapability()
17+
const { provides: zoomCapability } = useZoomCapability()
1818

19-
const {
20-
capability: annotationApi,
21-
activeToolId,
22-
selectedUid,
23-
canUndo,
24-
canRedo,
25-
} = useAnnotationStore()
19+
const { annoCapability, annoState } = usePluginStore()
2620

2721
const handleDelete = () => {
28-
if (selectedUid) {
29-
annotationApi?.deleteAnnotation(selectedUid)
22+
if (annoState?.selectedUid) {
23+
annoCapability?.deleteAnnotation(annoState.selectedUid)
3024
}
3125
}
3226

@@ -41,10 +35,12 @@ const Toolbar = () => {
4135
<button
4236
key={tool.id}
4337
onClick={() => {
44-
annotationApi?.activateTool(tool.id === activeToolId ? null : tool.id)
38+
annoCapability?.activateTool(tool.id === annoState?.activeToolId ? null : tool.id)
4539
}}
4640
className={`rounded-md px-3 py-1 text-sm font-medium transition-colors ${
47-
tool.id === activeToolId ? "bg-blue-500 text-white" : "bg-gray-100 hover:bg-gray-200"
41+
tool.id === annoState?.activeToolId
42+
? "bg-blue-500 text-white"
43+
: "bg-gray-100 hover:bg-gray-200"
4844
}`}
4945
title={tool.id}
5046
>
@@ -55,16 +51,16 @@ const Toolbar = () => {
5551
<div className="h-6 w-px bg-gray-200" />
5652

5753
<button
58-
onClick={() => zoom?.zoomOut()}
59-
disabled={!zoom}
54+
onClick={() => zoomCapability?.zoomOut()}
55+
disabled={!zoomCapability}
6056
className="rounded-md bg-gray-500 px-3 py-1 text-sm font-medium text-white transition-colors hover:bg-gray-600 disabled:cursor-not-allowed disabled:bg-gray-300"
6157
title="Zoom out"
6258
>
6359
<ZoomOut size={18} />
6460
</button>
6561
<button
66-
onClick={() => zoom?.zoomIn()}
67-
disabled={!zoom}
62+
onClick={() => zoomCapability?.zoomIn()}
63+
disabled={!zoomCapability}
6864
className="rounded-md bg-gray-500 px-3 py-1 text-sm font-medium text-white transition-colors hover:bg-gray-600 disabled:cursor-not-allowed disabled:bg-gray-300"
6965
title="Zoom in"
7066
>
@@ -74,16 +70,16 @@ const Toolbar = () => {
7470
<div className="h-6 w-px bg-gray-200" />
7571

7672
<button
77-
onClick={() => annotationApi?.undo()}
78-
disabled={!canUndo}
73+
onClick={() => annoCapability?.undo()}
74+
disabled={!annoState?.canUndo}
7975
className="rounded-md bg-gray-100 px-3 py-1 text-sm font-medium transition-colors hover:bg-gray-200 disabled:cursor-not-allowed disabled:opacity-50"
8076
title="Undo"
8177
>
8278
<Undo2 size={18} />
8379
</button>
8480
<button
85-
onClick={() => annotationApi?.redo()}
86-
disabled={!canRedo}
81+
onClick={() => annoCapability?.redo()}
82+
disabled={!annoState?.canRedo}
8783
className="rounded-md bg-gray-100 px-3 py-1 text-sm font-medium transition-colors hover:bg-gray-200 disabled:cursor-not-allowed disabled:opacity-50"
8884
title="Redo"
8985
>
@@ -93,23 +89,23 @@ const Toolbar = () => {
9389
<div className="h-6 w-px bg-gray-200" />
9490

9591
<button
96-
onClick={() => annotationApi?.exportAnnotationsToJSON?.()}
92+
onClick={() => annoCapability?.exportAnnotationsToJSON?.()}
9793
className="rounded-md bg-blue-500 px-3 py-1 text-sm font-medium text-white transition-colors hover:bg-blue-600"
9894
title="Export Annotations to JSON"
9995
>
10096
Export JSON
10197
</button>
10298
<button
103-
onClick={() => exportApi?.download()}
104-
disabled={!exportApi}
99+
onClick={() => exportCapability?.download()}
100+
disabled={!exportCapability}
105101
className="rounded-md bg-green-500 px-3 py-1 text-sm font-medium text-white transition-colors hover:bg-green-600 disabled:cursor-not-allowed disabled:bg-green-300"
106102
title="Download Annotated PDF"
107103
>
108104
<Download size={18} />
109105
</button>
110106
<button
111107
onClick={handleDelete}
112-
disabled={!selectedUid}
108+
disabled={!annoState?.selectedUid}
113109
className="rounded-md bg-red-500 px-3 py-1 text-sm font-medium text-white transition-colors hover:bg-red-600 disabled:cursor-not-allowed disabled:bg-red-300"
114110
title="Delete Selected Annotation"
115111
>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import usePluginStore from "@/components/plugin-store/hooks/use-plugin-store"
2+
import { useScrollCapability } from "@embedpdf/plugin-scroll/react"
3+
import { useEffect } from "react"
4+
import { useAnnotationCapability } from "../../pdf-container/plugin-annotation-2"
5+
import { useSelectionCapability } from "../../pdf-container/plugin-selection-2"
6+
7+
const PluginStoreSync = () => {
8+
const { provides: annoCapability } = useAnnotationCapability()
9+
const { provides: selectCapability } = useSelectionCapability()
10+
const { provides: scrollCapability } = useScrollCapability()
11+
12+
useEffect(() => {
13+
if (!annoCapability || !selectCapability || !scrollCapability) return
14+
15+
const store = usePluginStore.getState()
16+
17+
// initialize capabilities (which are static)
18+
store.setAnnoCapability(annoCapability)
19+
store.setSelectCapability(selectCapability)
20+
store.setScrollCapability(scrollCapability)
21+
22+
// sync store with changes
23+
const syncState = annoCapability.onStateChange((state) => {
24+
store.setAnnoState(state)
25+
})
26+
27+
return () => {
28+
syncState()
29+
// clear capabilities when unmounting
30+
store.setAnnoCapability(null)
31+
store.setAnnoState(null)
32+
store.setSelectCapability(null)
33+
store.setScrollCapability(null)
34+
}
35+
}, [annoCapability, selectCapability, scrollCapability])
36+
37+
return null
38+
}
39+
40+
export default PluginStoreSync

0 commit comments

Comments
 (0)