Panic.tsx

4.9 KB · raw

1import { createSignal, Show, Switch, Match } from "solid-js";2import { sendMessage } from "../App";34interface PanicProps {5  onCancel: () => void;6  onOpenExport: () => void;7  onDestroyed: () => void | Promise<void>;8}910export function PanicView(props: PanicProps) {11  const [step, setStep] = createSignal<1 | 2 | 3>(1);12  const [confirmText, setConfirmText] = createSignal("");13  const [destroying, setDestroying] = createSignal(false);1415  const canDestroy = () => confirmText() === "DESTROY";1617  async function handleDestroy() {18    if (destroying()) return;19    setDestroying(true);20    const res = await sendMessage({ type: "DESTROY_VAULT" });21    if (!res?.ok) {22      setDestroying(false);23      return;24    }25    await props.onDestroyed();26  }2728  return (29    <Switch>30      <Match when={step() === 1}>31        <div class="peach-panic">32          <h2 class="peach-panic-title">Before you destroy your vault</h2>33          <p class="peach-panic-body">34            Once destroyed, your vault cannot be recovered. Ever. There is no35            undo, no support ticket, no way back.36          </p>37          <p class="peach-panic-body">38            If you haven't already, export your vault now. It takes ten seconds39            and you'll be glad you did.40          </p>41          <button42            class="peach-panic-button peach-panic-button--primary"43            onClick={() => props.onOpenExport()}44          >45            Export my vault first46          </button>47          <div class="peach-panic-divider"></div>48          <p class="peach-panic-body">49            I have already exported my vault or I don't want to.50          </p>51          <button class="peach-panic-link" onClick={() => setStep(2)}>52            Continue to destruction →53          </button>54          <div class="peach-panic-actions">55            <button56              class="peach-panic-button peach-panic-button--ghost"57              onClick={() => props.onCancel()}58            >59              Back to settings60            </button>61          </div>62        </div>63      </Match>6465      <Match when={step() === 2}>66        <div class="peach-panic peach-panic-step2">67          <span class="peach-panic-icon" aria-hidden="true">⚠</span>68          <h2 class="peach-panic-title peach-panic-title--severe">69            This will permanently destroy your vault.70          </h2>71          <p class="peach-panic-body peach-panic-body--severe">72            Every password, card, passkey, note, and setting will be wiped from73            this device. This cannot be undone.74          </p>75          <p class="peach-panic-confirm-label">Type DESTROY to confirm:</p>76          <input77            class="peach-panic-confirm-input"78            classList={{ "peach-panic-confirm-input--match": canDestroy() }}79            type="text"80            value={confirmText()}81            onInput={(e) => setConfirmText(e.currentTarget.value)}82            autocomplete="off"83            spellcheck={false}84            autocapitalize="off"85            aria-label="Type DESTROY to confirm"86          />87          <div class="peach-panic-actions">88            <button89              class="peach-panic-button peach-panic-button--danger"90              disabled={!canDestroy()}91              onClick={() => setStep(3)}92            >93              Yes, destroy my vault94            </button>95            <button96              class="peach-panic-button peach-panic-button--ghost"97              onClick={() => {98                setConfirmText("");99                props.onCancel();100              }}101            >102              Cancel — keep my vault103            </button>104          </div>105        </div>106      </Match>107108      <Match when={step() === 3}>109        <div class="peach-panic peach-panic-step3">110          <div class="peach-panic-bar">THIS IS YOUR LAST CHANCE</div>111          <p class="peach-panic-body peach-panic-body--final-intro">112            Your vault is about to be permanently destroyed.113          </p>114          <p class="peach-panic-body peach-panic-body--final">115            There is no recovery.116            <br />117            There is no support.118            <br />119            There is no undo.120          </p>121          <div class="peach-panic-divider"></div>122          <div class="peach-panic-actions">123            <button124              class="peach-panic-final-button"125              disabled={destroying()}126              onClick={() => void handleDestroy()}127            >128              {destroying() ? "Destroying…" : "Destroy my vault forever"}129            </button>130            <Show when={!destroying()}>131              <button132                class="peach-panic-button peach-panic-button--ghost"133                onClick={() => {134                  setConfirmText("");135                  setStep(1);136                }}137              >138                No — take me back139              </button>140            </Show>141          </div>142        </div>143      </Match>144    </Switch>145  );146}