From 8b1180684cc64193f6447105a5a87cebd6ff0e43 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Thu, 10 Feb 2022 14:26:48 +0900 Subject: [PATCH] #170 perf: collection sort/group by name, save/load top entries --- android/app/build.gradle | 6 +- .../aves/channel/calls/DebugHandler.kt | 13 +- android/build.gradle | 2 +- lib/model/db/db_metadata.dart | 95 ++++++++++++ .../db_metadata_sqflite.dart} | 107 +++---------- .../db_metadata_sqflite_upgrade.dart} | 2 +- lib/model/filters/coordinate.dart | 4 +- lib/model/settings/defaults.dart | 6 +- .../{ => enums}/accessibility_animations.dart | 0 .../{ => enums}/accessibility_timeout.dart | 0 .../{ => enums}/coordinate_format.dart | 0 .../{ => enums}/entry_background.dart | 0 lib/model/settings/{ => enums}/enums.dart | 0 lib/model/settings/{ => enums}/home_page.dart | 0 lib/model/settings/{ => enums}/map_style.dart | 0 lib/model/settings/{ => enums}/screen_on.dart | 0 .../settings/{ => enums}/unit_system.dart | 0 .../settings/{ => enums}/video_loop_mode.dart | 0 lib/model/settings/settings.dart | 142 ++++++++---------- lib/model/settings/store/store.dart | 37 +++++ .../settings/store/store_shared_pref.dart | 60 ++++++++ lib/model/source/album.dart | 133 +++++++++------- lib/model/source/collection_lens.dart | 8 +- lib/model/source/collection_source.dart | 4 + lib/model/source/media_store_source.dart | 15 ++ lib/services/common/services.dart | 7 +- lib/theme/durations.dart | 2 +- lib/widgets/aves_app.dart | 99 ++++++++---- lib/widgets/collection/collection_grid.dart | 12 +- lib/widgets/collection/grid/list_details.dart | 2 +- .../common/action_mixins/feedback.dart | 4 +- .../common/identity/aves_filter_chip.dart | 2 +- lib/widgets/common/map/attribution.dart | 2 +- lib/widgets/common/map/buttons.dart | 4 +- lib/widgets/common/map/geo_map.dart | 4 +- lib/widgets/common/map/google/map.dart | 2 +- lib/widgets/common/map/leaflet/map.dart | 2 +- .../common/map/leaflet/scale_layer.dart | 2 +- lib/widgets/common/thumbnail/image.dart | 6 +- .../common/tile_extent_controller.dart | 2 +- lib/widgets/debug/settings.dart | 1 + lib/widgets/dialogs/location_pick_dialog.dart | 4 +- .../filter_grids/common/filter_grid_page.dart | 1 + lib/widgets/home_page.dart | 2 +- lib/widgets/map/map_info_row.dart | 2 +- lib/widgets/map/map_page.dart | 4 +- .../accessibility/remove_animations.dart | 4 +- .../accessibility/time_to_take_action.dart | 4 +- lib/widgets/settings/language/language.dart | 6 +- .../settings/navigation/navigation.dart | 6 +- lib/widgets/settings/video/video.dart | 4 +- .../settings/viewer/entry_background.dart | 4 +- lib/widgets/settings/viewer/viewer.dart | 2 +- lib/widgets/stats/stats_page.dart | 2 +- .../viewer/entry_horizontal_pager.dart | 2 +- lib/widgets/viewer/entry_viewer_stack.dart | 2 +- lib/widgets/viewer/info/location_section.dart | 2 +- lib/widgets/viewer/overlay/bottom/common.dart | 2 +- lib/widgets/viewer/video/fijkplayer.dart | 2 +- .../viewer/visual/entry_page_view.dart | 2 +- lib/widgets/viewer/visual/raster.dart | 4 +- lib/widgets/viewer/visual/vector.dart | 4 +- test/fake/metadata_db.dart | 2 +- test/model/collection_source_test.dart | 2 +- test/utils/geo_utils_test.dart | 2 +- test_driver/driver_screenshots.dart | 2 +- test_driver/driver_shaders.dart | 2 +- 67 files changed, 544 insertions(+), 318 deletions(-) create mode 100644 lib/model/db/db_metadata.dart rename lib/model/{metadata_db.dart => db/db_metadata_sqflite.dart} (88%) rename lib/model/{metadata_db_upgrade.dart => db/db_metadata_sqflite_upgrade.dart} (98%) rename lib/model/settings/{ => enums}/accessibility_animations.dart (100%) rename lib/model/settings/{ => enums}/accessibility_timeout.dart (100%) rename lib/model/settings/{ => enums}/coordinate_format.dart (100%) rename lib/model/settings/{ => enums}/entry_background.dart (100%) rename lib/model/settings/{ => enums}/enums.dart (100%) rename lib/model/settings/{ => enums}/home_page.dart (100%) rename lib/model/settings/{ => enums}/map_style.dart (100%) rename lib/model/settings/{ => enums}/screen_on.dart (100%) rename lib/model/settings/{ => enums}/unit_system.dart (100%) rename lib/model/settings/{ => enums}/video_loop_mode.dart (100%) create mode 100644 lib/model/settings/store/store.dart create mode 100644 lib/model/settings/store/store_shared_pref.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 8acc2d333..fed4ca45f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -141,7 +141,7 @@ repositories { } dependencies { - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2' implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.exifinterface:exifinterface:1.3.3' implementation 'androidx.multidex:multidex:2.0.1' @@ -152,10 +152,10 @@ dependencies { implementation 'com.github.deckerst:Android-TiffBitmapFactory:876e53870a' // forked, built by JitPack, cf https://jitpack.io/p/deckerst/pixymeta-android implementation 'com.github.deckerst:pixymeta-android:706bd73d6e' - implementation 'com.github.bumptech.glide:glide:4.12.0' + implementation 'com.github.bumptech.glide:glide:4.13.0' kapt 'androidx.annotation:annotation:1.3.0' - kapt 'com.github.bumptech.glide:compiler:4.12.0' + kapt 'com.github.bumptech.glide:compiler:4.13.0' compileOnly rootProject.findProject(':streams_channel') } diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DebugHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DebugHandler.kt index 4aebabf55..29f30d522 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DebugHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DebugHandler.kt @@ -32,12 +32,12 @@ import deckers.thibault.aves.utils.UriUtils.tryParseId import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.util.PathUtils import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.beyka.tiffbitmapfactory.TiffBitmapFactory import java.io.IOException -import java.util.* class DebugHandler(private val context: Context) : MethodCallHandler { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { @@ -81,7 +81,16 @@ class DebugHandler(private val context: Context) : MethodCallHandler { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { put("dataDir", context.dataDir) } - }.mapValues { it.value?.path } + }.mapValues { it.value?.path }.toMutableMap() + + // used by flutter plugin `path_provider` + dirs.putAll( + hashMapOf( + "flutter / cacheDir" to PathUtils.getCacheDirectory(context), + "flutter / dataDir" to PathUtils.getDataDirectory(context), + "flutter / filesDir" to PathUtils.getFilesDir(context), + ) + ) result.success(dirs) } diff --git a/android/build.gradle b/android/build.gradle index 57fd9118c..4174edca7 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.1.0' + classpath 'com.android.tools.build:gradle:7.1.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // GMS & Firebase Crashlytics are not actually used by all flavors classpath 'com.google.gms:google-services:4.3.10' diff --git a/lib/model/db/db_metadata.dart b/lib/model/db/db_metadata.dart new file mode 100644 index 000000000..e6a1a4726 --- /dev/null +++ b/lib/model/db/db_metadata.dart @@ -0,0 +1,95 @@ +import 'package:aves/model/covers.dart'; +import 'package:aves/model/entry.dart'; +import 'package:aves/model/favourites.dart'; +import 'package:aves/model/filters/filters.dart'; +import 'package:aves/model/metadata/address.dart'; +import 'package:aves/model/metadata/catalog.dart'; +import 'package:aves/model/video_playback.dart'; + +abstract class MetadataDb { + Future init(); + + Future dbFileSize(); + + Future reset(); + + Future removeIds(Set contentIds, {Set? dataTypes}); + + // entries + + Future clearEntries(); + + Future> loadAllEntries(); + + Future saveEntries(Iterable entries); + + Future updateEntryId(int oldId, AvesEntry entry); + + Future> searchEntries(String query, {int? limit}); + + Future> loadEntries(List ids); + + // date taken + + Future clearDates(); + + Future> loadDates(); + + // catalog metadata + + Future clearMetadataEntries(); + + Future> loadAllMetadataEntries(); + + Future saveMetadata(Set metadataEntries); + + Future updateMetadataId(int oldId, CatalogMetadata? metadata); + + // address + + Future clearAddresses(); + + Future> loadAllAddresses(); + + Future saveAddresses(Set addresses); + + Future updateAddressId(int oldId, AddressDetails? address); + + // favourites + + Future clearFavourites(); + + Future> loadAllFavourites(); + + Future addFavourites(Iterable rows); + + Future updateFavouriteId(int oldId, FavouriteRow row); + + Future removeFavourites(Iterable rows); + + // covers + + Future clearCovers(); + + Future> loadAllCovers(); + + Future addCovers(Iterable rows); + + Future updateCoverEntryId(int oldId, CoverRow row); + + Future removeCovers(Set filters); + + // video playback + + Future clearVideoPlayback(); + + Future> loadAllVideoPlayback(); + + Future loadVideoPlayback(int? contentId); + + Future addVideoPlayback(Set rows); + + Future updateVideoPlaybackId(int oldId, int? newId); + + Future removeVideoPlayback(Set contentIds); +} diff --git a/lib/model/metadata_db.dart b/lib/model/db/db_metadata_sqflite.dart similarity index 88% rename from lib/model/metadata_db.dart rename to lib/model/db/db_metadata_sqflite.dart index 2dfbe54ec..8f728ca88 100644 --- a/lib/model/metadata_db.dart +++ b/lib/model/db/db_metadata_sqflite.dart @@ -1,104 +1,19 @@ import 'dart:io'; import 'package:aves/model/covers.dart'; +import 'package:aves/model/db/db_metadata.dart'; +import 'package:aves/model/db/db_metadata_sqflite_upgrade.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/favourites.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/metadata/address.dart'; import 'package:aves/model/metadata/catalog.dart'; -import 'package:aves/model/metadata_db_upgrade.dart'; import 'package:aves/model/video_playback.dart'; import 'package:aves/services/common/services.dart'; import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; import 'package:sqflite/sqflite.dart'; -abstract class MetadataDb { - Future init(); - - Future dbFileSize(); - - Future reset(); - - Future removeIds(Set contentIds, {Set? dataTypes}); - - // entries - - Future clearEntries(); - - Future> loadAllEntries(); - - Future saveEntries(Iterable entries); - - Future updateEntryId(int oldId, AvesEntry entry); - - Future> searchEntries(String query, {int? limit}); - - // date taken - - Future clearDates(); - - Future> loadDates(); - - // catalog metadata - - Future clearMetadataEntries(); - - Future> loadAllMetadataEntries(); - - Future saveMetadata(Set metadataEntries); - - Future updateMetadataId(int oldId, CatalogMetadata? metadata); - - // address - - Future clearAddresses(); - - Future> loadAllAddresses(); - - Future saveAddresses(Set addresses); - - Future updateAddressId(int oldId, AddressDetails? address); - - // favourites - - Future clearFavourites(); - - Future> loadAllFavourites(); - - Future addFavourites(Iterable rows); - - Future updateFavouriteId(int oldId, FavouriteRow row); - - Future removeFavourites(Iterable rows); - - // covers - - Future clearCovers(); - - Future> loadAllCovers(); - - Future addCovers(Iterable rows); - - Future updateCoverEntryId(int oldId, CoverRow row); - - Future removeCovers(Set filters); - - // video playback - - Future clearVideoPlayback(); - - Future> loadAllVideoPlayback(); - - Future loadVideoPlayback(int? contentId); - - Future addVideoPlayback(Set rows); - - Future updateVideoPlaybackId(int oldId, int? newId); - - Future removeVideoPlayback(Set contentIds); -} - class SqfliteMetadataDb implements MetadataDb { late Future _database; @@ -235,6 +150,24 @@ class SqfliteMetadataDb implements MetadataDb { return entries; } + @override + Future> loadEntries(List ids) async { + if (ids.isEmpty) return {}; + final db = await _database; + final entries = {}; + await Future.forEach(ids, (id) async { + final maps = await db.query( + entryTable, + where: 'contentId = ?', + whereArgs: [id], + ); + if (maps.isNotEmpty) { + entries.add(AvesEntry.fromMap(maps.first)); + } + }); + return entries; + } + @override Future saveEntries(Iterable entries) async { if (entries.isEmpty) return; diff --git a/lib/model/metadata_db_upgrade.dart b/lib/model/db/db_metadata_sqflite_upgrade.dart similarity index 98% rename from lib/model/metadata_db_upgrade.dart rename to lib/model/db/db_metadata_sqflite_upgrade.dart index d69e7857c..f611e0294 100644 --- a/lib/model/metadata_db_upgrade.dart +++ b/lib/model/db/db_metadata_sqflite_upgrade.dart @@ -1,4 +1,4 @@ -import 'package:aves/model/metadata_db.dart'; +import 'package:aves/model/db/db_metadata_sqflite.dart'; import 'package:flutter/foundation.dart'; import 'package:sqflite/sqflite.dart'; diff --git a/lib/model/filters/coordinate.dart b/lib/model/filters/coordinate.dart index e211b625b..90664b8c0 100644 --- a/lib/model/filters/coordinate.dart +++ b/lib/model/filters/coordinate.dart @@ -1,7 +1,7 @@ import 'package:aves/l10n/l10n.dart'; import 'package:aves/model/filters/filters.dart'; -import 'package:aves/model/settings/coordinate_format.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/coordinate_format.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/theme/icons.dart'; import 'package:aves/utils/geo_utils.dart'; diff --git a/lib/model/settings/defaults.dart b/lib/model/settings/defaults.dart index 9f7a6f968..41306eafa 100644 --- a/lib/model/settings/defaults.dart +++ b/lib/model/settings/defaults.dart @@ -3,7 +3,7 @@ import 'package:aves/model/actions/entry_set_actions.dart'; import 'package:aves/model/actions/video_actions.dart'; import 'package:aves/model/filters/favourite.dart'; import 'package:aves/model/filters/mime.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/source/enums.dart'; import 'package:aves/widgets/filter_grids/albums_page.dart'; import 'package:aves/widgets/filter_grids/countries_page.dart'; @@ -106,4 +106,8 @@ class SettingsDefaults { // file picker static const filePickerShowHiddenFiles = false; + + // platform settings + static const isRotationLocked = false; + static const areAnimationsRemoved = false; } diff --git a/lib/model/settings/accessibility_animations.dart b/lib/model/settings/enums/accessibility_animations.dart similarity index 100% rename from lib/model/settings/accessibility_animations.dart rename to lib/model/settings/enums/accessibility_animations.dart diff --git a/lib/model/settings/accessibility_timeout.dart b/lib/model/settings/enums/accessibility_timeout.dart similarity index 100% rename from lib/model/settings/accessibility_timeout.dart rename to lib/model/settings/enums/accessibility_timeout.dart diff --git a/lib/model/settings/coordinate_format.dart b/lib/model/settings/enums/coordinate_format.dart similarity index 100% rename from lib/model/settings/coordinate_format.dart rename to lib/model/settings/enums/coordinate_format.dart diff --git a/lib/model/settings/entry_background.dart b/lib/model/settings/enums/entry_background.dart similarity index 100% rename from lib/model/settings/entry_background.dart rename to lib/model/settings/enums/entry_background.dart diff --git a/lib/model/settings/enums.dart b/lib/model/settings/enums/enums.dart similarity index 100% rename from lib/model/settings/enums.dart rename to lib/model/settings/enums/enums.dart diff --git a/lib/model/settings/home_page.dart b/lib/model/settings/enums/home_page.dart similarity index 100% rename from lib/model/settings/home_page.dart rename to lib/model/settings/enums/home_page.dart diff --git a/lib/model/settings/map_style.dart b/lib/model/settings/enums/map_style.dart similarity index 100% rename from lib/model/settings/map_style.dart rename to lib/model/settings/enums/map_style.dart diff --git a/lib/model/settings/screen_on.dart b/lib/model/settings/enums/screen_on.dart similarity index 100% rename from lib/model/settings/screen_on.dart rename to lib/model/settings/enums/screen_on.dart diff --git a/lib/model/settings/unit_system.dart b/lib/model/settings/enums/unit_system.dart similarity index 100% rename from lib/model/settings/unit_system.dart rename to lib/model/settings/enums/unit_system.dart diff --git a/lib/model/settings/video_loop_mode.dart b/lib/model/settings/enums/video_loop_mode.dart similarity index 100% rename from lib/model/settings/video_loop_mode.dart rename to lib/model/settings/enums/video_loop_mode.dart diff --git a/lib/model/settings/settings.dart b/lib/model/settings/settings.dart index 2740db8fd..a1ca41cae 100644 --- a/lib/model/settings/settings.dart +++ b/lib/model/settings/settings.dart @@ -7,15 +7,14 @@ import 'package:aves/model/actions/entry_set_actions.dart'; import 'package:aves/model/actions/video_actions.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/settings/defaults.dart'; -import 'package:aves/model/settings/enums.dart'; -import 'package:aves/model/settings/map_style.dart'; +import 'package:aves/model/settings/enums/enums.dart'; +import 'package:aves/model/settings/enums/map_style.dart'; import 'package:aves/model/source/enums.dart'; import 'package:aves/services/accessibility_service.dart'; import 'package:aves/services/common/services.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:shared_preferences/shared_preferences.dart'; final Settings settings = Settings._private(); @@ -25,8 +24,6 @@ class Settings extends ChangeNotifier { Stream get updateStream => _updateStreamController.stream; - static SharedPreferences? _prefs; - Settings._private(); static const Set internalKeys = { @@ -34,6 +31,9 @@ class Settings extends ChangeNotifier { catalogTimeZoneKey, videoShowRawTimedTextKey, searchHistoryKey, + platformAccelerometerRotationKey, + platformTransitionAnimationScaleKey, + topEntryIdsKey, }; // app @@ -48,6 +48,7 @@ class Settings extends ChangeNotifier { static const catalogTimeZoneKey = 'catalog_time_zone'; static const tileExtentPrefixKey = 'tile_extent_'; static const tileLayoutPrefixKey = 'tile_layout_'; + static const topEntryIdsKey = 'top_entry_ids'; // drawer static const drawerTypeBookmarksKey = 'drawer_type_bookmarks'; @@ -124,16 +125,10 @@ class Settings extends ChangeNotifier { // cf Android `Settings.Global.TRANSITION_ANIMATION_SCALE` static const platformTransitionAnimationScaleKey = 'transition_animation_scale'; - bool get initialized => _prefs != null; + bool get initialized => settingsStore.initialized; - Future init({ - required bool monitorPlatformSettings, - bool isRotationLocked = false, - bool areAnimationsRemoved = false, - }) async { - _prefs = await SharedPreferences.getInstance(); - _isRotationLocked = isRotationLocked; - _areAnimationsRemoved = areAnimationsRemoved; + Future init({required bool monitorPlatformSettings}) async { + await settingsStore.init(); if (monitorPlatformSettings) { _platformSettingsChangeChannel.receiveBroadcastStream().listen((event) => _onPlatformSettingsChange(event as Map?)); } @@ -141,9 +136,9 @@ class Settings extends ChangeNotifier { Future reset({required bool includeInternalKeys}) async { if (includeInternalKeys) { - await _prefs!.clear(); + await settingsStore.clear(); } else { - await Future.forEach(_prefs!.getKeys().whereNot(internalKeys.contains), _prefs!.remove); + await Future.forEach(settingsStore.getKeys().whereNot(Settings.internalKeys.contains), settingsStore.remove); } } @@ -189,7 +184,7 @@ class Settings extends ChangeNotifier { Locale? get locale { // exceptionally allow getting locale before settings are initialized - final tag = _prefs?.getString(localeKey); + final tag = initialized ? getString(localeKey) : null; if (tag != null) { final codes = tag.split(localeSeparator); return Locale.fromSubtags( @@ -250,11 +245,11 @@ class Settings extends ChangeNotifier { set homePage(HomePageSetting newValue) => setAndNotify(homePageKey, newValue.toString()); - String get catalogTimeZone => _prefs!.getString(catalogTimeZoneKey) ?? ''; + String get catalogTimeZone => getString(catalogTimeZoneKey) ?? ''; set catalogTimeZone(String newValue) => setAndNotify(catalogTimeZoneKey, newValue); - double getTileExtent(String routeName) => _prefs!.getDouble(tileExtentPrefixKey + routeName) ?? 0; + double getTileExtent(String routeName) => getDouble(tileExtentPrefixKey + routeName) ?? 0; void setTileExtent(String routeName, double newValue) => setAndNotify(tileExtentPrefixKey + routeName, newValue); @@ -262,10 +257,14 @@ class Settings extends ChangeNotifier { void setTileLayout(String routeName, TileLayout newValue) => setAndNotify(tileLayoutPrefixKey + routeName, newValue.toString()); + List? get topEntryIds => getStringList(topEntryIdsKey)?.map(int.tryParse).whereNotNull().toList(); + + set topEntryIds(List? newValue) => setAndNotify(topEntryIdsKey, newValue?.map((id) => id.toString()).whereNotNull().toList()); + // drawer List get drawerTypeBookmarks => - (_prefs!.getStringList(drawerTypeBookmarksKey))?.map((v) { + (getStringList(drawerTypeBookmarksKey))?.map((v) { if (v.isEmpty) return null; return CollectionFilter.fromJson(v); }).toList() ?? @@ -273,11 +272,11 @@ class Settings extends ChangeNotifier { set drawerTypeBookmarks(List newValue) => setAndNotify(drawerTypeBookmarksKey, newValue.map((filter) => filter?.toJson() ?? '').toList()); - List? get drawerAlbumBookmarks => _prefs!.getStringList(drawerAlbumBookmarksKey); + List? get drawerAlbumBookmarks => getStringList(drawerAlbumBookmarksKey); set drawerAlbumBookmarks(List? newValue) => setAndNotify(drawerAlbumBookmarksKey, newValue); - List get drawerPageBookmarks => _prefs!.getStringList(drawerPageBookmarksKey) ?? SettingsDefaults.drawerPageBookmarks; + List get drawerPageBookmarks => getStringList(drawerPageBookmarksKey) ?? SettingsDefaults.drawerPageBookmarks; set drawerPageBookmarks(List newValue) => setAndNotify(drawerPageBookmarksKey, newValue); @@ -341,11 +340,11 @@ class Settings extends ChangeNotifier { set tagSortFactor(ChipSortFactor newValue) => setAndNotify(tagSortFactorKey, newValue.toString()); - Set get pinnedFilters => (_prefs!.getStringList(pinnedFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); + Set get pinnedFilters => (getStringList(pinnedFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); set pinnedFilters(Set newValue) => setAndNotify(pinnedFiltersKey, newValue.map((filter) => filter.toJson()).toList()); - Set get hiddenFilters => (_prefs!.getStringList(hiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); + Set get hiddenFilters => (getStringList(hiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); set hiddenFilters(Set newValue) => setAndNotify(hiddenFiltersKey, newValue.map((filter) => filter.toJson()).toList()); @@ -415,7 +414,7 @@ class Settings extends ChangeNotifier { // subtitles - double get subtitleFontSize => _prefs!.getDouble(subtitleFontSizeKey) ?? SettingsDefaults.subtitleFontSize; + double get subtitleFontSize => getDouble(subtitleFontSizeKey) ?? SettingsDefaults.subtitleFontSize; set subtitleFontSize(double newValue) => setAndNotify(subtitleFontSizeKey, newValue); @@ -427,11 +426,11 @@ class Settings extends ChangeNotifier { set subtitleShowOutline(bool newValue) => setAndNotify(subtitleShowOutlineKey, newValue); - Color get subtitleTextColor => Color(_prefs!.getInt(subtitleTextColorKey) ?? SettingsDefaults.subtitleTextColor.value); + Color get subtitleTextColor => Color(getInt(subtitleTextColorKey) ?? SettingsDefaults.subtitleTextColor.value); set subtitleTextColor(Color newValue) => setAndNotify(subtitleTextColorKey, newValue.value); - Color get subtitleBackgroundColor => Color(_prefs!.getInt(subtitleBackgroundColorKey) ?? SettingsDefaults.subtitleBackgroundColor.value); + Color get subtitleBackgroundColor => Color(getInt(subtitleBackgroundColorKey) ?? SettingsDefaults.subtitleBackgroundColor.value); set subtitleBackgroundColor(Color newValue) => setAndNotify(subtitleBackgroundColorKey, newValue.value); @@ -441,7 +440,7 @@ class Settings extends ChangeNotifier { set infoMapStyle(EntryMapStyle newValue) => setAndNotify(infoMapStyleKey, newValue.toString()); - double get infoMapZoom => _prefs!.getDouble(infoMapZoomKey) ?? SettingsDefaults.infoMapZoom; + double get infoMapZoom => getDouble(infoMapZoomKey) ?? SettingsDefaults.infoMapZoom; set infoMapZoom(double newValue) => setAndNotify(infoMapZoomKey, newValue); @@ -459,7 +458,7 @@ class Settings extends ChangeNotifier { set saveSearchHistory(bool newValue) => setAndNotify(saveSearchHistoryKey, newValue); - List get searchHistory => (_prefs!.getStringList(searchHistoryKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toList(); + List get searchHistory => (getStringList(searchHistoryKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toList(); set searchHistory(List newValue) => setAndNotify(searchHistoryKey, newValue.map((filter) => filter.toJson()).toList()); @@ -481,11 +480,19 @@ class Settings extends ChangeNotifier { // convenience methods + int? getInt(String key) => settingsStore.getInt(key); + + double? getDouble(String key) => settingsStore.getDouble(key); + + String? getString(String key) => settingsStore.getString(key); + + List? getStringList(String key) => settingsStore.getStringList(key); + // ignore: avoid_positional_boolean_parameters - bool getBoolOrDefault(String key, bool defaultValue) => _prefs!.getBool(key) ?? defaultValue; + bool getBoolOrDefault(String key, bool defaultValue) => settingsStore.getBool(key) ?? defaultValue; T getEnumOrDefault(String key, T defaultValue, Iterable values) { - final valueString = _prefs!.getString(key); + final valueString = settingsStore.getString(key); for (final v in values) { if (v.toString() == valueString) { return v; @@ -495,28 +502,28 @@ class Settings extends ChangeNotifier { } List getEnumListOrDefault(String key, List defaultValue, Iterable values) { - return _prefs!.getStringList(key)?.map((s) => values.firstWhereOrNull((v) => v.toString() == s)).whereNotNull().toList() ?? defaultValue; + return settingsStore.getStringList(key)?.map((s) => values.firstWhereOrNull((v) => v.toString() == s)).whereNotNull().toList() ?? defaultValue; } void setAndNotify(String key, dynamic newValue) { - var oldValue = _prefs!.get(key); + var oldValue = settingsStore.get(key); if (newValue == null) { - _prefs!.remove(key); + settingsStore.remove(key); } else if (newValue is String) { - oldValue = _prefs!.getString(key); - _prefs!.setString(key, newValue); + oldValue = settingsStore.getString(key); + settingsStore.setString(key, newValue); } else if (newValue is List) { - oldValue = _prefs!.getStringList(key); - _prefs!.setStringList(key, newValue); + oldValue = settingsStore.getStringList(key); + settingsStore.setStringList(key, newValue); } else if (newValue is int) { - oldValue = _prefs!.getInt(key); - _prefs!.setInt(key, newValue); + oldValue = settingsStore.getInt(key); + settingsStore.setInt(key, newValue); } else if (newValue is double) { - oldValue = _prefs!.getDouble(key); - _prefs!.setDouble(key, newValue); + oldValue = settingsStore.getDouble(key); + settingsStore.setDouble(key, newValue); } else if (newValue is bool) { - oldValue = _prefs!.getBool(key); - _prefs!.setBool(key, newValue); + oldValue = settingsStore.getBool(key); + settingsStore.setBool(key, newValue); } if (oldValue != newValue) { _updateStreamController.add(key); @@ -527,50 +534,33 @@ class Settings extends ChangeNotifier { // platform settings void _onPlatformSettingsChange(Map? fields) { - var changed = false; fields?.forEach((key, value) { switch (key) { case platformAccelerometerRotationKey: if (value is num) { - final newValue = value == 0; - if (_isRotationLocked != newValue) { - _isRotationLocked = newValue; - if (!_isRotationLocked) { - windowService.requestOrientation(); - } - _updateStreamController.add(key); - changed = true; - } + isRotationLocked = value == 0; } break; case platformTransitionAnimationScaleKey: if (value is num) { - final newValue = value == 0; - if (_areAnimationsRemoved != newValue) { - _areAnimationsRemoved = newValue; - _updateStreamController.add(key); - changed = true; - } + areAnimationsRemoved = value == 0; } } }); - if (changed) { - notifyListeners(); - } } - bool _isRotationLocked = false; + bool get isRotationLocked => getBoolOrDefault(platformAccelerometerRotationKey, SettingsDefaults.isRotationLocked); - bool get isRotationLocked => _isRotationLocked; + set isRotationLocked(bool newValue) => setAndNotify(platformAccelerometerRotationKey, newValue); - bool _areAnimationsRemoved = false; + bool get areAnimationsRemoved => getBoolOrDefault(platformTransitionAnimationScaleKey, SettingsDefaults.areAnimationsRemoved); - bool get areAnimationsRemoved => _areAnimationsRemoved; + set areAnimationsRemoved(bool newValue) => setAndNotify(platformTransitionAnimationScaleKey, newValue); // import/export Map export() => Map.fromEntries( - _prefs!.getKeys().whereNot(internalKeys.contains).map((k) => MapEntry(k, _prefs!.get(k))), + settingsStore.getKeys().whereNot(internalKeys.contains).map((k) => MapEntry(k, settingsStore.get(k))), ); Future import(dynamic jsonMap) async { @@ -581,16 +571,16 @@ class Settings extends ChangeNotifier { // apply user modifications jsonMap.forEach((key, value) { if (value == null) { - _prefs!.remove(key); + settingsStore.remove(key); } else if (key.startsWith(tileExtentPrefixKey)) { if (value is double) { - _prefs!.setDouble(key, value); + settingsStore.setDouble(key, value); } else { debugPrint('failed to import key=$key, value=$value is not a double'); } } else if (key.startsWith(tileLayoutPrefixKey)) { if (value is String) { - _prefs!.setString(key, value); + settingsStore.setString(key, value); } else { debugPrint('failed to import key=$key, value=$value is not a string'); } @@ -599,7 +589,7 @@ class Settings extends ChangeNotifier { case subtitleTextColorKey: case subtitleBackgroundColorKey: if (value is int) { - _prefs!.setInt(key, value); + settingsStore.setInt(key, value); } else { debugPrint('failed to import key=$key, value=$value is not an int'); } @@ -607,7 +597,7 @@ class Settings extends ChangeNotifier { case subtitleFontSizeKey: case infoMapZoomKey: if (value is double) { - _prefs!.setDouble(key, value); + settingsStore.setDouble(key, value); } else { debugPrint('failed to import key=$key, value=$value is not a double'); } @@ -635,7 +625,7 @@ class Settings extends ChangeNotifier { case saveSearchHistoryKey: case filePickerShowHiddenFilesKey: if (value is bool) { - _prefs!.setBool(key, value); + settingsStore.setBool(key, value); } else { debugPrint('failed to import key=$key, value=$value is not a bool'); } @@ -658,7 +648,7 @@ class Settings extends ChangeNotifier { case accessibilityAnimationsKey: case timeToTakeActionKey: if (value is String) { - _prefs!.setString(key, value); + settingsStore.setString(key, value); } else { debugPrint('failed to import key=$key, value=$value is not a string'); } @@ -673,7 +663,7 @@ class Settings extends ChangeNotifier { case viewerQuickActionsKey: case videoQuickActionsKey: if (value is List) { - _prefs!.setStringList(key, value.cast()); + settingsStore.setStringList(key, value.cast()); } else { debugPrint('failed to import key=$key, value=$value is not a list'); } diff --git a/lib/model/settings/store/store.dart b/lib/model/settings/store/store.dart new file mode 100644 index 000000000..b12fa639f --- /dev/null +++ b/lib/model/settings/store/store.dart @@ -0,0 +1,37 @@ +abstract class SettingsStore { + bool get initialized; + + Future init(); + + Future clear(); + + Future remove(String key); + + // get + + Set getKeys(); + + Object? get(String key); + + bool? getBool(String key); + + int? getInt(String key); + + double? getDouble(String key); + + String? getString(String key); + + List? getStringList(String key); + + // set + + Future setBool(String key, bool value); + + Future setInt(String key, int value); + + Future setDouble(String key, double value); + + Future setString(String key, String value); + + Future setStringList(String key, List value); +} diff --git a/lib/model/settings/store/store_shared_pref.dart b/lib/model/settings/store/store_shared_pref.dart new file mode 100644 index 000000000..8f5019cf5 --- /dev/null +++ b/lib/model/settings/store/store_shared_pref.dart @@ -0,0 +1,60 @@ +import 'package:aves/model/settings/store/store.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class SharedPrefSettingsStore implements SettingsStore { + static SharedPreferences? _prefs; + + @override + bool get initialized => _prefs != null; + + @override + Future init() async { + _prefs = await SharedPreferences.getInstance(); + } + + @override + Future clear() => _prefs!.clear(); + + @override + Future remove(String key) => _prefs!.remove(key); + + // get + + @override + Set getKeys() => _prefs!.getKeys(); + + @override + Object? get(String key) => _prefs!.get(key); + + @override + bool? getBool(String key) => _prefs!.getBool(key); + + @override + int? getInt(String key) => _prefs!.getInt(key); + + @override + double? getDouble(String key) => _prefs!.getDouble(key); + + @override + String? getString(String key) => _prefs!.getString(key); + + @override + List? getStringList(String key) => _prefs!.getStringList(key); + + // set + + @override + Future setBool(String key, bool value) => _prefs!.setBool(key, value); + + @override + Future setInt(String key, int value) => _prefs!.setInt(key, value); + + @override + Future setDouble(String key, double value) => _prefs!.setDouble(key, value); + + @override + Future setString(String key, String value) => _prefs!.setString(key, value); + + @override + Future setStringList(String key, List value) => _prefs!.setStringList(key, value); +} diff --git a/lib/model/source/album.dart b/lib/model/source/album.dart index 25fe1eb68..6fe52cc1d 100644 --- a/lib/model/source/album.dart +++ b/lib/model/source/album.dart @@ -26,56 +26,9 @@ mixin AlbumMixin on SourceBase { return compareAsciiUpperCase(va, vb); } - void _notifyAlbumChange() => eventBus.fire(AlbumsChangedEvent()); - - String getAlbumDisplayName(BuildContext? context, String dirPath) { - final separator = pContext.separator; - assert(!dirPath.endsWith(separator)); - - if (context != null) { - final type = androidFileUtils.getAlbumType(dirPath); - if (type == AlbumType.camera) return context.l10n.albumCamera; - if (type == AlbumType.download) return context.l10n.albumDownload; - if (type == AlbumType.screenshots) return context.l10n.albumScreenshots; - if (type == AlbumType.screenRecordings) return context.l10n.albumScreenRecordings; - if (type == AlbumType.videoCaptures) return context.l10n.albumVideoCaptures; - } - - final dir = VolumeRelativeDirectory.fromPath(dirPath); - if (dir == null) return dirPath; - - final relativeDir = dir.relativeDir; - if (relativeDir.isEmpty) { - final volume = androidFileUtils.getStorageVolume(dirPath)!; - return volume.getDescription(context); - } - - String unique(String dirPath, Set others) { - final parts = pContext.split(dirPath); - for (var i = parts.length - 1; i > 0; i--) { - final name = pContext.joinAll(['', ...parts.skip(i)]); - final testName = '$separator$name'; - if (others.every((item) => !item!.endsWith(testName))) return name; - } - return dirPath; - } - - final otherAlbumsOnDevice = _directories.where((item) => item != dirPath).toSet(); - final uniqueNameInDevice = unique(dirPath, otherAlbumsOnDevice); - if (uniqueNameInDevice.length <= relativeDir.length) { - return uniqueNameInDevice; - } - - final volumePath = dir.volumePath; - String trimVolumePath(String? path) => path!.substring(dir.volumePath.length); - final otherAlbumsOnVolume = otherAlbumsOnDevice.where((path) => path!.startsWith(volumePath)).map(trimVolumePath).toSet(); - final uniqueNameInVolume = unique(trimVolumePath(dirPath), otherAlbumsOnVolume); - final volume = androidFileUtils.getStorageVolume(dirPath)!; - if (volume.isPrimary) { - return uniqueNameInVolume; - } else { - return '$uniqueNameInVolume (${volume.getDescription(context)})'; - } + void _onAlbumChanged() { + invalidateAlbumDisplayNames(); + eventBus.fire(AlbumsChangedEvent()); } Map getAlbumEntries() { @@ -109,7 +62,7 @@ mixin AlbumMixin on SourceBase { void addDirectories(Set albums) { if (!_directories.containsAll(albums)) { _directories.addAll(albums); - _notifyAlbumChange(); + _onAlbumChanged(); } } @@ -117,7 +70,7 @@ mixin AlbumMixin on SourceBase { final emptyAlbums = (albums ?? _directories).where((v) => _isEmptyAlbum(v) && !_newAlbums.contains(v)).toSet(); if (emptyAlbums.isNotEmpty) { _directories.removeAll(emptyAlbums); - _notifyAlbumChange(); + _onAlbumChanged(); invalidateAlbumFilterSummary(directories: emptyAlbums); final bookmarks = settings.drawerAlbumBookmarks; @@ -165,6 +118,8 @@ mixin AlbumMixin on SourceBase { AvesEntry? albumRecentEntry(AlbumFilter filter) { return _filterRecentEntryMap.putIfAbsent(filter.album, () => sortedEntriesByDate.firstWhereOrNull(filter.test)); } + + // new albums void createAlbum(String directory) { _newAlbums.add(directory); @@ -181,6 +136,80 @@ mixin AlbumMixin on SourceBase { void forgetNewAlbums(Set directories) { _newAlbums.removeAll(directories); } + + // display names + + final Map _albumDisplayNamesWithContext = {}, _albumDisplayNamesWithoutContext = {}; + + void invalidateAlbumDisplayNames() { + _albumDisplayNamesWithContext.clear(); + _albumDisplayNamesWithoutContext.clear(); + } + + String _computeDisplayName(BuildContext? context, String dirPath) { + final separator = pContext.separator; + assert(!dirPath.endsWith(separator)); + + if (context != null) { + final type = androidFileUtils.getAlbumType(dirPath); + switch (type) { + case AlbumType.camera: + return context.l10n.albumCamera; + case AlbumType.download: + return context.l10n.albumDownload; + case AlbumType.screenshots: + return context.l10n.albumScreenshots; + case AlbumType.screenRecordings: + return context.l10n.albumScreenRecordings; + case AlbumType.videoCaptures: + return context.l10n.albumVideoCaptures; + case AlbumType.regular: + case AlbumType.app: + break; + } + } + + final dir = VolumeRelativeDirectory.fromPath(dirPath); + if (dir == null) return dirPath; + + final relativeDir = dir.relativeDir; + if (relativeDir.isEmpty) { + final volume = androidFileUtils.getStorageVolume(dirPath)!; + return volume.getDescription(context); + } + + String unique(String dirPath, Set others) { + final parts = pContext.split(dirPath); + for (var i = parts.length - 1; i > 0; i--) { + final name = pContext.joinAll(['', ...parts.skip(i)]); + final testName = '$separator$name'; + if (others.every((item) => !item!.endsWith(testName))) return name; + } + return dirPath; + } + + final otherAlbumsOnDevice = _directories.where((item) => item != dirPath).toSet(); + final uniqueNameInDevice = unique(dirPath, otherAlbumsOnDevice); + if (uniqueNameInDevice.length <= relativeDir.length) { + return uniqueNameInDevice; + } + + final volumePath = dir.volumePath; + String trimVolumePath(String? path) => path!.substring(dir.volumePath.length); + final otherAlbumsOnVolume = otherAlbumsOnDevice.where((path) => path!.startsWith(volumePath)).map(trimVolumePath).toSet(); + final uniqueNameInVolume = unique(trimVolumePath(dirPath), otherAlbumsOnVolume); + final volume = androidFileUtils.getStorageVolume(dirPath)!; + if (volume.isPrimary) { + return uniqueNameInVolume; + } else { + return '$uniqueNameInVolume (${volume.getDescription(context)})'; + } + } + + String getAlbumDisplayName(BuildContext? context, String dirPath) { + final names = (context != null ? _albumDisplayNamesWithContext : _albumDisplayNamesWithoutContext); + return names.putIfAbsent(dirPath, () => _computeDisplayName(context, dirPath)); + } } class AlbumsChangedEvent {} diff --git a/lib/model/source/collection_lens.dart b/lib/model/source/collection_lens.dart index f94a085a8..301693be0 100644 --- a/lib/model/source/collection_lens.dart +++ b/lib/model/source/collection_lens.dart @@ -68,7 +68,12 @@ class CollectionLens with ChangeNotifier { })); favourites.addListener(_onFavouritesChanged); } - settings.addListener(_onSettingsChanged); + _subscriptions.add(settings.updateStream + .where([ + Settings.collectionSortFactorKey, + Settings.collectionGroupFactorKey, + ].contains) + .listen((_) => _onSettingsChanged())); _refresh(); } @@ -78,7 +83,6 @@ class CollectionLens with ChangeNotifier { ..forEach((sub) => sub.cancel()) ..clear(); favourites.removeListener(_onFavouritesChanged); - settings.removeListener(_onSettingsChanged); super.dispose(); } diff --git a/lib/model/source/collection_source.dart b/lib/model/source/collection_source.dart index 4c1591ba3..0b151aefc 100644 --- a/lib/model/source/collection_source.dart +++ b/lib/model/source/collection_source.dart @@ -39,6 +39,10 @@ mixin SourceBase { } abstract class CollectionSource with SourceBase, AlbumMixin, LocationMixin, TagMixin { + CollectionSource() { + settings.updateStream.where((key) => key == Settings.localeKey).listen((_) => invalidateAlbumDisplayNames()); + } + final EventBus _eventBus = EventBus(); @override diff --git a/lib/model/source/media_store_source.dart b/lib/model/source/media_store_source.dart index 0a88b12d2..d30a663d7 100644 --- a/lib/model/source/media_store_source.dart +++ b/lib/model/source/media_store_source.dart @@ -50,6 +50,16 @@ class MediaStoreSource extends CollectionSource { stateNotifier.value = SourceState.loading; clearEntries(); + final topIds = settings.topEntryIds; + late final Set topEntries; + if (topIds != null) { + debugPrint('$runtimeType refresh ${stopwatch.elapsed} load ${topIds.length} top entries'); + topEntries = await metadataDb.loadEntries(topIds); + addEntries(topEntries); + } else { + topEntries = {}; + } + debugPrint('$runtimeType refresh ${stopwatch.elapsed} fetch known entries'); final oldEntries = await metadataDb.loadAllEntries(); debugPrint('$runtimeType refresh ${stopwatch.elapsed} check obsolete entries'); @@ -57,6 +67,11 @@ class MediaStoreSource extends CollectionSource { final obsoleteContentIds = (await mediaStoreService.checkObsoleteContentIds(knownDateById.keys.toList())).toSet(); oldEntries.removeWhere((entry) => obsoleteContentIds.contains(entry.contentId)); + if (topEntries.isNotEmpty) { + final obsoleteTopEntries = topEntries.where((entry) => obsoleteContentIds.contains(entry.contentId)); + await removeEntries(obsoleteTopEntries.map((entry) => entry.uri).toSet()); + } + // show known entries debugPrint('$runtimeType refresh ${stopwatch.elapsed} add known entries'); addEntries(oldEntries); diff --git a/lib/services/common/services.dart b/lib/services/common/services.dart index 3a877b3d8..2ebcb67dc 100644 --- a/lib/services/common/services.dart +++ b/lib/services/common/services.dart @@ -1,5 +1,8 @@ import 'package:aves/model/availability.dart'; -import 'package:aves/model/metadata_db.dart'; +import 'package:aves/model/db/db_metadata.dart'; +import 'package:aves/model/db/db_metadata_sqflite.dart'; +import 'package:aves/model/settings/store/store.dart'; +import 'package:aves/model/settings/store/store_shared_pref.dart'; import 'package:aves/services/android_app_service.dart'; import 'package:aves/services/device_service.dart'; import 'package:aves/services/media/embedded_data_service.dart'; @@ -19,6 +22,7 @@ final getIt = GetIt.instance; final p.Context pContext = getIt(); final AvesAvailability availability = getIt(); final MetadataDb metadataDb = getIt(); +final SettingsStore settingsStore = getIt(); final AndroidAppService androidAppService = getIt(); final DeviceService deviceService = getIt(); @@ -35,6 +39,7 @@ void initPlatformServices() { getIt.registerLazySingleton(p.Context.new); getIt.registerLazySingleton(LiveAvesAvailability.new); getIt.registerLazySingleton(SqfliteMetadataDb.new); + getIt.registerLazySingleton(SharedPrefSettingsStore.new); getIt.registerLazySingleton(PlatformAndroidAppService.new); getIt.registerLazySingleton(PlatformDeviceService.new); diff --git a/lib/theme/durations.dart b/lib/theme/durations.dart index bed800993..4c91a1685 100644 --- a/lib/theme/durations.dart +++ b/lib/theme/durations.dart @@ -1,4 +1,4 @@ -import 'package:aves/model/settings/accessibility_animations.dart'; +import 'package:aves/model/settings/enums/accessibility_animations.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:flutter/widgets.dart'; import 'package:provider/provider.dart'; diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index d8b8e5d4a..357a1ad85 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -1,12 +1,14 @@ import 'dart:async'; +import 'dart:ui'; import 'package:aves/app_flavor.dart'; import 'package:aves/app_mode.dart'; import 'package:aves/l10n/l10n.dart'; import 'package:aves/model/device.dart'; -import 'package:aves/model/settings/accessibility_animations.dart'; -import 'package:aves/model/settings/screen_on.dart'; +import 'package:aves/model/settings/enums/accessibility_animations.dart'; +import 'package:aves/model/settings/enums/screen_on.dart'; import 'package:aves/model/settings/settings.dart'; +import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_source.dart'; import 'package:aves/model/source/media_store_source.dart'; import 'package:aves/services/accessibility_service.dart'; @@ -16,12 +18,15 @@ import 'package:aves/theme/icons.dart'; import 'package:aves/theme/themes.dart'; import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/utils/debouncer.dart'; +import 'package:aves/widgets/collection/collection_grid.dart'; +import 'package:aves/widgets/collection/collection_page.dart'; import 'package:aves/widgets/common/behaviour/route_tracker.dart'; import 'package:aves/widgets/common/behaviour/routes.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/providers/highlight_info_provider.dart'; import 'package:aves/widgets/home_page.dart'; import 'package:aves/widgets/welcome_page.dart'; +import 'package:collection/collection.dart'; import 'package:equatable/equatable.dart'; import 'package:fijkplayer/fijkplayer.dart'; import 'package:flutter/foundation.dart'; @@ -43,7 +48,7 @@ class AvesApp extends StatefulWidget { _AvesAppState createState() => _AvesAppState(); } -class _AvesAppState extends State { +class _AvesAppState extends State with WidgetsBindingObserver { final ValueNotifier appModeNotifier = ValueNotifier(AppMode.main); late Future _appSetup; final _mediaStoreSource = MediaStoreSource(); @@ -70,6 +75,7 @@ class _AvesAppState extends State { _newIntentChannel.receiveBroadcastStream().listen((event) => _onNewIntent(event as Map?)); _analysisCompletionChannel.receiveBroadcastStream().listen((event) => _onAnalysisCompletion()); _errorChannel.receiveBroadcastStream().listen((event) => _onError(event as String?)); + WidgetsBinding.instance!.addObserver(this); } @override @@ -158,26 +164,45 @@ class _AvesAppState extends State { ); } + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + debugPrint('$runtimeType lifecycle ${state.name}'); + switch (state) { + case AppLifecycleState.inactive: + _saveTopEntries(); + break; + case AppLifecycleState.paused: + case AppLifecycleState.detached: + case AppLifecycleState.resumed: + break; + } + } + + // save IDs of entries visible at the top of the collection page with current layout settings + void _saveTopEntries() { + final stopwatch = Stopwatch()..start(); + final screenSize = window.physicalSize / window.devicePixelRatio; + var tileExtent = settings.getTileExtent(CollectionPage.routeName); + if (tileExtent == 0) { + tileExtent = screenSize.shortestSide / CollectionGrid.columnCountDefault; + } + final rows = (screenSize.height / tileExtent).ceil(); + final columns = (screenSize.width / tileExtent).ceil(); + final count = rows * columns; + final collection = CollectionLens(source: _mediaStoreSource, listenToSource: false); + settings.topEntryIds = collection.sortedEntries.take(count).map((entry) => entry.contentId).whereNotNull().toList(); + collection.dispose(); + debugPrint('Saved $count top entries in ${stopwatch.elapsed.inMilliseconds}ms'); + } + // setup before the first page is displayed. keep it short Future _setup() async { final stopwatch = Stopwatch()..start(); - // TODO TLAD [init] init settings/device w/o platform calls (first platform channel call takes ~800ms): - // 1) use cached values if any, - // 2a) call platform w/ delay if cached - // 2b) call platform w/o delay if not cached - // 3) cache platform call results across app restarts - await device.init(); - final isRotationLocked = await windowService.isRotationLocked(); - final areAnimationsRemoved = await AccessibilityService.areAnimationsRemoved(); - - // TODO TLAD [init] migrate settings away from `shared_preferences` to a platform-free solution - await settings.init( - monitorPlatformSettings: true, - isRotationLocked: isRotationLocked, - areAnimationsRemoved: areAnimationsRemoved, - ); + await settings.init(monitorPlatformSettings: true); + settings.isRotationLocked = await windowService.isRotationLocked(); + settings.areAnimationsRemoved = await AccessibilityService.areAnimationsRemoved(); _monitorSettings(); FijkLog.setLevel(FijkLogLevel.Warn); @@ -187,22 +212,30 @@ class _AvesAppState extends State { } void _monitorSettings() { - // keep screen on - settings.updateStream.where((key) => key == Settings.keepScreenOnKey).listen( - (_) => settings.keepScreenOn.apply(), - ); - settings.keepScreenOn.apply(); + void applyIsInstalledAppAccessAllowed() { + if (settings.isInstalledAppAccessAllowed) { + androidFileUtils.initAppNames(); + } else { + androidFileUtils.resetAppNames(); + } + } - // installed app access - settings.updateStream.where((key) => key == Settings.isInstalledAppAccessAllowedKey).listen( - (_) { - if (settings.isInstalledAppAccessAllowed) { - androidFileUtils.initAppNames(); - } else { - androidFileUtils.resetAppNames(); - } - }, - ); + void applyKeepScreenOn() { + settings.keepScreenOn.apply(); + } + + void applyIsRotationLocked() { + if (!settings.isRotationLocked) { + windowService.requestOrientation(); + } + } + + settings.updateStream.where((key) => key == Settings.isInstalledAppAccessAllowedKey).listen((_) => applyIsInstalledAppAccessAllowed()); + settings.updateStream.where((key) => key == Settings.keepScreenOnKey).listen((_) => applyKeepScreenOn()); + settings.updateStream.where((key) => key == Settings.platformAccelerometerRotationKey).listen((_) => applyIsRotationLocked()); + + applyKeepScreenOn(); + applyIsRotationLocked(); } Future _setupErrorReporting() async { diff --git a/lib/widgets/collection/collection_grid.dart b/lib/widgets/collection/collection_grid.dart index 4041019b6..0c599becc 100644 --- a/lib/widgets/collection/collection_grid.dart +++ b/lib/widgets/collection/collection_grid.dart @@ -39,6 +39,11 @@ import 'package:tuple/tuple.dart'; class CollectionGrid extends StatefulWidget { final String? settingsRouteKey; + static const int columnCountDefault = 4; + static const double extentMin = 46; + static const double extentMax = 300; + static const double spacing = 2; + const CollectionGrid({ Key? key, this.settingsRouteKey, @@ -61,9 +66,10 @@ class _CollectionGridState extends State { Widget build(BuildContext context) { _tileExtentController ??= TileExtentController( settingsRouteKey: widget.settingsRouteKey ?? context.currentRouteName!, - columnCountDefault: 4, - extentMin: 46, - spacing: 2, + columnCountDefault: CollectionGrid.columnCountDefault, + extentMin: CollectionGrid.extentMin, + extentMax: CollectionGrid.extentMax, + spacing: CollectionGrid.spacing, ); return TileExtentControllerProvider( controller: _tileExtentController!, diff --git a/lib/widgets/collection/grid/list_details.dart b/lib/widgets/collection/grid/list_details.dart index 5170b5327..98d2a6636 100644 --- a/lib/widgets/collection/grid/list_details.dart +++ b/lib/widgets/collection/grid/list_details.dart @@ -1,5 +1,5 @@ import 'package:aves/model/entry.dart'; -import 'package:aves/model/settings/coordinate_format.dart'; +import 'package:aves/model/settings/enums/coordinate_format.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/theme/format.dart'; import 'package:aves/theme/icons.dart'; diff --git a/lib/widgets/common/action_mixins/feedback.dart b/lib/widgets/common/action_mixins/feedback.dart index 08b53b5cc..b3ab4343d 100644 --- a/lib/widgets/common/action_mixins/feedback.dart +++ b/lib/widgets/common/action_mixins/feedback.dart @@ -1,8 +1,8 @@ import 'dart:async'; import 'dart:math'; -import 'package:aves/model/settings/accessibility_animations.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/accessibility_animations.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/services/accessibility_service.dart'; import 'package:aves/theme/durations.dart'; diff --git a/lib/widgets/common/identity/aves_filter_chip.dart b/lib/widgets/common/identity/aves_filter_chip.dart index b8504df7d..7061b9f99 100644 --- a/lib/widgets/common/identity/aves_filter_chip.dart +++ b/lib/widgets/common/identity/aves_filter_chip.dart @@ -4,7 +4,7 @@ import 'package:aves/model/filters/album.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/location.dart'; import 'package:aves/model/filters/tag.dart'; -import 'package:aves/model/settings/accessibility_animations.dart'; +import 'package:aves/model/settings/enums/accessibility_animations.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/theme/icons.dart'; diff --git a/lib/widgets/common/map/attribution.dart b/lib/widgets/common/map/attribution.dart index 030c68caf..afeb94a2b 100644 --- a/lib/widgets/common/map/attribution.dart +++ b/lib/widgets/common/map/attribution.dart @@ -1,4 +1,4 @@ -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/viewer/info/common.dart'; import 'package:flutter/material.dart'; diff --git a/lib/widgets/common/map/buttons.dart b/lib/widgets/common/map/buttons.dart index 0a933970d..48223c7cb 100644 --- a/lib/widgets/common/map/buttons.dart +++ b/lib/widgets/common/map/buttons.dart @@ -1,6 +1,6 @@ import 'package:aves/model/filters/coordinate.dart'; -import 'package:aves/model/settings/enums.dart'; -import 'package:aves/model/settings/map_style.dart'; +import 'package:aves/model/settings/enums/enums.dart'; +import 'package:aves/model/settings/enums/map_style.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves/theme/durations.dart'; diff --git a/lib/widgets/common/map/geo_map.dart b/lib/widgets/common/map/geo_map.dart index ffd8176a6..b9862fdee 100644 --- a/lib/widgets/common/map/geo_map.dart +++ b/lib/widgets/common/map/geo_map.dart @@ -2,8 +2,8 @@ import 'dart:async'; import 'dart:math'; import 'package:aves/model/entry.dart'; -import 'package:aves/model/settings/enums.dart'; -import 'package:aves/model/settings/map_style.dart'; +import 'package:aves/model/settings/enums/enums.dart'; +import 'package:aves/model/settings/enums/map_style.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/utils/change_notifier.dart'; diff --git a/lib/widgets/common/map/google/map.dart b/lib/widgets/common/map/google/map.dart index c00462773..1cf44550d 100644 --- a/lib/widgets/common/map/google/map.dart +++ b/lib/widgets/common/map/google/map.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:aves/model/entry_images.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/utils/change_notifier.dart'; import 'package:aves/widgets/common/map/buttons.dart'; import 'package:aves/widgets/common/map/controller.dart'; diff --git a/lib/widgets/common/map/leaflet/map.dart b/lib/widgets/common/map/leaflet/map.dart index f04a5d464..600a10f1b 100644 --- a/lib/widgets/common/map/leaflet/map.dart +++ b/lib/widgets/common/map/leaflet/map.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/utils/debouncer.dart'; diff --git a/lib/widgets/common/map/leaflet/scale_layer.dart b/lib/widgets/common/map/leaflet/scale_layer.dart index 32b0dd69b..37e76093c 100644 --- a/lib/widgets/common/map/leaflet/scale_layer.dart +++ b/lib/widgets/common/map/leaflet/scale_layer.dart @@ -1,4 +1,4 @@ -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/widgets/common/basic/outlined_text.dart'; import 'package:aves/widgets/common/map/leaflet/scalebar_utils.dart'; import 'package:flutter/material.dart'; diff --git a/lib/widgets/common/thumbnail/image.dart b/lib/widgets/common/thumbnail/image.dart index 3edba69d8..0a6961070 100644 --- a/lib/widgets/common/thumbnail/image.dart +++ b/lib/widgets/common/thumbnail/image.dart @@ -4,9 +4,9 @@ import 'dart:ui'; import 'package:aves/image_providers/thumbnail_provider.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/entry_images.dart'; -import 'package:aves/model/settings/accessibility_animations.dart'; -import 'package:aves/model/settings/entry_background.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/accessibility_animations.dart'; +import 'package:aves/model/settings/enums/entry_background.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves/widgets/common/fx/checkered_decoration.dart'; diff --git a/lib/widgets/common/tile_extent_controller.dart b/lib/widgets/common/tile_extent_controller.dart index 1e39af61e..5a055a2ed 100644 --- a/lib/widgets/common/tile_extent_controller.dart +++ b/lib/widgets/common/tile_extent_controller.dart @@ -20,7 +20,7 @@ class TileExtentController { this.columnCountMin = 2, required this.columnCountDefault, required this.extentMin, - this.extentMax = 300, + required this.extentMax, required this.spacing, }) { userPreferredExtent = settings.getTileExtent(settingsRouteKey); diff --git a/lib/widgets/debug/settings.dart b/lib/widgets/debug/settings.dart index de9cf5806..81bded031 100644 --- a/lib/widgets/debug/settings.dart +++ b/lib/widgets/debug/settings.dart @@ -68,6 +68,7 @@ class DebugSettingsSection extends StatelessWidget { 'searchHistory': toMultiline(settings.searchHistory), 'locale': '${settings.locale}', 'systemLocales': '${WidgetsBinding.instance!.window.locales}', + 'topEntryIds': '${settings.topEntryIds}', }, ), ), diff --git a/lib/widgets/dialogs/location_pick_dialog.dart b/lib/widgets/dialogs/location_pick_dialog.dart index ecdd98f5d..ce0cf1e65 100644 --- a/lib/widgets/dialogs/location_pick_dialog.dart +++ b/lib/widgets/dialogs/location_pick_dialog.dart @@ -1,7 +1,7 @@ import 'dart:async'; -import 'package:aves/model/settings/coordinate_format.dart'; -import 'package:aves/model/settings/map_style.dart'; +import 'package:aves/model/settings/enums/coordinate_format.dart'; +import 'package:aves/model/settings/enums/map_style.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/services/common/services.dart'; diff --git a/lib/widgets/filter_grids/common/filter_grid_page.dart b/lib/widgets/filter_grids/common/filter_grid_page.dart index e9e098ddc..387513474 100644 --- a/lib/widgets/filter_grids/common/filter_grid_page.dart +++ b/lib/widgets/filter_grids/common/filter_grid_page.dart @@ -164,6 +164,7 @@ class _FilterGridState extends State> settingsRouteKey: widget.settingsRouteKey ?? context.currentRouteName!, columnCountDefault: 3, extentMin: 60, + extentMax: 300, spacing: 8, ); return TileExtentControllerProvider( diff --git a/lib/widgets/home_page.dart b/lib/widgets/home_page.dart index 980b4531a..8e0e1dcfe 100644 --- a/lib/widgets/home_page.dart +++ b/lib/widgets/home_page.dart @@ -4,7 +4,7 @@ import 'package:aves/app_mode.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/filters/album.dart'; import 'package:aves/model/filters/filters.dart'; -import 'package:aves/model/settings/home_page.dart'; +import 'package:aves/model/settings/enums/home_page.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_source.dart'; diff --git a/lib/widgets/map/map_info_row.dart b/lib/widgets/map/map_info_row.dart index 53ad3c54f..093acf11a 100644 --- a/lib/widgets/map/map_info_row.dart +++ b/lib/widgets/map/map_info_row.dart @@ -1,5 +1,5 @@ import 'package:aves/model/entry.dart'; -import 'package:aves/model/settings/coordinate_format.dart'; +import 'package:aves/model/settings/enums/coordinate_format.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves/services/geocoding_service.dart'; diff --git a/lib/widgets/map/map_page.dart b/lib/widgets/map/map_page.dart index 214dd0398..61195d8a6 100644 --- a/lib/widgets/map/map_page.dart +++ b/lib/widgets/map/map_page.dart @@ -4,8 +4,8 @@ import 'package:aves/model/entry.dart'; import 'package:aves/model/filters/coordinate.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/highlight.dart'; -import 'package:aves/model/settings/enums.dart'; -import 'package:aves/model/settings/map_style.dart'; +import 'package:aves/model/settings/enums/enums.dart'; +import 'package:aves/model/settings/enums/map_style.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/theme/durations.dart'; diff --git a/lib/widgets/settings/accessibility/remove_animations.dart b/lib/widgets/settings/accessibility/remove_animations.dart index bf257867f..bf3095cef 100644 --- a/lib/widgets/settings/accessibility/remove_animations.dart +++ b/lib/widgets/settings/accessibility/remove_animations.dart @@ -1,5 +1,5 @@ -import 'package:aves/model/settings/accessibility_animations.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/accessibility_animations.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; diff --git a/lib/widgets/settings/accessibility/time_to_take_action.dart b/lib/widgets/settings/accessibility/time_to_take_action.dart index 75ceb0cb9..ced0e082d 100644 --- a/lib/widgets/settings/accessibility/time_to_take_action.dart +++ b/lib/widgets/settings/accessibility/time_to_take_action.dart @@ -1,5 +1,5 @@ -import 'package:aves/model/settings/accessibility_timeout.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/accessibility_timeout.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/services/accessibility_service.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; diff --git a/lib/widgets/settings/language/language.dart b/lib/widgets/settings/language/language.dart index d83ca6989..4baf94b13 100644 --- a/lib/widgets/settings/language/language.dart +++ b/lib/widgets/settings/language/language.dart @@ -1,7 +1,7 @@ -import 'package:aves/model/settings/coordinate_format.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/coordinate_format.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; -import 'package:aves/model/settings/unit_system.dart'; +import 'package:aves/model/settings/enums/unit_system.dart'; import 'package:aves/theme/icons.dart'; import 'package:aves/utils/color_utils.dart'; import 'package:aves/utils/constants.dart'; diff --git a/lib/widgets/settings/navigation/navigation.dart b/lib/widgets/settings/navigation/navigation.dart index 50f8252fa..57c6c5c51 100644 --- a/lib/widgets/settings/navigation/navigation.dart +++ b/lib/widgets/settings/navigation/navigation.dart @@ -1,6 +1,6 @@ -import 'package:aves/model/settings/enums.dart'; -import 'package:aves/model/settings/home_page.dart'; -import 'package:aves/model/settings/screen_on.dart'; +import 'package:aves/model/settings/enums/enums.dart'; +import 'package:aves/model/settings/enums/home_page.dart'; +import 'package:aves/model/settings/enums/screen_on.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/theme/icons.dart'; import 'package:aves/utils/color_utils.dart'; diff --git a/lib/widgets/settings/video/video.dart b/lib/widgets/settings/video/video.dart index 52fa4b2b3..9d2c48c1f 100644 --- a/lib/widgets/settings/video/video.dart +++ b/lib/widgets/settings/video/video.dart @@ -1,7 +1,7 @@ import 'package:aves/model/filters/mime.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; -import 'package:aves/model/settings/video_loop_mode.dart'; +import 'package:aves/model/settings/enums/video_loop_mode.dart'; import 'package:aves/model/source/collection_source.dart'; import 'package:aves/theme/icons.dart'; import 'package:aves/utils/color_utils.dart'; diff --git a/lib/widgets/settings/viewer/entry_background.dart b/lib/widgets/settings/viewer/entry_background.dart index 23a9017e0..2786129bd 100644 --- a/lib/widgets/settings/viewer/entry_background.dart +++ b/lib/widgets/settings/viewer/entry_background.dart @@ -1,5 +1,5 @@ -import 'package:aves/model/settings/entry_background.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/entry_background.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/widgets/common/fx/borders.dart'; import 'package:aves/widgets/common/fx/checkered_decoration.dart'; import 'package:flutter/material.dart'; diff --git a/lib/widgets/settings/viewer/viewer.dart b/lib/widgets/settings/viewer/viewer.dart index 3e0ddb026..cb1531f60 100644 --- a/lib/widgets/settings/viewer/viewer.dart +++ b/lib/widgets/settings/viewer/viewer.dart @@ -1,4 +1,4 @@ -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves/theme/icons.dart'; diff --git a/lib/widgets/stats/stats_page.dart b/lib/widgets/stats/stats_page.dart index 350df4fa5..32db49dae 100644 --- a/lib/widgets/stats/stats_page.dart +++ b/lib/widgets/stats/stats_page.dart @@ -6,7 +6,7 @@ import 'package:aves/model/filters/location.dart'; import 'package:aves/model/filters/mime.dart'; import 'package:aves/model/filters/rating.dart'; import 'package:aves/model/filters/tag.dart'; -import 'package:aves/model/settings/accessibility_animations.dart'; +import 'package:aves/model/settings/enums/accessibility_animations.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_source.dart'; diff --git a/lib/widgets/viewer/entry_horizontal_pager.dart b/lib/widgets/viewer/entry_horizontal_pager.dart index 86eddea63..a2dc6463d 100644 --- a/lib/widgets/viewer/entry_horizontal_pager.dart +++ b/lib/widgets/viewer/entry_horizontal_pager.dart @@ -1,5 +1,5 @@ import 'package:aves/model/entry.dart'; -import 'package:aves/model/settings/accessibility_animations.dart'; +import 'package:aves/model/settings/enums/accessibility_animations.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/widgets/common/magnifier/pan/gesture_detector_scope.dart'; diff --git a/lib/widgets/viewer/entry_viewer_stack.dart b/lib/widgets/viewer/entry_viewer_stack.dart index 67cd51461..cbf054fa4 100644 --- a/lib/widgets/viewer/entry_viewer_stack.dart +++ b/lib/widgets/viewer/entry_viewer_stack.dart @@ -4,7 +4,7 @@ import 'package:aves/model/device.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/highlight.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/services/common/services.dart'; diff --git a/lib/widgets/viewer/info/location_section.dart b/lib/widgets/viewer/info/location_section.dart index d216417ff..767e0dd8b 100644 --- a/lib/widgets/viewer/info/location_section.dart +++ b/lib/widgets/viewer/info/location_section.dart @@ -1,6 +1,6 @@ import 'package:aves/model/entry.dart'; import 'package:aves/model/filters/location.dart'; -import 'package:aves/model/settings/coordinate_format.dart'; +import 'package:aves/model/settings/enums/coordinate_format.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/services/common/services.dart'; diff --git a/lib/widgets/viewer/overlay/bottom/common.dart b/lib/widgets/viewer/overlay/bottom/common.dart index f30eda557..38e1b9912 100644 --- a/lib/widgets/viewer/overlay/bottom/common.dart +++ b/lib/widgets/viewer/overlay/bottom/common.dart @@ -3,7 +3,7 @@ import 'dart:math'; import 'package:aves/model/entry.dart'; import 'package:aves/model/metadata/overlay.dart'; import 'package:aves/model/multipage.dart'; -import 'package:aves/model/settings/coordinate_format.dart'; +import 'package:aves/model/settings/enums/coordinate_format.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves/theme/durations.dart'; diff --git a/lib/widgets/viewer/video/fijkplayer.dart b/lib/widgets/viewer/video/fijkplayer.dart index f04f0f164..24c5e7bf2 100644 --- a/lib/widgets/viewer/video/fijkplayer.dart +++ b/lib/widgets/viewer/video/fijkplayer.dart @@ -4,7 +4,7 @@ import 'dart:typed_data'; import 'package:aves/model/entry.dart'; import 'package:aves/model/settings/settings.dart'; -import 'package:aves/model/settings/video_loop_mode.dart'; +import 'package:aves/model/settings/enums/video_loop_mode.dart'; import 'package:aves/model/video/keys.dart'; import 'package:aves/model/video/metadata.dart'; import 'package:aves/utils/change_notifier.dart'; diff --git a/lib/widgets/viewer/visual/entry_page_view.dart b/lib/widgets/viewer/visual/entry_page_view.dart index 38a05b853..cb754bd1b 100644 --- a/lib/widgets/viewer/visual/entry_page_view.dart +++ b/lib/widgets/viewer/visual/entry_page_view.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:aves/model/entry.dart'; import 'package:aves/model/entry_images.dart'; -import 'package:aves/model/settings/accessibility_animations.dart'; +import 'package:aves/model/settings/enums/accessibility_animations.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/widgets/common/magnifier/controller/controller.dart'; diff --git a/lib/widgets/viewer/visual/raster.dart b/lib/widgets/viewer/visual/raster.dart index 5e1ac19f3..98ca8534e 100644 --- a/lib/widgets/viewer/visual/raster.dart +++ b/lib/widgets/viewer/visual/raster.dart @@ -3,8 +3,8 @@ import 'dart:math'; import 'package:aves/image_providers/region_provider.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/entry_images.dart'; -import 'package:aves/model/settings/entry_background.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/entry_background.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/utils/math_utils.dart'; import 'package:aves/widgets/common/fx/checkered_decoration.dart'; diff --git a/lib/widgets/viewer/visual/vector.dart b/lib/widgets/viewer/visual/vector.dart index a2ae34d07..3901b8c35 100644 --- a/lib/widgets/viewer/visual/vector.dart +++ b/lib/widgets/viewer/visual/vector.dart @@ -4,8 +4,8 @@ import 'dart:ui'; import 'package:aves/image_providers/region_provider.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/entry_images.dart'; -import 'package:aves/model/settings/entry_background.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/entry_background.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/utils/math_utils.dart'; import 'package:aves/widgets/common/fx/checkered_decoration.dart'; diff --git a/test/fake/metadata_db.dart b/test/fake/metadata_db.dart index 40042d0f8..595d2265e 100644 --- a/test/fake/metadata_db.dart +++ b/test/fake/metadata_db.dart @@ -4,7 +4,7 @@ import 'package:aves/model/favourites.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/metadata/address.dart'; import 'package:aves/model/metadata/catalog.dart'; -import 'package:aves/model/metadata_db.dart'; +import 'package:aves/model/db/db_metadata.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/test/model/collection_source_test.dart b/test/model/collection_source_test.dart index b641e886a..d468d024b 100644 --- a/test/model/collection_source_test.dart +++ b/test/model/collection_source_test.dart @@ -7,7 +7,7 @@ import 'package:aves/model/filters/album.dart'; import 'package:aves/model/filters/tag.dart'; import 'package:aves/model/metadata/address.dart'; import 'package:aves/model/metadata/catalog.dart'; -import 'package:aves/model/metadata_db.dart'; +import 'package:aves/model/db/db_metadata.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/enums.dart'; import 'package:aves/model/source/media_store_source.dart'; diff --git a/test/utils/geo_utils_test.dart b/test/utils/geo_utils_test.dart index 7c3f627ef..5f2cf7ecd 100644 --- a/test/utils/geo_utils_test.dart +++ b/test/utils/geo_utils_test.dart @@ -1,5 +1,5 @@ import 'package:aves/l10n/l10n.dart'; -import 'package:aves/model/settings/coordinate_format.dart'; +import 'package:aves/model/settings/enums/coordinate_format.dart'; import 'package:aves/utils/geo_utils.dart'; import 'package:latlong2/latlong.dart'; import 'package:test/test.dart'; diff --git a/test_driver/driver_screenshots.dart b/test_driver/driver_screenshots.dart index 652746749..cc1a095be 100644 --- a/test_driver/driver_screenshots.dart +++ b/test_driver/driver_screenshots.dart @@ -1,6 +1,6 @@ import 'package:aves/main_play.dart' as app; import 'package:aves/model/settings/defaults.dart'; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/enums.dart'; import 'package:aves/widgets/filter_grids/countries_page.dart'; diff --git a/test_driver/driver_shaders.dart b/test_driver/driver_shaders.dart index e8fe57ad6..5c9a1e65e 100644 --- a/test_driver/driver_shaders.dart +++ b/test_driver/driver_shaders.dart @@ -1,7 +1,7 @@ import 'dart:ui'; import 'package:aves/main_play.dart' as app; -import 'package:aves/model/settings/enums.dart'; +import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart';