import { Button } from '@/components/ui/Button/Button' import { Chip } from '@/components/ui/Chip/Chip' import { Divider } from '@/components/ui/Divider/Divider' import { MenuItem } from '@/components/ui/MenuItem/MenuItem' import { Skeleton } from '@/components/ui/Skeleton/Skeleton' import { Stack } from '@/components/ui/Stack/Stack' import { Text } from '@/components/ui/Text/Text' import { dbSqlite } from '@/nostr/db' import { spacing } from '@/themes/spacing.stylex' import { IconDatabase } from '@tabler/icons-react' import { useEffect, useState } from 'react' import { css } from 'react-strict-dom' const formatter = new Intl.NumberFormat() const DB_NAME = import.meta.env.VITE_DB_NAME export const SettingsStorageRoute = () => { const [totalEvents, setTotalEvents] = useState(null) const [totalTags, setTotalTags] = useState(null) const [dbSizeBytes, setDbSizeBytes] = useState(null) const [exporting, setExporting] = useState(false) const [confirmDelete, setConfirmDelete] = useState(false) const [deleting, setDeleting] = useState(false) useEffect(() => { const load = async () => { const [events, tags, size] = await Promise.all([ dbSqlite.countEvents(), dbSqlite.countTags(), dbSqlite.dbSizeBytes(), ]) setTotalEvents(events) setTotalTags(tags) setDbSizeBytes(size) } load() }, []) const handleExport = async () => { try { setExporting(true) const bytes = await dbSqlite.exportDB() const blob = new Blob([bytes as BlobPart], { type: 'application/octet-stream' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `${DB_NAME}.sqlite3` a.click() URL.revokeObjectURL(url) } finally { setExporting(false) } } const handleDelete = async () => { if (!confirmDelete) { setConfirmDelete(true) return } try { setDeleting(true) await dbSqlite.deleteDB() setTotalEvents(0) setTotalTags(0) setDbSizeBytes(0) } finally { setDeleting(false) setConfirmDelete(false) } } return ( Cache Relay } label='SQLite (WASM)' /> {dbSizeBytes !== null ? ( formatter.format(dbSizeBytes / (1024 * 1024)) + ' MB' ) : ( )} } /> {totalEvents !== null ? ( formatter.format(totalEvents) ) : ( )} } /> {totalTags !== null ? ( formatter.format(totalTags) ) : ( )} } /> {exporting ? 'Exporting…' : 'Export database'} } /> {confirmDelete ? 'Confirm delete database?' : deleting ? 'Deleting…' : 'Delete database'} } /> ) } const styles = css.create({ container: { height: '100%', }, root: { width: '100%', overflowY: 'auto', paddingBottom: spacing.padding3, }, header: { padding: spacing.padding2, height: 60, }, middle: { paddingBlock: spacing.padding2, }, number: { fontFamily: 'monospace', }, skeleton: { width: 18, height: 24, }, })