bump ver, get rid of buggy north-lock

This commit is contained in:
stopflock
2025-10-22 17:36:34 -05:00
parent 728ec08ab0
commit c8e2727f69
8 changed files with 27 additions and 128 deletions

View File

@@ -1,5 +1,5 @@
{
"1.2.6": {
"1.2.7": {
"content": "• NEW: Compass indicator shows map orientation and enables north-lock mode\n• Smart area caching: Loads 3x larger areas and refreshes data every 60 seconds for much faster browsing\n• Enhanced tile loading: Increased retry attempts with faster delays - tiles load much more reliably\n• Better network status: Simplified loading indicator logic\n• Instant node display: Surveillance devices now appear immediately when data finishes loading\n• Node limit alerts: Get notified when some nodes are not drawn"
},
"1.2.4": {

View File

@@ -130,7 +130,7 @@ class AppState extends ChangeNotifier {
int get maxCameras => _settingsState.maxCameras;
UploadMode get uploadMode => _settingsState.uploadMode;
FollowMeMode get followMeMode => _settingsState.followMeMode;
bool get northLockEnabled => _settingsState.northLockEnabled;
bool get proximityAlertsEnabled => _settingsState.proximityAlertsEnabled;
int get proximityAlertDistance => _settingsState.proximityAlertDistance;
bool get networkStatusIndicatorEnabled => _settingsState.networkStatusIndicatorEnabled;
@@ -411,10 +411,6 @@ class AppState extends ChangeNotifier {
await _settingsState.setFollowMeMode(mode);
}
Future<void> setNorthLockEnabled(bool enabled) async {
await _settingsState.setNorthLockEnabled(enabled);
}
/// Set proximity alerts enabled/disabled
Future<void> setProximityAlertsEnabled(bool enabled) async {
await _settingsState.setProximityAlertsEnabled(enabled);

View File

@@ -69,8 +69,7 @@ const double kPreFetchAreaExpansionMultiplier = 3.0; // Expand visible bounds by
const int kPreFetchZoomLevel = 10; // Always pre-fetch at this zoom level for consistent area sizes
const int kMaxPreFetchSplitDepth = 3; // Maximum recursive splits when hitting Overpass node limit
// North lock configuration
const double kNorthLockDisableThresholdDegrees = 10.0; // Rotation threshold to disable north lock (degrees)
// Data refresh configuration
const int kDataRefreshIntervalSeconds = 60; // Refresh cached data after this many seconds
// Follow-me mode smooth transitions

View File

@@ -24,7 +24,6 @@ class SettingsState extends ChangeNotifier {
static const String _selectedTileTypePrefsKey = 'selected_tile_type';
static const String _legacyTestModePrefsKey = 'test_mode';
static const String _followMeModePrefsKey = 'follow_me_mode';
static const String _northLockEnabledPrefsKey = 'north_lock_enabled';
static const String _proximityAlertsEnabledPrefsKey = 'proximity_alerts_enabled';
static const String _proximityAlertDistancePrefsKey = 'proximity_alert_distance';
static const String _networkStatusIndicatorEnabledPrefsKey = 'network_status_indicator_enabled';
@@ -34,7 +33,6 @@ class SettingsState extends ChangeNotifier {
int _maxCameras = 250;
UploadMode _uploadMode = kEnableDevelopmentModes ? UploadMode.simulate : UploadMode.production;
FollowMeMode _followMeMode = FollowMeMode.follow;
bool _northLockEnabled = false;
bool _proximityAlertsEnabled = false;
int _proximityAlertDistance = kProximityAlertDefaultDistance;
bool _networkStatusIndicatorEnabled = false;
@@ -47,7 +45,6 @@ class SettingsState extends ChangeNotifier {
int get maxCameras => _maxCameras;
UploadMode get uploadMode => _uploadMode;
FollowMeMode get followMeMode => _followMeMode;
bool get northLockEnabled => _northLockEnabled;
bool get proximityAlertsEnabled => _proximityAlertsEnabled;
int get proximityAlertDistance => _proximityAlertDistance;
bool get networkStatusIndicatorEnabled => _networkStatusIndicatorEnabled;
@@ -100,9 +97,6 @@ class SettingsState extends ChangeNotifier {
_maxCameras = prefs.getInt(_maxCamerasPrefsKey) ?? 250;
}
// Load north lock enabled setting
_northLockEnabled = prefs.getBool(_northLockEnabledPrefsKey) ?? false;
// Load proximity alerts settings
_proximityAlertsEnabled = prefs.getBool(_proximityAlertsEnabledPrefsKey) ?? false;
_proximityAlertDistance = prefs.getInt(_proximityAlertDistancePrefsKey) ?? kProximityAlertDefaultDistance;
@@ -298,29 +292,12 @@ class SettingsState extends ChangeNotifier {
if (_followMeMode != mode) {
_followMeMode = mode;
// Disable north lock when switching to rotating mode (incompatible)
if (mode == FollowMeMode.rotating && _northLockEnabled) {
_northLockEnabled = false;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_northLockEnabledPrefsKey, false);
}
final prefs = await SharedPreferences.getInstance();
await prefs.setInt(_followMeModePrefsKey, mode.index);
notifyListeners();
}
}
/// Set north lock enabled/disabled
Future<void> setNorthLockEnabled(bool enabled) async {
if (_northLockEnabled != enabled) {
_northLockEnabled = enabled;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_northLockEnabledPrefsKey, enabled);
notifyListeners();
}
}
/// Set proximity alerts enabled/disabled
Future<void> setProximityAlertsEnabled(bool enabled) async {
if (_proximityAlertsEnabled != enabled) {

View File

@@ -6,7 +6,7 @@ import 'package:provider/provider.dart';
import '../app_state.dart';
/// A compass indicator widget that shows the current map rotation and allows tapping to enable/disable north lock.
/// A compass indicator widget that shows the current map rotation and allows tapping to animate to north.
/// The compass appears in the top-right corner of the map and is disabled (non-interactive) when in follow+rotate mode.
class CompassIndicator extends StatefulWidget {
final AnimatedMapController mapController;
@@ -21,8 +21,6 @@ class CompassIndicator extends StatefulWidget {
}
class _CompassIndicatorState extends State<CompassIndicator> {
double _lastRotation = 0.0;
@override
Widget build(BuildContext context) {
return Consumer<AppState>(
@@ -40,38 +38,23 @@ class _CompassIndicatorState extends State<CompassIndicator> {
// Check if we're in follow+rotate mode (compass should be disabled)
final isDisabled = appState.followMeMode == FollowMeMode.rotating;
final northLockEnabled = appState.northLockEnabled;
// Force rebuild when north lock changes by comparing rotation
if (northLockEnabled && rotationDegrees != _lastRotation) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) setState(() {});
});
}
_lastRotation = rotationDegrees;
return Positioned(
top: (appState.uploadMode == UploadMode.sandbox || appState.uploadMode == UploadMode.simulate) ? 60 : 18,
right: 16,
child: GestureDetector(
onTap: isDisabled ? null : () {
// Toggle north lock (but not when in follow+rotate mode)
final newNorthLockEnabled = !northLockEnabled;
appState.setNorthLockEnabled(newNorthLockEnabled);
// If enabling north lock, animate to north-up orientation
if (newNorthLockEnabled) {
try {
widget.mapController.animateTo(
dest: widget.mapController.mapController.camera.center,
zoom: widget.mapController.mapController.camera.zoom,
rotation: 0.0,
duration: const Duration(milliseconds: 500),
curve: Curves.easeOut,
);
} catch (_) {
// Controller not ready, ignore
}
// Animate to north-up orientation
try {
widget.mapController.animateTo(
dest: widget.mapController.mapController.camera.center,
zoom: widget.mapController.mapController.camera.zoom,
rotation: 0.0,
duration: const Duration(milliseconds: 500),
curve: Curves.easeOut,
);
} catch (_) {
// Controller not ready, ignore
}
},
child: Container(
@@ -85,10 +68,8 @@ class _CompassIndicatorState extends State<CompassIndicator> {
border: Border.all(
color: isDisabled
? Colors.grey.shade400
: (northLockEnabled
? Theme.of(context).colorScheme.primary
: Colors.grey.shade300),
width: northLockEnabled ? 3.0 : 2.0,
: Colors.grey.shade300,
width: 2.0,
),
boxShadow: [
BoxShadow(
@@ -128,9 +109,7 @@ class _CompassIndicatorState extends State<CompassIndicator> {
size: 20,
color: isDisabled
? Colors.grey.shade600
: (northLockEnabled
? Colors.red.shade700
: Colors.red.shade600),
: Colors.red.shade600,
),
),
// Small 'N' label
@@ -141,9 +120,7 @@ class _CompassIndicatorState extends State<CompassIndicator> {
fontWeight: FontWeight.bold,
color: isDisabled
? Colors.grey.shade600
: (northLockEnabled
? Colors.red.shade700
: Colors.red.shade600),
: Colors.red.shade600,
),
),
],

View File

@@ -89,8 +89,7 @@ class GpsController {
int proximityAlertDistance = 200,
List<OsmNode> nearbyNodes = const [],
List<NodeProfile> enabledProfiles = const [],
// Optional parameter for north lock functionality
bool northLockEnabled = false,
}) {
final latLng = LatLng(position.latitude, position.longitude);
_currentLatLng = latLng;
@@ -114,12 +113,11 @@ class GpsController {
WidgetsBinding.instance.addPostFrameCallback((_) {
try {
if (followMeMode == FollowMeMode.follow) {
// Follow position only, keep current rotation (unless north lock is enabled)
final rotation = northLockEnabled ? 0.0 : controller.mapController.camera.rotation;
// Follow position only, keep current rotation
controller.animateTo(
dest: latLng,
zoom: controller.mapController.camera.zoom,
rotation: rotation,
rotation: controller.mapController.camera.rotation,
duration: kFollowMeAnimationDuration,
curve: Curves.easeOut,
);
@@ -157,7 +155,7 @@ class GpsController {
required int Function() getProximityAlertDistance,
required List<OsmNode> Function() getNearbyNodes,
required List<NodeProfile> Function() getEnabledProfiles,
required bool Function() getNorthLockEnabled,
}) async {
final perm = await Geolocator.requestPermission();
if (perm == LocationPermission.denied ||
@@ -173,8 +171,6 @@ class GpsController {
final proximityAlertDistance = getProximityAlertDistance();
final nearbyNodes = getNearbyNodes();
final enabledProfiles = getEnabledProfiles();
final northLockEnabled = getNorthLockEnabled();
processPositionUpdate(
position: position,
followMeMode: currentFollowMeMode,
@@ -184,7 +180,6 @@ class GpsController {
proximityAlertDistance: proximityAlertDistance,
nearbyNodes: nearbyNodes,
enabledProfiles: enabledProfiles,
northLockEnabled: northLockEnabled,
);
});
}

View File

@@ -74,8 +74,7 @@ class MapViewState extends State<MapView> {
// Track map center to clear queue on significant panning
LatLng? _lastCenter;
// Track rotation to detect intentional vs accidental rotation
double? _lastRotation;
// State for proximity alert banner
bool _showProximityBanner = false;
@@ -181,17 +180,7 @@ class MapViewState extends State<MapView> {
}
return [];
},
getNorthLockEnabled: () {
if (mounted) {
try {
return context.read<AppState>().northLockEnabled;
} catch (e) {
debugPrint('[MapView] Could not read north lock enabled: $e');
return false;
}
}
return false;
},
);
// Fetch initial cameras
@@ -561,41 +550,7 @@ class MapViewState extends State<MapView> {
if (gesture) {
widget.onUserGesture();
// Handle north lock: prevent rotation or disable lock if user rotates significantly
if (appState.northLockEnabled) {
try {
final currentRotation = pos.rotation;
if (_lastRotation != null) {
// Calculate rotation change since last gesture
final rotationChange = (currentRotation - _lastRotation!).abs();
// If user tries to rotate significantly, disable north lock and allow it
if (rotationChange > kNorthLockDisableThresholdDegrees) {
appState.setNorthLockEnabled(false);
// Allow this rotation to proceed
} else {
// Small rotation or zoom gesture - force map back to north (0°)
if (currentRotation.abs() > 0.1) { // Only correct if actually rotated
WidgetsBinding.instance.addPostFrameCallback((_) {
try {
_controller.animateTo(
dest: pos.center,
zoom: pos.zoom,
rotation: 0.0,
duration: const Duration(milliseconds: 100), // Quick snap back
curve: Curves.easeOut,
);
} catch (_) {
// Controller not ready, ignore
}
});
}
}
}
_lastRotation = currentRotation;
} catch (_) {
// Controller not ready, ignore
}
}
}
if (session != null) {

View File

@@ -1,7 +1,7 @@
name: deflockapp
description: Map public surveillance infrastructure with OpenStreetMap
publish_to: "none"
version: 1.2.6+5 # The thing after the + is the version code, incremented with each release
version: 1.2.7+6 # The thing after the + is the version code, incremented with each release
environment:
sdk: ">=3.5.0 <4.0.0" # oauth2_client 4.x needs Dart 3.5+