From 04745d69734f26f831645b8b8a4cba9b6176d1e9 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Fri, 23 Jun 2023 22:06:36 +0200 Subject: [PATCH] settings split, ijk player package --- lib/model/settings/defaults.dart | 23 - lib/model/settings/modules/app.dart | 109 ++ lib/model/settings/modules/collection.dart | 56 + lib/model/settings/modules/display.dart | 37 + lib/model/settings/modules/filter_grids.dart | 74 ++ lib/model/settings/modules/info.dart | 16 + lib/model/settings/modules/navigation.dart | 62 + lib/model/settings/modules/search.dart | 14 + lib/model/settings/modules/viewer.dart | 52 + lib/model/settings/settings.dart | 1154 ++++------------- .../{store => }/store_shared_pref.dart | 2 +- lib/model/source/collection_lens.dart | 8 +- lib/model/source/collection_source.dart | 4 +- lib/model/video/metadata.dart | 7 +- lib/services/analysis_service.dart | 2 - lib/services/common/services.dart | 4 +- lib/widgets/aves_app.dart | 16 +- lib/widgets/collection/collection_page.dart | 3 +- .../grid/sections/fixed/scale_overlay.dart | 2 +- .../grid/sections/mosaic/scale_overlay.dart | 2 +- .../common/identity/aves_filter_chip.dart | 2 +- .../common/tile_extent_controller.dart | 8 +- lib/widgets/viewer/video/conductor.dart | 8 +- plugins/aves_model/lib/aves_model.dart | 4 + .../aves_model/lib/src/settings/access.dart | 105 ++ .../aves_model/lib/src/settings/event.dart | 11 + plugins/aves_model/lib/src/settings/keys.dart | 185 +++ .../aves_model/lib/src/settings}/store.dart | 0 plugins/aves_model/pubspec.lock | 2 +- plugins/aves_model/pubspec.yaml | 1 + plugins/aves_services_google/pubspec.lock | 8 +- plugins/aves_utils/lib/aves_utils.dart | 1 + .../aves_utils/lib/src}/colors.dart | 0 plugins/aves_video/lib/aves_video.dart | 3 + plugins/aves_video/lib/src/controller.dart | 8 +- .../aves_video/lib/src/settings/defaults.dart | 26 + .../lib/src/settings/subtitles.dart | 30 + .../aves_video/lib/src/settings/video.dart | 40 + .../aves_video/lib/src}/video_loop_mode.dart | 0 plugins/aves_video/pubspec.lock | 7 + plugins/aves_video/pubspec.yaml | 2 + plugins/aves_video_ijk/.gitignore | 30 + plugins/aves_video_ijk/.metadata | 10 + plugins/aves_video_ijk/analysis_options.yaml | 1 + .../aves_video_ijk/lib/aves_video_ijk.dart | 3 + .../aves_video_ijk/lib/src/controller.dart | 13 +- plugins/aves_video_ijk/pubspec.lock | 117 ++ plugins/aves_video_ijk/pubspec.yaml | 26 + pubspec.lock | 23 +- pubspec.yaml | 2 + 50 files changed, 1319 insertions(+), 1004 deletions(-) create mode 100644 lib/model/settings/modules/app.dart create mode 100644 lib/model/settings/modules/collection.dart create mode 100644 lib/model/settings/modules/display.dart create mode 100644 lib/model/settings/modules/filter_grids.dart create mode 100644 lib/model/settings/modules/info.dart create mode 100644 lib/model/settings/modules/navigation.dart create mode 100644 lib/model/settings/modules/search.dart create mode 100644 lib/model/settings/modules/viewer.dart rename lib/model/settings/{store => }/store_shared_pref.dart (96%) create mode 100644 plugins/aves_model/lib/src/settings/access.dart create mode 100644 plugins/aves_model/lib/src/settings/event.dart create mode 100644 plugins/aves_model/lib/src/settings/keys.dart rename {lib/model/settings/store => plugins/aves_model/lib/src/settings}/store.dart (100%) rename {lib/utils => plugins/aves_utils/lib/src}/colors.dart (100%) create mode 100644 plugins/aves_video/lib/src/settings/defaults.dart create mode 100644 plugins/aves_video/lib/src/settings/subtitles.dart create mode 100644 plugins/aves_video/lib/src/settings/video.dart rename {lib/model/settings/enums => plugins/aves_video/lib/src}/video_loop_mode.dart (100%) create mode 100644 plugins/aves_video_ijk/.gitignore create mode 100644 plugins/aves_video_ijk/.metadata create mode 100644 plugins/aves_video_ijk/analysis_options.yaml create mode 100644 plugins/aves_video_ijk/lib/aves_video_ijk.dart rename lib/widgets/viewer/video/fijkplayer.dart => plugins/aves_video_ijk/lib/src/controller.dart (98%) create mode 100644 plugins/aves_video_ijk/pubspec.lock create mode 100644 plugins/aves_video_ijk/pubspec.yaml diff --git a/lib/model/settings/defaults.dart b/lib/model/settings/defaults.dart index 8c24ecf29..ce55394e4 100644 --- a/lib/model/settings/defaults.dart +++ b/lib/model/settings/defaults.dart @@ -1,9 +1,6 @@ -import 'dart:ui'; - import 'package:aves/model/filters/recent.dart'; import 'package:aves/model/naming_pattern.dart'; import 'package:aves/ref/mime_types.dart'; -import 'package:aves/utils/colors.dart'; import 'package:aves/widgets/filter_grids/albums_page.dart'; import 'package:aves/widgets/filter_grids/countries_page.dart'; import 'package:aves/widgets/filter_grids/tags_page.dart'; @@ -84,26 +81,6 @@ class SettingsDefaults { static const viewerUseCutout = true; static const enableMotionPhotoAutoPlay = false; - // video - static const enableVideoHardwareAcceleration = true; - static const videoAutoPlayMode = VideoAutoPlayMode.disabled; - static const videoBackgroundMode = VideoBackgroundMode.disabled; - static const videoLoopMode = VideoLoopMode.shortOnly; - static const videoResumptionMode = VideoResumptionMode.ask; - static const videoShowRawTimedText = false; - static const videoControls = VideoControls.play; - static const videoGestureDoubleTapTogglePlay = false; - static const videoGestureSideDoubleTapSeek = true; - static const videoGestureVerticalDragBrightnessVolume = false; - - // subtitles - static const subtitleFontSize = 20.0; - static const subtitleTextAlignment = TextAlign.center; - static const subtitleTextPosition = SubtitlePosition.bottom; - static const subtitleShowOutline = true; - static const subtitleTextColor = Color(0xFFFFFFFF); - static const subtitleBackgroundColor = ColorUtils.transparentBlack; - // info static const infoMapZoom = 12.0; static const coordinateFormat = CoordinateFormat.dms; diff --git a/lib/model/settings/modules/app.dart b/lib/model/settings/modules/app.dart new file mode 100644 index 000000000..a4b1f9f86 --- /dev/null +++ b/lib/model/settings/modules/app.dart @@ -0,0 +1,109 @@ +import 'package:aves/model/filters/filters.dart'; +import 'package:aves/model/settings/defaults.dart'; +import 'package:aves/widgets/aves_app.dart'; +import 'package:aves_model/aves_model.dart'; +import 'package:collection/collection.dart'; +import 'package:flutter/widgets.dart'; + +mixin AppSettings on SettingsAccess { + static const int _recentFilterHistoryMax = 10; + + bool get hasAcceptedTerms => getBool(SettingKeys.hasAcceptedTermsKey) ?? SettingsDefaults.hasAcceptedTerms; + + set hasAcceptedTerms(bool newValue) => set(SettingKeys.hasAcceptedTermsKey, newValue); + + bool get canUseAnalysisService => getBool(SettingKeys.canUseAnalysisServiceKey) ?? SettingsDefaults.canUseAnalysisService; + + set canUseAnalysisService(bool newValue) => set(SettingKeys.canUseAnalysisServiceKey, newValue); + + bool get isInstalledAppAccessAllowed => getBool(SettingKeys.isInstalledAppAccessAllowedKey) ?? SettingsDefaults.isInstalledAppAccessAllowed; + + set isInstalledAppAccessAllowed(bool newValue) => set(SettingKeys.isInstalledAppAccessAllowedKey, newValue); + + bool get isErrorReportingAllowed => getBool(SettingKeys.isErrorReportingAllowedKey) ?? SettingsDefaults.isErrorReportingAllowed; + + set isErrorReportingAllowed(bool newValue) => set(SettingKeys.isErrorReportingAllowedKey, newValue); + + static const localeSeparator = '-'; + + Locale? get locale { + // exceptionally allow getting locale before settings are initialized + final tag = initialized ? getString(SettingKeys.localeKey) : null; + if (tag != null) { + final codes = tag.split(localeSeparator); + return Locale.fromSubtags( + languageCode: codes[0], + scriptCode: codes[1] == '' ? null : codes[1], + countryCode: codes[2] == '' ? null : codes[2], + ); + } + return null; + } + + set locale(Locale? newValue) { + String? tag; + if (newValue != null) { + tag = [ + newValue.languageCode, + newValue.scriptCode ?? '', + newValue.countryCode ?? '', + ].join(localeSeparator); + } + set(SettingKeys.localeKey, tag); + _appliedLocale = null; + } + + List _systemLocalesFallback = []; + + set systemLocalesFallback(List locales) => _systemLocalesFallback = locales; + + Locale? _appliedLocale; + + void resetAppliedLocale() => _appliedLocale = null; + + Locale get appliedLocale { + if (_appliedLocale == null) { + final _locale = locale; + final preferredLocales = []; + if (_locale != null) { + preferredLocales.add(_locale); + } else { + preferredLocales.addAll(WidgetsBinding.instance.platformDispatcher.locales); + if (preferredLocales.isEmpty) { + // the `window` locales may be empty in a window-less service context + preferredLocales.addAll(_systemLocalesFallback); + } + } + _appliedLocale = basicLocaleListResolution(preferredLocales, AvesApp.supportedLocales); + } + return _appliedLocale!; + } + + int get catalogTimeZoneRawOffsetMillis => getInt(SettingKeys.catalogTimeZoneRawOffsetMillisKey) ?? 0; + + set catalogTimeZoneRawOffsetMillis(int newValue) => set(SettingKeys.catalogTimeZoneRawOffsetMillisKey, newValue); + + double getTileExtent(String routeName) => getDouble(SettingKeys.tileExtentPrefixKey + routeName) ?? 0; + + void setTileExtent(String routeName, double newValue) => set(SettingKeys.tileExtentPrefixKey + routeName, newValue); + + TileLayout getTileLayout(String routeName) => getEnumOrDefault(SettingKeys.tileLayoutPrefixKey + routeName, SettingsDefaults.tileLayout, TileLayout.values); + + void setTileLayout(String routeName, TileLayout newValue) => set(SettingKeys.tileLayoutPrefixKey + routeName, newValue.toString()); + + String get entryRenamingPattern => getString(SettingKeys.entryRenamingPatternKey) ?? SettingsDefaults.entryRenamingPattern; + + set entryRenamingPattern(String newValue) => set(SettingKeys.entryRenamingPatternKey, newValue); + + List? get topEntryIds => getStringList(SettingKeys.topEntryIdsKey)?.map(int.tryParse).whereNotNull().toList(); + + set topEntryIds(List? newValue) => set(SettingKeys.topEntryIdsKey, newValue?.map((id) => id.toString()).whereNotNull().toList()); + + List get recentDestinationAlbums => getStringList(SettingKeys.recentDestinationAlbumsKey) ?? []; + + set recentDestinationAlbums(List newValue) => set(SettingKeys.recentDestinationAlbumsKey, newValue.take(_recentFilterHistoryMax).toList()); + + List get recentTags => (getStringList(SettingKeys.recentTagsKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toList(); + + set recentTags(List newValue) => set(SettingKeys.recentTagsKey, newValue.take(_recentFilterHistoryMax).map((filter) => filter.toJson()).toList()); +} diff --git a/lib/model/settings/modules/collection.dart b/lib/model/settings/modules/collection.dart new file mode 100644 index 000000000..cb973b78c --- /dev/null +++ b/lib/model/settings/modules/collection.dart @@ -0,0 +1,56 @@ +import 'package:aves/model/settings/defaults.dart'; +import 'package:aves_model/aves_model.dart'; + +mixin CollectionSettings on SettingsAccess { + List get collectionBurstPatterns => getStringList(SettingKeys.collectionBurstPatternsKey) ?? []; + + set collectionBurstPatterns(List newValue) => set(SettingKeys.collectionBurstPatternsKey, newValue); + + EntryGroupFactor get collectionSectionFactor => getEnumOrDefault(SettingKeys.collectionGroupFactorKey, SettingsDefaults.collectionSectionFactor, EntryGroupFactor.values); + + set collectionSectionFactor(EntryGroupFactor newValue) => set(SettingKeys.collectionGroupFactorKey, newValue.toString()); + + EntrySortFactor get collectionSortFactor => getEnumOrDefault(SettingKeys.collectionSortFactorKey, SettingsDefaults.collectionSortFactor, EntrySortFactor.values); + + set collectionSortFactor(EntrySortFactor newValue) => set(SettingKeys.collectionSortFactorKey, newValue.toString()); + + bool get collectionSortReverse => getBool(SettingKeys.collectionSortReverseKey) ?? false; + + set collectionSortReverse(bool newValue) => set(SettingKeys.collectionSortReverseKey, newValue); + + List get collectionBrowsingQuickActions => getEnumListOrDefault(SettingKeys.collectionBrowsingQuickActionsKey, SettingsDefaults.collectionBrowsingQuickActions, EntrySetAction.values); + + set collectionBrowsingQuickActions(List newValue) => set(SettingKeys.collectionBrowsingQuickActionsKey, newValue.map((v) => v.toString()).toList()); + + List get collectionSelectionQuickActions => getEnumListOrDefault(SettingKeys.collectionSelectionQuickActionsKey, SettingsDefaults.collectionSelectionQuickActions, EntrySetAction.values); + + set collectionSelectionQuickActions(List newValue) => set(SettingKeys.collectionSelectionQuickActionsKey, newValue.map((v) => v.toString()).toList()); + + bool get showThumbnailFavourite => getBool(SettingKeys.showThumbnailFavouriteKey) ?? SettingsDefaults.showThumbnailFavourite; + + set showThumbnailFavourite(bool newValue) => set(SettingKeys.showThumbnailFavouriteKey, newValue); + + ThumbnailOverlayLocationIcon get thumbnailLocationIcon => getEnumOrDefault(SettingKeys.thumbnailLocationIconKey, SettingsDefaults.thumbnailLocationIcon, ThumbnailOverlayLocationIcon.values); + + set thumbnailLocationIcon(ThumbnailOverlayLocationIcon newValue) => set(SettingKeys.thumbnailLocationIconKey, newValue.toString()); + + ThumbnailOverlayTagIcon get thumbnailTagIcon => getEnumOrDefault(SettingKeys.thumbnailTagIconKey, SettingsDefaults.thumbnailTagIcon, ThumbnailOverlayTagIcon.values); + + set thumbnailTagIcon(ThumbnailOverlayTagIcon newValue) => set(SettingKeys.thumbnailTagIconKey, newValue.toString()); + + bool get showThumbnailMotionPhoto => getBool(SettingKeys.showThumbnailMotionPhotoKey) ?? SettingsDefaults.showThumbnailMotionPhoto; + + set showThumbnailMotionPhoto(bool newValue) => set(SettingKeys.showThumbnailMotionPhotoKey, newValue); + + bool get showThumbnailRating => getBool(SettingKeys.showThumbnailRatingKey) ?? SettingsDefaults.showThumbnailRating; + + set showThumbnailRating(bool newValue) => set(SettingKeys.showThumbnailRatingKey, newValue); + + bool get showThumbnailRaw => getBool(SettingKeys.showThumbnailRawKey) ?? SettingsDefaults.showThumbnailRaw; + + set showThumbnailRaw(bool newValue) => set(SettingKeys.showThumbnailRawKey, newValue); + + bool get showThumbnailVideoDuration => getBool(SettingKeys.showThumbnailVideoDurationKey) ?? SettingsDefaults.showThumbnailVideoDuration; + + set showThumbnailVideoDuration(bool newValue) => set(SettingKeys.showThumbnailVideoDurationKey, newValue); +} diff --git a/lib/model/settings/modules/display.dart b/lib/model/settings/modules/display.dart new file mode 100644 index 000000000..390dd8761 --- /dev/null +++ b/lib/model/settings/modules/display.dart @@ -0,0 +1,37 @@ +import 'package:aves/model/device.dart'; +import 'package:aves/model/settings/defaults.dart'; +import 'package:aves_model/aves_model.dart'; + +mixin DisplaySettings on SettingsAccess { + DisplayRefreshRateMode get displayRefreshRateMode => getEnumOrDefault(SettingKeys.displayRefreshRateModeKey, SettingsDefaults.displayRefreshRateMode, DisplayRefreshRateMode.values); + + set displayRefreshRateMode(DisplayRefreshRateMode newValue) => set(SettingKeys.displayRefreshRateModeKey, newValue.toString()); + + AvesThemeBrightness get themeBrightness => getEnumOrDefault(SettingKeys.themeBrightnessKey, SettingsDefaults.themeBrightness, AvesThemeBrightness.values); + + set themeBrightness(AvesThemeBrightness newValue) => set(SettingKeys.themeBrightnessKey, newValue.toString()); + + AvesThemeColorMode get themeColorMode => getEnumOrDefault(SettingKeys.themeColorModeKey, SettingsDefaults.themeColorMode, AvesThemeColorMode.values); + + set themeColorMode(AvesThemeColorMode newValue) => set(SettingKeys.themeColorModeKey, newValue.toString()); + + bool get enableDynamicColor => getBool(SettingKeys.enableDynamicColorKey) ?? SettingsDefaults.enableDynamicColor; + + set enableDynamicColor(bool newValue) => set(SettingKeys.enableDynamicColorKey, newValue); + + bool get enableBlurEffect => getBool(SettingKeys.enableBlurEffectKey) ?? SettingsDefaults.enableBlurEffect; + + set enableBlurEffect(bool newValue) => set(SettingKeys.enableBlurEffectKey, newValue); + + MaxBrightness get maxBrightness => getEnumOrDefault(SettingKeys.maxBrightnessKey, SettingsDefaults.maxBrightness, MaxBrightness.values); + + set maxBrightness(MaxBrightness newValue) => set(SettingKeys.maxBrightnessKey, newValue.toString()); + + bool get forceTvLayout => getBool(SettingKeys.forceTvLayoutKey) ?? SettingsDefaults.forceTvLayout; + + set forceTvLayout(bool newValue) => set(SettingKeys.forceTvLayoutKey, newValue); + + bool get useTvLayout => device.isTelevision || forceTvLayout; + + bool get isReadOnly => useTvLayout; +} diff --git a/lib/model/settings/modules/filter_grids.dart b/lib/model/settings/modules/filter_grids.dart new file mode 100644 index 000000000..4476349a2 --- /dev/null +++ b/lib/model/settings/modules/filter_grids.dart @@ -0,0 +1,74 @@ +import 'package:aves/model/filters/filters.dart'; +import 'package:aves/model/settings/defaults.dart'; +import 'package:aves/model/settings/modules/search.dart'; +import 'package:aves_model/aves_model.dart'; +import 'package:collection/collection.dart'; + +mixin FilterGridsSettings on SettingsAccess, SearchSettings { + AlbumChipGroupFactor get albumGroupFactor => getEnumOrDefault(SettingKeys.albumGroupFactorKey, SettingsDefaults.albumGroupFactor, AlbumChipGroupFactor.values); + + set albumGroupFactor(AlbumChipGroupFactor newValue) => set(SettingKeys.albumGroupFactorKey, newValue.toString()); + + ChipSortFactor get albumSortFactor => getEnumOrDefault(SettingKeys.albumSortFactorKey, SettingsDefaults.chipListSortFactor, ChipSortFactor.values); + + set albumSortFactor(ChipSortFactor newValue) => set(SettingKeys.albumSortFactorKey, newValue.toString()); + + ChipSortFactor get countrySortFactor => getEnumOrDefault(SettingKeys.countrySortFactorKey, SettingsDefaults.chipListSortFactor, ChipSortFactor.values); + + set countrySortFactor(ChipSortFactor newValue) => set(SettingKeys.countrySortFactorKey, newValue.toString()); + + ChipSortFactor get stateSortFactor => getEnumOrDefault(SettingKeys.stateSortFactorKey, SettingsDefaults.chipListSortFactor, ChipSortFactor.values); + + set stateSortFactor(ChipSortFactor newValue) => set(SettingKeys.stateSortFactorKey, newValue.toString()); + + ChipSortFactor get placeSortFactor => getEnumOrDefault(SettingKeys.placeSortFactorKey, SettingsDefaults.chipListSortFactor, ChipSortFactor.values); + + set placeSortFactor(ChipSortFactor newValue) => set(SettingKeys.placeSortFactorKey, newValue.toString()); + + ChipSortFactor get tagSortFactor => getEnumOrDefault(SettingKeys.tagSortFactorKey, SettingsDefaults.chipListSortFactor, ChipSortFactor.values); + + set tagSortFactor(ChipSortFactor newValue) => set(SettingKeys.tagSortFactorKey, newValue.toString()); + + bool get albumSortReverse => getBool(SettingKeys.albumSortReverseKey) ?? false; + + set albumSortReverse(bool newValue) => set(SettingKeys.albumSortReverseKey, newValue); + + bool get countrySortReverse => getBool(SettingKeys.countrySortReverseKey) ?? false; + + set countrySortReverse(bool newValue) => set(SettingKeys.countrySortReverseKey, newValue); + + bool get stateSortReverse => getBool(SettingKeys.stateSortReverseKey) ?? false; + + set stateSortReverse(bool newValue) => set(SettingKeys.stateSortReverseKey, newValue); + + bool get placeSortReverse => getBool(SettingKeys.placeSortReverseKey) ?? false; + + set placeSortReverse(bool newValue) => set(SettingKeys.placeSortReverseKey, newValue); + + bool get tagSortReverse => getBool(SettingKeys.tagSortReverseKey) ?? false; + + set tagSortReverse(bool newValue) => set(SettingKeys.tagSortReverseKey, newValue); + + Set get pinnedFilters => (getStringList(SettingKeys.pinnedFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); + + set pinnedFilters(Set newValue) => set(SettingKeys.pinnedFiltersKey, newValue.map((filter) => filter.toJson()).toList()); + + Set get hiddenFilters => (getStringList(SettingKeys.hiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); + + set hiddenFilters(Set newValue) => set(SettingKeys.hiddenFiltersKey, newValue.map((filter) => filter.toJson()).toList()); + + void changeFilterVisibility(Set filters, bool visible) { + final _hiddenFilters = hiddenFilters; + if (visible) { + _hiddenFilters.removeAll(filters); + } else { + _hiddenFilters.addAll(filters); + searchHistory = searchHistory..removeWhere(filters.contains); + } + hiddenFilters = _hiddenFilters; + } + + bool get showAlbumPickQuery => getBool(SettingKeys.showAlbumPickQueryKey) ?? false; + + set showAlbumPickQuery(bool newValue) => set(SettingKeys.showAlbumPickQueryKey, newValue); +} diff --git a/lib/model/settings/modules/info.dart b/lib/model/settings/modules/info.dart new file mode 100644 index 000000000..18e809455 --- /dev/null +++ b/lib/model/settings/modules/info.dart @@ -0,0 +1,16 @@ +import 'package:aves/model/settings/defaults.dart'; +import 'package:aves_model/aves_model.dart'; + +mixin InfoSettings on SettingsAccess { + double get infoMapZoom => getDouble(SettingKeys.infoMapZoomKey) ?? SettingsDefaults.infoMapZoom; + + set infoMapZoom(double newValue) => set(SettingKeys.infoMapZoomKey, newValue); + + CoordinateFormat get coordinateFormat => getEnumOrDefault(SettingKeys.coordinateFormatKey, SettingsDefaults.coordinateFormat, CoordinateFormat.values); + + set coordinateFormat(CoordinateFormat newValue) => set(SettingKeys.coordinateFormatKey, newValue.toString()); + + UnitSystem get unitSystem => getEnumOrDefault(SettingKeys.unitSystemKey, SettingsDefaults.unitSystem, UnitSystem.values); + + set unitSystem(UnitSystem newValue) => set(SettingKeys.unitSystemKey, newValue.toString()); +} diff --git a/lib/model/settings/modules/navigation.dart b/lib/model/settings/modules/navigation.dart new file mode 100644 index 000000000..a18610077 --- /dev/null +++ b/lib/model/settings/modules/navigation.dart @@ -0,0 +1,62 @@ +import 'package:aves/model/filters/filters.dart'; +import 'package:aves/model/settings/defaults.dart'; +import 'package:aves_model/aves_model.dart'; + +mixin NavigationSettings on SettingsAccess { + bool get mustBackTwiceToExit => getBool(SettingKeys.mustBackTwiceToExitKey) ?? SettingsDefaults.mustBackTwiceToExit; + + set mustBackTwiceToExit(bool newValue) => set(SettingKeys.mustBackTwiceToExitKey, newValue); + + KeepScreenOn get keepScreenOn => getEnumOrDefault(SettingKeys.keepScreenOnKey, SettingsDefaults.keepScreenOn, KeepScreenOn.values); + + set keepScreenOn(KeepScreenOn newValue) => set(SettingKeys.keepScreenOnKey, newValue.toString()); + + HomePageSetting get homePage => getEnumOrDefault(SettingKeys.homePageKey, SettingsDefaults.homePage, HomePageSetting.values); + + set homePage(HomePageSetting newValue) => set(SettingKeys.homePageKey, newValue.toString()); + + bool get enableBottomNavigationBar => getBool(SettingKeys.enableBottomNavigationBarKey) ?? SettingsDefaults.enableBottomNavigationBar; + + set enableBottomNavigationBar(bool newValue) => set(SettingKeys.enableBottomNavigationBarKey, newValue); + + bool get confirmCreateVault => getBool(SettingKeys.confirmCreateVaultKey) ?? SettingsDefaults.confirm; + + set confirmCreateVault(bool newValue) => set(SettingKeys.confirmCreateVaultKey, newValue); + + bool get confirmDeleteForever => getBool(SettingKeys.confirmDeleteForeverKey) ?? SettingsDefaults.confirm; + + set confirmDeleteForever(bool newValue) => set(SettingKeys.confirmDeleteForeverKey, newValue); + + bool get confirmMoveToBin => getBool(SettingKeys.confirmMoveToBinKey) ?? SettingsDefaults.confirm; + + set confirmMoveToBin(bool newValue) => set(SettingKeys.confirmMoveToBinKey, newValue); + + bool get confirmMoveUndatedItems => getBool(SettingKeys.confirmMoveUndatedItemsKey) ?? SettingsDefaults.confirm; + + set confirmMoveUndatedItems(bool newValue) => set(SettingKeys.confirmMoveUndatedItemsKey, newValue); + + bool get confirmAfterMoveToBin => getBool(SettingKeys.confirmAfterMoveToBinKey) ?? SettingsDefaults.confirm; + + set confirmAfterMoveToBin(bool newValue) => set(SettingKeys.confirmAfterMoveToBinKey, newValue); + + bool get setMetadataDateBeforeFileOp => getBool(SettingKeys.setMetadataDateBeforeFileOpKey) ?? SettingsDefaults.setMetadataDateBeforeFileOp; + + set setMetadataDateBeforeFileOp(bool newValue) => set(SettingKeys.setMetadataDateBeforeFileOpKey, newValue); + + List get drawerTypeBookmarks => + (getStringList(SettingKeys.drawerTypeBookmarksKey))?.map((v) { + if (v.isEmpty) return null; + return CollectionFilter.fromJson(v); + }).toList() ?? + SettingsDefaults.drawerTypeBookmarks; + + set drawerTypeBookmarks(List newValue) => set(SettingKeys.drawerTypeBookmarksKey, newValue.map((filter) => filter?.toJson() ?? '').toList()); + + List? get drawerAlbumBookmarks => getStringList(SettingKeys.drawerAlbumBookmarksKey); + + set drawerAlbumBookmarks(List? newValue) => set(SettingKeys.drawerAlbumBookmarksKey, newValue); + + List get drawerPageBookmarks => getStringList(SettingKeys.drawerPageBookmarksKey) ?? SettingsDefaults.drawerPageBookmarks; + + set drawerPageBookmarks(List newValue) => set(SettingKeys.drawerPageBookmarksKey, newValue); +} diff --git a/lib/model/settings/modules/search.dart b/lib/model/settings/modules/search.dart new file mode 100644 index 000000000..a6dba9bee --- /dev/null +++ b/lib/model/settings/modules/search.dart @@ -0,0 +1,14 @@ +import 'package:aves/model/filters/filters.dart'; +import 'package:aves/model/settings/defaults.dart'; +import 'package:aves_model/aves_model.dart'; +import 'package:collection/collection.dart'; + +mixin SearchSettings on SettingsAccess { + bool get saveSearchHistory => getBool(SettingKeys.saveSearchHistoryKey) ?? SettingsDefaults.saveSearchHistory; + + set saveSearchHistory(bool newValue) => set(SettingKeys.saveSearchHistoryKey, newValue); + + List get searchHistory => (getStringList(SettingKeys.searchHistoryKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toList(); + + set searchHistory(List newValue) => set(SettingKeys.searchHistoryKey, newValue.map((filter) => filter.toJson()).toList()); +} diff --git a/lib/model/settings/modules/viewer.dart b/lib/model/settings/modules/viewer.dart new file mode 100644 index 000000000..1f8ad5729 --- /dev/null +++ b/lib/model/settings/modules/viewer.dart @@ -0,0 +1,52 @@ +import 'package:aves/model/settings/defaults.dart'; +import 'package:aves_model/aves_model.dart'; + +mixin ViewerSettings on SettingsAccess { + List get viewerQuickActions => getEnumListOrDefault(SettingKeys.viewerQuickActionsKey, SettingsDefaults.viewerQuickActions, EntryAction.values); + + set viewerQuickActions(List newValue) => set(SettingKeys.viewerQuickActionsKey, newValue.map((v) => v.toString()).toList()); + + bool get showOverlayOnOpening => getBool(SettingKeys.showOverlayOnOpeningKey) ?? SettingsDefaults.showOverlayOnOpening; + + set showOverlayOnOpening(bool newValue) => set(SettingKeys.showOverlayOnOpeningKey, newValue); + + bool get showOverlayMinimap => getBool(SettingKeys.showOverlayMinimapKey) ?? SettingsDefaults.showOverlayMinimap; + + set showOverlayMinimap(bool newValue) => set(SettingKeys.showOverlayMinimapKey, newValue); + + bool get showOverlayInfo => getBool(SettingKeys.showOverlayInfoKey) ?? SettingsDefaults.showOverlayInfo; + + set showOverlayInfo(bool newValue) => set(SettingKeys.showOverlayInfoKey, newValue); + + bool get showOverlayDescription => getBool(SettingKeys.showOverlayDescriptionKey) ?? SettingsDefaults.showOverlayDescription; + + set showOverlayDescription(bool newValue) => set(SettingKeys.showOverlayDescriptionKey, newValue); + + bool get showOverlayRatingTags => getBool(SettingKeys.showOverlayRatingTagsKey) ?? SettingsDefaults.showOverlayRatingTags; + + set showOverlayRatingTags(bool newValue) => set(SettingKeys.showOverlayRatingTagsKey, newValue); + + bool get showOverlayShootingDetails => getBool(SettingKeys.showOverlayShootingDetailsKey) ?? SettingsDefaults.showOverlayShootingDetails; + + set showOverlayShootingDetails(bool newValue) => set(SettingKeys.showOverlayShootingDetailsKey, newValue); + + bool get showOverlayThumbnailPreview => getBool(SettingKeys.showOverlayThumbnailPreviewKey) ?? SettingsDefaults.showOverlayThumbnailPreview; + + set showOverlayThumbnailPreview(bool newValue) => set(SettingKeys.showOverlayThumbnailPreviewKey, newValue); + + bool get viewerGestureSideTapNext => getBool(SettingKeys.viewerGestureSideTapNextKey) ?? SettingsDefaults.viewerGestureSideTapNext; + + set viewerGestureSideTapNext(bool newValue) => set(SettingKeys.viewerGestureSideTapNextKey, newValue); + + bool get viewerUseCutout => getBool(SettingKeys.viewerUseCutoutKey) ?? SettingsDefaults.viewerUseCutout; + + set viewerUseCutout(bool newValue) => set(SettingKeys.viewerUseCutoutKey, newValue); + + bool get enableMotionPhotoAutoPlay => getBool(SettingKeys.enableMotionPhotoAutoPlayKey) ?? SettingsDefaults.enableMotionPhotoAutoPlay; + + set enableMotionPhotoAutoPlay(bool newValue) => set(SettingKeys.enableMotionPhotoAutoPlayKey, newValue); + + EntryBackground get imageBackground => getEnumOrDefault(SettingKeys.imageBackgroundKey, SettingsDefaults.imageBackground, EntryBackground.values); + + set imageBackground(EntryBackground newValue) => set(SettingKeys.imageBackgroundKey, newValue.toString()); +} diff --git a/lib/model/settings/settings.dart b/lib/model/settings/settings.dart index 966b545db..27956405a 100644 --- a/lib/model/settings/settings.dart +++ b/lib/model/settings/settings.dart @@ -9,10 +9,17 @@ import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/mime.dart'; import 'package:aves/model/settings/defaults.dart'; import 'package:aves/model/settings/enums/map_style.dart'; +import 'package:aves/model/settings/modules/app.dart'; +import 'package:aves/model/settings/modules/collection.dart'; +import 'package:aves/model/settings/modules/display.dart'; +import 'package:aves/model/settings/modules/filter_grids.dart'; +import 'package:aves/model/settings/modules/info.dart'; +import 'package:aves/model/settings/modules/navigation.dart'; +import 'package:aves/model/settings/modules/search.dart'; +import 'package:aves/model/settings/modules/viewer.dart'; import 'package:aves/ref/bursts.dart'; import 'package:aves/services/accessibility_service.dart'; import 'package:aves/services/common/services.dart'; -import 'package:aves/widgets/aves_app.dart'; import 'package:aves/widgets/common/search/page.dart'; import 'package:aves/widgets/filter_grids/albums_page.dart'; import 'package:aves/widgets/filter_grids/countries_page.dart'; @@ -21,6 +28,7 @@ import 'package:aves/widgets/filter_grids/tags_page.dart'; import 'package:aves_map/aves_map.dart'; import 'package:aves_model/aves_model.dart'; import 'package:aves_utils/aves_utils.dart'; +import 'package:aves_video/aves_video.dart'; import 'package:collection/collection.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/services.dart'; @@ -29,202 +37,28 @@ import 'package:latlong2/latlong.dart'; final Settings settings = Settings._private(); -class Settings extends ChangeNotifier { +class Settings with ChangeNotifier, SettingsAccess, AppSettings, DisplaySettings, NavigationSettings, SearchSettings, CollectionSettings, FilterGridsSettings, ViewerSettings, VideoSettings, SubtitlesSettings, InfoSettings { final List _subscriptions = []; final EventChannel _platformSettingsChangeChannel = const OptionalEventChannel('deckers.thibault/aves/settings_change'); final StreamController _updateStreamController = StreamController.broadcast(); + final StreamController _updateTileExtentStreamController = StreamController.broadcast(); + @override Stream get updateStream => _updateStreamController.stream; + Stream get updateTileExtentStream => _updateTileExtentStreamController.stream; + + @override + bool get initialized => store.initialized; + + @override + SettingsStore get store => settingsStore; + Settings._private(); - static const int _recentFilterHistoryMax = 10; - static const Set _internalKeys = { - hasAcceptedTermsKey, - catalogTimeZoneRawOffsetMillisKey, - searchHistoryKey, - platformAccelerometerRotationKey, - platformTransitionAnimationScaleKey, - topEntryIdsKey, - recentDestinationAlbumsKey, - recentTagsKey, - }; - static const _widgetKeyPrefix = 'widget_'; - - // app - static const hasAcceptedTermsKey = 'has_accepted_terms'; - static const canUseAnalysisServiceKey = 'can_use_analysis_service'; - static const isInstalledAppAccessAllowedKey = 'is_installed_app_access_allowed'; - static const isErrorReportingAllowedKey = 'is_crashlytics_enabled'; - static const localeKey = 'locale'; - static const catalogTimeZoneRawOffsetMillisKey = 'catalog_time_zone_raw_offset_millis'; - static const tileExtentPrefixKey = 'tile_extent_'; - static const tileLayoutPrefixKey = 'tile_layout_'; - static const entryRenamingPatternKey = 'entry_renaming_pattern'; - static const topEntryIdsKey = 'top_entry_ids'; - static const recentDestinationAlbumsKey = 'recent_destination_albums'; - static const recentTagsKey = 'recent_tags'; - - // display - static const displayRefreshRateModeKey = 'display_refresh_rate_mode'; - static const themeBrightnessKey = 'theme_brightness'; - static const themeColorModeKey = 'theme_color_mode'; - static const enableDynamicColorKey = 'dynamic_color'; - static const enableBlurEffectKey = 'enable_overlay_blur_effect'; - static const maxBrightnessKey = 'max_brightness'; - static const forceTvLayoutKey = 'force_tv_layout'; - - // navigation - static const mustBackTwiceToExitKey = 'must_back_twice_to_exit'; - static const keepScreenOnKey = 'keep_screen_on'; - static const homePageKey = 'home_page'; - static const enableBottomNavigationBarKey = 'show_bottom_navigation_bar'; - static const confirmCreateVaultKey = 'confirm_create_vault'; - static const confirmDeleteForeverKey = 'confirm_delete_forever'; - static const confirmMoveToBinKey = 'confirm_move_to_bin'; - static const confirmMoveUndatedItemsKey = 'confirm_move_undated_items'; - static const confirmAfterMoveToBinKey = 'confirm_after_move_to_bin'; - static const setMetadataDateBeforeFileOpKey = 'set_metadata_date_before_file_op'; - static const drawerTypeBookmarksKey = 'drawer_type_bookmarks'; - static const drawerAlbumBookmarksKey = 'drawer_album_bookmarks'; - static const drawerPageBookmarksKey = 'drawer_page_bookmarks'; - - // collection - static const collectionBurstPatternsKey = 'collection_burst_patterns'; - static const collectionGroupFactorKey = 'collection_group_factor'; - static const collectionSortFactorKey = 'collection_sort_factor'; - static const collectionSortReverseKey = 'collection_sort_reverse'; - static const collectionBrowsingQuickActionsKey = 'collection_browsing_quick_actions'; - static const collectionSelectionQuickActionsKey = 'collection_selection_quick_actions'; - static const showThumbnailFavouriteKey = 'show_thumbnail_favourite'; - static const thumbnailLocationIconKey = 'thumbnail_location_icon'; - static const thumbnailTagIconKey = 'thumbnail_tag_icon'; - static const showThumbnailMotionPhotoKey = 'show_thumbnail_motion_photo'; - static const showThumbnailRatingKey = 'show_thumbnail_rating'; - static const showThumbnailRawKey = 'show_thumbnail_raw'; - static const showThumbnailVideoDurationKey = 'show_thumbnail_video_duration'; - - // filter grids - static const albumGroupFactorKey = 'album_group_factor'; - static const albumSortFactorKey = 'album_sort_factor'; - static const countrySortFactorKey = 'country_sort_factor'; - static const stateSortFactorKey = 'state_sort_factor'; - static const placeSortFactorKey = 'place_sort_factor'; - static const tagSortFactorKey = 'tag_sort_factor'; - static const albumSortReverseKey = 'album_sort_reverse'; - static const countrySortReverseKey = 'country_sort_reverse'; - static const stateSortReverseKey = 'state_sort_reverse'; - static const placeSortReverseKey = 'place_sort_reverse'; - static const tagSortReverseKey = 'tag_sort_reverse'; - static const pinnedFiltersKey = 'pinned_filters'; - static const hiddenFiltersKey = 'hidden_filters'; - static const showAlbumPickQueryKey = 'show_album_pick_query'; - - // viewer - static const viewerQuickActionsKey = 'viewer_quick_actions'; - static const showOverlayOnOpeningKey = 'show_overlay_on_opening'; - static const showOverlayMinimapKey = 'show_overlay_minimap'; - static const showOverlayInfoKey = 'show_overlay_info'; - static const showOverlayDescriptionKey = 'show_overlay_description'; - static const showOverlayRatingTagsKey = 'show_overlay_rating_tags'; - static const showOverlayShootingDetailsKey = 'show_overlay_shooting_details'; - static const showOverlayThumbnailPreviewKey = 'show_overlay_thumbnail_preview'; - static const viewerGestureSideTapNextKey = 'viewer_gesture_side_tap_next'; - static const viewerUseCutoutKey = 'viewer_use_cutout'; - static const enableMotionPhotoAutoPlayKey = 'motion_photo_auto_play'; - static const imageBackgroundKey = 'image_background'; - - // video - static const enableVideoHardwareAccelerationKey = 'video_hwaccel_mediacodec'; - static const videoBackgroundModeKey = 'video_background_mode'; - static const videoAutoPlayModeKey = 'video_auto_play_mode'; - static const videoLoopModeKey = 'video_loop'; - static const videoResumptionModeKey = 'video_resumption_mode'; - static const videoControlsKey = 'video_controls'; - static const videoGestureDoubleTapTogglePlayKey = 'video_gesture_double_tap_toggle_play'; - static const videoGestureSideDoubleTapSeekKey = 'video_gesture_side_double_tap_skip'; - static const videoGestureVerticalDragBrightnessVolumeKey = 'video_gesture_vertical_drag_brightness_volume'; - - // subtitles - static const subtitleFontSizeKey = 'subtitle_font_size'; - static const subtitleTextAlignmentKey = 'subtitle_text_alignment'; - static const subtitleTextPositionKey = 'subtitle_text_position'; - static const subtitleShowOutlineKey = 'subtitle_show_outline'; - static const subtitleTextColorKey = 'subtitle_text_color'; - static const subtitleBackgroundColorKey = 'subtitle_background_color'; - - // info - static const infoMapZoomKey = 'info_map_zoom'; - static const coordinateFormatKey = 'coordinates_format'; - static const unitSystemKey = 'unit_system'; - - // tag editor - - static const tagEditorCurrentFilterSectionExpandedKey = 'tag_editor_current_filter_section_expanded'; - static const tagEditorExpandedSectionKey = 'tag_editor_expanded_section'; - - // converter - - static const convertMimeTypeKey = 'convert_mime_type'; - static const convertQualityKey = 'convert_quality'; - static const convertWriteMetadataKey = 'convert_write_metadata'; - - // map - static const mapStyleKey = 'info_map_style'; - static const mapDefaultCenterKey = 'map_default_center'; - - // search - static const saveSearchHistoryKey = 'save_search_history'; - static const searchHistoryKey = 'search_history'; - - // bin - static const enableBinKey = 'enable_bin'; - - // accessibility - static const showPinchGestureAlternativesKey = 'show_pinch_gesture_alternatives'; - static const accessibilityAnimationsKey = 'accessibility_animations'; - static const timeToTakeActionKey = 'time_to_take_action'; - - // file picker - static const filePickerShowHiddenFilesKey = 'file_picker_show_hidden_files'; - - // screen saver - static const screenSaverFillScreenKey = 'screen_saver_fill_screen'; - static const screenSaverAnimatedZoomEffectKey = 'screen_saver_animated_zoom_effect'; - static const screenSaverTransitionKey = 'screen_saver_transition'; - static const screenSaverVideoPlaybackKey = 'screen_saver_video_playback'; - static const screenSaverIntervalKey = 'screen_saver_interval'; - static const screenSaverCollectionFiltersKey = 'screen_saver_collection_filters'; - - // slideshow - static const slideshowRepeatKey = 'slideshow_loop'; - static const slideshowShuffleKey = 'slideshow_shuffle'; - static const slideshowFillScreenKey = 'slideshow_fill_screen'; - static const slideshowAnimatedZoomEffectKey = 'slideshow_animated_zoom_effect'; - static const slideshowTransitionKey = 'slideshow_transition'; - static const slideshowVideoPlaybackKey = 'slideshow_video_playback'; - static const slideshowIntervalKey = 'slideshow_interval'; - - // widget - static const widgetOutlinePrefixKey = '${_widgetKeyPrefix}outline_'; - static const widgetShapePrefixKey = '${_widgetKeyPrefix}shape_'; - static const widgetCollectionFiltersPrefixKey = '${_widgetKeyPrefix}collection_filters_'; - static const widgetOpenPagePrefixKey = '${_widgetKeyPrefix}open_page_'; - static const widgetDisplayedItemPrefixKey = '${_widgetKeyPrefix}displayed_item_'; - static const widgetUriPrefixKey = '${_widgetKeyPrefix}uri_'; - - // platform settings - // cf Android `Settings.System.ACCELEROMETER_ROTATION` - static const platformAccelerometerRotationKey = 'accelerometer_rotation'; - - // cf Android `Settings.Global.TRANSITION_ANIMATION_SCALE` - static const platformTransitionAnimationScaleKey = 'transition_animation_scale'; - - bool get initialized => settingsStore.initialized; - Future init({required bool monitorPlatformSettings}) async { - await settingsStore.init(); - _appliedLocale = null; + await store.init(); + resetAppliedLocale(); if (monitorPlatformSettings) { _subscriptions ..forEach((sub) => sub.cancel()) @@ -233,18 +67,16 @@ class Settings extends ChangeNotifier { } } - Future reload() => settingsStore.reload(); + Future reload() => store.reload(); Future reset({required bool includeInternalKeys}) async { if (includeInternalKeys) { - await settingsStore.clear(); + await store.clear(); } else { - await Future.forEach(settingsStore.getKeys().whereNot(isInternalKey), settingsStore.remove); + await Future.forEach(store.getKeys().whereNot(SettingKeys.isInternalKey), store.remove); } } - bool isInternalKey(String key) => _internalKeys.contains(key) || key.startsWith(_widgetKeyPrefix); - Future setContextualDefaults(AppFlavor flavor) async { // performance final performanceClass = await deviceService.getPerformanceClass(); @@ -304,725 +136,181 @@ class Settings extends ChangeNotifier { Future sanitize() async { if (timeToTakeAction == AccessibilityTimeout.system && !await AccessibilityService.hasRecommendedTimeouts()) { - _set(timeToTakeActionKey, null); + set(SettingKeys.timeToTakeActionKey, null); } if (viewerUseCutout != SettingsDefaults.viewerUseCutout && !await windowService.isCutoutAware()) { - _set(viewerUseCutoutKey, null); + set(SettingKeys.viewerUseCutoutKey, null); } if (videoBackgroundMode == VideoBackgroundMode.pip && !device.supportPictureInPicture) { - _set(videoBackgroundModeKey, null); + set(SettingKeys.videoBackgroundModeKey, null); } collectionBurstPatterns = collectionBurstPatterns.where(BurstPatterns.options.contains).toList(); } - // app - - bool get hasAcceptedTerms => getBool(hasAcceptedTermsKey) ?? SettingsDefaults.hasAcceptedTerms; - - set hasAcceptedTerms(bool newValue) => _set(hasAcceptedTermsKey, newValue); - - bool get canUseAnalysisService => getBool(canUseAnalysisServiceKey) ?? SettingsDefaults.canUseAnalysisService; - - set canUseAnalysisService(bool newValue) => _set(canUseAnalysisServiceKey, newValue); - - bool get isInstalledAppAccessAllowed => getBool(isInstalledAppAccessAllowedKey) ?? SettingsDefaults.isInstalledAppAccessAllowed; - - set isInstalledAppAccessAllowed(bool newValue) => _set(isInstalledAppAccessAllowedKey, newValue); - - bool get isErrorReportingAllowed => getBool(isErrorReportingAllowedKey) ?? SettingsDefaults.isErrorReportingAllowed; - - set isErrorReportingAllowed(bool newValue) => _set(isErrorReportingAllowedKey, newValue); - - static const localeSeparator = '-'; - - Locale? get locale { - // exceptionally allow getting locale before settings are initialized - final tag = initialized ? getString(localeKey) : null; - if (tag != null) { - final codes = tag.split(localeSeparator); - return Locale.fromSubtags( - languageCode: codes[0], - scriptCode: codes[1] == '' ? null : codes[1], - countryCode: codes[2] == '' ? null : codes[2], - ); - } - return null; - } - - set locale(Locale? newValue) { - String? tag; - if (newValue != null) { - tag = [ - newValue.languageCode, - newValue.scriptCode ?? '', - newValue.countryCode ?? '', - ].join(localeSeparator); - } - _set(localeKey, tag); - _appliedLocale = null; - } - - List _systemLocalesFallback = []; - - set systemLocalesFallback(List locales) => _systemLocalesFallback = locales; - - Locale? _appliedLocale; - - Locale get appliedLocale { - if (_appliedLocale == null) { - final _locale = locale; - final preferredLocales = []; - if (_locale != null) { - preferredLocales.add(_locale); - } else { - preferredLocales.addAll(WidgetsBinding.instance.platformDispatcher.locales); - if (preferredLocales.isEmpty) { - // the `window` locales may be empty in a window-less service context - preferredLocales.addAll(_systemLocalesFallback); - } - } - _appliedLocale = basicLocaleListResolution(preferredLocales, AvesApp.supportedLocales); - } - return _appliedLocale!; - } - - int get catalogTimeZoneRawOffsetMillis => getInt(catalogTimeZoneRawOffsetMillisKey) ?? 0; - - set catalogTimeZoneRawOffsetMillis(int newValue) => _set(catalogTimeZoneRawOffsetMillisKey, newValue); - - double getTileExtent(String routeName) => getDouble(tileExtentPrefixKey + routeName) ?? 0; - - void setTileExtent(String routeName, double newValue) => _set(tileExtentPrefixKey + routeName, newValue); - - TileLayout getTileLayout(String routeName) => getEnumOrDefault(tileLayoutPrefixKey + routeName, SettingsDefaults.tileLayout, TileLayout.values); - - void setTileLayout(String routeName, TileLayout newValue) => _set(tileLayoutPrefixKey + routeName, newValue.toString()); - - String get entryRenamingPattern => getString(entryRenamingPatternKey) ?? SettingsDefaults.entryRenamingPattern; - - set entryRenamingPattern(String newValue) => _set(entryRenamingPatternKey, newValue); - - List? get topEntryIds => getStringList(topEntryIdsKey)?.map(int.tryParse).whereNotNull().toList(); - - set topEntryIds(List? newValue) => _set(topEntryIdsKey, newValue?.map((id) => id.toString()).whereNotNull().toList()); - - List get recentDestinationAlbums => getStringList(recentDestinationAlbumsKey) ?? []; - - set recentDestinationAlbums(List newValue) => _set(recentDestinationAlbumsKey, newValue.take(_recentFilterHistoryMax).toList()); - - List get recentTags => (getStringList(recentTagsKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toList(); - - set recentTags(List newValue) => _set(recentTagsKey, newValue.take(_recentFilterHistoryMax).map((filter) => filter.toJson()).toList()); - - // display - - DisplayRefreshRateMode get displayRefreshRateMode => getEnumOrDefault(displayRefreshRateModeKey, SettingsDefaults.displayRefreshRateMode, DisplayRefreshRateMode.values); - - set displayRefreshRateMode(DisplayRefreshRateMode newValue) => _set(displayRefreshRateModeKey, newValue.toString()); - - AvesThemeBrightness get themeBrightness => getEnumOrDefault(themeBrightnessKey, SettingsDefaults.themeBrightness, AvesThemeBrightness.values); - - set themeBrightness(AvesThemeBrightness newValue) => _set(themeBrightnessKey, newValue.toString()); - - AvesThemeColorMode get themeColorMode => getEnumOrDefault(themeColorModeKey, SettingsDefaults.themeColorMode, AvesThemeColorMode.values); - - set themeColorMode(AvesThemeColorMode newValue) => _set(themeColorModeKey, newValue.toString()); - - bool get enableDynamicColor => getBool(enableDynamicColorKey) ?? SettingsDefaults.enableDynamicColor; - - set enableDynamicColor(bool newValue) => _set(enableDynamicColorKey, newValue); - - bool get enableBlurEffect => getBool(enableBlurEffectKey) ?? SettingsDefaults.enableBlurEffect; - - set enableBlurEffect(bool newValue) => _set(enableBlurEffectKey, newValue); - - MaxBrightness get maxBrightness => getEnumOrDefault(maxBrightnessKey, SettingsDefaults.maxBrightness, MaxBrightness.values); - - set maxBrightness(MaxBrightness newValue) => _set(maxBrightnessKey, newValue.toString()); - - bool get forceTvLayout => getBool(forceTvLayoutKey) ?? SettingsDefaults.forceTvLayout; - - set forceTvLayout(bool newValue) => _set(forceTvLayoutKey, newValue); - - bool get useTvLayout => device.isTelevision || forceTvLayout; - - bool get isReadOnly => useTvLayout; - - // navigation - - bool get mustBackTwiceToExit => getBool(mustBackTwiceToExitKey) ?? SettingsDefaults.mustBackTwiceToExit; - - set mustBackTwiceToExit(bool newValue) => _set(mustBackTwiceToExitKey, newValue); - - KeepScreenOn get keepScreenOn => getEnumOrDefault(keepScreenOnKey, SettingsDefaults.keepScreenOn, KeepScreenOn.values); - - set keepScreenOn(KeepScreenOn newValue) => _set(keepScreenOnKey, newValue.toString()); - - HomePageSetting get homePage => getEnumOrDefault(homePageKey, SettingsDefaults.homePage, HomePageSetting.values); - - set homePage(HomePageSetting newValue) => _set(homePageKey, newValue.toString()); - - bool get enableBottomNavigationBar => getBool(enableBottomNavigationBarKey) ?? SettingsDefaults.enableBottomNavigationBar; - - set enableBottomNavigationBar(bool newValue) => _set(enableBottomNavigationBarKey, newValue); - - bool get confirmCreateVault => getBool(confirmCreateVaultKey) ?? SettingsDefaults.confirm; - - set confirmCreateVault(bool newValue) => _set(confirmCreateVaultKey, newValue); - - bool get confirmDeleteForever => getBool(confirmDeleteForeverKey) ?? SettingsDefaults.confirm; - - set confirmDeleteForever(bool newValue) => _set(confirmDeleteForeverKey, newValue); - - bool get confirmMoveToBin => getBool(confirmMoveToBinKey) ?? SettingsDefaults.confirm; - - set confirmMoveToBin(bool newValue) => _set(confirmMoveToBinKey, newValue); - - bool get confirmMoveUndatedItems => getBool(confirmMoveUndatedItemsKey) ?? SettingsDefaults.confirm; - - set confirmMoveUndatedItems(bool newValue) => _set(confirmMoveUndatedItemsKey, newValue); - - bool get confirmAfterMoveToBin => getBool(confirmAfterMoveToBinKey) ?? SettingsDefaults.confirm; - - set confirmAfterMoveToBin(bool newValue) => _set(confirmAfterMoveToBinKey, newValue); - - bool get setMetadataDateBeforeFileOp => getBool(setMetadataDateBeforeFileOpKey) ?? SettingsDefaults.setMetadataDateBeforeFileOp; - - set setMetadataDateBeforeFileOp(bool newValue) => _set(setMetadataDateBeforeFileOpKey, newValue); - - List get drawerTypeBookmarks => - (getStringList(drawerTypeBookmarksKey))?.map((v) { - if (v.isEmpty) return null; - return CollectionFilter.fromJson(v); - }).toList() ?? - SettingsDefaults.drawerTypeBookmarks; - - set drawerTypeBookmarks(List newValue) => _set(drawerTypeBookmarksKey, newValue.map((filter) => filter?.toJson() ?? '').toList()); - - List? get drawerAlbumBookmarks => getStringList(drawerAlbumBookmarksKey); - - set drawerAlbumBookmarks(List? newValue) => _set(drawerAlbumBookmarksKey, newValue); - - List get drawerPageBookmarks => getStringList(drawerPageBookmarksKey) ?? SettingsDefaults.drawerPageBookmarks; - - set drawerPageBookmarks(List newValue) => _set(drawerPageBookmarksKey, newValue); - - // collection - - List get collectionBurstPatterns => getStringList(collectionBurstPatternsKey) ?? []; - - set collectionBurstPatterns(List newValue) => _set(collectionBurstPatternsKey, newValue); - - EntryGroupFactor get collectionSectionFactor => getEnumOrDefault(collectionGroupFactorKey, SettingsDefaults.collectionSectionFactor, EntryGroupFactor.values); - - set collectionSectionFactor(EntryGroupFactor newValue) => _set(collectionGroupFactorKey, newValue.toString()); - - EntrySortFactor get collectionSortFactor => getEnumOrDefault(collectionSortFactorKey, SettingsDefaults.collectionSortFactor, EntrySortFactor.values); - - set collectionSortFactor(EntrySortFactor newValue) => _set(collectionSortFactorKey, newValue.toString()); - - bool get collectionSortReverse => getBool(collectionSortReverseKey) ?? false; - - set collectionSortReverse(bool newValue) => _set(collectionSortReverseKey, newValue); - - List get collectionBrowsingQuickActions => getEnumListOrDefault(collectionBrowsingQuickActionsKey, SettingsDefaults.collectionBrowsingQuickActions, EntrySetAction.values); - - set collectionBrowsingQuickActions(List newValue) => _set(collectionBrowsingQuickActionsKey, newValue.map((v) => v.toString()).toList()); - - List get collectionSelectionQuickActions => getEnumListOrDefault(collectionSelectionQuickActionsKey, SettingsDefaults.collectionSelectionQuickActions, EntrySetAction.values); - - set collectionSelectionQuickActions(List newValue) => _set(collectionSelectionQuickActionsKey, newValue.map((v) => v.toString()).toList()); - - bool get showThumbnailFavourite => getBool(showThumbnailFavouriteKey) ?? SettingsDefaults.showThumbnailFavourite; - - set showThumbnailFavourite(bool newValue) => _set(showThumbnailFavouriteKey, newValue); - - ThumbnailOverlayLocationIcon get thumbnailLocationIcon => getEnumOrDefault(thumbnailLocationIconKey, SettingsDefaults.thumbnailLocationIcon, ThumbnailOverlayLocationIcon.values); - - set thumbnailLocationIcon(ThumbnailOverlayLocationIcon newValue) => _set(thumbnailLocationIconKey, newValue.toString()); - - ThumbnailOverlayTagIcon get thumbnailTagIcon => getEnumOrDefault(thumbnailTagIconKey, SettingsDefaults.thumbnailTagIcon, ThumbnailOverlayTagIcon.values); - - set thumbnailTagIcon(ThumbnailOverlayTagIcon newValue) => _set(thumbnailTagIconKey, newValue.toString()); - - bool get showThumbnailMotionPhoto => getBool(showThumbnailMotionPhotoKey) ?? SettingsDefaults.showThumbnailMotionPhoto; - - set showThumbnailMotionPhoto(bool newValue) => _set(showThumbnailMotionPhotoKey, newValue); - - bool get showThumbnailRating => getBool(showThumbnailRatingKey) ?? SettingsDefaults.showThumbnailRating; - - set showThumbnailRating(bool newValue) => _set(showThumbnailRatingKey, newValue); - - bool get showThumbnailRaw => getBool(showThumbnailRawKey) ?? SettingsDefaults.showThumbnailRaw; - - set showThumbnailRaw(bool newValue) => _set(showThumbnailRawKey, newValue); - - bool get showThumbnailVideoDuration => getBool(showThumbnailVideoDurationKey) ?? SettingsDefaults.showThumbnailVideoDuration; - - set showThumbnailVideoDuration(bool newValue) => _set(showThumbnailVideoDurationKey, newValue); - - // filter grids - - AlbumChipGroupFactor get albumGroupFactor => getEnumOrDefault(albumGroupFactorKey, SettingsDefaults.albumGroupFactor, AlbumChipGroupFactor.values); - - set albumGroupFactor(AlbumChipGroupFactor newValue) => _set(albumGroupFactorKey, newValue.toString()); - - ChipSortFactor get albumSortFactor => getEnumOrDefault(albumSortFactorKey, SettingsDefaults.chipListSortFactor, ChipSortFactor.values); - - set albumSortFactor(ChipSortFactor newValue) => _set(albumSortFactorKey, newValue.toString()); - - ChipSortFactor get countrySortFactor => getEnumOrDefault(countrySortFactorKey, SettingsDefaults.chipListSortFactor, ChipSortFactor.values); - - set countrySortFactor(ChipSortFactor newValue) => _set(countrySortFactorKey, newValue.toString()); - - ChipSortFactor get stateSortFactor => getEnumOrDefault(stateSortFactorKey, SettingsDefaults.chipListSortFactor, ChipSortFactor.values); - - set stateSortFactor(ChipSortFactor newValue) => _set(stateSortFactorKey, newValue.toString()); - - ChipSortFactor get placeSortFactor => getEnumOrDefault(placeSortFactorKey, SettingsDefaults.chipListSortFactor, ChipSortFactor.values); - - set placeSortFactor(ChipSortFactor newValue) => _set(placeSortFactorKey, newValue.toString()); - - ChipSortFactor get tagSortFactor => getEnumOrDefault(tagSortFactorKey, SettingsDefaults.chipListSortFactor, ChipSortFactor.values); - - set tagSortFactor(ChipSortFactor newValue) => _set(tagSortFactorKey, newValue.toString()); - - bool get albumSortReverse => getBool(albumSortReverseKey) ?? false; - - set albumSortReverse(bool newValue) => _set(albumSortReverseKey, newValue); - - bool get countrySortReverse => getBool(countrySortReverseKey) ?? false; - - set countrySortReverse(bool newValue) => _set(countrySortReverseKey, newValue); - - bool get stateSortReverse => getBool(stateSortReverseKey) ?? false; - - set stateSortReverse(bool newValue) => _set(stateSortReverseKey, newValue); - - bool get placeSortReverse => getBool(placeSortReverseKey) ?? false; - - set placeSortReverse(bool newValue) => _set(placeSortReverseKey, newValue); - - bool get tagSortReverse => getBool(tagSortReverseKey) ?? false; - - set tagSortReverse(bool newValue) => _set(tagSortReverseKey, newValue); - - Set get pinnedFilters => (getStringList(pinnedFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); - - set pinnedFilters(Set newValue) => _set(pinnedFiltersKey, newValue.map((filter) => filter.toJson()).toList()); - - Set get hiddenFilters => (getStringList(hiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); - - set hiddenFilters(Set newValue) => _set(hiddenFiltersKey, newValue.map((filter) => filter.toJson()).toList()); - - void changeFilterVisibility(Set filters, bool visible) { - final _hiddenFilters = hiddenFilters; - if (visible) { - _hiddenFilters.removeAll(filters); - } else { - _hiddenFilters.addAll(filters); - searchHistory = searchHistory..removeWhere(filters.contains); - } - hiddenFilters = _hiddenFilters; - } - - bool get showAlbumPickQuery => getBool(showAlbumPickQueryKey) ?? false; - - set showAlbumPickQuery(bool newValue) => _set(showAlbumPickQueryKey, newValue); - - // viewer - - List get viewerQuickActions => getEnumListOrDefault(viewerQuickActionsKey, SettingsDefaults.viewerQuickActions, EntryAction.values); - - set viewerQuickActions(List newValue) => _set(viewerQuickActionsKey, newValue.map((v) => v.toString()).toList()); - - bool get showOverlayOnOpening => getBool(showOverlayOnOpeningKey) ?? SettingsDefaults.showOverlayOnOpening; - - set showOverlayOnOpening(bool newValue) => _set(showOverlayOnOpeningKey, newValue); - - bool get showOverlayMinimap => getBool(showOverlayMinimapKey) ?? SettingsDefaults.showOverlayMinimap; - - set showOverlayMinimap(bool newValue) => _set(showOverlayMinimapKey, newValue); - - bool get showOverlayInfo => getBool(showOverlayInfoKey) ?? SettingsDefaults.showOverlayInfo; - - set showOverlayInfo(bool newValue) => _set(showOverlayInfoKey, newValue); - - bool get showOverlayDescription => getBool(showOverlayDescriptionKey) ?? SettingsDefaults.showOverlayDescription; - - set showOverlayDescription(bool newValue) => _set(showOverlayDescriptionKey, newValue); - - bool get showOverlayRatingTags => getBool(showOverlayRatingTagsKey) ?? SettingsDefaults.showOverlayRatingTags; - - set showOverlayRatingTags(bool newValue) => _set(showOverlayRatingTagsKey, newValue); - - bool get showOverlayShootingDetails => getBool(showOverlayShootingDetailsKey) ?? SettingsDefaults.showOverlayShootingDetails; - - set showOverlayShootingDetails(bool newValue) => _set(showOverlayShootingDetailsKey, newValue); - - bool get showOverlayThumbnailPreview => getBool(showOverlayThumbnailPreviewKey) ?? SettingsDefaults.showOverlayThumbnailPreview; - - set showOverlayThumbnailPreview(bool newValue) => _set(showOverlayThumbnailPreviewKey, newValue); - - bool get viewerGestureSideTapNext => getBool(viewerGestureSideTapNextKey) ?? SettingsDefaults.viewerGestureSideTapNext; - - set viewerGestureSideTapNext(bool newValue) => _set(viewerGestureSideTapNextKey, newValue); - - bool get viewerUseCutout => getBool(viewerUseCutoutKey) ?? SettingsDefaults.viewerUseCutout; - - set viewerUseCutout(bool newValue) => _set(viewerUseCutoutKey, newValue); - - bool get enableMotionPhotoAutoPlay => getBool(enableMotionPhotoAutoPlayKey) ?? SettingsDefaults.enableMotionPhotoAutoPlay; - - set enableMotionPhotoAutoPlay(bool newValue) => _set(enableMotionPhotoAutoPlayKey, newValue); - - EntryBackground get imageBackground => getEnumOrDefault(imageBackgroundKey, SettingsDefaults.imageBackground, EntryBackground.values); - - set imageBackground(EntryBackground newValue) => _set(imageBackgroundKey, newValue.toString()); - - // video - - bool get enableVideoHardwareAcceleration => getBool(enableVideoHardwareAccelerationKey) ?? SettingsDefaults.enableVideoHardwareAcceleration; - - set enableVideoHardwareAcceleration(bool newValue) => _set(enableVideoHardwareAccelerationKey, newValue); - - VideoAutoPlayMode get videoAutoPlayMode => getEnumOrDefault(videoAutoPlayModeKey, SettingsDefaults.videoAutoPlayMode, VideoAutoPlayMode.values); - - set videoAutoPlayMode(VideoAutoPlayMode newValue) => _set(videoAutoPlayModeKey, newValue.toString()); - - VideoBackgroundMode get videoBackgroundMode => getEnumOrDefault(videoBackgroundModeKey, SettingsDefaults.videoBackgroundMode, VideoBackgroundMode.values); - - set videoBackgroundMode(VideoBackgroundMode newValue) => _set(videoBackgroundModeKey, newValue.toString()); - - VideoLoopMode get videoLoopMode => getEnumOrDefault(videoLoopModeKey, SettingsDefaults.videoLoopMode, VideoLoopMode.values); - - set videoLoopMode(VideoLoopMode newValue) => _set(videoLoopModeKey, newValue.toString()); - - VideoResumptionMode get videoResumptionMode => getEnumOrDefault(videoResumptionModeKey, SettingsDefaults.videoResumptionMode, VideoResumptionMode.values); - - set videoResumptionMode(VideoResumptionMode newValue) => _set(videoResumptionModeKey, newValue.toString()); - - VideoControls get videoControls => getEnumOrDefault(videoControlsKey, SettingsDefaults.videoControls, VideoControls.values); - - set videoControls(VideoControls newValue) => _set(videoControlsKey, newValue.toString()); - - bool get videoGestureDoubleTapTogglePlay => getBool(videoGestureDoubleTapTogglePlayKey) ?? SettingsDefaults.videoGestureDoubleTapTogglePlay; - - set videoGestureDoubleTapTogglePlay(bool newValue) => _set(videoGestureDoubleTapTogglePlayKey, newValue); - - bool get videoGestureSideDoubleTapSeek => getBool(videoGestureSideDoubleTapSeekKey) ?? SettingsDefaults.videoGestureSideDoubleTapSeek; - - set videoGestureSideDoubleTapSeek(bool newValue) => _set(videoGestureSideDoubleTapSeekKey, newValue); - - bool get videoGestureVerticalDragBrightnessVolume => getBool(videoGestureVerticalDragBrightnessVolumeKey) ?? SettingsDefaults.videoGestureVerticalDragBrightnessVolume; - - set videoGestureVerticalDragBrightnessVolume(bool newValue) => _set(videoGestureVerticalDragBrightnessVolumeKey, newValue); - - // subtitles - - double get subtitleFontSize => getDouble(subtitleFontSizeKey) ?? SettingsDefaults.subtitleFontSize; - - set subtitleFontSize(double newValue) => _set(subtitleFontSizeKey, newValue); - - TextAlign get subtitleTextAlignment => getEnumOrDefault(subtitleTextAlignmentKey, SettingsDefaults.subtitleTextAlignment, TextAlign.values); - - set subtitleTextAlignment(TextAlign newValue) => _set(subtitleTextAlignmentKey, newValue.toString()); - - SubtitlePosition get subtitleTextPosition => getEnumOrDefault(subtitleTextPositionKey, SettingsDefaults.subtitleTextPosition, SubtitlePosition.values); - - set subtitleTextPosition(SubtitlePosition newValue) => _set(subtitleTextPositionKey, newValue.toString()); - - bool get subtitleShowOutline => getBool(subtitleShowOutlineKey) ?? SettingsDefaults.subtitleShowOutline; - - set subtitleShowOutline(bool newValue) => _set(subtitleShowOutlineKey, newValue); - - Color get subtitleTextColor => Color(getInt(subtitleTextColorKey) ?? SettingsDefaults.subtitleTextColor.value); - - set subtitleTextColor(Color newValue) => _set(subtitleTextColorKey, newValue.value); - - Color get subtitleBackgroundColor => Color(getInt(subtitleBackgroundColorKey) ?? SettingsDefaults.subtitleBackgroundColor.value); - - set subtitleBackgroundColor(Color newValue) => _set(subtitleBackgroundColorKey, newValue.value); - - // info - - double get infoMapZoom => getDouble(infoMapZoomKey) ?? SettingsDefaults.infoMapZoom; - - set infoMapZoom(double newValue) => _set(infoMapZoomKey, newValue); - - CoordinateFormat get coordinateFormat => getEnumOrDefault(coordinateFormatKey, SettingsDefaults.coordinateFormat, CoordinateFormat.values); - - set coordinateFormat(CoordinateFormat newValue) => _set(coordinateFormatKey, newValue.toString()); - - UnitSystem get unitSystem => getEnumOrDefault(unitSystemKey, SettingsDefaults.unitSystem, UnitSystem.values); - - set unitSystem(UnitSystem newValue) => _set(unitSystemKey, newValue.toString()); - // tag editor - bool get tagEditorCurrentFilterSectionExpanded => getBool(tagEditorCurrentFilterSectionExpandedKey) ?? SettingsDefaults.tagEditorCurrentFilterSectionExpanded; + bool get tagEditorCurrentFilterSectionExpanded => getBool(SettingKeys.tagEditorCurrentFilterSectionExpandedKey) ?? SettingsDefaults.tagEditorCurrentFilterSectionExpanded; - set tagEditorCurrentFilterSectionExpanded(bool newValue) => _set(tagEditorCurrentFilterSectionExpandedKey, newValue); + set tagEditorCurrentFilterSectionExpanded(bool newValue) => set(SettingKeys.tagEditorCurrentFilterSectionExpandedKey, newValue); - String? get tagEditorExpandedSection => getString(tagEditorExpandedSectionKey); + String? get tagEditorExpandedSection => getString(SettingKeys.tagEditorExpandedSectionKey); - set tagEditorExpandedSection(String? newValue) => _set(tagEditorExpandedSectionKey, newValue); + set tagEditorExpandedSection(String? newValue) => set(SettingKeys.tagEditorExpandedSectionKey, newValue); // converter - String get convertMimeType => getString(convertMimeTypeKey) ?? SettingsDefaults.convertMimeType; + String get convertMimeType => getString(SettingKeys.convertMimeTypeKey) ?? SettingsDefaults.convertMimeType; - set convertMimeType(String newValue) => _set(convertMimeTypeKey, newValue); + set convertMimeType(String newValue) => set(SettingKeys.convertMimeTypeKey, newValue); - int get convertQuality => getInt(convertQualityKey) ?? SettingsDefaults.convertQuality; + int get convertQuality => getInt(SettingKeys.convertQualityKey) ?? SettingsDefaults.convertQuality; - set convertQuality(int newValue) => _set(convertQualityKey, newValue); + set convertQuality(int newValue) => set(SettingKeys.convertQualityKey, newValue); - bool get convertWriteMetadata => getBool(convertWriteMetadataKey) ?? SettingsDefaults.convertWriteMetadata; + bool get convertWriteMetadata => getBool(SettingKeys.convertWriteMetadataKey) ?? SettingsDefaults.convertWriteMetadata; - set convertWriteMetadata(bool newValue) => _set(convertWriteMetadataKey, newValue); + set convertWriteMetadata(bool newValue) => set(SettingKeys.convertWriteMetadataKey, newValue); // map EntryMapStyle? get mapStyle { - final preferred = getEnumOrDefault(mapStyleKey, null, EntryMapStyle.values); + final preferred = getEnumOrDefault(SettingKeys.mapStyleKey, null, EntryMapStyle.values); if (preferred == null) return null; final available = availability.mapStyles; return available.contains(preferred) ? preferred : available.first; } - set mapStyle(EntryMapStyle? newValue) => _set(mapStyleKey, newValue?.toString()); + set mapStyle(EntryMapStyle? newValue) => set(SettingKeys.mapStyleKey, newValue?.toString()); LatLng? get mapDefaultCenter { - final json = getString(mapDefaultCenterKey); + final json = getString(SettingKeys.mapDefaultCenterKey); return json != null ? LatLng.fromJson(jsonDecode(json)) : null; } - set mapDefaultCenter(LatLng? newValue) => _set(mapDefaultCenterKey, newValue != null ? jsonEncode(newValue.toJson()) : null); - - // search - - bool get saveSearchHistory => getBool(saveSearchHistoryKey) ?? SettingsDefaults.saveSearchHistory; - - set saveSearchHistory(bool newValue) => _set(saveSearchHistoryKey, newValue); - - List get searchHistory => (getStringList(searchHistoryKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toList(); - - set searchHistory(List newValue) => _set(searchHistoryKey, newValue.map((filter) => filter.toJson()).toList()); + set mapDefaultCenter(LatLng? newValue) => set(SettingKeys.mapDefaultCenterKey, newValue != null ? jsonEncode(newValue.toJson()) : null); // bin - bool get enableBin => getBool(enableBinKey) ?? SettingsDefaults.enableBin; + bool get enableBin => getBool(SettingKeys.enableBinKey) ?? SettingsDefaults.enableBin; - set enableBin(bool newValue) => _set(enableBinKey, newValue); + set enableBin(bool newValue) => set(SettingKeys.enableBinKey, newValue); // accessibility - bool get showPinchGestureAlternatives => getBool(showPinchGestureAlternativesKey) ?? SettingsDefaults.showPinchGestureAlternatives; + bool get showPinchGestureAlternatives => getBool(SettingKeys.showPinchGestureAlternativesKey) ?? SettingsDefaults.showPinchGestureAlternatives; - set showPinchGestureAlternatives(bool newValue) => _set(showPinchGestureAlternativesKey, newValue); + set showPinchGestureAlternatives(bool newValue) => set(SettingKeys.showPinchGestureAlternativesKey, newValue); - AccessibilityAnimations get accessibilityAnimations => getEnumOrDefault(accessibilityAnimationsKey, SettingsDefaults.accessibilityAnimations, AccessibilityAnimations.values); + AccessibilityAnimations get accessibilityAnimations => getEnumOrDefault(SettingKeys.accessibilityAnimationsKey, SettingsDefaults.accessibilityAnimations, AccessibilityAnimations.values); - set accessibilityAnimations(AccessibilityAnimations newValue) => _set(accessibilityAnimationsKey, newValue.toString()); + set accessibilityAnimations(AccessibilityAnimations newValue) => set(SettingKeys.accessibilityAnimationsKey, newValue.toString()); - AccessibilityTimeout get timeToTakeAction => getEnumOrDefault(timeToTakeActionKey, SettingsDefaults.timeToTakeAction, AccessibilityTimeout.values); + AccessibilityTimeout get timeToTakeAction => getEnumOrDefault(SettingKeys.timeToTakeActionKey, SettingsDefaults.timeToTakeAction, AccessibilityTimeout.values); - set timeToTakeAction(AccessibilityTimeout newValue) => _set(timeToTakeActionKey, newValue.toString()); + set timeToTakeAction(AccessibilityTimeout newValue) => set(SettingKeys.timeToTakeActionKey, newValue.toString()); // file picker - bool get filePickerShowHiddenFiles => getBool(filePickerShowHiddenFilesKey) ?? SettingsDefaults.filePickerShowHiddenFiles; + bool get filePickerShowHiddenFiles => getBool(SettingKeys.filePickerShowHiddenFilesKey) ?? SettingsDefaults.filePickerShowHiddenFiles; - set filePickerShowHiddenFiles(bool newValue) => _set(filePickerShowHiddenFilesKey, newValue); + set filePickerShowHiddenFiles(bool newValue) => set(SettingKeys.filePickerShowHiddenFilesKey, newValue); // screen saver - bool get screenSaverFillScreen => getBool(screenSaverFillScreenKey) ?? SettingsDefaults.slideshowFillScreen; + bool get screenSaverFillScreen => getBool(SettingKeys.screenSaverFillScreenKey) ?? SettingsDefaults.slideshowFillScreen; - set screenSaverFillScreen(bool newValue) => _set(screenSaverFillScreenKey, newValue); + set screenSaverFillScreen(bool newValue) => set(SettingKeys.screenSaverFillScreenKey, newValue); - bool get screenSaverAnimatedZoomEffect => getBool(screenSaverAnimatedZoomEffectKey) ?? SettingsDefaults.slideshowAnimatedZoomEffect; + bool get screenSaverAnimatedZoomEffect => getBool(SettingKeys.screenSaverAnimatedZoomEffectKey) ?? SettingsDefaults.slideshowAnimatedZoomEffect; - set screenSaverAnimatedZoomEffect(bool newValue) => _set(screenSaverAnimatedZoomEffectKey, newValue); + set screenSaverAnimatedZoomEffect(bool newValue) => set(SettingKeys.screenSaverAnimatedZoomEffectKey, newValue); - ViewerTransition get screenSaverTransition => getEnumOrDefault(screenSaverTransitionKey, SettingsDefaults.slideshowTransition, ViewerTransition.values); + ViewerTransition get screenSaverTransition => getEnumOrDefault(SettingKeys.screenSaverTransitionKey, SettingsDefaults.slideshowTransition, ViewerTransition.values); - set screenSaverTransition(ViewerTransition newValue) => _set(screenSaverTransitionKey, newValue.toString()); + set screenSaverTransition(ViewerTransition newValue) => set(SettingKeys.screenSaverTransitionKey, newValue.toString()); - SlideshowVideoPlayback get screenSaverVideoPlayback => getEnumOrDefault(screenSaverVideoPlaybackKey, SettingsDefaults.slideshowVideoPlayback, SlideshowVideoPlayback.values); + SlideshowVideoPlayback get screenSaverVideoPlayback => getEnumOrDefault(SettingKeys.screenSaverVideoPlaybackKey, SettingsDefaults.slideshowVideoPlayback, SlideshowVideoPlayback.values); - set screenSaverVideoPlayback(SlideshowVideoPlayback newValue) => _set(screenSaverVideoPlaybackKey, newValue.toString()); + set screenSaverVideoPlayback(SlideshowVideoPlayback newValue) => set(SettingKeys.screenSaverVideoPlaybackKey, newValue.toString()); - int get screenSaverInterval => getInt(screenSaverIntervalKey) ?? SettingsDefaults.slideshowInterval; + int get screenSaverInterval => getInt(SettingKeys.screenSaverIntervalKey) ?? SettingsDefaults.slideshowInterval; - set screenSaverInterval(int newValue) => _set(screenSaverIntervalKey, newValue); + set screenSaverInterval(int newValue) => set(SettingKeys.screenSaverIntervalKey, newValue); - Set get screenSaverCollectionFilters => (getStringList(screenSaverCollectionFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); + Set get screenSaverCollectionFilters => (getStringList(SettingKeys.screenSaverCollectionFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); - set screenSaverCollectionFilters(Set newValue) => _set(screenSaverCollectionFiltersKey, newValue.map((filter) => filter.toJson()).toList()); + set screenSaverCollectionFilters(Set newValue) => set(SettingKeys.screenSaverCollectionFiltersKey, newValue.map((filter) => filter.toJson()).toList()); // slideshow - bool get slideshowRepeat => getBool(slideshowRepeatKey) ?? SettingsDefaults.slideshowRepeat; + bool get slideshowRepeat => getBool(SettingKeys.slideshowRepeatKey) ?? SettingsDefaults.slideshowRepeat; - set slideshowRepeat(bool newValue) => _set(slideshowRepeatKey, newValue); + set slideshowRepeat(bool newValue) => set(SettingKeys.slideshowRepeatKey, newValue); - bool get slideshowShuffle => getBool(slideshowShuffleKey) ?? SettingsDefaults.slideshowShuffle; + bool get slideshowShuffle => getBool(SettingKeys.slideshowShuffleKey) ?? SettingsDefaults.slideshowShuffle; - set slideshowShuffle(bool newValue) => _set(slideshowShuffleKey, newValue); + set slideshowShuffle(bool newValue) => set(SettingKeys.slideshowShuffleKey, newValue); - bool get slideshowFillScreen => getBool(slideshowFillScreenKey) ?? SettingsDefaults.slideshowFillScreen; + bool get slideshowFillScreen => getBool(SettingKeys.slideshowFillScreenKey) ?? SettingsDefaults.slideshowFillScreen; - set slideshowFillScreen(bool newValue) => _set(slideshowFillScreenKey, newValue); + set slideshowFillScreen(bool newValue) => set(SettingKeys.slideshowFillScreenKey, newValue); - bool get slideshowAnimatedZoomEffect => getBool(slideshowAnimatedZoomEffectKey) ?? SettingsDefaults.slideshowAnimatedZoomEffect; + bool get slideshowAnimatedZoomEffect => getBool(SettingKeys.slideshowAnimatedZoomEffectKey) ?? SettingsDefaults.slideshowAnimatedZoomEffect; - set slideshowAnimatedZoomEffect(bool newValue) => _set(slideshowAnimatedZoomEffectKey, newValue); + set slideshowAnimatedZoomEffect(bool newValue) => set(SettingKeys.slideshowAnimatedZoomEffectKey, newValue); - ViewerTransition get slideshowTransition => getEnumOrDefault(slideshowTransitionKey, SettingsDefaults.slideshowTransition, ViewerTransition.values); + ViewerTransition get slideshowTransition => getEnumOrDefault(SettingKeys.slideshowTransitionKey, SettingsDefaults.slideshowTransition, ViewerTransition.values); - set slideshowTransition(ViewerTransition newValue) => _set(slideshowTransitionKey, newValue.toString()); + set slideshowTransition(ViewerTransition newValue) => set(SettingKeys.slideshowTransitionKey, newValue.toString()); - SlideshowVideoPlayback get slideshowVideoPlayback => getEnumOrDefault(slideshowVideoPlaybackKey, SettingsDefaults.slideshowVideoPlayback, SlideshowVideoPlayback.values); + SlideshowVideoPlayback get slideshowVideoPlayback => getEnumOrDefault(SettingKeys.slideshowVideoPlaybackKey, SettingsDefaults.slideshowVideoPlayback, SlideshowVideoPlayback.values); - set slideshowVideoPlayback(SlideshowVideoPlayback newValue) => _set(slideshowVideoPlaybackKey, newValue.toString()); + set slideshowVideoPlayback(SlideshowVideoPlayback newValue) => set(SettingKeys.slideshowVideoPlaybackKey, newValue.toString()); - int get slideshowInterval => getInt(slideshowIntervalKey) ?? SettingsDefaults.slideshowInterval; + int get slideshowInterval => getInt(SettingKeys.slideshowIntervalKey) ?? SettingsDefaults.slideshowInterval; - set slideshowInterval(int newValue) => _set(slideshowIntervalKey, newValue); + set slideshowInterval(int newValue) => set(SettingKeys.slideshowIntervalKey, newValue); // widget Color? getWidgetOutline(int widgetId) { - final value = getInt('$widgetOutlinePrefixKey$widgetId'); + final value = getInt('${SettingKeys.widgetOutlinePrefixKey}$widgetId'); return value != null ? Color(value) : null; } - void setWidgetOutline(int widgetId, Color? newValue) => _set('$widgetOutlinePrefixKey$widgetId', newValue?.value); + void setWidgetOutline(int widgetId, Color? newValue) => set('${SettingKeys.widgetOutlinePrefixKey}$widgetId', newValue?.value); - WidgetShape getWidgetShape(int widgetId) => getEnumOrDefault('$widgetShapePrefixKey$widgetId', SettingsDefaults.widgetShape, WidgetShape.values); + WidgetShape getWidgetShape(int widgetId) => getEnumOrDefault('${SettingKeys.widgetShapePrefixKey}$widgetId', SettingsDefaults.widgetShape, WidgetShape.values); - void setWidgetShape(int widgetId, WidgetShape newValue) => _set('$widgetShapePrefixKey$widgetId', newValue.toString()); + void setWidgetShape(int widgetId, WidgetShape newValue) => set('${SettingKeys.widgetShapePrefixKey}$widgetId', newValue.toString()); - Set getWidgetCollectionFilters(int widgetId) => (getStringList('$widgetCollectionFiltersPrefixKey$widgetId') ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); + Set getWidgetCollectionFilters(int widgetId) => (getStringList('${SettingKeys.widgetCollectionFiltersPrefixKey}$widgetId') ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); - void setWidgetCollectionFilters(int widgetId, Set newValue) => _set('$widgetCollectionFiltersPrefixKey$widgetId', newValue.map((filter) => filter.toJson()).toList()); + void setWidgetCollectionFilters(int widgetId, Set newValue) => set('${SettingKeys.widgetCollectionFiltersPrefixKey}$widgetId', newValue.map((filter) => filter.toJson()).toList()); - WidgetOpenPage getWidgetOpenPage(int widgetId) => getEnumOrDefault('$widgetOpenPagePrefixKey$widgetId', SettingsDefaults.widgetOpenPage, WidgetOpenPage.values); + WidgetOpenPage getWidgetOpenPage(int widgetId) => getEnumOrDefault('${SettingKeys.widgetOpenPagePrefixKey}$widgetId', SettingsDefaults.widgetOpenPage, WidgetOpenPage.values); - void setWidgetOpenPage(int widgetId, WidgetOpenPage newValue) => _set('$widgetOpenPagePrefixKey$widgetId', newValue.toString()); + void setWidgetOpenPage(int widgetId, WidgetOpenPage newValue) => set('${SettingKeys.widgetOpenPagePrefixKey}$widgetId', newValue.toString()); - WidgetDisplayedItem getWidgetDisplayedItem(int widgetId) => getEnumOrDefault('$widgetDisplayedItemPrefixKey$widgetId', SettingsDefaults.widgetDisplayedItem, WidgetDisplayedItem.values); + WidgetDisplayedItem getWidgetDisplayedItem(int widgetId) => getEnumOrDefault('${SettingKeys.widgetDisplayedItemPrefixKey}$widgetId', SettingsDefaults.widgetDisplayedItem, WidgetDisplayedItem.values); - void setWidgetDisplayedItem(int widgetId, WidgetDisplayedItem newValue) => _set('$widgetDisplayedItemPrefixKey$widgetId', newValue.toString()); + void setWidgetDisplayedItem(int widgetId, WidgetDisplayedItem newValue) => set('${SettingKeys.widgetDisplayedItemPrefixKey}$widgetId', newValue.toString()); - String? getWidgetUri(int widgetId) => getString('$widgetUriPrefixKey$widgetId'); + String? getWidgetUri(int widgetId) => getString('${SettingKeys.widgetUriPrefixKey}$widgetId'); - void setWidgetUri(int widgetId, String? newValue) => _set('$widgetUriPrefixKey$widgetId', newValue); - - // convenience methods - - bool? getBool(String key) { - try { - return settingsStore.getBool(key); - } catch (error) { - // ignore, could be obsolete value of different type - return null; - } - } - - int? getInt(String key) { - try { - return settingsStore.getInt(key); - } catch (error) { - // ignore, could be obsolete value of different type - return null; - } - } - - double? getDouble(String key) { - try { - return settingsStore.getDouble(key); - } catch (error) { - // ignore, could be obsolete value of different type - return null; - } - } - - String? getString(String key) { - try { - return settingsStore.getString(key); - } catch (error) { - // ignore, could be obsolete value of different type - return null; - } - } - - List? getStringList(String key) { - try { - return settingsStore.getStringList(key); - } catch (error) { - // ignore, could be obsolete value of different type - return null; - } - } - - T getEnumOrDefault(String key, T defaultValue, Iterable values) { - try { - final valueString = settingsStore.getString(key); - for (final v in values) { - if (v.toString() == valueString) { - return v; - } - } - } catch (error) { - // ignore, could be obsolete value of different type - } - return defaultValue; - } - - List getEnumListOrDefault(String key, List defaultValue, Iterable values) { - return settingsStore.getStringList(key)?.map((s) => values.firstWhereOrNull((v) => v.toString() == s)).whereNotNull().toList() ?? defaultValue; - } - - void _set(String key, dynamic newValue) { - var oldValue = settingsStore.get(key); - if (newValue == null) { - settingsStore.remove(key); - } else if (newValue is String) { - oldValue = getString(key); - settingsStore.setString(key, newValue); - } else if (newValue is List) { - oldValue = getStringList(key); - settingsStore.setStringList(key, newValue); - } else if (newValue is int) { - oldValue = getInt(key); - settingsStore.setInt(key, newValue); - } else if (newValue is double) { - oldValue = getDouble(key); - settingsStore.setDouble(key, newValue); - } else if (newValue is bool) { - oldValue = getBool(key); - settingsStore.setBool(key, newValue); - } - if (oldValue != newValue) { - _updateStreamController.add(SettingsChangedEvent(key, oldValue, newValue)); - notifyListeners(); - } - } + void setWidgetUri(int widgetId, String? newValue) => set('${SettingKeys.widgetUriPrefixKey}$widgetId', newValue); // platform settings void _onPlatformSettingsChanged(Map? fields) { fields?.forEach((key, value) { switch (key) { - case platformAccelerometerRotationKey: + case SettingKeys.platformAccelerometerRotationKey: if (value is num) { isRotationLocked = value == 0; } - case platformTransitionAnimationScaleKey: + case SettingKeys.platformTransitionAnimationScaleKey: if (value is num) { areAnimationsRemoved = value == 0; } @@ -1030,18 +318,18 @@ class Settings extends ChangeNotifier { }); } - bool get isRotationLocked => getBool(platformAccelerometerRotationKey) ?? SettingsDefaults.isRotationLocked; + bool get isRotationLocked => getBool(SettingKeys.platformAccelerometerRotationKey) ?? SettingsDefaults.isRotationLocked; - set isRotationLocked(bool newValue) => _set(platformAccelerometerRotationKey, newValue); + set isRotationLocked(bool newValue) => set(SettingKeys.platformAccelerometerRotationKey, newValue); - bool get areAnimationsRemoved => getBool(platformTransitionAnimationScaleKey) ?? SettingsDefaults.areAnimationsRemoved; + bool get areAnimationsRemoved => getBool(SettingKeys.platformTransitionAnimationScaleKey) ?? SettingsDefaults.areAnimationsRemoved; - set areAnimationsRemoved(bool newValue) => _set(platformTransitionAnimationScaleKey, newValue); + set areAnimationsRemoved(bool newValue) => set(SettingKeys.platformTransitionAnimationScaleKey, newValue); // import/export Map export() => Map.fromEntries( - settingsStore.getKeys().whereNot(isInternalKey).map((k) => MapEntry(k, settingsStore.get(k))), + store.getKeys().whereNot(SettingKeys.isInternalKey).map((k) => MapEntry(k, store.get(k))), ); Future import(dynamic jsonMap) async { @@ -1051,171 +339,169 @@ class Settings extends ChangeNotifier { // apply user modifications jsonMap.forEach((key, newValue) { - final oldValue = settingsStore.get(key); + final oldValue = store.get(key); if (newValue == null) { - settingsStore.remove(key); - } else if (key.startsWith(tileExtentPrefixKey)) { + store.remove(key); + } else if (key.startsWith(SettingKeys.tileExtentPrefixKey)) { if (newValue is double) { - settingsStore.setDouble(key, newValue); + store.setDouble(key, newValue); } else { debugPrint('failed to import key=$key, value=$newValue is not a double'); } - } else if (key.startsWith(tileLayoutPrefixKey)) { + } else if (key.startsWith(SettingKeys.tileLayoutPrefixKey)) { if (newValue is String) { - settingsStore.setString(key, newValue); + store.setString(key, newValue); } else { debugPrint('failed to import key=$key, value=$newValue is not a string'); } } else { switch (key) { - case subtitleTextColorKey: - case subtitleBackgroundColorKey: - case convertQualityKey: - case screenSaverIntervalKey: - case slideshowIntervalKey: + case SettingKeys.subtitleTextColorKey: + case SettingKeys.subtitleBackgroundColorKey: + case SettingKeys.convertQualityKey: + case SettingKeys.screenSaverIntervalKey: + case SettingKeys.slideshowIntervalKey: if (newValue is int) { - settingsStore.setInt(key, newValue); + store.setInt(key, newValue); } else { debugPrint('failed to import key=$key, value=$newValue is not an int'); } - case subtitleFontSizeKey: - case infoMapZoomKey: + case SettingKeys.subtitleFontSizeKey: + case SettingKeys.infoMapZoomKey: if (newValue is double) { - settingsStore.setDouble(key, newValue); + store.setDouble(key, newValue); } else { debugPrint('failed to import key=$key, value=$newValue is not a double'); } - case isInstalledAppAccessAllowedKey: - case isErrorReportingAllowedKey: - case enableDynamicColorKey: - case enableBlurEffectKey: - case enableBottomNavigationBarKey: - case mustBackTwiceToExitKey: - case confirmCreateVaultKey: - case confirmDeleteForeverKey: - case confirmMoveToBinKey: - case confirmMoveUndatedItemsKey: - case confirmAfterMoveToBinKey: - case setMetadataDateBeforeFileOpKey: - case collectionSortReverseKey: - case showThumbnailFavouriteKey: - case showThumbnailMotionPhotoKey: - case showThumbnailRatingKey: - case showThumbnailRawKey: - case showThumbnailVideoDurationKey: - case albumSortReverseKey: - case countrySortReverseKey: - case stateSortReverseKey: - case placeSortReverseKey: - case tagSortReverseKey: - case showAlbumPickQueryKey: - case showOverlayOnOpeningKey: - case showOverlayMinimapKey: - case showOverlayInfoKey: - case showOverlayDescriptionKey: - case showOverlayRatingTagsKey: - case showOverlayShootingDetailsKey: - case showOverlayThumbnailPreviewKey: - case viewerGestureSideTapNextKey: - case viewerUseCutoutKey: - case enableMotionPhotoAutoPlayKey: - case enableVideoHardwareAccelerationKey: - case videoGestureDoubleTapTogglePlayKey: - case videoGestureSideDoubleTapSeekKey: - case videoGestureVerticalDragBrightnessVolumeKey: - case subtitleShowOutlineKey: - case tagEditorCurrentFilterSectionExpandedKey: - case convertWriteMetadataKey: - case saveSearchHistoryKey: - case showPinchGestureAlternativesKey: - case filePickerShowHiddenFilesKey: - case screenSaverFillScreenKey: - case screenSaverAnimatedZoomEffectKey: - case slideshowRepeatKey: - case slideshowShuffleKey: - case slideshowFillScreenKey: - case slideshowAnimatedZoomEffectKey: + case SettingKeys.isInstalledAppAccessAllowedKey: + case SettingKeys.isErrorReportingAllowedKey: + case SettingKeys.enableDynamicColorKey: + case SettingKeys.enableBlurEffectKey: + case SettingKeys.enableBottomNavigationBarKey: + case SettingKeys.mustBackTwiceToExitKey: + case SettingKeys.confirmCreateVaultKey: + case SettingKeys.confirmDeleteForeverKey: + case SettingKeys.confirmMoveToBinKey: + case SettingKeys.confirmMoveUndatedItemsKey: + case SettingKeys.confirmAfterMoveToBinKey: + case SettingKeys.setMetadataDateBeforeFileOpKey: + case SettingKeys.collectionSortReverseKey: + case SettingKeys.showThumbnailFavouriteKey: + case SettingKeys.showThumbnailMotionPhotoKey: + case SettingKeys.showThumbnailRatingKey: + case SettingKeys.showThumbnailRawKey: + case SettingKeys.showThumbnailVideoDurationKey: + case SettingKeys.albumSortReverseKey: + case SettingKeys.countrySortReverseKey: + case SettingKeys.stateSortReverseKey: + case SettingKeys.placeSortReverseKey: + case SettingKeys.tagSortReverseKey: + case SettingKeys.showAlbumPickQueryKey: + case SettingKeys.showOverlayOnOpeningKey: + case SettingKeys.showOverlayMinimapKey: + case SettingKeys.showOverlayInfoKey: + case SettingKeys.showOverlayDescriptionKey: + case SettingKeys.showOverlayRatingTagsKey: + case SettingKeys.showOverlayShootingDetailsKey: + case SettingKeys.showOverlayThumbnailPreviewKey: + case SettingKeys.viewerGestureSideTapNextKey: + case SettingKeys.viewerUseCutoutKey: + case SettingKeys.enableMotionPhotoAutoPlayKey: + case SettingKeys.enableVideoHardwareAccelerationKey: + case SettingKeys.videoGestureDoubleTapTogglePlayKey: + case SettingKeys.videoGestureSideDoubleTapSeekKey: + case SettingKeys.videoGestureVerticalDragBrightnessVolumeKey: + case SettingKeys.subtitleShowOutlineKey: + case SettingKeys.tagEditorCurrentFilterSectionExpandedKey: + case SettingKeys.convertWriteMetadataKey: + case SettingKeys.saveSearchHistoryKey: + case SettingKeys.showPinchGestureAlternativesKey: + case SettingKeys.filePickerShowHiddenFilesKey: + case SettingKeys.screenSaverFillScreenKey: + case SettingKeys.screenSaverAnimatedZoomEffectKey: + case SettingKeys.slideshowRepeatKey: + case SettingKeys.slideshowShuffleKey: + case SettingKeys.slideshowFillScreenKey: + case SettingKeys.slideshowAnimatedZoomEffectKey: if (newValue is bool) { - settingsStore.setBool(key, newValue); + store.setBool(key, newValue); } else { debugPrint('failed to import key=$key, value=$newValue is not a bool'); } - case localeKey: - case displayRefreshRateModeKey: - case themeBrightnessKey: - case themeColorModeKey: - case maxBrightnessKey: - case keepScreenOnKey: - case homePageKey: - case collectionGroupFactorKey: - case collectionSortFactorKey: - case thumbnailLocationIconKey: - case thumbnailTagIconKey: - case albumGroupFactorKey: - case albumSortFactorKey: - case countrySortFactorKey: - case stateSortFactorKey: - case placeSortFactorKey: - case tagSortFactorKey: - case imageBackgroundKey: - case videoAutoPlayModeKey: - case videoBackgroundModeKey: - case videoLoopModeKey: - case videoResumptionModeKey: - case videoControlsKey: - case subtitleTextAlignmentKey: - case subtitleTextPositionKey: - case tagEditorExpandedSectionKey: - case convertMimeTypeKey: - case mapStyleKey: - case mapDefaultCenterKey: - case coordinateFormatKey: - case unitSystemKey: - case accessibilityAnimationsKey: - case timeToTakeActionKey: - case screenSaverTransitionKey: - case screenSaverVideoPlaybackKey: - case slideshowTransitionKey: - case slideshowVideoPlaybackKey: + case SettingKeys.localeKey: + case SettingKeys.displayRefreshRateModeKey: + case SettingKeys.themeBrightnessKey: + case SettingKeys.themeColorModeKey: + case SettingKeys.maxBrightnessKey: + case SettingKeys.keepScreenOnKey: + case SettingKeys.homePageKey: + case SettingKeys.collectionGroupFactorKey: + case SettingKeys.collectionSortFactorKey: + case SettingKeys.thumbnailLocationIconKey: + case SettingKeys.thumbnailTagIconKey: + case SettingKeys.albumGroupFactorKey: + case SettingKeys.albumSortFactorKey: + case SettingKeys.countrySortFactorKey: + case SettingKeys.stateSortFactorKey: + case SettingKeys.placeSortFactorKey: + case SettingKeys.tagSortFactorKey: + case SettingKeys.imageBackgroundKey: + case SettingKeys.videoAutoPlayModeKey: + case SettingKeys.videoBackgroundModeKey: + case SettingKeys.videoLoopModeKey: + case SettingKeys.videoResumptionModeKey: + case SettingKeys.videoControlsKey: + case SettingKeys.subtitleTextAlignmentKey: + case SettingKeys.subtitleTextPositionKey: + case SettingKeys.tagEditorExpandedSectionKey: + case SettingKeys.convertMimeTypeKey: + case SettingKeys.mapStyleKey: + case SettingKeys.mapDefaultCenterKey: + case SettingKeys.coordinateFormatKey: + case SettingKeys.unitSystemKey: + case SettingKeys.accessibilityAnimationsKey: + case SettingKeys.timeToTakeActionKey: + case SettingKeys.screenSaverTransitionKey: + case SettingKeys.screenSaverVideoPlaybackKey: + case SettingKeys.slideshowTransitionKey: + case SettingKeys.slideshowVideoPlaybackKey: if (newValue is String) { - settingsStore.setString(key, newValue); + store.setString(key, newValue); } else { debugPrint('failed to import key=$key, value=$newValue is not a string'); } - case drawerTypeBookmarksKey: - case drawerAlbumBookmarksKey: - case drawerPageBookmarksKey: - case collectionBurstPatternsKey: - case pinnedFiltersKey: - case hiddenFiltersKey: - case collectionBrowsingQuickActionsKey: - case collectionSelectionQuickActionsKey: - case viewerQuickActionsKey: - case screenSaverCollectionFiltersKey: + case SettingKeys.drawerTypeBookmarksKey: + case SettingKeys.drawerAlbumBookmarksKey: + case SettingKeys.drawerPageBookmarksKey: + case SettingKeys.collectionBurstPatternsKey: + case SettingKeys.pinnedFiltersKey: + case SettingKeys.hiddenFiltersKey: + case SettingKeys.collectionBrowsingQuickActionsKey: + case SettingKeys.collectionSelectionQuickActionsKey: + case SettingKeys.viewerQuickActionsKey: + case SettingKeys.screenSaverCollectionFiltersKey: if (newValue is List) { - settingsStore.setStringList(key, newValue.cast()); + store.setStringList(key, newValue.cast()); } else { debugPrint('failed to import key=$key, value=$newValue is not a list'); } } } if (oldValue != newValue) { - _updateStreamController.add(SettingsChangedEvent(key, oldValue, newValue)); + notifyKeyChange(key, oldValue, newValue); } }); await sanitize(); notifyListeners(); } } -} -@immutable -class SettingsChangedEvent { - final String key; - final dynamic oldValue; - final dynamic newValue; - - // old and new values as stored, e.g. `List` for collections - const SettingsChangedEvent(this.key, this.oldValue, this.newValue); + @override + void notifyKeyChange(String key, dynamic oldValue, dynamic newValue) { + _updateStreamController.add(SettingsChangedEvent(key, oldValue, newValue)); + if (key.startsWith(SettingKeys.tileExtentPrefixKey)) { + _updateTileExtentStreamController.add(SettingsChangedEvent(key, oldValue, newValue)); + } + } } diff --git a/lib/model/settings/store/store_shared_pref.dart b/lib/model/settings/store_shared_pref.dart similarity index 96% rename from lib/model/settings/store/store_shared_pref.dart rename to lib/model/settings/store_shared_pref.dart index 10e2477c0..6547d8c36 100644 --- a/lib/model/settings/store/store_shared_pref.dart +++ b/lib/model/settings/store_shared_pref.dart @@ -1,4 +1,4 @@ -import 'package:aves/model/settings/store/store.dart'; +import 'package:aves_model/aves_model.dart'; import 'package:flutter/foundation.dart'; import 'package:shared_preferences/shared_preferences.dart'; diff --git a/lib/model/source/collection_lens.dart b/lib/model/source/collection_lens.dart index dfc922a3b..b6d66733e 100644 --- a/lib/model/source/collection_lens.dart +++ b/lib/model/source/collection_lens.dart @@ -84,10 +84,10 @@ class CollectionLens with ChangeNotifier { } _subscriptions.add(settings.updateStream .where((event) => [ - Settings.collectionBurstPatternsKey, - Settings.collectionSortFactorKey, - Settings.collectionGroupFactorKey, - Settings.collectionSortReverseKey, + SettingKeys.collectionBurstPatternsKey, + SettingKeys.collectionSortFactorKey, + SettingKeys.collectionGroupFactorKey, + SettingKeys.collectionSortReverseKey, ].contains(event.key)) .listen((_) => _onSettingsChanged())); refresh(); diff --git a/lib/model/source/collection_source.dart b/lib/model/source/collection_source.dart index e12ee7da3..a6b76d4c4 100644 --- a/lib/model/source/collection_source.dart +++ b/lib/model/source/collection_source.dart @@ -61,8 +61,8 @@ mixin SourceBase { abstract class CollectionSource with SourceBase, AlbumMixin, CountryMixin, PlaceMixin, StateMixin, LocationMixin, TagMixin, TrashMixin { CollectionSource() { - settings.updateStream.where((event) => event.key == Settings.localeKey).listen((_) => invalidateAlbumDisplayNames()); - settings.updateStream.where((event) => event.key == Settings.hiddenFiltersKey).listen((event) { + settings.updateStream.where((event) => event.key == SettingKeys.localeKey).listen((_) => invalidateAlbumDisplayNames()); + settings.updateStream.where((event) => event.key == SettingKeys.hiddenFiltersKey).listen((event) { final oldValue = event.oldValue; if (oldValue is List?) { final oldHiddenFilters = (oldValue ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); diff --git a/lib/model/video/metadata.dart b/lib/model/video/metadata.dart index 25593eb39..c7707fec5 100644 --- a/lib/model/video/metadata.dart +++ b/lib/model/video/metadata.dart @@ -15,13 +15,14 @@ import 'package:aves/utils/file_utils.dart'; import 'package:aves/utils/math_utils.dart'; import 'package:aves/utils/string_utils.dart'; import 'package:aves/utils/time_utils.dart'; -import 'package:aves/widgets/viewer/video/fijkplayer.dart'; import 'package:aves_model/aves_model.dart'; +import 'package:aves_video_ijk/aves_video_ijk.dart'; import 'package:collection/collection.dart'; import 'package:fijkplayer/fijkplayer.dart'; import 'package:flutter/foundation.dart'; class VideoMetadataFormatter { + static bool _initializedFijkLog = false; static final _dateY4M2D2H2m2s2Pattern = RegExp(r'(\d{4})[-./:](\d{1,2})[-./:](\d{1,2})([ T](\d{1,2}):(\d{1,2}):(\d{1,2})( ([ap]\.? ?m\.?))?)?'); static final _ambiguousDatePatterns = { RegExp(r'^\d{2}[-/]\d{2}[-/]\d{4}$'), @@ -45,6 +46,10 @@ class VideoMetadataFormatter { }; static Future getVideoMetadata(AvesEntry entry) async { + if (!_initializedFijkLog) { + _initializedFijkLog = true; + FijkLog.setLevel(FijkLogLevel.Warn); + } final player = FijkPlayer(); final info = await player.setDataSourceUntilPrepared(entry.uri).then((v) { return player.getInfo(); diff --git a/lib/services/analysis_service.dart b/lib/services/analysis_service.dart index 071561f35..eeb91fb8b 100644 --- a/lib/services/analysis_service.dart +++ b/lib/services/analysis_service.dart @@ -10,7 +10,6 @@ import 'package:aves/services/common/services.dart'; import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/view/view.dart'; import 'package:aves_model/aves_model.dart'; -import 'package:fijkplayer/fijkplayer.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -52,7 +51,6 @@ Future _init() async { await device.init(); await mobileServices.init(); await settings.init(monitorPlatformSettings: false); - FijkLog.setLevel(FijkLogLevel.Warn); await reportService.init(); final analyzer = Analyzer(); diff --git a/lib/services/common/services.dart b/lib/services/common/services.dart index 89ce1c47a..83c22a918 100644 --- a/lib/services/common/services.dart +++ b/lib/services/common/services.dart @@ -1,8 +1,7 @@ import 'package:aves/model/availability.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/model/settings/store_shared_pref.dart'; import 'package:aves/services/app_service.dart'; import 'package:aves/services/device_service.dart'; import 'package:aves/services/media/embedded_data_service.dart'; @@ -15,6 +14,7 @@ import 'package:aves/services/metadata/metadata_fetch_service.dart'; import 'package:aves/services/security_service.dart'; import 'package:aves/services/storage_service.dart'; import 'package:aves/services/window_service.dart'; +import 'package:aves_model/aves_model.dart'; import 'package:aves_report/aves_report.dart'; import 'package:aves_report_platform/aves_report_platform.dart'; import 'package:aves_services/aves_services.dart'; diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index 35bce20a5..6f90e7521 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -41,7 +41,6 @@ import 'package:aves_model/aves_model.dart'; import 'package:aves_utils/aves_utils.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:equatable/equatable.dart'; -import 'package:fijkplayer/fijkplayer.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -456,7 +455,6 @@ class _AvesAppState extends State with WidgetsBindingObserver { await _onTvLayoutChanged(); _monitorSettings(); - FijkLog.setLevel(FijkLogLevel.Warn); unawaited(_setupErrorReporting()); debugPrint('App setup in ${stopwatch.elapsed.inMilliseconds}ms'); @@ -549,15 +547,15 @@ class _AvesAppState extends State with WidgetsBindingObserver { final settingStream = settings.updateStream; // app - settingStream.where((event) => event.key == Settings.isInstalledAppAccessAllowedKey).listen((_) => applyIsInstalledAppAccessAllowed()); + settingStream.where((event) => event.key == SettingKeys.isInstalledAppAccessAllowedKey).listen((_) => applyIsInstalledAppAccessAllowed()); // display - settingStream.where((event) => event.key == Settings.displayRefreshRateModeKey).listen((_) => applyDisplayRefreshRateMode()); - settingStream.where((event) => event.key == Settings.maxBrightnessKey).listen((_) => applyMaxBrightness()); - settingStream.where((event) => event.key == Settings.forceTvLayoutKey).listen((_) => applyForceTvLayout()); + settingStream.where((event) => event.key == SettingKeys.displayRefreshRateModeKey).listen((_) => applyDisplayRefreshRateMode()); + settingStream.where((event) => event.key == SettingKeys.maxBrightnessKey).listen((_) => applyMaxBrightness()); + settingStream.where((event) => event.key == SettingKeys.forceTvLayoutKey).listen((_) => applyForceTvLayout()); // navigation - settingStream.where((event) => event.key == Settings.keepScreenOnKey).listen((_) => applyKeepScreenOn()); + settingStream.where((event) => event.key == SettingKeys.keepScreenOnKey).listen((_) => applyKeepScreenOn()); // platform settings - settingStream.where((event) => event.key == Settings.platformAccelerometerRotationKey).listen((_) => applyIsRotationLocked()); + settingStream.where((event) => event.key == SettingKeys.platformAccelerometerRotationKey).listen((_) => applyIsRotationLocked()); applyDisplayRefreshRateMode(); applyMaxBrightness(); @@ -567,7 +565,7 @@ class _AvesAppState extends State with WidgetsBindingObserver { Future _setupErrorReporting() async { await reportService.init(); - settings.updateStream.where((event) => event.key == Settings.isErrorReportingAllowedKey).listen( + settings.updateStream.where((event) => event.key == SettingKeys.isErrorReportingAllowedKey).listen( (_) => reportService.setCollectionEnabled(settings.isErrorReportingAllowed), ); await reportService.setCollectionEnabled(settings.isErrorReportingAllowed); diff --git a/lib/widgets/collection/collection_page.dart b/lib/widgets/collection/collection_page.dart index 93bc20b49..844bc757f 100644 --- a/lib/widgets/collection/collection_page.dart +++ b/lib/widgets/collection/collection_page.dart @@ -27,6 +27,7 @@ import 'package:aves/widgets/common/providers/selection_provider.dart'; import 'package:aves/widgets/navigation/drawer/app_drawer.dart'; import 'package:aves/widgets/navigation/nav_bar/nav_bar.dart'; import 'package:aves/widgets/navigation/tv_rail.dart'; +import 'package:aves_model/aves_model.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -64,7 +65,7 @@ class _CollectionPageState extends State { filters: widget.filters, ); super.initState(); - _subscriptions.add(settings.updateStream.where((event) => event.key == Settings.enableBinKey).listen((_) { + _subscriptions.add(settings.updateStream.where((event) => event.key == SettingKeys.enableBinKey).listen((_) { if (!settings.enableBin) { _collection.removeFilter(TrashFilter.instance); } diff --git a/lib/widgets/common/grid/sections/fixed/scale_overlay.dart b/lib/widgets/common/grid/sections/fixed/scale_overlay.dart index 8d5200a97..2c60d998d 100644 --- a/lib/widgets/common/grid/sections/fixed/scale_overlay.dart +++ b/lib/widgets/common/grid/sections/fixed/scale_overlay.dart @@ -1,8 +1,8 @@ import 'package:aves/theme/durations.dart'; -import 'package:aves/utils/colors.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/providers/media_query_data_provider.dart'; import 'package:aves_model/aves_model.dart'; +import 'package:aves_utils/aves_utils.dart'; import 'package:flutter/material.dart'; class FixedExtentScaleOverlay extends StatelessWidget { diff --git a/lib/widgets/common/grid/sections/mosaic/scale_overlay.dart b/lib/widgets/common/grid/sections/mosaic/scale_overlay.dart index ea6298e42..dac60fbac 100644 --- a/lib/widgets/common/grid/sections/mosaic/scale_overlay.dart +++ b/lib/widgets/common/grid/sections/mosaic/scale_overlay.dart @@ -1,7 +1,7 @@ import 'package:aves/theme/durations.dart'; -import 'package:aves/utils/colors.dart'; import 'package:aves/widgets/common/grid/sections/mosaic/scale_grid.dart'; import 'package:aves/widgets/common/providers/media_query_data_provider.dart'; +import 'package:aves_utils/aves_utils.dart'; import 'package:flutter/material.dart'; typedef MosaicItemBuilder = Widget Function(int index, double targetExtent); diff --git a/lib/widgets/common/identity/aves_filter_chip.dart b/lib/widgets/common/identity/aves_filter_chip.dart index 1192c6322..b0e2cca66 100644 --- a/lib/widgets/common/identity/aves_filter_chip.dart +++ b/lib/widgets/common/identity/aves_filter_chip.dart @@ -165,7 +165,7 @@ class _AvesFilterChipState extends State { _tapped = false; _subscriptions.add(covers.packageChangeStream.listen(_onCoverColorChanged)); _subscriptions.add(covers.colorChangeStream.listen(_onCoverColorChanged)); - _subscriptions.add(settings.updateStream.where((event) => event.key == Settings.themeColorModeKey).listen((_) { + _subscriptions.add(settings.updateStream.where((event) => event.key == SettingKeys.themeColorModeKey).listen((_) { // delay so that contextual colors reflect the new settings WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) return; diff --git a/lib/widgets/common/tile_extent_controller.dart b/lib/widgets/common/tile_extent_controller.dart index 924ecbdf3..10ae6dc9d 100644 --- a/lib/widgets/common/tile_extent_controller.dart +++ b/lib/widgets/common/tile_extent_controller.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:math'; import 'package:aves/model/settings/settings.dart'; @@ -13,6 +14,7 @@ class TileExtentController { late double userPreferredExtent; Size _viewportSize = Size.zero; + final List _subscriptions = []; Size get viewportSize => _viewportSize; @@ -28,11 +30,13 @@ class TileExtentController { // initialize extent to 0, so that it will be dynamically sized on first launch extentNotifier = ValueNotifier(0); userPreferredExtent = settings.getTileExtent(settingsRouteKey); - settings.addListener(_onSettingsChanged); + _subscriptions.add(settings.updateTileExtentStream.listen((_) => _onSettingsChanged())); } void dispose() { - settings.removeListener(_onSettingsChanged); + _subscriptions + ..forEach((sub) => sub.cancel()) + ..clear(); } void _onSettingsChanged() { diff --git a/lib/widgets/viewer/video/conductor.dart b/lib/widgets/viewer/video/conductor.dart index dfe886e18..67100990d 100644 --- a/lib/widgets/viewer/video/conductor.dart +++ b/lib/widgets/viewer/video/conductor.dart @@ -6,9 +6,9 @@ import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves/widgets/viewer/video/db_playback_state_handler.dart'; -import 'package:aves/widgets/viewer/video/fijkplayer.dart'; import 'package:aves_model/aves_model.dart'; import 'package:aves_video/aves_video.dart'; +import 'package:aves_video_ijk/aves_video_ijk.dart'; import 'package:collection/collection.dart'; class VideoConductor { @@ -37,7 +37,11 @@ class VideoConductor { if (controller != null) { _controllers.remove(controller); } else { - controller = IjkPlayerAvesVideoController(entry, playbackStateHandler: playbackStateHandler); + controller = IjkPlayerAvesVideoController( + entry, + playbackStateHandler: playbackStateHandler, + settings: settings, + ); _subscriptions.add(controller.statusStream.listen((event) => _onControllerStatusChanged(entry, controller!, event))); } _controllers.insert(0, controller); diff --git a/plugins/aves_model/lib/aves_model.dart b/plugins/aves_model/lib/aves_model.dart index 30d67e558..bef278c0c 100644 --- a/plugins/aves_model/lib/aves_model.dart +++ b/plugins/aves_model/lib/aves_model.dart @@ -14,7 +14,11 @@ export 'src/editor/enums.dart'; export 'src/entry/base.dart'; export 'src/metadata/enums.dart'; export 'src/metadata/fields.dart'; +export 'src/settings/access.dart'; export 'src/settings/enums.dart'; +export 'src/settings/event.dart'; +export 'src/settings/keys.dart'; +export 'src/settings/store.dart'; export 'src/source/album.dart'; export 'src/source/enums.dart'; export 'src/source/vault.dart'; diff --git a/plugins/aves_model/lib/src/settings/access.dart b/plugins/aves_model/lib/src/settings/access.dart new file mode 100644 index 000000000..3dbf406c8 --- /dev/null +++ b/plugins/aves_model/lib/src/settings/access.dart @@ -0,0 +1,105 @@ +import 'package:aves_model/aves_model.dart'; +import 'package:collection/collection.dart'; + +mixin SettingsAccess { + bool get initialized; + + SettingsStore get store; + + Stream get updateStream; + + void notifyKeyChange(String key, dynamic oldValue, dynamic newValue); + + void notifyListeners(); + + void set(String key, dynamic newValue) { + var oldValue = store.get(key); + if (newValue == null) { + store.remove(key); + } else if (newValue is String) { + oldValue = getString(key); + store.setString(key, newValue); + } else if (newValue is List) { + oldValue = getStringList(key); + store.setStringList(key, newValue); + } else if (newValue is int) { + oldValue = getInt(key); + store.setInt(key, newValue); + } else if (newValue is double) { + oldValue = getDouble(key); + store.setDouble(key, newValue); + } else if (newValue is bool) { + oldValue = getBool(key); + store.setBool(key, newValue); + } + if (oldValue != newValue) { + notifyKeyChange(key, oldValue, newValue); + notifyListeners(); + } + } + + // getters + + bool? getBool(String key) { + try { + return store.getBool(key); + } catch (error) { + // ignore, could be obsolete value of different type + return null; + } + } + + int? getInt(String key) { + try { + return store.getInt(key); + } catch (error) { + // ignore, could be obsolete value of different type + return null; + } + } + + double? getDouble(String key) { + try { + return store.getDouble(key); + } catch (error) { + // ignore, could be obsolete value of different type + return null; + } + } + + String? getString(String key) { + try { + return store.getString(key); + } catch (error) { + // ignore, could be obsolete value of different type + return null; + } + } + + List? getStringList(String key) { + try { + return store.getStringList(key); + } catch (error) { + // ignore, could be obsolete value of different type + return null; + } + } + + T getEnumOrDefault(String key, T defaultValue, Iterable values) { + try { + final valueString = store.getString(key); + for (final v in values) { + if (v.toString() == valueString) { + return v; + } + } + } catch (error) { + // ignore, could be obsolete value of different type + } + return defaultValue; + } + + List getEnumListOrDefault(String key, List defaultValue, Iterable values) { + return store.getStringList(key)?.map((s) => values.firstWhereOrNull((v) => v.toString() == s)).whereNotNull().toList() ?? defaultValue; + } +} diff --git a/plugins/aves_model/lib/src/settings/event.dart b/plugins/aves_model/lib/src/settings/event.dart new file mode 100644 index 000000000..22b3bfa60 --- /dev/null +++ b/plugins/aves_model/lib/src/settings/event.dart @@ -0,0 +1,11 @@ +import 'package:meta/meta.dart'; + +@immutable +class SettingsChangedEvent { + final String key; + final dynamic oldValue; + final dynamic newValue; + + // old and new values as stored, e.g. `List` for collections + const SettingsChangedEvent(this.key, this.oldValue, this.newValue); +} diff --git a/plugins/aves_model/lib/src/settings/keys.dart b/plugins/aves_model/lib/src/settings/keys.dart new file mode 100644 index 000000000..82ac1f37e --- /dev/null +++ b/plugins/aves_model/lib/src/settings/keys.dart @@ -0,0 +1,185 @@ +class SettingKeys { + static bool isInternalKey(String key) => _internalKeys.contains(key) || key.startsWith(_widgetKeyPrefix); + + static const Set _internalKeys = { + hasAcceptedTermsKey, + catalogTimeZoneRawOffsetMillisKey, + searchHistoryKey, + platformAccelerometerRotationKey, + platformTransitionAnimationScaleKey, + topEntryIdsKey, + recentDestinationAlbumsKey, + recentTagsKey, + }; + + static const _widgetKeyPrefix = 'widget_'; + + // app + static const hasAcceptedTermsKey = 'has_accepted_terms'; + static const canUseAnalysisServiceKey = 'can_use_analysis_service'; + static const isInstalledAppAccessAllowedKey = 'is_installed_app_access_allowed'; + static const isErrorReportingAllowedKey = 'is_crashlytics_enabled'; + static const localeKey = 'locale'; + static const catalogTimeZoneRawOffsetMillisKey = 'catalog_time_zone_raw_offset_millis'; + static const tileExtentPrefixKey = 'tile_extent_'; + static const tileLayoutPrefixKey = 'tile_layout_'; + static const entryRenamingPatternKey = 'entry_renaming_pattern'; + static const topEntryIdsKey = 'top_entry_ids'; + static const recentDestinationAlbumsKey = 'recent_destination_albums'; + static const recentTagsKey = 'recent_tags'; + + // display + static const displayRefreshRateModeKey = 'display_refresh_rate_mode'; + static const themeBrightnessKey = 'theme_brightness'; + static const themeColorModeKey = 'theme_color_mode'; + static const enableDynamicColorKey = 'dynamic_color'; + static const enableBlurEffectKey = 'enable_overlay_blur_effect'; + static const maxBrightnessKey = 'max_brightness'; + static const forceTvLayoutKey = 'force_tv_layout'; + + // navigation + static const mustBackTwiceToExitKey = 'must_back_twice_to_exit'; + static const keepScreenOnKey = 'keep_screen_on'; + static const homePageKey = 'home_page'; + static const enableBottomNavigationBarKey = 'show_bottom_navigation_bar'; + static const confirmCreateVaultKey = 'confirm_create_vault'; + static const confirmDeleteForeverKey = 'confirm_delete_forever'; + static const confirmMoveToBinKey = 'confirm_move_to_bin'; + static const confirmMoveUndatedItemsKey = 'confirm_move_undated_items'; + static const confirmAfterMoveToBinKey = 'confirm_after_move_to_bin'; + static const setMetadataDateBeforeFileOpKey = 'set_metadata_date_before_file_op'; + static const drawerTypeBookmarksKey = 'drawer_type_bookmarks'; + static const drawerAlbumBookmarksKey = 'drawer_album_bookmarks'; + static const drawerPageBookmarksKey = 'drawer_page_bookmarks'; + + // collection + static const collectionBurstPatternsKey = 'collection_burst_patterns'; + static const collectionGroupFactorKey = 'collection_group_factor'; + static const collectionSortFactorKey = 'collection_sort_factor'; + static const collectionSortReverseKey = 'collection_sort_reverse'; + static const collectionBrowsingQuickActionsKey = 'collection_browsing_quick_actions'; + static const collectionSelectionQuickActionsKey = 'collection_selection_quick_actions'; + static const showThumbnailFavouriteKey = 'show_thumbnail_favourite'; + static const thumbnailLocationIconKey = 'thumbnail_location_icon'; + static const thumbnailTagIconKey = 'thumbnail_tag_icon'; + static const showThumbnailMotionPhotoKey = 'show_thumbnail_motion_photo'; + static const showThumbnailRatingKey = 'show_thumbnail_rating'; + static const showThumbnailRawKey = 'show_thumbnail_raw'; + static const showThumbnailVideoDurationKey = 'show_thumbnail_video_duration'; + + // filter grids + static const albumGroupFactorKey = 'album_group_factor'; + static const albumSortFactorKey = 'album_sort_factor'; + static const countrySortFactorKey = 'country_sort_factor'; + static const stateSortFactorKey = 'state_sort_factor'; + static const placeSortFactorKey = 'place_sort_factor'; + static const tagSortFactorKey = 'tag_sort_factor'; + static const albumSortReverseKey = 'album_sort_reverse'; + static const countrySortReverseKey = 'country_sort_reverse'; + static const stateSortReverseKey = 'state_sort_reverse'; + static const placeSortReverseKey = 'place_sort_reverse'; + static const tagSortReverseKey = 'tag_sort_reverse'; + static const pinnedFiltersKey = 'pinned_filters'; + static const hiddenFiltersKey = 'hidden_filters'; + static const showAlbumPickQueryKey = 'show_album_pick_query'; + + // viewer + static const viewerQuickActionsKey = 'viewer_quick_actions'; + static const showOverlayOnOpeningKey = 'show_overlay_on_opening'; + static const showOverlayMinimapKey = 'show_overlay_minimap'; + static const showOverlayInfoKey = 'show_overlay_info'; + static const showOverlayDescriptionKey = 'show_overlay_description'; + static const showOverlayRatingTagsKey = 'show_overlay_rating_tags'; + static const showOverlayShootingDetailsKey = 'show_overlay_shooting_details'; + static const showOverlayThumbnailPreviewKey = 'show_overlay_thumbnail_preview'; + static const viewerGestureSideTapNextKey = 'viewer_gesture_side_tap_next'; + static const viewerUseCutoutKey = 'viewer_use_cutout'; + static const enableMotionPhotoAutoPlayKey = 'motion_photo_auto_play'; + static const imageBackgroundKey = 'image_background'; + + // video + static const enableVideoHardwareAccelerationKey = 'video_hwaccel_mediacodec'; + static const videoBackgroundModeKey = 'video_background_mode'; + static const videoAutoPlayModeKey = 'video_auto_play_mode'; + static const videoLoopModeKey = 'video_loop'; + static const videoResumptionModeKey = 'video_resumption_mode'; + static const videoControlsKey = 'video_controls'; + static const videoGestureDoubleTapTogglePlayKey = 'video_gesture_double_tap_toggle_play'; + static const videoGestureSideDoubleTapSeekKey = 'video_gesture_side_double_tap_skip'; + static const videoGestureVerticalDragBrightnessVolumeKey = 'video_gesture_vertical_drag_brightness_volume'; + + // subtitles + static const subtitleFontSizeKey = 'subtitle_font_size'; + static const subtitleTextAlignmentKey = 'subtitle_text_alignment'; + static const subtitleTextPositionKey = 'subtitle_text_position'; + static const subtitleShowOutlineKey = 'subtitle_show_outline'; + static const subtitleTextColorKey = 'subtitle_text_color'; + static const subtitleBackgroundColorKey = 'subtitle_background_color'; + + // info + static const infoMapZoomKey = 'info_map_zoom'; + static const coordinateFormatKey = 'coordinates_format'; + static const unitSystemKey = 'unit_system'; + + // tag editor + + static const tagEditorCurrentFilterSectionExpandedKey = 'tag_editor_current_filter_section_expanded'; + static const tagEditorExpandedSectionKey = 'tag_editor_expanded_section'; + + // converter + + static const convertMimeTypeKey = 'convert_mime_type'; + static const convertQualityKey = 'convert_quality'; + static const convertWriteMetadataKey = 'convert_write_metadata'; + + // map + static const mapStyleKey = 'info_map_style'; + static const mapDefaultCenterKey = 'map_default_center'; + + // search + static const saveSearchHistoryKey = 'save_search_history'; + static const searchHistoryKey = 'search_history'; + + // bin + static const enableBinKey = 'enable_bin'; + + // accessibility + static const showPinchGestureAlternativesKey = 'show_pinch_gesture_alternatives'; + static const accessibilityAnimationsKey = 'accessibility_animations'; + static const timeToTakeActionKey = 'time_to_take_action'; + + // file picker + static const filePickerShowHiddenFilesKey = 'file_picker_show_hidden_files'; + + // screen saver + static const screenSaverFillScreenKey = 'screen_saver_fill_screen'; + static const screenSaverAnimatedZoomEffectKey = 'screen_saver_animated_zoom_effect'; + static const screenSaverTransitionKey = 'screen_saver_transition'; + static const screenSaverVideoPlaybackKey = 'screen_saver_video_playback'; + static const screenSaverIntervalKey = 'screen_saver_interval'; + static const screenSaverCollectionFiltersKey = 'screen_saver_collection_filters'; + + // slideshow + static const slideshowRepeatKey = 'slideshow_loop'; + static const slideshowShuffleKey = 'slideshow_shuffle'; + static const slideshowFillScreenKey = 'slideshow_fill_screen'; + static const slideshowAnimatedZoomEffectKey = 'slideshow_animated_zoom_effect'; + static const slideshowTransitionKey = 'slideshow_transition'; + static const slideshowVideoPlaybackKey = 'slideshow_video_playback'; + static const slideshowIntervalKey = 'slideshow_interval'; + + // widget + static const widgetOutlinePrefixKey = '${_widgetKeyPrefix}outline_'; + static const widgetShapePrefixKey = '${_widgetKeyPrefix}shape_'; + static const widgetCollectionFiltersPrefixKey = '${_widgetKeyPrefix}collection_filters_'; + static const widgetOpenPagePrefixKey = '${_widgetKeyPrefix}open_page_'; + static const widgetDisplayedItemPrefixKey = '${_widgetKeyPrefix}displayed_item_'; + static const widgetUriPrefixKey = '${_widgetKeyPrefix}uri_'; + + // platform settings + // cf Android `Settings.System.ACCELEROMETER_ROTATION` + static const platformAccelerometerRotationKey = 'accelerometer_rotation'; + + // cf Android `Settings.Global.TRANSITION_ANIMATION_SCALE` + static const platformTransitionAnimationScaleKey = 'transition_animation_scale'; +} \ No newline at end of file diff --git a/lib/model/settings/store/store.dart b/plugins/aves_model/lib/src/settings/store.dart similarity index 100% rename from lib/model/settings/store/store.dart rename to plugins/aves_model/lib/src/settings/store.dart diff --git a/plugins/aves_model/pubspec.lock b/plugins/aves_model/pubspec.lock index 39823942d..269a124e9 100644 --- a/plugins/aves_model/pubspec.lock +++ b/plugins/aves_model/pubspec.lock @@ -10,7 +10,7 @@ packages: source: hosted version: "1.3.0" collection: - dependency: transitive + dependency: "direct main" description: name: collection sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" diff --git a/plugins/aves_model/pubspec.yaml b/plugins/aves_model/pubspec.yaml index d24556f14..fe317bde2 100644 --- a/plugins/aves_model/pubspec.yaml +++ b/plugins/aves_model/pubspec.yaml @@ -8,6 +8,7 @@ environment: dependencies: flutter: sdk: flutter + collection: equatable: meta: diff --git a/plugins/aves_services_google/pubspec.lock b/plugins/aves_services_google/pubspec.lock index 9b19a7c43..aad8b46e8 100644 --- a/plugins/aves_services_google/pubspec.lock +++ b/plugins/aves_services_google/pubspec.lock @@ -188,10 +188,10 @@ packages: dependency: "direct main" description: name: google_maps_flutter - sha256: "7b417a64ee7a060f42cf44d8c274d3b562423f6fe57d2911b7b536857c0d8eb6" + sha256: "7e35644d8a88ad86409976db8fa23ddc7d933f8239e57405e4660534be09acd2" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" google_maps_flutter_android: dependency: "direct main" description: @@ -441,10 +441,10 @@ packages: dependency: transitive description: name: win32 - sha256: "7dacfda1edcca378031db9905ad7d7bd56b29fd1a90b0908b71a52a12c41e36b" + sha256: "1414f27dd781737e51afa9711f2ac2ace6ab4498ee98e20863fa5505aa00c58c" url: "https://pub.dev" source: hosted - version: "5.0.3" + version: "5.0.4" win32_registry: dependency: transitive description: diff --git a/plugins/aves_utils/lib/aves_utils.dart b/plugins/aves_utils/lib/aves_utils.dart index d41bcfd2b..c2f027c4e 100644 --- a/plugins/aves_utils/lib/aves_utils.dart +++ b/plugins/aves_utils/lib/aves_utils.dart @@ -1,5 +1,6 @@ library aves_utils; export 'src/change_notifier.dart'; +export 'src/colors.dart'; export 'src/optional_event_channel.dart'; export 'src/vector_utils.dart'; diff --git a/lib/utils/colors.dart b/plugins/aves_utils/lib/src/colors.dart similarity index 100% rename from lib/utils/colors.dart rename to plugins/aves_utils/lib/src/colors.dart diff --git a/plugins/aves_video/lib/aves_video.dart b/plugins/aves_video/lib/aves_video.dart index 6c308814d..8bafd4faa 100644 --- a/plugins/aves_video/lib/aves_video.dart +++ b/plugins/aves_video/lib/aves_video.dart @@ -1,4 +1,7 @@ library aves_video; export 'src/controller.dart'; +export 'src/settings/subtitles.dart'; +export 'src/settings/video.dart'; export 'src/stream.dart'; +export 'src/video_loop_mode.dart'; diff --git a/plugins/aves_video/lib/src/controller.dart b/plugins/aves_video/lib/src/controller.dart index 3d658ecb8..834fe228f 100644 --- a/plugins/aves_video/lib/src/controller.dart +++ b/plugins/aves_video/lib/src/controller.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:aves_model/aves_model.dart'; +import 'package:aves_video/src/settings/video.dart'; import 'package:aves_video/src/stream.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; @@ -8,12 +9,17 @@ import 'package:flutter/widgets.dart'; abstract class AvesVideoController { final AvesEntryBase _entry; final PlaybackStateHandler playbackStateHandler; + final VideoSettings settings; AvesEntryBase get entry => _entry; static const resumeTimeSaveMinDuration = Duration(minutes: 2); - AvesVideoController(AvesEntryBase entry, {required this.playbackStateHandler}) : _entry = entry { + AvesVideoController( + AvesEntryBase entry, { + required this.playbackStateHandler, + required this.settings, + }) : _entry = entry { entry.visualChangeNotifier.addListener(onVisualChanged); } diff --git a/plugins/aves_video/lib/src/settings/defaults.dart b/plugins/aves_video/lib/src/settings/defaults.dart new file mode 100644 index 000000000..fcdc9b0df --- /dev/null +++ b/plugins/aves_video/lib/src/settings/defaults.dart @@ -0,0 +1,26 @@ +import 'dart:ui'; + +import 'package:aves_model/aves_model.dart'; +import 'package:aves_utils/aves_utils.dart'; + +class SettingsDefaults { + // video + static const enableVideoHardwareAcceleration = true; + static const videoAutoPlayMode = VideoAutoPlayMode.disabled; + static const videoBackgroundMode = VideoBackgroundMode.disabled; + static const videoLoopMode = VideoLoopMode.shortOnly; + static const videoResumptionMode = VideoResumptionMode.ask; + static const videoShowRawTimedText = false; + static const videoControls = VideoControls.play; + static const videoGestureDoubleTapTogglePlay = false; + static const videoGestureSideDoubleTapSeek = true; + static const videoGestureVerticalDragBrightnessVolume = false; + + // subtitles + static const subtitleFontSize = 20.0; + static const subtitleTextAlignment = TextAlign.center; + static const subtitleTextPosition = SubtitlePosition.bottom; + static const subtitleShowOutline = true; + static const subtitleTextColor = Color(0xFFFFFFFF); + static const subtitleBackgroundColor = ColorUtils.transparentBlack; +} diff --git a/plugins/aves_video/lib/src/settings/subtitles.dart b/plugins/aves_video/lib/src/settings/subtitles.dart new file mode 100644 index 000000000..c001055c8 --- /dev/null +++ b/plugins/aves_video/lib/src/settings/subtitles.dart @@ -0,0 +1,30 @@ +import 'dart:ui'; + +import 'package:aves_model/aves_model.dart'; +import 'package:aves_video/src/settings/defaults.dart'; + +mixin SubtitlesSettings on SettingsAccess { + double get subtitleFontSize => getDouble(SettingKeys.subtitleFontSizeKey) ?? SettingsDefaults.subtitleFontSize; + + set subtitleFontSize(double newValue) => set(SettingKeys.subtitleFontSizeKey, newValue); + + TextAlign get subtitleTextAlignment => getEnumOrDefault(SettingKeys.subtitleTextAlignmentKey, SettingsDefaults.subtitleTextAlignment, TextAlign.values); + + set subtitleTextAlignment(TextAlign newValue) => set(SettingKeys.subtitleTextAlignmentKey, newValue.toString()); + + SubtitlePosition get subtitleTextPosition => getEnumOrDefault(SettingKeys.subtitleTextPositionKey, SettingsDefaults.subtitleTextPosition, SubtitlePosition.values); + + set subtitleTextPosition(SubtitlePosition newValue) => set(SettingKeys.subtitleTextPositionKey, newValue.toString()); + + bool get subtitleShowOutline => getBool(SettingKeys.subtitleShowOutlineKey) ?? SettingsDefaults.subtitleShowOutline; + + set subtitleShowOutline(bool newValue) => set(SettingKeys.subtitleShowOutlineKey, newValue); + + Color get subtitleTextColor => Color(getInt(SettingKeys.subtitleTextColorKey) ?? SettingsDefaults.subtitleTextColor.value); + + set subtitleTextColor(Color newValue) => set(SettingKeys.subtitleTextColorKey, newValue.value); + + Color get subtitleBackgroundColor => Color(getInt(SettingKeys.subtitleBackgroundColorKey) ?? SettingsDefaults.subtitleBackgroundColor.value); + + set subtitleBackgroundColor(Color newValue) => set(SettingKeys.subtitleBackgroundColorKey, newValue.value); +} diff --git a/plugins/aves_video/lib/src/settings/video.dart b/plugins/aves_video/lib/src/settings/video.dart new file mode 100644 index 000000000..11aa335ff --- /dev/null +++ b/plugins/aves_video/lib/src/settings/video.dart @@ -0,0 +1,40 @@ +import 'package:aves_model/aves_model.dart'; +import 'package:aves_video/src/settings/defaults.dart'; + +mixin VideoSettings on SettingsAccess { + bool get enableVideoHardwareAcceleration => getBool(SettingKeys.enableVideoHardwareAccelerationKey) ?? SettingsDefaults.enableVideoHardwareAcceleration; + + set enableVideoHardwareAcceleration(bool newValue) => set(SettingKeys.enableVideoHardwareAccelerationKey, newValue); + + VideoAutoPlayMode get videoAutoPlayMode => getEnumOrDefault(SettingKeys.videoAutoPlayModeKey, SettingsDefaults.videoAutoPlayMode, VideoAutoPlayMode.values); + + set videoAutoPlayMode(VideoAutoPlayMode newValue) => set(SettingKeys.videoAutoPlayModeKey, newValue.toString()); + + VideoBackgroundMode get videoBackgroundMode => getEnumOrDefault(SettingKeys.videoBackgroundModeKey, SettingsDefaults.videoBackgroundMode, VideoBackgroundMode.values); + + set videoBackgroundMode(VideoBackgroundMode newValue) => set(SettingKeys.videoBackgroundModeKey, newValue.toString()); + + VideoLoopMode get videoLoopMode => getEnumOrDefault(SettingKeys.videoLoopModeKey, SettingsDefaults.videoLoopMode, VideoLoopMode.values); + + set videoLoopMode(VideoLoopMode newValue) => set(SettingKeys.videoLoopModeKey, newValue.toString()); + + VideoResumptionMode get videoResumptionMode => getEnumOrDefault(SettingKeys.videoResumptionModeKey, SettingsDefaults.videoResumptionMode, VideoResumptionMode.values); + + set videoResumptionMode(VideoResumptionMode newValue) => set(SettingKeys.videoResumptionModeKey, newValue.toString()); + + VideoControls get videoControls => getEnumOrDefault(SettingKeys.videoControlsKey, SettingsDefaults.videoControls, VideoControls.values); + + set videoControls(VideoControls newValue) => set(SettingKeys.videoControlsKey, newValue.toString()); + + bool get videoGestureDoubleTapTogglePlay => getBool(SettingKeys.videoGestureDoubleTapTogglePlayKey) ?? SettingsDefaults.videoGestureDoubleTapTogglePlay; + + set videoGestureDoubleTapTogglePlay(bool newValue) => set(SettingKeys.videoGestureDoubleTapTogglePlayKey, newValue); + + bool get videoGestureSideDoubleTapSeek => getBool(SettingKeys.videoGestureSideDoubleTapSeekKey) ?? SettingsDefaults.videoGestureSideDoubleTapSeek; + + set videoGestureSideDoubleTapSeek(bool newValue) => set(SettingKeys.videoGestureSideDoubleTapSeekKey, newValue); + + bool get videoGestureVerticalDragBrightnessVolume => getBool(SettingKeys.videoGestureVerticalDragBrightnessVolumeKey) ?? SettingsDefaults.videoGestureVerticalDragBrightnessVolume; + + set videoGestureVerticalDragBrightnessVolume(bool newValue) => set(SettingKeys.videoGestureVerticalDragBrightnessVolumeKey, newValue); +} diff --git a/lib/model/settings/enums/video_loop_mode.dart b/plugins/aves_video/lib/src/video_loop_mode.dart similarity index 100% rename from lib/model/settings/enums/video_loop_mode.dart rename to plugins/aves_video/lib/src/video_loop_mode.dart diff --git a/plugins/aves_video/pubspec.lock b/plugins/aves_video/pubspec.lock index 091723a3d..57255f687 100644 --- a/plugins/aves_video/pubspec.lock +++ b/plugins/aves_video/pubspec.lock @@ -8,6 +8,13 @@ packages: relative: true source: path version: "0.0.1" + aves_utils: + dependency: "direct main" + description: + path: "../aves_utils" + relative: true + source: path + version: "0.0.1" characters: dependency: transitive description: diff --git a/plugins/aves_video/pubspec.yaml b/plugins/aves_video/pubspec.yaml index 7c477db6e..258cd6ded 100644 --- a/plugins/aves_video/pubspec.yaml +++ b/plugins/aves_video/pubspec.yaml @@ -10,6 +10,8 @@ dependencies: sdk: flutter aves_model: path: ../aves_model + aves_utils: + path: ../aves_utils dev_dependencies: flutter_lints: diff --git a/plugins/aves_video_ijk/.gitignore b/plugins/aves_video_ijk/.gitignore new file mode 100644 index 000000000..28124a571 --- /dev/null +++ b/plugins/aves_video_ijk/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +#/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/plugins/aves_video_ijk/.metadata b/plugins/aves_video_ijk/.metadata new file mode 100644 index 000000000..9596faeed --- /dev/null +++ b/plugins/aves_video_ijk/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 796c8ef79279f9c774545b3771238c3098dbefab + channel: stable + +project_type: package diff --git a/plugins/aves_video_ijk/analysis_options.yaml b/plugins/aves_video_ijk/analysis_options.yaml new file mode 100644 index 000000000..f04c6cf0f --- /dev/null +++ b/plugins/aves_video_ijk/analysis_options.yaml @@ -0,0 +1 @@ +include: ../../analysis_options.yaml diff --git a/plugins/aves_video_ijk/lib/aves_video_ijk.dart b/plugins/aves_video_ijk/lib/aves_video_ijk.dart new file mode 100644 index 000000000..2d580f1d1 --- /dev/null +++ b/plugins/aves_video_ijk/lib/aves_video_ijk.dart @@ -0,0 +1,3 @@ +library aves_video_ijk; + +export 'src/controller.dart'; diff --git a/lib/widgets/viewer/video/fijkplayer.dart b/plugins/aves_video_ijk/lib/src/controller.dart similarity index 98% rename from lib/widgets/viewer/video/fijkplayer.dart rename to plugins/aves_video_ijk/lib/src/controller.dart index 80d65934e..4afb2e0e1 100644 --- a/lib/widgets/viewer/video/fijkplayer.dart +++ b/plugins/aves_video_ijk/lib/src/controller.dart @@ -1,7 +1,5 @@ import 'dart:async'; -import 'package:aves/model/settings/enums/video_loop_mode.dart'; -import 'package:aves/model/settings/settings.dart'; import 'package:aves_model/aves_model.dart'; import 'package:aves_utils/aves_utils.dart'; import 'package:aves_video/aves_video.dart'; @@ -11,6 +9,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class IjkPlayerAvesVideoController extends AvesVideoController { + static bool _initializedFijkLog = false; + final EventChannel _eventChannel = const OptionalEventChannel('befovy.com/fijk/event'); late FijkPlayer _instance; @@ -61,7 +61,12 @@ class IjkPlayerAvesVideoController extends AvesVideoController { IjkPlayerAvesVideoController( super.entry, { required super.playbackStateHandler, + required super.settings, }) { + if (!_initializedFijkLog) { + _initializedFijkLog = true; + FijkLog.setLevel(FijkLogLevel.Warn); + } _instance = FijkPlayer(); _valueStream.map((value) => value.videoRenderStart).firstWhere((v) => v, orElse: () => false).then( (started) { @@ -96,8 +101,8 @@ class IjkPlayerAvesVideoController extends AvesVideoController { _subscriptions.add(_instance.onTimedText.listen(_timedTextStreamController.add)); _subscriptions.add(settings.updateStream .where((event) => { - Settings.enableVideoHardwareAccelerationKey, - Settings.videoLoopModeKey, + SettingKeys.enableVideoHardwareAccelerationKey, + SettingKeys.videoLoopModeKey, }.contains(event.key)) .listen((_) => _instance.reset())); } diff --git a/plugins/aves_video_ijk/pubspec.lock b/plugins/aves_video_ijk/pubspec.lock new file mode 100644 index 000000000..360c9ce06 --- /dev/null +++ b/plugins/aves_video_ijk/pubspec.lock @@ -0,0 +1,117 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + aves_model: + dependency: "direct main" + description: + path: "../aves_model" + relative: true + source: path + version: "0.0.1" + aves_utils: + dependency: "direct main" + description: + path: "../aves_utils" + relative: true + source: path + version: "0.0.1" + aves_video: + dependency: "direct main" + description: + path: "../aves_video" + relative: true + source: path + version: "0.0.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + collection: + dependency: "direct main" + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + equatable: + dependency: transitive + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + fijkplayer: + dependency: "direct main" + description: + path: "." + ref: aves + resolved-ref: "935a2d86ebf45fbdbaf8b4a0921d5eaea87410d6" + url: "https://github.com/deckerst/fijkplayer.git" + source: git + version: "0.10.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" + source: hosted + version: "2.0.1" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + lints: + dependency: transitive + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" +sdks: + dart: ">=3.0.0 <4.0.0" diff --git a/plugins/aves_video_ijk/pubspec.yaml b/plugins/aves_video_ijk/pubspec.yaml new file mode 100644 index 000000000..e1cdc9f77 --- /dev/null +++ b/plugins/aves_video_ijk/pubspec.yaml @@ -0,0 +1,26 @@ +name: aves_video_ijk +version: 0.0.1 +publish_to: none + +environment: + sdk: ">=3.0.0 <4.0.0" + +dependencies: + flutter: + sdk: flutter + aves_model: + path: ../aves_model + aves_video: + path: ../aves_video + aves_utils: + path: ../aves_utils + collection: + fijkplayer: + git: + url: https://github.com/deckerst/fijkplayer.git + ref: aves + +dev_dependencies: + flutter_lints: + +flutter: diff --git a/pubspec.lock b/pubspec.lock index f8f256d5a..874bda926 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -126,6 +126,13 @@ packages: relative: true source: path version: "0.0.1" + aves_video_ijk: + dependency: "direct main" + description: + path: "plugins/aves_video_ijk" + relative: true + source: path + version: "0.0.1" barcode: dependency: transitive description: @@ -590,10 +597,10 @@ packages: dependency: transitive description: name: google_maps_flutter - sha256: "7b417a64ee7a060f42cf44d8c274d3b562423f6fe57d2911b7b536857c0d8eb6" + sha256: "7e35644d8a88ad86409976db8fa23ddc7d933f8239e57405e4660534be09acd2" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" google_maps_flutter_android: dependency: transitive description: @@ -1454,10 +1461,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: eed4e6a1164aa9794409325c3b707ff424d4d1c2a785e7db67f8bbda00e36e51 + sha256: "15f5acbf0dce90146a0f5a2c4a002b1814a6303c4c5c075aa2623b2d16156f03" url: "https://pub.dev" source: hosted - version: "6.0.35" + version: "6.0.36" url_launcher_ios: dependency: transitive description: @@ -1486,10 +1493,10 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" url_launcher_web: dependency: transitive description: @@ -1566,10 +1573,10 @@ packages: dependency: transitive description: name: win32 - sha256: "7dacfda1edcca378031db9905ad7d7bd56b29fd1a90b0908b71a52a12c41e36b" + sha256: "1414f27dd781737e51afa9711f2ac2ace6ab4498ee98e20863fa5505aa00c58c" url: "https://pub.dev" source: hosted - version: "5.0.3" + version: "5.0.4" win32_registry: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 07f1d1dba..f7f048526 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,6 +40,8 @@ dependencies: path: plugins/aves_services_google aves_video: path: plugins/aves_video + aves_video_ijk: + path: plugins/aves_video_ijk aves_ui: path: plugins/aves_ui aves_utils: