From c03922a1ce16374dba46c53c8a30d75d1198f4fd Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Thu, 21 Oct 2021 15:52:26 +0300 Subject: [PATCH] Persist UI option --- lib/redux/app/app_actions.dart | 2 + lib/redux/ui/pref_state.dart | 4 + lib/redux/ui/pref_state.g.dart | 51 ++++-- lib/ui/settings/device_settings.dart | 9 ++ lib/ui/settings/device_settings_vm.dart | 199 ++++++++++++------------ lib/utils/i18n.dart | 13 +- 6 files changed, 163 insertions(+), 115 deletions(-) diff --git a/lib/redux/app/app_actions.dart b/lib/redux/app/app_actions.dart index 04ad2d710..47ad6dc24 100644 --- a/lib/redux/app/app_actions.dart +++ b/lib/redux/app/app_actions.dart @@ -134,6 +134,7 @@ class UpdateUserPreferences implements PersistPrefs { this.colorTheme, this.customColors, this.persistData, + this.persistUi, }); final AppLayout appLayout; @@ -151,6 +152,7 @@ class UpdateUserPreferences implements PersistPrefs { final int rowsPerPage; final String colorTheme; final bool persistData; + final bool persistUi; final BuiltMap customColors; } diff --git a/lib/redux/ui/pref_state.dart b/lib/redux/ui/pref_state.dart index e4137cd33..9da49d3da 100644 --- a/lib/redux/ui/pref_state.dart +++ b/lib/redux/ui/pref_state.dart @@ -27,6 +27,7 @@ abstract class PrefState implements Built { longPressSelectionIsDefault: true, showKanban: false, persistData: false, + persistUI: true, companyPrefs: BuiltMap(), sortFields: BuiltMap(), customColors: BuiltMap(CONTRAST_COLORS), @@ -98,6 +99,8 @@ abstract class PrefState implements Built { bool get persistData; + bool get persistUI; + bool get longPressSelectionIsDefault; bool get requireAuthentication; @@ -175,6 +178,7 @@ abstract class PrefState implements Built { ..isPreviewVisible = false ..isFilterVisible = false ..persistData = false + ..persistUI = true ..colorTheme = builder.enableDarkMode == true ? kColorThemeLight : kColorThemeLight; diff --git a/lib/redux/ui/pref_state.g.dart b/lib/redux/ui/pref_state.g.dart index 887ebde59..972b05154 100644 --- a/lib/redux/ui/pref_state.g.dart +++ b/lib/redux/ui/pref_state.g.dart @@ -154,6 +154,9 @@ class _$PrefStateSerializer implements StructuredSerializer { 'persistData', serializers.serialize(object.persistData, specifiedType: const FullType(bool)), + 'persistUI', + serializers.serialize(object.persistUI, + specifiedType: const FullType(bool)), 'longPressSelectionIsDefault', serializers.serialize(object.longPressSelectionIsDefault, specifiedType: const FullType(bool)), @@ -248,6 +251,10 @@ class _$PrefStateSerializer implements StructuredSerializer { result.persistData = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool; break; + case 'persistUI': + result.persistUI = serializers.deserialize(value, + specifiedType: const FullType(bool)) as bool; + break; case 'longPressSelectionIsDefault': result.longPressSelectionIsDefault = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool; @@ -535,6 +542,8 @@ class _$PrefState extends PrefState { @override final bool persistData; @override + final bool persistUI; + @override final bool longPressSelectionIsDefault; @override final bool requireAuthentication; @@ -564,6 +573,7 @@ class _$PrefState extends PrefState { this.enableDarkMode, this.isFilterVisible, this.persistData, + this.persistUI, this.longPressSelectionIsDefault, this.requireAuthentication, this.rowsPerPage, @@ -596,6 +606,7 @@ class _$PrefState extends PrefState { isFilterVisible, 'PrefState', 'isFilterVisible'); BuiltValueNullFieldError.checkNotNull( persistData, 'PrefState', 'persistData'); + BuiltValueNullFieldError.checkNotNull(persistUI, 'PrefState', 'persistUI'); BuiltValueNullFieldError.checkNotNull(longPressSelectionIsDefault, 'PrefState', 'longPressSelectionIsDefault'); BuiltValueNullFieldError.checkNotNull( @@ -634,6 +645,7 @@ class _$PrefState extends PrefState { enableDarkMode == other.enableDarkMode && isFilterVisible == other.isFilterVisible && persistData == other.persistData && + persistUI == other.persistUI && longPressSelectionIsDefault == other.longPressSelectionIsDefault && requireAuthentication == other.requireAuthentication && rowsPerPage == other.rowsPerPage && @@ -664,27 +676,29 @@ class _$PrefState extends PrefState { $jc( $jc( $jc( - 0, - appLayout + $jc( + 0, + appLayout + .hashCode), + moduleLayout .hashCode), - moduleLayout + menuSidebarMode .hashCode), - menuSidebarMode + historySidebarMode .hashCode), - historySidebarMode + useSidebarEditor .hashCode), - useSidebarEditor + customColors .hashCode), - customColors + isPreviewVisible .hashCode), - isPreviewVisible - .hashCode), - isMenuVisible.hashCode), - showKanban.hashCode), - isHistoryVisible.hashCode), - enableDarkMode.hashCode), - isFilterVisible.hashCode), - persistData.hashCode), + isMenuVisible.hashCode), + showKanban.hashCode), + isHistoryVisible.hashCode), + enableDarkMode.hashCode), + isFilterVisible.hashCode), + persistData.hashCode), + persistUI.hashCode), longPressSelectionIsDefault.hashCode), requireAuthentication.hashCode), rowsPerPage.hashCode), @@ -709,6 +723,7 @@ class _$PrefState extends PrefState { ..add('enableDarkMode', enableDarkMode) ..add('isFilterVisible', isFilterVisible) ..add('persistData', persistData) + ..add('persistUI', persistUI) ..add('longPressSelectionIsDefault', longPressSelectionIsDefault) ..add('requireAuthentication', requireAuthentication) ..add('rowsPerPage', rowsPerPage) @@ -786,6 +801,10 @@ class PrefStateBuilder implements Builder { bool get persistData => _$this._persistData; set persistData(bool persistData) => _$this._persistData = persistData; + bool _persistUI; + bool get persistUI => _$this._persistUI; + set persistUI(bool persistUI) => _$this._persistUI = persistUI; + bool _longPressSelectionIsDefault; bool get longPressSelectionIsDefault => _$this._longPressSelectionIsDefault; set longPressSelectionIsDefault(bool longPressSelectionIsDefault) => @@ -836,6 +855,7 @@ class PrefStateBuilder implements Builder { _enableDarkMode = $v.enableDarkMode; _isFilterVisible = $v.isFilterVisible; _persistData = $v.persistData; + _persistUI = $v.persistUI; _longPressSelectionIsDefault = $v.longPressSelectionIsDefault; _requireAuthentication = $v.requireAuthentication; _rowsPerPage = $v.rowsPerPage; @@ -885,6 +905,7 @@ class PrefStateBuilder implements Builder { enableDarkMode: BuiltValueNullFieldError.checkNotNull(enableDarkMode, 'PrefState', 'enableDarkMode'), isFilterVisible: BuiltValueNullFieldError.checkNotNull(isFilterVisible, 'PrefState', 'isFilterVisible'), persistData: BuiltValueNullFieldError.checkNotNull(persistData, 'PrefState', 'persistData'), + persistUI: BuiltValueNullFieldError.checkNotNull(persistUI, 'PrefState', 'persistUI'), longPressSelectionIsDefault: BuiltValueNullFieldError.checkNotNull(longPressSelectionIsDefault, 'PrefState', 'longPressSelectionIsDefault'), requireAuthentication: BuiltValueNullFieldError.checkNotNull(requireAuthentication, 'PrefState', 'requireAuthentication'), rowsPerPage: BuiltValueNullFieldError.checkNotNull(rowsPerPage, 'PrefState', 'rowsPerPage'), diff --git a/lib/ui/settings/device_settings.dart b/lib/ui/settings/device_settings.dart index 7cf608b75..d7c4797ac 100644 --- a/lib/ui/settings/device_settings.dart +++ b/lib/ui/settings/device_settings.dart @@ -196,6 +196,15 @@ class _DeviceSettingsState extends State } }, ), + SwitchListTile( + title: Text(localization.persistUi), + subtitle: Text(localization.persistUiHelp), + value: prefState.persistUI, + onChanged: (value) => + viewModel.onPersistUiChanged(context, value), + activeColor: Theme.of(context).accentColor, + secondary: Icon(Icons.save_alt), + ), SwitchListTile( title: Text(localization.persistData), subtitle: Text(localization.persistDataHelp), diff --git a/lib/ui/settings/device_settings_vm.dart b/lib/ui/settings/device_settings_vm.dart index f545f45c8..e7a6950b5 100644 --- a/lib/ui/settings/device_settings_vm.dart +++ b/lib/ui/settings/device_settings_vm.dart @@ -49,110 +49,116 @@ class DeviceSettingsVM { @required this.onRowsPerPageChanged, @required this.onCustomColorsChanged, @required this.onPersistDataChanged, + @required this.onPersistUiChanged, }); static DeviceSettingsVM fromStore(Store store) { return DeviceSettingsVM( - state: store.state, - onRefreshTap: (BuildContext context) => - showRefreshDataDialog(context: context, includeStatic: true), - onLogoutTap: (BuildContext context) { - final completer = snackBarCompleter( - context, AppLocalization.of(context).endedAllSessions); - store.dispatch(UserLogoutAll(completer: completer)); - }, - onDarkModeChanged: (BuildContext context, bool value) async { - store.dispatch(UpdateUserPreferences( - enableDarkMode: value, - colorTheme: value ? kColorThemeDark : kColorThemeLight, - customColors: value - ? BuiltMap() - : BuiltMap(PrefState.CONTRAST_COLORS))); - store.dispatch(UpdatedSetting()); - AppBuilder.of(context).rebuild(); - }, - onLongPressSelectionIsDefault: - (BuildContext context, bool value) async { - store.dispatch( - UpdateUserPreferences(longPressSelectionIsDefault: value)); - }, - onMenuModeChanged: (context, value) async { - if (store.state.prefState.menuSidebarMode == value) { - return; - } + state: store.state, + onRefreshTap: (BuildContext context) => + showRefreshDataDialog(context: context, includeStatic: true), + onLogoutTap: (BuildContext context) { + final completer = snackBarCompleter( + context, AppLocalization.of(context).endedAllSessions); + store.dispatch(UserLogoutAll(completer: completer)); + }, + onDarkModeChanged: (BuildContext context, bool value) async { + store.dispatch(UpdateUserPreferences( + enableDarkMode: value, + colorTheme: value ? kColorThemeDark : kColorThemeLight, + customColors: value + ? BuiltMap() + : BuiltMap(PrefState.CONTRAST_COLORS))); + store.dispatch(UpdatedSetting()); + AppBuilder.of(context).rebuild(); + }, + onLongPressSelectionIsDefault: (BuildContext context, bool value) async { + store.dispatch( + UpdateUserPreferences(longPressSelectionIsDefault: value)); + }, + onMenuModeChanged: (context, value) async { + if (store.state.prefState.menuSidebarMode == value) { + return; + } - store.dispatch(UpdateUserPreferences(menuMode: value)); - }, - onHistoryModeChanged: (context, value) async { - if (store.state.prefState.historySidebarMode == value) { - return; - } + store.dispatch(UpdateUserPreferences(menuMode: value)); + }, + onHistoryModeChanged: (context, value) async { + if (store.state.prefState.historySidebarMode == value) { + return; + } - store.dispatch(UpdateUserPreferences(historyMode: value)); - }, - onColorThemeChanged: (context, value) async { - if (store.state.prefState.colorTheme != value) { - store.dispatch(UpdateUserPreferences(colorTheme: value)); - } - }, - onRowsPerPageChanged: (context, value) { - store.dispatch(UpdateUserPreferences(rowsPerPage: value)); - }, - onLayoutChanged: (BuildContext context, AppLayout value) async { - if (store.state.prefState.appLayout == value) { - return; - } - store.dispatch(UpdateUserPreferences(appLayout: value)); - AppBuilder.of(context).rebuild(); - WidgetsBinding.instance.addPostFrameCallback((duration) { - if (value == AppLayout.mobile) { - store.dispatch(ViewDashboard()); - } else { - store.dispatch(ViewMainScreen(addDelay: true)); - } - }); - }, - onRequireAuthenticationChanged: - (BuildContext context, bool value) async { - bool authenticated = false; - try { - authenticated = await LocalAuthentication().authenticate( - localizedReason: - AppLocalization.of(context).authenticateToChangeSetting, - biometricOnly: true, - useErrorDialogs: true, - stickyAuth: false); - } catch (e) { - print(e); - } - if (authenticated) { - store.dispatch(UpdateUserPreferences(requireAuthentication: value)); - } else {} - }, - //authenticationSupported: LocalAuthentication().canCheckBiometrics, - // TODO remove this once issue is resolved: - // https://github.com/flutter/flutter/issues/24339 - authenticationSupported: Future( - () async { - bool enable = false; - try { - enable = await LocalAuthentication().canCheckBiometrics; - } catch (e) { - // do nothing - } - return enable; - }, - ), - onCustomColorsChanged: (context, customColors) { - store.dispatch(UpdateUserPreferences(customColors: customColors)); - store.dispatch(UpdatedSetting()); - }, - onPersistDataChanged: (context, value) { - store.dispatch(UpdateUserPreferences(persistData: value)); - if (value) { - store.dispatch(UserLoginSuccess()); + store.dispatch(UpdateUserPreferences(historyMode: value)); + }, + onColorThemeChanged: (context, value) async { + if (store.state.prefState.colorTheme != value) { + store.dispatch(UpdateUserPreferences(colorTheme: value)); + } + }, + onRowsPerPageChanged: (context, value) { + store.dispatch(UpdateUserPreferences(rowsPerPage: value)); + }, + onLayoutChanged: (BuildContext context, AppLayout value) async { + if (store.state.prefState.appLayout == value) { + return; + } + store.dispatch(UpdateUserPreferences(appLayout: value)); + AppBuilder.of(context).rebuild(); + WidgetsBinding.instance.addPostFrameCallback((duration) { + if (value == AppLayout.mobile) { + store.dispatch(ViewDashboard()); + } else { + store.dispatch(ViewMainScreen(addDelay: true)); } }); + }, + onRequireAuthenticationChanged: (BuildContext context, bool value) async { + bool authenticated = false; + try { + authenticated = await LocalAuthentication().authenticate( + localizedReason: + AppLocalization.of(context).authenticateToChangeSetting, + biometricOnly: true, + useErrorDialogs: true, + stickyAuth: false); + } catch (e) { + print(e); + } + if (authenticated) { + store.dispatch(UpdateUserPreferences(requireAuthentication: value)); + } else {} + }, + //authenticationSupported: LocalAuthentication().canCheckBiometrics, + // TODO remove this once issue is resolved: + // https://github.com/flutter/flutter/issues/24339 + authenticationSupported: Future( + () async { + bool enable = false; + try { + enable = await LocalAuthentication().canCheckBiometrics; + } catch (e) { + // do nothing + } + return enable; + }, + ), + onCustomColorsChanged: (context, customColors) { + store.dispatch(UpdateUserPreferences(customColors: customColors)); + store.dispatch(UpdatedSetting()); + }, + onPersistDataChanged: (context, value) { + store.dispatch(UpdateUserPreferences(persistData: value)); + if (value) { + store.dispatch(UserLoginSuccess()); + } + }, + onPersistUiChanged: (context, value) { + store.dispatch(UpdateUserPreferences(persistUi: value)); + if (value) { + store.dispatch(PersistUI()); + } + }, + ); } final AppState state; @@ -167,6 +173,7 @@ class DeviceSettingsVM { final Function(BuildContext, bool) onLongPressSelectionIsDefault; final Function(BuildContext, bool) onRequireAuthenticationChanged; final Function(BuildContext, bool) onPersistDataChanged; + final Function(BuildContext, bool) onPersistUiChanged; final Function(BuildContext, int) onRowsPerPageChanged; final Future authenticationSupported; } diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index 3ba42b73d..3da51747f 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -16,9 +16,10 @@ mixin LocalizationsProvider on LocaleCodeAware { 'en': { // STARTER: lang key - do not remove comment 'persist_data_help': - 'Save data locally to enable the app to start faster\nMay affect performance', - 'persist_data_ui': - 'Save UI state to enable the app to start at the last location\nMay slightly affect performance', + 'Save data locally to enable the app to start faster, disabling may improve performance in large accounts', + 'persist_ui': 'Persist UI', + 'persist_ui_help': + 'Save UI state to enable the app to start at the last location, disabling may slightly improve performance', 'client_postal_code': 'Client Postal Code', 'client_vat_number': 'Client VAT Number', 'has_tasks': 'Has Tasks', @@ -62733,10 +62734,14 @@ mixin LocalizationsProvider on LocaleCodeAware { _localizedValues[localeCode]['persist_data_help'] ?? _localizedValues['en']['persist_data_help']; - String get persistUIHelp => + String get persistUiHelp => _localizedValues[localeCode]['persist_ui_help'] ?? _localizedValues['en']['persist_ui_help']; + String get persistUi => + _localizedValues[localeCode]['persist_ui'] ?? + _localizedValues['en']['persist_ui']; + // STARTER: lang field - do not remove comment String lookup(String key) {