From 83595f4d92c1123cd9cf4bc42ced625f4e25c8b6 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Sun, 15 Oct 2023 16:46:43 +0200 Subject: [PATCH] fix: Only init live location after permission check --- lib/screens/LocationsOverviewScreen.dart | 514 ++++++++++++----------- lib/services/manager_service/task.dart | 4 +- pubspec.lock | 34 +- 3 files changed, 292 insertions(+), 260 deletions(-) diff --git a/lib/screens/LocationsOverviewScreen.dart b/lib/screens/LocationsOverviewScreen.dart index 6516a8d..cd92680 100644 --- a/lib/screens/LocationsOverviewScreen.dart +++ b/lib/screens/LocationsOverviewScreen.dart @@ -136,7 +136,6 @@ class _LocationsOverviewScreenState extends State ..addObserver(this) ..addPostFrameCallback((_) { _setLocationFromSettings(); - _initLiveLocationUpdate(); locationFetchers.fetchPreviewLocations(); taskService.checkup(logService); @@ -146,6 +145,8 @@ class _LocationsOverviewScreenState extends State Geolocator.checkPermission().then((status) { if ({LocationPermission.always, LocationPermission.whileInUse} .contains(status)) { + _initLiveLocationUpdate(); + updateCurrentPosition( askPermissions: false, showErrorMessage: false, @@ -231,8 +232,7 @@ class _LocationsOverviewScreenState extends State } List mergeLocationsIfRequired( - final List locations, - ) { + final List locations,) { if (locations.isEmpty) { return locations; } @@ -269,7 +269,7 @@ class _LocationsOverviewScreenState extends State notificationText: l10n.backgroundLocationFetch_text, notificationTitle: l10n.backgroundLocationFetch_title, notificationIcon: - const AndroidResource(name: "ic_quick_actions_share_now"), + const AndroidResource(name: "ic_quick_actions_share_now"), ), ); } else if (isPlatformApple()) { @@ -320,7 +320,7 @@ class _LocationsOverviewScreenState extends State void _handleViewAlarmChecker() { _viewsAlarmCheckerTimer = Timer.periodic( const Duration(minutes: 1), - (_) { + (_) { final viewService = context.read(); if (viewService.viewsWithAlarms.isEmpty) { @@ -330,9 +330,7 @@ class _LocationsOverviewScreenState extends State ); } - Future _animateToPosition( - final Position position, - ) async { + Future _animateToPosition(final Position position,) async { if (flutterMapController != null) { final zoom = max(15, flutterMapController!.zoom).toDouble(); @@ -456,7 +454,9 @@ class _LocationsOverviewScreenState extends State return CurrentLocationLayer( positionStream: - context.read().locationMarkerStream, + context + .read() + .locationMarkerStream, followOnLocationUpdate: FollowOnLocationUpdate.never, style: LocationMarkerStyle( marker: DefaultLocationMarker( @@ -474,27 +474,32 @@ class _LocationsOverviewScreenState extends State final locationFetchers = context.read(); final Iterable<(TaskView, LocationPointService)> circleLocations = - selectedViewID == null - ? locationFetchers.fetchers - .where((fetcher) => fetcher.sortedLocations.isNotEmpty) - .map((fetcher) => (fetcher.view, fetcher.sortedLocations.last)) - : viewService.views - .map( - (view) => mergeLocationsIfRequired( - locationFetchers - .getLocations(view) - .whereNot((location) => location == visibleLocation) - .toList(), - ), - ) - .expand((element) => element) - .map((location) => (selectedView!, location)); - final ownLocations = context.watch().previewLocations.map( - (location) => LatLng( + selectedViewID == null + ? locationFetchers.fetchers + .where((fetcher) => fetcher.sortedLocations.isNotEmpty) + .map((fetcher) => (fetcher.view, fetcher.sortedLocations.last)) + : viewService.views + .map( + (view) => + mergeLocationsIfRequired( + locationFetchers + .getLocations(view) + .whereNot((location) => location == visibleLocation) + .toList(), + ), + ) + .expand((element) => element) + .map((location) => (selectedView!, location)); + final ownLocations = context + .watch() + .previewLocations + .map( + (location) => + LatLng( location.latitude, location.longitude, ), - ); + ); if (settings.getMapProvider() == MapProvider.apple) { return apple_maps.AppleMap( @@ -525,29 +530,30 @@ class _LocationsOverviewScreenState extends State (view) => selectedViewID == null || view.id == selectedViewID) .map( (view) => - mergeLocationsIfRequired(locationFetchers.getLocations(view)) - .map( - (location) => apple_maps.Circle( - circleId: apple_maps.CircleId(location.id), - center: apple_maps.LatLng( - location.latitude, - location.longitude, - ), - radius: location.accuracy, - fillColor: view.color.withOpacity(0.2), - strokeColor: view.color, - strokeWidth: location.accuracy < 10 ? 1 : 3), - ) - .toList(), - ) + mergeLocationsIfRequired(locationFetchers.getLocations(view)) + .map( + (location) => + apple_maps.Circle( + circleId: apple_maps.CircleId(location.id), + center: apple_maps.LatLng( + location.latitude, + location.longitude, + ), + radius: location.accuracy, + fillColor: view.color.withOpacity(0.2), + strokeColor: view.color, + strokeWidth: location.accuracy < 10 ? 1 : 3), + ) + .toList(), + ) .expand((element) => element) .toSet(), polylines: Set.from( locationFetchers.fetchers .where((fetcher) => - selectedViewID == null || fetcher.view.id == selectedViewID) + selectedViewID == null || fetcher.view.id == selectedViewID) .map( - (fetcher) { + (fetcher) { final view = fetcher.view; return apple_maps.Polyline( @@ -565,14 +571,15 @@ class _LocationsOverviewScreenState extends State }, // TODO points: mergeLocationsIfRequired( - locationFetchers.getLocations(view)) + locationFetchers.getLocations(view)) .reversed .map( - (location) => apple_maps.LatLng( + (location) => + apple_maps.LatLng( location.latitude, location.longitude, ), - ) + ) .toList(), ); }, @@ -595,18 +602,18 @@ class _LocationsOverviewScreenState extends State CircleLayer( circles: circleLocations .map((data) { - final view = data.$1; - final location = data.$2; - - return CircleMarker( - radius: location.accuracy, - useRadiusInMeter: true, - point: LatLng(location.latitude, location.longitude), - borderStrokeWidth: 1, - color: view.color.withOpacity(.1 * colorOpacityMultiplier), - borderColor: view.color.withOpacity(colorOpacityMultiplier), - ); - }) + final view = data.$1; + final location = data.$2; + + return CircleMarker( + radius: location.accuracy, + useRadiusInMeter: true, + point: LatLng(location.latitude, location.longitude), + borderStrokeWidth: 1, + color: view.color.withOpacity(.1 * colorOpacityMultiplier), + borderColor: view.color.withOpacity(colorOpacityMultiplier), + ); + }) .toList() .cast(), ), @@ -630,9 +637,9 @@ class _LocationsOverviewScreenState extends State polylines: List.from( locationFetchers.fetchers .where((fetcher) => - selectedViewID == null || fetcher.view.id == selectedViewID) + selectedViewID == null || fetcher.view.id == selectedViewID) .map( - (fetcher) { + (fetcher) { final view = fetcher.view; final locations = mergeLocationsIfRequired( locationFetchers.getLocations(view), @@ -643,16 +650,16 @@ class _LocationsOverviewScreenState extends State strokeWidth: 10, strokeJoin: StrokeJoin.round, gradientColors: locations.length <= - LOCATION_POLYLINE_OPAQUE_AMOUNT_THRESHOLD + LOCATION_POLYLINE_OPAQUE_AMOUNT_THRESHOLD ? null : List.generate( - 9, (index) => view.color.withOpacity(0.9)) + - [view.color.withOpacity(.3)], + 9, (index) => view.color.withOpacity(0.9)) + + [view.color.withOpacity(.3)], points: locations.reversed .map( (location) => - LatLng(location.latitude, location.longitude), - ) + LatLng(location.latitude, location.longitude), + ) .toList(), ); }, @@ -667,7 +674,8 @@ class _LocationsOverviewScreenState extends State strokeWidth: 10, strokeJoin: StrokeJoin.round, gradientColors: ownLocations - .mapIndexed((index, _) => Colors.cyanAccent + .mapIndexed((index, _) => + Colors.cyanAccent .withOpacity(index / ownLocations.length)) .toList(), points: ownLocations.toList(), @@ -681,7 +689,7 @@ class _LocationsOverviewScreenState extends State popupDisplayOptions: PopupDisplayOptions( builder: (context, marker) { final view = viewService.views.firstWhere( - (view) => Key(view.id) == marker.key, + (view) => Key(view.id) == marker.key, ); return ViewLocationPopup( @@ -699,10 +707,14 @@ class _LocationsOverviewScreenState extends State ), markers: viewService.views .where((view) => - (selectedViewID == null || view.id == selectedViewID) && - locationFetchers.getLocations(view).isNotEmpty) + (selectedViewID == null || view.id == selectedViewID) && + locationFetchers + .getLocations(view) + .isNotEmpty) .map((view) { - final latestLocation = locationFetchers.getLocations(view).last; + final latestLocation = locationFetchers + .getLocations(view) + .last; return Marker( key: Key(view.id), @@ -711,18 +723,19 @@ class _LocationsOverviewScreenState extends State latestLocation.longitude, ), anchorPos: AnchorPos.align(AnchorAlign.top), - builder: (context) => Icon( - Icons.location_on, - size: 40, - color: view.color, - shadows: const [ - Shadow( - blurRadius: 10, - color: Colors.black, - offset: Offset(0, 0), + builder: (context) => + Icon( + Icons.location_on, + size: 40, + color: view.color, + shadows: const [ + Shadow( + blurRadius: 10, + color: Colors.black, + offset: Offset(0, 0), + ), + ], ), - ], - ), ); }).toList(), ), @@ -737,10 +750,11 @@ class _LocationsOverviewScreenState extends State return Stack( children: locationFetchers.fetchers .where((fetcher) => - (selectedViewID == null || fetcher.view.id == selectedViewID) && - fetcher.sortedLocations.isNotEmpty) + (selectedViewID == null || fetcher.view.id == selectedViewID) && + fetcher.sortedLocations.isNotEmpty) .map( - (fetcher) => OutOfBoundMarker( + (fetcher) => + OutOfBoundMarker( lastViewLocation: fetcher.sortedLocations.last, onTap: () { showViewLocations(fetcher.view); @@ -750,13 +764,12 @@ class _LocationsOverviewScreenState extends State appleMapController: appleMapController, flutterMapController: flutterMapController, ), - ) + ) .toList(), ); } - void showViewLocations( - final TaskView view, { + void showViewLocations(final TaskView view, { final bool jumpToLatestLocation = true, }) async { final locationFetchers = context.read(); @@ -798,8 +811,7 @@ class _LocationsOverviewScreenState extends State } } - Widget buildViewTile( - final TaskView? view, { + Widget buildViewTile(final TaskView? view, { final MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, }) { final l10n = AppLocalizations.of(context); @@ -854,14 +866,15 @@ class _LocationsOverviewScreenState extends State showCupertinoModalPopup( context: context, barrierDismissible: true, - builder: (cupertino) => CupertinoActionSheet( - cancelButton: CupertinoActionSheetAction( - onPressed: () { - Navigator.pop(context); - }, - child: Text(l10n.cancelLabel), - ), - actions: [ + builder: (cupertino) => + CupertinoActionSheet( + cancelButton: CupertinoActionSheetAction( + onPressed: () { + Navigator.pop(context); + }, + child: Text(l10n.cancelLabel), + ), + actions: [ CupertinoActionSheetAction( child: buildViewTile( null, @@ -876,32 +889,34 @@ class _LocationsOverviewScreenState extends State }, ) ] + - viewService.views - .map( - (view) => CupertinoActionSheetAction( - onPressed: () { - Navigator.pop(context); - showViewLocations(view); - }, - child: buildViewTile( - view, - mainAxisAlignment: MainAxisAlignment.center, - ), - ), + viewService.views + .map( + (view) => + CupertinoActionSheetAction( + onPressed: () { + Navigator.pop(context); + showViewLocations(view); + }, + child: buildViewTile( + view, + mainAxisAlignment: MainAxisAlignment + .center, + ), + ), ) - .toList(), - ), + .toList(), + ), ); }, child: selectedViewID == null ? Icon( - Icons.location_on_rounded, - color: settings.getPrimaryColor(context), - ) + Icons.location_on_rounded, + color: settings.getPrimaryColor(context), + ) : Icon( - Icons.circle_rounded, - color: selectedView!.color, - ), + Icons.circle_rounded, + color: selectedView!.color, + ), ), ), ), @@ -922,88 +937,93 @@ class _LocationsOverviewScreenState extends State vertical: SMALL_SPACE, ), child: PlatformWidget( - material: (context, _) => DropdownButton( - isDense: true, - value: selectedViewID, - onChanged: (selection) { - if (selection == null) { - setState(() { - showFAB = true; - selectedViewID = null; - visibleLocation = null; - }); - return; - } - - final view = viewService.views.firstWhere( - (view) => view.id == selection, - ); - - showViewLocations(view); - }, - underline: Container(), - alignment: Alignment.center, - isExpanded: true, - items: [ - DropdownMenuItem( - value: null, - child: buildViewTile(null), - ), - for (final view in viewService.views) ...[ - DropdownMenuItem( - value: view.id, - child: buildViewTile(view), - ), - ], - ], - ), - cupertino: (context, _) => CupertinoButton( - onPressed: () { - showCupertinoModalPopup( - context: context, - barrierDismissible: true, - builder: (cupertino) => CupertinoActionSheet( - cancelButton: CupertinoActionSheetAction( - onPressed: () { - Navigator.pop(context); - }, - child: Text(l10n.cancelLabel), + material: (context, _) => + DropdownButton( + isDense: true, + value: selectedViewID, + onChanged: (selection) { + if (selection == null) { + setState(() { + showFAB = true; + selectedViewID = null; + visibleLocation = null; + }); + return; + } + + final view = viewService.views.firstWhere( + (view) => view.id == selection, + ); + + showViewLocations(view); + }, + underline: Container(), + alignment: Alignment.center, + isExpanded: true, + items: [ + DropdownMenuItem( + value: null, + child: buildViewTile(null), ), - actions: [ - CupertinoActionSheetAction( - child: buildViewTile( - null, - mainAxisAlignment: MainAxisAlignment.center, + for (final view in viewService.views) ...[ + DropdownMenuItem( + value: view.id, + child: buildViewTile(view), + ), + ], + ], + ), + cupertino: (context, _) => + CupertinoButton( + onPressed: () { + showCupertinoModalPopup( + context: context, + barrierDismissible: true, + builder: (cupertino) => + CupertinoActionSheet( + cancelButton: CupertinoActionSheetAction( + onPressed: () { + Navigator.pop(context); + }, + child: Text(l10n.cancelLabel), ), - onPressed: () { - Navigator.pop(context); - setState(() { - selectedViewID = null; - visibleLocation = null; - }); - }, - ) - ] + - viewService.views - .map( - (view) => CupertinoActionSheetAction( + actions: [ + CupertinoActionSheetAction( + child: buildViewTile( + null, + mainAxisAlignment: MainAxisAlignment + .center, + ), onPressed: () { Navigator.pop(context); - showViewLocations(view); + setState(() { + selectedViewID = null; + visibleLocation = null; + }); }, - child: buildViewTile( - view, - mainAxisAlignment: - MainAxisAlignment.center, - ), - ), - ) - .toList(), - ), - ); - }, - child: buildViewTile(selectedView), - ), + ) + ] + + viewService.views + .map( + (view) => + CupertinoActionSheetAction( + onPressed: () { + Navigator.pop(context); + showViewLocations(view); + }, + child: buildViewTile( + view, + mainAxisAlignment: + MainAxisAlignment.center, + ), + ), + ) + .toList(), + ), + ); + }, + child: buildViewTile(selectedView), + ), ), ), ), @@ -1058,7 +1078,7 @@ class _LocationsOverviewScreenState extends State final settings = context.read(); final link = - await (task as Task).publisher.generateLink(settings.getServerHost()); + await (task as Task).publisher.generateLink(settings.getServerHost()); // Copy to clipboard await Clipboard.setData(ClipboardData(text: link)); @@ -1088,7 +1108,7 @@ class _LocationsOverviewScreenState extends State AnimatedScale( scale: showDetailedLocations ? 1 : 0, duration: - showDetailedLocations ? 1200.milliseconds : 100.milliseconds, + showDetailedLocations ? 1200.milliseconds : 100.milliseconds, curve: showDetailedLocations ? Curves.elasticOut : Curves.easeIn, child: Tooltip( message: disableShowDetailedLocations @@ -1111,7 +1131,7 @@ class _LocationsOverviewScreenState extends State onPressed: () { setState(() { disableShowDetailedLocations = - !disableShowDetailedLocations; + !disableShowDetailedLocations; }); }, ), @@ -1208,7 +1228,7 @@ class _LocationsOverviewScreenState extends State onPressed: importLocation, icon: const Icon(Icons.download_rounded), label: - Text(l10n.sharesOverviewScreen_importTask_action_import), + Text(l10n.sharesOverviewScreen_importTask_action_import), backgroundColor: background, foregroundColor: foreground, ), @@ -1290,58 +1310,62 @@ class _LocationsOverviewScreenState extends State showCupertinoModalPopup( context: context, barrierDismissible: true, - builder: (cupertino) => CupertinoActionSheet( - cancelButton: CupertinoActionSheetAction( - onPressed: () => Navigator.pop(context), - child: Text(l10n.cancelLabel), - ), - actions: [ - CupertinoActionSheetAction( - onPressed: withPopNavigation(createNewQuickLocationShare)( - context), - child: CupertinoListTile( - leading: const Icon(Icons.share_location_rounded), - title: Text(l10n.shareLocation_title), + builder: (cupertino) => + CupertinoActionSheet( + cancelButton: CupertinoActionSheetAction( + onPressed: () => Navigator.pop(context), + child: Text(l10n.cancelLabel), ), - ), - CupertinoActionSheetAction( - onPressed: withPopNavigation(importLocation)(context), - child: CupertinoListTile( - leading: + actions: [ + CupertinoActionSheetAction( + onPressed: withPopNavigation( + createNewQuickLocationShare)( + context), + child: CupertinoListTile( + leading: const Icon(Icons.share_location_rounded), + title: Text(l10n.shareLocation_title), + ), + ), + CupertinoActionSheetAction( + onPressed: withPopNavigation(importLocation)(context), + child: CupertinoListTile( + leading: const Icon(CupertinoIcons.square_arrow_down_fill), - title: Text( - l10n.sharesOverviewScreen_importTask_action_import), - ), - ), - CupertinoActionSheetAction( - onPressed: () { - Navigator.pop(context); + title: Text( + l10n + .sharesOverviewScreen_importTask_action_import), + ), + ), + CupertinoActionSheetAction( + onPressed: () { + Navigator.pop(context); - Navigator.push( - context, - MaterialWithModalsPageRoute( - builder: (context) => const SharesOverviewScreen(), + Navigator.push( + context, + MaterialWithModalsPageRoute( + builder: ( + context) => const SharesOverviewScreen(), + ), + ); + }, + child: CupertinoListTile( + leading: const Icon(CupertinoIcons.list_bullet), + title: Text(l10n.sharesOverviewScreen_title), ), - ); - }, - child: CupertinoListTile( - leading: const Icon(CupertinoIcons.list_bullet), - title: Text(l10n.sharesOverviewScreen_title), - ), - ), - CupertinoActionSheetAction( - onPressed: () { - Navigator.pop(context); + ), + CupertinoActionSheetAction( + onPressed: () { + Navigator.pop(context); - showSettings(context); - }, - child: CupertinoListTile( - leading: Icon(context.platformIcons.settings), - title: Text(l10n.settingsScreen_title), - ), + showSettings(context); + }, + child: CupertinoListTile( + leading: Icon(context.platformIcons.settings), + title: Text(l10n.settingsScreen_title), + ), + ), + ], ), - ], - ), ); }, ), diff --git a/lib/services/manager_service/task.dart b/lib/services/manager_service/task.dart index eaac08d..7627920 100644 --- a/lib/services/manager_service/task.dart +++ b/lib/services/manager_service/task.dart @@ -31,7 +31,7 @@ void _showPermissionMissingNotification({ AndroidChannelIDs.appIssues.name, l10n.androidNotificationChannel_appIssues_name, channelDescription: - l10n.androidNotificationChannel_appIssues_description, + l10n.androidNotificationChannel_appIssues_description, onlyAlertOnce: true, importance: Importance.max, priority: Priority.max, @@ -153,7 +153,7 @@ Future runBackgroundTask({ DateTime.now().difference(settings.lastHeadlessRun!).abs() > BATTERY_SAVER_ENABLED_MINIMUM_TIME_BETWEEN_HEADLESS_RUNS; - if (shouldRunBasedOnBatterySaver && shouldRunBasedOnLastRun) { + if (!shouldRunBasedOnBatterySaver && !shouldRunBasedOnLastRun) { // We don't want to run the headless task too often when the battery saver is enabled. FlutterLogs.logInfo( LOG_TAG, diff --git a/pubspec.lock b/pubspec.lock index 16deb8f..0383709 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -261,10 +261,10 @@ packages: dependency: "direct main" description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" convert: dependency: transitive description: @@ -825,10 +825,10 @@ packages: dependency: "direct main" description: name: intl - sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.18.0" + version: "0.18.1" io: dependency: transitive description: @@ -953,18 +953,18 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" material_design_icons_flutter: dependency: "direct main" description: @@ -1366,10 +1366,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: @@ -1414,10 +1414,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" timezone: dependency: transitive description: @@ -1650,6 +1650,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -1707,5 +1715,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.10.0"