mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Route scanner status colors through the active theme
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
376eb3c367
commit
d94cc2183d
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../model/arp_scanner_status.dart';
|
import '../model/arp_scanner_status.dart';
|
||||||
|
import '../theme/app_colors.dart';
|
||||||
import '../utils/duration_formatter.dart';
|
import '../utils/duration_formatter.dart';
|
||||||
import '../utils/oott_api.dart';
|
import '../utils/oott_api.dart';
|
||||||
import 'scanner_status_card.dart';
|
import 'scanner_status_card.dart';
|
||||||
@@ -18,12 +19,19 @@ class ArpScannerCard extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ScannerStatus _resolve(ArpScannerStatus status, double elapsed) {
|
static ScannerStatus _resolve(
|
||||||
|
BuildContext context,
|
||||||
|
ArpScannerStatus status,
|
||||||
|
double elapsed,
|
||||||
|
) {
|
||||||
|
final successColor =
|
||||||
|
Theme.of(context).extension<AppColorExtension>()!.success;
|
||||||
|
final neutralColor = Theme.of(context).colorScheme.outline;
|
||||||
if (status.isRunning) {
|
if (status.isRunning) {
|
||||||
final sub = status.runningForSeconds != null
|
final sub = status.runningForSeconds != null
|
||||||
? ['Running for ${formatSeconds(status.runningForSeconds! + elapsed)}']
|
? ['Running for ${formatSeconds(status.runningForSeconds! + elapsed)}']
|
||||||
: <String>[];
|
: <String>[];
|
||||||
return (color: Colors.green, label: 'Running', sublabels: sub);
|
return (color: successColor, label: 'Running', sublabels: sub);
|
||||||
}
|
}
|
||||||
if (status.nextRunInSeconds != null) {
|
if (status.nextRunInSeconds != null) {
|
||||||
final remaining = (status.nextRunInSeconds! - elapsed).clamp(
|
final remaining = (status.nextRunInSeconds! - elapsed).clamp(
|
||||||
@@ -31,11 +39,11 @@ class ArpScannerCard extends StatelessWidget {
|
|||||||
double.infinity,
|
double.infinity,
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
color: Colors.grey,
|
color: neutralColor,
|
||||||
label: 'Waiting for next run',
|
label: 'Waiting for next run',
|
||||||
sublabels: ['Next run in ${formatSeconds(remaining)}'],
|
sublabels: ['Next run in ${formatSeconds(remaining)}'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (color: Colors.grey, label: 'Not yet started', sublabels: []);
|
return (color: neutralColor, label: 'Not yet started', sublabels: []);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../model/mdns_scanner_status.dart';
|
import '../model/mdns_scanner_status.dart';
|
||||||
|
import '../theme/app_colors.dart';
|
||||||
import '../utils/duration_formatter.dart';
|
import '../utils/duration_formatter.dart';
|
||||||
import '../utils/oott_api.dart';
|
import '../utils/oott_api.dart';
|
||||||
import 'scanner_status_card.dart';
|
import 'scanner_status_card.dart';
|
||||||
@@ -18,9 +19,17 @@ class MdnsScannerCard extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ScannerStatus _resolve(MdnsScannerStatus status, double elapsed) {
|
static ScannerStatus _resolve(
|
||||||
|
BuildContext context,
|
||||||
|
MdnsScannerStatus status,
|
||||||
|
double elapsed,
|
||||||
|
) {
|
||||||
if (!status.isListening) {
|
if (!status.isListening) {
|
||||||
return (color: Colors.grey, label: 'Not yet started', sublabels: []);
|
return (
|
||||||
|
color: Theme.of(context).colorScheme.outline,
|
||||||
|
label: 'Not yet started',
|
||||||
|
sublabels: [],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
final sublabels = <String>[
|
final sublabels = <String>[
|
||||||
status.listeningForSeconds != null
|
status.listeningForSeconds != null
|
||||||
@@ -29,6 +38,10 @@ class MdnsScannerCard extends StatelessWidget {
|
|||||||
if (status.lastDeviceSeenSecondsAgo != null)
|
if (status.lastDeviceSeenSecondsAgo != null)
|
||||||
'Last device ${formatSeconds(status.lastDeviceSeenSecondsAgo! + elapsed)} ago',
|
'Last device ${formatSeconds(status.lastDeviceSeenSecondsAgo! + elapsed)} ago',
|
||||||
];
|
];
|
||||||
return (color: Colors.green, label: 'Listening', sublabels: sublabels);
|
return (
|
||||||
|
color: Theme.of(context).extension<AppColorExtension>()!.success,
|
||||||
|
label: 'Listening',
|
||||||
|
sublabels: sublabels,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import 'polled_stale_indicator.dart';
|
|||||||
typedef ScannerStatus = ({Color color, String label, List<String> sublabels});
|
typedef ScannerStatus = ({Color color, String label, List<String> sublabels});
|
||||||
|
|
||||||
typedef ScannerStatusResolver<T> =
|
typedef ScannerStatusResolver<T> =
|
||||||
ScannerStatus Function(T value, double elapsedSeconds);
|
ScannerStatus Function(BuildContext context, T value, double elapsedSeconds);
|
||||||
|
|
||||||
/// Generic card that polls a scanner status endpoint and renders the result
|
/// Generic card that polls a scanner status endpoint and renders the result
|
||||||
/// using the provided [resolver]. The two scanner cards (ARP, mDNS) are thin
|
/// using the provided [resolver]. The two scanner cards (ARP, mDNS) are thin
|
||||||
@@ -71,7 +71,7 @@ class _ScannerStatusCardState<T> extends State<ScannerStatusCard<T>> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final status = _resolveStatus(freshness);
|
final status = _resolveStatus(context, freshness);
|
||||||
final isStale = freshness == PolledFreshness.stale;
|
final isStale = freshness == PolledFreshness.stale;
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
@@ -124,10 +124,10 @@ class _ScannerStatusCardState<T> extends State<ScannerStatusCard<T>> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScannerStatus _resolveStatus(PolledFreshness freshness) {
|
ScannerStatus _resolveStatus(BuildContext context, PolledFreshness freshness) {
|
||||||
if (freshness == PolledFreshness.error) {
|
if (freshness == PolledFreshness.error) {
|
||||||
return (
|
return (
|
||||||
color: Colors.red,
|
color: Theme.of(context).colorScheme.error,
|
||||||
label: 'Error',
|
label: 'Error',
|
||||||
sublabels: [
|
sublabels: [
|
||||||
_polled.lastErrorMessage ??
|
_polled.lastErrorMessage ??
|
||||||
@@ -139,6 +139,6 @@ class _ScannerStatusCardState<T> extends State<ScannerStatusCard<T>> {
|
|||||||
.difference(_polled.lastSuccessAt!)
|
.difference(_polled.lastSuccessAt!)
|
||||||
.inSeconds
|
.inSeconds
|
||||||
.toDouble();
|
.toDouble();
|
||||||
return widget.resolver(_polled.value as T, elapsed);
|
return widget.resolver(context, _polled.value as T, elapsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:go_router/go_router.dart';
|
|||||||
import '../model/arp_scanner_status.dart';
|
import '../model/arp_scanner_status.dart';
|
||||||
import '../model/mdns_scanner_status.dart';
|
import '../model/mdns_scanner_status.dart';
|
||||||
import '../navigation.dart';
|
import '../navigation.dart';
|
||||||
|
import '../theme/app_colors.dart';
|
||||||
import '../utils/backend_reachability.dart';
|
import '../utils/backend_reachability.dart';
|
||||||
import '../utils/duration_formatter.dart';
|
import '../utils/duration_formatter.dart';
|
||||||
import '../utils/oott_api.dart';
|
import '../utils/oott_api.dart';
|
||||||
@@ -120,8 +121,8 @@ class _ScannersStatusCardState extends State<ScannersStatusCard>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final (arpColor, arpText) = _resolveArp(arpFreshness);
|
final (arpColor, arpText) = _resolveArp(context, arpFreshness);
|
||||||
final (mdnsColor, mdnsText) = _resolveMdns(mdnsFreshness);
|
final (mdnsColor, mdnsText) = _resolveMdns(context, mdnsFreshness);
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
@@ -201,9 +202,12 @@ class _ScannersStatusCardState extends State<ScannersStatusCard>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
(Color, String) _resolveArp(PolledFreshness freshness) {
|
(Color, String) _resolveArp(BuildContext context, PolledFreshness freshness) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final successColor = theme.extension<AppColorExtension>()!.success;
|
||||||
|
final neutralColor = theme.colorScheme.outline;
|
||||||
if (freshness == PolledFreshness.error) {
|
if (freshness == PolledFreshness.error) {
|
||||||
return (Colors.red, 'Error');
|
return (theme.colorScheme.error, 'Error');
|
||||||
}
|
}
|
||||||
final status = _arp.value!;
|
final status = _arp.value!;
|
||||||
final elapsed = DateTime.now()
|
final elapsed = DateTime.now()
|
||||||
@@ -212,21 +216,24 @@ class _ScannersStatusCardState extends State<ScannersStatusCard>
|
|||||||
.toDouble();
|
.toDouble();
|
||||||
if (status.isRunning) {
|
if (status.isRunning) {
|
||||||
final secs = (status.runningForSeconds ?? 0) + elapsed;
|
final secs = (status.runningForSeconds ?? 0) + elapsed;
|
||||||
return (Colors.green, 'Running for ${formatSeconds(secs)}');
|
return (successColor, 'Running for ${formatSeconds(secs)}');
|
||||||
}
|
}
|
||||||
if (status.nextRunInSeconds != null) {
|
if (status.nextRunInSeconds != null) {
|
||||||
final remaining = (status.nextRunInSeconds! - elapsed).clamp(
|
final remaining = (status.nextRunInSeconds! - elapsed).clamp(
|
||||||
0.0,
|
0.0,
|
||||||
double.infinity,
|
double.infinity,
|
||||||
);
|
);
|
||||||
return (Colors.grey, 'Next run in ${formatSeconds(remaining)}');
|
return (neutralColor, 'Next run in ${formatSeconds(remaining)}');
|
||||||
}
|
}
|
||||||
return (Colors.grey, 'Not yet started');
|
return (neutralColor, 'Not yet started');
|
||||||
}
|
}
|
||||||
|
|
||||||
(Color, String) _resolveMdns(PolledFreshness freshness) {
|
(Color, String) _resolveMdns(BuildContext context, PolledFreshness freshness) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final successColor = theme.extension<AppColorExtension>()!.success;
|
||||||
|
final neutralColor = theme.colorScheme.outline;
|
||||||
if (freshness == PolledFreshness.error) {
|
if (freshness == PolledFreshness.error) {
|
||||||
return (Colors.red, 'Error');
|
return (theme.colorScheme.error, 'Error');
|
||||||
}
|
}
|
||||||
final status = _mdns.value!;
|
final status = _mdns.value!;
|
||||||
final elapsed = DateTime.now()
|
final elapsed = DateTime.now()
|
||||||
@@ -236,10 +243,10 @@ class _ScannersStatusCardState extends State<ScannersStatusCard>
|
|||||||
if (status.isListening) {
|
if (status.isListening) {
|
||||||
if (status.lastDeviceSeenSecondsAgo != null) {
|
if (status.lastDeviceSeenSecondsAgo != null) {
|
||||||
final secs = status.lastDeviceSeenSecondsAgo! + elapsed;
|
final secs = status.lastDeviceSeenSecondsAgo! + elapsed;
|
||||||
return (Colors.green, 'Last device seen ${formatSeconds(secs)} ago');
|
return (successColor, 'Last device seen ${formatSeconds(secs)} ago');
|
||||||
}
|
}
|
||||||
return (Colors.green, 'No devices seen yet');
|
return (successColor, 'No devices seen yet');
|
||||||
}
|
}
|
||||||
return (Colors.grey, 'Not yet started');
|
return (neutralColor, 'Not yet started');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user