diff --git a/frontend/src/pages/Editor.tsx b/frontend/src/pages/Editor.tsx index e3e549c..07163dd 100644 --- a/frontend/src/pages/Editor.tsx +++ b/frontend/src/pages/Editor.tsx @@ -3,8 +3,11 @@ import { DownloadSimpleIcon, ImageIcon, LockIcon, + QuestionIcon, SpinnerGapIcon, + StampIcon, TrayIcon, + VaultIcon, XCircleIcon, XIcon, } from "@phosphor-icons/react"; @@ -53,9 +56,12 @@ export default function Editor() { const [isInitialLoading, setIsInitialLoading] = useState(false); const [shareLink, setShareLink] = useState(null); const [lastSaved, setLastSaved] = useState(null); - const [status, setStatus] = useState<"DRAFT" | "SEALED">("DRAFT"); + const [status, setLetterStatus] = useState<"DRAFT" | "SEALED" | "VAULT">( + "DRAFT", + ); const [isSaveDatePulsing, setIsSaveDatePulsing] = useState(false); const [lastSavedPulseTick, setLastSavedPulseTick] = useState(0); + const [sealBtnClicked, setSealBtnClicked] = useState(false); const [saveOverlay, setSaveOverlay] = useState("idle"); const [showSaveOverlay, setShowSaveOverlay] = useState(false); @@ -66,6 +72,27 @@ export default function Editor() { const canvasRef = useRef(null); const fileInputRef = useRef(null); + const [offset, setOffset] = useState(0); + const toPlaceholderList = [ + "Someone dear...", + "Somewhere near...", + "Something to bear...", + ]; + const [toPlaceholder, setToPlaceholder] = useState(toPlaceholderList[0]); + + useEffect(() => { + const interval = setInterval(() => { + setOffset((offset) => { + const nextOffset = offset + 1; + setToPlaceholder(toPlaceholderList[offset % toPlaceholderList.length]); + console.log("Setting to ", toPlaceholder); + return nextOffset; + }); + }, 4000); + + return () => clearInterval(interval); + }, [offset, toPlaceholder]); + useEffect(() => { if (!(public_id && masterKey)) return; if (justSavedRef.current) { @@ -82,7 +109,7 @@ export default function Editor() { const letterData = res.data; setLastSaved(formatRelativeDate(new Date(letterData.updated_at))); - setStatus(letterData.status); + setLetterStatus(letterData.status); if (letterData.status === "SEALED") { navigateRef.current(PATHS.read(public_id), { replace: true }); @@ -192,7 +219,11 @@ export default function Editor() { } }; - const handleSave = async (status: "SEALED" | "DRAFT"): Promise => { + const handleSave = async ( + status: "SEALED" | "DRAFT" | "VAULT", + ): Promise => { + setSealBtnClicked(false); + let targetId = public_id || letterIdRef.current; if (!targetId) { targetId = crypto.randomUUID(); @@ -228,9 +259,15 @@ export default function Editor() { ); const formData = new FormData(); + if (status === "VAULT") { + formData.append("type", "VAULT"); + formData.append("unlock_at", ""); + formData.append("status", "SEALED"); + } else { + formData.append("type", "KEPT"); + formData.append("status", status); + } formData.append("public_id", targetId); - formData.append("type", "KEPT"); - formData.append("status", status); formData.append("encrypted_content", encrypted_letter.encrypted_content); formData.append("encrypted_dek", encrypted_letter.encrypted_dek); formData.append( @@ -251,7 +288,7 @@ export default function Editor() { } setLastSaved(formatRelativeDate(new Date())); - setStatus(status); + setLetterStatus(status); setLastSavedPulseTick((prev) => prev + 1); if (status === "SEALED" && encrypted_letter.sharingKey) { @@ -276,6 +313,115 @@ export default function Editor() { await navigator.clipboard.writeText(shareLink); }; + function ToolBar() { + return ( +
+
+ + +
+ +
+ + +
+ + +
+ +
+ +
+ or +
+ +
+ +
+ ); + } + + function LetterHead() { + return ( +
+
+ + + Sealed & View Only + +
+
+ ); + } + return ( <> -

Last Save @@ -297,6 +438,11 @@ export default function Editor() {
{lastSaved}

+
} /> @@ -441,7 +587,7 @@ export default function Editor() { setRecipient(e.target.value)} @@ -451,61 +597,7 @@ export default function Editor() { - {status === "DRAFT" ? ( -
-
- - -
- -
- - -
- - -
-
- ) : ( -
-
- - - Sealed & View Only - -
-
- )} + {status === "DRAFT" ? : }