From 831dc90b10a7dc14d1765c4f842419acbbf17f0c Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Tue, 21 Dec 2021 17:25:53 +0900 Subject: [PATCH] fixed locale setup in scan service --- .../aves/channel/calls/DeviceHandler.kt | 29 +++++++++++++++++++ lib/l10n/app_de.arb | 6 ++-- lib/model/settings/settings.dart | 18 ++++++++++-- lib/services/analysis_service.dart | 1 + lib/services/device_service.dart | 24 +++++++++++++++ lib/widgets/aves_app.dart | 7 ++--- lib/widgets/debug/settings.dart | 2 +- 7 files changed, 76 insertions(+), 11 deletions(-) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt index a4dcd071f..407686da2 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DeviceHandler.kt @@ -1,9 +1,11 @@ package deckers.thibault.aves.channel.calls import android.content.Context +import android.content.res.Resources import android.os.Build import androidx.core.content.pm.ShortcutManagerCompat import deckers.thibault.aves.channel.calls.Coresult.Companion.safe +import deckers.thibault.aves.model.FieldMap import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler @@ -14,6 +16,7 @@ class DeviceHandler(private val context: Context) : MethodCallHandler { when (call.method) { "getCapabilities" -> safe(call, result, ::getCapabilities) "getDefaultTimeZone" -> safe(call, result, ::getDefaultTimeZone) + "getLocales" -> safe(call, result, ::getLocales) "getPerformanceClass" -> safe(call, result, ::getPerformanceClass) else -> result.notImplemented() } @@ -41,6 +44,32 @@ class DeviceHandler(private val context: Context) : MethodCallHandler { result.success(TimeZone.getDefault().id) } + private fun getLocales(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) { + fun toMap(locale: Locale): FieldMap { + val fields: HashMap = hashMapOf( + "language" to locale.language, + "country" to locale.country, + ) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + fields["script"] = locale.script + } + return fields + } + + val locales = ArrayList() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + // when called from a window-less service, locales from `context.resources` + // do not reflect the current system settings, so we use `Resources.getSystem()` instead + val list = Resources.getSystem().configuration.locales + for (i in 0 until list.size()) { + locales.add(toMap(list.get(i))) + } + } else { + locales.add(toMap(Locale.getDefault())) + } + result.success(locales) + } + private fun getPerformanceClass(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { val performanceClass = Build.VERSION.MEDIA_PERFORMANCE_CLASS diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 25f1b9618..9ca46163b 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -249,9 +249,9 @@ "drawerCollectionPanoramas": "Panoramen", "drawerCollectionRaws": "Rohdaten Fotos", "drawerCollectionSphericalVideos": "360°-Videos", - "chipSortDate": "nach Datum", - "chipSortName": "nach Name", - "chipSortCount": "nach Anzahl", + "chipSortDate": "Nach Datum", + "chipSortName": "Nach Name", + "chipSortCount": "Nach Anzahl", "albumGroupTier": "Nach Ebene", "albumGroupVolume": "Nach Speichervolumen", "albumGroupNone": "Nicht gruppieren", diff --git a/lib/model/settings/settings.dart b/lib/model/settings/settings.dart index 308e20127..f76a97765 100644 --- a/lib/model/settings/settings.dart +++ b/lib/model/settings/settings.dart @@ -217,12 +217,26 @@ class Settings extends ChangeNotifier { _appliedLocale = null; } + List _systemLocalesFallback = []; + + set systemLocalesFallback(List locales) => _systemLocalesFallback = locales; + Locale? _appliedLocale; Locale get appliedLocale { if (_appliedLocale == null) { - final preferredLocale = locale; - _appliedLocale = basicLocaleListResolution(preferredLocale != null ? [preferredLocale] : null, AppLocalizations.supportedLocales); + final _locale = locale; + final preferredLocales = []; + if (_locale != null) { + preferredLocales.add(_locale); + } else { + preferredLocales.addAll(WidgetsBinding.instance!.window.locales); + if (preferredLocales.isEmpty) { + // the `window` locales may be empty in a window-less service context + preferredLocales.addAll(_systemLocalesFallback); + } + } + _appliedLocale = basicLocaleListResolution(preferredLocales, AppLocalizations.supportedLocales); } return _appliedLocale!; } diff --git a/lib/services/analysis_service.dart b/lib/services/analysis_service.dart index 746b47785..89d52983f 100644 --- a/lib/services/analysis_service.dart +++ b/lib/services/analysis_service.dart @@ -112,6 +112,7 @@ class Analyzer { stopSignal: ValueNotifier(false), ); + settings.systemLocalesFallback = await deviceService.getLocales(); _l10n = await AppLocalizations.delegate.load(settings.appliedLocale); _serviceStateNotifier.value = AnalyzerState.running; await _source.init(); diff --git a/lib/services/device_service.dart b/lib/services/device_service.dart index 1f08e9baf..88cc22522 100644 --- a/lib/services/device_service.dart +++ b/lib/services/device_service.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import 'package:aves/services/common/services.dart'; import 'package:flutter/services.dart'; @@ -6,6 +8,8 @@ abstract class DeviceService { Future getDefaultTimeZone(); + Future> getLocales(); + Future getPerformanceClass(); } @@ -33,6 +37,26 @@ class PlatformDeviceService implements DeviceService { return null; } + @override + Future> getLocales() async { + try { + final result = await platform.invokeMethod('getLocales'); + if (result != null) { + return (result as List).cast().map((tags) { + final language = tags['language'] as String?; + final country = tags['country'] as String?; + return Locale( + language ?? 'und', + (country != null && country.isEmpty) ? null : country, + ); + }).toList(); + } + } on PlatformException catch (e, stack) { + await reportService.recordError(e, stack); + } + return []; + } + @override Future getPerformanceClass() async { try { diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index 9cf82ac01..80c6846b0 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:ui'; import 'package:aves/app_flavor.dart'; import 'package:aves/app_mode.dart'; @@ -122,9 +121,7 @@ class _AvesAppState extends State { darkTheme: Themes.darkTheme, themeMode: ThemeMode.dark, locale: settingsLocale, - localizationsDelegates: const [ - ...AppLocalizations.localizationsDelegates, - ], + localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, // checkerboardRasterCacheImages: true, // checkerboardOffscreenLayers: true, @@ -200,7 +197,7 @@ class _AvesAppState extends State { ? 'profile' : 'debug', 'has_play_services': hasPlayServices, - 'locales': window.locales.join(', '), + 'locales': WidgetsBinding.instance!.window.locales.join(', '), 'time_zone': '${now.timeZoneName} (${now.timeZoneOffset})', }); _navigatorObservers = [ diff --git a/lib/widgets/debug/settings.dart b/lib/widgets/debug/settings.dart index 3f2231faa..b3461bea8 100644 --- a/lib/widgets/debug/settings.dart +++ b/lib/widgets/debug/settings.dart @@ -68,7 +68,7 @@ class DebugSettingsSection extends StatelessWidget { 'searchHistory': toMultiline(settings.searchHistory), 'lastVersionCheckDate': '${settings.lastVersionCheckDate}', 'locale': '${settings.locale}', - 'systemLocale': '${WidgetsBinding.instance!.window.locale}', + 'systemLocales': '${WidgetsBinding.instance!.window.locales}', }, ), ),