mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-14 10:34:06 +02:00
## Summary - propagate an `isEncrypted` flag from thumbnail generation into processed file metadata so uploads know when a password is still present - add queueing logic inside `FileContext` that detects encrypted uploads, prompts the user via a new modal, and automatically runs the Remove Password endpoint to replace the file and preserve history - introduce a dedicated `EncryptedPdfUnlockModal` component that mirrors existing styling and messaging for unlocking PDFs ## Testing - npm run typecheck:core ------ [Codex Task](https://chatgpt.com/codex/tasks/task_b_6919a0a418bc8328b886ec76a28170b7)
86 lines
2.6 KiB
TypeScript
86 lines
2.6 KiB
TypeScript
import { Modal, Stack, Text, Button, PasswordInput, Group } from '@mantine/core';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { type KeyboardEventHandler } from 'react';
|
|
import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from '@app/styles/zIndex';
|
|
|
|
interface EncryptedPdfUnlockModalProps {
|
|
opened: boolean;
|
|
fileName?: string;
|
|
password: string;
|
|
errorMessage?: string | null;
|
|
isProcessing: boolean;
|
|
onPasswordChange: (value: string) => void;
|
|
onUnlock: () => void;
|
|
onSkip: () => void;
|
|
}
|
|
|
|
const EncryptedPdfUnlockModal = ({
|
|
opened,
|
|
fileName,
|
|
password,
|
|
errorMessage,
|
|
isProcessing,
|
|
onPasswordChange,
|
|
onUnlock,
|
|
onSkip,
|
|
}: EncryptedPdfUnlockModalProps) => {
|
|
const { t } = useTranslation();
|
|
|
|
const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = (event) => {
|
|
if (event.key === 'Enter' && !isProcessing && password.trim().length > 0) {
|
|
onUnlock();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Modal
|
|
opened={opened}
|
|
onClose={onSkip}
|
|
title={t('encryptedPdfUnlock.title', 'Remove password to continue')}
|
|
centered
|
|
size="md"
|
|
closeOnClickOutside={!isProcessing}
|
|
closeOnEscape={!isProcessing}
|
|
zIndex={Z_INDEX_OVER_FULLSCREEN_SURFACE}
|
|
>
|
|
<Stack gap="md">
|
|
<Text fw={600} ta="center">{fileName}</Text>
|
|
<Text c="dimmed" ta="center">
|
|
{t(
|
|
'encryptedPdfUnlock.description',
|
|
'This PDF is password protected. Enter the password so you can continue working with it.'
|
|
)}
|
|
</Text>
|
|
|
|
<Stack gap={4}>
|
|
<PasswordInput
|
|
label={t('encryptedPdfUnlock.password.label', 'PDF password')}
|
|
placeholder={t('encryptedPdfUnlock.password.placeholder', 'Enter the PDF password')}
|
|
value={password}
|
|
onChange={(event) => onPasswordChange(event.currentTarget.value)}
|
|
onKeyDown={handleKeyDown}
|
|
disabled={isProcessing}
|
|
autoFocus
|
|
/>
|
|
{errorMessage ? (
|
|
<Text c="red" size="sm">
|
|
{errorMessage}
|
|
</Text>
|
|
) : null}
|
|
</Stack>
|
|
|
|
<Group justify="space-between">
|
|
<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>
|
|
</Stack>
|
|
</Modal>
|
|
);
|
|
};
|
|
|
|
export default EncryptedPdfUnlockModal;
|