Fix encrypted pdf handling (#6088)

Fix and improve encrypted pdf handling
This commit is contained in:
Reece Browne
2026-04-13 13:20:43 +01:00
committed by GitHub
parent d53beb9bce
commit 76aa5c7e2f
12 changed files with 527 additions and 67 deletions
@@ -9,8 +9,10 @@ interface EncryptedPdfUnlockModalProps {
password: string;
errorMessage?: string | null;
isProcessing: boolean;
remainingCount: number;
onPasswordChange: (value: string) => void;
onUnlock: () => void;
onUnlockAll: () => void;
onSkip: () => void;
}
@@ -20,8 +22,10 @@ const EncryptedPdfUnlockModal = ({
password,
errorMessage,
isProcessing,
remainingCount,
onPasswordChange,
onUnlock,
onUnlockAll,
onSkip,
}: EncryptedPdfUnlockModalProps) => {
const { t } = useTranslation();
@@ -75,9 +79,16 @@ const EncryptedPdfUnlockModal = ({
<Button variant="light" color="var(--mantine-color-gray-8)" onClick={onSkip} disabled={isProcessing}>
{t("encryptedPdfUnlock.skip", "Skip for now")}
</Button>
<Button onClick={onUnlock} loading={isProcessing} disabled={password.trim().length === 0}>
{t("encryptedPdfUnlock.unlock", "Unlock & Continue")}
</Button>
<Group gap="xs">
{remainingCount > 0 && (
<Button variant="light" onClick={onUnlockAll} loading={isProcessing} disabled={password.trim().length === 0}>
{t("encryptedPdfUnlock.unlockAll", "Use for all ({{count}})", { count: remainingCount + 1 })}
</Button>
)}
<Button onClick={onUnlock} loading={isProcessing} disabled={password.trim().length === 0}>
{t("encryptedPdfUnlock.unlock", "Unlock & Continue")}
</Button>
</Group>
</Group>
</Stack>
</Modal>
@@ -1,6 +1,7 @@
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
import { Box, Center, Text, ActionIcon } from "@mantine/core";
import { Box, Center, Text, ActionIcon, Button, Stack } from "@mantine/core";
import CloseIcon from "@mui/icons-material/Close";
import LockIcon from "@mui/icons-material/Lock";
import { useFileState, useFileActions } from "@app/contexts/FileContext";
import { useFileWithUrl } from "@app/hooks/useFileWithUrl";
@@ -350,6 +351,13 @@ const EmbedPdfViewerContent = ({
}
}, [previewFile, fileWithUrl]);
// Check if the current file is encrypted (gate the viewer to prevent PDFium crash)
const isCurrentFileEncrypted = React.useMemo(() => {
if (!currentFile || !isStirlingFile(currentFile)) return false;
const stub = selectors.getStirlingFileStub(currentFile.fileId);
return stub?.processedFile?.isEncrypted === true;
}, [currentFile, selectors]);
const bookmarkCacheKey = React.useMemo(() => {
if (currentFile && isStirlingFile(currentFile)) {
return currentFile.fileId;
@@ -1045,7 +1053,7 @@ const EmbedPdfViewerContent = ({
console.log("[FormFill] Fetching form fields for:", currentFileId);
fetchFormFields(currentFile, currentFileId ?? undefined);
}
}, [isFormFillToolActive, currentFile, currentFileId, fetchFormFields]);
}, [isFormFillToolActive, currentFile, currentFileId, fetchFormFields, isCurrentFileEncrypted]);
const sidebarWidthRem = 15;
const commentsSidebarWidthRem = 18;
@@ -1087,6 +1095,23 @@ const EmbedPdfViewerContent = ({
<Center style={{ flex: 1 }}>
<Text c="red">Error: No file provided to viewer</Text>
</Center>
) : isCurrentFileEncrypted ? (
<Center style={{ flex: 1 }}>
<Stack align="center" gap="md">
<LockIcon style={{ fontSize: 48, opacity: 0.5 }} />
<Text fw={500}>This PDF is password-protected</Text>
<Button
variant="filled"
onClick={() => {
if (currentFile && isStirlingFile(currentFile)) {
actions.openEncryptedUnlockPrompt(currentFile.fileId);
}
}}
>
Unlock
</Button>
</Stack>
</Center>
) : (
<>
{/* EmbedPDF Viewer */}