import { useState, useEffect } from 'react'; import { Wrench, Download, Upload, RotateCcw, Database, FileText, HardDrive, X, Loader2, Cpu, ChevronRight, AlertCircle } from 'lucide-react'; import { toast } from 'sonner'; import { getFileContents, putFileContents, humanFileSize } from '../webdav'; interface ToolsPageProps { config: any; setConfig: (config: any) => void; } interface FirmwareEntry { version: string; date: string; description: string; url: string; size?: number; } function FirmwareOverlay({ onClose }: { onClose: () => void }) { const [entries, setEntries] = useState(null); const [loadError, setLoadError] = useState(null); const [installing, setInstalling] = useState(null); useEffect(() => { getFileContents('/.sys/firmware.json') .then(async (blob) => { const parsed = JSON.parse(await blob.text()); if (Array.isArray(parsed)) { setEntries(parsed); } else { setLoadError('Unexpected firmware manifest format.'); } }) .catch((e: any) => setLoadError(e?.message || 'Failed to load firmware list.')); }, []); const install = async (entry: FirmwareEntry) => { setInstalling(entry.url); try { let data: ArrayBuffer; if (/^https?:\/\//.test(entry.url)) { const r = await fetch(entry.url); if (!r.ok) throw new Error(`Download failed: ${r.status} ${r.statusText}`); data = await r.arrayBuffer(); } else { const blob = await getFileContents(entry.url); data = await blob.arrayBuffer(); } await putFileContents('/sd/.bin', data); toast.success(`Firmware ${entry.version} saved to /sd/.bin`); onClose(); } catch (e: any) { toast.error(`Install failed: ${e?.message || String(e)}`); } finally { setInstalling(null); } }; return (

Change Firmware

Selected firmware will be saved to /sd/.bin

{entries === null && !loadError && (
Loading firmware list…
)} {loadError && (
{loadError}
)} {entries && entries.length === 0 && (
No firmware updates available.
)} {entries && entries.map((entry) => { const isInstalling = installing === entry.url; const busy = installing !== null; return (
{entry.version} {entry.date} {entry.size != null && ( · {humanFileSize(entry.size)} )}

{entry.description}

); })}
); } export default function ToolsPage({ config }: ToolsPageProps) { const [showFirmware, setShowFirmware] = useState(false); const handleBackup = () => { const dataStr = JSON.stringify(config, null, 2); const dataUri = 'data:application/json;charset=utf-8,' + encodeURIComponent(dataStr); const exportFileDefaultName = `meatloaf-config-${new Date().toISOString().split('T')[0]}.json`; const linkElement = document.createElement('a'); linkElement.setAttribute('href', dataUri); linkElement.setAttribute('download', exportFileDefaultName); linkElement.click(); toast.success('Configuration backed up'); }; const handleRestore = () => { const input = document.createElement('input'); input.type = 'file'; input.accept = '.json'; input.onchange = (e: any) => { const file = e.target.files[0]; const reader = new FileReader(); reader.onload = (event: any) => { try { const config = JSON.parse(event.target.result); toast.success('Configuration restored'); console.log('Restored config:', config); } catch (error) { toast.error('Invalid configuration file'); } }; reader.readAsText(file); }; input.click(); }; const handleFactoryReset = () => { if (confirm('Are you sure you want to reset to factory defaults? This cannot be undone.')) { toast.success('Configuration reset to factory defaults'); } }; const handleFormatSD = () => { if (confirm('Are you sure you want to format the SD card? All data will be lost.')) { toast.success('SD card formatting started'); } }; const handleSystemUpdate = () => { toast.loading('Checking for updates...'); setTimeout(() => { toast.dismiss(); toast.success('System is up to date'); }, 2000); }; const handleExportLogs = () => { toast.success('System logs exported'); }; return (
System Information
Firmware Version v2.5.1
Hardware Revision Rev C
Serial Number ML-2024-0420

System Tools

Storage Tools

Storage Info
4.2 GB used of 8 GB
{showFirmware && setShowFirmware(false)} />}
); }