From c712aba72463935f7af110630c7738f302619a3b Mon Sep 17 00:00:00 2001 From: Doug Borg Date: Mon, 2 Feb 2026 00:55:03 -0700 Subject: [PATCH] Add flutter_lints and fix analyzer errors, dead code, and unused imports --- lib/app_state.dart | 2 -- lib/migrations.dart | 1 - lib/models/direction_fov.dart | 2 +- lib/models/node_profile.dart | 1 - lib/models/operator_profile.dart | 1 - lib/screens/advanced_settings_screen.dart | 1 - .../coordinators/sheet_coordinator.dart | 3 +- lib/screens/home_screen.dart | 34 ------------------- lib/screens/operator_profile_editor.dart | 1 - lib/screens/profile_editor.dart | 1 - .../settings/sections/language_section.dart | 6 ++-- .../sections/offline_areas_section.dart | 8 ++--- .../settings/sections/queue_section.dart | 17 +++++----- .../sections/upload_mode_section.dart | 1 - lib/screens/tile_provider_editor_screen.dart | 1 - lib/screens/upload_queue_screen.dart | 27 +++++++-------- lib/services/auth_service.dart | 4 +-- lib/services/changelog_service.dart | 5 ++- lib/services/deep_link_service.dart | 3 +- lib/services/deflock_tile_provider.dart | 10 +++--- lib/services/map_data_provider.dart | 1 - .../nodes_from_osm_api.dart | 3 +- .../map_data_submodules/tiles_from_local.dart | 1 - lib/services/network_status.dart | 2 +- lib/services/node_data_manager.dart | 2 -- lib/services/offline_area_service.dart | 3 -- lib/services/routing_service.dart | 10 +++--- lib/services/suspected_location_cache.dart | 1 - lib/services/suspected_location_database.dart | 2 -- lib/services/suspected_location_service.dart | 4 +-- lib/services/tile_preview_service.dart | 1 + lib/services/uploader.dart | 10 ++---- lib/state/search_state.dart | 1 - lib/widgets/add_node_sheet.dart | 34 +++++-------------- lib/widgets/changelog_dialog.dart | 1 - lib/widgets/compass_indicator.dart | 1 - lib/widgets/download_area_dialog.dart | 4 +-- lib/widgets/edit_node_sheet.dart | 23 +++++-------- lib/widgets/map/direction_cones.dart | 28 --------------- lib/widgets/map/map_data_manager.dart | 1 - lib/widgets/map/map_overlays.dart | 2 -- lib/widgets/map/marker_layer_builder.dart | 1 - lib/widgets/map/node_markers.dart | 4 +-- lib/widgets/map/node_refresh_controller.dart | 1 - .../map/suspected_location_markers.dart | 4 +-- lib/widgets/map/tile_layer_manager.dart | 3 +- lib/widgets/node_provider_with_cache.dart | 3 -- lib/widgets/nuclear_reset_dialog.dart | 8 ++--- lib/widgets/proximity_warning_dialog.dart | 1 - lib/widgets/search_bar.dart | 6 ++-- lib/widgets/suspected_location_sheet.dart | 3 -- pubspec.lock | 16 +++++++++ pubspec.yaml | 3 ++ test/models/tile_provider_test.dart | 16 ++++----- 54 files changed, 107 insertions(+), 226 deletions(-) diff --git a/lib/app_state.dart b/lib/app_state.dart index 78ef65d..88b92bf 100644 --- a/lib/app_state.dart +++ b/lib/app_state.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter_map/flutter_map.dart' show LatLngBounds; import 'package:http/http.dart' as http; import 'package:latlong2/latlong.dart'; @@ -23,7 +22,6 @@ import 'services/operator_profile_service.dart'; import 'services/deep_link_service.dart'; import 'widgets/node_provider_with_cache.dart'; import 'services/profile_service.dart'; -import 'widgets/proximity_warning_dialog.dart'; import 'widgets/reauth_messages_dialog.dart'; import 'dev_config.dart'; import 'state/auth_state.dart'; diff --git a/lib/migrations.dart b/lib/migrations.dart index a661501..54f2dca 100644 --- a/lib/migrations.dart +++ b/lib/migrations.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; diff --git a/lib/models/direction_fov.dart b/lib/models/direction_fov.dart index 9e65fd5..948a60e 100644 --- a/lib/models/direction_fov.dart +++ b/lib/models/direction_fov.dart @@ -9,7 +9,7 @@ class DirectionFov { DirectionFov(this.centerDegrees, this.fovDegrees); @override - String toString() => 'DirectionFov(center: ${centerDegrees}°, fov: ${fovDegrees}°)'; + String toString() => 'DirectionFov(center: $centerDegrees°, fov: $fovDegrees°)'; @override bool operator ==(Object other) => diff --git a/lib/models/node_profile.dart b/lib/models/node_profile.dart index e532cde..61aaad6 100644 --- a/lib/models/node_profile.dart +++ b/lib/models/node_profile.dart @@ -1,4 +1,3 @@ -import 'package:uuid/uuid.dart'; import 'osm_node.dart'; /// Sentinel value for copyWith methods to distinguish between null and not provided diff --git a/lib/models/operator_profile.dart b/lib/models/operator_profile.dart index 30db363..487086a 100644 --- a/lib/models/operator_profile.dart +++ b/lib/models/operator_profile.dart @@ -1,4 +1,3 @@ -import 'package:uuid/uuid.dart'; import 'osm_node.dart'; /// A bundle of OSM tags that describe a particular surveillance operator. diff --git a/lib/screens/advanced_settings_screen.dart b/lib/screens/advanced_settings_screen.dart index 17bf570..b5630a4 100644 --- a/lib/screens/advanced_settings_screen.dart +++ b/lib/screens/advanced_settings_screen.dart @@ -3,7 +3,6 @@ import 'settings/sections/max_nodes_section.dart'; import 'settings/sections/proximity_alerts_section.dart'; import 'settings/sections/suspected_locations_section.dart'; import 'settings/sections/tile_provider_section.dart'; -import 'settings/sections/network_status_section.dart'; import '../services/localization_service.dart'; class AdvancedSettingsScreen extends StatelessWidget { diff --git a/lib/screens/coordinators/sheet_coordinator.dart b/lib/screens/coordinators/sheet_coordinator.dart index 14f15f4..c984641 100644 --- a/lib/screens/coordinators/sheet_coordinator.dart +++ b/lib/screens/coordinators/sheet_coordinator.dart @@ -9,7 +9,6 @@ import '../../widgets/add_node_sheet.dart'; import '../../widgets/edit_node_sheet.dart'; import '../../widgets/navigation_sheet.dart'; import '../../widgets/measured_sheet.dart'; -import '../../state/settings_state.dart' show FollowMeMode; /// Coordinates all bottom sheet operations including opening, closing, height tracking, /// and sheet-related validation logic. @@ -266,7 +265,7 @@ class SheetCoordinator { /// Restore the follow-me mode that was active before opening a node sheet void _restoreFollowMeMode(AppState appState) { if (_followMeModeBeforeSheet != null) { - debugPrint('[SheetCoordinator] Restoring follow-me mode: ${_followMeModeBeforeSheet}'); + debugPrint('[SheetCoordinator] Restoring follow-me mode: $_followMeModeBeforeSheet'); appState.setFollowMeMode(_followMeModeBeforeSheet!); _followMeModeBeforeSheet = null; // Clear stored state } diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 32f01d9..3242edc 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map_animations/flutter_map_animations.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:latlong2/latlong.dart'; import 'package:provider/provider.dart'; import '../app_state.dart'; @@ -10,12 +8,9 @@ import '../dev_config.dart'; import '../widgets/map_view.dart'; import '../services/localization_service.dart'; -import '../widgets/add_node_sheet.dart'; -import '../widgets/edit_node_sheet.dart'; import '../widgets/node_tag_sheet.dart'; import '../widgets/download_area_dialog.dart'; import '../widgets/measured_sheet.dart'; -import '../widgets/navigation_sheet.dart'; import '../widgets/search_bar.dart'; import '../widgets/suspected_location_sheet.dart'; import '../widgets/welcome_dialog.dart'; @@ -252,35 +247,6 @@ class _HomeScreenState extends State with TickerProviderStateMixin { ); } - void _zoomAndCenterForRoute(bool followMeEnabled, LatLng? userLocation, LatLng? routeStart) { - try { - LatLng centerLocation; - - if (followMeEnabled && userLocation != null) { - // Center on user if follow-me is enabled - centerLocation = userLocation; - debugPrint('[HomeScreen] Centering on user location for route start'); - } else if (routeStart != null) { - // Center on start pin if user is far away or no GPS - centerLocation = routeStart; - debugPrint('[HomeScreen] Centering on route start pin'); - } else { - debugPrint('[HomeScreen] No valid location to center on'); - return; - } - - // Animate to zoom 14 and center location - _mapController.animateTo( - dest: centerLocation, - zoom: 14.0, - duration: const Duration(milliseconds: 800), - curve: Curves.easeInOut, - ); - } catch (e) { - debugPrint('[HomeScreen] Could not zoom/center for route: $e'); - } - } - void _onResumeRoute() { _navigationCoordinator.resumeRoute( context: context, diff --git a/lib/screens/operator_profile_editor.dart b/lib/screens/operator_profile_editor.dart index 486a58a..b967d62 100644 --- a/lib/screens/operator_profile_editor.dart +++ b/lib/screens/operator_profile_editor.dart @@ -105,7 +105,6 @@ class _OperatorProfileEditorState extends State { return List.generate(_tags.length, (i) { final keyController = TextEditingController(text: _tags[i].key); - final valueController = TextEditingController(text: _tags[i].value); return Padding( padding: const EdgeInsets.only(bottom: 8.0), diff --git a/lib/screens/profile_editor.dart b/lib/screens/profile_editor.dart index e607479..08a6bf5 100644 --- a/lib/screens/profile_editor.dart +++ b/lib/screens/profile_editor.dart @@ -153,7 +153,6 @@ class _ProfileEditorState extends State { return List.generate(_tags.length, (i) { final keyController = TextEditingController(text: _tags[i].key); - final valueController = TextEditingController(text: _tags[i].value); return Padding( padding: const EdgeInsets.only(bottom: 8.0), diff --git a/lib/screens/settings/sections/language_section.dart b/lib/screens/settings/sections/language_section.dart index 6dbb42d..ccf58ca 100644 --- a/lib/screens/settings/sections/language_section.dart +++ b/lib/screens/settings/sections/language_section.dart @@ -23,14 +23,14 @@ class _LanguageSectionState extends State { _loadLanguageNames(); } - _loadSelectedLanguage() async { + Future _loadSelectedLanguage() async { final prefs = await SharedPreferences.getInstance(); setState(() { _selectedLanguage = prefs.getString('language_code'); }); } - _loadLanguageNames() async { + Future _loadLanguageNames() async { final locService = LocalizationService.instance; final Map names = {}; @@ -43,7 +43,7 @@ class _LanguageSectionState extends State { }); } - _setLanguage(String? languageCode) async { + Future _setLanguage(String? languageCode) async { await LocalizationService.instance.setLanguage(languageCode); setState(() { _selectedLanguage = languageCode; diff --git a/lib/screens/settings/sections/offline_areas_section.dart b/lib/screens/settings/sections/offline_areas_section.dart index 8c623c0..51261e8 100644 --- a/lib/screens/settings/sections/offline_areas_section.dart +++ b/lib/screens/settings/sections/offline_areas_section.dart @@ -87,9 +87,9 @@ class _OfflineAreasSectionState extends State { : "${(area.sizeBytes / 1024).toStringAsFixed(1)} ${locService.t('offlineAreas.kilobytes')}" : '--'; - String subtitle = '${locService.t('offlineAreas.provider')}: ${area.tileProviderDisplay}\n' + - '${locService.t('offlineAreas.maxZoom')}: Z${area.maxZoom}' + '\n' + - '${locService.t('offlineAreas.latitude')}: ${area.bounds.southWest.latitude.toStringAsFixed(3)}, ${area.bounds.southWest.longitude.toStringAsFixed(3)}\n' + + String subtitle = '${locService.t('offlineAreas.provider')}: ${area.tileProviderDisplay}\n' + '${locService.t('offlineAreas.maxZoom')}: Z${area.maxZoom}\n' + '${locService.t('offlineAreas.latitude')}: ${area.bounds.southWest.latitude.toStringAsFixed(3)}, ${area.bounds.southWest.longitude.toStringAsFixed(3)}\n' '${locService.t('offlineAreas.latitude')}: ${area.bounds.northEast.latitude.toStringAsFixed(3)}, ${area.bounds.northEast.longitude.toStringAsFixed(3)}'; if (area.status == OfflineAreaStatus.downloading) { @@ -207,7 +207,7 @@ class _OfflineAreasSectionState extends State { : null, ), ); - }).toList(), + }), ], ); }, diff --git a/lib/screens/settings/sections/queue_section.dart b/lib/screens/settings/sections/queue_section.dart index 4c4d946..45baa1c 100644 --- a/lib/screens/settings/sections/queue_section.dart +++ b/lib/screens/settings/sections/queue_section.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../../../app_state.dart'; import '../../../services/localization_service.dart'; -import '../../../state/settings_state.dart'; class QueueSection extends StatelessWidget { const QueueSection({super.key}); @@ -116,16 +115,16 @@ class QueueSection extends StatelessWidget { (upload.error ? locService.t('queue.error') : "") + (upload.completing ? locService.t('queue.completing') : "")), subtitle: Text( - locService.t('queue.destination', params: [_getUploadModeDisplayName(upload.uploadMode)]) + '\n' + - locService.t('queue.latitude', params: [upload.coord.latitude.toStringAsFixed(6)]) + '\n' + - locService.t('queue.longitude', params: [upload.coord.longitude.toStringAsFixed(6)]) + '\n' + - locService.t('queue.direction', params: [ - upload.direction is String + '${locService.t('queue.destination', params: [_getUploadModeDisplayName(upload.uploadMode)])}\n' + '${locService.t('queue.latitude', params: [upload.coord.latitude.toStringAsFixed(6)])}\n' + '${locService.t('queue.longitude', params: [upload.coord.longitude.toStringAsFixed(6)])}\n' + '${locService.t('queue.direction', params: [ + upload.direction is String ? upload.direction.toString() : upload.direction.round().toString() - ]) + '\n' + - locService.t('queue.attempts', params: [upload.attempts.toString()]) + - (upload.error ? "\n${locService.t('queue.uploadFailedRetry')}" : "") + ])}\n' + '${locService.t('queue.attempts', params: [upload.attempts.toString()])}' + '${upload.error ? "\n${locService.t('queue.uploadFailedRetry')}" : ""}' ), trailing: Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/screens/settings/sections/upload_mode_section.dart b/lib/screens/settings/sections/upload_mode_section.dart index 6875596..65d280e 100644 --- a/lib/screens/settings/sections/upload_mode_section.dart +++ b/lib/screens/settings/sections/upload_mode_section.dart @@ -95,7 +95,6 @@ class UploadModeSection extends StatelessWidget { ), ); case UploadMode.simulate: - default: return Text( locService.t('uploadMode.simulateDescription'), style: TextStyle( diff --git a/lib/screens/tile_provider_editor_screen.dart b/lib/screens/tile_provider_editor_screen.dart index 01a51d2..213090a 100644 --- a/lib/screens/tile_provider_editor_screen.dart +++ b/lib/screens/tile_provider_editor_screen.dart @@ -2,7 +2,6 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:http/http.dart' as http; -import 'package:collection/collection.dart'; import '../app_state.dart'; import '../models/tile_provider.dart'; diff --git a/lib/screens/upload_queue_screen.dart b/lib/screens/upload_queue_screen.dart index 3221030..16ca969 100644 --- a/lib/screens/upload_queue_screen.dart +++ b/lib/screens/upload_queue_screen.dart @@ -3,7 +3,6 @@ import 'package:provider/provider.dart'; import '../app_state.dart'; import '../models/pending_upload.dart'; import '../services/localization_service.dart'; -import '../state/settings_state.dart'; class UploadQueueScreen extends StatelessWidget { const UploadQueueScreen({super.key}); @@ -114,8 +113,8 @@ class UploadQueueScreen extends StatelessWidget { margin: const EdgeInsets.only(bottom: 16), padding: const EdgeInsets.all(12), decoration: BoxDecoration( - color: Colors.orange.withOpacity(0.1), - border: Border.all(color: Colors.orange.withOpacity(0.3)), + color: Colors.orange.withValues(alpha: 0.1), + border: Border.all(color: Colors.orange.withValues(alpha: 0.3)), borderRadius: BorderRadius.circular(8), ), child: Row( @@ -205,7 +204,7 @@ class UploadQueueScreen extends StatelessWidget { icon: const Icon(Icons.clear_all), label: Text(locService.t('queue.clearUploadQueue')), style: ElevatedButton.styleFrom( - backgroundColor: appState.pendingCount > 0 ? null : Theme.of(context).disabledColor.withOpacity(0.1), + backgroundColor: appState.pendingCount > 0 ? null : Theme.of(context).disabledColor.withValues(alpha: 0.1), ), ), ), @@ -224,13 +223,13 @@ class UploadQueueScreen extends StatelessWidget { Icon( Icons.check_circle_outline, size: 64, - color: Theme.of(context).textTheme.bodySmall?.color?.withOpacity(0.4), + color: Theme.of(context).textTheme.bodySmall?.color?.withValues(alpha: 0.4), ), const SizedBox(height: 16), Text( locService.t('queue.nothingInQueue'), style: Theme.of(context).textTheme.titleMedium?.copyWith( - color: Theme.of(context).textTheme.bodySmall?.color?.withOpacity(0.6), + color: Theme.of(context).textTheme.bodySmall?.color?.withValues(alpha: 0.6), ), textAlign: TextAlign.center, ), @@ -272,16 +271,16 @@ class UploadQueueScreen extends StatelessWidget { _getUploadStateText(upload, locService) ), subtitle: Text( - locService.t('queue.destination', params: [_getUploadModeDisplayName(upload.uploadMode)]) + '\n' + - locService.t('queue.latitude', params: [upload.coord.latitude.toStringAsFixed(6)]) + '\n' + - locService.t('queue.longitude', params: [upload.coord.longitude.toStringAsFixed(6)]) + '\n' + - locService.t('queue.direction', params: [ - upload.direction is String + '${locService.t('queue.destination', params: [_getUploadModeDisplayName(upload.uploadMode)])}\n' + '${locService.t('queue.latitude', params: [upload.coord.latitude.toStringAsFixed(6)])}\n' + '${locService.t('queue.longitude', params: [upload.coord.longitude.toStringAsFixed(6)])}\n' + '${locService.t('queue.direction', params: [ + upload.direction is String ? upload.direction.toString() : upload.direction.round().toString() - ]) + '\n' + - locService.t('queue.attempts', params: [upload.attempts.toString()]) + - (upload.uploadState == UploadState.error ? "\n${locService.t('queue.uploadFailedRetry')}" : "") + ])}\n' + '${locService.t('queue.attempts', params: [upload.attempts.toString()])}' + '${upload.uploadState == UploadState.error ? "\n${locService.t('queue.uploadFailedRetry')}" : ""}' ), trailing: Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/services/auth_service.dart b/lib/services/auth_service.dart index bdc1b9c..843d642 100644 --- a/lib/services/auth_service.dart +++ b/lib/services/auth_service.dart @@ -1,6 +1,5 @@ import 'dart:convert'; import 'dart:developer'; -import 'dart:math' as math; import 'package:oauth2_client/oauth2_client.dart'; import 'package:oauth2_client/oauth2_helper.dart'; @@ -30,7 +29,6 @@ class AuthService { case UploadMode.sandbox: return 'osm_token_sandbox'; case UploadMode.simulate: - default: return 'osm_token_simulate'; } } @@ -97,7 +95,7 @@ class AuthService { final tokenJson = jsonEncode(tokenMap); final prefs = await SharedPreferences.getInstance(); await prefs.setString(_tokenKey, tokenJson); // Save token for current mode - _displayName = await _fetchUsername(token!.accessToken!); + _displayName = await _fetchUsername(token.accessToken!); return _displayName; } catch (e) { print('AuthService: OAuth login failed: $e'); diff --git a/lib/services/changelog_service.dart b/lib/services/changelog_service.dart index 244fc19..9244d70 100644 --- a/lib/services/changelog_service.dart +++ b/lib/services/changelog_service.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -304,8 +303,8 @@ class ChangelogService { final v2Parts = v2.split('.').map(int.parse).toList(); // Ensure we have at least 3 parts (major.minor.patch) - while (v1Parts.length < 3) v1Parts.add(0); - while (v2Parts.length < 3) v2Parts.add(0); + while (v1Parts.length < 3) { v1Parts.add(0); } + while (v2Parts.length < 3) { v2Parts.add(0); } // Compare major version first if (v1Parts[0] < v2Parts[0]) return -1; diff --git a/lib/services/deep_link_service.dart b/lib/services/deep_link_service.dart index ca57599..cbf4f2e 100644 --- a/lib/services/deep_link_service.dart +++ b/lib/services/deep_link_service.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:app_links/app_links.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/foundation.dart'; import '../models/node_profile.dart'; import 'profile_import_service.dart'; @@ -87,7 +86,7 @@ class DeepLinkService { } } - /// Handle profile add deep link: deflockapp://profiles/add?p= + /// Handle profile add deep link: `deflockapp://profiles/add?p=` void _handleAddProfileLink(Uri uri) { final base64Data = uri.queryParameters['p']; diff --git a/lib/services/deflock_tile_provider.dart b/lib/services/deflock_tile_provider.dart index 0c95d53..f5b9533 100644 --- a/lib/services/deflock_tile_provider.dart +++ b/lib/services/deflock_tile_provider.dart @@ -1,12 +1,12 @@ -import 'package:flutter_map/flutter_map.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; import 'dart:async'; import 'dart:typed_data'; import 'dart:ui'; +import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; + import '../app_state.dart'; -import '../models/tile_provider.dart' as models; import 'map_data_provider.dart'; import 'offline_area_service.dart'; @@ -108,7 +108,7 @@ class DeflockTileImageProvider extends ImageProvider { // Re-throw the exception and let FlutterMap handle missing tiles gracefully // This is better than trying to provide fallback images - throw e; + rethrow; } } diff --git a/lib/services/map_data_provider.dart b/lib/services/map_data_provider.dart index d989589..34c24c8 100644 --- a/lib/services/map_data_provider.dart +++ b/lib/services/map_data_provider.dart @@ -1,6 +1,5 @@ import 'package:latlong2/latlong.dart'; import 'package:flutter_map/flutter_map.dart'; -import 'package:flutter/foundation.dart'; import '../models/node_profile.dart'; import '../models/osm_node.dart'; diff --git a/lib/services/map_data_submodules/nodes_from_osm_api.dart b/lib/services/map_data_submodules/nodes_from_osm_api.dart index 142e6fd..8d7e676 100644 --- a/lib/services/map_data_submodules/nodes_from_osm_api.dart +++ b/lib/services/map_data_submodules/nodes_from_osm_api.dart @@ -1,4 +1,3 @@ -import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:flutter/foundation.dart'; import 'package:latlong2/latlong.dart'; @@ -81,7 +80,7 @@ Future> _fetchFromOsmApi({ debugPrint('[fetchOsmApiNodes] Exception: $e'); // Don't report status here - let the top level handle it - throw e; // Re-throw to let caller handle + rethrow; // Re-throw to let caller handle } } diff --git a/lib/services/map_data_submodules/tiles_from_local.dart b/lib/services/map_data_submodules/tiles_from_local.dart index 69b732c..373f20d 100644 --- a/lib/services/map_data_submodules/tiles_from_local.dart +++ b/lib/services/map_data_submodules/tiles_from_local.dart @@ -1,5 +1,4 @@ import 'dart:io'; -import 'package:latlong2/latlong.dart'; import '../offline_area_service.dart'; import '../offline_areas/offline_area_models.dart'; import '../offline_areas/offline_tile_utils.dart'; diff --git a/lib/services/network_status.dart b/lib/services/network_status.dart index f482b69..4dd3bb3 100644 --- a/lib/services/network_status.dart +++ b/lib/services/network_status.dart @@ -5,7 +5,7 @@ import 'dart:async'; /// Only tracks the latest user-initiated request - background requests are ignored. enum NetworkRequestStatus { idle, // No active requests - loading, // Request in progress + loading, // Request in progress splitting, // Request being split due to limits/timeouts success, // Data loaded successfully timeout, // Request timed out diff --git a/lib/services/node_data_manager.dart b/lib/services/node_data_manager.dart index 94da51a..2dbaeeb 100644 --- a/lib/services/node_data_manager.dart +++ b/lib/services/node_data_manager.dart @@ -1,6 +1,4 @@ import 'dart:async'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; import 'package:latlong2/latlong.dart'; import 'package:flutter_map/flutter_map.dart'; diff --git a/lib/services/offline_area_service.dart b/lib/services/offline_area_service.dart index ccdcf8c..9300825 100644 --- a/lib/services/offline_area_service.dart +++ b/lib/services/offline_area_service.dart @@ -1,17 +1,14 @@ import 'dart:io'; import 'dart:convert'; import 'package:flutter/foundation.dart'; -import 'package:latlong2/latlong.dart'; import 'package:flutter_map/flutter_map.dart' show LatLngBounds; import 'package:path_provider/path_provider.dart'; import 'offline_areas/offline_area_models.dart'; import 'offline_areas/offline_tile_utils.dart'; import 'offline_areas/offline_area_downloader.dart'; -import '../models/osm_node.dart'; import '../app_state.dart'; import 'map_data_provider.dart'; -import 'package:deflockapp/dev_config.dart'; /// Service for managing download, storage, and retrieval of offline map areas and cameras. class OfflineAreaService { diff --git a/lib/services/routing_service.dart b/lib/services/routing_service.dart index 94b43bc..b2dc90f 100644 --- a/lib/services/routing_service.dart +++ b/lib/services/routing_service.dart @@ -36,9 +36,9 @@ class RoutingService { debugPrint('[RoutingService] Calculating route from $start to $end'); final prefs = await SharedPreferences.getInstance(); - final avoidance_distance = await prefs.getInt('navigation_avoidance_distance'); + final avoidanceDistance = prefs.getInt('navigation_avoidance_distance') ?? 250; - final enabled_profiles = AppState.instance.enabledProfiles.map((p) { + final enabledProfiles = AppState.instance.enabledProfiles.map((p) { final full = p.toJson(); return { 'id': full['id'], @@ -47,7 +47,7 @@ class RoutingService { }; }).toList(); - final uri = Uri.parse('$_baseUrl'); + final uri = Uri.parse(_baseUrl); final params = { 'start': { 'longitude': start.longitude, @@ -57,8 +57,8 @@ class RoutingService { 'longitude': end.longitude, 'latitude': end.latitude }, - 'avoidance_distance': avoidance_distance, - 'enabled_profiles': enabled_profiles, + 'avoidance_distance': avoidanceDistance, + 'enabled_profiles': enabledProfiles, 'show_exclusion_zone': false, // for debugging: if true, returns a GeoJSON Feature MultiPolygon showing what areas are avoided in calculating the route }; diff --git a/lib/services/suspected_location_cache.dart b/lib/services/suspected_location_cache.dart index bb58480..9c4c72b 100644 --- a/lib/services/suspected_location_cache.dart +++ b/lib/services/suspected_location_cache.dart @@ -1,6 +1,5 @@ import 'package:flutter/foundation.dart'; import 'package:flutter_map/flutter_map.dart'; -import 'package:latlong2/latlong.dart'; import '../models/suspected_location.dart'; import 'suspected_location_service.dart'; diff --git a/lib/services/suspected_location_database.dart b/lib/services/suspected_location_database.dart index b893b9f..c6c61e3 100644 --- a/lib/services/suspected_location_database.dart +++ b/lib/services/suspected_location_database.dart @@ -143,7 +143,6 @@ class SuspectedLocationDatabase { // Process entries in batches to avoid memory issues const batchSize = 1000; - int totalInserted = 0; int validCount = 0; int errorCount = 0; @@ -188,7 +187,6 @@ class SuspectedLocationDatabase { // Commit this batch await batch.commit(noResult: true); - totalInserted += currentBatch.length; // Log progress every few batches if ((i ~/ batchSize) % 5 == 0) { diff --git a/lib/services/suspected_location_service.dart b/lib/services/suspected_location_service.dart index 4f82c96..8f57f33 100644 --- a/lib/services/suspected_location_service.dart +++ b/lib/services/suspected_location_service.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; -import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:http/http.dart' as http; @@ -208,7 +206,7 @@ class SuspectedLocationService { validRows++; } - } catch (e, stackTrace) { + } catch (e) { // Skip rows that can't be parsed debugPrint('[SuspectedLocationService] Error parsing row $rowIndex: $e'); continue; diff --git a/lib/services/tile_preview_service.dart b/lib/services/tile_preview_service.dart index 91d3b68..d04abb3 100644 --- a/lib/services/tile_preview_service.dart +++ b/lib/services/tile_preview_service.dart @@ -1,4 +1,5 @@ import 'dart:typed_data'; + import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; diff --git a/lib/services/uploader.dart b/lib/services/uploader.dart index 88926fc..8c675ae 100644 --- a/lib/services/uploader.dart +++ b/lib/services/uploader.dart @@ -147,7 +147,7 @@ class Uploader { final currentNodeXml = currentNodeResp.body; final versionMatch = RegExp(r'version="(\d+)"').firstMatch(currentNodeXml); if (versionMatch == null) { - final errorMsg = 'Could not parse version from node XML: ${currentNodeXml.length > 200 ? currentNodeXml.substring(0, 200) + "..." : currentNodeXml}'; + final errorMsg = 'Could not parse version from node XML: ${currentNodeXml.length > 200 ? '${currentNodeXml.substring(0, 200)}...' : currentNodeXml}'; debugPrint('[Uploader] $errorMsg'); return UploadResult.failure(errorMessage: errorMsg, changesetId: changesetId); } @@ -184,7 +184,7 @@ class Uploader { final currentNodeXml = currentNodeResp.body; final versionMatch = RegExp(r'version="(\d+)"').firstMatch(currentNodeXml); if (versionMatch == null) { - final errorMsg = 'Could not parse version from node XML for deletion: ${currentNodeXml.length > 200 ? currentNodeXml.substring(0, 200) + "..." : currentNodeXml}'; + final errorMsg = 'Could not parse version from node XML for deletion: ${currentNodeXml.length > 200 ? '${currentNodeXml.substring(0, 200)}...' : currentNodeXml}'; debugPrint('[Uploader] $errorMsg'); return UploadResult.failure(errorMessage: errorMsg, changesetId: changesetId); } @@ -350,12 +350,6 @@ class Uploader { headers: _headers, ).timeout(kUploadHttpTimeout); - Future _post(String path, String body) => http.post( - Uri.https(_host, path), - headers: _headers, - body: body, - ).timeout(kUploadHttpTimeout); - Future _put(String path, String body) => http.put( Uri.https(_host, path), headers: _headers, diff --git a/lib/state/search_state.dart b/lib/state/search_state.dart index 3adccea..7bc915b 100644 --- a/lib/state/search_state.dart +++ b/lib/state/search_state.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:latlong2/latlong.dart'; import '../models/search_result.dart'; import '../services/search_service.dart'; diff --git a/lib/widgets/add_node_sheet.dart b/lib/widgets/add_node_sheet.dart index 0a7ec2b..49bc90e 100644 --- a/lib/widgets/add_node_sheet.dart +++ b/lib/widgets/add_node_sheet.dart @@ -7,7 +7,6 @@ import 'package:flutter_map/flutter_map.dart'; import '../app_state.dart'; import '../dev_config.dart'; import '../models/node_profile.dart'; -import '../models/operator_profile.dart'; import '../services/localization_service.dart'; import '../services/map_data_provider.dart'; import '../services/node_data_manager.dart'; @@ -59,23 +58,6 @@ class _AddNodeSheetState extends State { } } - /// Listen for tutorial completion from AppState - void _onTutorialCompleted() { - _hideTutorial(); - } - - /// Also check periodically if tutorial was completed by another sheet - void _recheckTutorialStatus() async { - if (_showTutorial) { - final hasCompleted = await ChangelogService().hasCompletedPositioningTutorial(); - if (hasCompleted && mounted) { - setState(() { - _showTutorial = false; - }); - } - } - } - void _hideTutorial() { if (mounted && _showTutorial) { setState(() { @@ -402,11 +384,11 @@ class _AddNodeSheetState extends State { final locService = LocalizationService.instance; final appState = context.watch(); - void _commit() { + void commit() { _checkProximityAndCommit(context, appState, locService); } - void _cancel() { + void cancel() { appState.cancelSession(); Navigator.pop(context); } @@ -442,11 +424,11 @@ class _AddNodeSheetState extends State { session.profile!.isSubmittable && hasGoodCoverage; - void _navigateToLogin() { + void navigateToLogin() { Navigator.pushNamed(context, '/settings/osm-account'); } - - void _openRefineTags() async { + + void openRefineTags() async { final result = await Navigator.push( context, MaterialPageRoute( @@ -578,7 +560,7 @@ class _AddNodeSheetState extends State { child: SizedBox( width: double.infinity, child: OutlinedButton.icon( - onPressed: session.profile != null ? _openRefineTags : null, // Disabled when no profile selected + onPressed: session.profile != null ? openRefineTags : null, // Disabled when no profile selected icon: const Icon(Icons.tune), label: Text(locService.t('addNode.refineTags')), ), @@ -591,14 +573,14 @@ class _AddNodeSheetState extends State { children: [ Expanded( child: OutlinedButton( - onPressed: _cancel, + onPressed: cancel, child: Text(locService.cancel), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton( - onPressed: !appState.isLoggedIn ? _navigateToLogin : (allowSubmit ? _commit : null), + onPressed: !appState.isLoggedIn ? navigateToLogin : (allowSubmit ? commit : null), child: Text(!appState.isLoggedIn ? locService.t('actions.logIn') : locService.t('actions.submit')), ), ), diff --git a/lib/widgets/changelog_dialog.dart b/lib/widgets/changelog_dialog.dart index 862508b..99216ca 100644 --- a/lib/widgets/changelog_dialog.dart +++ b/lib/widgets/changelog_dialog.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import '../services/changelog_service.dart'; import '../services/version_service.dart'; class ChangelogDialog extends StatelessWidget { diff --git a/lib/widgets/compass_indicator.dart b/lib/widgets/compass_indicator.dart index e804836..4770379 100644 --- a/lib/widgets/compass_indicator.dart +++ b/lib/widgets/compass_indicator.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:math'; import 'package:flutter/material.dart'; -import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map_animations/flutter_map_animations.dart'; import 'package:provider/provider.dart'; diff --git a/lib/widgets/download_area_dialog.dart b/lib/widgets/download_area_dialog.dart index 2888490..0a4ef32 100644 --- a/lib/widgets/download_area_dialog.dart +++ b/lib/widgets/download_area_dialog.dart @@ -57,8 +57,7 @@ class _DownloadAreaDialogState extends State { } final minZoom = 1; // Always start from zoom 1 to show area overview when zoomed out - final maxZoom = _zoom.toInt(); - + // Calculate maximum possible zoom based on tile count limit and tile provider max zoom final maxPossibleZoom = _calculateMaxZoomForTileLimit(bounds, minZoom); @@ -124,7 +123,6 @@ class _DownloadAreaDialogState extends State { final locService = LocalizationService.instance; final appState = context.watch(); final bounds = widget.controller.camera.visibleBounds; - final maxZoom = _zoom.toInt(); final isOfflineMode = appState.offlineMode; // Use the calculated max possible zoom instead of fixed span diff --git a/lib/widgets/edit_node_sheet.dart b/lib/widgets/edit_node_sheet.dart index 99421e0..c9c197e 100644 --- a/lib/widgets/edit_node_sheet.dart +++ b/lib/widgets/edit_node_sheet.dart @@ -7,14 +7,11 @@ import 'package:flutter_map/flutter_map.dart'; import '../app_state.dart'; import '../dev_config.dart'; import '../models/node_profile.dart'; -import '../models/operator_profile.dart'; import '../models/pending_upload.dart'; import '../services/localization_service.dart'; import '../services/map_data_provider.dart'; import '../services/node_data_manager.dart'; import '../services/changelog_service.dart'; -import '../state/settings_state.dart'; -import '../state/session_state.dart'; import 'refine_tags_sheet.dart'; import 'advanced_edit_options_sheet.dart'; import 'proximity_warning_dialog.dart'; @@ -435,25 +432,23 @@ class _EditNodeSheetState extends State { final locService = LocalizationService.instance; final appState = context.watch(); - void _commit() { + void commit() { // Check if there are any actual changes to submit if (!_hasActualChanges(widget.session)) { _showNoChangesDialog(context, locService); return; } - + _checkProximityAndCommit(context, appState, locService); } - void _cancel() { + void cancel() { appState.cancelEditSession(); Navigator.pop(context); } final session = widget.session; final submittableProfiles = appState.enabledProfiles.where((p) => p.isSubmittable).toList(); - final isSandboxMode = appState.uploadMode == UploadMode.sandbox; - // Check if we have good cache coverage around the node position bool hasGoodCoverage = true; final nodeCoord = session.originalNode.coord; @@ -481,11 +476,11 @@ class _EditNodeSheetState extends State { session.profile!.isSubmittable && hasGoodCoverage; - void _navigateToLogin() { + void navigateToLogin() { Navigator.pushNamed(context, '/settings/osm-account'); } - - void _openRefineTags() async { + + void openRefineTags() async { final result = await Navigator.push( context, MaterialPageRoute( @@ -694,7 +689,7 @@ class _EditNodeSheetState extends State { child: SizedBox( width: double.infinity, child: OutlinedButton.icon( - onPressed: session.profile != null ? _openRefineTags : null, // Disabled when no profile selected + onPressed: session.profile != null ? openRefineTags : null, // Disabled when no profile selected icon: const Icon(Icons.tune), label: Text(locService.t('editNode.refineTags')), ), @@ -707,14 +702,14 @@ class _EditNodeSheetState extends State { children: [ Expanded( child: OutlinedButton( - onPressed: _cancel, + onPressed: cancel, child: Text(locService.cancel), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton( - onPressed: !appState.isLoggedIn ? _navigateToLogin : (allowSubmit ? _commit : null), + onPressed: !appState.isLoggedIn ? navigateToLogin : (allowSubmit ? commit : null), child: Text(!appState.isLoggedIn ? locService.t('actions.logIn') : locService.t('actions.saveEdit')), ), ), diff --git a/lib/widgets/map/direction_cones.dart b/lib/widgets/map/direction_cones.dart index df984a3..fce8265 100644 --- a/lib/widgets/map/direction_cones.dart +++ b/lib/widgets/map/direction_cones.dart @@ -6,7 +6,6 @@ import 'package:latlong2/latlong.dart'; import '../../app_state.dart'; import '../../dev_config.dart'; import '../../models/osm_node.dart'; -import '../../models/direction_fov.dart'; /// Helper class to build direction cone polygons for cameras class DirectionConesBuilder { @@ -113,11 +112,6 @@ class DirectionConesBuilder { node.coord.longitude.abs() <= 180; } - static bool _isPendingUpload(OsmNode node) { - return node.tags.containsKey('_pending_upload') && - node.tags['_pending_upload'] == 'true'; - } - /// Build cone with variable FOV width - new method for range notation support static Polygon _buildConeWithFov( LatLng origin, @@ -141,28 +135,6 @@ class DirectionConesBuilder { ); } - /// Legacy method for backward compatibility - uses dev_config FOV - static Polygon _buildCone( - LatLng origin, - double bearingDeg, - double zoom, { - required BuildContext context, - bool isPending = false, - bool isSession = false, - bool isActiveDirection = true, - }) { - return _buildConeInternal( - origin: origin, - bearingDeg: bearingDeg, - halfAngleDeg: kDirectionConeHalfAngle, - zoom: zoom, - context: context, - isPending: isPending, - isSession: isSession, - isActiveDirection: isActiveDirection, - ); - } - /// Internal cone building method that handles the actual rendering static Polygon _buildConeInternal({ required LatLng origin, diff --git a/lib/widgets/map/map_data_manager.dart b/lib/widgets/map/map_data_manager.dart index d9f3676..a74c6da 100644 --- a/lib/widgets/map/map_data_manager.dart +++ b/lib/widgets/map/map_data_manager.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; -import 'package:flutter_map_animations/flutter_map_animations.dart'; import 'package:latlong2/latlong.dart'; import '../../models/osm_node.dart'; diff --git a/lib/widgets/map/map_overlays.dart b/lib/widgets/map/map_overlays.dart index e02cf99..b284319 100644 --- a/lib/widgets/map/map_overlays.dart +++ b/lib/widgets/map/map_overlays.dart @@ -1,12 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map_animations/flutter_map_animations.dart'; import 'package:provider/provider.dart'; import '../../app_state.dart'; import '../../dev_config.dart'; import '../../services/localization_service.dart'; -import '../camera_icon.dart'; import '../compass_indicator.dart'; import 'layer_selector_button.dart'; diff --git a/lib/widgets/map/marker_layer_builder.dart b/lib/widgets/map/marker_layer_builder.dart index f70a9dd..26528b4 100644 --- a/lib/widgets/map/marker_layer_builder.dart +++ b/lib/widgets/map/marker_layer_builder.dart @@ -6,7 +6,6 @@ import 'package:latlong2/latlong.dart'; import '../../models/osm_node.dart'; import '../../models/suspected_location.dart'; import '../../app_state.dart'; -import '../../state/session_state.dart'; import '../../dev_config.dart'; import '../camera_icon.dart'; import '../provisional_pin.dart'; diff --git a/lib/widgets/map/node_markers.dart b/lib/widgets/map/node_markers.dart index 4d1292c..7c386be 100644 --- a/lib/widgets/map/node_markers.dart +++ b/lib/widgets/map/node_markers.dart @@ -20,8 +20,8 @@ class NodeMapMarker extends StatefulWidget { required this.mapController, this.onNodeTap, this.enabled = true, - Key? key, - }) : super(key: key); + super.key, + }); @override State createState() => _NodeMapMarkerState(); diff --git a/lib/widgets/map/node_refresh_controller.dart b/lib/widgets/map/node_refresh_controller.dart index 0105d72..5fce1b3 100644 --- a/lib/widgets/map/node_refresh_controller.dart +++ b/lib/widgets/map/node_refresh_controller.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_map_animations/flutter_map_animations.dart'; import 'package:flutter_map/flutter_map.dart'; -import 'package:latlong2/latlong.dart'; import '../../models/node_profile.dart'; import '../../app_state.dart' show UploadMode; diff --git a/lib/widgets/map/suspected_location_markers.dart b/lib/widgets/map/suspected_location_markers.dart index 0666300..f48c824 100644 --- a/lib/widgets/map/suspected_location_markers.dart +++ b/lib/widgets/map/suspected_location_markers.dart @@ -20,8 +20,8 @@ class SuspectedLocationMapMarker extends StatefulWidget { required this.mapController, this.onLocationTap, this.enabled = true, - Key? key, - }) : super(key: key); + super.key, + }); @override State createState() => _SuspectedLocationMapMarkerState(); diff --git a/lib/widgets/map/tile_layer_manager.dart b/lib/widgets/map/tile_layer_manager.dart index 97f5303..d436ade 100644 --- a/lib/widgets/map/tile_layer_manager.dart +++ b/lib/widgets/map/tile_layer_manager.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; -import 'package:latlong2/latlong.dart'; import '../../models/tile_provider.dart' as models; import '../../services/deflock_tile_provider.dart'; @@ -93,7 +92,7 @@ class TileLayerManager { return TileLayer( urlTemplate: urlTemplate, // Critical for cache key generation userAgentPackageName: 'me.deflock.deflockapp', - maxZoom: selectedTileType?.maxZoom?.toDouble() ?? 18.0, + maxZoom: selectedTileType?.maxZoom.toDouble() ?? 18.0, tileProvider: _tileProvider!, ); } diff --git a/lib/widgets/node_provider_with_cache.dart b/lib/widgets/node_provider_with_cache.dart index e54eade..09ff7ce 100644 --- a/lib/widgets/node_provider_with_cache.dart +++ b/lib/widgets/node_provider_with_cache.dart @@ -1,12 +1,9 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import 'package:latlong2/latlong.dart'; import 'package:flutter_map/flutter_map.dart' show LatLngBounds; -import '../services/map_data_provider.dart'; import '../services/node_data_manager.dart'; import '../services/node_spatial_cache.dart'; -import '../services/network_status.dart'; import '../models/node_profile.dart'; import '../models/osm_node.dart'; import '../app_state.dart'; diff --git a/lib/widgets/nuclear_reset_dialog.dart b/lib/widgets/nuclear_reset_dialog.dart index ad10d34..e899f5c 100644 --- a/lib/widgets/nuclear_reset_dialog.dart +++ b/lib/widgets/nuclear_reset_dialog.dart @@ -8,15 +8,15 @@ class NuclearResetDialog extends StatelessWidget { final String errorReport; const NuclearResetDialog({ - Key? key, + super.key, required this.errorReport, - }) : super(key: key); + }); @override Widget build(BuildContext context) { - return WillPopScope( + return PopScope( // Prevent back button from closing dialog - onWillPop: () async => false, + canPop: false, child: AlertDialog( title: const Row( children: [ diff --git a/lib/widgets/proximity_warning_dialog.dart b/lib/widgets/proximity_warning_dialog.dart index 81402f8..ba9298f 100644 --- a/lib/widgets/proximity_warning_dialog.dart +++ b/lib/widgets/proximity_warning_dialog.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:latlong2/latlong.dart'; import '../models/osm_node.dart'; import '../services/localization_service.dart'; diff --git a/lib/widgets/search_bar.dart b/lib/widgets/search_bar.dart index 0e09dbb..61a2f4a 100644 --- a/lib/widgets/search_bar.dart +++ b/lib/widgets/search_bar.dart @@ -107,7 +107,7 @@ class _LocationSearchBarState extends State { borderRadius: const BorderRadius.vertical(bottom: Radius.circular(12)), boxShadow: [ BoxShadow( - color: Theme.of(context).shadowColor.withOpacity(0.2), + color: Theme.of(context).shadowColor.withValues(alpha: 0.2), blurRadius: 8, offset: const Offset(0, 2), ), @@ -152,7 +152,7 @@ class _LocationSearchBarState extends State { : null, dense: true, onTap: () => _onResultTap(result), - )).toList(), + )), ], ), ); @@ -184,7 +184,7 @@ class _LocationSearchBarState extends State { borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( - color: Theme.of(context).shadowColor.withOpacity(0.2), + color: Theme.of(context).shadowColor.withValues(alpha: 0.2), blurRadius: 8, offset: const Offset(0, 2), ), diff --git a/lib/widgets/suspected_location_sheet.dart b/lib/widgets/suspected_location_sheet.dart index 8e9d4d0..470e7b9 100644 --- a/lib/widgets/suspected_location_sheet.dart +++ b/lib/widgets/suspected_location_sheet.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; import '../models/suspected_location.dart'; -import '../app_state.dart'; import '../services/localization_service.dart'; import '../dev_config.dart'; @@ -17,7 +15,6 @@ class SuspectedLocationSheet extends StatelessWidget { return AnimatedBuilder( animation: LocalizationService.instance, builder: (context, child) { - final appState = context.watch(); final locService = LocalizationService.instance; // Get all fields except location and ticket_no diff --git a/pubspec.lock b/pubspec.lock index c266e82..27e167b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -222,6 +222,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" + url: "https://pub.dev" + source: hosted + version: "6.0.0" flutter_local_notifications: dependency: "direct main" description: @@ -496,6 +504,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0" + lints: + dependency: transitive + description: + name: lints + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" + url: "https://pub.dev" + source: hosted + version: "6.1.0" lists: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 1dda115..1a50411 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -33,15 +33,18 @@ dependencies: shared_preferences: ^2.2.2 sqflite: ^2.4.1 path: ^1.8.3 + path_provider: ^2.1.0 uuid: ^4.0.0 package_info_plus: ^8.0.0 csv: ^6.0.0 + collection: ^1.18.0 dev_dependencies: flutter_test: sdk: flutter mocktail: ^1.0.4 flutter_launcher_icons: ^0.14.4 + flutter_lints: ^6.0.0 flutter_native_splash: ^2.4.6 flutter: diff --git a/test/models/tile_provider_test.dart b/test/models/tile_provider_test.dart index 3d825b0..c4c9f21 100644 --- a/test/models/tile_provider_test.dart +++ b/test/models/tile_provider_test.dart @@ -31,16 +31,16 @@ void main() { ); // Test 0-3 range - final url_0_3_a = tileType0_3.getTileUrl(1, 0, 0); - final url_0_3_b = tileType0_3.getTileUrl(1, 3, 0); - expect(url_0_3_a, contains('s0.example.com')); - expect(url_0_3_b, contains('s3.example.com')); + final url03A = tileType0_3.getTileUrl(1, 0, 0); + final url03B = tileType0_3.getTileUrl(1, 3, 0); + expect(url03A, contains('s0.example.com')); + expect(url03B, contains('s3.example.com')); // Test 1-4 range - final url_1_4_a = tileType1_4.getTileUrl(1, 0, 0); - final url_1_4_b = tileType1_4.getTileUrl(1, 3, 0); - expect(url_1_4_a, contains('s1.example.com')); - expect(url_1_4_b, contains('s4.example.com')); + final url14A = tileType1_4.getTileUrl(1, 0, 0); + final url14B = tileType1_4.getTileUrl(1, 3, 0); + expect(url14A, contains('s1.example.com')); + expect(url14B, contains('s4.example.com')); // Test consistency final url1 = tileType0_3.getTileUrl(1, 2, 3);