Skip to content

Commit b1ca801

Browse files
committed
Fixed Zone Full Issue
1 parent 63996c7 commit b1ca801

File tree

8 files changed

+102
-44
lines changed

8 files changed

+102
-44
lines changed

android/local.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ sdk.dir=/opt/homebrew/share/android-commandlinetools
22
flutter.sdk=/opt/homebrew/share/flutter
33
flutter.buildMode=release
44
flutter.versionName=1.0.0
5-
flutter.versionCode=1769658133
5+
flutter.versionCode=1769747121

ios/Flutter/Generated.xcconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ FLUTTER_BUILD_NAME=1.0.0
88
FLUTTER_BUILD_NUMBER=1
99
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
1010
EXCLUDED_ARCHS[sdk=iphoneos*]=armv7
11-
DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguNw==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049M2I2MmVmYzJhMw==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43
11+
DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguOQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049NjczMjNkZTI4NQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NTg3YzE4Zjg3Mw==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC44
1212
DART_OBFUSCATION=false
1313
TRACK_WIDGET_CREATION=true
1414
TREE_SHAKE_ICONS=false

ios/Flutter/flutter_export_environment.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export "FLUTTER_TARGET=/Users/schnobbc/Documents/Github/MeshMapper_Flutter_App/l
77
export "FLUTTER_BUILD_DIR=build"
88
export "FLUTTER_BUILD_NAME=1.0.0"
99
export "FLUTTER_BUILD_NUMBER=1"
10-
export "DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguNw==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049M2I2MmVmYzJhMw==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NzhmYzMwMTJlNA==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC43"
10+
export "DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguOQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049NjczMjNkZTI4NQ==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049NTg3YzE4Zjg3Mw==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC44"
1111
export "DART_OBFUSCATION=false"
1212
export "TRACK_WIDGET_CREATION=true"
1313
export "TREE_SHAKE_ICONS=false"

lib/providers/app_state_provider.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,9 @@ class AppStateProvider extends ChangeNotifier {
736736
return _preferences.autoPowerSet || _preferences.powerLevelSet || _deviceModel != null;
737737
};
738738

739+
// Check if TX is allowed by API (zone capacity)
740+
_pingService!.checkTxAllowed = () => txAllowed;
741+
739742
_pingService!.onTxPing = (ping) {
740743
_txPings.add(ping);
741744

lib/screens/home_screen.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,16 @@ class _HomeScreenState extends State<HomeScreen> {
298298
return ('Offline Mode Active', 'Pings are saved locally. Zone detection is paused until you go back online.', Icons.flight, Colors.grey);
299299
}
300300
if (appState.inZone == true && appState.zoneCode != null) {
301+
if (!appState.isConnected) {
302+
return ('${appState.zoneName ?? appState.zoneCode} Zone',
303+
'You\'re in an authorized zone. Connect to a device to start wardriving.',
304+
Icons.flight, Colors.grey);
305+
}
306+
if (!appState.txAllowed) {
307+
return ('${appState.zoneName ?? appState.zoneCode} Zone',
308+
'You\'re in an authorized zone. However, the zone is at Active Wardrive capacity. You can still wardrive, but only Passive Mode is allowed.',
309+
Icons.flight, Colors.red);
310+
}
301311
return ('${appState.zoneName ?? appState.zoneCode} Zone',
302312
'You\'re in an active zone with ${appState.zoneSlotsAvailable ?? "?"} TX slots available. Ready to wardrive!',
303313
Icons.flight, Colors.green);
@@ -590,7 +600,9 @@ class _HomeScreenState extends State<HomeScreen> {
590600
case GpsStatus.locked:
591601
if (appState.inZone == true && appState.zoneCode != null) {
592602
icon = Icons.flight;
593-
color = Colors.green;
603+
color = appState.isConnected
604+
? (appState.txAllowed ? Colors.green : Colors.red)
605+
: Colors.grey;
594606
text = appState.zoneCode!;
595607
} else if (appState.inZone == false) {
596608
icon = Icons.flight;

lib/services/ping_service.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ class PingService {
9696
bool Function()? checkExternalAntennaConfigured;
9797
bool Function()? checkPowerLevelConfigured;
9898

99+
/// Callback to check if TX is allowed by API (zone capacity check)
100+
bool Function()? checkTxAllowed;
101+
99102
/// Callback for ping events
100103
void Function(TxPing)? onTxPing;
101104
void Function(RxPing)? onRxPing;
@@ -182,6 +185,11 @@ class PingService {
182185
return PingValidation.notConnected;
183186
}
184187

188+
// Check if TX is allowed by API (zone capacity)
189+
if (checkTxAllowed != null && !checkTxAllowed!()) {
190+
return PingValidation.txNotAllowed;
191+
}
192+
185193
// Check external antenna configuration
186194
if (checkExternalAntennaConfigured != null && !checkExternalAntennaConfigured!()) {
187195
return PingValidation.externalAntennaRequired;
@@ -241,6 +249,11 @@ class PingService {
241249
return PingValidation.notConnected;
242250
}
243251

252+
// Check if TX is allowed by API (zone capacity)
253+
if (checkTxAllowed != null && !checkTxAllowed!()) {
254+
return PingValidation.txNotAllowed;
255+
}
256+
244257
// Check external antenna configuration
245258
if (checkExternalAntennaConfigured != null && !checkExternalAntennaConfigured!()) {
246259
return PingValidation.externalAntennaRequired;
@@ -991,6 +1004,9 @@ enum PingValidation {
9911004

9921005
/// Cooldown period active (< 7s since last ping)
9931006
cooldownActive,
1007+
1008+
/// TX not allowed by API (zone at capacity)
1009+
txNotAllowed,
9941010
}
9951011

9961012
extension PingValidationExtension on PingValidation {
@@ -1016,6 +1032,8 @@ extension PingValidationExtension on PingValidation {
10161032
return 'Move 25m before next ping';
10171033
case PingValidation.cooldownActive:
10181034
return 'Wait 7 seconds between pings';
1035+
case PingValidation.txNotAllowed:
1036+
return 'Zone at TX capacity (Passive Only)';
10191037
}
10201038
}
10211039
}

lib/widgets/ping_controls.dart

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class PingControls extends StatelessWidget {
3535
// TX is blocked when offline mode is active and connected
3636
final txBlockedByOffline = appState.offlineMode && appState.isConnected;
3737

38+
// TX not allowed when API says zone is at TX capacity
39+
final txNotAllowed = appState.isConnected && !appState.txAllowed;
40+
3841
// Calculate distance feedback for TX Ping button
3942
final distanceFromLastPing = appState.distanceFromLastPing;
4043
final needToMove = validation == PingValidation.tooCloseToLastPing && distanceFromLastPing != null;
@@ -95,25 +98,27 @@ class PingControls extends StatelessWidget {
9598
icon: Icons.cell_tower,
9699
label: txBlockedByOffline
97100
? 'TX Disabled'
98-
: isActiveModeRunning
99-
? 'Send Ping' // Just disabled when Active Mode is running
100-
: isPingSending
101-
? 'Sending...'
102-
: rxWindowActive
103-
? 'Listening ${rxWindowRemaining}s' // Manual ping listening (works during Passive Mode too)
104-
: discoveryWindowActive
105-
? 'Cooldown ${discoveryWindowRemaining}s' // Cooldown during Passive Mode listening
106-
: cooldownActive
107-
? 'Cooldown ${cooldownRemaining}s' // After Active Mode disabled
108-
: 'Send Ping',
101+
: txNotAllowed
102+
? 'Zone Full'
103+
: isActiveModeRunning
104+
? 'Send Ping' // Just disabled when Active Mode is running
105+
: isPingSending
106+
? 'Sending...'
107+
: rxWindowActive
108+
? 'Listening ${rxWindowRemaining}s' // Manual ping listening (works during Passive Mode too)
109+
: discoveryWindowActive
110+
? 'Cooldown ${discoveryWindowRemaining}s' // Cooldown during Passive Mode listening
111+
: cooldownActive
112+
? 'Cooldown ${cooldownRemaining}s' // After Active Mode disabled
113+
: 'Send Ping',
109114
color: const Color(0xFF0EA5E9), // sky-500
110-
enabled: canPing && !isActiveModeRunning && !cooldownActive && !txBlockedByOffline &&
115+
enabled: canPing && !isActiveModeRunning && !cooldownActive && !txBlockedByOffline && !txNotAllowed &&
111116
!rxWindowActive && !isPingSending && !discoveryWindowActive && !isPendingDisable,
112117
isActive: (isPingSending || rxWindowActive) && !isActiveModeRunning, // Only active during manual ping flow
113118
onPressed: () => _sendPing(context, appState),
114119
showCooldown: false, // No longer needed - countdown shown in label
115-
subtitle: txBlockedByOffline ? 'Offline Mode' : ((isPingSending || rxWindowActive || cooldownActive || discoveryWindowActive) ? null : moveSubtitle),
116-
subtitleColor: txBlockedByOffline ? Colors.orange : Colors.orange.shade600,
120+
subtitle: txBlockedByOffline ? 'Offline Mode' : txNotAllowed ? 'Passive Only' : ((isPingSending || rxWindowActive || cooldownActive || discoveryWindowActive) ? null : moveSubtitle),
121+
subtitleColor: txBlockedByOffline ? Colors.orange : txNotAllowed ? Colors.red : Colors.orange.shade600,
117122
),
118123
),
119124
const SizedBox(width: 10),
@@ -127,35 +132,37 @@ class PingControls extends StatelessWidget {
127132
icon: Icons.sensors,
128133
label: txBlockedByOffline
129134
? 'TX Disabled'
130-
: isPendingDisable
131-
? (rxWindowActive
132-
? 'Stopping ${rxWindowRemaining}s' // Show remaining time until disable completes
133-
: 'Stopping...') // Brief transition state
134-
: isActiveModeRunning
135-
? (isPingInProgress && !rxWindowActive
136-
? 'Sending...' // Brief moment while ping is being sent
135+
: txNotAllowed
136+
? 'Zone Full'
137+
: isPendingDisable
138+
? (rxWindowActive
139+
? 'Stopping ${rxWindowRemaining}s' // Show remaining time until disable completes
140+
: 'Stopping...') // Brief transition state
141+
: isActiveModeRunning
142+
? (isPingInProgress && !rxWindowActive
143+
? 'Sending...' // Brief moment while ping is being sent
144+
: rxWindowActive
145+
? 'Listening ${rxWindowRemaining}s' // During RX window
146+
: autoPingWaiting
147+
? 'Next ping ${autoPingRemaining}s' // Waiting for next auto ping
148+
: 'Active Mode') // Initial state before first ping
137149
: rxWindowActive
138-
? 'Listening ${rxWindowRemaining}s' // During RX window
139-
: autoPingWaiting
140-
? 'Next ping ${autoPingRemaining}s' // Waiting for next auto ping
141-
: 'Active Mode') // Initial state before first ping
142-
: rxWindowActive
143-
? 'Cooldown ${rxWindowRemaining}s' // During manual ping
144-
: cooldownActive
145-
? 'Cooldown ${cooldownRemaining}s' // After Active Mode disabled
146-
: 'Active Mode',
150+
? 'Cooldown ${rxWindowRemaining}s' // During manual ping
151+
: cooldownActive
152+
? 'Cooldown ${cooldownRemaining}s' // After Active Mode disabled
153+
: 'Active Mode',
147154
color: isPendingDisable
148155
? Colors.orange // Orange when stopping
149156
: isActiveModeRunning
150157
? const Color(0xFF22C55E) // green-500
151158
: const Color(0xFF6366F1), // indigo-500
152159
// When pending disable, button is disabled but still shows stopping state
153-
enabled: !isPendingDisable && ((isActiveModeRunning || (canStartAuto && !isPassiveModeRunning && !cooldownActive && !isPingSending && !rxWindowActive)) && !txBlockedByOffline),
160+
enabled: !isPendingDisable && ((isActiveModeRunning || (canStartAuto && !isPassiveModeRunning && !cooldownActive && !isPingSending && !rxWindowActive)) && !txBlockedByOffline && !txNotAllowed),
154161
isActive: isPendingDisable || (isActiveModeRunning && (isPingInProgress || rxWindowActive || autoPingWaiting)), // Active during stopping or sending/listening/waiting phases
155162
onPressed: () => _toggleTxRxAuto(context, appState),
156163
showCooldown: false, // No longer needed - countdown shown in label
157-
subtitle: txBlockedByOffline ? 'Offline Mode' : (isPendingDisable ? 'Stopping' : null),
158-
subtitleColor: Colors.orange,
164+
subtitle: txBlockedByOffline ? 'Offline Mode' : txNotAllowed ? 'Passive Only' : (isPendingDisable ? 'Stopping' : null),
165+
subtitleColor: txBlockedByOffline ? Colors.orange : txNotAllowed ? Colors.red : Colors.orange,
159166
),
160167
),
161168
const SizedBox(width: 10),
@@ -764,6 +771,9 @@ class _CompactPingControlsState extends State<CompactPingControls> {
764771
// TX is blocked when offline mode is active and connected
765772
final txBlockedByOffline = appState.offlineMode && appState.isConnected;
766773

774+
// TX not allowed when API says zone is at TX capacity
775+
final txNotAllowed = appState.isConnected && !appState.txAllowed;
776+
767777
final prefs = appState.preferences;
768778
final isPowerSet = prefs.autoPowerSet || prefs.powerLevelSet || appState.deviceModel != null;
769779

@@ -795,12 +805,12 @@ class _CompactPingControlsState extends State<CompactPingControls> {
795805
(cooldownActive && _lastActiveButton == _LastActiveButton.passiveMode);
796806

797807
// Determine which buttons are colored (enabled or active)
798-
final sendPingEnabled = canPing && !isActiveModeRunning && !cooldownActive && !txBlockedByOffline &&
808+
final sendPingEnabled = canPing && !isActiveModeRunning && !cooldownActive && !txBlockedByOffline && !txNotAllowed &&
799809
!rxWindowActive && !isPingSending && !discoveryWindowActive && !isPendingDisable;
800810
final sendPingActive = (isPingSending || rxWindowActive) && !isActiveModeRunning && !cooldownActive;
801811
final sendPingShowColor = sendPingEnabled || sendPingActive;
802812

803-
final activeModeEnabled = !isPendingDisable && ((isActiveModeRunning || (canStartAuto && !isPassiveModeRunning && !cooldownActive && !isPingSending && !rxWindowActive)) && !txBlockedByOffline);
813+
final activeModeEnabled = !isPendingDisable && ((isActiveModeRunning || (canStartAuto && !isPassiveModeRunning && !cooldownActive && !isPingSending && !rxWindowActive)) && !txBlockedByOffline && !txNotAllowed);
804814
final activeModeActive = isPendingDisable || (isActiveModeRunning && (isPingInProgress || rxWindowActive || autoPingWaiting));
805815
final activeModeShowColor = activeModeEnabled || activeModeActive;
806816

@@ -1063,6 +1073,9 @@ class LandscapePingControls extends StatelessWidget {
10631073
// TX is blocked when offline mode is active and connected
10641074
final txBlockedByOffline = appState.offlineMode && appState.isConnected;
10651075

1076+
// TX not allowed when API says zone is at TX capacity
1077+
final txNotAllowed = appState.isConnected && !appState.txAllowed;
1078+
10661079
final prefs = appState.preferences;
10671080
final isPowerSet = prefs.autoPowerSet || prefs.powerLevelSet || appState.deviceModel != null;
10681081

@@ -1091,9 +1104,9 @@ class LandscapePingControls extends StatelessWidget {
10911104
Expanded(
10921105
child: _LandscapeIconButton(
10931106
icon: Icons.cell_tower,
1094-
tooltip: 'Send Ping',
1107+
tooltip: txNotAllowed ? 'Zone Full (Passive Only)' : 'Send Ping',
10951108
color: const Color(0xFF0EA5E9), // sky-500
1096-
enabled: canPing && !isActiveModeRunning && !cooldownActive && !txBlockedByOffline &&
1109+
enabled: canPing && !isActiveModeRunning && !cooldownActive && !txBlockedByOffline && !txNotAllowed &&
10971110
!rxWindowActive && !isPingSending && !discoveryWindowActive && !isPendingDisable,
10981111
isActive: (isPingSending || rxWindowActive) && !isActiveModeRunning,
10991112
countdown: isPingSending
@@ -1114,13 +1127,13 @@ class LandscapePingControls extends StatelessWidget {
11141127
Expanded(
11151128
child: _LandscapeIconButton(
11161129
icon: Icons.sensors,
1117-
tooltip: 'Active Mode',
1130+
tooltip: txNotAllowed ? 'Zone Full (Passive Only)' : 'Active Mode',
11181131
color: isPendingDisable
11191132
? Colors.orange
11201133
: isActiveModeRunning
11211134
? const Color(0xFF22C55E) // green-500
11221135
: const Color(0xFF6366F1), // indigo-500
1123-
enabled: !isPendingDisable && ((isActiveModeRunning || (canStartAuto && !isPassiveModeRunning && !cooldownActive && !isPingSending && !rxWindowActive)) && !txBlockedByOffline),
1136+
enabled: !isPendingDisable && ((isActiveModeRunning || (canStartAuto && !isPassiveModeRunning && !cooldownActive && !isPingSending && !rxWindowActive)) && !txBlockedByOffline && !txNotAllowed),
11241137
isActive: isPendingDisable || (isActiveModeRunning && (isPingInProgress || rxWindowActive || autoPingWaiting)),
11251138
countdown: isActiveModeRunning
11261139
? (rxWindowActive

lib/widgets/status_bar.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,16 @@ class _StatusBarState extends State<StatusBar> {
123123
return ('Offline Mode Active', 'Pings are saved locally. Zone detection is paused until you go back online.', Icons.flight, Colors.grey);
124124
}
125125
if (appState.inZone == true && appState.zoneCode != null) {
126+
if (!appState.isConnected) {
127+
return ('${appState.zoneName ?? appState.zoneCode} Zone',
128+
'You\'re in an authorized zone. Connect to a device to start wardriving.',
129+
Icons.flight, Colors.grey);
130+
}
131+
if (!appState.txAllowed) {
132+
return ('${appState.zoneName ?? appState.zoneCode} Zone',
133+
'You\'re in an authorized zone. However, the zone is at Active Wardrive capacity. You can still wardrive, but only Passive Mode is allowed.',
134+
Icons.flight, Colors.red);
135+
}
126136
return ('${appState.zoneName ?? appState.zoneCode} Zone',
127137
'You\'re in an active zone with ${appState.zoneSlotsAvailable ?? "?"} TX slots available. Ready to wardrive!',
128138
Icons.flight, Colors.green);
@@ -170,7 +180,9 @@ class _StatusBarState extends State<StatusBar> {
170180
// Check if we're in a zone and have zone code from API
171181
if (appState.inZone == true && appState.zoneCode != null) {
172182
icon = Icons.flight;
173-
color = Colors.green;
183+
color = appState.isConnected
184+
? (appState.txAllowed ? Colors.green : Colors.red)
185+
: Colors.grey; // Grey when not connected, red when zone is at TX capacity
174186
text = appState.zoneCode!;
175187
} else if (appState.inZone == false) {
176188
// GPS locked but outside any zone

0 commit comments

Comments
 (0)