Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
400dee57d4
|
@@ -149,6 +149,11 @@ final colorProvider = StateNotifierProvider<ColorNotifier, BusylightColor>(
|
||||
},
|
||||
);
|
||||
|
||||
// ── Connection lost indicator ─────────────────────────────────────────────────
|
||||
// Set to true by the polling notifier when a poll fails, false on success.
|
||||
|
||||
final connectionLostProvider = StateProvider<bool>((_) => false);
|
||||
|
||||
// ── Background polling ────────────────────────────────────────────────────────
|
||||
// Periodically pulls status + color from the device and silently updates state.
|
||||
|
||||
@@ -181,8 +186,11 @@ class PollingNotifier extends StateNotifier<void> {
|
||||
_ref.read(busylightStatusProvider.notifier).setLocalStatus(status);
|
||||
_ref.read(colorProvider.notifier).silentSet(color);
|
||||
_ref.read(brightnessProvider.notifier).silentSet(color.brightness);
|
||||
// Connection restored — clear the lost flag
|
||||
_ref.read(connectionLostProvider.notifier).state = false;
|
||||
} catch (_) {
|
||||
// Silently ignore poll errors — connection issues are shown on manual refresh
|
||||
// Signal connectivity issue to the UI
|
||||
_ref.read(connectionLostProvider.notifier).state = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@ class _BodyState extends ConsumerState<_Body> {
|
||||
final brightness = ref.watch(brightnessProvider);
|
||||
final color = ref.watch(colorProvider);
|
||||
final presets = ref.watch(presetsProvider);
|
||||
final connectionLost = ref.watch(connectionLostProvider);
|
||||
|
||||
final status = statusAsync.valueOrNull ?? BusylightStatus.off;
|
||||
final displayColor = _statusColor(status, color);
|
||||
@@ -129,7 +130,7 @@ class _BodyState extends ConsumerState<_Body> {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(24),
|
||||
children: [
|
||||
// Live color preview dot
|
||||
// Live color preview dot — shows wifi-off icon when connection lost
|
||||
Center(
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
@@ -137,10 +138,12 @@ class _BodyState extends ConsumerState<_Body> {
|
||||
height: 100,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: status == BusylightStatus.off
|
||||
color: connectionLost
|
||||
? Colors.grey.shade900
|
||||
: status == BusylightStatus.off
|
||||
? Colors.grey.shade900
|
||||
: displayColor.withOpacity(brightness),
|
||||
boxShadow: status != BusylightStatus.off
|
||||
boxShadow: (!connectionLost && status != BusylightStatus.off)
|
||||
? [BoxShadow(
|
||||
color: displayColor.withOpacity(0.5 * brightness),
|
||||
blurRadius: 40,
|
||||
@@ -148,13 +151,20 @@ class _BodyState extends ConsumerState<_Body> {
|
||||
)]
|
||||
: null,
|
||||
),
|
||||
child: connectionLost
|
||||
? const Icon(Icons.wifi_off, color: Colors.grey, size: 36)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Center(
|
||||
child: Text(
|
||||
status.label.toUpperCase(),
|
||||
style: const TextStyle(color: Colors.grey, letterSpacing: 2, fontSize: 13),
|
||||
connectionLost ? 'NO CONNECTION' : status.label.toUpperCase(),
|
||||
style: TextStyle(
|
||||
color: connectionLost ? Colors.red.shade700 : Colors.grey,
|
||||
letterSpacing: 2,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 36),
|
||||
@@ -177,9 +187,11 @@ class _BodyState extends ConsumerState<_Body> {
|
||||
BusylightStatus.off,
|
||||
].map((s) => StatusButton(
|
||||
status: s,
|
||||
isActive: status == s,
|
||||
isActive: !connectionLost && status == s,
|
||||
isPending: _pendingStatus == s,
|
||||
onTap: _pendingStatus == null ? () => _setStatus(s) : () {},
|
||||
onTap: (!connectionLost && _pendingStatus == null)
|
||||
? () => _setStatus(s)
|
||||
: () {},
|
||||
)).toList(),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
@@ -188,7 +200,7 @@ class _BodyState extends ConsumerState<_Body> {
|
||||
_PresetsScroller(
|
||||
presets: presets,
|
||||
pendingPresetId: _pendingPresetId,
|
||||
onPresetTap: (_pendingStatus == null && _pendingPresetId == null)
|
||||
onPresetTap: (!connectionLost && _pendingStatus == null && _pendingPresetId == null)
|
||||
? _applyPreset
|
||||
: (_) {},
|
||||
onPresetDelete: (preset) => ref.read(presetsProvider.notifier).remove(preset.id),
|
||||
|
||||
Reference in New Issue
Block a user