diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index 4719cc2c3..e7371334a 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -2117,6 +2117,9 @@ "tags": "differentiate,contrast,changes,analysis", "title": "Compare", "header": "Compare PDFs", + "workbench": { + "label": "Compare view" + }, "highlightColor": { "1": "Highlight Colour 1:", "2": "Highlight Colour 2:" @@ -2168,7 +2171,9 @@ }, "dropdown": { "deletions": "Deletions ({{count}})", - "additions": "Additions ({{count}})" + "additions": "Additions ({{count}})", + "searchPlaceholder": "Search changes...", + "noResults": "No changes found" }, "actions": { "stackVertically": "Stack vertically", diff --git a/frontend/public/locales/en-US/translation.json b/frontend/public/locales/en-US/translation.json index 535b0fce4..0f4f42872 100644 --- a/frontend/public/locales/en-US/translation.json +++ b/frontend/public/locales/en-US/translation.json @@ -1286,6 +1286,9 @@ "title": "Compare view", "noData": "Run a comparison to view the summary and diff." }, + "workbench": { + "label": "Compare view" + }, "base": { "label": "Base Document", "placeholder": "Select a base PDF" @@ -1322,6 +1325,12 @@ "added": "Added in comparison" }, "newLine": "new-line", + "dropdown": { + "deletions": "Deletions ({{count}})", + "additions": "Additions ({{count}})", + "searchPlaceholder": "Search changes...", + "noResults": "No changes found" + }, "summary": { "baseHeading": "Base document", "comparisonHeading": "Comparison document", diff --git a/frontend/src/components/tools/compare/CompareDocumentPane.tsx b/frontend/src/components/tools/compare/CompareDocumentPane.tsx index c33a5c00a..995edfe5b 100644 --- a/frontend/src/components/tools/compare/CompareDocumentPane.tsx +++ b/frontend/src/components/tools/compare/CompareDocumentPane.tsx @@ -1,5 +1,5 @@ import { Alert, Group, Loader, Stack, Text } from '@mantine/core'; -import { RefObject } from 'react'; +import { RefObject, useMemo } from 'react'; import type { PagePreview, WordHighlightEntry } from './types'; import type { TokenBoundingBox } from '../../../types/compare'; import CompareNavigationDropdown from './CompareNavigationDropdown'; @@ -108,7 +108,15 @@ const CompareDocumentPane = ({ pageLabel, altLabel, }: CompareDocumentPaneProps) => { - // Constants that vary by pane + const isMobileViewport = useMediaQuery('(max-width: 1024px)'); + const pairedPageMap = useMemo(() => { + const map = new Map(); + pairedPages.forEach((item) => { + map.set(item.pageNumber, item); + }); + return map; + }, [pairedPages]); + const HIGHLIGHT_COLOR = pane === 'base' ? '#ff6b6b' : '#51cf66'; // red for base (removals), green for comparison (additions) const HIGHLIGHT_OPACITY = pane === 'base' ? 0.45 : 0.35; const OFFSET_PIXELS = pane === 'base' ? 4 : 2; @@ -163,7 +171,7 @@ const CompareDocumentPane = ({ )} {pages.map((page) => { - const peerPage = pairedPages.find((item) => item.pageNumber === page.pageNumber); + const peerPage = pairedPageMap.get(page.pageNumber); const targetHeight = peerPage ? Math.max(page.height, peerPage.height) : page.height; const fit = targetHeight / page.height; const rowHeightPx = getRowHeightPx(page.pageNumber); @@ -172,9 +180,8 @@ const CompareDocumentPane = ({ const isPortrait = rotationNorm === 0 || rotationNorm === 180; const isStackedPortrait = layout === 'stacked' && isPortrait; const viewportWidth = typeof window !== 'undefined' ? window.innerWidth : 1200; - const isMobile = useMediaQuery('(max-width: 1024px)'); const containerW = scrollRef.current?.clientWidth ?? viewportWidth; - const stackedWidth = isMobile + const stackedWidth = isMobileViewport ? Math.max(320, Math.round(containerW)) : Math.max(320, Math.round(viewportWidth * 0.5)); const stackedHeight = Math.round(stackedWidth * 1.4142); diff --git a/frontend/src/components/tools/compare/CompareNavigationDropdown.tsx b/frontend/src/components/tools/compare/CompareNavigationDropdown.tsx index 69e2844fd..b7fd05904 100644 --- a/frontend/src/components/tools/compare/CompareNavigationDropdown.tsx +++ b/frontend/src/components/tools/compare/CompareNavigationDropdown.tsx @@ -17,6 +17,8 @@ const CompareNavigationDropdown = ({ }: NavigationDropdownProps) => { const { t } = useTranslation(); const newLineLabel = t('compare.newLine', 'new-line'); + const formatPageLabel = (page: number) => + t('compare.dropdown.pagePrefix', { page, defaultValue: 'Page {{page}}' }); const combobox = useCombobox({ onDropdownClose: () => { combobox.resetSelectedOption(); @@ -168,10 +170,16 @@ const CompareNavigationDropdown = ({
- setQuery(e.currentTarget.value)} /> + setQuery(e.currentTarget.value)} + />
{stickyPage != null && ( -
{`Page ${stickyPage}`}
+
+ {t('compare.summary.pageLabel', 'Page')}{' '}{stickyPage} +
)} {normalizedChanges.length > 0 ? ( @@ -186,7 +194,7 @@ const CompareNavigationDropdown = ({ className={["compare-dropdown-group", stickyPage === lastPage ? "compare-dropdown-group--hidden" : ""].filter(Boolean).join(" ")} key={`group-${lastPage}`} > - {`Page ${lastPage}`} + {t('compare.summary.pageLabel', 'Page')}{' '}{lastPage}
); } @@ -208,7 +216,7 @@ const CompareNavigationDropdown = ({ return nodes; })() ) : ( - No changes found + {t('compare.dropdown.noResults', 'No changes found')} )}