import { useState } from 'react'; import { Keystore, LocalStorageAdapter } from '@dgb-wallet/keystore'; import { useActiveSeed } from './ActiveSeed.js'; import { useOrderedWallets, useListDrag, renameWallet, notifyWalletsChanged } from './wallet-order.js'; const keystore = new Keystore(new LocalStorageAdapter()); // Left sidebar shown on desktop (>=1024px). Lists every saved wallet // with click-to-switch, plus the Create/Import CTAs. Mirrors the // WalletMenu dropdown that stays available on mobile — same actions, // permanent surface. Keeps the current wallet visually highlighted. // No Explorer / Settings entries here — both live as pills in the // dashboard's right-side panel, so a copy here was a duplicate. // // Rows are drag-and-drop reorderable; the order persists (wallet-order.ts) // and is shared with the wallet menu and the login picker. The first // wallet in the list is the one that opens automatically after unlock. export function WalletSidebar({ onSwitchWallet, onCreate, onImport, }: { onSwitchWallet: (label: string) => void; onCreate: () => void; onImport: () => void; }): JSX.Element { const { active, relabel } = useActiveSeed(); const { wallets, move, reload } = useOrderedWallets(active?.setAt); const drag = useListDrag(move); // Inline rename: hover a row → pencil → the label becomes an input. // Enter saves, Escape cancels. Errors (duplicate / empty) show under // the row until the next keystroke. const [editing, setEditing] = useState(null); const [draft, setDraft] = useState(''); const [renameErr, setRenameErr] = useState(null); function startRename(label: string): void { setEditing(label); setDraft(label); setRenameErr(null); } function cancelRename(): void { setEditing(null); setRenameErr(null); } async function commitRename(): Promise { if (!editing) return; const from = editing; try { const to = await renameWallet(from, draft); if (active?.label === from) relabel(to); setEditing(null); setRenameErr(null); reload(); } catch (e) { setRenameErr((e as Error).message.replace(/^keystore: /, '')); } } // Delete an encrypted seed from the keystore. Guarded elsewhere so it // never runs on the currently-active wallet — the button is disabled // for that row and this function double-checks defensively. Uses the // native confirm dialog because deletion is irreversible and typing // through a modal for this would just be noise. async function forgetWallet(label: string): Promise { if (active?.label === label) return; if (!confirm(`Delete encrypted seed "${label}"? This can't be undone. If you don't have the seed phrase written down, the funds become unrecoverable.`)) return; await keystore.delete(label); notifyWalletsChanged(); reload(); } return ( ); }