import React, { useEffect, useState } from 'react'; import { Plus, Upload, Target } from '../icons'; import CanaryTokenDrawer from './CanaryTokenDrawer'; import type { CanaryTokenRow } from './CanaryTokenDrawer'; import { STATE_COLOR } from './CanaryTokens/types'; import { Stat } from './CanaryTokens/ui'; import { extractError } from './CanaryTokens/helpers'; import { useCanaryTokens } from './CanaryTokens/useCanaryTokens'; import { CreateTokenModal } from './CanaryTokens/CreateTokenModal'; import { UploadModal } from './CanaryTokens/UploadModal'; import { FileDropModal, loadFileDrops, saveFileDrops, type FileDropEntry, } from './CanaryTokens/FileDropModal'; import { TokenListView, type StateFilter, type ScopeFilter, } from './CanaryTokens/TokenListView'; import { BlobListView } from './CanaryTokens/BlobListView'; import { FileDropListView } from './CanaryTokens/FileDropListView'; type Tab = 'tokens' | 'blobs' | 'filedrops'; const CanaryTokens: React.FC = () => { const { tokens, blobs, deckies, topologies, loading, error, prependToken, prependBlob, markTokenRevoked, deleteBlob, } = useCanaryTokens(); // Pure-UI state. The local fileDrops log lives entirely in the // browser; the server doesn't persist it. const [tab, setTab] = useState('tokens'); const [fileDrops, setFileDrops] = useState(() => loadFileDrops()); const [filter, setFilter] = useState(''); const [stateFilter, setStateFilter] = useState('all'); const [scopeFilter, setScopeFilter] = useState('all'); const [showCreate, setShowCreate] = useState(false); const [showUpload, setShowUpload] = useState(false); const [showFileDrop, setShowFileDrop] = useState(false); const [drawerToken, setDrawerToken] = useState(null); // Alt+C / Alt+D — open create-token / drop-file modals // (per feedback_linux_meta_key — never Meta/⌘ on Linux). useEffect(() => { const handler = (e: KeyboardEvent) => { const anyModalOpen = showCreate || showUpload || showFileDrop || drawerToken; if (anyModalOpen) return; if (e.altKey && e.key.toLowerCase() === 'c') { e.preventDefault(); setShowCreate(true); } else if (e.altKey && e.key.toLowerCase() === 'd') { e.preventDefault(); setShowFileDrop(true); } }; window.addEventListener('keydown', handler); return () => window.removeEventListener('keydown', handler); }, [showCreate, showUpload, showFileDrop, drawerToken]); const counts = (() => { const c = { planted: 0, revoked: 0, failed: 0, hits: 0 }; for (const t of tokens) { c[t.state] += 1; c.hits += t.trigger_count; } return c; })(); const handleDeleteBlob = async (uuid: string) => { if (!window.confirm('Delete this blob? Refused if any token still references it.')) return; const r = await deleteBlob(uuid); if (!r.ok) alert(extractError(r.reason, 'Delete failed.')); }; const handleClearFileDrops = () => { if (!window.confirm('Clear local file drop history? This does not delete dropped files.')) return; setFileDrops([]); saveFileDrops([]); }; return (

CANARY TOKENS

{tokens.length} TOKEN{tokens.length === 1 ? '' : 'S'} · {counts.planted} PLANTED · {counts.hits} TOTAL HIT{counts.hits === 1 ? '' : 'S'} · {blobs.length} UPLOADED BLOB{blobs.length === 1 ? '' : 'S'}
{(['tokens', 'blobs', 'filedrops'] as const).map((t) => ( ))}
{tab === 'tokens' && ( )} {tab === 'blobs' && ( )} {tab === 'filedrops' && ( )} {showCreate && ( setShowCreate(false)} onCreated={(t) => { prependToken(t); setShowCreate(false); }} /> )} {showUpload && ( setShowUpload(false)} onUploaded={(b) => { prependBlob(b); setShowUpload(false); }} /> )} {drawerToken && ( setDrawerToken(null)} onRevoked={(uuid) => { markTokenRevoked(uuid); setDrawerToken(null); }} /> )} {showFileDrop && ( setShowFileDrop(false)} onDropped={(entry) => { setFileDrops((prev) => { const next = [entry, ...prev].slice(0, 200); saveFileDrops(next); return next; }); setShowFileDrop(false); setTab('filedrops'); }} /> )}
); }; export default CanaryTokens;