// ignore_for_file: deprecated_member_use_from_same_package import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:nc_photos/account.dart'; import 'package:nc_photos/entity/collection/util.dart'; import 'package:nc_photos/entity/pref.dart'; import 'package:nc_photos/json_util.dart'; import 'package:nc_photos/k.dart' as k; import 'package:nc_photos/language_util.dart'; import 'package:nc_photos/protected_page_handler.dart'; import 'package:nc_photos/size.dart'; import 'package:np_codegen/np_codegen.dart'; import 'package:np_common/object_util.dart'; import 'package:np_gps_map/np_gps_map.dart'; import 'package:np_string/np_string.dart'; import 'package:rxdart/rxdart.dart'; part 'pref_controller.g.dart'; part 'pref_controller/type.dart'; part 'pref_controller/util.dart'; @npSubjectAccessor class PrefController { PrefController(this.pref); Future setAccounts(List value) => _set>( controller: _accountsController, setter: (pref, value) => pref.setAccounts3(value), value: value, ); Future setCurrentAccountIndex(int? value) => _setOrRemove( controller: _currentAccountIndexController, setter: (pref, value) => pref.setCurrentAccountIndex(value), remover: (pref) => pref.setCurrentAccountIndex(null), value: value, ); Future setAppLanguage(AppLanguage value) => _set( controller: _languageController, setter: (pref, value) => pref.setLanguage(value.langId), value: value, ); Future setHomePhotosZoomLevel(int value) => _set( controller: _homePhotosZoomLevelController, setter: (pref, value) => pref.setHomePhotosZoomLevel(value), value: value, ); Future setAlbumBrowserZoomLevel(int value) => _set( controller: _albumBrowserZoomLevelController, setter: (pref, value) => pref.setAlbumBrowserZoomLevel(value), value: value, ); Future setHomeAlbumsSort(CollectionSort value) => _set( controller: _homeAlbumsSortController, setter: (pref, value) => pref.setHomeAlbumsSort(value.index), value: value, ); Future setEnableExif(bool value) => _set( controller: _isEnableExifController, setter: (pref, value) => pref.setEnableExif(value), value: value, ); Future setProcessExifWifiOnly(bool value) => _set( controller: _shouldProcessExifWifiOnlyController, setter: (pref, value) => pref.setProcessExifWifiOnly(value), value: value, ); Future setMemoriesRange(int value) => _set( controller: _memoriesRangeController, setter: (pref, value) => pref.setMemoriesRange(value), value: value, ); Future setViewerScreenBrightness(int value) => _set( controller: _viewerScreenBrightnessController, setter: (pref, value) => pref.setViewerScreenBrightness(value), value: value, ); Future setViewerForceRotation(bool value) => _set( controller: _isViewerForceRotationController, setter: (pref, value) => pref.setViewerForceRotation(value), value: value, ); Future setGpsMapProvider(GpsMapProvider value) => _set( controller: _gpsMapProviderController, setter: (pref, value) => pref.setGpsMapProvider(value.index), value: value, ); Future setAlbumBrowserShowDate(bool value) => _set( controller: _isAlbumBrowserShowDateController, setter: (pref, value) => pref.setAlbumBrowserShowDate(value), value: value, ); Future setDoubleTapExit(bool value) => _set( controller: _isDoubleTapExitController, setter: (pref, value) => pref.setDoubleTapExit(value), value: value, ); Future setSaveEditResultToServer(bool value) => _set( controller: _isSaveEditResultToServerController, setter: (pref, value) => pref.setSaveEditResultToServer(value), value: value, ); Future setEnhanceMaxSize(SizeInt value) => _set( controller: _enhanceMaxSizeController, setter: (pref, value) async { return (await Future.wait([ pref.setEnhanceMaxWidth(value.width), pref.setEnhanceMaxHeight(value.height), ])) .reduce((a, b) => a && b); }, value: value, ); Future setDarkTheme(bool value) => _set( controller: _isDarkThemeController, setter: (pref, value) => pref.setDarkTheme(value), value: value, ); Future setFollowSystemTheme(bool value) => _set( controller: _isFollowSystemThemeController, setter: (pref, value) => pref.setFollowSystemTheme(value), value: value, ); Future setUseBlackInDarkTheme(bool value) => _set( controller: _isUseBlackInDarkThemeController, setter: (pref, value) => pref.setUseBlackInDarkTheme(value), value: value, ); Future setSeedColor(Color? value) => _setOrRemove( controller: _seedColorController, setter: (pref, value) => pref.setSeedColor(value.withAlpha(0xFF).value), remover: (pref) => pref.setSeedColor(null), value: value, ); Future setSecondarySeedColor(Color? value) => _setOrRemove( controller: _secondarySeedColorController, setter: (pref, value) => pref.setSecondarySeedColor(value.withAlpha(0xFF).value), remover: (pref) => pref.setSecondarySeedColor(null), value: value, ); Future setDontShowVideoPreviewHint(bool value) => _set( controller: _isDontShowVideoPreviewHintController, setter: (pref, value) => pref.setDontShowVideoPreviewHint(value), value: value, ); Future setMapBrowserPrevPosition(MapCoord? value) => _setOrRemove( controller: _mapBrowserPrevPositionController, setter: (pref, value) => pref.setMapBrowserPrevPosition( jsonEncode([value.latitude, value.longitude])), remover: (pref) => pref.setMapBrowserPrevPosition(null), value: value, ); Future setNewHttpEngine(bool value) => _set( controller: _isNewHttpEngineController, setter: (pref, value) => pref.setNewHttpEngine(value), value: value, ); Future setFirstRunTime(DateTime? value) => _setOrRemove( controller: _firstRunTimeController, setter: (pref, value) => pref.setFirstRunTime(value.millisecondsSinceEpoch), remover: (pref) => pref.setFirstRunTime(null), value: value, ); Future setLastVersion(int value) => _set( controller: _lastVersionController, setter: (pref, value) => pref.setLastVersion(value), value: value, ); Future setMapDefaultRangeType(PrefMapDefaultRangeType value) => _set( controller: _mapDefaultRangeTypeController, setter: (pref, value) => pref.setMapDefaultRangeType(value), value: value, ); Future setMapDefaultCustomRange(Duration value) => _set( controller: _mapDefaultCustomRangeController, setter: (pref, value) => pref.setMapDefaultCustomRange(value), value: value, ); Future _set({ required BehaviorSubject controller, required Future Function(Pref pref, T value) setter, required T value, }) => _doSet( pref: pref, controller: controller, setter: setter, value: value, ); Future _setOrRemove({ required BehaviorSubject controller, required Future Function(Pref pref, T value) setter, required Future Function(Pref pref) remover, required T? value, T? defaultValue, }) => _doSetOrRemove( pref: pref, controller: controller, setter: setter, remover: remover, value: value, defaultValue: defaultValue, ); static AppLanguage _langIdToAppLanguage(int langId) { try { return supportedLanguages[langId]!; } catch (_) { return supportedLanguages[0]!; } } final Pref pref; @npSubjectAccessor late final _accountsController = BehaviorSubject.seeded(pref.getAccounts3() ?? []); @npSubjectAccessor late final _currentAccountIndexController = BehaviorSubject.seeded(pref.getCurrentAccountIndex()); @npSubjectAccessor late final _languageController = BehaviorSubject.seeded(_langIdToAppLanguage(pref.getLanguageOr(0))); @npSubjectAccessor late final _homePhotosZoomLevelController = BehaviorSubject.seeded(pref.getHomePhotosZoomLevelOr(0)); @npSubjectAccessor late final _albumBrowserZoomLevelController = BehaviorSubject.seeded(pref.getAlbumBrowserZoomLevelOr(0)); @npSubjectAccessor late final _homeAlbumsSortController = BehaviorSubject.seeded( CollectionSort.values[pref.getHomeAlbumsSortOr(0)]); @npSubjectAccessor late final _isEnableExifController = BehaviorSubject.seeded(pref.isEnableExifOr(true)); @npSubjectAccessor late final _shouldProcessExifWifiOnlyController = BehaviorSubject.seeded(pref.shouldProcessExifWifiOnlyOr(true)); @npSubjectAccessor late final _memoriesRangeController = BehaviorSubject.seeded(pref.getMemoriesRangeOr(2)); @npSubjectAccessor late final _viewerScreenBrightnessController = BehaviorSubject.seeded(pref.getViewerScreenBrightnessOr(-1)); @npSubjectAccessor late final _isViewerForceRotationController = BehaviorSubject.seeded(pref.isViewerForceRotationOr(false)); @npSubjectAccessor late final _gpsMapProviderController = BehaviorSubject.seeded( GpsMapProvider.values[pref.getGpsMapProviderOr(0)]); @npSubjectAccessor late final _isAlbumBrowserShowDateController = BehaviorSubject.seeded(pref.isAlbumBrowserShowDateOr(false)); @npSubjectAccessor late final _isDoubleTapExitController = BehaviorSubject.seeded(pref.isDoubleTapExitOr(false)); @npSubjectAccessor late final _isSaveEditResultToServerController = BehaviorSubject.seeded(pref.isSaveEditResultToServerOr(true)); @npSubjectAccessor late final _enhanceMaxSizeController = BehaviorSubject.seeded( SizeInt(pref.getEnhanceMaxWidthOr(), pref.getEnhanceMaxHeightOr())); @npSubjectAccessor late final _isDarkThemeController = BehaviorSubject.seeded(pref.isDarkThemeOr(false)); @npSubjectAccessor late final _isFollowSystemThemeController = BehaviorSubject.seeded(pref.isFollowSystemThemeOr(false)); @npSubjectAccessor late final _isUseBlackInDarkThemeController = BehaviorSubject.seeded(pref.isUseBlackInDarkThemeOr(false)); @NpSubjectAccessor(type: "Color?") late final _seedColorController = BehaviorSubject.seeded(pref.getSeedColor()?.let(Color.new)); @NpSubjectAccessor(type: "Color?") late final _secondarySeedColorController = BehaviorSubject.seeded( pref.getSecondarySeedColor()?.let(Color.new)); @npSubjectAccessor late final _isDontShowVideoPreviewHintController = BehaviorSubject.seeded(pref.isDontShowVideoPreviewHintOr(false)); @npSubjectAccessor late final _mapBrowserPrevPositionController = BehaviorSubject.seeded(pref .getMapBrowserPrevPosition() ?.let(tryJsonDecode) ?.let(_tryMapCoordFromJson)); @npSubjectAccessor late final _isNewHttpEngineController = BehaviorSubject.seeded(pref.isNewHttpEngine() ?? false); @npSubjectAccessor late final _firstRunTimeController = BehaviorSubject.seeded(pref .getFirstRunTime() ?.let((v) => DateTime.fromMillisecondsSinceEpoch(v).toUtc())); @npSubjectAccessor late final _lastVersionController = BehaviorSubject.seeded(pref.getLastVersion() ?? // v6 is the last version without saving the version number in pref (pref.getSetupProgress() == null ? k.version : 6)); @npSubjectAccessor late final _mapDefaultRangeTypeController = BehaviorSubject.seeded( pref.getMapDefaultRangeType() ?? PrefMapDefaultRangeType.thisMonth); @npSubjectAccessor late final _mapDefaultCustomRangeController = BehaviorSubject.seeded( pref.getMapDefaultCustomRange() ?? const Duration(days: 30)); } extension PrefControllerExtension on PrefController { Account? get currentAccountValue { try { return accountsValue[currentAccountIndexValue!]; } catch (_) { return null; } } } @npSubjectAccessor class SecurePrefController { SecurePrefController(this.securePref); Future setProtectedPageAuthType(ProtectedPageAuthType? value) => _setOrRemove( controller: _protectedPageAuthTypeController, setter: (pref, value) => pref.setProtectedPageAuthType(value.index), remover: (pref) => pref.setProtectedPageAuthType(null), value: value, ); Future setProtectedPageAuthPin(CiString? value) => _setOrRemove( controller: _protectedPageAuthPinController, setter: (pref, value) => pref.setProtectedPageAuthPin(value.toCaseInsensitiveString()), remover: (pref) => pref.setProtectedPageAuthPin(null), value: value, ); Future setProtectedPageAuthPassword(CiString? value) => _setOrRemove( controller: _protectedPageAuthPasswordController, setter: (pref, value) => pref.setProtectedPageAuthPassword(value.toCaseInsensitiveString()), remover: (pref) => pref.setProtectedPageAuthPassword(null), value: value, ); // ignore: unused_element Future _set({ required BehaviorSubject controller, required Future Function(Pref pref, T value) setter, required T value, }) => _doSet( pref: securePref, controller: controller, setter: setter, value: value, ); // ignore: unused_element Future _setOrRemove({ required BehaviorSubject controller, required Future Function(Pref pref, T value) setter, required Future Function(Pref pref) remover, required T? value, T? defaultValue, }) => _doSetOrRemove( pref: securePref, controller: controller, setter: setter, remover: remover, value: value, defaultValue: defaultValue, ); final Pref securePref; @npSubjectAccessor late final _protectedPageAuthTypeController = BehaviorSubject.seeded( securePref .getProtectedPageAuthType() ?.let((e) => ProtectedPageAuthType.values[e])); @npSubjectAccessor late final _protectedPageAuthPinController = BehaviorSubject.seeded(securePref.getProtectedPageAuthPin()?.toCi()); @npSubjectAccessor late final _protectedPageAuthPasswordController = BehaviorSubject.seeded(securePref.getProtectedPageAuthPassword()?.toCi()); } Future _doSet({ required Pref pref, required BehaviorSubject controller, required Future Function(Pref pref, T value) setter, required T value, }) async { final backup = controller.value; controller.add(value); try { if (!await setter(pref, value)) { throw StateError("Unknown error"); } return true; } catch (e, stackTrace) { _$__NpLog.log.severe("[_doSet] Failed setting preference", e, stackTrace); controller ..addError(e, stackTrace) ..add(backup); return false; } } Future _doSetOrRemove({ required Pref pref, required BehaviorSubject controller, required Future Function(Pref pref, T value) setter, required Future Function(Pref pref) remover, required T? value, T? defaultValue, }) async { final backup = controller.value; controller.add(value ?? defaultValue); try { if (value == null) { if (!await remover(pref)) { throw StateError("Unknown error"); } } else { if (!await setter(pref, value)) { throw StateError("Unknown error"); } } return true; } catch (e, stackTrace) { _$__NpLog.log .severe("[_doSetOrRemove] Failed setting preference", e, stackTrace); controller ..addError(e, stackTrace) ..add(backup); return false; } } @npLog // ignore: camel_case_types class __ {}