diff --git a/src/islands/dev/TextEncrypt.tsx b/src/islands/dev/TextEncrypt.tsx new file mode 100644 index 0000000..625822d --- /dev/null +++ b/src/islands/dev/TextEncrypt.tsx @@ -0,0 +1,97 @@ +import { useState } from 'react'; +import { Lock, Unlock } from 'lucide-react'; +import { Button } from '@/components/ui/Button'; +import { TextArea } from '@/components/ui/TextArea'; +import { CopyButton } from '@/components/ui/CopyButton'; +import { encryptText, decryptText } from '@/tools/dev/textcrypt.lib'; +import type { Lang } from '@/i18n/config'; + +type Mode = 'encrypt' | 'decrypt'; + +const TR: Record> = { + en: { + intro: 'Encrypt a message with a password (AES-256) so only someone with the password can read it — then share the scrambled text safely. All in your browser; the password never leaves your device.', + encrypt: 'Encrypt', decrypt: 'Decrypt', password: 'Password', + inEnc: 'Message to encrypt', inDec: 'Encrypted text to decrypt', + outEnc: 'Encrypted text', outDec: 'Decrypted message', + run: 'Encrypt', runDec: 'Decrypt', copy: 'Copy', + needPw: 'Enter a password.', failEnc: 'Could not encrypt.', failDec: 'Wrong password or invalid text.', + placeholderEnc: 'Type a secret message…', placeholderDec: 'Paste the encrypted text…', + }, + id: { + intro: 'Enkripsi pesan dengan kata sandi (AES-256) agar hanya yang punya kata sandi bisa membacanya — lalu bagikan teks teracak dengan aman. Semua di browser Anda; kata sandi tidak pernah keluar dari perangkat.', + encrypt: 'Enkripsi', decrypt: 'Dekripsi', password: 'Kata sandi', + inEnc: 'Pesan untuk dienkripsi', inDec: 'Teks terenkripsi untuk didekripsi', + outEnc: 'Teks terenkripsi', outDec: 'Pesan terdekripsi', + run: 'Enkripsi', runDec: 'Dekripsi', copy: 'Salin', + needPw: 'Masukkan kata sandi.', failEnc: 'Tidak dapat mengenkripsi.', failDec: 'Kata sandi salah atau teks tidak valid.', + placeholderEnc: 'Ketik pesan rahasia…', placeholderDec: 'Tempel teks terenkripsi…', + }, +}; + +export default function TextEncrypt({ lang = 'en' }: { lang?: Lang }) { + const t = TR[lang] ?? TR.en; + const [mode, setMode] = useState('encrypt'); + const [text, setText] = useState(''); + const [password, setPassword] = useState(''); + const [out, setOut] = useState(''); + const [busy, setBusy] = useState(false); + const [error, setError] = useState(''); + + const run = async () => { + if (!password) { setError(t.needPw); return; } + setBusy(true); setError(''); setOut(''); + try { + setOut(mode === 'encrypt' ? await encryptText(text, password) : await decryptText(text, password)); + } catch { + setError(mode === 'encrypt' ? t.failEnc : t.failDec); + } finally { + setBusy(false); + } + }; + + const switchMode = (m: Mode) => { setMode(m); setOut(''); setError(''); }; + + return ( +
+

{t.intro}

+ +
+ + +
+ +
+ {mode === 'encrypt' ? t.inEnc : t.inDec} +