Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/react-mui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@embedpdf/plugin-history": "workspace:*",
"@embedpdf/plugin-annotation": "workspace:*",
"@embedpdf/plugin-redaction": "workspace:*",
"@embedpdf/plugin-watermark": "workspace:*",
"@embedpdf/utils": "workspace:*",
"@embedpdf/models": "workspace:*",
"@embedpdf/pdfium": "workspace:*",
Expand Down
106 changes: 105 additions & 1 deletion examples/react-mui/src/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ import {
AnnotationPluginPackage,
AnnotationTool,
} from '@embedpdf/plugin-annotation/react';
import { WatermarkPluginPackage } from '@embedpdf/plugin-watermark';
import { CircularProgress, Box, Alert } from '@mui/material';
import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined';
import { useMemo, useRef } from 'react';
import BrandingWatermarkOutlinedIcon from '@mui/icons-material/BrandingWatermarkOutlined';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import { PageControls } from './components/page-controls';
import { Search } from './components/search';
Expand All @@ -49,8 +51,10 @@ import { Toolbar } from './components/toolbar';
import { ViewSidebarReverseIcon } from './icons';
import { AnnotationSelectionMenu } from './components/annotation-selection-menu';
import { RedactionSelectionMenu } from './components/redaction-selection-menu';
import { WatermarkPanel } from './components/watermark-panel';

const consoleLogger = new ConsoleLogger();
const WATERMARK_TAKEOVER_PLACEMENT_THRESHOLD = 500;

function App() {
const isDev = useMemo(
Expand All @@ -60,6 +64,47 @@ function App() {

const { engine, isLoading, error } = usePdfiumEngine(isDev ? { logger: consoleLogger } : {});
const popperContainerRef = useRef<HTMLDivElement>(null);
const [watermarkBusy, setWatermarkBusy] = useState<{
isApplying: boolean;
status: string;
fullPageTakeover: boolean;
startedAt: number;
}>({
isApplying: false,
status: '',
fullPageTakeover: false,
startedAt: 0,
});
const [watermarkBusyElapsedSeconds, setWatermarkBusyElapsedSeconds] = useState(0);

const handleWatermarkApplyStateChange = useCallback(
(state: { isApplying: boolean; status: string; fullPageTakeover: boolean }) => {
setWatermarkBusy((prev) => ({
isApplying: state.isApplying,
status: state.status,
fullPageTakeover: state.fullPageTakeover,
startedAt: state.isApplying ? (prev.isApplying ? prev.startedAt : Date.now()) : 0,
}));
},
[],
);

useEffect(() => {
if (!watermarkBusy.isApplying || watermarkBusy.startedAt === 0) {
setWatermarkBusyElapsedSeconds(0);
return;
}

const tick = () => {
setWatermarkBusyElapsedSeconds(
Math.max(0, Math.floor((Date.now() - watermarkBusy.startedAt) / 1000)),
);
};

tick();
const intervalId = globalThis.setInterval(tick, 1000);
return () => globalThis.clearInterval(intervalId);
}, [watermarkBusy.isApplying, watermarkBusy.startedAt]);

const plugins = useMemo(
() => [
Expand Down Expand Up @@ -98,6 +143,7 @@ function App() {
width: 120,
paddingY: 10,
}),
createPluginRegistration(WatermarkPluginPackage),
],
[],
);
Expand Down Expand Up @@ -189,6 +235,18 @@ function App() {
position: 'left',
props: { documentId: activeDocumentId },
},
{
id: 'watermark',
component: WatermarkPanel,
icon: BrandingWatermarkOutlinedIcon,
label: 'Watermark',
position: 'right',
props: {
documentId: activeDocumentId,
takeoverPlacementThreshold: WATERMARK_TAKEOVER_PLACEMENT_THRESHOLD,
onApplyStateChange: handleWatermarkApplyStateChange,
},
},
];

return (
Expand Down Expand Up @@ -328,6 +386,52 @@ function App() {
{/* Right Sidebar */}
<Drawer position="right" />
</Box>

{watermarkBusy.isApplying && watermarkBusy.fullPageTakeover && (
<Box
sx={{
position: 'absolute',
inset: 0,
zIndex: 2500,
backgroundColor: 'rgba(17, 24, 39, 0.45)',
backdropFilter: 'blur(2px)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
p: 3,
}}
>
<Box
sx={{
width: 'min(560px, 92vw)',
bgcolor: 'background.paper',
borderRadius: 2,
boxShadow: 6,
p: 3,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: 1.25,
textAlign: 'center',
}}
>
<CircularProgress size={34} />
<Alert severity="info" sx={{ width: '100%' }}>
{watermarkBusy.status || 'Applying watermark across pages...'}
</Alert>
<Box>
<Box sx={{ fontSize: 13, color: 'text.secondary' }}>
Viewer interactions are paused while watermark processing is in progress.
</Box>
{watermarkBusyElapsedSeconds >= 15 && (
<Box sx={{ fontSize: 13, color: 'text.secondary', mt: 0.5 }}>
Still running ({watermarkBusyElapsedSeconds}s). Large documents can take a while.
</Box>
)}
</Box>
</Box>
</Box>
)}
</Box>
</DrawerProvider>
);
Expand Down
1 change: 1 addition & 0 deletions examples/react-mui/src/components/toolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ export const Toolbar = ({ documentId }: ToolbarProps) => {
<Tab label="Redact" value="redact" />
</Tabs>
</Box>
<DrawerToggleButton componentId="watermark" />
<DrawerToggleButton componentId="search" />
</MuiToolbar>
</AppBar>
Expand Down
Loading