undo silly AI stuff

This commit is contained in:
EthanHealy01 2025-12-16 14:19:59 +00:00
parent 70ac8af978
commit 7864d1c4e2
2 changed files with 39 additions and 101 deletions

View File

@ -1,27 +1,18 @@
import { Modal, Text, Button, Group, Stack } from "@mantine/core";
import { useNavigationGuard, useNavigationState } from "@app/contexts/NavigationContext";
import { useNavigationGuard } from "@app/contexts/NavigationContext";
import { useTranslation } from "react-i18next";
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
import CheckCircleOutlineIcon from "@mui/icons-material/CheckCircleOutline";
import { useRedactionMode } from "@app/contexts/RedactionContext";
import FitText from "@app/components/shared/FitText";
interface NavigationWarningModalProps {
onApplyAndContinue?: () => Promise<void>;
onExportAndContinue?: () => Promise<void>;
}
const NavigationWarningModal = ({ onApplyAndContinue, onExportAndContinue }: NavigationWarningModalProps) => {
const NavigationWarningModal = ({ onApplyAndContinue }: NavigationWarningModalProps) => {
const { t } = useTranslation();
const { showNavigationWarning, hasUnsavedChanges, pendingNavigation, cancelNavigation, confirmNavigation, setHasUnsavedChanges } =
useNavigationGuard();
const { selectedTool } = useNavigationState();
const { pendingCount } = useRedactionMode();
// Check if we're in redact mode with pending redactions
const isRedactMode = selectedTool === 'redact';
const hasPendingRedactions = pendingCount > 0;
const handleKeepWorking = () => {
cancelNavigation();
@ -40,13 +31,6 @@ const NavigationWarningModal = ({ onApplyAndContinue, onExportAndContinue }: Nav
confirmNavigation();
};
const _handleExportAndContinue = async () => {
if (onExportAndContinue) {
await onExportAndContinue();
}
setHasUnsavedChanges(false);
confirmNavigation();
};
const BUTTON_WIDTH = "12rem";
// Only show modal if there are unsaved changes AND there's an actual pending navigation
@ -59,9 +43,7 @@ const NavigationWarningModal = ({ onApplyAndContinue, onExportAndContinue }: Nav
<Modal
opened={showNavigationWarning}
onClose={handleKeepWorking}
title={isRedactMode && hasPendingRedactions
? t("pendingRedactionsTitle", "Unapplied Redactions")
: t("unsavedChangesTitle", "Unsaved Changes")}
title={t("unsavedChangesTitle", "Unsaved Changes")}
centered
size="auto"
closeOnClickOutside={true}
@ -70,9 +52,7 @@ const NavigationWarningModal = ({ onApplyAndContinue, onExportAndContinue }: Nav
<Stack>
<Stack ta="center" p="md">
<Text size="md" fw="300">
{isRedactMode && hasPendingRedactions
? t("pendingRedactions", "You have unapplied redactions that will be lost.")
: t("unsavedChanges", "You have unsaved changes to your PDF.")}
{t("unsavedChanges", "You have unsaved changes to your PDF.")}
</Text>
<Text size="lg" fw="500" >
{t("areYouSure", "Are you sure you want to leave?")}
@ -83,24 +63,16 @@ const NavigationWarningModal = ({ onApplyAndContinue, onExportAndContinue }: Nav
<Group justify="space-between" gap="xl" visibleFrom="md">
<Group gap="sm">
<Button variant="light" color="var(--mantine-color-gray-8)" onClick={handleKeepWorking} w={BUTTON_WIDTH} leftSection={<ArrowBackIcon fontSize="small" />}>
<FitText text={t("keepWorking", "Keep Working")} minimumFontScale={0.55} />
{t("keepWorking", "Keep Working")}
</Button>
</Group>
<Group gap="sm">
<Button variant="filled" color="var(--mantine-color-red-9)" onClick={handleDiscardChanges} w={BUTTON_WIDTH} leftSection={<DeleteOutlineIcon fontSize="small" />}>
<FitText
text={isRedactMode && hasPendingRedactions
? t("discardRedactions", "Discard & Leave")
: t("discardChanges", "Discard & Leave")}
minimumFontScale={0.55}
/>
{t("discardChanges", "Discard Changes")}
</Button>
{onApplyAndContinue && (
<Button variant="filled" onClick={handleApplyAndContinue} w={BUTTON_WIDTH} leftSection={<CheckCircleOutlineIcon fontSize="small" />}>
<FitText
text={t("applyAndContinue", "Save & Leave")}
minimumFontScale={0.55}
/>
{t("applyAndContinue", "Apply & Leave")}
</Button>
)}
</Group>
@ -109,22 +81,14 @@ const NavigationWarningModal = ({ onApplyAndContinue, onExportAndContinue }: Nav
{/* Mobile layout: centered stack of 4 buttons */}
<Stack align="center" gap="sm" hiddenFrom="md">
<Button variant="light" color="var(--mantine-color-gray-8)" onClick={handleKeepWorking} w={BUTTON_WIDTH} leftSection={<ArrowBackIcon fontSize="small" />}>
<FitText text={t("keepWorking", "Keep Working")} minimumFontScale={0.55} />
{t("keepWorking", "Keep Working")}
</Button>
<Button variant="filled" color="var(--mantine-color-red-9)" onClick={handleDiscardChanges} w={BUTTON_WIDTH} leftSection={<DeleteOutlineIcon fontSize="small" />}>
<FitText
text={isRedactMode && hasPendingRedactions
? t("discardRedactions", "Discard & Leave")
: t("discardChanges", "Discard & Leave")}
minimumFontScale={0.55}
/>
{t("discardChanges", "Discard Changes")}
</Button>
{onApplyAndContinue && (
<Button variant="filled" onClick={handleApplyAndContinue} w={BUTTON_WIDTH} leftSection={<CheckCircleOutlineIcon fontSize="small" />}>
<FitText
text={t("applyAndContinue", "Save & Leave")}
minimumFontScale={0.55}
/>
{t("applyAndContinue", "Apply & Leave")}
</Button>
)}
</Stack>

View File

@ -7,9 +7,7 @@ import { ViewerContext } from '@app/contexts/ViewerContext';
import { useSignature } from '@app/contexts/SignatureContext';
import { ColorSwatchButton, ColorPicker } from '@app/components/annotation/shared/ColorPicker';
import { useFileState, useFileContext } from '@app/contexts/FileContext';
import { generateThumbnailWithMetadata } from '@app/utils/thumbnailUtils';
import { createProcessedFile } from '@app/contexts/file/fileActions';
import { createStirlingFile, createNewStirlingFileStub } from '@app/types/fileContext';
import { createStirlingFilesAndStubs } from '@app/services/fileStubHelpers';
import { useNavigationState, useNavigationGuard, useNavigationActions } from '@app/contexts/NavigationContext';
import { useSidebarContext } from '@app/contexts/SidebarContext';
import { useToolWorkflow } from '@app/contexts/ToolWorkflowContext';
@ -50,8 +48,8 @@ export default function ViewerAnnotationControls({ currentView, disabled = false
// Get redaction pending state and navigation guard
const { pendingCount: redactionPendingCount, isRedacting: _isRedacting } = useRedactionMode();
const { requestNavigation } = useNavigationGuard();
const { setRedactionMode, activateTextSelection, setRedactionConfig } = useRedaction();
const { requestNavigation, setHasUnsavedChanges } = useNavigationGuard();
const { setRedactionMode, activateTextSelection, setRedactionConfig, setRedactionsApplied } = useRedaction();
// Turn off annotation mode when switching away from viewer
useEffect(() => {
@ -67,37 +65,23 @@ export default function ViewerAnnotationControls({ currentView, disabled = false
// Persist annotations to file if there are unsaved changes
const saveAnnotationsIfNeeded = async () => {
if (!viewerContext?.exportActions?.saveAsCopy || currentView !== 'viewer') return;
const hasUnsavedAnnotations = historyApiRef?.current?.canUndo() || false;
if (!hasUnsavedAnnotations) return;
if (!viewerContext?.exportActions?.saveAsCopy || currentView !== 'viewer' || !historyApiRef?.current?.canUndo()) return;
if (activeFiles.length === 0 || state.files.ids.length === 0) return;
try {
const pdfArrayBuffer = await viewerContext.exportActions.saveAsCopy();
if (!pdfArrayBuffer) return;
const arrayBuffer = await viewerContext.exportActions.saveAsCopy();
if (!arrayBuffer) return;
const blob = new Blob([pdfArrayBuffer], { type: 'application/pdf' });
const originalFileName = activeFiles.length > 0 ? activeFiles[0].name : 'document.pdf';
const newFile = new File([blob], originalFileName, { type: 'application/pdf' });
const file = new File([new Blob([arrayBuffer])], activeFiles[0].name, { type: 'application/pdf' });
const parentStub = selectors.getStirlingFileStub(state.files.ids[0]);
if (!parentStub) return;
if (activeFiles.length > 0) {
const thumbnailResult = await generateThumbnailWithMetadata(newFile);
const processedFileMetadata = createProcessedFile(thumbnailResult.pageCount, thumbnailResult.thumbnail);
const currentFileIds = state.files.ids;
if (currentFileIds.length > 0) {
const currentFileId = currentFileIds[0];
const currentRecord = selectors.getStirlingFileStub(currentFileId);
if (!currentRecord) {
console.error('No file record found for:', currentFileId);
return;
}
const outputStub = createNewStirlingFileStub(newFile, undefined, thumbnailResult.thumbnail, processedFileMetadata);
const outputStirlingFile = createStirlingFile(newFile, outputStub.id);
await fileActions.consumeFiles([currentFileId], [outputStirlingFile], [outputStub]);
}
}
const { stirlingFiles, stubs } = await createStirlingFilesAndStubs([file], parentStub, 'redact');
await fileActions.consumeFiles([state.files.ids[0]], stirlingFiles, stubs);
// Clear unsaved changes flags after successful save
setHasUnsavedChanges(false);
setRedactionsApplied(false);
} catch (error) {
console.error('Error auto-saving annotations before redaction:', error);
}
@ -321,30 +305,20 @@ export default function ViewerAnnotationControls({ currentView, disabled = false
const originalFileName = activeFiles.length > 0 ? activeFiles[0].name : 'document.pdf';
const newFile = new File([blob], originalFileName, { type: 'application/pdf' });
// Replace the current file in context with the saved version (exact same logic as Sign tool)
if (activeFiles.length > 0) {
// Generate thumbnail and metadata for the saved file
const thumbnailResult = await generateThumbnailWithMetadata(newFile);
const processedFileMetadata = createProcessedFile(thumbnailResult.pageCount, thumbnailResult.thumbnail);
// Get current file info
const currentFileIds = state.files.ids;
if (currentFileIds.length > 0) {
const currentFileId = currentFileIds[0];
const currentRecord = selectors.getStirlingFileStub(currentFileId);
if (!currentRecord) {
console.error('No file record found for:', currentFileId);
return;
}
// Create output stub and file (exact same as Sign tool)
const outputStub = createNewStirlingFileStub(newFile, undefined, thumbnailResult.thumbnail, processedFileMetadata);
const outputStirlingFile = createStirlingFile(newFile, outputStub.id);
// Replace the original file with the saved version
await fileActions.consumeFiles([currentFileId], [outputStirlingFile], [outputStub]);
// Replace the current file in context with the saved version
if (activeFiles.length > 0 && state.files.ids.length > 0) {
const parentStub = selectors.getStirlingFileStub(state.files.ids[0]);
if (!parentStub) {
console.error('No file record found for:', state.files.ids[0]);
return;
}
const { stirlingFiles, stubs } = await createStirlingFilesAndStubs([newFile], parentStub, 'multiTool');
await fileActions.consumeFiles([state.files.ids[0]], stirlingFiles, stubs);
// Clear unsaved changes flags after successful save
setHasUnsavedChanges(false);
setRedactionsApplied(false);
}
}
} catch (error) {