country locale fixes

This commit is contained in:
Thibault Deckers 2021-10-17 19:46:29 +09:00
parent 5db804c0e7
commit 85a0c504d6
10 changed files with 40 additions and 28 deletions

View file

@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'dart:ui';
import 'package:aves/geo/countries.dart'; import 'package:aves/geo/countries.dart';
import 'package:aves/model/entry_cache.dart'; import 'package:aves/model/entry_cache.dart';
@ -9,7 +10,6 @@ import 'package:aves/model/metadata/catalog.dart';
import 'package:aves/model/metadata/date_modifier.dart'; import 'package:aves/model/metadata/date_modifier.dart';
import 'package:aves/model/metadata/enums.dart'; import 'package:aves/model/metadata/enums.dart';
import 'package:aves/model/multipage.dart'; import 'package:aves/model/multipage.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/model/video/metadata.dart'; import 'package:aves/model/video/metadata.dart';
import 'package:aves/ref/mime_types.dart'; import 'package:aves/ref/mime_types.dart';
import 'package:aves/services/common/service_policy.dart'; import 'package:aves/services/common/service_policy.dart';
@ -21,7 +21,6 @@ import 'package:aves/utils/change_notifier.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:country_code/country_code.dart'; import 'package:country_code/country_code.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:latlong2/latlong.dart'; import 'package:latlong2/latlong.dart';
class AvesEntry { class AvesEntry {
@ -469,11 +468,11 @@ class AvesEntry {
addressChangeNotifier.notifyListeners(); addressChangeNotifier.notifyListeners();
} }
Future<void> locate({required bool background, required bool force}) async { Future<void> locate({required bool background, required bool force, required Locale geocoderLocale}) async {
if (!hasGps) return; if (!hasGps) return;
await _locateCountry(force: force); await _locateCountry(force: force);
if (await availability.canLocatePlaces) { if (await availability.canLocatePlaces) {
await locatePlace(background: background, force: force); await locatePlace(background: background, force: force, geocoderLocale: geocoderLocale);
} }
} }
@ -493,15 +492,8 @@ class AvesEntry {
); );
} }
String? _geocoderLocale;
String get geocoderLocale {
_geocoderLocale ??= (settings.locale ?? WidgetsBinding.instance!.window.locale).toString();
return _geocoderLocale!;
}
// full reverse geocoding, requiring Play Services and some connectivity // full reverse geocoding, requiring Play Services and some connectivity
Future<void> locatePlace({required bool background, required bool force}) async { Future<void> locatePlace({required bool background, required bool force, required Locale geocoderLocale}) async {
if (!hasGps || (hasFineAddress && !force)) return; if (!hasGps || (hasFineAddress && !force)) return;
try { try {
Future<List<Address>> call() => GeocodingService.getAddress(latLng!, geocoderLocale); Future<List<Address>> call() => GeocodingService.getAddress(latLng!, geocoderLocale);
@ -531,7 +523,7 @@ class AvesEntry {
} }
} }
Future<String?> findAddressLine() async { Future<String?> findAddressLine({required Locale geocoderLocale}) async {
if (!hasGps) return null; if (!hasGps) return null;
try { try {
@ -608,7 +600,7 @@ class AvesEntry {
metadataChangeNotifier.notifyListeners(); metadataChangeNotifier.notifyListeners();
} }
Future<void> refresh({required bool background, required bool persist, required bool force}) async { Future<void> refresh({required bool background, required bool persist, required bool force, required Locale geocoderLocale}) async {
_catalogMetadata = null; _catalogMetadata = null;
_addressDetails = null; _addressDetails = null;
_bestDate = null; _bestDate = null;
@ -622,7 +614,7 @@ class AvesEntry {
if (updated != null) { if (updated != null) {
await _applyNewFields(updated.toMap(), persist: persist); await _applyNewFields(updated.toMap(), persist: persist);
await catalog(background: background, persist: persist, force: force); await catalog(background: background, persist: persist, force: force);
await locate(background: background, force: force); await locate(background: background, force: force, geocoderLocale: geocoderLocale);
} }
} }

View file

@ -15,6 +15,7 @@ import 'package:aves/services/common/services.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
final Settings settings = Settings._private(); final Settings settings = Settings._private();
@ -202,6 +203,17 @@ class Settings extends ChangeNotifier {
].join(localeSeparator); ].join(localeSeparator);
} }
setAndNotify(localeKey, tag); setAndNotify(localeKey, tag);
_appliedLocale = null;
}
Locale? _appliedLocale;
Locale get appliedLocale {
if (_appliedLocale == null) {
final preferredLocale = locale;
_appliedLocale = basicLocaleListResolution(preferredLocale != null ? [preferredLocale] : null, AppLocalizations.supportedLocales);
}
return _appliedLocale!;
} }
bool get mustBackTwiceToExit => getBoolOrDefault(mustBackTwiceToExitKey, SettingsDefaults.mustBackTwiceToExit); bool get mustBackTwiceToExit => getBoolOrDefault(mustBackTwiceToExitKey, SettingsDefaults.mustBackTwiceToExit);

View file

@ -264,7 +264,7 @@ abstract class CollectionSource with SourceBase, AlbumMixin, LocationMixin, TagM
Future<Set<String>> refreshUris(Set<String> changedUris, {AnalysisController? analysisController}); Future<Set<String>> refreshUris(Set<String> changedUris, {AnalysisController? analysisController});
Future<void> refreshEntry(AvesEntry entry) async { Future<void> refreshEntry(AvesEntry entry) async {
await entry.refresh(background: false, persist: true, force: true); await entry.refresh(background: false, persist: true, force: true, geocoderLocale: settings.appliedLocale);
updateDerivedFilters({entry}); updateDerivedFilters({entry});
eventBus.fire(EntryRefreshedEvent({entry})); eventBus.fire(EntryRefreshedEvent({entry}));
} }

View file

@ -4,6 +4,7 @@ import 'package:aves/geo/countries.dart';
import 'package:aves/model/entry.dart'; import 'package:aves/model/entry.dart';
import 'package:aves/model/filters/location.dart'; import 'package:aves/model/filters/location.dart';
import 'package:aves/model/metadata/address.dart'; import 'package:aves/model/metadata/address.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/model/source/analysis_controller.dart'; import 'package:aves/model/source/analysis_controller.dart';
import 'package:aves/model/source/collection_source.dart'; import 'package:aves/model/source/collection_source.dart';
import 'package:aves/model/source/enums.dart'; import 'package:aves/model/source/enums.dart';
@ -110,7 +111,7 @@ mixin LocationMixin on SourceBase {
if (knownLocations.containsKey(latLng)) { if (knownLocations.containsKey(latLng)) {
entry.addressDetails = knownLocations[latLng]?.copyWith(contentId: entry.contentId); entry.addressDetails = knownLocations[latLng]?.copyWith(contentId: entry.contentId);
} else { } else {
await entry.locatePlace(background: true, force: force); await entry.locatePlace(background: true, force: force, geocoderLocale: settings.appliedLocale);
// it is intended to insert `null` if the geocoder failed, // it is intended to insert `null` if the geocoder failed,
// so that we skip geocoding of following entries with the same coordinates // so that we skip geocoding of following entries with the same coordinates
knownLocations[latLng] = entry.addressDetails; knownLocations[latLng] = entry.addressDetails;
@ -153,9 +154,15 @@ mixin LocationMixin on SourceBase {
// so we merge countries by code, keeping only one name for each code // so we merge countries by code, keeping only one name for each code
final countriesByCode = Map.fromEntries(locations.map((address) { final countriesByCode = Map.fromEntries(locations.map((address) {
final code = address.countryCode; final code = address.countryCode;
return code?.isNotEmpty == true ? MapEntry(code, address.countryName) : null; if (code == null || code.isEmpty) return null;
return MapEntry(code, address.countryName);
}).whereNotNull()); }).whereNotNull());
final updatedCountries = countriesByCode.entries.map((kv) => '${kv.value}${LocationFilter.locationSeparator}${kv.key}').toList()..sort(compareAsciiUpperCase); final updatedCountries = countriesByCode.entries.map((kv) {
final code = kv.key;
final name = kv.value;
return '${name != null && name.isNotEmpty ? name : code}${LocationFilter.locationSeparator}$code';
}).toList()
..sort(compareAsciiUpperCase);
if (!listEquals(updatedCountries, sortedCountries)) { if (!listEquals(updatedCountries, sortedCountries)) {
sortedCountries = List.unmodifiable(updatedCountries); sortedCountries = List.unmodifiable(updatedCountries);
invalidateCountryFilterSummary(); invalidateCountryFilterSummary();

View file

@ -98,9 +98,7 @@ class Analyzer {
debugPrint('$runtimeType start'); debugPrint('$runtimeType start');
_serviceStateNotifier.value = AnalyzerState.running; _serviceStateNotifier.value = AnalyzerState.running;
final preferredLocale = settings.locale; _l10n = await AppLocalizations.delegate.load(settings.appliedLocale);
final appLocale = basicLocaleListResolution(preferredLocale != null ? [preferredLocale] : null, AppLocalizations.supportedLocales);
_l10n = await AppLocalizations.delegate.load(appLocale);
_controller.stopSignal.value = false; _controller.stopSignal.value = false;
await _source.init(); await _source.init();

View file

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:ui';
import 'package:aves/services/common/services.dart'; import 'package:aves/services/common/services.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
@ -9,12 +10,12 @@ class GeocodingService {
static const platform = MethodChannel('deckers.thibault/aves/geocoding'); static const platform = MethodChannel('deckers.thibault/aves/geocoding');
// geocoding requires Google Play Services // geocoding requires Google Play Services
static Future<List<Address>> getAddress(LatLng coordinates, String locale) async { static Future<List<Address>> getAddress(LatLng coordinates, Locale locale) async {
try { try {
final result = await platform.invokeMethod('getAddress', <String, dynamic>{ final result = await platform.invokeMethod('getAddress', <String, dynamic>{
'latitude': coordinates.latitude, 'latitude': coordinates.latitude,
'longitude': coordinates.longitude, 'longitude': coordinates.longitude,
'locale': locale, 'locale': locale.toString(),
// we only really need one address, but sometimes the native geocoder // we only really need one address, but sometimes the native geocoder
// returns nothing with `maxResults` of 1, but succeeds with `maxResults` of 2+ // returns nothing with `maxResults` of 1, but succeeds with `maxResults` of 2+
'maxResults': 2, 'maxResults': 2,

View file

@ -147,7 +147,7 @@ class _AddressRowState extends State<_AddressRow> {
Future<String?> _getAddressLine(AvesEntry? entry) async { Future<String?> _getAddressLine(AvesEntry? entry) async {
if (entry != null && await availability.canLocatePlaces) { if (entry != null && await availability.canLocatePlaces) {
final addresses = await GeocodingService.getAddress(entry.latLng!, entry.geocoderLocale); final addresses = await GeocodingService.getAddress(entry.latLng!, settings.appliedLocale);
if (addresses.isNotEmpty) { if (addresses.isNotEmpty) {
final address = addresses.first; final address = addresses.first;
return address.addressLine; return address.addressLine;

View file

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:aves/model/entry.dart'; import 'package:aves/model/entry.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/theme/durations.dart'; import 'package:aves/theme/durations.dart';
import 'package:aves/widgets/common/magnifier/pan/scroll_physics.dart'; import 'package:aves/widgets/common/magnifier/pan/scroll_physics.dart';
@ -169,7 +170,7 @@ class _ViewerVerticalPageViewState extends State<ViewerVerticalPageView> {
// so that we can display the address instead of coordinates // so that we can display the address instead of coordinates
// even when initial collection locating has not reached this entry yet // even when initial collection locating has not reached this entry yet
await _entry.catalog(background: false, persist: true, force: false); await _entry.catalog(background: false, persist: true, force: false);
await _entry.locate(background: false, force: false); await _entry.locate(background: false, force: false, geocoderLocale: settings.appliedLocale);
} else { } else {
Navigator.pop(context); Navigator.pop(context);
} }

View file

@ -3,6 +3,7 @@ import 'package:aves/model/actions/entry_info_actions.dart';
import 'package:aves/model/entry.dart'; import 'package:aves/model/entry.dart';
import 'package:aves/model/metadata/date_modifier.dart'; import 'package:aves/model/metadata/date_modifier.dart';
import 'package:aves/model/metadata/enums.dart'; import 'package:aves/model/metadata/enums.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/model/source/collection_source.dart'; import 'package:aves/model/source/collection_source.dart';
import 'package:aves/widgets/common/action_mixins/feedback.dart'; import 'package:aves/widgets/common/action_mixins/feedback.dart';
import 'package:aves/widgets/common/action_mixins/permission_aware.dart'; import 'package:aves/widgets/common/action_mixins/permission_aware.dart';
@ -42,7 +43,7 @@ class EntryInfoActionDelegate with FeedbackMixin, PermissionAwareMixin {
if (_isMainMode(context) && source != null) { if (_isMainMode(context) && source != null) {
await source.refreshEntry(entry); await source.refreshEntry(entry);
} else { } else {
await entry.refresh(background: false, persist: false, force: true); await entry.refresh(background: false, persist: false, force: true, geocoderLocale: settings.appliedLocale);
} }
showFeedback(context, l10n.genericSuccessFeedback); showFeedback(context, l10n.genericSuccessFeedback);
} else { } else {

View file

@ -158,7 +158,7 @@ class _AddressInfoGroupState extends State<_AddressInfoGroup> {
super.initState(); super.initState();
_addressLineLoader = availability.canLocatePlaces.then((connected) { _addressLineLoader = availability.canLocatePlaces.then((connected) {
if (connected) { if (connected) {
return entry.findAddressLine(); return entry.findAddressLine(geocoderLocale: settings.appliedLocale);
} }
return null; return null;
}); });