Persist UI option

This commit is contained in:
Hillel Coren 2021-10-21 15:52:26 +03:00
parent 0c01b9afbb
commit c03922a1ce
6 changed files with 163 additions and 115 deletions

View File

@ -134,6 +134,7 @@ class UpdateUserPreferences implements PersistPrefs {
this.colorTheme, this.colorTheme,
this.customColors, this.customColors,
this.persistData, this.persistData,
this.persistUi,
}); });
final AppLayout appLayout; final AppLayout appLayout;
@ -151,6 +152,7 @@ class UpdateUserPreferences implements PersistPrefs {
final int rowsPerPage; final int rowsPerPage;
final String colorTheme; final String colorTheme;
final bool persistData; final bool persistData;
final bool persistUi;
final BuiltMap<String, String> customColors; final BuiltMap<String, String> customColors;
} }

View File

@ -27,6 +27,7 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
longPressSelectionIsDefault: true, longPressSelectionIsDefault: true,
showKanban: false, showKanban: false,
persistData: false, persistData: false,
persistUI: true,
companyPrefs: BuiltMap<String, CompanyPrefState>(), companyPrefs: BuiltMap<String, CompanyPrefState>(),
sortFields: BuiltMap<EntityType, PrefStateSortField>(), sortFields: BuiltMap<EntityType, PrefStateSortField>(),
customColors: BuiltMap<String, String>(CONTRAST_COLORS), customColors: BuiltMap<String, String>(CONTRAST_COLORS),
@ -98,6 +99,8 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
bool get persistData; bool get persistData;
bool get persistUI;
bool get longPressSelectionIsDefault; bool get longPressSelectionIsDefault;
bool get requireAuthentication; bool get requireAuthentication;
@ -175,6 +178,7 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
..isPreviewVisible = false ..isPreviewVisible = false
..isFilterVisible = false ..isFilterVisible = false
..persistData = false ..persistData = false
..persistUI = true
..colorTheme = ..colorTheme =
builder.enableDarkMode == true ? kColorThemeLight : kColorThemeLight; builder.enableDarkMode == true ? kColorThemeLight : kColorThemeLight;

View File

@ -154,6 +154,9 @@ class _$PrefStateSerializer implements StructuredSerializer<PrefState> {
'persistData', 'persistData',
serializers.serialize(object.persistData, serializers.serialize(object.persistData,
specifiedType: const FullType(bool)), specifiedType: const FullType(bool)),
'persistUI',
serializers.serialize(object.persistUI,
specifiedType: const FullType(bool)),
'longPressSelectionIsDefault', 'longPressSelectionIsDefault',
serializers.serialize(object.longPressSelectionIsDefault, serializers.serialize(object.longPressSelectionIsDefault,
specifiedType: const FullType(bool)), specifiedType: const FullType(bool)),
@ -248,6 +251,10 @@ class _$PrefStateSerializer implements StructuredSerializer<PrefState> {
result.persistData = serializers.deserialize(value, result.persistData = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool; specifiedType: const FullType(bool)) as bool;
break; break;
case 'persistUI':
result.persistUI = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool;
break;
case 'longPressSelectionIsDefault': case 'longPressSelectionIsDefault':
result.longPressSelectionIsDefault = serializers.deserialize(value, result.longPressSelectionIsDefault = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool; specifiedType: const FullType(bool)) as bool;
@ -535,6 +542,8 @@ class _$PrefState extends PrefState {
@override @override
final bool persistData; final bool persistData;
@override @override
final bool persistUI;
@override
final bool longPressSelectionIsDefault; final bool longPressSelectionIsDefault;
@override @override
final bool requireAuthentication; final bool requireAuthentication;
@ -564,6 +573,7 @@ class _$PrefState extends PrefState {
this.enableDarkMode, this.enableDarkMode,
this.isFilterVisible, this.isFilterVisible,
this.persistData, this.persistData,
this.persistUI,
this.longPressSelectionIsDefault, this.longPressSelectionIsDefault,
this.requireAuthentication, this.requireAuthentication,
this.rowsPerPage, this.rowsPerPage,
@ -596,6 +606,7 @@ class _$PrefState extends PrefState {
isFilterVisible, 'PrefState', 'isFilterVisible'); isFilterVisible, 'PrefState', 'isFilterVisible');
BuiltValueNullFieldError.checkNotNull( BuiltValueNullFieldError.checkNotNull(
persistData, 'PrefState', 'persistData'); persistData, 'PrefState', 'persistData');
BuiltValueNullFieldError.checkNotNull(persistUI, 'PrefState', 'persistUI');
BuiltValueNullFieldError.checkNotNull(longPressSelectionIsDefault, BuiltValueNullFieldError.checkNotNull(longPressSelectionIsDefault,
'PrefState', 'longPressSelectionIsDefault'); 'PrefState', 'longPressSelectionIsDefault');
BuiltValueNullFieldError.checkNotNull( BuiltValueNullFieldError.checkNotNull(
@ -634,6 +645,7 @@ class _$PrefState extends PrefState {
enableDarkMode == other.enableDarkMode && enableDarkMode == other.enableDarkMode &&
isFilterVisible == other.isFilterVisible && isFilterVisible == other.isFilterVisible &&
persistData == other.persistData && persistData == other.persistData &&
persistUI == other.persistUI &&
longPressSelectionIsDefault == other.longPressSelectionIsDefault && longPressSelectionIsDefault == other.longPressSelectionIsDefault &&
requireAuthentication == other.requireAuthentication && requireAuthentication == other.requireAuthentication &&
rowsPerPage == other.rowsPerPage && rowsPerPage == other.rowsPerPage &&
@ -664,27 +676,29 @@ class _$PrefState extends PrefState {
$jc( $jc(
$jc( $jc(
$jc( $jc(
0, $jc(
appLayout 0,
appLayout
.hashCode),
moduleLayout
.hashCode), .hashCode),
moduleLayout menuSidebarMode
.hashCode), .hashCode),
menuSidebarMode historySidebarMode
.hashCode), .hashCode),
historySidebarMode useSidebarEditor
.hashCode), .hashCode),
useSidebarEditor customColors
.hashCode), .hashCode),
customColors isPreviewVisible
.hashCode), .hashCode),
isPreviewVisible isMenuVisible.hashCode),
.hashCode), showKanban.hashCode),
isMenuVisible.hashCode), isHistoryVisible.hashCode),
showKanban.hashCode), enableDarkMode.hashCode),
isHistoryVisible.hashCode), isFilterVisible.hashCode),
enableDarkMode.hashCode), persistData.hashCode),
isFilterVisible.hashCode), persistUI.hashCode),
persistData.hashCode),
longPressSelectionIsDefault.hashCode), longPressSelectionIsDefault.hashCode),
requireAuthentication.hashCode), requireAuthentication.hashCode),
rowsPerPage.hashCode), rowsPerPage.hashCode),
@ -709,6 +723,7 @@ class _$PrefState extends PrefState {
..add('enableDarkMode', enableDarkMode) ..add('enableDarkMode', enableDarkMode)
..add('isFilterVisible', isFilterVisible) ..add('isFilterVisible', isFilterVisible)
..add('persistData', persistData) ..add('persistData', persistData)
..add('persistUI', persistUI)
..add('longPressSelectionIsDefault', longPressSelectionIsDefault) ..add('longPressSelectionIsDefault', longPressSelectionIsDefault)
..add('requireAuthentication', requireAuthentication) ..add('requireAuthentication', requireAuthentication)
..add('rowsPerPage', rowsPerPage) ..add('rowsPerPage', rowsPerPage)
@ -786,6 +801,10 @@ class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
bool get persistData => _$this._persistData; bool get persistData => _$this._persistData;
set persistData(bool persistData) => _$this._persistData = 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 _longPressSelectionIsDefault;
bool get longPressSelectionIsDefault => _$this._longPressSelectionIsDefault; bool get longPressSelectionIsDefault => _$this._longPressSelectionIsDefault;
set longPressSelectionIsDefault(bool longPressSelectionIsDefault) => set longPressSelectionIsDefault(bool longPressSelectionIsDefault) =>
@ -836,6 +855,7 @@ class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
_enableDarkMode = $v.enableDarkMode; _enableDarkMode = $v.enableDarkMode;
_isFilterVisible = $v.isFilterVisible; _isFilterVisible = $v.isFilterVisible;
_persistData = $v.persistData; _persistData = $v.persistData;
_persistUI = $v.persistUI;
_longPressSelectionIsDefault = $v.longPressSelectionIsDefault; _longPressSelectionIsDefault = $v.longPressSelectionIsDefault;
_requireAuthentication = $v.requireAuthentication; _requireAuthentication = $v.requireAuthentication;
_rowsPerPage = $v.rowsPerPage; _rowsPerPage = $v.rowsPerPage;
@ -885,6 +905,7 @@ class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
enableDarkMode: BuiltValueNullFieldError.checkNotNull(enableDarkMode, 'PrefState', 'enableDarkMode'), enableDarkMode: BuiltValueNullFieldError.checkNotNull(enableDarkMode, 'PrefState', 'enableDarkMode'),
isFilterVisible: BuiltValueNullFieldError.checkNotNull(isFilterVisible, 'PrefState', 'isFilterVisible'), isFilterVisible: BuiltValueNullFieldError.checkNotNull(isFilterVisible, 'PrefState', 'isFilterVisible'),
persistData: BuiltValueNullFieldError.checkNotNull(persistData, 'PrefState', 'persistData'), persistData: BuiltValueNullFieldError.checkNotNull(persistData, 'PrefState', 'persistData'),
persistUI: BuiltValueNullFieldError.checkNotNull(persistUI, 'PrefState', 'persistUI'),
longPressSelectionIsDefault: BuiltValueNullFieldError.checkNotNull(longPressSelectionIsDefault, 'PrefState', 'longPressSelectionIsDefault'), longPressSelectionIsDefault: BuiltValueNullFieldError.checkNotNull(longPressSelectionIsDefault, 'PrefState', 'longPressSelectionIsDefault'),
requireAuthentication: BuiltValueNullFieldError.checkNotNull(requireAuthentication, 'PrefState', 'requireAuthentication'), requireAuthentication: BuiltValueNullFieldError.checkNotNull(requireAuthentication, 'PrefState', 'requireAuthentication'),
rowsPerPage: BuiltValueNullFieldError.checkNotNull(rowsPerPage, 'PrefState', 'rowsPerPage'), rowsPerPage: BuiltValueNullFieldError.checkNotNull(rowsPerPage, 'PrefState', 'rowsPerPage'),

View File

@ -196,6 +196,15 @@ class _DeviceSettingsState extends State<DeviceSettings>
} }
}, },
), ),
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( SwitchListTile(
title: Text(localization.persistData), title: Text(localization.persistData),
subtitle: Text(localization.persistDataHelp), subtitle: Text(localization.persistDataHelp),

View File

@ -49,110 +49,116 @@ class DeviceSettingsVM {
@required this.onRowsPerPageChanged, @required this.onRowsPerPageChanged,
@required this.onCustomColorsChanged, @required this.onCustomColorsChanged,
@required this.onPersistDataChanged, @required this.onPersistDataChanged,
@required this.onPersistUiChanged,
}); });
static DeviceSettingsVM fromStore(Store<AppState> store) { static DeviceSettingsVM fromStore(Store<AppState> store) {
return DeviceSettingsVM( return DeviceSettingsVM(
state: store.state, state: store.state,
onRefreshTap: (BuildContext context) => onRefreshTap: (BuildContext context) =>
showRefreshDataDialog(context: context, includeStatic: true), showRefreshDataDialog(context: context, includeStatic: true),
onLogoutTap: (BuildContext context) { onLogoutTap: (BuildContext context) {
final completer = snackBarCompleter<Null>( final completer = snackBarCompleter<Null>(
context, AppLocalization.of(context).endedAllSessions); context, AppLocalization.of(context).endedAllSessions);
store.dispatch(UserLogoutAll(completer: completer)); store.dispatch(UserLogoutAll(completer: completer));
}, },
onDarkModeChanged: (BuildContext context, bool value) async { onDarkModeChanged: (BuildContext context, bool value) async {
store.dispatch(UpdateUserPreferences( store.dispatch(UpdateUserPreferences(
enableDarkMode: value, enableDarkMode: value,
colorTheme: value ? kColorThemeDark : kColorThemeLight, colorTheme: value ? kColorThemeDark : kColorThemeLight,
customColors: value customColors: value
? BuiltMap<String, String>() ? BuiltMap<String, String>()
: BuiltMap<String, String>(PrefState.CONTRAST_COLORS))); : BuiltMap<String, String>(PrefState.CONTRAST_COLORS)));
store.dispatch(UpdatedSetting()); store.dispatch(UpdatedSetting());
AppBuilder.of(context).rebuild(); AppBuilder.of(context).rebuild();
}, },
onLongPressSelectionIsDefault: onLongPressSelectionIsDefault: (BuildContext context, bool value) async {
(BuildContext context, bool value) async { store.dispatch(
store.dispatch( UpdateUserPreferences(longPressSelectionIsDefault: value));
UpdateUserPreferences(longPressSelectionIsDefault: value)); },
}, onMenuModeChanged: (context, value) async {
onMenuModeChanged: (context, value) async { if (store.state.prefState.menuSidebarMode == value) {
if (store.state.prefState.menuSidebarMode == value) { return;
return; }
}
store.dispatch(UpdateUserPreferences(menuMode: value)); store.dispatch(UpdateUserPreferences(menuMode: value));
}, },
onHistoryModeChanged: (context, value) async { onHistoryModeChanged: (context, value) async {
if (store.state.prefState.historySidebarMode == value) { if (store.state.prefState.historySidebarMode == value) {
return; return;
} }
store.dispatch(UpdateUserPreferences(historyMode: value)); store.dispatch(UpdateUserPreferences(historyMode: value));
}, },
onColorThemeChanged: (context, value) async { onColorThemeChanged: (context, value) async {
if (store.state.prefState.colorTheme != value) { if (store.state.prefState.colorTheme != value) {
store.dispatch(UpdateUserPreferences(colorTheme: value)); store.dispatch(UpdateUserPreferences(colorTheme: value));
} }
}, },
onRowsPerPageChanged: (context, value) { onRowsPerPageChanged: (context, value) {
store.dispatch(UpdateUserPreferences(rowsPerPage: value)); store.dispatch(UpdateUserPreferences(rowsPerPage: value));
}, },
onLayoutChanged: (BuildContext context, AppLayout value) async { onLayoutChanged: (BuildContext context, AppLayout value) async {
if (store.state.prefState.appLayout == value) { if (store.state.prefState.appLayout == value) {
return; return;
} }
store.dispatch(UpdateUserPreferences(appLayout: value)); store.dispatch(UpdateUserPreferences(appLayout: value));
AppBuilder.of(context).rebuild(); AppBuilder.of(context).rebuild();
WidgetsBinding.instance.addPostFrameCallback((duration) { WidgetsBinding.instance.addPostFrameCallback((duration) {
if (value == AppLayout.mobile) { if (value == AppLayout.mobile) {
store.dispatch(ViewDashboard()); store.dispatch(ViewDashboard());
} else { } else {
store.dispatch(ViewMainScreen(addDelay: true)); 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<bool>(
() 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());
} }
}); });
},
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<bool>(
() 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; final AppState state;
@ -167,6 +173,7 @@ class DeviceSettingsVM {
final Function(BuildContext, bool) onLongPressSelectionIsDefault; final Function(BuildContext, bool) onLongPressSelectionIsDefault;
final Function(BuildContext, bool) onRequireAuthenticationChanged; final Function(BuildContext, bool) onRequireAuthenticationChanged;
final Function(BuildContext, bool) onPersistDataChanged; final Function(BuildContext, bool) onPersistDataChanged;
final Function(BuildContext, bool) onPersistUiChanged;
final Function(BuildContext, int) onRowsPerPageChanged; final Function(BuildContext, int) onRowsPerPageChanged;
final Future<bool> authenticationSupported; final Future<bool> authenticationSupported;
} }

View File

@ -16,9 +16,10 @@ mixin LocalizationsProvider on LocaleCodeAware {
'en': { 'en': {
// STARTER: lang key - do not remove comment // STARTER: lang key - do not remove comment
'persist_data_help': 'persist_data_help':
'Save data locally to enable the app to start faster\nMay affect performance', 'Save data locally to enable the app to start faster, disabling may improve performance in large accounts',
'persist_data_ui': 'persist_ui': 'Persist UI',
'Save UI state to enable the app to start at the last location\nMay slightly affect performance', '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_postal_code': 'Client Postal Code',
'client_vat_number': 'Client VAT Number', 'client_vat_number': 'Client VAT Number',
'has_tasks': 'Has Tasks', 'has_tasks': 'Has Tasks',
@ -62733,10 +62734,14 @@ mixin LocalizationsProvider on LocaleCodeAware {
_localizedValues[localeCode]['persist_data_help'] ?? _localizedValues[localeCode]['persist_data_help'] ??
_localizedValues['en']['persist_data_help']; _localizedValues['en']['persist_data_help'];
String get persistUIHelp => String get persistUiHelp =>
_localizedValues[localeCode]['persist_ui_help'] ?? _localizedValues[localeCode]['persist_ui_help'] ??
_localizedValues['en']['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 // STARTER: lang field - do not remove comment
String lookup(String key) { String lookup(String key) {