@@ -22,6 +22,9 @@ class PingControls extends StatelessWidget {
2222 final isRxAutoRunning = appState.autoPingEnabled && appState.autoMode == AutoMode .rxOnly;
2323 final cooldownActive = appState.cooldownTimer.isRunning; // Shared cooldown for both TX Ping and TX/RX Auto
2424 final cooldownRemaining = appState.cooldownTimer.remainingSec;
25+ final rxWindowActive = appState.rxWindowTimer.isRunning; // RX listening window after ping
26+ final rxWindowRemaining = appState.rxWindowTimer.remainingSec;
27+ final isPingSending = appState.isPingSending; // True immediately when button clicked
2528
2629 // TX is blocked when offline mode is active and connected
2730 final txBlockedByOffline = appState.offlineMode && appState.isConnected;
@@ -78,17 +81,23 @@ class PingControls extends StatelessWidget {
7881 Row (
7982 children: [
8083 // Send Ping button - disabled when offline mode is active, but works during Passive Mode
84+ // Shows active state with pulse animation during sending and RX listening window
8185 Expanded (
8286 child: _ActionButton (
8387 icon: Icons .cell_tower,
8488 label: txBlockedByOffline
8589 ? 'TX Disabled'
86- : (cooldownActive && ! isTxRxAutoRunning ? '$cooldownRemaining s' : 'Send Ping' ),
90+ : isPingSending
91+ ? 'Sending...'
92+ : rxWindowActive
93+ ? 'Listening ${rxWindowRemaining }s'
94+ : (cooldownActive && ! isTxRxAutoRunning ? '$cooldownRemaining s' : 'Send Ping' ),
8795 color: const Color (0xFF0EA5E9 ), // sky-500
88- enabled: canPing && ! isTxRxAutoRunning && ! cooldownActive && ! txBlockedByOffline,
96+ enabled: canPing && ! isTxRxAutoRunning && ! cooldownActive && ! txBlockedByOffline && ! rxWindowActive && ! isPingSending,
97+ isActive: isPingSending || rxWindowActive,
8998 onPressed: () => _sendPing (context, appState),
9099 showCooldown: cooldownActive && ! isTxRxAutoRunning && ! txBlockedByOffline,
91- subtitle: txBlockedByOffline ? 'Offline Mode' : moveSubtitle,
100+ subtitle: txBlockedByOffline ? 'Offline Mode' : ((isPingSending || rxWindowActive) ? null : moveSubtitle) ,
92101 subtitleColor: txBlockedByOffline ? Colors .orange : Colors .orange.shade600,
93102 ),
94103 ),
@@ -256,7 +265,10 @@ class _ActionButtonState extends State<_ActionButton>
256265
257266 @override
258267 Widget build (BuildContext context) {
259- final effectiveColor = widget.enabled ? widget.color : Colors .grey;
268+ // Use color when enabled, active (RX listening), or during cooldown
269+ // This prevents the button from going grey during cooldown
270+ final showColor = widget.enabled || widget.isActive || widget.showCooldown;
271+ final effectiveColor = showColor ? widget.color : Colors .grey;
260272 final borderOpacity = widget.isActive ? 0.6 : 0.3 ;
261273
262274 return AnimatedBuilder (
@@ -294,7 +306,7 @@ class _ActionButtonState extends State<_ActionButton>
294306 Icon (
295307 widget.icon,
296308 size: 26 ,
297- color: widget.enabled
309+ color: showColor
298310 ? effectiveColor
299311 : Colors .grey.shade400,
300312 ),
@@ -326,7 +338,7 @@ class _ActionButtonState extends State<_ActionButton>
326338 style: TextStyle (
327339 fontSize: 11 ,
328340 fontWeight: widget.isActive ? FontWeight .w600 : FontWeight .w500,
329- color: widget.enabled
341+ color: showColor
330342 ? (widget.isActive ? effectiveColor : Colors .grey.shade700)
331343 : Colors .grey.shade400,
332344 ),
0 commit comments