Refactor frontend: extract widgets and eliminate duplicated scanner state

- Convert ArpScannerCard to a self-managing StatefulWidget (owns its own 5s refresh + 1s tick timers), removing the duplicated state management that existed in both HomeScreen and StatusScreen
- Extract NotificationCard to home/notification_card.dart
- Extract DeviceSummaryCard (with its 1-min refresh timer) to widgets/device_summary_card.dart
- HomeScreen drops from 515 to 253 lines; StatusScreen from 82 to 19 lines

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
rzuasti
2026-05-28 19:23:27 -04:00
co-authored by Claude Sonnet 4.6
parent 251d8a479e
commit f113da9cd0
5 changed files with 322 additions and 362 deletions
+4 -66
View File
@@ -1,67 +1,10 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:frontend/model/arp_scanner_status.dart';
import 'package:frontend/utils/oott_api.dart';
import 'package:frontend/widgets/arp_scanner_card.dart';
class StatusScreen extends StatefulWidget {
import '../widgets/arp_scanner_card.dart';
class StatusScreen extends StatelessWidget {
const StatusScreen({super.key});
@override
State<StatusScreen> createState() => _StatusScreenState();
}
class _StatusScreenState extends State<StatusScreen> {
ArpScannerStatus? _status;
DateTime? _statusReceivedAt;
bool _isLoading = true;
String? _error;
Timer? _refreshTimer;
Timer? _tickTimer;
@override
void initState() {
super.initState();
_loadStatus();
_refreshTimer = Timer.periodic(
const Duration(seconds: 5),
(_) => _loadStatus(),
);
_tickTimer = Timer.periodic(
const Duration(seconds: 1),
(_) {
if (mounted) setState(() {});
},
);
}
@override
void dispose() {
_refreshTimer?.cancel();
_tickTimer?.cancel();
super.dispose();
}
Future<void> _loadStatus() async {
try {
final status = await BackendAPI.instance.getArpScannerStatus();
if (!mounted) return;
setState(() {
_status = status;
_statusReceivedAt = DateTime.now();
_error = null;
_isLoading = false;
});
} catch (e) {
if (!mounted) return;
setState(() {
_error = e.toString();
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Column(
@@ -69,12 +12,7 @@ class _StatusScreenState extends State<StatusScreen> {
children: [
Text('Status', style: Theme.of(context).textTheme.headlineMedium),
const SizedBox(height: 20),
ArpScannerCard(
status: _status,
statusReceivedAt: _statusReceivedAt,
error: _error,
isLoading: _isLoading,
),
const ArpScannerCard(),
],
);
}