From fd0f469c9fc046ef6115d2d60f73f94fe2a012b3 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 18:53:35 +0200 Subject: [PATCH 01/13] feat: Migrate to Flutter Map and improve LocationsMap.dart --- ios/Podfile.lock | 6 + lib/widgets/LocationsMap.dart | 376 +++++++++++----------------------- pubspec.lock | 72 +++++++ pubspec.yaml | 1 + 4 files changed, 204 insertions(+), 251 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 3f3c7ee4..ec36c8a9 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -60,6 +60,8 @@ PODS: - Flutter - map_launcher (0.0.1): - Flutter + - package_info_plus (0.4.5): + - Flutter - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS @@ -94,6 +96,7 @@ DEPENDENCIES: - geocoding_ios (from `.symlinks/plugins/geocoding_ios/ios`) - geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`) - map_launcher (from `.symlinks/plugins/map_launcher/ios`) + - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - quick_actions_ios (from `.symlinks/plugins/quick_actions_ios/ios`) @@ -138,6 +141,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/geolocator_apple/ios" map_launcher: :path: ".symlinks/plugins/map_launcher/ios" + package_info_plus: + :path: ".symlinks/plugins/package_info_plus/ios" path_provider_foundation: :path: ".symlinks/plugins/path_provider_foundation/darwin" permission_handler_apple: @@ -168,6 +173,7 @@ SPEC CHECKSUMS: geocoding_ios: a389ea40f6f548de6e63006a2e31bf66ff80769a geolocator_apple: cc556e6844d508c95df1e87e3ea6fa4e58c50401 map_launcher: e325db1261d029ff33e08e03baccffe09593ffea + package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7 path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8 permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce Polyline: 2a1f29f87f8d9b7de868940f4f76deb8c678a5b1 diff --git a/lib/widgets/LocationsMap.dart b/lib/widgets/LocationsMap.dart index 36ed4bc0..bd13ad2f 100644 --- a/lib/widgets/LocationsMap.dart +++ b/lib/widgets/LocationsMap.dart @@ -3,11 +3,12 @@ import 'dart:collection'; import 'dart:io'; import 'package:apple_maps_flutter/apple_maps_flutter.dart' as AppleMaps; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_osm_plugin/flutter_osm_plugin.dart'; +import 'package:flutter_map/flutter_map.dart'; import 'package:geolocator/geolocator.dart'; import 'package:intl/intl.dart'; +// Provided by the flutter_map package +import 'package:latlong2/latlong.dart'; import 'package:locus/services/settings_service.dart'; import 'package:provider/provider.dart'; @@ -94,103 +95,35 @@ class LocationsMapController extends ChangeNotifier { } } -class LocationsMapAppleMaps extends StatefulWidget { +class LocationsMap extends StatefulWidget { final LocationsMapController controller; final double initialZoomLevel; final bool initWithUserPosition; - const LocationsMapAppleMaps({ + LocationsMap({ required this.controller, - required this.initialZoomLevel, - required this.initWithUserPosition, + this.initialZoomLevel = 16, + this.initWithUserPosition = false, Key? key, }) : super(key: key); @override - State createState() => _LocationsMapAppleMapsState(); + State createState() => _LocationsMapState(); } -class _LocationsMapAppleMapsState extends State { +class _LocationsMapState extends State { late final StreamSubscription _controllerSubscription; - AppleMaps.AppleMapController? _controller; - Position? userPosition; - - @override - void initState() { - super.initState(); - - widget.controller.addListener(rebuild); - _controllerSubscription = - widget.controller.eventListener.listen(eventEmitterListener); - - fetchInitialPosition(); - } - - @override - void didUpdateWidget(covariant LocationsMapAppleMaps oldWidget) { - super.didUpdateWidget(oldWidget); - } - - @override - void dispose() { - widget.controller.removeListener(rebuild); - _controllerSubscription.cancel(); - - super.dispose(); - } - - void eventEmitterListener(final Map data) async { - switch (data["type"]) { - case "goTo": - final location = data["location"] as LocationPointService; - final zoomLevel = await _controller!.getZoomLevel(); - - _controller!.animateCamera( - AppleMaps.CameraUpdate.newCameraPosition( - AppleMaps.CameraPosition( - target: AppleMaps.LatLng( - location.latitude, - location.longitude, - ), - zoom: zoomLevel ?? 16, - ), - ), - ); - break; - } - } - Future fetchInitialPosition() async { - final locationData = await Geolocator.getCurrentPosition( - // We want to get the position as fast as possible - desiredAccuracy: LocationAccuracy.lowest, - timeLimit: const Duration(seconds: 5), - ); + AppleMaps.AppleMapController? appleMapsController; + MapController? flutterMapController; - setState(() { - userPosition = locationData; - }); + static toAppleCoordinate(final LatLng latLng) => + AppleMaps.LatLng(latLng.latitude, latLng.longitude); - updateCameraLocation(); - } - - Future updateCameraLocation() async { - final zoomLevel = await _controller!.getZoomLevel(); - - await _controller!.animateCamera( - AppleMaps.CameraUpdate.newCameraPosition( - AppleMaps.CameraPosition( - target: getInitialPosition(), - zoom: zoomLevel ?? 16, - ), - ), - ); - } - - void rebuild() async { - await updateCameraLocation(); + bool get shouldUseAppleMaps { + final settings = context.watch(); - setState(() {}); + return settings.getMapProvider() == MapProvider.apple; } String get snippetText { @@ -212,137 +145,38 @@ class _LocationsMapAppleMapsState extends State { ].where((element) => element.isNotEmpty).join("\n"); } - AppleMaps.LatLng getInitialPosition() { - if (widget.initWithUserPosition || - (!widget.initWithUserPosition && widget.controller.locations.isEmpty)) { - if (userPosition != null) { - return AppleMaps.LatLng( - userPosition!.latitude, - userPosition!.longitude, - ); - } - } else if (widget.controller.locations.isNotEmpty) { - return AppleMaps.LatLng( - widget.controller.locations.last.latitude, - widget.controller.locations.last.longitude, - ); - } - - return const AppleMaps.LatLng(0, 0); - } - @override - Widget build(BuildContext context) { - return AppleMaps.AppleMap( - initialCameraPosition: AppleMaps.CameraPosition( - target: getInitialPosition(), - zoom: widget.initialZoomLevel, - ), - onMapCreated: (controller) { - _controller = controller; - }, - myLocationEnabled: true, - annotations: widget.controller.locations.isNotEmpty - ? { - AppleMaps.Annotation( - annotationId: AppleMaps.AnnotationId( - "annotation_${widget.controller.locations.last.latitude}:${widget.controller.locations.last.longitude}", - ), - position: AppleMaps.LatLng( - widget.controller.locations.last.latitude, - widget.controller.locations.last.longitude, - ), - infoWindow: AppleMaps.InfoWindow( - title: "Last location", - snippet: snippetText, - ), - ), - } - : {}, - circles: widget.controller.locations - .map( - (location) => AppleMaps.Circle( - circleId: AppleMaps.CircleId( - "circle_${location.latitude}:${location.longitude}", - ), - center: AppleMaps.LatLng( - location.latitude, - location.longitude, - ), - fillColor: Colors.blue.withOpacity(0.2), - strokeColor: Colors.blue, - strokeWidth: location.accuracy < 10 ? 1 : 3, - radius: location.accuracy, - ), - ) - .toSet(), - ); - } -} - -class LocationsMapOSM extends StatefulWidget { - final LocationsMapController controller; - final double initialZoomLevel; - final bool initWithUserPosition; - - const LocationsMapOSM({ - required this.controller, - required this.initialZoomLevel, - required this.initWithUserPosition, - Key? key, - }) : super(key: key); - - @override - State createState() => _LocationsMapOSMState(); -} + void initState() { + super.initState(); -class _LocationsMapOSMState extends State { - late final MapController _controller; - late final StreamSubscription _controllerSubscription; + _controllerSubscription = + widget.controller.eventListener.listen(eventEmitterListener); - GeoPoint? getInitPosition() { - if (widget.initWithUserPosition && widget.controller.locations.isNotEmpty) { - // Return null as we set `initMapWithUserPosition` - return null; + if (widget.initWithUserPosition) { + fetchUserPosition(); } + } + LatLng getInitialPosition() { if (widget.controller.locations.isNotEmpty) { - return GeoPoint( - latitude: widget.controller.locations.last.latitude, - longitude: widget.controller.locations.last.longitude, + return LatLng( + widget.controller.locations.last.latitude, + widget.controller.locations.last.longitude, ); } - return null; + return LatLng(0, 0); } @override - void initState() { - super.initState(); - - _controller = MapController( - initMapWithUserPosition: - widget.initWithUserPosition || widget.controller.locations.isEmpty, - initPosition: getInitPosition(), - ); - widget.controller.addListener(rebuild); - _controllerSubscription = - widget.controller.eventListener.listen(eventEmitterListener); - } - - @override - void dispose() { - _controller.dispose(); - widget.controller.removeListener(rebuild); + dispose() { _controllerSubscription.cancel(); - super.dispose(); - } - - void rebuild() async { - drawCircles(); + if (flutterMapController != null) { + flutterMapController!.dispose(); + } - setState(() {}); + super.dispose(); } void eventEmitterListener(final Map data) async { @@ -350,64 +184,41 @@ class _LocationsMapOSMState extends State { case "goTo": final location = data["location"] as LocationPointService; - _controller.goToLocation( - GeoPoint( - latitude: location.latitude, - longitude: location.longitude, + moveToPosition( + LatLng( + location.latitude, + location.longitude, ), ); - break; } } - void drawCircles() { - _controller.removeAllCircle(); - - for (final location in widget.controller.locations) { - _controller.drawCircle( - CircleOSM( - key: "circle_${location.latitude}:${location.longitude}", - centerPoint: GeoPoint( - latitude: location.latitude, - longitude: location.longitude, + void moveToPosition(final LatLng latLng) async { + if (shouldUseAppleMaps) { + appleMapsController!.moveCamera( + AppleMaps.CameraUpdate.newCameraPosition( + AppleMaps.CameraPosition( + target: toAppleCoordinate(latLng), ), - radius: location.accuracy, - color: Colors.blue, - strokeWidth: location.accuracy < 10 ? 1 : 3, ), ); + } else { + flutterMapController!.move(latLng, flutterMapController!.zoom); } } - @override - Widget build(BuildContext context) { - return OSMFlutter( - controller: _controller, - initZoom: widget.initialZoomLevel, - trackMyPosition: true, - androidHotReloadSupport: kDebugMode, - onMapIsReady: (controller) { - drawCircles(); - }, - onGeoPointClicked: (point) { - print(point); - }, + Future fetchUserPosition() async { + final locationData = await Geolocator.getCurrentPosition( + // We want to get the position as fast as possible + desiredAccuracy: LocationAccuracy.lowest, ); - } -} -class LocationsMap extends StatelessWidget { - final LocationsMapController controller; - final double initialZoomLevel; - final bool initWithUserPosition; - - const LocationsMap({ - required this.controller, - this.initialZoomLevel = 16, - this.initWithUserPosition = false, - Key? key, - }) : super(key: key); + moveToPosition(LatLng( + locationData!.latitude, + locationData!.longitude, + )); + } @override Widget build(BuildContext context) { @@ -415,16 +226,79 @@ class LocationsMap extends StatelessWidget { switch (settings.getMapProvider()) { case MapProvider.apple: - return LocationsMapAppleMaps( - controller: controller, - initialZoomLevel: initialZoomLevel, - initWithUserPosition: initWithUserPosition, + return AppleMaps.AppleMap( + initialCameraPosition: AppleMaps.CameraPosition( + target: toAppleCoordinate(getInitialPosition()), + zoom: widget.initialZoomLevel, + ), + onMapCreated: (controller) { + appleMapsController = controller; + }, + myLocationEnabled: true, + annotations: widget.controller.locations.isNotEmpty + ? { + AppleMaps.Annotation( + annotationId: AppleMaps.AnnotationId( + "annotation_${widget.controller.locations.last.latitude}:${widget.controller.locations.last.longitude}", + ), + position: AppleMaps.LatLng( + widget.controller.locations.last.latitude, + widget.controller.locations.last.longitude, + ), + infoWindow: AppleMaps.InfoWindow( + title: "Last location", + snippet: snippetText, + ), + ), + } + : {}, + circles: widget.controller.locations + .map( + (location) => AppleMaps.Circle( + circleId: AppleMaps.CircleId( + "circle_${location.latitude}:${location.longitude}", + ), + center: AppleMaps.LatLng( + location.latitude, + location.longitude, + ), + fillColor: Colors.blue.withOpacity(0.2), + strokeColor: Colors.blue, + strokeWidth: location.accuracy < 10 ? 1 : 3, + radius: location.accuracy, + ), + ) + .toSet(), ); case MapProvider.openStreetMap: - return LocationsMapOSM( - controller: controller, - initialZoomLevel: initialZoomLevel, - initWithUserPosition: initWithUserPosition, + return FlutterMap( + options: MapOptions( + center: getInitialPosition(), + zoom: widget.initialZoomLevel, + ), + children: [ + TileLayer( + urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', + userAgentPackageName: 'com.example.app', + ), + CircleLayer( + circles: widget.controller.locations + .map( + (location) => CircleMarker( + point: LatLng( + location.latitude, + location.longitude, + ), + color: Colors.blue.withOpacity(0.2), + borderColor: Colors.blue, + borderStrokeWidth: location.accuracy < 10 ? 1 : 3, + radius: location.accuracy, + useRadiusInMeter: true, + ), + ) + .toList(), + ), + ], ); } } diff --git a/pubspec.lock b/pubspec.lock index 75fff824..f5564e65 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -459,6 +459,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_map: + dependency: "direct main" + description: + name: flutter_map + sha256: "52c65a977daae42f9aae6748418dd1535eaf27186e9bac9bf431843082bc75a3" + url: "https://pub.dev" + source: hosted + version: "4.0.0" flutter_osm_interface: dependency: transitive description: @@ -765,6 +773,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.8.1" + latlong2: + dependency: transitive + description: + name: latlong2 + sha256: "08ef7282ba9f76e8495e49e2dc4d653015ac929dce5f92b375a415d30b407ea0" + url: "https://pub.dev" + source: hosted + version: "0.8.2" lints: dependency: transitive description: @@ -773,6 +789,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + lists: + dependency: transitive + description: + name: lists + sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27" + url: "https://pub.dev" + source: hosted + version: "1.0.1" logger: dependency: "direct main" description: @@ -829,6 +853,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + mgrs_dart: + dependency: transitive + description: + name: mgrs_dart + sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7 + url: "https://pub.dev" + source: hosted + version: "2.0.0" mime: dependency: transitive description: @@ -1029,6 +1061,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.7.3" + polylabel: + dependency: transitive + description: + name: polylabel + sha256: "41b9099afb2aa6c1730bdd8a0fab1400d287694ec7615dd8516935fa3144214b" + url: "https://pub.dev" + source: hosted + version: "1.0.1" pool: dependency: transitive description: @@ -1045,6 +1085,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.2.4" + proj4dart: + dependency: transitive + description: + name: proj4dart + sha256: c8a659ac9b6864aa47c171e78d41bbe6f5e1d7bd790a5814249e6b68bc44324e + url: "https://pub.dev" + source: hosted + version: "2.1.0" provider: dependency: "direct main" description: @@ -1274,6 +1322,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" + url: "https://pub.dev" + source: hosted + version: "2.0.1" typed_data: dependency: transitive description: @@ -1306,6 +1362,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.0" + unicode: + dependency: transitive + description: + name: unicode + sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1" + url: "https://pub.dev" + source: hosted + version: "0.3.1" upower: dependency: transitive description: @@ -1466,6 +1530,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + wkt_parser: + dependency: transitive + description: + name: wkt_parser + sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13" + url: "https://pub.dev" + source: hosted + version: "2.0.0" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8fda8461..783dd4cc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -86,6 +86,7 @@ dependencies: version: ^3.0.2 nearby_connections: ^3.3.0 english_words: ^4.0.0 + flutter_map: ^4.0.0 # Uncomment this for publishing FLOSS variant # Taken from https://github.com/Zverik/every_door/blob/aaf8d2fdeac483041bcac2c7c79ef760b99dff2b/pubspec.yaml#L55 From d76ea97d97a37205d1219833719fc2cffd82cf67 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 20:04:08 +0200 Subject: [PATCH 02/13] feat: Add PopupMarker --- lib/widgets/LocationsMap.dart | 34 ++++++++++++++++++++++++++++++---- pubspec.lock | 18 +++++++++++++++++- pubspec.yaml | 1 + 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/lib/widgets/LocationsMap.dart b/lib/widgets/LocationsMap.dart index bd13ad2f..168c02f6 100644 --- a/lib/widgets/LocationsMap.dart +++ b/lib/widgets/LocationsMap.dart @@ -5,11 +5,13 @@ import 'dart:io'; import 'package:apple_maps_flutter/apple_maps_flutter.dart' as AppleMaps; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map_marker_popup/flutter_map_marker_popup.dart'; import 'package:geolocator/geolocator.dart'; import 'package:intl/intl.dart'; // Provided by the flutter_map package import 'package:latlong2/latlong.dart'; import 'package:locus/services/settings_service.dart'; +import 'package:locus/widgets/Paper.dart'; import 'package:provider/provider.dart'; import '../services/location_point_service.dart'; @@ -215,8 +217,8 @@ class _LocationsMapState extends State { ); moveToPosition(LatLng( - locationData!.latitude, - locationData!.longitude, + locationData.latitude, + locationData.longitude, )); } @@ -278,8 +280,9 @@ class _LocationsMapState extends State { ), children: [ TileLayer( - urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', - userAgentPackageName: 'com.example.app', + urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + subdomains: const ['a', 'b', 'c'], + userAgentPackageName: "app.myzel394.locus", ), CircleLayer( circles: widget.controller.locations @@ -298,6 +301,29 @@ class _LocationsMapState extends State { ) .toList(), ), + if (widget.controller.locations.isNotEmpty) + PopupMarkerLayer( + options: PopupMarkerLayerOptions( + markers: [ + Marker( + point: LatLng( + widget.controller.locations.last.latitude, + widget.controller.locations.last.longitude, + ), + builder: (context) => Icon( + Icons.location_on, + color: Colors.red, + ), + ), + ], + popupDisplayOptions: PopupDisplayOptions( + builder: (context, marker) => Paper( + width: null, + child: Text(snippetText), + ), + ), + ), + ), ], ); } diff --git a/pubspec.lock b/pubspec.lock index f5564e65..6d071c44 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,6 +25,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.13.0" + animated_stack_widget: + dependency: transitive + description: + name: animated_stack_widget + sha256: ce4788dd158768c9d4388354b6fb72600b78e041a37afc4c279c63ecafcb9408 + url: "https://pub.dev" + source: hosted + version: "0.0.4" animations: dependency: "direct main" description: @@ -467,6 +475,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + flutter_map_marker_popup: + dependency: "direct main" + description: + name: flutter_map_marker_popup + sha256: "71457476f91d6174c132577d37c11a78ad9502be65e699b22aa7a745b07414a5" + url: "https://pub.dev" + source: hosted + version: "5.1.0" flutter_osm_interface: dependency: transitive description: @@ -1564,4 +1580,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.7.0" + flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index 783dd4cc..6dbe1580 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -87,6 +87,7 @@ dependencies: nearby_connections: ^3.3.0 english_words: ^4.0.0 flutter_map: ^4.0.0 + flutter_map_marker_popup: ^5.1.0 # Uncomment this for publishing FLOSS variant # Taken from https://github.com/Zverik/every_door/blob/aaf8d2fdeac483041bcac2c7c79ef760b99dff2b/pubspec.yaml#L55 From 4b4636178a72c48a68a7e9f5f9cc5b4b91b712b3 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 20:55:36 +0200 Subject: [PATCH 03/13] fix: Clone elements to update them --- lib/services/task_service.dart | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/services/task_service.dart b/lib/services/task_service.dart index 01652042..378d8d4a 100644 --- a/lib/services/task_service.dart +++ b/lib/services/task_service.dart @@ -265,8 +265,8 @@ class Task extends ChangeNotifier { Future update({ String? name, - List? relays, - List? timers, + Iterable? relays, + Iterable? timers, bool? deleteAfterRun, }) async { if (name != null) { @@ -274,13 +274,16 @@ class Task extends ChangeNotifier { } if (relays != null) { + // We need to copy the relays as they somehow also get cleared when `this.relays.clear` is called. + final newRelays = [...relays]; this.relays.clear(); - this.relays.addAll(relays); + this.relays.addAll(newRelays); } if (timers != null) { + final newTimers = [...timers]; this.timers.clear(); - this.timers.addAll(timers); + this.timers.addAll(newTimers); } if (deleteAfterRun != null) { From ee25a74aea7955c316034e3821568bd258cfb1ed Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 20:57:20 +0200 Subject: [PATCH 04/13] fix: Await task update --- .../task_detail_screen_widgets/Details.dart | 110 ++++++------------ 1 file changed, 37 insertions(+), 73 deletions(-) diff --git a/lib/screens/task_detail_screen_widgets/Details.dart b/lib/screens/task_detail_screen_widgets/Details.dart index 423ddf42..dac63a16 100644 --- a/lib/screens/task_detail_screen_widgets/Details.dart +++ b/lib/screens/task_detail_screen_widgets/Details.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:flutter_platform_widgets/flutter_platform_widgets.dart' - hide PlatformListTile; +import 'package:flutter_platform_widgets/flutter_platform_widgets.dart' hide PlatformListTile; import 'package:locus/constants/spacing.dart'; import 'package:locus/models/log.dart'; import 'package:locus/screens/LocationPointsDetailsScreen.dart'; @@ -102,8 +101,7 @@ class _DetailsState extends State
{ style: getBodyTextTextStyle(context), ), TextSpan( - text: - " (${widget.locations.last.latitude}, ${widget.locations.last.longitude})", + text: " (${widget.locations.last.latitude}, ${widget.locations.last.longitude})", style: getCaptionTextStyle(context), ), ], @@ -121,12 +119,9 @@ class _DetailsState extends State
{ const SizedBox(width: SMALL_SPACE), isLoading ? SizedBox.square( - dimension: - getIconSizeForBodyText(context), - child: - PlatformCircularProgressIndicator( - material: (_, __) => - MaterialProgressIndicatorData( + dimension: getIconSizeForBodyText(context), + child: PlatformCircularProgressIndicator( + material: (_, __) => MaterialProgressIndicatorData( strokeWidth: 2, ), ), @@ -137,8 +132,7 @@ class _DetailsState extends State
{ ), const SizedBox(height: MEDIUM_SPACE), Tooltip( - message: - l10n.taskDetails_mostRecentLocationExplanation, + message: l10n.taskDetails_mostRecentLocationExplanation, textAlign: TextAlign.center, child: Row( mainAxisAlignment: MainAxisAlignment.start, @@ -169,8 +163,7 @@ class _DetailsState extends State
{ opaque: false, fullscreenDialog: true, barrierDismissible: true, - pageBuilder: (context, _, __) => - LocationPointsDetailsScreen( + pageBuilder: (context, _, __) => LocationPointsDetailsScreen( locations: widget.locations, isPreview: false, ), @@ -226,9 +219,9 @@ class _DetailsState extends State
{ ), ); - widget.task - .update(relays: _relaysController.relays); + await widget.task.update(relays: _relaysController.relays); taskService.update(widget.task); + await taskService.save(); }, ), ], @@ -248,8 +241,7 @@ class _DetailsState extends State
{ })(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { - final isRunning = snapshot.hasData && - snapshot.data?["startedAt"] != null; + final isRunning = snapshot.hasData && snapshot.data?["startedAt"] != null; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -276,10 +268,8 @@ class _DetailsState extends State
{ icon: const Icon(Icons.stop_rounded), ), onPressed: () async { - final logService = - context.read(); - await widget.task - .stopExecutionImmediately(); + final logService = context.read(); + await widget.task.stopExecutionImmediately(); taskService.update(widget.task); @@ -300,10 +290,8 @@ class _DetailsState extends State
{ icon: const Icon(Icons.play_arrow_rounded), ), onPressed: () async { - final logService = - context.read(); - await widget.task - .startExecutionImmediately(); + final logService = context.read(); + await widget.task.startExecutionImmediately(); taskService.update(widget.task); @@ -320,8 +308,7 @@ class _DetailsState extends State
{ const SizedBox(width: MEDIUM_SPACE), FutureBuilder>( future: (() async { - final status = - await widget.task.getScheduleStatus(); + final status = await widget.task.getScheduleStatus(); if (status == null) { return Map.from({}); @@ -330,16 +317,11 @@ class _DetailsState extends State
{ return status; })(), builder: (context, scheduleSnapshot) { - if (scheduleSnapshot.connectionState == - ConnectionState.done) { - if (scheduleSnapshot.hasData && - (scheduleSnapshot.data?.isNotEmpty ?? - false)) { + if (scheduleSnapshot.connectionState == ConnectionState.done) { + if (scheduleSnapshot.hasData && (scheduleSnapshot.data?.isNotEmpty ?? false)) { return PlatformTextButton( - child: - Text(l10n.taskAction_stopSchedule), - material: (_, __) => - MaterialTextButtonData( + child: Text(l10n.taskAction_stopSchedule), + material: (_, __) => MaterialTextButtonData( icon: const Icon(Icons.stop_outlined), ), onPressed: () async { @@ -353,16 +335,12 @@ class _DetailsState extends State
{ await showPlatformDialog( context: context, - builder: (context) => - PlatformAlertDialog( - title: Text(l10n - .taskAction_stopSchedule_title), - content: Text(l10n - .taskAction_stopSchedule_description), + builder: (context) => PlatformAlertDialog( + title: Text(l10n.taskAction_stopSchedule_title), + content: Text(l10n.taskAction_stopSchedule_description), actions: [ PlatformDialogAction( - child: Text( - l10n.closeNeutralAction), + child: Text(l10n.closeNeutralAction), onPressed: () { Navigator.of(context).pop(); }, @@ -374,16 +352,12 @@ class _DetailsState extends State
{ ); } else { return PlatformTextButton( - child: - Text(l10n.taskAction_startSchedule), - material: (_, __) => - MaterialTextButtonData( - icon: const Icon( - Icons.schedule_rounded), + child: Text(l10n.taskAction_startSchedule), + material: (_, __) => MaterialTextButtonData( + icon: const Icon(Icons.schedule_rounded), ), onPressed: () async { - final startDate = - await widget.task.startSchedule(); + final startDate = await widget.task.startSchedule(); taskService.update(widget.task); @@ -394,19 +368,14 @@ class _DetailsState extends State
{ if (startDate == null) { await showPlatformDialog( context: context, - builder: (context) => - PlatformAlertDialog( - title: Text(l10n - .taskAction_startSchedule_notScheduled_title), - content: Text(l10n - .taskAction_startSchedule_notScheduled_description), + builder: (context) => PlatformAlertDialog( + title: Text(l10n.taskAction_startSchedule_notScheduled_title), + content: Text(l10n.taskAction_startSchedule_notScheduled_description), actions: [ PlatformDialogAction( - child: Text(l10n - .closeNeutralAction), + child: Text(l10n.closeNeutralAction), onPressed: () { - Navigator.of(context) - .pop(); + Navigator.of(context).pop(); }, ), ], @@ -415,10 +384,8 @@ class _DetailsState extends State
{ } else { await showPlatformDialog( context: context, - builder: (context) => - PlatformAlertDialog( - title: Text(l10n - .taskAction_startSchedule_title), + builder: (context) => PlatformAlertDialog( + title: Text(l10n.taskAction_startSchedule_title), content: Text( l10n.taskAction_startSchedule_description( startDate, @@ -426,11 +393,9 @@ class _DetailsState extends State
{ ), actions: [ PlatformDialogAction( - child: Text(l10n - .closeNeutralAction), + child: Text(l10n.closeNeutralAction), onPressed: () { - Navigator.of(context) - .pop(); + Navigator.of(context).pop(); }, ), ], @@ -443,8 +408,7 @@ class _DetailsState extends State
{ } return PlatformCircularProgressIndicator( - material: (_, __) => - MaterialProgressIndicatorData( + material: (_, __) => MaterialProgressIndicatorData( strokeWidth: 2, ), ); From 302230c7f348a96956d922a0f5360494c7814544 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 20:57:29 +0200 Subject: [PATCH 05/13] fix: Make icon in Map constant --- lib/widgets/LocationsMap.dart | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/lib/widgets/LocationsMap.dart b/lib/widgets/LocationsMap.dart index 168c02f6..68f8a2c6 100644 --- a/lib/widgets/LocationsMap.dart +++ b/lib/widgets/LocationsMap.dart @@ -8,6 +8,7 @@ import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map_marker_popup/flutter_map_marker_popup.dart'; import 'package:geolocator/geolocator.dart'; import 'package:intl/intl.dart'; + // Provided by the flutter_map package import 'package:latlong2/latlong.dart'; import 'package:locus/services/settings_service.dart'; @@ -24,8 +25,7 @@ class LocationsMapController extends ChangeNotifier { // To inform our wrappers to update the map, we use a stream. // This emits event to which our wrappers listen to. - final StreamController> _eventEmitter = - StreamController.broadcast(); + final StreamController> _eventEmitter = StreamController.broadcast(); LocationsMapController({ List? locations, @@ -42,8 +42,7 @@ class LocationsMapController extends ChangeNotifier { bool get useAppleMaps => Platform.isIOS; - UnmodifiableListView get locations => - UnmodifiableListView(_locations); + UnmodifiableListView get locations => UnmodifiableListView(_locations); @override void dispose() { @@ -73,8 +72,7 @@ class LocationsMapController extends ChangeNotifier { } // Groups the locations by hour and returns a map of the hour and the number of locations in that hour. - Map> getLocationsPerHour() => - locations.fold( + Map> getLocationsPerHour() => locations.fold( {}, (final Map> value, element) { final date = normalizeDateTime(element.createdAt); @@ -119,8 +117,7 @@ class _LocationsMapState extends State { AppleMaps.AppleMapController? appleMapsController; MapController? flutterMapController; - static toAppleCoordinate(final LatLng latLng) => - AppleMaps.LatLng(latLng.latitude, latLng.longitude); + static toAppleCoordinate(final LatLng latLng) => AppleMaps.LatLng(latLng.latitude, latLng.longitude); bool get shouldUseAppleMaps { final settings = context.watch(); @@ -131,14 +128,9 @@ class _LocationsMapState extends State { String get snippetText { final location = widget.controller.locations.last; - final batteryInfo = location.batteryLevel == null - ? "" - : "Battery at ${(location.batteryLevel! * 100).ceil()}%"; - final dateInfo = - "Date: ${DateFormat.yMd().add_jm().format(location.createdAt)}"; - final speedInfo = location.speed == null - ? "" - : "Moving at ${(location.speed!.abs() * 3.6).ceil()} km/h"; + final batteryInfo = location.batteryLevel == null ? "" : "Battery at ${(location.batteryLevel! * 100).ceil()}%"; + final dateInfo = "Date: ${DateFormat.yMd().add_jm().format(location.createdAt)}"; + final speedInfo = location.speed == null ? "" : "Moving at ${(location.speed!.abs() * 3.6).ceil()} km/h"; return [ batteryInfo, @@ -151,8 +143,7 @@ class _LocationsMapState extends State { void initState() { super.initState(); - _controllerSubscription = - widget.controller.eventListener.listen(eventEmitterListener); + _controllerSubscription = widget.controller.eventListener.listen(eventEmitterListener); if (widget.initWithUserPosition) { fetchUserPosition(); @@ -310,7 +301,7 @@ class _LocationsMapState extends State { widget.controller.locations.last.latitude, widget.controller.locations.last.longitude, ), - builder: (context) => Icon( + builder: (context) => const Icon( Icons.location_on, color: Colors.red, ), From 8dfc5a8acdbc3be65b4def7cc95a26d11b0a5b71 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 21:09:01 +0200 Subject: [PATCH 06/13] fix: Improve location details --- lib/screens/LocationPointsDetailsScreen.dart | 27 ++++---- .../LocationDetails.dart | 61 ++++++++++++------- 2 files changed, 52 insertions(+), 36 deletions(-) diff --git a/lib/screens/LocationPointsDetailsScreen.dart b/lib/screens/LocationPointsDetailsScreen.dart index af1eaa10..0c204235 100644 --- a/lib/screens/LocationPointsDetailsScreen.dart +++ b/lib/screens/LocationPointsDetailsScreen.dart @@ -23,18 +23,19 @@ class LocationPointsDetailsScreen extends StatelessWidget { final locationElements = locations.isEmpty ? Text( - l10n.taskDetails_noLocations, - style: getBodyTextTextStyle(context), - ) + l10n.taskDetails_noLocations, + style: getBodyTextTextStyle(context), + ) : ListView.builder( - shrinkWrap: isPreview, - physics: isPreview ? const NeverScrollableScrollPhysics() : null, - itemCount: locations.length, - itemBuilder: (_, index) => LocationDetails( - location: locations[index], - isPreview: isPreview, - ), - ); + shrinkWrap: isPreview, + physics: isPreview ? const NeverScrollableScrollPhysics() : null, + itemCount: locations.length, + itemBuilder: (_, index) => + LocationDetails( + location: locations[locations.length - index - 1], + isPreview: isPreview, + ), + ); final content = Hero( tag: "container", child: Material( @@ -43,8 +44,8 @@ class LocationPointsDetailsScreen extends StatelessWidget { roundness: isPreview ? null : 0, constraints: isPreview ? const BoxConstraints( - maxHeight: 300, - ) + maxHeight: 300, + ) : null, child: locationElements, ), diff --git a/lib/screens/task_detail_screen_widgets/LocationDetails.dart b/lib/screens/task_detail_screen_widgets/LocationDetails.dart index 304b4163..3403a32e 100644 --- a/lib/screens/task_detail_screen_widgets/LocationDetails.dart +++ b/lib/screens/task_detail_screen_widgets/LocationDetails.dart @@ -2,12 +2,13 @@ import 'package:battery_plus/battery_plus.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:flutter_platform_widgets/flutter_platform_widgets.dart' - hide PlatformListTile; +import 'package:flutter_platform_widgets/flutter_platform_widgets.dart' hide PlatformListTile; import 'package:locus/constants/spacing.dart'; import 'package:locus/services/location_point_service.dart'; import 'package:locus/utils/theme.dart'; +import 'package:provider/provider.dart'; +import '../../services/settings_service.dart'; import '../../widgets/PlatformListTile.dart'; class LocationDetails extends StatefulWidget { @@ -25,6 +26,7 @@ class LocationDetails extends StatefulWidget { } class _LocationDetailsState extends State { + String address = ""; bool isOpened = false; String get formattedString => @@ -34,13 +36,10 @@ class _LocationDetailsState extends State { final l10n = AppLocalizations.of(context); return { - BatteryState.charging: - l10n.taskDetails_locationDetails_batteryState_charging, - BatteryState.discharging: - l10n.taskDetails_locationDetails_batteryState_discharging, + BatteryState.charging: l10n.taskDetails_locationDetails_batteryState_charging, + BatteryState.discharging: l10n.taskDetails_locationDetails_batteryState_discharging, BatteryState.full: l10n.taskDetails_locationDetails_batteryState_full, - BatteryState.unknown: - l10n.taskDetails_locationDetails_batteryState_unknown, + BatteryState.unknown: l10n.taskDetails_locationDetails_batteryState_unknown, null: l10n.taskDetails_locationDetails_batteryState_unknown, }; } @@ -83,6 +82,20 @@ class _LocationDetailsState extends State { } } + void fetchAddress() async { + if (this.address.isNotEmpty) { + return; + } + + final settings = context.read(); + + final address = await settings.getAddress(widget.location.latitude, widget.location.longitude); + + setState(() { + this.address = address; + }); + } + @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context); @@ -94,6 +107,8 @@ class _LocationDetailsState extends State { onPressed: widget.isPreview ? null : () { + fetchAddress(); + setState(() { isOpened = !isOpened; }); @@ -101,7 +116,9 @@ class _LocationDetailsState extends State { child: Align( alignment: Alignment.centerLeft, child: Text( - formattedString, + l10n.taskDetails_locationDetails_createdAt_value( + widget.location.createdAt, + ), textAlign: TextAlign.start, style: getBodyTextTextStyle(context), ), @@ -123,14 +140,16 @@ class _LocationDetailsState extends State { children: [ PlatformListTile( title: Text( - l10n.taskDetails_locationDetails_createdAt_value( - widget.location.createdAt, - ), + formattedString, ), - subtitle: Text( - l10n.taskDetails_locationDetails_createdAt_label, + leading: const Icon(Icons.my_location), + trailing: const SizedBox.shrink(), + ), + PlatformListTile( + title: Text( + address, ), - leading: Icon(context.platformIcons.time), + leading: Icon(context.platformIcons.location), trailing: const SizedBox.shrink(), ), PlatformListTile( @@ -139,8 +158,7 @@ class _LocationDetailsState extends State { widget.location.accuracy.round(), ), ), - subtitle: - Text(l10n.taskDetails_locationDetails_accuracy_label), + subtitle: Text(l10n.taskDetails_locationDetails_accuracy_label), leading: const Icon(Icons.location_on), trailing: const SizedBox.shrink(), ), @@ -152,8 +170,7 @@ class _LocationDetailsState extends State { (widget.location.batteryLevel! * 100).floor(), ), ), - subtitle: - Text(l10n.taskDetails_locationDetails_battery_label), + subtitle: Text(l10n.taskDetails_locationDetails_battery_label), leading: Icon( getIconForBatteryLevel( widget.location.batteryLevel, @@ -184,8 +201,7 @@ class _LocationDetailsState extends State { ), leading: PlatformWidget( material: (_, __) => const Icon(Icons.speed), - cupertino: (_, __) => - const Icon(CupertinoIcons.speedometer), + cupertino: (_, __) => const Icon(CupertinoIcons.speedometer), ), trailing: const SizedBox.shrink(), ), @@ -197,8 +213,7 @@ class _LocationDetailsState extends State { widget.location.altitude!.toInt().abs(), ), ), - subtitle: - Text(l10n.taskDetails_locationDetails_altitude_label), + subtitle: Text(l10n.taskDetails_locationDetails_altitude_label), leading: PlatformWidget( material: (_, __) => const Icon(Icons.height_rounded), cupertino: (_, __) => const Icon(CupertinoIcons.alt), From 0675bb8af19904de29076458761a7fddcabb7657 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 21:10:04 +0200 Subject: [PATCH 07/13] fix: Use l10n for location details title --- lib/l10n/app_en.arb | 3 +- lib/screens/LocationPointsDetailsScreen.dart | 31 +++++++++----------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ba65c897..ab6f0740 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -490,5 +490,6 @@ "logs_system_initiator_description": "This log was created by the system", "logs_task_creationContext_description": "{context, select, inApp{Task created inside the App} quickAction{Task created via Quick Action} other{Unknown error occurred}}", "logs_title": "Locus automatically creates logs", - "logs_description": "Logs are kept for 7 days and are automatically deleted afterwards." + "logs_description": "Logs are kept for 7 days and are automatically deleted afterwards.", + "locationPointsScreen_title": "Location Points" } \ No newline at end of file diff --git a/lib/screens/LocationPointsDetailsScreen.dart b/lib/screens/LocationPointsDetailsScreen.dart index 0c204235..da81cb0a 100644 --- a/lib/screens/LocationPointsDetailsScreen.dart +++ b/lib/screens/LocationPointsDetailsScreen.dart @@ -23,19 +23,18 @@ class LocationPointsDetailsScreen extends StatelessWidget { final locationElements = locations.isEmpty ? Text( - l10n.taskDetails_noLocations, - style: getBodyTextTextStyle(context), - ) + l10n.taskDetails_noLocations, + style: getBodyTextTextStyle(context), + ) : ListView.builder( - shrinkWrap: isPreview, - physics: isPreview ? const NeverScrollableScrollPhysics() : null, - itemCount: locations.length, - itemBuilder: (_, index) => - LocationDetails( - location: locations[locations.length - index - 1], - isPreview: isPreview, - ), - ); + shrinkWrap: isPreview, + physics: isPreview ? const NeverScrollableScrollPhysics() : null, + itemCount: locations.length, + itemBuilder: (_, index) => LocationDetails( + location: locations[locations.length - index - 1], + isPreview: isPreview, + ), + ); final content = Hero( tag: "container", child: Material( @@ -44,8 +43,8 @@ class LocationPointsDetailsScreen extends StatelessWidget { roundness: isPreview ? null : 0, constraints: isPreview ? const BoxConstraints( - maxHeight: 300, - ) + maxHeight: 300, + ) : null, child: locationElements, ), @@ -58,9 +57,7 @@ class LocationPointsDetailsScreen extends StatelessWidget { return PlatformScaffold( appBar: PlatformAppBar( - title: Text( - "Location Points", - ), + title: Text(l10n.locationPointsScreen_title), ), body: SafeArea( child: content, From 0e5407eefa180592a97714d45ceff670b1f5fa33 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 21:13:07 +0200 Subject: [PATCH 08/13] fix: Add animation to location points screen --- lib/screens/LocationPointsDetailsScreen.dart | 4 ++++ lib/screens/task_detail_screen_widgets/Details.dart | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/screens/LocationPointsDetailsScreen.dart b/lib/screens/LocationPointsDetailsScreen.dart index da81cb0a..a448d383 100644 --- a/lib/screens/LocationPointsDetailsScreen.dart +++ b/lib/screens/LocationPointsDetailsScreen.dart @@ -58,7 +58,11 @@ class LocationPointsDetailsScreen extends StatelessWidget { return PlatformScaffold( appBar: PlatformAppBar( title: Text(l10n.locationPointsScreen_title), + material: (_, __) => MaterialAppBarData( + centerTitle: true, + ), ), + backgroundColor: Colors.transparent, body: SafeArea( child: content, ), diff --git a/lib/screens/task_detail_screen_widgets/Details.dart b/lib/screens/task_detail_screen_widgets/Details.dart index dac63a16..a06981e6 100644 --- a/lib/screens/task_detail_screen_widgets/Details.dart +++ b/lib/screens/task_detail_screen_widgets/Details.dart @@ -160,8 +160,9 @@ class _DetailsState extends State
{ : () { Navigator.of(context).push( PageRouteBuilder( - opaque: false, + opaque: true, fullscreenDialog: true, + barrierColor: Colors.black.withOpacity(0.7), barrierDismissible: true, pageBuilder: (context, _, __) => LocationPointsDetailsScreen( locations: widget.locations, From 6447cb58320a0593bde8b6e15c133c33fb4b2d43 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 21:25:23 +0200 Subject: [PATCH 09/13] fix: Set max zoom --- lib/widgets/LocationsMap.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/widgets/LocationsMap.dart b/lib/widgets/LocationsMap.dart index 68f8a2c6..114d7efb 100644 --- a/lib/widgets/LocationsMap.dart +++ b/lib/widgets/LocationsMap.dart @@ -268,7 +268,9 @@ class _LocationsMapState extends State { options: MapOptions( center: getInitialPosition(), zoom: widget.initialZoomLevel, + maxZoom: 18, ), + mapController: flutterMapController, children: [ TileLayer( urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', From fb14513e3693c8ff658ec30f51ca4e8a79f296ac Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 21:28:50 +0200 Subject: [PATCH 10/13] feat: Add cached LocationsMap.dart --- lib/main.dart | 10 ++++---- lib/widgets/LocationsMap.dart | 2 ++ pubspec.lock | 48 +++++++++++++++++++++++++++++++++++ pubspec.yaml | 1 + 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8b3b1168..15cd658a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:disable_battery_optimization/disable_battery_optimization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:locus/App.dart'; import 'package:locus/services/app_update_service.dart'; @@ -29,13 +30,12 @@ void main() async { Permission.locationAlways.isGranted, TaskService.restore(), ViewService.restore(), - Platform.isAndroid - ? DisableBatteryOptimization.isBatteryOptimizationDisabled - : Future.value(true), + Platform.isAndroid ? DisableBatteryOptimization.isBatteryOptimizationDisabled : Future.value(true), SettingsService.restore(), hasGrantedNotificationPermission(), LogService.restore(), AppUpdateService.restore(), + FlutterMapTileCaching.initialise(), ]); final bool hasLocationAlwaysGranted = futures[0]; final TaskService taskService = futures[1]; @@ -47,6 +47,7 @@ void main() async { final AppUpdateService appUpdateService = futures[7]; await logService.deleteOldLogs(); + await FMTC.instance('mapStore').manage.createAsync(); appUpdateService.checkForUpdates(force: true); @@ -57,8 +58,7 @@ void main() async { ChangeNotifierProvider(create: (_) => viewService), ChangeNotifierProvider(create: (_) => settingsService), ChangeNotifierProvider(create: (_) => logService), - ChangeNotifierProvider( - create: (_) => appUpdateService), + ChangeNotifierProvider(create: (_) => appUpdateService), ], child: App( hasLocationAlwaysGranted: hasLocationAlwaysGranted, diff --git a/lib/widgets/LocationsMap.dart b/lib/widgets/LocationsMap.dart index 114d7efb..9d2bc73e 100644 --- a/lib/widgets/LocationsMap.dart +++ b/lib/widgets/LocationsMap.dart @@ -6,6 +6,7 @@ import 'package:apple_maps_flutter/apple_maps_flutter.dart' as AppleMaps; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map_marker_popup/flutter_map_marker_popup.dart'; +import 'package:flutter_map_tile_caching/flutter_map_tile_caching.dart'; import 'package:geolocator/geolocator.dart'; import 'package:intl/intl.dart'; @@ -276,6 +277,7 @@ class _LocationsMapState extends State { urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', subdomains: const ['a', 'b', 'c'], userAgentPackageName: "app.myzel394.locus", + tileProvider: FMTC.instance('mapStore').getTileProvider(), ), CircleLayer( circles: widget.controller.locations diff --git a/pubspec.lock b/pubspec.lock index 6d071c44..ecacbee2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -483,6 +483,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.0" + flutter_map_tile_caching: + dependency: "direct main" + description: + name: flutter_map_tile_caching + sha256: "828a555ef12a88e0b93d79e83813ad3c5fa5b410dcb6943ac530bb25f32daaa0" + url: "https://pub.dev" + source: hosted + version: "8.0.0" flutter_osm_interface: dependency: transitive description: @@ -733,6 +741,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.6" + http2: + dependency: transitive + description: + name: http2 + sha256: "58805ebc6513eed3b98ee0a455a8357e61d187bf2e0fdc1e53120770f78de258" + url: "https://pub.dev" + source: hosted + version: "2.0.1" http_multi_server: dependency: transitive description: @@ -749,6 +765,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + http_plus: + dependency: transitive + description: + name: http_plus + sha256: "6e2af403727ea5bd0a6a45edbe8e1ebc9d5d49b38a93893e1c00e2a307035773" + url: "https://pub.dev" + source: hosted + version: "0.2.2" image: dependency: transitive description: @@ -773,6 +797,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + isar: + dependency: transitive + description: + name: isar + sha256: "99165dadb2cf2329d3140198363a7e7bff9bbd441871898a87e26914d25cf1ea" + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" + isar_flutter_libs: + dependency: transitive + description: + name: isar_flutter_libs + sha256: bc6768cc4b9c61aabff77152e7f33b4b17d2fc93134f7af1c3dd51500fe8d5e8 + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" js: dependency: transitive description: @@ -1149,6 +1189,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.0" + queue: + dependency: transitive + description: + name: queue + sha256: "9a41ecadc15db79010108c06eae229a45c56b18db699760f34e8c9ac9b831ff9" + url: "https://pub.dev" + source: hosted + version: "3.1.0+2" quick_actions: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 6dbe1580..f7aa4d37 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -88,6 +88,7 @@ dependencies: english_words: ^4.0.0 flutter_map: ^4.0.0 flutter_map_marker_popup: ^5.1.0 + flutter_map_tile_caching: ^8.0.0 # Uncomment this for publishing FLOSS variant # Taken from https://github.com/Zverik/every_door/blob/aaf8d2fdeac483041bcac2c7c79ef760b99dff2b/pubspec.yaml#L55 From 5fc8f17307cf8bd5bd201adb1f55c560800d0b61 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 21:30:18 +0200 Subject: [PATCH 11/13] feat: Add open maps to latest location to TaskDetailScreen.dart --- lib/screens/TaskDetailScreen.dart | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lib/screens/TaskDetailScreen.dart b/lib/screens/TaskDetailScreen.dart index 0a34036a..d15d6215 100644 --- a/lib/screens/TaskDetailScreen.dart +++ b/lib/screens/TaskDetailScreen.dart @@ -8,10 +8,13 @@ import 'package:locus/services/task_service.dart'; import 'package:locus/widgets/LocationFetchError.dart'; import 'package:locus/widgets/LocationsLoadingScreen.dart'; import 'package:locus/widgets/LocationsMap.dart'; +import 'package:map_launcher/map_launcher.dart'; import '../api/get-locations.dart'; import '../constants/spacing.dart'; import '../widgets/LocationFetchEmpty.dart'; +import '../widgets/OpenInMaps.dart'; +import '../widgets/PlatformPopup.dart'; class TaskDetailScreen extends StatefulWidget { final Task task; @@ -104,6 +107,31 @@ class _TaskDetailScreenState extends State { cupertino: (_, __) => CupertinoNavigationBarData( backgroundColor: CupertinoTheme.of(context).barBackgroundColor.withOpacity(.5), ), + trailingActions: _controller.locations.isNotEmpty + ? [ + PlatformPopup( + type: PlatformPopupType.tap, + items: [ + PlatformPopupMenuItem( + label: PlatformListTile( + leading: Icon(context.platformIcons.location), + trailing: const SizedBox.shrink(), + title: Text(l10n.viewDetails_actions_openLatestLocation), + ), + onPressed: () async { + await showPlatformModalSheet( + context: context, + builder: (context) => OpenInMaps( + destination: + Coords(_controller.locations.last.latitude, _controller.locations.last.longitude), + ), + ); + }, + ) + ], + ), + ] + : [], ), body: _isError ? const LocationFetchError() From 95274bf407bcd29438fff0c28a0ae3d7d8da323c Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 21:39:07 +0200 Subject: [PATCH 12/13] ui(material): Improve bottom sheet color --- lib/screens/CreateTaskScreen.dart | 55 ++--- lib/screens/MainScreen.dart | 1 - lib/screens/SettingsScreen.dart | 2 +- lib/screens/TaskDetailScreen.dart | 1 + lib/screens/ViewDetailScreen.dart | 213 ++++++++---------- .../main_screen_widgets/ImportTask.dart | 10 +- .../task_detail_screen_widgets/Details.dart | 1 - lib/widgets/ModalSheet.dart | 1 - 8 files changed, 123 insertions(+), 161 deletions(-) diff --git a/lib/screens/CreateTaskScreen.dart b/lib/screens/CreateTaskScreen.dart index 682ce71b..a9a62347 100644 --- a/lib/screens/CreateTaskScreen.dart +++ b/lib/screens/CreateTaskScreen.dart @@ -3,8 +3,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:flutter_platform_widgets/flutter_platform_widgets.dart' - hide PlatformListTile; +import 'package:flutter_platform_widgets/flutter_platform_widgets.dart' hide PlatformListTile; import 'package:locus/constants/spacing.dart'; import 'package:locus/screens/create_task_screen_widgets/ExampleTasksRoulette.dart'; import 'package:locus/services/task_service.dart'; @@ -53,8 +52,7 @@ class _CreateTaskScreenState extends State { _nameController.addListener(() { final taskService = context.read(); final lowerCasedName = _nameController.text.toLowerCase(); - final alreadyExists = taskService.tasks - .any((element) => element.name.toLowerCase() == lowerCasedName); + final alreadyExists = taskService.tasks.any((element) => element.name.toLowerCase() == lowerCasedName); setState(() { anotherTaskAlreadyExists = alreadyExists; @@ -202,15 +200,12 @@ class _CreateTaskScreenState extends State { autofillHints: const [AutofillHints.name], material: (_, __) => MaterialTextFormFieldData( decoration: InputDecoration( - labelText: - l10n.createTask_fields_name_label, + labelText: l10n.createTask_fields_name_label, prefixIcon: Icon(context.platformIcons.tag), ), ), - cupertino: (_, __) => - CupertinoTextFormFieldData( - placeholder: - l10n.createTask_fields_name_label, + cupertino: (_, __) => CupertinoTextFormFieldData( + placeholder: l10n.createTask_fields_name_label, prefix: Icon(context.platformIcons.tag), ), ) @@ -251,24 +246,19 @@ class _CreateTaskScreenState extends State { direction: Axis.horizontal, children: [ PlatformElevatedButton( - material: (_, __) => - MaterialElevatedButtonData( + material: (_, __) => MaterialElevatedButtonData( icon: PlatformWidget( - material: (_, __) => - const Icon(Icons.dns_rounded), - cupertino: (_, __) => const Icon( - CupertinoIcons.list_bullet), + material: (_, __) => const Icon(Icons.dns_rounded), + cupertino: (_, __) => const Icon(CupertinoIcons.list_bullet), ), ), - cupertino: (_, __) => - CupertinoElevatedButtonData( + cupertino: (_, __) => CupertinoElevatedButtonData( padding: getSmallButtonPadding(context), ), onPressed: () { showPlatformModalSheet( context: context, material: MaterialModalSheetData( - backgroundColor: Colors.transparent, isScrollControlled: true, isDismissible: true, ), @@ -277,9 +267,8 @@ class _CreateTaskScreenState extends State { ), ); }, - child: Text( - l10n.createTask_fields_relays_selectLabel( - _relaysController.relays.length)), + child: + Text(l10n.createTask_fields_relays_selectLabel(_relaysController.relays.length)), ) .animate() .then(delay: IN_DELAY * 4) @@ -294,19 +283,16 @@ class _CreateTaskScreenState extends State { curve: Curves.easeOut, ), PlatformElevatedButton( - material: (_, __) => - MaterialElevatedButtonData( + material: (_, __) => MaterialElevatedButtonData( icon: const Icon(Icons.timer_rounded), ), - cupertino: (_, __) => - CupertinoElevatedButtonData( + cupertino: (_, __) => CupertinoElevatedButtonData( padding: getSmallButtonPadding(context), ), onPressed: () async { await showPlatformModalSheet( context: context, material: MaterialModalSheetData( - backgroundColor: Colors.transparent, isScrollControlled: true, isDismissible: true, ), @@ -316,8 +302,7 @@ class _CreateTaskScreenState extends State { ); }, child: Text( - l10n.createTask_fields_timers_selectLabel( - _timersController.timers.length), + l10n.createTask_fields_timers_selectLabel(_timersController.timers.length), ), ) .animate() @@ -336,8 +321,7 @@ class _CreateTaskScreenState extends State { ), const SizedBox(height: MEDIUM_SPACE), PlatformListTile( - title: - Text(l10n.mainScreen_createTask_scheduleNow), + title: Text(l10n.mainScreen_createTask_scheduleNow), leading: PlatformSwitch( value: _scheduleNow, onChanged: (value) { @@ -352,14 +336,11 @@ class _CreateTaskScreenState extends State { showPlatformDialog( context: context, builder: (context) => PlatformAlertDialog( - title: Text(l10n - .mainScreen_createTask_scheduleNow_help_title), - content: Text(l10n - .mainScreen_createTask_scheduleNow_help_description), + title: Text(l10n.mainScreen_createTask_scheduleNow_help_title), + content: Text(l10n.mainScreen_createTask_scheduleNow_help_description), actions: [ PlatformDialogAction( - child: PlatformText( - l10n.closeNeutralAction), + child: PlatformText(l10n.closeNeutralAction), onPressed: () { Navigator.of(context).pop(); }, diff --git a/lib/screens/MainScreen.dart b/lib/screens/MainScreen.dart index bfc256cb..be2900ca 100644 --- a/lib/screens/MainScreen.dart +++ b/lib/screens/MainScreen.dart @@ -138,7 +138,6 @@ class _MainScreenState extends State { await showPlatformModalSheet( context: context, material: MaterialModalSheetData( - backgroundColor: Colors.transparent, isScrollControlled: true, isDismissible: true, ), diff --git a/lib/screens/SettingsScreen.dart b/lib/screens/SettingsScreen.dart index 3dfd0717..da92947c 100644 --- a/lib/screens/SettingsScreen.dart +++ b/lib/screens/SettingsScreen.dart @@ -199,7 +199,6 @@ class _SettingsScreenState extends State { await showPlatformModalSheet( context: context, material: MaterialModalSheetData( - backgroundColor: Colors.transparent, isScrollControlled: true, isDismissible: true, ), @@ -305,6 +304,7 @@ class _SettingsScreenState extends State { onPressed: (_) async { final shouldPopContext = await showPlatformModalSheet( context: context, + material: MaterialModalSheetData(), builder: (context) => ImportSheet( onImport: (final taskService, final viewService, final settings) async { await Future.wait([ diff --git a/lib/screens/TaskDetailScreen.dart b/lib/screens/TaskDetailScreen.dart index d15d6215..ba334331 100644 --- a/lib/screens/TaskDetailScreen.dart +++ b/lib/screens/TaskDetailScreen.dart @@ -121,6 +121,7 @@ class _TaskDetailScreenState extends State { onPressed: () async { await showPlatformModalSheet( context: context, + material: MaterialModalSheetData(), builder: (context) => OpenInMaps( destination: Coords(_controller.locations.last.latitude, _controller.locations.last.longitude), diff --git a/lib/screens/ViewDetailScreen.dart b/lib/screens/ViewDetailScreen.dart index bec7d01b..c29573b1 100644 --- a/lib/screens/ViewDetailScreen.dart +++ b/lib/screens/ViewDetailScreen.dart @@ -32,22 +32,22 @@ class LineSliderTickMarkShape extends SliderTickMarkShape { } @override - void paint(PaintingContext context, - Offset center, { - required RenderBox parentBox, - required SliderThemeData sliderTheme, - required Animation enableAnimation, - required Offset thumbCenter, - required bool isEnabled, - required TextDirection textDirection, - }) { + void paint( + PaintingContext context, + Offset center, { + required RenderBox parentBox, + required SliderThemeData sliderTheme, + required Animation enableAnimation, + required Offset thumbCenter, + required bool isEnabled, + required TextDirection textDirection, + }) { // This block is just copied from `slider_theme` final bool isTickMarkRightOfThumb = center.dx > thumbCenter.dx; final begin = - isTickMarkRightOfThumb ? sliderTheme.disabledInactiveTickMarkColor : sliderTheme.disabledActiveTickMarkColor; + isTickMarkRightOfThumb ? sliderTheme.disabledInactiveTickMarkColor : sliderTheme.disabledActiveTickMarkColor; final end = isTickMarkRightOfThumb ? sliderTheme.inactiveTickMarkColor : sliderTheme.activeTickMarkColor; - final Paint paint = Paint() - ..color = ColorTween(begin: begin, end: end).evaluate(enableAnimation)!; + final Paint paint = Paint()..color = ColorTween(begin: begin, end: end).evaluate(enableAnimation)!; final trackHeight = sliderTheme.trackHeight!; @@ -133,116 +133,103 @@ class _ViewDetailScreenState extends State { title: Text(l10n.viewDetails_title), trailingActions: _controller.locations.isNotEmpty ? [ - PlatformPopup( - type: PlatformPopupType.tap, - items: [ - PlatformPopupMenuItem( - label: PlatformListTile( - leading: Icon(context.platformIcons.location), - trailing: const SizedBox.shrink(), - title: Text(l10n.viewDetails_actions_openLatestLocation), + PlatformPopup( + type: PlatformPopupType.tap, + items: [ + PlatformPopupMenuItem( + label: PlatformListTile( + leading: Icon(context.platformIcons.location), + trailing: const SizedBox.shrink(), + title: Text(l10n.viewDetails_actions_openLatestLocation), + ), + onPressed: () async { + await showPlatformModalSheet( + context: context, + material: MaterialModalSheetData(), + builder: (context) => OpenInMaps( + destination: + Coords(_controller.locations.last.latitude, _controller.locations.last.longitude), + ), + ); + }, + ) + ], ), - onPressed: () async { - await showPlatformModalSheet( - context: context, - builder: (context) => - OpenInMaps( - destination: - Coords(_controller.locations.last.latitude, _controller.locations.last.longitude), - ), - ); - }, - ) - ], - ), - ] + ] : [], - material: (_, __) => - MaterialAppBarData( - centerTitle: true, - ), - cupertino: (_, __) => - CupertinoNavigationBarData( - backgroundColor: CupertinoTheme - .of(context) - .barBackgroundColor - .withOpacity(.5), - ), + material: (_, __) => MaterialAppBarData( + centerTitle: true, + ), + cupertino: (_, __) => CupertinoNavigationBarData( + backgroundColor: CupertinoTheme.of(context).barBackgroundColor.withOpacity(.5), + ), ), body: _isError ? const LocationFetchError() : _isLoading - ? SafeArea( - child: Padding( - padding: const EdgeInsets.all(MEDIUM_SPACE), - child: LocationsLoadingScreen( - locations: _controller.locations, - onTimeout: () { - setState(() { - _isError = true; - }); - }, - ), - ), - ) - : Column( - children: [ - Expanded( - flex: 11, - child: LocationsMap( - controller: _controller, - ), - ), - Expanded( - flex: 1, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: List.generate(24, (index) => 23 - index).map((hour) { - final date = DateTime.now().subtract(Duration(hours: hour)); - final normalizedDate = LocationsMapController.normalizeDateTime(date); - - final onTap = () { - _controller.clear(); - - final locations = locationsPerHour[normalizedDate] ?? []; - - if (locations.isNotEmpty) { - _controller.addAll(locations); - _controller.goTo(locations.last); - } - }; - final child = FillUpPaint( - color: shades[0]!, - fillPercentage: (locationsPerHour[normalizedDate]?.length ?? 0).toDouble() / maxLocations, - size: Size( - MediaQuery - .of(context) - .size - .width / 24, - MediaQuery - .of(context) - .size - .height * (1 / 12), + ? SafeArea( + child: Padding( + padding: const EdgeInsets.all(MEDIUM_SPACE), + child: LocationsLoadingScreen( + locations: _controller.locations, + onTimeout: () { + setState(() { + _isError = true; + }); + }, + ), ), - ); - - return PlatformWidget( - material: (_, __) => - InkWell( - onTap: onTap, - child: child, + ) + : Column( + children: [ + Expanded( + flex: 11, + child: LocationsMap( + controller: _controller, ), - cupertino: (_, __) => - GestureDetector( - onTap: onTap, - child: child, + ), + Expanded( + flex: 1, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: List.generate(24, (index) => 23 - index).map((hour) { + final date = DateTime.now().subtract(Duration(hours: hour)); + final normalizedDate = LocationsMapController.normalizeDateTime(date); + + final onTap = () { + _controller.clear(); + + final locations = locationsPerHour[normalizedDate] ?? []; + + if (locations.isNotEmpty) { + _controller.addAll(locations); + _controller.goTo(locations.last); + } + }; + final child = FillUpPaint( + color: shades[0]!, + fillPercentage: (locationsPerHour[normalizedDate]?.length ?? 0).toDouble() / maxLocations, + size: Size( + MediaQuery.of(context).size.width / 24, + MediaQuery.of(context).size.height * (1 / 12), + ), + ); + + return PlatformWidget( + material: (_, __) => InkWell( + onTap: onTap, + child: child, + ), + cupertino: (_, __) => GestureDetector( + onTap: onTap, + child: child, + ), + ); + }).toList(), ), - ); - }).toList(), - ), - ), - ], - ), + ), + ], + ), ); } } diff --git a/lib/screens/main_screen_widgets/ImportTask.dart b/lib/screens/main_screen_widgets/ImportTask.dart index 87534b23..275fcd6c 100644 --- a/lib/screens/main_screen_widgets/ImportTask.dart +++ b/lib/screens/main_screen_widgets/ImportTask.dart @@ -120,16 +120,14 @@ class _ImportTaskState extends State with TickerProviderStateMixin { onPressed: () { Navigator.of(context).pop(ImportScreen.askURL); }, - child: Text( - l10n.mainScreen_importTask_action_importMethod_url), + child: Text(l10n.mainScreen_importTask_action_importMethod_url), ), CupertinoActionSheetAction( isDefaultAction: true, onPressed: () { Navigator.of(context).pop(ImportScreen.importFile); }, - child: Text(l10n - .mainScreen_importTask_action_importMethod_file), + child: Text(l10n.mainScreen_importTask_action_importMethod_file), ), ], ), @@ -144,12 +142,10 @@ class _ImportTaskState extends State with TickerProviderStateMixin { await showPlatformModalSheet( context: context, material: MaterialModalSheetData( - backgroundColor: Colors.transparent, isScrollControlled: true, isDismissible: true, ), - builder: (context) => - ImportTaskSheet(initialScreen: initialScreen), + builder: (context) => ImportTaskSheet(initialScreen: initialScreen), ); _controller.forward(); diff --git a/lib/screens/task_detail_screen_widgets/Details.dart b/lib/screens/task_detail_screen_widgets/Details.dart index a06981e6..6de0ec9c 100644 --- a/lib/screens/task_detail_screen_widgets/Details.dart +++ b/lib/screens/task_detail_screen_widgets/Details.dart @@ -211,7 +211,6 @@ class _DetailsState extends State
{ await showPlatformModalSheet( context: context, material: MaterialModalSheetData( - backgroundColor: Colors.transparent, isScrollControlled: true, isDismissible: true, ), diff --git a/lib/widgets/ModalSheet.dart b/lib/widgets/ModalSheet.dart index dbff0e6d..17d1ce6d 100644 --- a/lib/widgets/ModalSheet.dart +++ b/lib/widgets/ModalSheet.dart @@ -21,7 +21,6 @@ class ModalSheet extends StatelessWidget { topLeft: Radius.circular(LARGE_SPACE), topRight: Radius.circular(LARGE_SPACE), ), - color: getSheetColor(context), ), child: Padding( padding: const EdgeInsets.only( From 24de815e561c68d90583f88f43a756762762a578 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Tue, 30 May 2023 21:47:31 +0200 Subject: [PATCH 13/13] ui(material): Make input color adjacent to primary color --- lib/App.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/App.dart b/lib/App.dart index 701cd0ae..079dbac0 100644 --- a/lib/App.dart +++ b/lib/App.dart @@ -100,6 +100,11 @@ class App extends StatelessWidget { dialogBackgroundColor: settings.primaryColor == null ? darkColorScheme.background : HSLColor.fromColor(settings.primaryColor!).withLightness(0.15).toColor(), + inputDecorationTheme: DARK_THEME_MATERIAL.inputDecorationTheme.copyWith( + fillColor: settings.primaryColor == null + ? null + : HSLColor.fromColor(settings.primaryColor!).withLightness(0.3).withSaturation(.5).toColor(), + ), ); } @@ -118,6 +123,11 @@ class App extends StatelessWidget { dialogBackgroundColor: settings.primaryColor == null ? null : HSLColor.fromColor(settings.primaryColor!).withLightness(0.15).toColor(), + inputDecorationTheme: DARK_THEME_MATERIAL.inputDecorationTheme.copyWith( + fillColor: settings.primaryColor == null + ? null + : HSLColor.fromColor(settings.primaryColor!).withLightness(0.3).withSaturation(.5).toColor(), + ), ); })(), themeMode: ThemeMode.system,