From 8b1d37fc32c5af792db3b3b5db94302144e0d68d Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Wed, 27 Jan 2021 18:57:38 +0900 Subject: [PATCH] only geolocate and show maps when connected --- lib/model/connectivity.dart | 28 ++++++++ lib/model/source/location.dart | 5 +- lib/utils/constants.dart | 14 ++-- lib/widgets/home_page.dart | 10 ++- lib/widgets/viewer/entry_vertical_pager.dart | 9 ++- lib/widgets/viewer/entry_viewer_stack.dart | 12 +++- lib/widgets/viewer/info/location_section.dart | 70 +++++++++++-------- pubspec.lock | 28 ++++++++ pubspec.yaml | 1 + 9 files changed, 137 insertions(+), 40 deletions(-) create mode 100644 lib/model/connectivity.dart diff --git a/lib/model/connectivity.dart b/lib/model/connectivity.dart new file mode 100644 index 000000000..009c0fa1c --- /dev/null +++ b/lib/model/connectivity.dart @@ -0,0 +1,28 @@ +import 'package:connectivity/connectivity.dart'; +import 'package:flutter/foundation.dart'; + +final AvesConnectivity connectivity = AvesConnectivity._private(); + +class AvesConnectivity { + bool _isConnected; + + AvesConnectivity._private() { + Connectivity().onConnectivityChanged.listen(_updateFromResult); + } + + void onResume() => _isConnected = null; + + Future get isConnected async { + if (_isConnected != null) return SynchronousFuture(_isConnected); + final result = await (Connectivity().checkConnectivity()); + _updateFromResult(result); + return _isConnected; + } + + Future get canGeolocate => isConnected; + + void _updateFromResult(ConnectivityResult result) { + _isConnected = result != ConnectivityResult.none; + debugPrint('Device is connected=$_isConnected'); + } +} diff --git a/lib/model/source/location.dart b/lib/model/source/location.dart index 16de86443..37d6c0af8 100644 --- a/lib/model/source/location.dart +++ b/lib/model/source/location.dart @@ -1,7 +1,8 @@ import 'dart:math'; -import 'package:aves/model/filters/location.dart'; +import 'package:aves/model/connectivity.dart'; import 'package:aves/model/entry.dart'; +import 'package:aves/model/filters/location.dart'; import 'package:aves/model/metadata.dart'; import 'package:aves/model/metadata_db.dart'; import 'package:aves/model/source/collection_source.dart'; @@ -27,6 +28,8 @@ mixin LocationMixin on SourceBase { } Future locateEntries() async { + if (!(await connectivity.canGeolocate)) return; + // final stopwatch = Stopwatch()..start(); final byLocated = groupBy(rawEntries.where((entry) => entry.hasGps), (entry) => entry.isLocated); final todo = byLocated[false] ?? []; diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart index 51597f019..87453882c 100644 --- a/lib/utils/constants.dart +++ b/lib/utils/constants.dart @@ -29,14 +29,14 @@ class Constants { Dependency( name: 'AndroidX Core-KTX', license: 'Apache 2.0', - licenseUrl: 'https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/LICENSE.txt', - sourceUrl: 'https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/core/core-ktx', + licenseUrl: 'https://android.googlesource.com/platform/frameworks/support/+/androidx-main/LICENSE.txt', + sourceUrl: 'https://android.googlesource.com/platform/frameworks/support/+/androidx-main/core/core-ktx', ), Dependency( name: 'AndroidX Exifinterface', license: 'Apache 2.0', - licenseUrl: 'https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/LICENSE.txt', - sourceUrl: 'https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/exifinterface/exifinterface', + licenseUrl: 'https://android.googlesource.com/platform/frameworks/support/+/androidx-main/LICENSE.txt', + sourceUrl: 'https://android.googlesource.com/platform/frameworks/support/+/androidx-main/exifinterface/exifinterface', ), Dependency( name: 'Android-TiffBitmapFactory', @@ -83,6 +83,12 @@ class Constants { licenseUrl: 'https://github.com/dart-lang/collection/blob/master/LICENSE', sourceUrl: 'https://github.com/dart-lang/collection', ), + Dependency( + name: 'Connectivity', + license: 'BSD 3-Clause', + licenseUrl: 'https://github.com/flutter/plugins/blob/master/packages/connectivity/connectivity/LICENSE', + sourceUrl: 'https://github.com/flutter/plugins/blob/master/packages/connectivity/connectivity', + ), Dependency( name: 'Decorated Icon', license: 'MIT', diff --git a/lib/widgets/home_page.dart b/lib/widgets/home_page.dart index 08346aa82..0cff14049 100644 --- a/lib/widgets/home_page.dart +++ b/lib/widgets/home_page.dart @@ -1,4 +1,5 @@ import 'package:aves/main.dart'; +import 'package:aves/model/connectivity.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/settings/home_page.dart'; @@ -111,9 +112,14 @@ class _HomePageState extends State { Future _initViewerEntry({@required String uri, @required String mimeType}) async { final entry = await ImageFileService.getEntry(uri, mimeType); if (entry != null) { - // cataloguing is essential for geolocation and video rotation + // cataloguing is essential for coordinates and video rotation await entry.catalog(); - unawaited(entry.locate()); + // locating is fine in the background + unawaited(connectivity.canGeolocate.then((connected) { + if (connected) { + entry.locate(); + } + })); } return entry; } diff --git a/lib/widgets/viewer/entry_vertical_pager.dart b/lib/widgets/viewer/entry_vertical_pager.dart index 95391d6a9..2abf301a7 100644 --- a/lib/widgets/viewer/entry_vertical_pager.dart +++ b/lib/widgets/viewer/entry_vertical_pager.dart @@ -1,5 +1,6 @@ import 'dart:math'; +import 'package:aves/model/connectivity.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/widgets/common/magnifier/pan/scroll_physics.dart'; @@ -150,8 +151,12 @@ class _ViewerVerticalPageViewState extends State { entry.imageChangeNotifier.addListener(_onImageChanged); // make sure to locate the entry, // so that we can display the address instead of coordinates - // even when background locating has not reached this entry yet - entry.locate(); + // even when initial collection locating has not reached this entry yet + connectivity.canGeolocate.then((connected) { + if (connected) { + entry.locate(); + } + }); } else { Navigator.pop(context); } diff --git a/lib/widgets/viewer/entry_viewer_stack.dart b/lib/widgets/viewer/entry_viewer_stack.dart index 7ede8f873..f9eec2f2d 100644 --- a/lib/widgets/viewer/entry_viewer_stack.dart +++ b/lib/widgets/viewer/entry_viewer_stack.dart @@ -1,5 +1,6 @@ import 'dart:math'; +import 'package:aves/model/connectivity.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/settings/screen_on.dart'; @@ -141,8 +142,15 @@ class _EntryViewerStackState extends State with SingleTickerPr @override void didChangeAppLifecycleState(AppLifecycleState state) { - if (state == AppLifecycleState.paused) { - _pauseVideoControllers(); + switch (state) { + case AppLifecycleState.paused: + _pauseVideoControllers(); + break; + case AppLifecycleState.resumed: + connectivity.onResume(); + break; + default: + break; } } diff --git a/lib/widgets/viewer/info/location_section.dart b/lib/widgets/viewer/info/location_section.dart index bbf521cc2..1dd7a3e0c 100644 --- a/lib/widgets/viewer/info/location_section.dart +++ b/lib/widgets/viewer/info/location_section.dart @@ -1,5 +1,6 @@ -import 'package:aves/model/filters/location.dart'; +import 'package:aves/model/connectivity.dart'; import 'package:aves/model/entry.dart'; +import 'package:aves/model/filters/location.dart'; import 'package:aves/model/settings/coordinate_format.dart'; import 'package:aves/model/settings/map_style.dart'; import 'package:aves/model/settings/settings.dart'; @@ -102,34 +103,40 @@ class _LocationSectionState extends State with TickerProviderSt crossAxisAlignment: CrossAxisAlignment.start, children: [ if (widget.showTitle) SectionRow(AIcons.location), - NotificationListener( - onNotification: (notification) { - if (notification is MapStyleChangedNotification) setState(() {}); - return false; + FutureBuilder( + future: connectivity.isConnected, + builder: (context, snapshot) { + if (snapshot.data != true) return SizedBox(); + return NotificationListener( + onNotification: (notification) { + if (notification is MapStyleChangedNotification) setState(() {}); + return false; + }, + child: AnimatedSize( + alignment: Alignment.topCenter, + curve: Curves.easeInOutCubic, + duration: Durations.mapStyleSwitchAnimation, + vsync: this, + child: settings.infoMapStyle.isGoogleMaps + ? EntryGoogleMap( + // `LatLng` used by `google_maps_flutter` is not the one from `latlong` package + latLng: Tuple2(entry.latLng.latitude, entry.latLng.longitude), + geoUri: entry.geoUri, + initialZoom: settings.infoMapZoom, + markerId: entry.uri ?? entry.path, + markerBuilder: buildMarker, + ) + : EntryLeafletMap( + latLng: entry.latLng, + geoUri: entry.geoUri, + initialZoom: settings.infoMapZoom, + style: settings.infoMapStyle, + markerSize: Size(extent, extent + pointerSize.height), + markerBuilder: buildMarker, + ), + ), + ); }, - child: AnimatedSize( - alignment: Alignment.topCenter, - curve: Curves.easeInOutCubic, - duration: Durations.mapStyleSwitchAnimation, - vsync: this, - child: settings.infoMapStyle.isGoogleMaps - ? EntryGoogleMap( - // `LatLng` used by `google_maps_flutter` is not the one from `latlong` package - latLng: Tuple2(entry.latLng.latitude, entry.latLng.longitude), - geoUri: entry.geoUri, - initialZoom: settings.infoMapZoom, - markerId: entry.uri ?? entry.path, - markerBuilder: buildMarker, - ) - : EntryLeafletMap( - latLng: entry.latLng, - geoUri: entry.geoUri, - initialZoom: settings.infoMapZoom, - style: settings.infoMapStyle, - markerSize: Size(extent, extent + pointerSize.height), - markerBuilder: buildMarker, - ), - ), ), if (entry.hasGps) _AddressInfoGroup(entry: entry), if (filters.isNotEmpty) @@ -174,7 +181,12 @@ class _AddressInfoGroupState extends State<_AddressInfoGroup> { @override void initState() { super.initState(); - _addressLineLoader = entry.findAddressLine(); + _addressLineLoader = connectivity.canGeolocate.then((connected) { + if (connected) { + return entry.findAddressLine(); + } + return null; + }); } @override diff --git a/pubspec.lock b/pubspec.lock index b3b97f713..97fe07ccf 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -113,6 +113,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0-nullsafety.3" + connectivity: + dependency: "direct main" + description: + name: connectivity + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + connectivity_for_web: + dependency: transitive + description: + name: connectivity_for_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.1+4" + connectivity_macos: + dependency: transitive + description: + name: connectivity_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.0+7" + connectivity_platform_interface: + dependency: transitive + description: + name: connectivity_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.6" console_log_handler: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 63fee4179..7dbfd751f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -33,6 +33,7 @@ dependencies: sdk: flutter charts_flutter: collection: + connectivity: decorated_icon: event_bus: expansion_tile_card: