import { useState, useEffect } from 'react'; import { Input } from '../ui/input'; import { Label } from '../ui/label'; import { Button } from '../ui/button'; import { Separator } from '../ui/separator'; import { toast } from '../ui/sonner'; import type { AppSettings, AppSettingsUpdate, HealthStatus, RadioConfig, RadioConfigUpdate, } from '../../types'; export function SettingsIdentitySection({ config, health, appSettings, pageMode, onSave, onSaveAppSettings, onSetPrivateKey, onReboot, onAdvertise, onClose, className, }: { config: RadioConfig; health: HealthStatus | null; appSettings: AppSettings; pageMode: boolean; onSave: (update: RadioConfigUpdate) => Promise; onSaveAppSettings: (update: AppSettingsUpdate) => Promise; onSetPrivateKey: (key: string) => Promise; onReboot: () => Promise; onAdvertise: () => Promise; onClose: () => void; className?: string; }) { const [name, setName] = useState(''); const [privateKey, setPrivateKey] = useState(''); const [advertIntervalHours, setAdvertIntervalHours] = useState('0'); const [floodScope, setFloodScope] = useState(''); const [busy, setBusy] = useState(false); const [rebooting, setRebooting] = useState(false); const [advertising, setAdvertising] = useState(false); const [error, setError] = useState(null); useEffect(() => { setName(config.name); }, [config]); useEffect(() => { setAdvertIntervalHours(String(Math.round(appSettings.advert_interval / 3600))); setFloodScope(appSettings.flood_scope); }, [appSettings]); const handleSaveIdentity = async () => { setError(null); setBusy(true); try { const update: RadioConfigUpdate = { name }; await onSave(update); const appUpdate: AppSettingsUpdate = {}; const hours = parseInt(advertIntervalHours, 10); const newAdvertInterval = isNaN(hours) ? 0 : hours * 3600; if (newAdvertInterval !== appSettings.advert_interval) { appUpdate.advert_interval = newAdvertInterval; } if (floodScope !== appSettings.flood_scope) { appUpdate.flood_scope = floodScope; } if (Object.keys(appUpdate).length > 0) { await onSaveAppSettings(appUpdate); } toast.success('Identity settings saved'); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to save'); } finally { setBusy(false); } }; const handleSetPrivateKey = async () => { if (!privateKey.trim()) { setError('Private key is required'); return; } setError(null); setBusy(true); try { await onSetPrivateKey(privateKey.trim()); setPrivateKey(''); toast.success('Private key set, rebooting...'); setRebooting(true); await onReboot(); if (!pageMode) { onClose(); } } catch (err) { setError(err instanceof Error ? err.message : 'Failed to set private key'); } finally { setRebooting(false); setBusy(false); } }; const handleAdvertise = async () => { setAdvertising(true); try { await onAdvertise(); } finally { setAdvertising(false); } }; return (
setName(e.target.value)} />
setAdvertIntervalHours(e.target.value)} className="w-28" /> hours (0 = off)

How often to automatically advertise presence. Set to 0 to disable. Minimum: 1 hour. Recommended: 24 hours or higher.

setFloodScope(e.target.value)} placeholder="#MyRegion" />

Tag outgoing flood messages with a region name (e.g. #MyRegion). Repeaters with this region configured will prioritize your traffic. Leave empty to disable.

setPrivateKey(e.target.value)} placeholder="64-character hex private key" />

Send a flood advertisement to announce your presence on the mesh network.

{!health?.radio_connected && (

Radio not connected

)}
{error && (
{error}
)}
); }