import { Bookmark, Copy, MessageSquare } from "lucide-react"; import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { useToast } from "@/hooks/use-toast"; interface EnhancedLineNumberedTextProps { content: string; fontSizeClass?: string; onAnnotate: (lineNumber: number) => void; highlightedLine?: number; workId: string; } export function EnhancedLineNumberedText({ content, fontSizeClass = "text-size-md", onAnnotate, highlightedLine, workId, }: EnhancedLineNumberedTextProps) { const { toast } = useToast(); const [hoveredLine, setHoveredLine] = useState(null); const [bookmarkedLines, setBookmarkedLines] = useState>( new Set(), ); const [lineAnnotationCounts, _setLineAnnotationCounts] = useState< Record >({ // Mock annotation counts - in a real app this would come from an API 2: 3, 5: 1, 8: 7, }); // Split content into lines const lines = content.split("\n"); const handleLineHover = (lineNumber: number) => { setHoveredLine(lineNumber); }; const handleLineLeave = () => { setHoveredLine(null); }; const handleCopyLine = (_lineNumber: number, lineText: string) => { navigator.clipboard.writeText(lineText); toast({ description: "Line copied to clipboard", duration: 2000, }); }; const handleCopyLineLink = (lineNumber: number) => { const url = new URL(window.location.href); url.hash = `line-${lineNumber}`; navigator.clipboard.writeText(url.toString()); toast({ description: "Link to line copied to clipboard", duration: 2000, }); }; const handleToggleBookmark = async (lineNumber: number) => { try { const isBookmarked = bookmarkedLines.has(lineNumber); // Optimistically update UI setBookmarkedLines((prev) => { const newBookmarks = new Set(prev); if (isBookmarked) { newBookmarks.delete(lineNumber); } else { newBookmarks.add(lineNumber); } return newBookmarks; }); // In a real app, this would make an API call // await apiRequest('POST', '/api/reading-bookmarks', { // userId: 1, // Mock user ID // workId, // lineNumber, // isBookmarked: !isBookmarked // }); toast({ description: isBookmarked ? "Bookmark removed" : "Line bookmarked", duration: 2000, }); } catch (_error) { // Revert on error toast({ title: "Error", description: "Could not update bookmark", variant: "destructive", }); } }; return (
{lines.map((line, index) => { const lineNumber = index + 1; const isHighlighted = lineNumber === highlightedLine; const _isHovered = lineNumber === hoveredLine; const isBookmarked = bookmarkedLines.has(lineNumber); const annotationCount = lineAnnotationCounts[lineNumber] || 0; // For blank lines, render a smaller empty line if (!line.trim()) { return (
); } return (
handleLineHover(lineNumber)} onMouseLeave={handleLineLeave} > {/* Line number indicator with bookmark feature */}
handleToggleBookmark(lineNumber)} > {isBookmarked ? ( ) : ( {lineNumber} )}
{/* Line content */}

{line}

{/* Annotation indicator - if the line has annotations */} {annotationCount > 0 && (
onAnnotate(lineNumber)} >
{annotationCount}

Click to view annotations

)} {/* Action buttons that appear on hover */}
); })}
); }