Skip to content
This repository was archived by the owner on Sep 19, 2025. It is now read-only.

Commit 03710d5

Browse files
committed
Refactor FileReader and enhance note-taking functionality
- Updated the default marker color in FileReaderContent to blue for better visibility. - Integrated current file path management in EditHistoryContext to support file-specific annotations. - Enhanced note management in NoteBar with improved state handling and integration with EditHistoryContext. - Added file path awareness in PDFViewer and DocumentViewer to ensure correct loading of annotations. - Introduced FileAnnotationStorage service for persistent storage of annotations and history in localStorage. - Improved popover behavior in LeftToolbar for better user experience.
1 parent ad56ca8 commit 03710d5

9 files changed

Lines changed: 471 additions & 127 deletions

File tree

src/frontend/components/reader/FileReaderContent.tsx

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ import 'react-pdf/dist/Page/TextLayer.css';
1414
import 'react-pdf/dist/Page/AnnotationLayer.css';
1515

1616
// Define default colors
17-
const DEFAULT_MARKER_COLOR = 'rgba(255, 255, 0, 0.3)'; // Yellow
17+
const DEFAULT_MARKER_COLOR = 'rgba(0, 196, 255, 0.3)'; // Blue
1818
const DEFAULT_DRAWING_COLOR = '#FF0000'; // Red
1919
const DEFAULT_LINE_WIDTH = 2;
2020

2121
const FileReaderContent = memo(() => {
2222
const navigate = useNavigate();
2323
const { zoomLevel, setZoomLevel, isDraggingZoom } = useZoom();
2424
const { activeTabId, getTabById, isLoading, setIsLoading } = useTabs();
25-
const { undo, redo } = useEditHistoryContext();
25+
const { undo, redo, setCurrentFilePath } = useEditHistoryContext();
2626

2727
// Group all state hooks together at the top
2828
const [numPages, setNumPages] = useState<number | null>(10); // Default to 10 pages as placeholder
@@ -78,8 +78,18 @@ const FileReaderContent = memo(() => {
7878
if (activeTab) {
7979
// Only update the file path if it actually changed
8080
if (filePath !== activeTab.path) {
81+
console.log(`Switching from ${filePath} to ${activeTab.path}`);
82+
83+
// First set the current file path in the EditHistoryContext
84+
// This will cause the EditHistoryContext to load annotations for the new file
85+
setCurrentFilePath(activeTab.path);
86+
87+
// Then update our local state
8188
setFilePath(activeTab.path);
8289

90+
// Reset the active tool when switching documents
91+
setActiveTool(null);
92+
8393
// Check if we have a saved page position for this document
8494
if (documentPageMap.has(activeTab.path)) {
8595
setPageNumber(documentPageMap.get(activeTab.path) || 1);
@@ -95,13 +105,21 @@ const FileReaderContent = memo(() => {
95105
} else {
96106
// If no active tab, use a default file based on file type preference
97107
if (filePath !== DEFAULT_FILES[FileType.PDF]) {
108+
// First set the current file path in the EditHistoryContext
109+
setCurrentFilePath(DEFAULT_FILES[FileType.PDF]);
110+
111+
// Then update our local state
98112
setFilePath(DEFAULT_FILES[FileType.PDF]);
113+
114+
// Reset the active tool
115+
setActiveTool(null);
116+
99117
setPageNumber(1);
100118
}
101119

102120
previousActiveTabIdRef.current = null;
103121
}
104-
}, [activeTabId, getTabById, filePath, documentPageMap, pageNumber]);
122+
}, [activeTabId, getTabById, filePath, documentPageMap, pageNumber, setCurrentFilePath]);
105123

106124
const handleDocumentLoadSuccess = useCallback((numPages?: number) => {
107125
if (numPages) {
@@ -278,7 +296,7 @@ const FileReaderContent = memo(() => {
278296

279297
// Calculate new zoom level based on wheel direction
280298
const delta = e.deltaY < 0 ? 25 : -25; // Increase/decrease by 25%
281-
const newZoom = Math.min(Math.max(zoomLevel + delta, 50), 200); // Limit between 50% and 200%
299+
const newZoom = Math.min(Math.max(zoomLevel + delta, 50), 400); // Limit between 50% and 400%
282300

283301
setZoomLevel(newZoom);
284302
}

src/frontend/components/reader/LeftToolbar.tsx

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { memo, useState } from 'react';
1+
import React, { memo, useState, useRef, useEffect } from 'react';
22
import { Button } from '@/components/ui/button';
33
import {
44
Hand,
@@ -81,6 +81,11 @@ const LeftToolbar = memo(({
8181
}: LeftToolbarProps) => {
8282
const { undo, redo, canUndo, canRedo } = useEditHistoryContext();
8383
const [openPopover, setOpenPopover] = useState<string | null>(null);
84+
const popoverTriggerRefs = useRef<Record<string, HTMLDivElement | null>>({});
85+
const popoverTimeoutRef = useRef<NodeJS.Timeout | null>(null);
86+
87+
// Track whether a popover is open for tooltip control
88+
const [isAnyPopoverOpen, setIsAnyPopoverOpen] = useState(false);
8489

8590
// Create base tools array
8691
const baseTools: Tool[] = [
@@ -166,15 +171,39 @@ const LeftToolbar = memo(({
166171
return null;
167172
};
168173

169-
// Handle popover toggle
170-
const togglePopover = (toolId: string) => {
171-
if (openPopover === toolId) {
172-
setOpenPopover(null);
173-
} else {
174+
// Handle popover hover behavior
175+
const handlePopoverHover = (toolId: string, isHovering: boolean) => {
176+
// Only show popovers for the active tool or if already open
177+
if (toolId !== activeTool && openPopover !== toolId) {
178+
return;
179+
}
180+
181+
if (popoverTimeoutRef.current) {
182+
clearTimeout(popoverTimeoutRef.current);
183+
popoverTimeoutRef.current = null;
184+
}
185+
186+
if (isHovering) {
174187
setOpenPopover(toolId);
188+
setIsAnyPopoverOpen(true);
189+
} else {
190+
// Add a small delay before closing to prevent flickering when moving between button and popover
191+
popoverTimeoutRef.current = setTimeout(() => {
192+
setOpenPopover(null);
193+
setIsAnyPopoverOpen(false);
194+
}, 300);
175195
}
176196
};
177197

198+
// Cleanup timeout on unmount
199+
useEffect(() => {
200+
return () => {
201+
if (popoverTimeoutRef.current) {
202+
clearTimeout(popoverTimeoutRef.current);
203+
}
204+
};
205+
}, []);
206+
178207
return (
179208
<div className="fixed left-4 top-1/2 -translate-y-1/2 flex flex-col items-center space-y-2 bg-background/90 backdrop-blur-sm p-2 rounded-lg shadow-md border border-border">
180209
<TooltipProvider delayDuration={300}>
@@ -212,11 +241,27 @@ const LeftToolbar = memo(({
212241
{/* Main tools */}
213242
{tools.map(tool => (
214243
<div key={tool.id} className="relative">
215-
{tool.showPopover ? (
216-
<Popover open={openPopover === tool.id} onOpenChange={() => togglePopover(tool.id)}>
244+
{tool.showPopover && (activeTool === tool.id) ? (
245+
<Popover
246+
open={openPopover === tool.id}
247+
onOpenChange={(open) => {
248+
if (!open && openPopover === tool.id) {
249+
setOpenPopover(null);
250+
setIsAnyPopoverOpen(false);
251+
} else if (open) {
252+
setIsAnyPopoverOpen(true);
253+
}
254+
}}
255+
>
217256
<PopoverTrigger asChild>
218-
<div className="relative">
219-
<Tooltip>
257+
<div
258+
className="relative"
259+
ref={(ref: HTMLDivElement | null) => { popoverTriggerRefs.current[tool.id] = ref; }}
260+
onMouseEnter={() => handlePopoverHover(tool.id, true)}
261+
onMouseLeave={() => handlePopoverHover(tool.id, false)}
262+
>
263+
{/* Only hide tooltip when tool is active or popover is open */}
264+
<Tooltip open={activeTool === tool.id || openPopover === tool.id ? false : undefined}>
220265
<TooltipTrigger asChild>
221266
<Button
222267
variant={tool.variant || (activeTool === tool.id ? "secondary" : "ghost")}
@@ -246,7 +291,13 @@ const LeftToolbar = memo(({
246291
</Tooltip>
247292
</div>
248293
</PopoverTrigger>
249-
<PopoverContent side="right" align="start" className="w-auto p-2">
294+
<PopoverContent
295+
side="right"
296+
align="start"
297+
className="w-auto p-2"
298+
onMouseEnter={() => handlePopoverHover(tool.id, true)}
299+
onMouseLeave={() => handlePopoverHover(tool.id, false)}
300+
>
250301
{tool.id === 'marker' && (
251302
<div className="space-y-2">
252303
<p className="text-xs font-medium">Marker Color</p>
@@ -329,7 +380,7 @@ const LeftToolbar = memo(({
329380
</PopoverContent>
330381
</Popover>
331382
) : (
332-
<Tooltip>
383+
<Tooltip open={activeTool === tool.id ? false : undefined}>
333384
<TooltipTrigger asChild>
334385
<Button
335386
variant={tool.variant || (activeTool === tool.id ? "secondary" : "ghost")}
@@ -347,6 +398,7 @@ const LeftToolbar = memo(({
347398
aria-pressed={activeTool === tool.id}
348399
>
349400
{tool.icon}
401+
{getColorIndicator(tool.id)}
350402
</Button>
351403
</TooltipTrigger>
352404
<TooltipContent side="right" align="center" className="max-w-[200px]">

0 commit comments

Comments
 (0)