From 28173fe9a460a834dd46c4c5010787cfa1d688d9 Mon Sep 17 00:00:00 2001 From: EthanHealy01 Date: Wed, 29 Oct 2025 01:43:33 +0000 Subject: [PATCH] cleanups, delete unused files, revert unnecessary git changes, etc etc --- .../public/locales/en-GB/translation.json | 3 + .../public/locales/en-US/translation.json | 3 + .../tools/compare/CompareDocumentPane.tsx | 65 +++--- .../compare/CompareNavigationDropdown.tsx | 38 ++-- .../tools/compare/CompareReviewActions.tsx | 50 ----- .../tools/compare/CompareSelectionStep.tsx | 105 ---------- .../tools/compare/CompareUploadSection.tsx | 23 +-- .../tools/compare/CompareWorkbenchView.tsx | 8 +- .../components/tools/compare/compareUtils.ts | 10 - .../components/tools/compare/compareView.css | 52 +++-- .../hooks/useCompareChangeNavigation.ts | 16 ++ .../compare/hooks/useCompareHighlights.ts | 8 +- .../tools/compare/hooks/useComparePanZoom.ts | 88 ++------ .../hooks/useCompareRightRailButtons.tsx | 4 +- .../src/components/tools/compare/types.ts | 14 -- .../fileEditor/FileEditorThumbnail.tsx | 4 +- .../components/pageEditor/PageThumbnail.tsx | 4 +- .../core/components/shared/AppConfigModal.tsx | 4 +- .../src/core/components/tools/ToolPanel.tsx | 4 +- .../tools/shared/createToolFlow.tsx | 6 +- .../src/core/contexts/FilesModalContext.tsx | 4 +- .../tools/compare/useCompareOperation.ts | 67 ++++++- frontend/src/core/hooks/useIsMobile.ts | 9 + .../core/hooks/useProgressivePagePreviews.ts | 10 +- .../core/hooks/useShouldShowWelcomeModal.ts | 4 +- frontend/src/core/pages/HomePage.tsx | 4 +- frontend/src/core/styles/theme.css | 14 ++ frontend/src/core/tools/Compare.tsx | 6 +- frontend/src/core/types/compare.ts | 188 ++++++++++++++++++ frontend/src/core/types/compareWorkbench.ts | 20 -- .../hooks/useShouldShowWelcomeModal.ts | 4 +- 31 files changed, 411 insertions(+), 428 deletions(-) delete mode 100644 frontend/src/components/tools/compare/CompareReviewActions.tsx delete mode 100644 frontend/src/components/tools/compare/CompareSelectionStep.tsx delete mode 100644 frontend/src/components/tools/compare/compareUtils.ts delete mode 100644 frontend/src/components/tools/compare/types.ts create mode 100644 frontend/src/core/hooks/useIsMobile.ts delete mode 100644 frontend/src/core/types/compareWorkbench.ts diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index 098eaeb96..cc2badf7b 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -2173,6 +2173,9 @@ "comparisonHeading": "Comparison document", "pageLabel": "Page" }, + "rendering": { + "rendering": "rendering" + }, "dropdown": { "deletions": "Deletions ({{count}})", "additions": "Additions ({{count}})", diff --git a/frontend/public/locales/en-US/translation.json b/frontend/public/locales/en-US/translation.json index 93dab8a0f..661d18a87 100644 --- a/frontend/public/locales/en-US/translation.json +++ b/frontend/public/locales/en-US/translation.json @@ -1336,6 +1336,9 @@ "comparisonHeading": "Comparison document", "pageLabel": "Page" }, + "rendering": { + "rendering": "rendering" + }, "status": { "extracting": "Extracting text...", "processing": "Analyzing differences...", diff --git a/frontend/src/components/tools/compare/CompareDocumentPane.tsx b/frontend/src/components/tools/compare/CompareDocumentPane.tsx index 043af823a..b835b2d7b 100644 --- a/frontend/src/components/tools/compare/CompareDocumentPane.tsx +++ b/frontend/src/components/tools/compare/CompareDocumentPane.tsx @@ -1,45 +1,21 @@ import { Alert, Group, Loader, Stack, Text } from '@mantine/core'; -import { RefObject, useMemo } from 'react'; -import type { PagePreview, WordHighlightEntry } from './types'; -import type { TokenBoundingBox } from '@app/types/compare'; +import { useMemo } from 'react'; +import type { PagePreview } from '@app/types/compare'; +import type { TokenBoundingBox, CompareDocumentPaneProps } from '@app/types/compare'; import CompareNavigationDropdown from './CompareNavigationDropdown'; -import { toRgba } from './compareUtils'; import LazyLoadContainer from '@app/components/shared/LazyLoadContainer'; -import { useMediaQuery } from '@mantine/hooks'; +import { useIsMobile } from '@app/hooks/useIsMobile'; -interface CompareDocumentPaneProps { - pane: 'base' | 'comparison'; - layout: 'side-by-side' | 'stacked'; - scrollRef: RefObject; - peerScrollRef: RefObject; - handleScrollSync: (source: HTMLDivElement | null, target: HTMLDivElement | null) => void; - beginPan: (pane: 'base' | 'comparison', event: React.MouseEvent) => void; - continuePan: (event: React.MouseEvent) => void; - endPan: () => void; - handleWheelZoom: (pane: 'base' | 'comparison', event: React.WheelEvent) => void; - handleWheelOverscroll: (pane: 'base' | 'comparison', event: React.WheelEvent) => void; - onTouchStart: (pane: 'base' | 'comparison', event: React.TouchEvent) => void; - onTouchMove: (event: React.TouchEvent) => void; - onTouchEnd: (event: React.TouchEvent) => void; - isPanMode: boolean; - zoom: number; - pan?: { x: number; y: number }; - title: string; - dropdownPlaceholder?: string; - changes: Array<{ value: string; label: string; pageNumber?: number }>; - onNavigateChange: (id: string, pageNumber?: number) => void; - isLoading: boolean; - processingMessage: string; - emptyMessage: string; - pages: PagePreview[]; - pairedPages: PagePreview[]; - getRowHeightPx: (pageNumber: number) => number; - wordHighlightMap: Map; - metaIndexToGroupId: Map; - documentLabel: string; - pageLabel: string; - altLabel: string; -} +const toRgba = (hexColor: string, alpha: number): string => { + const hex = hexColor.replace('#', ''); + if (hex.length !== 6) { + return hexColor; + } + const r = parseInt(hex.slice(0, 2), 16); + const g = parseInt(hex.slice(2, 4), 16); + const b = parseInt(hex.slice(4, 6), 16); + return `rgba(${r}, ${g}, ${b}, ${alpha})`; +}; // Merge overlapping or touching rects into larger non-overlapping blocks. // This is more robust across rotations (vertical "lines" etc.) and prevents dark spots. @@ -110,7 +86,7 @@ const CompareDocumentPane = ({ pageLabel, altLabel, }: CompareDocumentPaneProps) => { - const isMobileViewport = useMediaQuery('(max-width: 1024px)'); + const isMobileViewport = useIsMobile(); const pairedPageMap = useMemo(() => { const map = new Map(); pairedPages.forEach((item) => { @@ -139,6 +115,7 @@ const CompareDocumentPane = ({ placeholder={dropdownPlaceholder ?? ''} className={pane === 'comparison' ? 'compare-changes-select--comparison' : undefined} onNavigate={onNavigateChange} + renderedPageNumbers={useMemo(() => new Set(pages.map(p => p.pageNumber)), [pages])} /> )} @@ -180,7 +157,9 @@ const CompareDocumentPane = ({ const highlightOffset = OFFSET_PIXELS / page.height; const rotationNorm = ((page.rotation ?? 0) % 360 + 360) % 360; const isPortrait = rotationNorm === 0 || rotationNorm === 180; + const isLandscape = rotationNorm === 90 || rotationNorm === 270; const isStackedPortrait = layout === 'stacked' && isPortrait; + const isStackedLandscape = layout === 'stacked' && isLandscape; const viewportWidth = typeof window !== 'undefined' ? window.innerWidth : 1200; const containerW = scrollRef.current?.clientWidth ?? viewportWidth; const stackedWidth = isMobileViewport @@ -213,7 +192,11 @@ const CompareDocumentPane = ({
; - placeholder: string; - className?: string; - onNavigate: (value: string, pageNumber?: number) => void; -} +import type { NavigationDropdownProps } from '@app/types/compare'; const CompareNavigationDropdown = ({ changes, placeholder, className, onNavigate, + renderedPageNumbers, }: NavigationDropdownProps) => { const { t } = useTranslation(); const newLineLabel = t('compare.newLine', 'new-line'); @@ -63,15 +58,26 @@ const CompareNavigationDropdown = ({ const isMeaningful = (s: string) => { const t = sanitize(s); - // Keep only items that have at least one letter or digit (unicode-aware) - try { - if (!/[\p{L}\p{N}]/u.test(t)) return false; - } catch { - if (!/[A-Za-z0-9]/.test(t)) return false; - } + + // Build a unicode-aware regex if supported; otherwise fall back to a plain ASCII class. + const rx = + (() => { + try { + // Construct at runtime so old engines don’t fail parse-time + console.debug('Using Unicode props'); + return new RegExp('[\\p{L}\\p{N}\\p{P}\\p{S}]', 'u'); + } catch { + // Fallback (no Unicode props): letters, digits, and common punctuation/symbols + console.debug('No Unicode props, falling back to ASCII class'); + return /[A-Za-z0-9.,!?;:(){}"'`~@#$%^&*+=|<>/[\]]/; + } + })(); + + if (!rx.test(t)) return false; return t.length > 0; }; + const [query, setQuery] = useState(''); const viewportRef = useRef(null); const [stickyPage, setStickyPage] = useState(null); @@ -168,6 +174,9 @@ const CompareNavigationDropdown = ({ {stickyPage != null && (
{t('compare.summary.pageLabel', 'Page')}{' '}{stickyPage} + {renderedPageNumbers && !renderedPageNumbers.has(stickyPage) && ( + — {t('compare.rendering.rendering', 'rendering')} + )}
)} @@ -184,6 +193,9 @@ const CompareNavigationDropdown = ({ key={`group-${lastPage}`} > {t('compare.summary.pageLabel', 'Page')}{' '}{lastPage} + {renderedPageNumbers && !renderedPageNumbers.has(lastPage) && ( + — {t('compare.rendering.rendering', 'rendering')} + )}
); } diff --git a/frontend/src/components/tools/compare/CompareReviewActions.tsx b/frontend/src/components/tools/compare/CompareReviewActions.tsx deleted file mode 100644 index 6bfa55a49..000000000 --- a/frontend/src/components/tools/compare/CompareReviewActions.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Button, Group, Stack, Text } from '@mantine/core'; -import SwapHorizRoundedIcon from '@mui/icons-material/SwapHorizRounded'; -import DownloadRoundedIcon from '@mui/icons-material/DownloadRounded'; -import { useTranslation } from 'react-i18next'; - -interface CompareReviewActionsProps { - onSwitchOrder: () => void; - onDownloadSummary: () => void; - disableDownload?: boolean; - disableSwitch?: boolean; -} - -const CompareReviewActions = ({ - onSwitchOrder, - onDownloadSummary, - disableDownload = false, - disableSwitch = false, -}: CompareReviewActionsProps) => { - const { t } = useTranslation(); - - return ( - - - {t('compare.review.actionsHint', 'Review the comparison, switch document roles, or export the summary.')} - - - - - - - ); -}; - -export default CompareReviewActions; - diff --git a/frontend/src/components/tools/compare/CompareSelectionStep.tsx b/frontend/src/components/tools/compare/CompareSelectionStep.tsx deleted file mode 100644 index 01689107a..000000000 --- a/frontend/src/components/tools/compare/CompareSelectionStep.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { useMemo } from 'react'; -import { Badge, Card, Group, Select, Stack, Text } from '@mantine/core'; -import { useTranslation } from 'react-i18next'; -import { useAllFiles } from '../../../contexts/FileContext'; -import { formatFileSize } from '../../../utils/fileUtils'; -import type { FileId } from '../../../types/file'; - -interface CompareSelectionStepProps { - role: 'base' | 'comparison'; - selectedFileId: FileId | null; - onFileSelect: (fileId: FileId | null) => void; - disabled?: boolean; -} - -export const CompareSelectionStep = ({ - role, - selectedFileId, - onFileSelect, - disabled = false, -}: CompareSelectionStepProps) => { - const { t } = useTranslation(); - const { fileStubs } = useAllFiles(); - - const labels = useMemo(() => { - if (role === 'base') { - return { - title: t('compare.base.label', 'Base document'), - placeholder: t('compare.base.placeholder', 'Select a base PDF'), - }; - } - - return { - title: t('compare.comparison.label', 'Comparison document'), - placeholder: t('compare.comparison.placeholder', 'Select a comparison PDF'), - }; - }, [role, t]); - - const options = useMemo(() => { - return fileStubs - .filter((stub) => stub.type?.includes('pdf') || stub.name.toLowerCase().endsWith('.pdf')) - .map((stub) => ({ - value: stub.id as unknown as string, - label: stub.name, - })); - }, [fileStubs]); - - const selectedStub = useMemo(() => fileStubs.find((stub) => stub.id === selectedFileId), [fileStubs, selectedFileId]); - - const selectValue = selectedFileId ? (selectedFileId as unknown as string) : null; - - // Hide dropdown until there are files in the workbench - if (options.length === 0) { - return ( - - - {t('compare.addFilesHint', 'Add PDFs in the Files step to enable selection.')} - - - ); - } - - return ( - -