From 5bd28889b68be5e2b94b04a61d675fd4ae468986 Mon Sep 17 00:00:00 2001 From: Connor Yoh Date: Fri, 31 Oct 2025 16:03:34 +0000 Subject: [PATCH] PrivateContent Wrapper --- .../fileEditor/FileEditorThumbnail.tsx | 34 +++++++------- .../fileManager/CompactFileDetails.tsx | 30 ++++++------ .../components/fileManager/FileInfoCard.tsx | 5 +- .../components/fileManager/FileListItem.tsx | 5 +- .../components/pageEditor/FileThumbnail.tsx | 46 ++++++++++--------- .../components/pageEditor/PageThumbnail.tsx | 32 +++++++------ .../components/shared/FileDropdownMenu.tsx | 9 +++- .../core/components/shared/PrivateContent.tsx | 42 +++++++++++++++++ .../core/components/shared/TopControls.tsx | 3 +- .../shared/filePreview/DocumentThumbnail.tsx | 31 +++++++------ .../addPageNumbers/PageNumberPreview.tsx | 15 +++--- .../tools/shared/ResultsPreview.tsx | 4 +- .../core/components/viewer/LocalEmbedPDF.tsx | 27 +++++------ .../components/viewer/ThumbnailSidebar.tsx | 26 ++++++----- 14 files changed, 190 insertions(+), 119 deletions(-) create mode 100644 frontend/src/core/components/shared/PrivateContent.tsx diff --git a/frontend/src/core/components/fileEditor/FileEditorThumbnail.tsx b/frontend/src/core/components/fileEditor/FileEditorThumbnail.tsx index 93ed2b05a..cc6124636 100644 --- a/frontend/src/core/components/fileEditor/FileEditorThumbnail.tsx +++ b/frontend/src/core/components/fileEditor/FileEditorThumbnail.tsx @@ -21,6 +21,7 @@ import { FileId } from '@app/types/file'; import { formatFileSize } from '@app/utils/fileUtils'; import ToolChain from '@app/components/shared/ToolChain'; import HoverActionMenu, { HoverAction } from '@app/components/shared/HoverActionMenu'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; @@ -328,8 +329,8 @@ const FileEditorThumbnail = ({ marginTop: '0.5rem', marginBottom: '0.5rem', }}> - - {file.name} + + {file.name}
{file.thumbnailUrl && ( - {file.name} { - const img = e.currentTarget; - img.style.display = 'none'; - img.parentElement?.setAttribute('data-thumb-missing', 'true'); - }} - style={{ - maxWidth: '80%', + + {file.name} { + const img = e.currentTarget; + img.style.display = 'none'; + img.parentElement?.setAttribute('data-thumb-missing', 'true'); + }} + style={{ + maxWidth: '80%', maxHeight: '80%', objectFit: 'contain', borderRadius: 0, @@ -378,6 +379,7 @@ const FileEditorThumbnail = ({ alignSelf: 'start' }} /> + )}
diff --git a/frontend/src/core/components/fileManager/CompactFileDetails.tsx b/frontend/src/core/components/fileManager/CompactFileDetails.tsx index 6da3b553e..724c3a9a3 100644 --- a/frontend/src/core/components/fileManager/CompactFileDetails.tsx +++ b/frontend/src/core/components/fileManager/CompactFileDetails.tsx @@ -6,6 +6,7 @@ import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import { useTranslation } from 'react-i18next'; import { getFileSize } from '@app/utils/fileUtils'; import { StirlingFileStub } from '@app/types/fileContext'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; interface CompactFileDetailsProps { currentFile: StirlingFileStub | null; @@ -41,18 +42,19 @@ const CompactFileDetails: React.FC = ({ {/* Small preview */} {currentFile && thumbnail ? ( - {currentFile.name} + + {currentFile.name} + ) : currentFile ? (
= ({ {/* File info */} - - {currentFile ? currentFile.name : 'No file selected'} + + {currentFile ? currentFile.name : 'No file selected'} {currentFile ? getFileSize(currentFile) : ''} diff --git a/frontend/src/core/components/fileManager/FileInfoCard.tsx b/frontend/src/core/components/fileManager/FileInfoCard.tsx index f898cbc67..e62d3cd64 100644 --- a/frontend/src/core/components/fileManager/FileInfoCard.tsx +++ b/frontend/src/core/components/fileManager/FileInfoCard.tsx @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next'; import { detectFileExtension, getFileSize } from '@app/utils/fileUtils'; import { StirlingFileStub } from '@app/types/fileContext'; import ToolChain from '@app/components/shared/ToolChain'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; interface FileInfoCardProps { currentFile: StirlingFileStub | null; @@ -26,7 +27,9 @@ const FileInfoCard: React.FC = ({ - {t('fileManager.fileName', 'Name')} + + {t('fileManager.fileName', 'Name')} + {currentFile ? currentFile.name : ''} diff --git a/frontend/src/core/components/fileManager/FileListItem.tsx b/frontend/src/core/components/fileManager/FileListItem.tsx index d8c0aac70..6e4115aeb 100644 --- a/frontend/src/core/components/fileManager/FileListItem.tsx +++ b/frontend/src/core/components/fileManager/FileListItem.tsx @@ -13,6 +13,7 @@ import { useFileManagerContext } from '@app/contexts/FileManagerContext'; import { zipFileService } from '@app/services/zipFileService'; import ToolChain from '@app/components/shared/ToolChain'; import { Z_INDEX_OVER_FILE_MANAGER_MODAL } from '@app/styles/zIndex'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; interface FileListItemProps { file: StirlingFileStub; @@ -99,7 +100,9 @@ const FileListItem: React.FC = ({ - {file.name} + + {file.name} + v{currentVersion} diff --git a/frontend/src/core/components/pageEditor/FileThumbnail.tsx b/frontend/src/core/components/pageEditor/FileThumbnail.tsx index 9cfc1e4c3..a24cf9307 100644 --- a/frontend/src/core/components/pageEditor/FileThumbnail.tsx +++ b/frontend/src/core/components/pageEditor/FileThumbnail.tsx @@ -12,6 +12,7 @@ import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-d import styles from '@app/components/pageEditor/PageEditor.module.css'; import { useFileContext } from '@app/contexts/FileContext'; import { FileId } from '@app/types/file'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; interface FileItem { id: FileId; @@ -316,29 +317,30 @@ const FileThumbnail = ({ }} > {file.thumbnail && ( - {file.name} { - // Hide broken image if blob URL was revoked - const img = e.target as HTMLImageElement; - img.style.display = 'none'; + + {file.name} { + // Hide broken image if blob URL was revoked + const img = e.target as HTMLImageElement; + img.style.display = 'none'; + }} + style={{ + maxWidth: '80%', + maxHeight: '80%', + objectFit: 'contain', + borderRadius: 0, + background: '#ffffff', + border: '1px solid var(--border-default)', + display: 'block', + marginLeft: 'auto', + marginRight: 'auto', + alignSelf: 'start' }} - style={{ - maxWidth: '80%', - maxHeight: '80%', - objectFit: 'contain', - borderRadius: 0, - background: '#ffffff', - border: '1px solid var(--border-default)', - display: 'block', - marginLeft: 'auto', - marginRight: 'auto', - alignSelf: 'start' - }} - /> + /> + )} diff --git a/frontend/src/core/components/pageEditor/PageThumbnail.tsx b/frontend/src/core/components/pageEditor/PageThumbnail.tsx index f0124b2c6..2546a607e 100644 --- a/frontend/src/core/components/pageEditor/PageThumbnail.tsx +++ b/frontend/src/core/components/pageEditor/PageThumbnail.tsx @@ -14,6 +14,7 @@ import { useThumbnailGeneration } from '@app/hooks/useThumbnailGeneration'; import { useFilesModalContext } from '@app/contexts/FilesModalContext'; import styles from '@app/components/pageEditor/PageEditor.module.css'; import HoverActionMenu, { HoverAction } from '@app/components/shared/HoverActionMenu'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; interface PageThumbnailProps { @@ -442,21 +443,22 @@ const PageThumbnail: React.FC = ({ }}> ) : thumbnailUrl ? ( - {`Page + + {`Page + ) : (
📄 diff --git a/frontend/src/core/components/shared/FileDropdownMenu.tsx b/frontend/src/core/components/shared/FileDropdownMenu.tsx index 8a78e7631..24583ea77 100644 --- a/frontend/src/core/components/shared/FileDropdownMenu.tsx +++ b/frontend/src/core/components/shared/FileDropdownMenu.tsx @@ -3,6 +3,7 @@ import { Menu, Loader, Group, Text } from '@mantine/core'; import VisibilityIcon from '@mui/icons-material/Visibility'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import FitText from '@app/components/shared/FitText'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; interface FileDropdownMenuProps { displayName: string; @@ -31,7 +32,9 @@ export const FileDropdownMenu: React.FC = ({ ) : ( )} - + + +
@@ -61,7 +64,9 @@ export const FileDropdownMenu: React.FC = ({ >
- + + +
{file.versionNumber && file.versionNumber > 1 && ( diff --git a/frontend/src/core/components/shared/PrivateContent.tsx b/frontend/src/core/components/shared/PrivateContent.tsx new file mode 100644 index 000000000..208b0c0b2 --- /dev/null +++ b/frontend/src/core/components/shared/PrivateContent.tsx @@ -0,0 +1,42 @@ +import React from 'react'; + +type PrivateContentProps = { + children: React.ReactNode; + as?: 'span' | 'div'; +} & ( + | React.HTMLAttributes + | React.HTMLAttributes +); + +/** + * Wrapper component for content that should not be captured by analytics tools. + * Currently applies the 'ph-no-capture' className to prevent PostHog capture. + * + * Use this component to wrap any content containing sensitive or private information + * that should be excluded from analytics tracking. + * + * @example + * // For inline content (default): + * + * Sensitive filename.pdf + * + * + * // For block-level content: + * + *
Block content
+ *
+ */ +export const PrivateContent: React.FC = ({ + children, + as: Component = 'span', + className = '', + ...props +}) => { + const combinedClassName = `ph-no-capture${className ? ` ${className}` : ''}`; + + return ( + + {children} + + ); +}; diff --git a/frontend/src/core/components/shared/TopControls.tsx b/frontend/src/core/components/shared/TopControls.tsx index 6c6ac6999..64c78b8f1 100644 --- a/frontend/src/core/components/shared/TopControls.tsx +++ b/frontend/src/core/components/shared/TopControls.tsx @@ -9,6 +9,7 @@ import PictureAsPdfIcon from "@mui/icons-material/PictureAsPdf"; import { WorkbenchType, isValidWorkbench } from '@app/types/workbench'; import type { CustomWorkbenchViewInstance } from '@app/contexts/ToolWorkflowContext'; import { FileDropdownMenu } from '@app/components/shared/FileDropdownMenu'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; const viewOptionStyle: React.CSSProperties = { @@ -54,7 +55,7 @@ const createViewOptions = ( ) : ( )} - {displayName} + {displayName} ), value: "viewer", diff --git a/frontend/src/core/components/shared/filePreview/DocumentThumbnail.tsx b/frontend/src/core/components/shared/filePreview/DocumentThumbnail.tsx index ffa465fc9..5ace7d03f 100644 --- a/frontend/src/core/components/shared/filePreview/DocumentThumbnail.tsx +++ b/frontend/src/core/components/shared/filePreview/DocumentThumbnail.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { Box, Center, Image } from '@mantine/core'; import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf'; import { StirlingFileStub } from '@app/types/fileContext'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; export interface DocumentThumbnailProps { file: File | StirlingFileStub | null; @@ -35,13 +36,14 @@ const DocumentThumbnail: React.FC = ({ if (thumbnail) { return ( - {`Preview + + {`Preview + {children} ); @@ -50,13 +52,14 @@ const DocumentThumbnail: React.FC = ({ return (
- + + +
{children}
diff --git a/frontend/src/core/components/tools/addPageNumbers/PageNumberPreview.tsx b/frontend/src/core/components/tools/addPageNumbers/PageNumberPreview.tsx index 830703f21..8edb8fa2c 100644 --- a/frontend/src/core/components/tools/addPageNumbers/PageNumberPreview.tsx +++ b/frontend/src/core/components/tools/addPageNumbers/PageNumberPreview.tsx @@ -4,6 +4,7 @@ import { AddPageNumbersParameters } from '@app/components/tools/addPageNumbers/u import { pdfWorkerManager } from '@app/services/pdfWorkerManager'; import { useThumbnailGeneration } from '@app/hooks/useThumbnailGeneration'; import styles from '@app/components/tools/addPageNumbers/PageNumberPreview.module.css'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; // Simple utilities for page numbers (adapted from stamp) const A4_ASPECT_RATIO = 0.707; @@ -197,12 +198,14 @@ export default function PageNumberPreview({ parameters, onParameterChange, file, style={containerStyle} > {pageThumbnail && ( - page preview + + page preview + )} {/* Quick position overlay grid - EXACT copy from stamp */} diff --git a/frontend/src/core/components/tools/shared/ResultsPreview.tsx b/frontend/src/core/components/tools/shared/ResultsPreview.tsx index feb4004f7..9a4921af0 100644 --- a/frontend/src/core/components/tools/shared/ResultsPreview.tsx +++ b/frontend/src/core/components/tools/shared/ResultsPreview.tsx @@ -3,6 +3,7 @@ import { Box, Text, Loader, Stack, Center, Flex } from '@mantine/core'; import FilePreview from '@app/components/shared/FilePreview'; import FileMetadata from '@app/components/tools/shared/FileMetadata'; import NavigationControls from '@app/components/tools/shared/NavigationControls'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; export interface ReviewFile { file: File; @@ -62,7 +63,6 @@ const ResultsPreview = ({ {/* File name at the top */} - {currentFile.file.name} + {currentFile.file.name} diff --git a/frontend/src/core/components/viewer/LocalEmbedPDF.tsx b/frontend/src/core/components/viewer/LocalEmbedPDF.tsx index bfe75df2f..bd9af743f 100644 --- a/frontend/src/core/components/viewer/LocalEmbedPDF.tsx +++ b/frontend/src/core/components/viewer/LocalEmbedPDF.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import { createPluginRegistration } from '@embedpdf/core'; import { EmbedPDF } from '@embedpdf/core/react'; import { usePdfiumEngine } from '@embedpdf/engines/react'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; // Import the essential plugins import { Viewport, ViewportPluginPackage } from '@embedpdf/plugin-viewport/react'; @@ -184,18 +185,17 @@ export function LocalEmbedPDF({ file, url, enableAnnotations = false, onSignatur // Wrap your UI with the provider return ( -
+ +
-
+
+ ); } diff --git a/frontend/src/core/components/viewer/ThumbnailSidebar.tsx b/frontend/src/core/components/viewer/ThumbnailSidebar.tsx index 510a6c1a6..48fce6ae1 100644 --- a/frontend/src/core/components/viewer/ThumbnailSidebar.tsx +++ b/frontend/src/core/components/viewer/ThumbnailSidebar.tsx @@ -1,6 +1,7 @@ import { useState, useEffect } from 'react'; import { Box, ScrollArea } from '@mantine/core'; import { useViewer } from '@app/contexts/ViewerContext'; +import { PrivateContent } from '@app/components/shared/PrivateContent'; interface ThumbnailSidebarProps { visible: boolean; @@ -145,18 +146,19 @@ export function ThumbnailSidebar({ visible, onToggle: _onToggle, activeFileIndex > {/* Thumbnail Image */} {thumbnails[pageIndex] && thumbnails[pageIndex] !== 'error' ? ( - {`Page + + {`Page + ) : thumbnails[pageIndex] === 'error' ? (