From 2f5e959fb01ae9554f606a1e645205ba67b86c06 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Thu, 21 Nov 2024 23:47:39 +0100 Subject: [PATCH 01/12] integrate with OS app language settings on Android >=14 --- CHANGELOG.md | 4 ++++ .../aves/channel/calls/DeviceHandler.kt | 19 +++++++++++++++++++ lib/services/device_service.dart | 13 +++++++++++++ lib/widgets/aves_app.dart | 1 + 4 files changed, 37 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 741cb66d8..32a801e41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- integrate with OS app language settings on Android >=14 + ## [v1.11.18] - 2024-11-18 ### Changed 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 3fe35ae01..47cb4a572 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,11 +1,14 @@ package deckers.thibault.aves.channel.calls +import android.app.LocaleConfig +import android.app.LocaleManager import android.content.Context import android.content.Intent import android.content.res.Resources import android.location.Geocoder import android.net.Uri import android.os.Build +import android.os.LocaleList import android.provider.MediaStore import android.provider.Settings import androidx.core.content.pm.ShortcutManagerCompat @@ -32,6 +35,7 @@ class DeviceHandler(private val context: Context) : MethodCallHandler { "getCapabilities" -> defaultScope.launch { safe(call, result, ::getCapabilities) } "getDefaultTimeZoneRawOffsetMillis" -> safe(call, result, ::getDefaultTimeZoneRawOffsetMillis) "getLocales" -> safe(call, result, ::getLocales) + "setLocaleConfig" -> safe(call, result, ::setLocaleConfig) "getPerformanceClass" -> safe(call, result, ::getPerformanceClass) "isLocked" -> safe(call, result, ::isLocked) "isSystemFilePickerEnabled" -> safe(call, result, ::isSystemFilePickerEnabled) @@ -88,6 +92,21 @@ class DeviceHandler(private val context: Context) : MethodCallHandler { result.success(locales) } + private fun setLocaleConfig(call: MethodCall, result: MethodChannel.Result) { + val locales = call.argument>("locales") + if (locales.isNullOrEmpty()) { + result.error("setLocaleConfig-args", "missing arguments", null) + return + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + val lm = context.getSystemService(Context.LOCALE_SERVICE) as? LocaleManager + lm?.overrideLocaleConfig = LocaleConfig(LocaleList.forLanguageTags(locales.joinToString(","))) + } + + result.success(true) + } + 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/services/device_service.dart b/lib/services/device_service.dart index 0eac24328..ad702490d 100644 --- a/lib/services/device_service.dart +++ b/lib/services/device_service.dart @@ -12,6 +12,8 @@ abstract class DeviceService { Future> getLocales(); + Future setLocaleConfig(List locales); + Future getPerformanceClass(); Future isLocked(); @@ -80,6 +82,17 @@ class PlatformDeviceService implements DeviceService { return []; } + @override + Future setLocaleConfig(List locales) async { + try { + await _platform.invokeMethod('setLocaleConfig', { + 'locales': locales.map((v) => v.toLanguageTag()).toList(), + }); + } on PlatformException catch (e, stack) { + await reportService.recordError(e, stack); + } + } + @override Future getPerformanceClass() async { try { diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index e75829d11..cc1179ffd 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -502,6 +502,7 @@ class _AvesAppState extends State with WidgetsBindingObserver { _monitorSettings(); videoControllerFactory.init(); + unawaited(deviceService.setLocaleConfig(AvesApp.supportedLocales)); unawaited(storageService.deleteTempDirectory()); unawaited(_setupErrorReporting()); From 1f679ec11cf7f03443831b5223273b8db5524426 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Nov 2024 07:47:57 +0900 Subject: [PATCH 02/12] Bump step-security/harden-runner from 2.10.1 to 2.10.2 (#1306) Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.10.1 to 2.10.2. - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/91182cccc01eb5e619899d80e4e971d6181294a7...0080882f6c36860b6ba35c610c98ce87d4e2f26f) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- .github/workflows/quality-check.yml | 4 ++-- .github/workflows/release.yml | 4 ++-- .github/workflows/scorecards.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 955b3b3fb..7c997cfd1 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 with: egress-policy: audit diff --git a/.github/workflows/quality-check.yml b/.github/workflows/quality-check.yml index 4051df96a..31c51e875 100644 --- a/.github/workflows/quality-check.yml +++ b/.github/workflows/quality-check.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 with: egress-policy: audit @@ -52,7 +52,7 @@ jobs: build-mode: manual steps: - name: Harden Runner - uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 with: egress-policy: audit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 17147aa87..e82037478 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: id-token: write steps: - name: Harden Runner - uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 with: egress-policy: audit @@ -98,7 +98,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 with: egress-policy: audit diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index a2291978f..0fe567907 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 with: egress-policy: audit From b50c3052041286be76e5245eb6697285f7ec1c12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Nov 2024 07:48:09 +0900 Subject: [PATCH 03/12] Bump github/codeql-action from 3.27.4 to 3.27.5 (#1308) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.4 to 3.27.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/ea9e4e37992a54ee68a9622e985e60c8e8f12d9f...f09c1c0a94de965c15400f5634aa42fac8fb8f88) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/quality-check.yml | 4 ++-- .github/workflows/scorecards.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/quality-check.yml b/.github/workflows/quality-check.yml index 31c51e875..6f573c642 100644 --- a/.github/workflows/quality-check.yml +++ b/.github/workflows/quality-check.yml @@ -69,7 +69,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4 + uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -83,6 +83,6 @@ jobs: ./flutterw build apk --profile -t lib/main_play.dart --flavor play - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4 + uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 0fe567907..781659b9f 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -71,6 +71,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4 + uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5 with: sarif_file: results.sarif From 66f0e2b1e9c688f7cad4aa65d19a9d2190746cb3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Nov 2024 07:48:17 +0900 Subject: [PATCH 04/12] Bump actions/dependency-review-action from 4.4.0 to 4.5.0 (#1310) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.4.0 to 4.5.0. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/4081bf99e2866ebe428fc0477b69eb4fcda7220a...3b139cfc5fae8b618d3eae3675e383bb1769c019) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 7c997cfd1..21a469b13 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -24,4 +24,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: 'Dependency Review' - uses: actions/dependency-review-action@4081bf99e2866ebe428fc0477b69eb4fcda7220a # v4.4.0 + uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 From ec7e4ac2f20a22c7456c48839c2abb48735e8de8 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sat, 23 Nov 2024 22:33:01 +0100 Subject: [PATCH 05/12] simplified time zone offset check --- .../thibault/aves/channel/calls/DeviceHandler.kt | 5 ----- lib/model/settings/modules/app.dart | 4 ++-- lib/model/source/media_store_source.dart | 16 +++++++--------- lib/services/device_service.dart | 12 ------------ lib/widgets/debug/settings.dart | 2 +- plugins/aves_model/lib/src/settings/keys.dart | 4 ++-- test/fake/device_service.dart | 3 --- 7 files changed, 12 insertions(+), 34 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 47cb4a572..15cd66c86 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 @@ -33,7 +33,6 @@ class DeviceHandler(private val context: Context) : MethodCallHandler { when (call.method) { "canManageMedia" -> safe(call, result, ::canManageMedia) "getCapabilities" -> defaultScope.launch { safe(call, result, ::getCapabilities) } - "getDefaultTimeZoneRawOffsetMillis" -> safe(call, result, ::getDefaultTimeZoneRawOffsetMillis) "getLocales" -> safe(call, result, ::getLocales) "setLocaleConfig" -> safe(call, result, ::setLocaleConfig) "getPerformanceClass" -> safe(call, result, ::getPerformanceClass) @@ -67,10 +66,6 @@ class DeviceHandler(private val context: Context) : MethodCallHandler { ) } - private fun getDefaultTimeZoneRawOffsetMillis(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) { - result.success(TimeZone.getDefault().rawOffset) - } - private fun getLocales(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) { fun toMap(locale: Locale): FieldMap = hashMapOf( "language" to locale.language, diff --git a/lib/model/settings/modules/app.dart b/lib/model/settings/modules/app.dart index 2b9caa141..4c3538be5 100644 --- a/lib/model/settings/modules/app.dart +++ b/lib/model/settings/modules/app.dart @@ -87,9 +87,9 @@ mixin AppSettings on SettingsAccess { set forceWesternArabicNumerals(bool newValue) => set(SettingKeys.forceWesternArabicNumeralsKey, newValue); - int get catalogTimeZoneRawOffsetMillis => getInt(SettingKeys.catalogTimeZoneRawOffsetMillisKey) ?? 0; + int get catalogTimeZoneOffsetMillis => getInt(SettingKeys.catalogTimeZoneOffsetMillisKey) ?? 0; - set catalogTimeZoneRawOffsetMillis(int newValue) => set(SettingKeys.catalogTimeZoneRawOffsetMillisKey, newValue); + set catalogTimeZoneOffsetMillis(int newValue) => set(SettingKeys.catalogTimeZoneOffsetMillisKey, newValue); double getTileExtent(String routeName) => getDouble(SettingKeys.tileExtentPrefixKey + routeName) ?? 0; diff --git a/lib/model/source/media_store_source.dart b/lib/model/source/media_store_source.dart index c2a85e28f..f9affcfb7 100644 --- a/lib/model/source/media_store_source.dart +++ b/lib/model/source/media_store_source.dart @@ -59,15 +59,13 @@ class MediaStoreSource extends CollectionSource { await vaults.init(); await favourites.init(); await covers.init(); - final currentTimeZoneOffset = await deviceService.getDefaultTimeZoneRawOffsetMillis(); - if (currentTimeZoneOffset != null) { - final catalogTimeZoneOffset = settings.catalogTimeZoneRawOffsetMillis; - if (currentTimeZoneOffset != catalogTimeZoneOffset) { - unawaited(reportService.recordError('Time zone offset change: $currentTimeZoneOffset -> $catalogTimeZoneOffset. Clear catalog metadata to get correct date/times.', null)); - await localMediaDb.clearDates(); - await localMediaDb.clearCatalogMetadata(); - settings.catalogTimeZoneRawOffsetMillis = currentTimeZoneOffset; - } + final currentTimeZoneOffset = DateTime.now().timeZoneOffset.inMilliseconds; + final catalogTimeZoneOffset = settings.catalogTimeZoneOffsetMillis; + if (currentTimeZoneOffset != catalogTimeZoneOffset) { + unawaited(reportService.recordError('Time zone offset change: $currentTimeZoneOffset -> $catalogTimeZoneOffset. Clear catalog metadata to get correct date/times.', null)); + await localMediaDb.clearDates(); + await localMediaDb.clearCatalogMetadata(); + settings.catalogTimeZoneOffsetMillis = currentTimeZoneOffset; } await loadDates(); debugPrint('$runtimeType load essentials complete in ${stopwatch.elapsed.inMilliseconds}ms'); diff --git a/lib/services/device_service.dart b/lib/services/device_service.dart index ad702490d..eeceda1fc 100644 --- a/lib/services/device_service.dart +++ b/lib/services/device_service.dart @@ -8,8 +8,6 @@ abstract class DeviceService { Future> getCapabilities(); - Future getDefaultTimeZoneRawOffsetMillis(); - Future> getLocales(); Future setLocaleConfig(List locales); @@ -52,16 +50,6 @@ class PlatformDeviceService implements DeviceService { return {}; } - @override - Future getDefaultTimeZoneRawOffsetMillis() async { - try { - return await _platform.invokeMethod('getDefaultTimeZoneRawOffsetMillis'); - } on PlatformException catch (e, stack) { - await reportService.recordError(e, stack); - } - return null; - } - @override Future> getLocales() async { try { diff --git a/lib/widgets/debug/settings.dart b/lib/widgets/debug/settings.dart index 262b89a22..b8976059a 100644 --- a/lib/widgets/debug/settings.dart +++ b/lib/widgets/debug/settings.dart @@ -55,7 +55,7 @@ class _DebugSettingsSectionState extends State with Automa padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8), child: InfoRowGroup( info: { - 'catalogTimeZoneRawOffsetMillis': '${settings.catalogTimeZoneRawOffsetMillis}', + 'catalogTimeZoneRawOffsetMillis': '${settings.catalogTimeZoneOffsetMillis}', 'tileExtent - Collection': '${settings.getTileExtent(CollectionPage.routeName)}', 'tileExtent - Albums': '${settings.getTileExtent(AlbumListPage.routeName)}', 'tileExtent - Countries': '${settings.getTileExtent(CountryListPage.routeName)}', diff --git a/plugins/aves_model/lib/src/settings/keys.dart b/plugins/aves_model/lib/src/settings/keys.dart index 19be577ed..6efba4aa1 100644 --- a/plugins/aves_model/lib/src/settings/keys.dart +++ b/plugins/aves_model/lib/src/settings/keys.dart @@ -3,7 +3,7 @@ class SettingKeys { static const Set _internalKeys = { hasAcceptedTermsKey, - catalogTimeZoneRawOffsetMillisKey, + catalogTimeZoneOffsetMillisKey, searchHistoryKey, platformAccelerometerRotationKey, platformTransitionAnimationScaleKey, @@ -21,7 +21,7 @@ class SettingKeys { static const isErrorReportingAllowedKey = 'is_crashlytics_enabled'; static const localeKey = 'locale'; static const forceWesternArabicNumeralsKey = 'force_western_arabic_numerals'; - static const catalogTimeZoneRawOffsetMillisKey = 'catalog_time_zone_raw_offset_millis'; + static const catalogTimeZoneOffsetMillisKey = 'catalog_time_zone_raw_offset_millis'; static const tileExtentPrefixKey = 'tile_extent_'; static const tileLayoutPrefixKey = 'tile_layout_'; static const entryRenamingPatternKey = 'entry_renaming_pattern'; diff --git a/test/fake/device_service.dart b/test/fake/device_service.dart index 82f81f5c3..07705e24d 100644 --- a/test/fake/device_service.dart +++ b/test/fake/device_service.dart @@ -3,9 +3,6 @@ import 'package:flutter/foundation.dart'; import 'package:test/fake.dart'; class FakeDeviceService extends Fake implements DeviceService { - @override - Future getDefaultTimeZoneRawOffsetMillis() => SynchronousFuture(3600000); - @override Future getAvailableHeapSize() => SynchronousFuture(0x7fffffff); From ffbf0bd8f278f8fe307c8dda222b400da6db120d Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sat, 23 Nov 2024 23:24:41 +0100 Subject: [PATCH 06/12] improved error reporting --- lib/model/entry/extensions/metadata_edition.dart | 4 ++-- lib/model/media/video/metadata.dart | 4 ++-- lib/model/source/media_store_source.dart | 6 +++--- lib/model/source/trash.dart | 2 +- lib/model/vaults/vaults.dart | 2 +- lib/services/metadata/metadata_edit_service.dart | 10 +++------- lib/widgets/aves_app.dart | 2 +- lib/widgets/viewer/action/single_entry_editor.dart | 4 ++-- lib/widgets/viewer/controls/cast.dart | 4 ++-- plugins/aves_report/lib/aves_report.dart | 2 +- .../aves_report_console/lib/aves_report_platform.dart | 2 +- .../lib/aves_report_platform.dart | 4 +++- plugins/aves_report_crashlytics/pubspec.lock | 2 +- plugins/aves_report_crashlytics/pubspec.yaml | 1 + test/fake/report_service.dart | 2 +- 15 files changed, 25 insertions(+), 26 deletions(-) diff --git a/lib/model/entry/extensions/metadata_edition.dart b/lib/model/entry/extensions/metadata_edition.dart index 6ad3b2dce..5e4228279 100644 --- a/lib/model/entry/extensions/metadata_edition.dart +++ b/lib/model/entry/extensions/metadata_edition.dart @@ -32,7 +32,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { final appliedModifier = await _applyDateModifierToEntry(userModifier); if (appliedModifier == null) { if (isValid && userModifier.action != DateEditAction.copyField) { - await reportService.recordError('failed to get date for modifier=$userModifier, entry=$this', null); + await reportService.recordError('failed to get date for modifier=$userModifier, entry=$this'); } return {}; } @@ -65,7 +65,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { final shiftedDate = date.add(Duration(seconds: appliedModifier.shiftSeconds!)); editCreateDateXmp(descriptions, shiftedDate); } else { - reportService.recordError('failed to parse XMP date=$xmpDate', null); + reportService.recordError('failed to parse XMP date=$xmpDate'); } } case DateEditAction.remove: diff --git a/lib/model/media/video/metadata.dart b/lib/model/media/video/metadata.dart index 3349e202f..972f227ba 100644 --- a/lib/model/media/video/metadata.dart +++ b/lib/model/media/video/metadata.dart @@ -1,12 +1,12 @@ import 'dart:async'; import 'package:aves/model/entry/entry.dart'; -import 'package:aves/model/metadata/catalog.dart'; import 'package:aves/model/media/video/channel_layouts.dart'; import 'package:aves/model/media/video/codecs.dart'; import 'package:aves/model/media/video/profiles/aac.dart'; import 'package:aves/model/media/video/profiles/h264.dart'; import 'package:aves/model/media/video/profiles/hevc.dart'; +import 'package:aves/model/metadata/catalog.dart'; import 'package:aves/ref/languages.dart'; import 'package:aves/ref/locales.dart'; import 'package:aves/ref/mime_types.dart'; @@ -99,7 +99,7 @@ class VideoMetadataFormatter { if (isDefined(dateString)) { dateMillis = parseVideoDate(dateString); if (dateMillis == null && !isAmbiguousDate(dateString)) { - await reportService.recordError('getCatalogMetadata failed to parse date=$dateString for mimeType=${entry.mimeType} entry=$entry', null); + await reportService.recordError('getCatalogMetadata failed to parse date=$dateString for mimeType=${entry.mimeType} entry=$entry'); } } diff --git a/lib/model/source/media_store_source.dart b/lib/model/source/media_store_source.dart index f9affcfb7..9f01ef478 100644 --- a/lib/model/source/media_store_source.dart +++ b/lib/model/source/media_store_source.dart @@ -62,7 +62,7 @@ class MediaStoreSource extends CollectionSource { final currentTimeZoneOffset = DateTime.now().timeZoneOffset.inMilliseconds; final catalogTimeZoneOffset = settings.catalogTimeZoneOffsetMillis; if (currentTimeZoneOffset != catalogTimeZoneOffset) { - unawaited(reportService.recordError('Time zone offset change: $currentTimeZoneOffset -> $catalogTimeZoneOffset. Clear catalog metadata to get correct date/times.', null)); + unawaited(reportService.recordError('Time zone offset change: $currentTimeZoneOffset -> $catalogTimeZoneOffset. Clear catalog metadata to get correct date/times.')); await localMediaDb.clearDates(); await localMediaDb.clearCatalogMetadata(); settings.catalogTimeZoneOffsetMillis = currentTimeZoneOffset; @@ -212,7 +212,7 @@ class MediaStoreSource extends CollectionSource { // TODO TLAD find duplication cause final duplicates = await localMediaDb.searchLiveDuplicates(EntryOrigins.mediaStoreContent, newEntries); if (duplicates.isNotEmpty) { - unawaited(reportService.recordError(Exception('Loading entries yielded duplicates=${duplicates.join(', ')}'), StackTrace.current)); + unawaited(reportService.recordError(Exception('Loading entries yielded duplicates=${duplicates.join(', ')}'))); // post-error cleanup await localMediaDb.removeIds(duplicates.map((v) => v.id).toSet()); for (final duplicate in duplicates) { @@ -325,7 +325,7 @@ class MediaStoreSource extends CollectionSource { // TODO TLAD find duplication cause final duplicates = await localMediaDb.searchLiveDuplicates(EntryOrigins.mediaStoreContent, newEntries); if (duplicates.isNotEmpty) { - unawaited(reportService.recordError(Exception('Refreshing entries yielded duplicates=${duplicates.join(', ')}'), StackTrace.current)); + unawaited(reportService.recordError(Exception('Refreshing entries yielded duplicates=${duplicates.join(', ')}'))); // post-error cleanup await localMediaDb.removeIds(duplicates.map((v) => v.id).toSet()); for (final duplicate in duplicates) { diff --git a/lib/model/source/trash.dart b/lib/model/source/trash.dart index f3107cbf5..6afbce6be 100644 --- a/lib/model/source/trash.dart +++ b/lib/model/source/trash.dart @@ -76,7 +76,7 @@ mixin TrashMixin on SourceBase { sourceEntry.trashDetails = _buildTrashDetails(id); newEntries.add(sourceEntry); } else { - await reportService.recordError('Failed to recover untracked bin item at uri=$uri', null); + await reportService.recordError('Failed to recover untracked bin item at uri=$uri'); } } }); diff --git a/lib/model/vaults/vaults.dart b/lib/model/vaults/vaults.dart index a621c2952..7f80c563a 100644 --- a/lib/model/vaults/vaults.dart +++ b/lib/model/vaults/vaults.dart @@ -175,7 +175,7 @@ class Vaults extends ChangeNotifier { sourceEntry.origin = EntryOrigins.vault; newEntries.add(sourceEntry); } else { - await reportService.recordError('Failed to recover untracked vault item at uri=$uri', null); + await reportService.recordError('Failed to recover untracked vault item at uri=$uri'); } }); } diff --git a/lib/services/metadata/metadata_edit_service.dart b/lib/services/metadata/metadata_edit_service.dart index 7317e55e8..611b4cbc1 100644 --- a/lib/services/metadata/metadata_edit_service.dart +++ b/lib/services/metadata/metadata_edit_service.dart @@ -6,10 +6,8 @@ import 'package:aves/model/entry/extensions/props.dart'; import 'package:aves/model/metadata/date_modifier.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves_model/aves_model.dart'; -import 'package:aves_report/aves_report.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; -import 'package:stack_trace/stack_trace.dart'; abstract class MetadataEditService { Future> rotate(AvesEntry entry, {required bool clockwise}); @@ -135,24 +133,22 @@ class PlatformMetadataEditService implements MetadataEditService { } } - StackTrace? _currentStack() => ReportService.buildReportStack(Trace.current(), level: 1); - // distinct exceptions to convince Crashlytics to split reports into distinct issues // The distinct debug statement is there to make the body unique, so that the methods are not merged at compile time. Future mp4LargeMoov(CustomPlatformException e) { debugPrint('mp4LargeMoov $e'); - return reportService.recordError(e, _currentStack()); + return reportService.recordError(e); } Future mp4LargeOther(CustomPlatformException e) { debugPrint('mp4LargeOther $e'); - return reportService.recordError(e, _currentStack()); + return reportService.recordError(e); } Future fileNotFound(CustomPlatformException e) { debugPrint('fileNotFound $e'); - return reportService.recordError(e, _currentStack()); + return reportService.recordError(e); } } diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index cc1179ffd..7eedcdc33 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -693,7 +693,7 @@ class _AvesAppState extends State with WidgetsBindingObserver { _mediaStoreSource.updateDerivedFilters(); } - void _onError(String? error) => reportService.recordError(error, null); + void _onError(String? error) => reportService.recordError(error); void _onAppModeChanged() { final appMode = _appModeNotifier.value; diff --git a/lib/widgets/viewer/action/single_entry_editor.dart b/lib/widgets/viewer/action/single_entry_editor.dart index 85acb841f..46adba957 100644 --- a/lib/widgets/viewer/action/single_entry_editor.dart +++ b/lib/widgets/viewer/action/single_entry_editor.dart @@ -61,8 +61,8 @@ mixin SingleEntryEditorMixin on FeedbackMixin, PermissionAwareMixin { } else { showFeedback(context, FeedbackType.warn, l10n.genericFailureFeedback); } - } catch (error, stack) { - await reportService.recordError(error, stack); + } catch (e, stack) { + await reportService.recordError(e, stack); } source?.resumeMonitoring(); } diff --git a/lib/widgets/viewer/controls/cast.dart b/lib/widgets/viewer/controls/cast.dart index 731712a59..377f8714d 100644 --- a/lib/widgets/viewer/controls/cast.dart +++ b/lib/widgets/viewer/controls/cast.dart @@ -96,8 +96,8 @@ mixin CastMixin { ); debugPrint('cast: play entry=$entry'); unawaited(renderer.play()); - } catch (error, stack) { - await reportService.recordError(error, stack); + } catch (e, stack) { + await reportService.recordError(e, stack); } } diff --git a/plugins/aves_report/lib/aves_report.dart b/plugins/aves_report/lib/aves_report.dart index 4d3a3fc5c..609252260 100644 --- a/plugins/aves_report/lib/aves_report.dart +++ b/plugins/aves_report/lib/aves_report.dart @@ -15,7 +15,7 @@ abstract class ReportService { Future setCustomKeys(Map map); - Future recordError(dynamic exception, StackTrace? stack); + Future recordError(dynamic exception, [StackTrace? stack]); Future recordFlutterError(FlutterErrorDetails flutterErrorDetails); diff --git a/plugins/aves_report_console/lib/aves_report_platform.dart b/plugins/aves_report_console/lib/aves_report_platform.dart index e57e70f85..dd1d461ea 100644 --- a/plugins/aves_report_console/lib/aves_report_platform.dart +++ b/plugins/aves_report_console/lib/aves_report_platform.dart @@ -9,7 +9,7 @@ class PlatformReportService extends ReportService { Future log(String message) async => debugPrint('Report log with message=$message'); @override - Future recordError(dynamic exception, StackTrace? stack) async => debugPrint('Report error with exception=$exception, stack=$stack'); + Future recordError(dynamic exception, [StackTrace? stack]) async => debugPrint('Report error with exception=$exception, stack=$stack'); @override Future recordFlutterError(FlutterErrorDetails flutterErrorDetails) async => debugPrint('Report Flutter error with details=$flutterErrorDetails'); diff --git a/plugins/aves_report_crashlytics/lib/aves_report_platform.dart b/plugins/aves_report_crashlytics/lib/aves_report_platform.dart index 1bcd7f567..05a7efbf6 100644 --- a/plugins/aves_report_crashlytics/lib/aves_report_platform.dart +++ b/plugins/aves_report_crashlytics/lib/aves_report_platform.dart @@ -5,6 +5,7 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import 'package:stack_trace/stack_trace.dart'; class PlatformReportService extends ReportService { FirebaseCrashlytics? get _instance { @@ -65,11 +66,12 @@ class PlatformReportService extends ReportService { } @override - Future recordError(dynamic exception, StackTrace? stack) async { + Future recordError(dynamic exception, [StackTrace? stack]) async { if (exception is PlatformException && stack != null) { stack = ReportService.buildReportStack(stack, level: 2); } if (exception is! UnreportedStateError) { + stack ??= ReportService.buildReportStack(Trace.current(), level: 1); return _instance?.recordError(exception, stack); } } diff --git a/plugins/aves_report_crashlytics/pubspec.lock b/plugins/aves_report_crashlytics/pubspec.lock index da24c1b41..91fcf4ed0 100644 --- a/plugins/aves_report_crashlytics/pubspec.lock +++ b/plugins/aves_report_crashlytics/pubspec.lock @@ -213,7 +213,7 @@ packages: source: hosted version: "1.10.0" stack_trace: - dependency: transitive + dependency: "direct main" description: name: stack_trace sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" diff --git a/plugins/aves_report_crashlytics/pubspec.yaml b/plugins/aves_report_crashlytics/pubspec.yaml index c94c91d59..5c04ca756 100644 --- a/plugins/aves_report_crashlytics/pubspec.yaml +++ b/plugins/aves_report_crashlytics/pubspec.yaml @@ -14,6 +14,7 @@ dependencies: # so that the transitive `path` gets upgraded to v1.8.3 firebase_core: ">=2.10.0" firebase_crashlytics: + stack_trace: dev_dependencies: flutter_lints: diff --git a/test/fake/report_service.dart b/test/fake/report_service.dart index 898c9462c..a7a8f99b2 100644 --- a/test/fake/report_service.dart +++ b/test/fake/report_service.dart @@ -21,7 +21,7 @@ class FakeReportService extends ReportService { Future setCustomKeys(Map map) => SynchronousFuture(null); @override - Future recordError(dynamic exception, StackTrace? stack) => SynchronousFuture(null); + Future recordError(dynamic exception, [StackTrace? stack]) => SynchronousFuture(null); @override Future recordFlutterError(FlutterErrorDetails flutterErrorDetails) => SynchronousFuture(null); From 5b6eb44c0516fe81649894397340a53a661ddab2 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sun, 24 Nov 2024 00:08:26 +0100 Subject: [PATCH 07/12] trim new tags --- lib/widgets/aves_app.dart | 7 ------- lib/widgets/dialogs/entry_editors/tag_editor_page.dart | 3 ++- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index 7eedcdc33..39620f813 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -423,13 +423,6 @@ class _AvesAppState extends State with WidgetsBindingObserver { } } - @override - void didHaveMemoryPressure() { - super.didHaveMemoryPressure(); - debugPrint('App memory pressure'); - imageCache.clear(); - } - @override void didChangeMetrics() => _updateCutoutInsets(); diff --git a/lib/widgets/dialogs/entry_editors/tag_editor_page.dart b/lib/widgets/dialogs/entry_editors/tag_editor_page.dart index 28e9c7159..c0f7b3bc1 100644 --- a/lib/widgets/dialogs/entry_editors/tag_editor_page.dart +++ b/lib/widgets/dialogs/entry_editors/tag_editor_page.dart @@ -152,7 +152,7 @@ class _TagEditorPageState extends State { builder: (context, value, child) { return IconButton( icon: const Icon(AIcons.add), - onPressed: value.text.isEmpty ? null : () => _addCustomTag(_newTagTextController.text), + onPressed: value.text.trim().isEmpty ? null : () => _addCustomTag(_newTagTextController.text), tooltip: l10n.tagEditorPageAddTagTooltip, ); }, @@ -296,6 +296,7 @@ class _TagEditorPageState extends State { } void _addCustomTag(String newTag) { + newTag = newTag.trim(); if (newTag.isNotEmpty) { _addTag(TagFilter(newTag)); } From a3024fdf4ee2a073389ffb1105213b19ad9b34e9 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sun, 24 Nov 2024 00:52:29 +0100 Subject: [PATCH 08/12] minor --- lib/widgets/collection/app_bar.dart | 2 +- lib/widgets/collection/collection_grid.dart | 4 ++-- lib/widgets/common/basic/tv_edge_focus.dart | 2 +- lib/widgets/common/behaviour/pop/double_back.dart | 2 +- lib/widgets/common/behaviour/pop/tv_navigation.dart | 2 +- lib/widgets/common/identity/aves_app_bar.dart | 2 +- lib/widgets/debug/app_debug_page.dart | 2 +- lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart | 2 +- lib/widgets/dialogs/pick_dialogs/album_pick_page.dart | 2 +- lib/widgets/explorer/app_bar.dart | 2 +- lib/widgets/filter_grids/common/app_bar.dart | 2 +- lib/widgets/filter_grids/common/filter_grid_page.dart | 2 +- lib/widgets/navigation/nav_bar/nav_bar.dart | 2 +- .../settings/privacy/file_picker/file_picker_page.dart | 2 +- lib/widgets/settings/settings_mobile_page.dart | 2 +- lib/widgets/settings/thumbnails/overlay.dart | 4 ++-- lib/widgets/viewer/info/info_app_bar.dart | 2 +- lib/widgets/viewer/overlay/viewer_buttons.dart | 2 +- 18 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/widgets/collection/app_bar.dart b/lib/widgets/collection/app_bar.dart index aae93bac0..e2f47293f 100644 --- a/lib/widgets/collection/app_bar.dart +++ b/lib/widgets/collection/app_bar.dart @@ -399,7 +399,7 @@ class _CollectionAppBarState extends State with SingleTickerPr (action) => _buildButtonIcon(context, action, enabled: canApply(action), selection: selection), ); - final animations = context.select((s) => s.accessibilityAnimations); + final animations = context.select((v) => v.accessibilityAnimations); return [ ...quickActionButtons, PopupMenuButton( diff --git a/lib/widgets/collection/collection_grid.dart b/lib/widgets/collection/collection_grid.dart index 874f9004a..7199fd7ad 100644 --- a/lib/widgets/collection/collection_grid.dart +++ b/lib/widgets/collection/collection_grid.dart @@ -88,7 +88,7 @@ class _CollectionGridState extends State { @override Widget build(BuildContext context) { - final spacing = context.select((s) => s.getTileLayout(settingsRouteKey) == TileLayout.mosaic ? CollectionGrid.mosaicLayoutSpacing : CollectionGrid.fixedExtentLayoutSpacing); + final spacing = context.select((v) => v.getTileLayout(settingsRouteKey) == TileLayout.mosaic ? CollectionGrid.mosaicLayoutSpacing : CollectionGrid.fixedExtentLayoutSpacing); if (_tileExtentController?.spacing != spacing) { _tileExtentController = TileExtentController( settingsRouteKey: settingsRouteKey, @@ -136,7 +136,7 @@ class _CollectionGridContentState extends State<_CollectionGridContent> { Widget build(BuildContext context) { final selectable = context.select, bool>((v) => v.value.canSelectMedia); final settingsRouteKey = context.read().settingsRouteKey; - final tileLayout = context.select((s) => s.getTileLayout(settingsRouteKey)); + final tileLayout = context.select((v) => v.getTileLayout(settingsRouteKey)); return Consumer( builder: (context, collection, child) { final sectionedListLayoutProvider = ValueListenableBuilder( diff --git a/lib/widgets/common/basic/tv_edge_focus.dart b/lib/widgets/common/basic/tv_edge_focus.dart index 9e624a030..190d047e6 100644 --- a/lib/widgets/common/basic/tv_edge_focus.dart +++ b/lib/widgets/common/basic/tv_edge_focus.dart @@ -14,7 +14,7 @@ class TvEdgeFocus extends StatelessWidget { @override Widget build(BuildContext context) { - final useTvLayout = context.select((s) => s.useTvLayout); + final useTvLayout = context.select((v) => v.useTvLayout); return useTvLayout ? Focus( focusNode: focusNode, diff --git a/lib/widgets/common/behaviour/pop/double_back.dart b/lib/widgets/common/behaviour/pop/double_back.dart index b5a2b3729..d73aa5661 100644 --- a/lib/widgets/common/behaviour/pop/double_back.dart +++ b/lib/widgets/common/behaviour/pop/double_back.dart @@ -20,7 +20,7 @@ class DoubleBackPopHandler extends PopHandler { @override bool canPop(BuildContext context) { - if (context.select((s) => !s.mustBackTwiceToExit)) return true; + if (context.select((v) => !v.mustBackTwiceToExit)) return true; if (Navigator.canPop(context)) return true; return false; } diff --git a/lib/widgets/common/behaviour/pop/tv_navigation.dart b/lib/widgets/common/behaviour/pop/tv_navigation.dart index b895aa917..720a397ae 100644 --- a/lib/widgets/common/behaviour/pop/tv_navigation.dart +++ b/lib/widgets/common/behaviour/pop/tv_navigation.dart @@ -20,7 +20,7 @@ class TvNavigationPopHandler implements PopHandler { @override bool canPop(BuildContext context) { - if (context.select((s) => !s.useTvLayout)) return true; + if (context.select((v) => !v.useTvLayout)) return true; if (_isHome(context)) return true; return false; } diff --git a/lib/widgets/common/identity/aves_app_bar.dart b/lib/widgets/common/identity/aves_app_bar.dart index f66653fc2..9089a2bc8 100644 --- a/lib/widgets/common/identity/aves_app_bar.dart +++ b/lib/widgets/common/identity/aves_app_bar.dart @@ -260,7 +260,7 @@ class _AvesFloatingBarState extends State with RouteAware { return ValueListenableBuilder( valueListenable: _isBlurAllowedNotifier, builder: (context, isBlurAllowed, child) { - final blurred = isBlurAllowed && context.select((s) => s.enableBlurEffect); + final blurred = isBlurAllowed && context.select((v) => v.enableBlurEffect); return Container( foregroundDecoration: BoxDecoration( border: Border.all( diff --git a/lib/widgets/debug/app_debug_page.dart b/lib/widgets/debug/app_debug_page.dart index 004d4193f..0eb919a7a 100644 --- a/lib/widgets/debug/app_debug_page.dart +++ b/lib/widgets/debug/app_debug_page.dart @@ -37,7 +37,7 @@ class AppDebugPage extends StatelessWidget { @override Widget build(BuildContext context) { - final animations = context.select((s) => s.accessibilityAnimations); + final animations = context.select((v) => v.accessibilityAnimations); return Directionality( textDirection: TextDirection.ltr, child: AvesScaffold( diff --git a/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart b/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart index b3962c5fc..85f1d8151 100644 --- a/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart +++ b/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart @@ -71,7 +71,7 @@ class _RenameEntrySetPageState extends State { final l10n = context.l10n; final textScaler = MediaQuery.textScalerOf(context); final effectiveThumbnailExtent = max(thumbnailExtent, textScaler.scale(thumbnailExtent)); - final animations = context.select((s) => s.accessibilityAnimations); + final animations = context.select((v) => v.accessibilityAnimations); return AvesScaffold( appBar: AppBar( title: Text(l10n.renameEntrySetPageTitle), diff --git a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart index 66fd7a2b4..12ca7aff4 100644 --- a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart +++ b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart @@ -211,7 +211,7 @@ class _AlbumPickPageState extends State<_AlbumPickPage> { required bool Function(ChipSetAction action) isVisible, required void Function(ChipSetAction action) onActionSelected, }) { - final animations = context.select((s) => s.accessibilityAnimations); + final animations = context.select((v) => v.accessibilityAnimations); return [ if (widget.moveType != null) ..._quickActions.where(isVisible).map( diff --git a/lib/widgets/explorer/app_bar.dart b/lib/widgets/explorer/app_bar.dart index 5a9985f1e..f4883915a 100644 --- a/lib/widgets/explorer/app_bar.dart +++ b/lib/widgets/explorer/app_bar.dart @@ -104,7 +104,7 @@ class _ExplorerAppBarState extends State with WidgetsBindingObse } List _buildActions(BuildContext context, double maxWidth) { - final animations = context.select((s) => s.accessibilityAnimations); + final animations = context.select((v) => v.accessibilityAnimations); return [ IconButton( icon: const Icon(AIcons.search), diff --git a/lib/widgets/filter_grids/common/app_bar.dart b/lib/widgets/filter_grids/common/app_bar.dart index d75dd86f6..07bb607f2 100644 --- a/lib/widgets/filter_grids/common/app_bar.dart +++ b/lib/widgets/filter_grids/common/app_bar.dart @@ -329,7 +329,7 @@ class _FilterGridAppBarState _buildButtonIcon(context, actionDelegate, action, enabled: canApply(action)), ); - final animations = context.select((s) => s.accessibilityAnimations); + final animations = context.select((v) => v.accessibilityAnimations); return [ ...quickActionButtons, PopupMenuButton( diff --git a/lib/widgets/filter_grids/common/filter_grid_page.dart b/lib/widgets/filter_grids/common/filter_grid_page.dart index 9323ceb05..19769884e 100644 --- a/lib/widgets/filter_grids/common/filter_grid_page.dart +++ b/lib/widgets/filter_grids/common/filter_grid_page.dart @@ -286,7 +286,7 @@ class _FilterGridContentState extends State<_FilterG Widget build(BuildContext context) { final source = context.read(); final settingsRouteKey = context.read().settingsRouteKey; - final tileLayout = context.select((s) => s.getTileLayout(settingsRouteKey)); + final tileLayout = context.select((v) => v.getTileLayout(settingsRouteKey)); return Selector( selector: (context, query) => query.enabled, builder: (context, queryEnabled, child) { diff --git a/lib/widgets/navigation/nav_bar/nav_bar.dart b/lib/widgets/navigation/nav_bar/nav_bar.dart index 7e42b2fbe..87e9ea683 100644 --- a/lib/widgets/navigation/nav_bar/nav_bar.dart +++ b/lib/widgets/navigation/nav_bar/nav_bar.dart @@ -66,7 +66,7 @@ class _AppBottomNavBarState extends State { @override Widget build(BuildContext context) { - final showVideo = context.select((s) => !s.hiddenFilters.contains(MimeFilter.video)); + final showVideo = context.select((v) => !v.hiddenFilters.contains(MimeFilter.video)); final items = [ const AvesBottomNavItem(route: CollectionPage.routeName), diff --git a/lib/widgets/settings/privacy/file_picker/file_picker_page.dart b/lib/widgets/settings/privacy/file_picker/file_picker_page.dart index c9fa121e7..59a7b56cc 100644 --- a/lib/widgets/settings/privacy/file_picker/file_picker_page.dart +++ b/lib/widgets/settings/privacy/file_picker/file_picker_page.dart @@ -59,7 +59,7 @@ class _FilePickerPageState extends State { return !isHidden; } }).toList(); - final animations = context.select((s) => s.accessibilityAnimations); + final animations = context.select((v) => v.accessibilityAnimations); return PopScope( canPop: _directory.relativeDir.isEmpty, onPopInvokedWithResult: (didPop, result) { diff --git a/lib/widgets/settings/settings_mobile_page.dart b/lib/widgets/settings/settings_mobile_page.dart index ffb754546..664e1cfc4 100644 --- a/lib/widgets/settings/settings_mobile_page.dart +++ b/lib/widgets/settings/settings_mobile_page.dart @@ -46,7 +46,7 @@ class _SettingsMobilePageState extends State with FeedbackMi @override Widget build(BuildContext context) { - final animations = context.select((s) => s.accessibilityAnimations); + final animations = context.select((v) => v.accessibilityAnimations); return AvesScaffold( appBar: AppBar( title: InteractiveAppBarTitle( diff --git a/lib/widgets/settings/thumbnails/overlay.dart b/lib/widgets/settings/thumbnails/overlay.dart index 6a19793c1..108facaf2 100644 --- a/lib/widgets/settings/thumbnails/overlay.dart +++ b/lib/widgets/settings/thumbnails/overlay.dart @@ -143,7 +143,7 @@ class SettingsTileThumbnailLocationIcon extends SettingsTile { ); Widget _buildTrailing(BuildContext context) { - final iconType = context.select((s) => s.thumbnailLocationIcon); + final iconType = context.select((v) => v.thumbnailLocationIcon); return ThumbnailOverlayPage.buildTrailingIcon( context: context, key: iconType, @@ -168,7 +168,7 @@ class SettingsTileThumbnailTagIcon extends SettingsTile { ); Widget _buildTrailing(BuildContext context) { - final iconType = context.select((s) => s.thumbnailTagIcon); + final iconType = context.select((v) => v.thumbnailTagIcon); return ThumbnailOverlayPage.buildTrailingIcon( context: context, key: iconType, diff --git a/lib/widgets/viewer/info/info_app_bar.dart b/lib/widgets/viewer/info/info_app_bar.dart index 866b8f4cf..24f111962 100644 --- a/lib/widgets/viewer/info/info_app_bar.dart +++ b/lib/widgets/viewer/info/info_app_bar.dart @@ -50,7 +50,7 @@ class InfoAppBar extends StatelessWidget { final commonActions = EntryActions.commonMetadataActions.where(isVisible); final formatSpecificActions = EntryActions.formatSpecificMetadataActions.where(isVisible); final useTvLayout = settings.useTvLayout; - final animations = context.select((s) => s.accessibilityAnimations); + final animations = context.select((v) => v.accessibilityAnimations); return SliverAppBar( leading: useTvLayout ? null diff --git a/lib/widgets/viewer/overlay/viewer_buttons.dart b/lib/widgets/viewer/overlay/viewer_buttons.dart index 32e613aa3..4591d8ae4 100644 --- a/lib/widgets/viewer/overlay/viewer_buttons.dart +++ b/lib/widgets/viewer/overlay/viewer_buttons.dart @@ -252,7 +252,7 @@ class _ViewerButtonRowContentState extends State { final exportActions = widget.exportActions; final videoActions = widget.videoActions; final hasOverflowMenu = pageEntry.canRotate || pageEntry.canFlip || topLevelActions.isNotEmpty || exportActions.isNotEmpty || videoActions.isNotEmpty; - final animations = context.select((s) => s.accessibilityAnimations); + final animations = context.select((v) => v.accessibilityAnimations); return Selector( selector: (context, vc) => vc.getController(pageEntry), builder: (context, videoController, child) { From 1a78fdfd0bdf8ef059ad4442f4c2396eaf8129e1 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sun, 24 Nov 2024 01:15:36 +0100 Subject: [PATCH 09/12] #1292 remember title filter visibility by page --- CHANGELOG.md | 4 ++++ lib/model/settings/modules/filter_grids.dart | 4 ++-- lib/model/settings/settings.dart | 7 ++++++- lib/widgets/collection/collection_page.dart | 1 + .../collection/entry_set_action_delegate.dart | 2 ++ lib/widgets/common/providers/query_provider.dart | 6 +++--- .../dialogs/pick_dialogs/album_pick_page.dart | 16 ++-------------- .../dialogs/pick_dialogs/item_pick_page.dart | 3 +++ .../common/action_delegates/chip_set.dart | 2 ++ .../filter_grids/common/filter_nav_page.dart | 3 +++ plugins/aves_model/lib/src/settings/keys.dart | 2 +- 11 files changed, 29 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32a801e41..2ac3b01ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file. - integrate with OS app language settings on Android >=14 +### Changed + +- remember title filter visibility by page + ## [v1.11.18] - 2024-11-18 ### Changed diff --git a/lib/model/settings/modules/filter_grids.dart b/lib/model/settings/modules/filter_grids.dart index d2a7064f7..fc5a52275 100644 --- a/lib/model/settings/modules/filter_grids.dart +++ b/lib/model/settings/modules/filter_grids.dart @@ -51,7 +51,7 @@ mixin FilterGridsSettings on SettingsAccess { set pinnedFilters(Set newValue) => set(SettingKeys.pinnedFiltersKey, newValue.map((filter) => filter.toJson()).toList()); - bool get showAlbumPickQuery => getBool(SettingKeys.showAlbumPickQueryKey) ?? false; + bool getShowTitleQuery(String routeName) => getBool(SettingKeys.showTitleQueryPrefixKey + routeName) ?? false; - set showAlbumPickQuery(bool newValue) => set(SettingKeys.showAlbumPickQueryKey, newValue); + void setShowTitleQuery(String routeName, bool newValue) => set(SettingKeys.showTitleQueryPrefixKey + routeName, newValue); } diff --git a/lib/model/settings/settings.dart b/lib/model/settings/settings.dart index 40804ec4f..e1a52c276 100644 --- a/lib/model/settings/settings.dart +++ b/lib/model/settings/settings.dart @@ -360,6 +360,12 @@ class Settings with ChangeNotifier, SettingsAccess, AppSettings, DisplaySettings } else { debugPrint('failed to import key=$key, value=$newValue is not a string'); } + } else if (key.startsWith(SettingKeys.showTitleQueryPrefixKey)) { + if (newValue is bool) { + store.setBool(key, newValue); + } else { + debugPrint('failed to import key=$key, value=$newValue is not a bool'); + } } else { switch (key) { case SettingKeys.subtitleTextColorKey: @@ -404,7 +410,6 @@ class Settings with ChangeNotifier, SettingsAccess, AppSettings, DisplaySettings case SettingKeys.stateSortReverseKey: case SettingKeys.placeSortReverseKey: case SettingKeys.tagSortReverseKey: - case SettingKeys.showAlbumPickQueryKey: case SettingKeys.showOverlayOnOpeningKey: case SettingKeys.showOverlayMinimapKey: case SettingKeys.showOverlayInfoKey: diff --git a/lib/widgets/collection/collection_page.dart b/lib/widgets/collection/collection_page.dart index 777a4f262..e2631b6bd 100644 --- a/lib/widgets/collection/collection_page.dart +++ b/lib/widgets/collection/collection_page.dart @@ -91,6 +91,7 @@ class _CollectionPageState extends State { selector: (context, selection) => selection.selectedItems.isNotEmpty, builder: (context, hasSelection, child) { final body = QueryProvider( + startEnabled: settings.getShowTitleQuery(context.currentRouteName!), initialQuery: liveFilter?.query, child: Builder( builder: (context) { diff --git a/lib/widgets/collection/entry_set_action_delegate.dart b/lib/widgets/collection/entry_set_action_delegate.dart index fd9956bc4..93f1c5618 100644 --- a/lib/widgets/collection/entry_set_action_delegate.dart +++ b/lib/widgets/collection/entry_set_action_delegate.dart @@ -181,6 +181,8 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware case EntrySetAction.searchCollection: _goToSearch(context); case EntrySetAction.toggleTitleSearch: + final routeName = context.currentRouteName!; + settings.setShowTitleQuery(routeName, !settings.getShowTitleQuery(routeName)); context.read().toggle(); case EntrySetAction.addShortcut: _addShortcut(context); diff --git a/lib/widgets/common/providers/query_provider.dart b/lib/widgets/common/providers/query_provider.dart index e811e92ad..8c0506112 100644 --- a/lib/widgets/common/providers/query_provider.dart +++ b/lib/widgets/common/providers/query_provider.dart @@ -3,13 +3,13 @@ import 'package:flutter/widgets.dart'; import 'package:provider/provider.dart'; class QueryProvider extends StatelessWidget { - final bool enabled; + final bool startEnabled; final String? initialQuery; final Widget child; const QueryProvider({ super.key, - this.enabled = false, + this.startEnabled = false, this.initialQuery, required this.child, }); @@ -18,7 +18,7 @@ class QueryProvider extends StatelessWidget { Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) => Query( - enabled: enabled, + enabled: startEnabled, initialValue: initialQuery, ), child: child, diff --git a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart index 12ca7aff4..107383a5d 100644 --- a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart +++ b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart @@ -114,13 +114,13 @@ class _AlbumPickPageState extends State<_AlbumPickPage> { final gridItems = AlbumListPage.getAlbumGridItems(context, source); return SelectionProvider>( child: QueryProvider( - enabled: settings.showAlbumPickQuery, + startEnabled: settings.getShowTitleQuery(context.currentRouteName!), child: FilterGridPage( settingsRouteKey: AlbumListPage.routeName, appBar: FilterGridAppBar( source: source, title: title, - actionDelegate: _AlbumChipSetPickActionDelegate(gridItems), + actionDelegate: AlbumChipSetActionDelegate(gridItems), actionsBuilder: _buildActions, isEmpty: false, appBarHeightNotifier: _appBarHeightNotifier, @@ -287,15 +287,3 @@ class _AlbumPickPageState extends State<_AlbumPickPage> { Navigator.maybeOf(context)?.pop(filter); } } - -class _AlbumChipSetPickActionDelegate extends AlbumChipSetActionDelegate { - _AlbumChipSetPickActionDelegate(super.items); - - @override - void onActionSelected(BuildContext context, ChipSetAction action) { - if (action == ChipSetAction.toggleTitleSearch) { - settings.showAlbumPickQuery = !settings.showAlbumPickQuery; - } - super.onActionSelected(context, action); - } -} diff --git a/lib/widgets/dialogs/pick_dialogs/item_pick_page.dart b/lib/widgets/dialogs/pick_dialogs/item_pick_page.dart index 49fe4266a..f7abf4b8d 100644 --- a/lib/widgets/dialogs/pick_dialogs/item_pick_page.dart +++ b/lib/widgets/dialogs/pick_dialogs/item_pick_page.dart @@ -1,11 +1,13 @@ import 'package:aves/app_mode.dart'; import 'package:aves/model/entry/entry.dart'; import 'package:aves/model/filters/query.dart'; +import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/widgets/collection/collection_grid.dart'; import 'package:aves/widgets/collection/collection_page.dart'; import 'package:aves/widgets/common/basic/insets.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; +import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/providers/query_provider.dart'; import 'package:aves/widgets/common/providers/selection_provider.dart'; import 'package:collection/collection.dart'; @@ -49,6 +51,7 @@ class _ItemPickPageState extends State { child: AvesScaffold( body: SelectionProvider( child: QueryProvider( + startEnabled: settings.getShowTitleQuery(context.currentRouteName!), initialQuery: liveFilter?.query, child: GestureAreaProtectorStack( child: SafeArea( diff --git a/lib/widgets/filter_grids/common/action_delegates/chip_set.dart b/lib/widgets/filter_grids/common/action_delegates/chip_set.dart index a6a6cb814..b6b5537d7 100644 --- a/lib/widgets/filter_grids/common/action_delegates/chip_set.dart +++ b/lib/widgets/filter_grids/common/action_delegates/chip_set.dart @@ -179,6 +179,8 @@ abstract class ChipSetActionDelegate with FeedbackMi case ChipSetAction.search: _goToSearch(context); case ChipSetAction.toggleTitleSearch: + final routeName = context.currentRouteName!; + settings.setShowTitleQuery(routeName, !settings.getShowTitleQuery(routeName)); context.read().toggle(); case ChipSetAction.createAlbum: case ChipSetAction.createVault: diff --git a/lib/widgets/filter_grids/common/filter_nav_page.dart b/lib/widgets/filter_grids/common/filter_nav_page.dart index 92463e2d2..4b4f95a09 100644 --- a/lib/widgets/filter_grids/common/filter_nav_page.dart +++ b/lib/widgets/filter_grids/common/filter_nav_page.dart @@ -1,6 +1,8 @@ import 'package:aves/model/filters/filters.dart'; +import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_source.dart'; import 'package:aves/utils/time_utils.dart'; +import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/aves_filter_chip.dart'; import 'package:aves/widgets/common/providers/query_provider.dart'; import 'package:aves/widgets/common/providers/selection_provider.dart'; @@ -110,6 +112,7 @@ class _FilterNavigationPageState>( child: Builder( builder: (context) => QueryProvider( + startEnabled: settings.getShowTitleQuery(context.currentRouteName!), child: FilterGridPage( appBar: FilterGridAppBar( source: widget.source, diff --git a/plugins/aves_model/lib/src/settings/keys.dart b/plugins/aves_model/lib/src/settings/keys.dart index 6efba4aa1..0f44d3b58 100644 --- a/plugins/aves_model/lib/src/settings/keys.dart +++ b/plugins/aves_model/lib/src/settings/keys.dart @@ -86,7 +86,7 @@ class SettingKeys { static const pinnedFiltersKey = 'pinned_filters'; static const hiddenFiltersKey = 'hidden_filters'; static const deactivatedHiddenFiltersKey = 'deactivated_hidden_filters'; - static const showAlbumPickQueryKey = 'show_album_pick_query'; + static const showTitleQueryPrefixKey = 'show_title_query_'; // viewer static const viewerQuickActionsKey = 'viewer_quick_actions'; From fc9c2dfcc5a9cbb667519209443cab18303da7cf Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sun, 24 Nov 2024 23:09:47 +0100 Subject: [PATCH 10/12] minor fix --- lib/widgets/navigation/nav_bar/nav_bar.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/widgets/navigation/nav_bar/nav_bar.dart b/lib/widgets/navigation/nav_bar/nav_bar.dart index 87e9ea683..636a40036 100644 --- a/lib/widgets/navigation/nav_bar/nav_bar.dart +++ b/lib/widgets/navigation/nav_bar/nav_bar.dart @@ -91,6 +91,7 @@ class _AppBottomNavBarState extends State { .toList(), onTap: (index) => _goTo(context, items, index), currentIndex: _getCurrentIndex(context, items), + elevation: 0, type: BottomNavigationBarType.fixed, backgroundColor: backgroundColor, showSelectedLabels: false, From 8ff44186f6c9a97826ceca235976a13455c4a920 Mon Sep 17 00:00:00 2001 From: "Weblate (bot)" Date: Sun, 24 Nov 2024 23:11:34 +0100 Subject: [PATCH 11/12] l10n by weblate (#1304) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Translate-URL: https://hosted.weblate.org/projects/aves/app-android/et/ Translate-URL: https://hosted.weblate.org/projects/aves/app-android/hi/ Translate-URL: https://hosted.weblate.org/projects/aves/app-android/ru/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/ar/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/de/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/en_Shaw/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/es/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/et/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/fr/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/hi/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/id/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/ko/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/nl/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/pl/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/pt/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/ru/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/sv/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/tr/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/zh_Hans/ Translate-URL: https://hosted.weblate.org/projects/aves/store-short-description/et/ Translation: Aves/App - Android Translation: Aves/App - Main Translation: Aves/Store - Short description Co-authored-by: 5FeetUnder <15950507+5FeetUnder@users.noreply.github.com> Co-authored-by: AJ07 <101049867+ChAJ07@users.noreply.github.com> Co-authored-by: Cleverson Cândido Co-authored-by: Hasan Kara Co-authored-by: Languages add-on Co-authored-by: Linerly Co-authored-by: Mohamed Zeroug Co-authored-by: Paranoid Android Co-authored-by: Priit Jõerüüt Co-authored-by: Shift18 Co-authored-by: Stephan Paternotte Co-authored-by: Thibault Deckers Co-authored-by: bittin1ddc447d824349b2 Co-authored-by: gallegonovato Co-authored-by: kaajjo Co-authored-by: rehork Co-authored-by: wanzh --- .../app/src/main/res/values-hi/strings.xml | 1 + lib/l10n/app_en_Shaw.arb | 4 +- lib/l10n/app_et.arb | 175 +++++++++++++++++- lib/l10n/app_hi.arb | 28 ++- lib/l10n/app_ru.arb | 4 +- 5 files changed, 208 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/res/values-hi/strings.xml b/android/app/src/main/res/values-hi/strings.xml index 0447c8eb1..9b6676a4d 100644 --- a/android/app/src/main/res/values-hi/strings.xml +++ b/android/app/src/main/res/values-hi/strings.xml @@ -8,4 +8,5 @@ मीडिया जाँचे ऐवीज वीडियो + मैप \ No newline at end of file diff --git a/lib/l10n/app_en_Shaw.arb b/lib/l10n/app_en_Shaw.arb index 65a149a47..e9451a13a 100644 --- a/lib/l10n/app_en_Shaw.arb +++ b/lib/l10n/app_en_Shaw.arb @@ -1589,5 +1589,7 @@ "videoActionShowPreviousFrame": "𐑖𐑴 𐑐𐑮𐑰𐑝𐑾𐑕 𐑓𐑮𐑱𐑥", "@videoActionShowPreviousFrame": {}, "videoActionShowNextFrame": "𐑖𐑴 𐑯𐑧𐑒𐑕𐑑 𐑓𐑮𐑱𐑥", - "@videoActionShowNextFrame": {} + "@videoActionShowNextFrame": {}, + "newAlbumDialogAlbumAlreadyExistsHelper": "𐑨𐑤𐑚𐑩𐑥 𐑷𐑤𐑮𐑧𐑛𐑦 𐑦𐑜𐑟𐑦𐑕𐑑𐑕", + "@newAlbumDialogAlbumAlreadyExistsHelper": {} } diff --git a/lib/l10n/app_et.arb b/lib/l10n/app_et.arb index 9bc9c3e5c..af5471797 100644 --- a/lib/l10n/app_et.arb +++ b/lib/l10n/app_et.arb @@ -464,5 +464,178 @@ "videoLoopModeAlways": "Alati", "@videoLoopModeAlways": {}, "unitSystemMetric": "Meetermõõdustik", - "@unitSystemMetric": {} + "@unitSystemMetric": {}, + "viewerTransitionZoomIn": "Sissesuumimine", + "@viewerTransitionZoomIn": {}, + "wallpaperTargetLock": "Lukustusvaade", + "@wallpaperTargetLock": {}, + "wallpaperTargetHomeLock": "Avaleht ja lukustusvaade", + "@wallpaperTargetHomeLock": {}, + "widgetDisplayedItemRandom": "Juhuslik", + "@widgetDisplayedItemRandom": {}, + "widgetDisplayedItemMostRecent": "Viimane", + "@widgetDisplayedItemMostRecent": {}, + "widgetOpenPageHome": "Mine avalehele", + "@widgetOpenPageHome": {}, + "widgetOpenPageCollection": "Ava kogumik", + "@widgetOpenPageCollection": {}, + "widgetOpenPageViewer": "Ava sirvija", + "@widgetOpenPageViewer": {}, + "widgetTapUpdateWidget": "Värskenda vidinat", + "@widgetTapUpdateWidget": {}, + "storageVolumeDescriptionFallbackPrimary": "Sisemine andmehoidla", + "@storageVolumeDescriptionFallbackPrimary": {}, + "rootDirectoryDescription": "juurkaust", + "@rootDirectoryDescription": {}, + "viewerTransitionNone": "Määratlemata", + "@viewerTransitionNone": {}, + "wallpaperTargetHome": "Avaleht", + "@wallpaperTargetHome": {}, + "storageVolumeDescriptionFallbackNonPrimary": "SD-kaart", + "@storageVolumeDescriptionFallbackNonPrimary": {}, + "unitSystemImperial": "Inglise mõõdustik", + "@unitSystemImperial": {}, + "viewerTransitionSlide": "Äraliuglemine", + "@viewerTransitionSlide": {}, + "viewerTransitionFade": "Hajumine", + "@viewerTransitionFade": {}, + "viewerTransitionParallax": "Parallaks", + "@viewerTransitionParallax": {}, + "otherDirectoryDescription": "„{name}“ kaust", + "@otherDirectoryDescription": { + "placeholders": { + "name": { + "type": "String", + "example": "Pictures", + "description": "the name of a specific directory" + } + } + }, + "notEnoughSpaceDialogMessage": "See tegevus vajab „{volume}“ andmeruumis „{neededSize}“ vaba andmemahtu, kuid alles on vaid „{freeSize}“.", + "@notEnoughSpaceDialogMessage": { + "placeholders": { + "neededSize": { + "type": "String", + "example": "314 MB" + }, + "freeSize": { + "type": "String", + "example": "123 MB" + }, + "volume": { + "type": "String", + "example": "SD card", + "description": "the name of a storage volume" + } + } + }, + "missingSystemFilePickerDialogMessage": "Süsteemi failihaldur/failivalija on puudu või kasutuselt eemaldatud. Palun pane ta tööle ja proovi siis uuesti.", + "@missingSystemFilePickerDialogMessage": {}, + "nameConflictDialogSingleSourceMessage": "Mõnedel sihtkausta failidel on sama nimi.", + "@nameConflictDialogSingleSourceMessage": {}, + "videoStartOverButtonLabel": "ALUSTA UUESTI", + "@videoStartOverButtonLabel": {}, + "videoResumeButtonLabel": "JÄTKA", + "@videoResumeButtonLabel": {}, + "setCoverDialogLatest": "Viimane objekt", + "@setCoverDialogLatest": {}, + "setCoverDialogAuto": "Automaatne", + "@setCoverDialogAuto": {}, + "nameConflictDialogMultipleSourceMessage": "Mõnedel failidel on sama nimi.", + "@nameConflictDialogMultipleSourceMessage": {}, + "addShortcutDialogLabel": "Kiirnupu silt", + "@addShortcutDialogLabel": {}, + "addShortcutButtonLabel": "LISA", + "@addShortcutButtonLabel": {}, + "noMatchingAppDialogMessage": "Pole rakendusi, mis oskaks seda kasutada.", + "@noMatchingAppDialogMessage": {}, + "binEntriesConfirmationDialogMessage": "{count, plural, =1{Kas viskame selle objekti prügikasti?} other{Kas viskame need {count} objekti prügikasti?}}", + "@binEntriesConfirmationDialogMessage": { + "placeholders": { + "count": { + "format": "decimalPattern" + } + } + }, + "moveUndatedConfirmationDialogMessage": "Kas enne jätkamist salvestame objekti kuupäevad?", + "@moveUndatedConfirmationDialogMessage": {}, + "moveUndatedConfirmationDialogSetDate": "Salvesta kuupäevad", + "@moveUndatedConfirmationDialogSetDate": {}, + "videoResumeDialogMessage": "Kas sa soovid jätkata esitamist {time} kohalt?", + "@videoResumeDialogMessage": { + "placeholders": { + "time": { + "type": "String", + "example": "13:37" + } + } + }, + "patternDialogEnter": "Sisesta viipemuster", + "@patternDialogEnter": {}, + "patternDialogConfirm": "Korda viipemustrit", + "@patternDialogConfirm": {}, + "pinDialogEnter": "Sisesta PIN-kood", + "@pinDialogEnter": {}, + "pinDialogConfirm": "Korda PIN-koodi", + "@pinDialogConfirm": {}, + "passwordDialogEnter": "Sisesta salasõna", + "@passwordDialogEnter": {}, + "passwordDialogConfirm": "Korda salasõna", + "@passwordDialogConfirm": {}, + "renameAlbumDialogLabel": "Uus nimi", + "@renameAlbumDialogLabel": {}, + "renameAlbumDialogLabelAlreadyExistsHelper": "Selline kaust on juba olemas", + "@renameAlbumDialogLabelAlreadyExistsHelper": {}, + "renameEntrySetPageTitle": "Muuda nime", + "@renameEntrySetPageTitle": {}, + "renameEntrySetPagePatternFieldLabel": "Failide nimemuster", + "@renameEntrySetPagePatternFieldLabel": {}, + "renameEntrySetPageInsertTooltip": "Lisa väli", + "@renameEntrySetPageInsertTooltip": {}, + "renameEntrySetPagePreviewSectionTitle": "Eelvaade", + "@renameEntrySetPagePreviewSectionTitle": {}, + "renameProcessorCounter": "Loendur", + "@renameProcessorCounter": {}, + "renameProcessorHash": "Räsi", + "@renameProcessorHash": {}, + "renameProcessorName": "Nimi", + "@renameProcessorName": {}, + "storageAccessDialogMessage": "Palun anna sellele rakendusele järgmises ekraanivaates õigused „{directory}“ kaustale „{volume}“ andmekogus.", + "@storageAccessDialogMessage": { + "placeholders": { + "directory": { + "type": "String", + "description": "the name of a directory, using the output of `rootDirectoryDescription` or `otherDirectoryDescription`" + }, + "volume": { + "type": "String", + "example": "SD card", + "description": "the name of a storage volume" + } + } + }, + "restrictedAccessDialogMessage": "Sellel rakendusel pole õigusi muuta faile „{volume}“ andmekogu „{directory}“ kaustas.\n\nPalun kasuta failihaldurit või galeriirakendust failide tõstmiseks muude asukohta.", + "@restrictedAccessDialogMessage": { + "placeholders": { + "directory": { + "type": "String", + "description": "the name of a directory, using the output of `rootDirectoryDescription` or `otherDirectoryDescription`" + }, + "volume": { + "type": "String", + "example": "SD card", + "description": "the name of a storage volume" + } + } + }, + "setCoverDialogCustom": "Sinu valik", + "@setCoverDialogCustom": {}, + "deleteEntriesConfirmationDialogMessage": "{count, plural, =1{Kas kustutame selle objekti?} other{Kas kustutame need {count} objekti?}}", + "@deleteEntriesConfirmationDialogMessage": { + "placeholders": { + "count": { + "format": "decimalPattern" + } + } + } } diff --git a/lib/l10n/app_hi.arb b/lib/l10n/app_hi.arb index c027bc9ca..bca107eb8 100644 --- a/lib/l10n/app_hi.arb +++ b/lib/l10n/app_hi.arb @@ -964,5 +964,31 @@ "drawerCollectionImages": "इमेजेस", "@drawerCollectionImages": {}, "aboutDataUsageMisc": "विविध", - "@aboutDataUsageMisc": {} + "@aboutDataUsageMisc": {}, + "sortByName": "नाम से", + "@sortByName": {}, + "sortByDate": "दिनांक से", + "@sortByDate": {}, + "videoActionShowPreviousFrame": "पिछला फ्रेम दिखाए", + "@videoActionShowPreviousFrame": {}, + "videoActionShowNextFrame": "अगला फ्रेम दिखाए", + "@videoActionShowNextFrame": {}, + "newAlbumDialogAlbumAlreadyExistsHelper": "एल्बम पहले से उपलब्ध हैं", + "@newAlbumDialogAlbumAlreadyExistsHelper": {}, + "drawerCountryPage": "देश", + "@drawerCountryPage": {}, + "collectionPickPageTitle": "चुने", + "@collectionPickPageTitle": {}, + "drawerCollectionPanoramas": "पैनोरामा", + "@drawerCollectionPanoramas": {}, + "drawerCollectionRaws": "रॉ फ़ोटो", + "@drawerCollectionRaws": {}, + "drawerAlbumPage": "एल्बम", + "@drawerAlbumPage": {}, + "drawerCollectionSphericalVideos": "360⁰ वीडियो", + "@drawerCollectionSphericalVideos": {}, + "drawerPlacePage": "स्थान", + "@drawerPlacePage": {}, + "drawerTagPage": "टैग्स", + "@drawerTagPage": {} } diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index ce3230d0f..546ee4d6d 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -1390,5 +1390,7 @@ "mapStyleOsmLiberty": "OSM Liberty", "@mapStyleOsmLiberty": {}, "mapAttributionOsmLiberty": "Tiles by [OpenMapTiles](https://www.openmaptiles.org/), [CC BY](http://creativecommons.org/licenses/by/4.0) • Hosted by [OSM Americana](https://tile.ourmap.us)", - "@mapAttributionOsmLiberty": {} + "@mapAttributionOsmLiberty": {}, + "newAlbumDialogAlbumAlreadyExistsHelper": "Альбом уже существует", + "@newAlbumDialogAlbumAlreadyExistsHelper": {} } From cc58f919f7c779dada3383273d4bdd85da88b125 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sun, 24 Nov 2024 23:16:18 +0100 Subject: [PATCH 12/12] version bump --- CHANGELOG.md | 2 ++ fastlane/metadata/android/en-US/changelogs/138.txt | 5 +++++ fastlane/metadata/android/en-US/changelogs/13801.txt | 5 +++++ pubspec.yaml | 2 +- whatsnew/whatsnew-en-US | 2 +- 5 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/138.txt create mode 100644 fastlane/metadata/android/en-US/changelogs/13801.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ac3b01ad..c67508ef8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [v1.11.19] - 2024-11-24 + ### Added - integrate with OS app language settings on Android >=14 diff --git a/fastlane/metadata/android/en-US/changelogs/138.txt b/fastlane/metadata/android/en-US/changelogs/138.txt new file mode 100644 index 000000000..e405b5830 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/138.txt @@ -0,0 +1,5 @@ +In v1.11.19: +- peruse your videos frame by frame +- create map shortcuts to filtered collections +- enjoy the app in Shavian +Full changelog available on GitHub \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/13801.txt b/fastlane/metadata/android/en-US/changelogs/13801.txt new file mode 100644 index 000000000..e405b5830 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/13801.txt @@ -0,0 +1,5 @@ +In v1.11.19: +- peruse your videos frame by frame +- create map shortcuts to filtered collections +- enjoy the app in Shavian +Full changelog available on GitHub \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index c19cd905d..2b40001d1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ repository: https://github.com/deckerst/aves # - play changelog: /whatsnew/whatsnew-en-US # - izzy changelog: /fastlane/metadata/android/en-US/changelogs/XXX01.txt # - libre changelog: /fastlane/metadata/android/en-US/changelogs/XXX.txt -version: 1.11.18+137 +version: 1.11.19+138 publish_to: none environment: diff --git a/whatsnew/whatsnew-en-US b/whatsnew/whatsnew-en-US index 444e6cae9..e405b5830 100644 --- a/whatsnew/whatsnew-en-US +++ b/whatsnew/whatsnew-en-US @@ -1,4 +1,4 @@ -In v1.11.18: +In v1.11.19: - peruse your videos frame by frame - create map shortcuts to filtered collections - enjoy the app in Shavian