diff --git a/backend/docker-compose.yml b/backend/docker-compose.yml index c75d332..a46a75a 100644 --- a/backend/docker-compose.yml +++ b/backend/docker-compose.yml @@ -61,9 +61,9 @@ services: - maps-net ports: - "3001:3001" - environment: - DATABASE_URL: "postgres://maps:maps@postgres:5432/maps" - command: ["--listen-addresses", "0.0.0.0:3001"] + volumes: + - ./martin.yaml:/martin.yaml:ro + command: ["--config", "/martin.yaml"] depends_on: - postgres diff --git a/backend/martin.yaml b/backend/martin.yaml new file mode 100644 index 0000000..412a9c4 --- /dev/null +++ b/backend/martin.yaml @@ -0,0 +1,37 @@ +listen_addresses: '0.0.0.0:3001' + +postgres: + connection_string: 'postgres://maps:maps@postgres:5432/maps' + tables: + planet_osm_polygon: + schema: public + table: planet_osm_polygon + srid: 3857 + geometry_column: way + geometry_type: GEOMETRY + minzoom: 0 + maxzoom: 14 + planet_osm_line: + schema: public + table: planet_osm_line + srid: 3857 + geometry_column: way + geometry_type: GEOMETRY + minzoom: 0 + maxzoom: 14 + planet_osm_point: + schema: public + table: planet_osm_point + srid: 3857 + geometry_column: way + geometry_type: GEOMETRY + minzoom: 0 + maxzoom: 14 + planet_osm_roads: + schema: public + table: planet_osm_roads + srid: 3857 + geometry_column: way + geometry_type: GEOMETRY + minzoom: 0 + maxzoom: 14 diff --git a/mobile/android/app/src/main/AndroidManifest.xml b/mobile/android/app/src/main/AndroidManifest.xml index 566cab3..4a3fdff 100644 --- a/mobile/android/app/src/main/AndroidManifest.xml +++ b/mobile/android/app/src/main/AndroidManifest.xml @@ -1,8 +1,12 @@ + + + + android:icon="@mipmap/ic_launcher" + android:usesCleartextTraffic="true"> + + { - MapNotifier() - : super(MapState( - center: AppConstants.defaultCenter, - zoom: AppConstants.defaultZoom, - )); +class MapNotifier extends Notifier { + @override + MapState build() => MapState( + center: AppConstants.defaultCenter, + zoom: AppConstants.defaultZoom, + ); void updateCamera(LatLng center, double zoom) { state = state.copyWith(center: center, zoom: zoom); @@ -153,6 +153,4 @@ class MapNotifier extends StateNotifier { } } -final mapProvider = StateNotifierProvider((ref) { - return MapNotifier(); -}); +final mapProvider = NotifierProvider(MapNotifier.new); diff --git a/mobile/lib/features/offline/providers/offline_provider.dart b/mobile/lib/features/offline/providers/offline_provider.dart index 20c7e33..319d062 100644 --- a/mobile/lib/features/offline/providers/offline_provider.dart +++ b/mobile/lib/features/offline/providers/offline_provider.dart @@ -67,39 +67,30 @@ class OfflineState { } } -class OfflineNotifier extends StateNotifier { - final OfflineRepository _repository; +class OfflineNotifier extends Notifier { + late OfflineRepository _repository; - OfflineNotifier(this._repository) : super(const OfflineState()) { - _init(); - } - - Future _init() async { - await loadAvailableRegions(); - _repository.watchDownloadedRegions().listen((regions) { - if (mounted) { - state = state.copyWith(downloadedRegions: regions); - } + @override + OfflineState build() { + _repository = ref.watch(offlineRepositoryProvider); + final subscription = _repository.watchDownloadedRegions().listen((regions) { + state = state.copyWith(downloadedRegions: regions); }); + ref.onDispose(subscription.cancel); + Future.microtask(loadAvailableRegions); + return const OfflineState(); } Future loadAvailableRegions() async { state = state.copyWith(isLoading: true, clearError: true); try { final regions = await _repository.getAvailableRegions(); - if (mounted) { - state = state.copyWith( - availableRegions: regions, - isLoading: false, - ); - } + state = state.copyWith(availableRegions: regions, isLoading: false); } catch (e) { - if (mounted) { - state = state.copyWith( - isLoading: false, - error: 'Could not load available regions.', - ); - } + state = state.copyWith( + isLoading: false, + error: 'Could not load available regions.', + ); } } @@ -120,37 +111,31 @@ class OfflineNotifier extends StateNotifier { await _repository.downloadRegion( region: region, onProgress: (component, received, total) { - if (mounted) { - state = state.copyWith( - downloadProgress: { - ...state.downloadProgress, - region.id: DownloadProgress( - regionId: region.id, - component: component, - received: received, - total: total, - ), - }, - ); - } + state = state.copyWith( + downloadProgress: { + ...state.downloadProgress, + region.id: DownloadProgress( + regionId: region.id, + component: component, + received: received, + total: total, + ), + }, + ); }, ); - if (mounted) { - final newProgress = Map.from( - state.downloadProgress); - newProgress.remove(region.id); - state = state.copyWith(downloadProgress: newProgress); - } + final newProgress = + Map.from(state.downloadProgress); + newProgress.remove(region.id); + state = state.copyWith(downloadProgress: newProgress); } catch (e) { - if (mounted) { - final newProgress = Map.from( - state.downloadProgress); - newProgress.remove(region.id); - state = state.copyWith( - downloadProgress: newProgress, - error: 'Download failed for ${region.name}.', - ); - } + final newProgress = + Map.from(state.downloadProgress); + newProgress.remove(region.id); + state = state.copyWith( + downloadProgress: newProgress, + error: 'Download failed for ${region.name}.', + ); } } @@ -158,14 +143,10 @@ class OfflineNotifier extends StateNotifier { try { await _repository.deleteRegion(regionId); } catch (e) { - if (mounted) { - state = state.copyWith(error: 'Could not delete region.'); - } + state = state.copyWith(error: 'Could not delete region.'); } } } final offlineProvider = - StateNotifierProvider((ref) { - return OfflineNotifier(ref.watch(offlineRepositoryProvider)); -}); + NotifierProvider(OfflineNotifier.new); diff --git a/mobile/lib/features/places/providers/places_provider.dart b/mobile/lib/features/places/providers/places_provider.dart index c74bae6..74c2f83 100644 --- a/mobile/lib/features/places/providers/places_provider.dart +++ b/mobile/lib/features/places/providers/places_provider.dart @@ -31,18 +31,19 @@ class PlacesState { } } -class PlacesNotifier extends StateNotifier { - final PlacesRepository _repository; +class PlacesNotifier extends Notifier { + late PlacesRepository _repository; - PlacesNotifier(this._repository) : super(const PlacesState()) { - _loadFavorites(); + @override + PlacesState build() { + _repository = ref.watch(placesRepositoryProvider); + Future.microtask(_loadFavorites); + return const PlacesState(); } Future _loadFavorites() async { final favorites = await _repository.getAllFavorites(); - if (mounted) { - state = state.copyWith(favorites: favorites); - } + state = state.copyWith(favorites: favorites); } Future loadPoisInViewport({ @@ -61,16 +62,9 @@ class PlacesNotifier extends StateNotifier { maxLat: maxLat, category: category, ); - if (mounted) { - state = state.copyWith(pois: pois, isLoading: false); - } + state = state.copyWith(pois: pois, isLoading: false); } catch (e) { - if (mounted) { - state = state.copyWith( - isLoading: false, - error: 'Could not load places.', - ); - } + state = state.copyWith(isLoading: false, error: 'Could not load places.'); } } @@ -86,6 +80,4 @@ class PlacesNotifier extends StateNotifier { } final placesProvider = - StateNotifierProvider((ref) { - return PlacesNotifier(ref.watch(placesRepositoryProvider)); -}); + NotifierProvider(PlacesNotifier.new); diff --git a/mobile/lib/features/routing/presentation/screens/route_screen.dart b/mobile/lib/features/routing/presentation/screens/route_screen.dart index 536918c..964d826 100644 --- a/mobile/lib/features/routing/presentation/screens/route_screen.dart +++ b/mobile/lib/features/routing/presentation/screens/route_screen.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; -import 'package:flutter_map_cancellable_tile_provider/flutter_map_cancellable_tile_provider.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:latlong2/latlong.dart'; import '../../../map/providers/map_provider.dart'; +import '../../../search/data/search_repository.dart'; import '../../providers/routing_provider.dart'; import '../widgets/route_summary.dart'; import '../widgets/step_list.dart'; @@ -70,26 +70,32 @@ class _RouteScreenState extends ConsumerState { padding: const EdgeInsets.all(16), child: Column( children: [ - TextField( - readOnly: true, - decoration: InputDecoration( - labelText: 'From', - prefixIcon: const Icon(Icons.trip_origin), - hintText: routingState.originName, - ), - controller: - TextEditingController(text: routingState.originName), + _LocationField( + label: 'From', + icon: Icons.trip_origin, + value: routingState.originName, + onSelected: (result) { + ref.read(routingProvider.notifier).setOrigin( + result.latitude, + result.longitude, + result.name, + ); + ref.read(routingProvider.notifier).calculateRoute(); + }, ), const SizedBox(height: 8), - TextField( - readOnly: true, - decoration: InputDecoration( - labelText: 'To', - prefixIcon: const Icon(Icons.flag), - hintText: routingState.destName, - ), - controller: - TextEditingController(text: routingState.destName), + _LocationField( + label: 'To', + icon: Icons.flag, + value: routingState.destName, + onSelected: (result) { + ref.read(routingProvider.notifier).setDestination( + result.latitude, + result.longitude, + result.name, + ); + ref.read(routingProvider.notifier).calculateRoute(); + }, ), ], ), @@ -228,6 +234,30 @@ class _RouteScreenState extends ConsumerState { if (p.longitude > maxLon) maxLon = p.longitude; } + // Guard against degenerate bounds (single point or near-identical coords) + // which cause CameraFit.bounds to produce infinite zoom → NaN → crash. + final isDegenerate = + (maxLat - minLat).abs() < 1e-6 && (maxLon - minLon).abs() < 1e-6; + + final mapOptions = isDegenerate + ? MapOptions( + initialCenter: LatLng(minLat, minLon), + initialZoom: 15, + interactionOptions: + const InteractionOptions(flags: InteractiveFlag.none), + ) + : MapOptions( + initialCameraFit: CameraFit.bounds( + bounds: LatLngBounds( + LatLng(minLat, minLon), + LatLng(maxLat, maxLon), + ), + padding: const EdgeInsets.all(32), + ), + interactionOptions: + const InteractionOptions(flags: InteractiveFlag.none), + ); + return Container( height: 250, margin: const EdgeInsets.all(16), @@ -236,22 +266,11 @@ class _RouteScreenState extends ConsumerState { borderRadius: BorderRadius.circular(12), ), child: FlutterMap( - options: MapOptions( - initialCameraFit: CameraFit.bounds( - bounds: LatLngBounds( - LatLng(minLat, minLon), - LatLng(maxLat, maxLon), - ), - padding: const EdgeInsets.all(32), - ), - interactionOptions: const InteractionOptions( - flags: InteractiveFlag.none, - ), - ), + options: mapOptions, children: [ TileLayer( urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', - tileProvider: CancellableNetworkTileProvider(), + tileProvider: NetworkTileProvider(), userAgentPackageName: 'com.privacymaps.app', ), // Draw all routes, non-selected as faint, selected as bold. @@ -341,3 +360,134 @@ class _ProfileChip extends StatelessWidget { ); } } + +/// Tappable location field that opens an inline search dialog. +class _LocationField extends ConsumerStatefulWidget { + final String label; + final IconData icon; + final String? value; + final ValueChanged onSelected; + + const _LocationField({ + required this.label, + required this.icon, + required this.value, + required this.onSelected, + }); + + @override + ConsumerState<_LocationField> createState() => _LocationFieldState(); +} + +class _LocationFieldState extends ConsumerState<_LocationField> { + Future _openSearch() async { + final result = await showDialog( + context: context, + builder: (ctx) => _LocationSearchDialog(label: widget.label), + ); + if (result != null) widget.onSelected(result); + } + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: _openSearch, + borderRadius: BorderRadius.circular(8), + child: InputDecorator( + decoration: InputDecoration( + labelText: widget.label, + prefixIcon: Icon(widget.icon), + suffixIcon: const Icon(Icons.edit, size: 16), + border: const OutlineInputBorder(), + ), + child: Text(widget.value ?? ''), + ), + ); + } +} + +/// Dialog with a search field and live results. +class _LocationSearchDialog extends ConsumerStatefulWidget { + final String label; + const _LocationSearchDialog({required this.label}); + + @override + ConsumerState<_LocationSearchDialog> createState() => + _LocationSearchDialogState(); +} + +class _LocationSearchDialogState + extends ConsumerState<_LocationSearchDialog> { + final _controller = TextEditingController(); + List _results = []; + bool _loading = false; + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + Future _search(String query) async { + if (query.trim().length < 2) { + setState(() => _results = []); + return; + } + setState(() => _loading = true); + try { + final repo = ref.read(searchRepositoryProvider); + final results = await repo.search(query); + if (mounted) setState(() => _results = results); + } finally { + if (mounted) setState(() => _loading = false); + } + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(widget.label), + contentPadding: const EdgeInsets.fromLTRB(16, 12, 16, 0), + content: SizedBox( + width: 400, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: _controller, + autofocus: true, + decoration: const InputDecoration( + hintText: 'Search location…', + prefixIcon: Icon(Icons.search), + ), + onChanged: _search, + ), + if (_loading) const LinearProgressIndicator(), + ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 300), + child: ListView.builder( + shrinkWrap: true, + itemCount: _results.length, + itemBuilder: (ctx, i) { + final r = _results[i]; + return ListTile( + title: Text(r.name), + subtitle: Text(r.displayAddress, + maxLines: 1, overflow: TextOverflow.ellipsis), + onTap: () => Navigator.of(ctx).pop(r), + ); + }, + ), + ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text('Cancel'), + ), + ], + ); + } +} diff --git a/mobile/lib/features/routing/providers/routing_provider.dart b/mobile/lib/features/routing/providers/routing_provider.dart index 1fd8f55..2275a53 100644 --- a/mobile/lib/features/routing/providers/routing_provider.dart +++ b/mobile/lib/features/routing/providers/routing_provider.dart @@ -63,10 +63,14 @@ class RoutingState { : null; } -class RoutingNotifier extends StateNotifier { - final RoutingRepository _repository; +class RoutingNotifier extends Notifier { + late RoutingRepository _repository; - RoutingNotifier(this._repository) : super(const RoutingState()); + @override + RoutingState build() { + _repository = ref.watch(routingRepositoryProvider); + return const RoutingState(); + } void setOrigin(double lat, double lon, String name) { state = state.copyWith( @@ -113,25 +117,21 @@ class RoutingNotifier extends StateNotifier { destLat: state.destLat!, destLon: state.destLon!, ); - if (mounted) { - state = state.copyWith( - routes: routes, - selectedRouteIndex: 0, - isLoading: false, - ); - } + state = state.copyWith( + routes: routes, + selectedRouteIndex: 0, + isLoading: false, + ); } catch (e) { - if (mounted) { - state = state.copyWith( - isLoading: false, - error: 'Could not calculate route. Please try again.', - ); - } + state = state.copyWith( + isLoading: false, + error: 'Could not calculate route. Please try again.', + ); } } } final routingProvider = - StateNotifierProvider.autoDispose((ref) { - return RoutingNotifier(ref.watch(routingRepositoryProvider)); -}); + NotifierProvider.autoDispose( + RoutingNotifier.new, +); diff --git a/mobile/lib/features/search/providers/search_provider.dart b/mobile/lib/features/search/providers/search_provider.dart index 2a2d15d..9c292d2 100644 --- a/mobile/lib/features/search/providers/search_provider.dart +++ b/mobile/lib/features/search/providers/search_provider.dart @@ -38,19 +38,21 @@ class SearchState { } } -class SearchNotifier extends StateNotifier { - final SearchRepository _repository; +class SearchNotifier extends Notifier { + late SearchRepository _repository; Timer? _debounce; - SearchNotifier(this._repository) : super(const SearchState()) { - _loadHistory(); + @override + SearchState build() { + _repository = ref.watch(searchRepositoryProvider); + ref.onDispose(() => _debounce?.cancel()); + Future.microtask(_loadHistory); + return const SearchState(); } Future _loadHistory() async { final history = await _repository.getRecentSearches(); - if (mounted) { - state = state.copyWith(recentSearches: history); - } + state = state.copyWith(recentSearches: history); } void updateQuery(String query) { @@ -72,16 +74,14 @@ class SearchNotifier extends StateNotifier { Future _performSearch(String query) async { try { final results = await _repository.search(query); - if (mounted && state.query == query) { + if (state.query == query) { state = state.copyWith(results: results, isLoading: false); } } catch (e) { - if (mounted) { - state = state.copyWith( - isLoading: false, - error: 'Search failed. Please try again.', - ); - } + state = state.copyWith( + isLoading: false, + error: 'Search failed. Please try again.', + ); } } @@ -103,15 +103,9 @@ class SearchNotifier extends StateNotifier { await _repository.clearHistory(); await _loadHistory(); } - - @override - void dispose() { - _debounce?.cancel(); - super.dispose(); - } } final searchProvider = - StateNotifierProvider.autoDispose((ref) { - return SearchNotifier(ref.watch(searchRepositoryProvider)); -}); + NotifierProvider.autoDispose( + SearchNotifier.new, +); diff --git a/mobile/lib/features/settings/presentation/screens/settings_screen.dart b/mobile/lib/features/settings/presentation/screens/settings_screen.dart index bb2bbb7..0f462df 100644 --- a/mobile/lib/features/settings/presentation/screens/settings_screen.dart +++ b/mobile/lib/features/settings/presentation/screens/settings_screen.dart @@ -6,20 +6,21 @@ import '../../../../core/database/app_database.dart'; /// ThemeMode provider, watched by PrivacyMapsApp. final themeModeProvider = - StateNotifierProvider((ref) { - return ThemeModeNotifier(ref.watch(appDatabaseProvider)); -}); + NotifierProvider(ThemeModeNotifier.new); -class ThemeModeNotifier extends StateNotifier { - final AppDatabase _db; +class ThemeModeNotifier extends Notifier { + late AppDatabase _db; - ThemeModeNotifier(this._db) : super(ThemeMode.system) { - _load(); + @override + ThemeMode build() { + _db = ref.watch(appDatabaseProvider); + Future.microtask(_load); + return ThemeMode.system; } Future _load() async { final value = await _db.getSetting(AppConstants.settingThemeMode); - if (value != null && mounted) { + if (value != null) { state = _parse(value); } } diff --git a/mobile/macos/Flutter/GeneratedPluginRegistrant.swift b/mobile/macos/Flutter/GeneratedPluginRegistrant.swift index 7b00abe..49e6f22 100644 --- a/mobile/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/mobile/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,9 +6,11 @@ import FlutterMacOS import Foundation import geolocator_apple +import package_info_plus import sqlite3_flutter_libs func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) + FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) } diff --git a/mobile/macos/Podfile.lock b/mobile/macos/Podfile.lock index 3911e90..fd4791d 100644 --- a/mobile/macos/Podfile.lock +++ b/mobile/macos/Podfile.lock @@ -3,6 +3,8 @@ PODS: - geolocator_apple (1.2.0): - Flutter - FlutterMacOS + - package_info_plus (0.0.1): + - FlutterMacOS - sqlite3 (3.52.0): - sqlite3/common (= 3.52.0) - sqlite3/common (3.52.0) @@ -32,6 +34,7 @@ PODS: DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - geolocator_apple (from `Flutter/ephemeral/.symlinks/plugins/geolocator_apple/darwin`) + - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`) - sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`) SPEC REPOS: @@ -43,12 +46,15 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral geolocator_apple: :path: Flutter/ephemeral/.symlinks/plugins/geolocator_apple/darwin + package_info_plus: + :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos sqlite3_flutter_libs: :path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin SPEC CHECKSUMS: FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e + package_info_plus: f0052d280d17aa382b932f399edf32507174e870 sqlite3: a51c07cf16e023d6c48abd5e5791a61a47354921 sqlite3_flutter_libs: b3e120efe9a82017e5552a620f696589ed4f62ab diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index a2e93d7..9b67945 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -5,26 +5,26 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f + sha256: c209688d9f5a5f26b2fb47a188131a6fb9e876ae9e47af3737c0b4f58a93470d url: "https://pub.dev" source: hosted - version: "85.0.0" + version: "91.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: f4ad0fea5f102201015c9aae9d93bc02f75dd9491529a8c21f88d17a8523d44c + sha256: f51c8499b35f9b26820cfe914828a6a98a94efd5cc78b37bb7d03debae3a1d08 url: "https://pub.dev" source: hosted - version: "7.6.0" - analyzer_plugin: + version: "8.4.1" + analyzer_buffer: dependency: transitive description: - name: analyzer_plugin - sha256: a5ab7590c27b779f3d4de67f31c4109dbe13dd7339f86461a6f2a8ab2594d8ce + name: analyzer_buffer + sha256: aba2f75e63b3135fd1efaa8b6abefe1aa6e41b6bd9806221620fa48f98156033 url: "https://pub.dev" source: hosted - version: "0.13.4" + version: "0.1.11" args: dependency: transitive description: @@ -53,18 +53,18 @@ packages: dependency: transitive description: name: build - sha256: "51dc711996cbf609b90cbe5b335bbce83143875a9d58e4b5c6d3c4f684d3dda7" + sha256: aadd943f4f8cc946882c954c187e6115a84c98c81ad1d9c6cbf0895a8c85da9c url: "https://pub.dev" source: hosted - version: "2.5.4" + version: "4.0.5" build_config: dependency: transitive description: name: build_config - sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" + sha256: "4070d2a59f8eec34c97c86ceb44403834899075f66e8a9d59706f8e7834f6f71" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.3.0" build_daemon: dependency: transitive description: @@ -73,30 +73,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.1" - build_resolvers: - dependency: transitive - description: - name: build_resolvers - sha256: ee4257b3f20c0c90e72ed2b57ad637f694ccba48839a821e87db762548c22a62 - url: "https://pub.dev" - source: hosted - version: "2.5.4" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "382a4d649addbfb7ba71a3631df0ec6a45d5ab9b098638144faf27f02778eb53" + sha256: "521daf8d189deb79ba474e43a696b41c49fb3987818dbacf3308f1e03673a75e" url: "https://pub.dev" source: hosted - version: "2.5.4" - build_runner_core: - dependency: transitive - description: - name: build_runner_core - sha256: "85fbbb1036d576d966332a3f5ce83f2ce66a40bea1a94ad2d5fc29a19a0d3792" - url: "https://pub.dev" - source: hosted - version: "9.1.2" + version: "2.13.1" built_collection: dependency: transitive description: @@ -137,6 +121,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.4" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" cli_util: dependency: transitive description: @@ -185,6 +177,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" + url: "https://pub.dev" + source: hosted + version: "1.15.0" crypto: dependency: transitive description: @@ -193,22 +193,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.7" - custom_lint_core: - dependency: transitive - description: - name: custom_lint_core - sha256: "31110af3dde9d29fb10828ca33f1dce24d2798477b167675543ce3d208dee8be" - url: "https://pub.dev" - source: hosted - version: "0.7.5" - custom_lint_visitor: - dependency: transitive - description: - name: custom_lint_visitor - sha256: "4a86a0d8415a91fbb8298d6ef03e9034dc8e323a599ddc4120a0e36c433983a2" - url: "https://pub.dev" - source: hosted - version: "1.0.0+7.7.0" dart_earcut: dependency: transitive description: @@ -221,10 +205,18 @@ packages: dependency: transitive description: name: dart_style - sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb" + sha256: a9c30492da18ff84efe2422ba2d319a89942d93e58eb0b73d32abe822ef54b7b url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.3" + dbus: + dependency: transitive + description: + name: dbus + sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270 + url: "https://pub.dev" + source: hosted + version: "0.7.12" dio: dependency: "direct main" description: @@ -253,10 +245,10 @@ packages: dependency: "direct dev" description: name: drift_dev - sha256: "68c138e884527d2bd61df2ade276c3a144df84d1adeb0ab8f3196b5afe021bd4" + sha256: "4db0eeedc7e8bed117a9f22d867ab7a3a294300fed5c269aac90d0b3545967ca" url: "https://pub.dev" source: hosted - version: "2.28.0" + version: "2.28.3" executor_lib: dependency: transitive description: @@ -318,22 +310,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.2" - flutter_map_cancellable_tile_provider: - dependency: "direct main" - description: - name: flutter_map_cancellable_tile_provider - sha256: "03662220ce0cd784ad2f2a45c36fc379b8b315c74f5c12b5ff4a0515eab1acd1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" flutter_riverpod: dependency: "direct main" description: name: flutter_riverpod - sha256: "9532ee6db4a943a1ed8383072a2e3eeda041db5657cdf6d2acecf3c21ecbe7e1" + sha256: "38ec6c303e2c83ee84512f5fc2a82ae311531021938e63d7137eccc107bf3c02" url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "3.1.0" flutter_test: dependency: "direct dev" description: flutter @@ -348,18 +332,18 @@ packages: dependency: "direct dev" description: name: freezed - sha256: "59a584c24b3acdc5250bb856d0d3e9c0b798ed14a4af1ddb7dc1c7b41df91c9c" + sha256: "13065f10e135263a4f5a4391b79a8efc5fb8106f8dd555a9e49b750b45393d77" url: "https://pub.dev" source: hosted - version: "2.5.8" + version: "3.2.3" freezed_annotation: dependency: "direct main" description: name: freezed_annotation - sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 + sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "3.1.0" frontend_server_client: dependency: transitive description: @@ -368,22 +352,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + geoclue: + dependency: transitive + description: + name: geoclue + sha256: c2a998c77474fc57aa00c6baa2928e58f4b267649057a1c76738656e9dbd2a7f + url: "https://pub.dev" + source: hosted + version: "0.1.1" geolocator: dependency: "direct main" description: name: geolocator - sha256: "149876cc5207a0f5daf4fdd3bfcf0a0f27258b3fe95108fa084f527ad0568f1b" + sha256: "79939537046c9025be47ec645f35c8090ecadb6fe98eba146a0d25e8c1357516" url: "https://pub.dev" source: hosted - version: "12.0.0" + version: "14.0.2" geolocator_android: dependency: transitive description: name: geolocator_android - sha256: fcb1760a50d7500deca37c9a666785c047139b5f9ee15aa5469fae7dbbe3170d + sha256: "179c3cb66dfa674fc9ccbf2be872a02658724d1c067634e2c427cf6df7df901a" url: "https://pub.dev" source: hosted - version: "4.6.2" + version: "5.0.2" geolocator_apple: dependency: transitive description: @@ -392,6 +384,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.13" + geolocator_linux: + dependency: transitive + description: + name: geolocator_linux + sha256: d64112a205931926f4363bb6bd48f14cb38e7326833041d170615586cd143797 + url: "https://pub.dev" + source: hosted + version: "0.2.4" geolocator_platform_interface: dependency: transitive description: @@ -440,6 +440,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + gsettings: + dependency: transitive + description: + name: gsettings + sha256: "1b0ce661f5436d2db1e51f3c4295a49849f03d304003a7ba177d01e3a858249c" + url: "https://pub.dev" + source: hosted + version: "0.2.8" hooks: dependency: transitive description: @@ -488,14 +496,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" - js: - dependency: transitive - description: - name: js - sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" - url: "https://pub.dev" - source: hosted - version: "0.7.2" json_annotation: dependency: "direct main" description: @@ -508,10 +508,10 @@ packages: dependency: "direct dev" description: name: json_serializable - sha256: c50ef5fc083d5b5e12eef489503ba3bf5ccc899e487d691584699b4bdefeea8c + sha256: c5b2ee75210a0f263c6c7b9eeea80553dbae96ea1bf57f02484e806a3ffdffa3 url: "https://pub.dev" source: hosted - version: "6.9.5" + version: "6.11.2" latlong2: dependency: "direct main" description: @@ -616,6 +616,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + mockito: + dependency: transitive + description: + name: mockito + sha256: eff30d002f0c8bf073b6f929df4483b543133fcafce056870163587b03f1d422 + url: "https://pub.dev" + source: hosted + version: "5.6.4" native_toolchain_c: dependency: transitive description: @@ -624,6 +632,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.17.6" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" objective_c: dependency: transitive description: @@ -640,6 +656,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + package_info_plus: + dependency: transitive + description: + name: package_info_plus + sha256: "468c26b4254ab01979fa5e4a98cb343ea3631b9acee6f21028997419a80e1a20" + url: "https://pub.dev" + source: hosted + version: "9.0.1" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" + url: "https://pub.dev" + source: hosted + version: "3.2.1" path: dependency: "direct main" description: @@ -696,6 +728,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" + url: "https://pub.dev" + source: hosted + version: "7.0.2" platform: dependency: transitive description: @@ -772,34 +812,34 @@ packages: dependency: transitive description: name: riverpod - sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959" + sha256: "16ff608d21e8ea64364f2b7c049c94a02ab81668f78845862b6e88b71dd4935a" url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "3.1.0" riverpod_analyzer_utils: dependency: transitive description: name: riverpod_analyzer_utils - sha256: "837a6dc33f490706c7f4632c516bcd10804ee4d9ccc8046124ca56388715fdf3" + sha256: "947b05d04c52a546a2ac6b19ef2a54b08520ff6bdf9f23d67957a4c8df1c3bc0" url: "https://pub.dev" source: hosted - version: "0.5.9" + version: "1.0.0-dev.8" riverpod_annotation: dependency: "direct main" description: name: riverpod_annotation - sha256: e14b0bf45b71326654e2705d462f21b958f987087be850afd60578fcd502d1b8 + sha256: cc1474bc2df55ec3c1da1989d139dcef22cd5e2bd78da382e867a69a8eca2e46 url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "4.0.0" riverpod_generator: dependency: "direct dev" description: name: riverpod_generator - sha256: "120d3310f687f43e7011bb213b90a436f1bbc300f0e4b251a72c39bccb017a4f" + sha256: e43b1537229cc8f487f09b0c20d15dba840acbadcf5fc6dad7ad5e8ab75950dc url: "https://pub.dev" source: hosted - version: "2.6.4" + version: "4.0.0+1" shelf: dependency: transitive description: @@ -808,6 +848,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" shelf_web_socket: dependency: transitive description: @@ -825,18 +881,34 @@ packages: dependency: transitive description: name: source_gen - sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b" + sha256: "732792cfd197d2161a65bb029606a46e0a18ff30ef9e141a7a82172b05ea8ecd" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "4.2.2" source_helper: dependency: transitive description: name: source_helper - sha256: a447acb083d3a5ef17f983dd36201aeea33fedadb3228fa831f2f0c92f0f3aca + sha256: "6a3c6cc82073a8797f8c4dc4572146114a39652851c157db37e964d9c7038723" url: "https://pub.dev" source: hosted - version: "1.3.7" + version: "1.3.8" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" source_span: dependency: transitive description: @@ -917,6 +989,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.2" + test: + dependency: transitive + description: + name: test + sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7" + url: "https://pub.dev" + source: hosted + version: "1.30.0" test_api: dependency: transitive description: @@ -925,14 +1005,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.10" - timing: + test_core: dependency: transitive description: - name: timing - sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" + name: test_core + sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "0.6.16" typed_data: dependency: transitive description: @@ -1029,6 +1109,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + win32: + dependency: transitive + description: + name: win32 + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + url: "https://pub.dev" + source: hosted + version: "5.15.0" wkt_parser: dependency: transitive description: @@ -1045,6 +1141,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" + url: "https://pub.dev" + source: hosted + version: "6.6.1" yaml: dependency: transitive description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 3faa416..6538a68 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -31,17 +31,16 @@ dependencies: flutter: sdk: flutter flutter_map: ^7.0.0 - flutter_map_cancellable_tile_provider: ^3.0.0 vector_map_tiles: ^8.0.0 - flutter_riverpod: ^2.5.0 - riverpod_annotation: ^2.3.0 + flutter_riverpod: ^3.0.0 + riverpod_annotation: ^4.0.0 dio: ^5.4.0 - drift: ^2.16.0 + drift: ^2.28.0 sqlite3_flutter_libs: ^0.5.0 path_provider: ^2.1.0 - geolocator: ^12.0.0 + geolocator: ^14.0.0 go_router: ^14.0.0 - freezed_annotation: ^2.4.0 + freezed_annotation: ^3.0.0 json_annotation: ^4.9.0 latlong2: ^0.9.0 path: ^1.9.0 @@ -50,11 +49,11 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^5.0.0 - build_runner: ^2.4.0 - freezed: ^2.5.0 + build_runner: ^2.13.0 + freezed: ^3.0.0 json_serializable: ^6.7.0 - drift_dev: ^2.16.0 - riverpod_generator: ^2.4.0 + drift_dev: ^2.28.0 + riverpod_generator: ^4.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec