mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: add Sign PDF tool (draw/type/upload signatures, place on a PDF) (#370)
Draw, type, or upload a signature and place resizable/rotatable copies across PDF pages; output flattened server-side with PyMuPDF. Visual electronic signature, not cryptographic. New interactive-sign display mode (pdf.js + Konva) and a custom docs-pool route.
This commit is contained in:
@@ -36,6 +36,7 @@ import { CropCanvas } from "@/components/tools/crop-canvas";
|
||||
import type { EraserCanvasRef } from "@/components/tools/eraser-canvas";
|
||||
import { EraserCanvas } from "@/components/tools/eraser-canvas";
|
||||
import type { PreviewTransform } from "@/components/tools/rotate-settings";
|
||||
import { SignCanvas, type SignCanvasRef } from "@/components/tools/sign-canvas";
|
||||
import { useTranslation } from "@/contexts/i18n-context";
|
||||
import { useAuth } from "@/hooks/use-auth";
|
||||
import { useMobile } from "@/hooks/use-mobile";
|
||||
@@ -359,6 +360,11 @@ export function ToolPage() {
|
||||
// Center of the painted mask as a 0-100 percentage — used to init the slider at the right spot
|
||||
const [eraserSliderInitPos, setEraserSliderInitPos] = useState<number | null>(null);
|
||||
|
||||
// Sign state
|
||||
const signCanvasRef = useRef<SignCanvasRef | null>(null);
|
||||
const [signHasSelection, setSignHasSelection] = useState(false);
|
||||
const [signPlacementCount, setSignPlacementCount] = useState(0);
|
||||
|
||||
// Page-level drag overlay state
|
||||
const [isDraggingOver, setIsDraggingOver] = useState(false);
|
||||
const dragCounter = useRef(0);
|
||||
@@ -651,6 +657,14 @@ export function ToolPage() {
|
||||
maskedFileCount: eraserMaskedCount,
|
||||
}
|
||||
: undefined,
|
||||
signProps:
|
||||
displayMode === "interactive-sign"
|
||||
? {
|
||||
canvasRef: signCanvasRef,
|
||||
hasSelection: signHasSelection,
|
||||
placementCount: signPlacementCount,
|
||||
}
|
||||
: undefined,
|
||||
};
|
||||
|
||||
const ToolSettings = registryEntry.Settings;
|
||||
@@ -843,6 +857,17 @@ export function ToolPage() {
|
||||
);
|
||||
}
|
||||
|
||||
if (displayMode === "interactive-sign" && hasFile && originalBlobUrl) {
|
||||
return (
|
||||
<SignCanvas
|
||||
ref={signCanvasRef}
|
||||
fileUrl={originalBlobUrl}
|
||||
onSelectionChange={setSignHasSelection}
|
||||
onCountChange={setSignPlacementCount}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (displayMode === "interactive-split" && hasFile && originalBlobUrl) {
|
||||
if (registryEntry?.ResultsPanel) {
|
||||
const Panel = registryEntry.ResultsPanel;
|
||||
|
||||
Reference in New Issue
Block a user