only geolocate and show maps when connected

This commit is contained in:
Thibault Deckers 2021-01-27 18:57:38 +09:00
parent a85612269a
commit 8b1d37fc32
9 changed files with 137 additions and 40 deletions

View file

@ -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<bool> get isConnected async {
if (_isConnected != null) return SynchronousFuture(_isConnected);
final result = await (Connectivity().checkConnectivity());
_updateFromResult(result);
return _isConnected;
}
Future<bool> get canGeolocate => isConnected;
void _updateFromResult(ConnectivityResult result) {
_isConnected = result != ConnectivityResult.none;
debugPrint('Device is connected=$_isConnected');
}
}

View file

@ -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<void> locateEntries() async {
if (!(await connectivity.canGeolocate)) return;
// final stopwatch = Stopwatch()..start();
final byLocated = groupBy<AvesEntry, bool>(rawEntries.where((entry) => entry.hasGps), (entry) => entry.isLocated);
final todo = byLocated[false] ?? [];

View file

@ -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',

View file

@ -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<HomePage> {
Future<AvesEntry> _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;
}

View file

@ -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<ViewerVerticalPageView> {
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);
}

View file

@ -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<EntryViewerStack> 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;
}
}

View file

@ -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<LocationSection> with TickerProviderSt
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.showTitle) SectionRow(AIcons.location),
NotificationListener(
onNotification: (notification) {
if (notification is MapStyleChangedNotification) setState(() {});
return false;
FutureBuilder<bool>(
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<double, double>(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<double, double>(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

View file

@ -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:

View file

@ -33,6 +33,7 @@ dependencies:
sdk: flutter
charts_flutter:
collection:
connectivity:
decorated_icon:
event_bus:
expansion_tile_card: