feat: non-blocking scan with progressive device discovery

Backend:
- asyncio.to_thread(_nmap_scan) — nmap no longer blocks the event loop
- Commit each discovered device immediately (previously one bulk commit at end)
- Update ScanRun.devices_found after each device so history panel shows live count
- broadcast_scan_update() pushes {type: scan_device_found} WS event per device
- Refactor broadcast_status to shared _broadcast() helper, adds type: "status" field

Frontend:
- useStatusPolling handles both WS message types (status / scan_device_found)
- canvasStore: scanEventTs + notifyScanDeviceFound() action
- PendingDevicesPanel auto-refreshes when WS scan event is received
This commit is contained in:
Pouzor
2026-03-07 16:06:44 +01:00
parent 974e782057
commit bec699ba93
5 changed files with 72 additions and 25 deletions
+7 -2
View File
@@ -150,7 +150,7 @@ export function Sidebar({ onAddNode, onScan, onSave }: SidebarProps) {
function PendingDevicesPanel() {
const [devices, setDevices] = useState<PendingDevice[]>([])
const [loading, setLoading] = useState(false)
const { addNode } = useCanvasStore()
const { addNode, scanEventTs } = useCanvasStore()
const load = useCallback(async () => {
setLoading(true)
@@ -165,7 +165,12 @@ function PendingDevicesPanel() {
}, [])
// Load on mount
useState(() => { load() })
useEffect(() => { load() }, [load])
// Auto-refresh when the backend pushes a scan_device_found event
useEffect(() => {
if (scanEventTs > 0) load()
}, [scanEventTs, load])
const handleApprove = async (device: PendingDevice) => {
try {