From 7212d73524bb383bacdda8e29a2244e0d76f0538 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Wed, 10 Nov 2021 09:34:45 +0200 Subject: [PATCH] [UX] Clicking row in index view automatically opens corresponding edit view #247 --- lib/redux/app/app_actions.dart | 4 +- lib/redux/ui/pref_reducer.dart | 8 ++++ lib/redux/ui/pref_state.dart | 4 ++ lib/redux/ui/pref_state.g.dart | 63 +++++++++++++++---------- lib/ui/settings/device_settings.dart | 30 ++++++++---- lib/ui/settings/device_settings_vm.dart | 5 ++ lib/utils/i18n.dart | 15 ++++++ 7 files changed, 93 insertions(+), 36 deletions(-) diff --git a/lib/redux/app/app_actions.dart b/lib/redux/app/app_actions.dart index e4e98396d..8da8009cb 100644 --- a/lib/redux/app/app_actions.dart +++ b/lib/redux/app/app_actions.dart @@ -140,6 +140,7 @@ class UpdateUserPreferences implements PersistPrefs { this.customColors, this.persistData, this.persistUi, + this.tapSelectedToEdit, }); final AppLayout appLayout; @@ -158,6 +159,7 @@ class UpdateUserPreferences implements PersistPrefs { final String colorTheme; final bool persistData; final bool persistUi; + final bool tapSelectedToEdit; final BuiltMap customColors; } @@ -1429,7 +1431,7 @@ void selectEntity({ entityUIState.selectedId == entity.id) { if (entityUIState.tabIndex > 0) { store.dispatch(PreviewEntity()); - } else { + } else if (state.prefState.tapSelectedToEdit) { editEntity(context: context, entity: entity); } } else { diff --git a/lib/redux/ui/pref_reducer.dart b/lib/redux/ui/pref_reducer.dart index fb4b527a7..15c78165a 100644 --- a/lib/redux/ui/pref_reducer.dart +++ b/lib/redux/ui/pref_reducer.dart @@ -61,6 +61,8 @@ PrefState prefReducer( ..isFilterVisible = isFilterVisibleReducer(state.isFilterVisible, action) ..longPressSelectionIsDefault = longPressReducer(state.longPressSelectionIsDefault, action) + ..tapSelectedToEdit = + tapSelectedToEditReducer(state.tapSelectedToEdit, action) ..requireAuthentication = requireAuthenticationReducer(state.requireAuthentication, action) ..colorTheme = colorThemeReducer(state.colorTheme, action) @@ -275,6 +277,12 @@ Reducer longPressReducer = combineReducers([ }), ]); +Reducer tapSelectedToEditReducer = combineReducers([ + TypedReducer((tapSelectedToEdit, action) { + return action.tapSelectedToEdit ?? tapSelectedToEdit; + }), +]); + Reducer isPreviewVisibleReducer = combineReducers([ TypedReducer((value, action) { return !value; diff --git a/lib/redux/ui/pref_state.dart b/lib/redux/ui/pref_state.dart index 9da49d3da..876744614 100644 --- a/lib/redux/ui/pref_state.dart +++ b/lib/redux/ui/pref_state.dart @@ -25,6 +25,7 @@ abstract class PrefState implements Built { colorTheme: kColorThemeLight, isFilterVisible: false, longPressSelectionIsDefault: true, + tapSelectedToEdit: false, showKanban: false, persistData: false, persistUI: true, @@ -105,6 +106,8 @@ abstract class PrefState implements Built { bool get requireAuthentication; + bool get tapSelectedToEdit; + int get rowsPerPage; String get colorTheme; @@ -177,6 +180,7 @@ abstract class PrefState implements Built { ..showKanban = false ..isPreviewVisible = false ..isFilterVisible = false + ..tapSelectedToEdit = false ..persistData = false ..persistUI = true ..colorTheme = diff --git a/lib/redux/ui/pref_state.g.dart b/lib/redux/ui/pref_state.g.dart index 972b05154..bc99ffcd1 100644 --- a/lib/redux/ui/pref_state.g.dart +++ b/lib/redux/ui/pref_state.g.dart @@ -163,6 +163,9 @@ class _$PrefStateSerializer implements StructuredSerializer { 'requireAuthentication', serializers.serialize(object.requireAuthentication, specifiedType: const FullType(bool)), + 'tapSelectedToEdit', + serializers.serialize(object.tapSelectedToEdit, + specifiedType: const FullType(bool)), 'rowsPerPage', serializers.serialize(object.rowsPerPage, specifiedType: const FullType(int)), @@ -263,6 +266,10 @@ class _$PrefStateSerializer implements StructuredSerializer { result.requireAuthentication = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool; break; + case 'tapSelectedToEdit': + result.tapSelectedToEdit = serializers.deserialize(value, + specifiedType: const FullType(bool)) as bool; + break; case 'rowsPerPage': result.rowsPerPage = serializers.deserialize(value, specifiedType: const FullType(int)) as int; @@ -548,6 +555,8 @@ class _$PrefState extends PrefState { @override final bool requireAuthentication; @override + final bool tapSelectedToEdit; + @override final int rowsPerPage; @override final String colorTheme; @@ -576,6 +585,7 @@ class _$PrefState extends PrefState { this.persistUI, this.longPressSelectionIsDefault, this.requireAuthentication, + this.tapSelectedToEdit, this.rowsPerPage, this.colorTheme, this.sortFields, @@ -611,6 +621,8 @@ class _$PrefState extends PrefState { 'PrefState', 'longPressSelectionIsDefault'); BuiltValueNullFieldError.checkNotNull( requireAuthentication, 'PrefState', 'requireAuthentication'); + BuiltValueNullFieldError.checkNotNull( + tapSelectedToEdit, 'PrefState', 'tapSelectedToEdit'); BuiltValueNullFieldError.checkNotNull( rowsPerPage, 'PrefState', 'rowsPerPage'); BuiltValueNullFieldError.checkNotNull( @@ -648,6 +660,7 @@ class _$PrefState extends PrefState { persistUI == other.persistUI && longPressSelectionIsDefault == other.longPressSelectionIsDefault && requireAuthentication == other.requireAuthentication && + tapSelectedToEdit == other.tapSelectedToEdit && rowsPerPage == other.rowsPerPage && colorTheme == other.colorTheme && sortFields == other.sortFields && @@ -675,32 +688,22 @@ class _$PrefState extends PrefState { $jc( $jc( $jc( - $jc( - $jc( - 0, - appLayout - .hashCode), - moduleLayout - .hashCode), - menuSidebarMode - .hashCode), - historySidebarMode - .hashCode), - useSidebarEditor - .hashCode), - customColors - .hashCode), - isPreviewVisible - .hashCode), - isMenuVisible.hashCode), - showKanban.hashCode), - isHistoryVisible.hashCode), - enableDarkMode.hashCode), - isFilterVisible.hashCode), - persistData.hashCode), - persistUI.hashCode), - longPressSelectionIsDefault.hashCode), - requireAuthentication.hashCode), + $jc($jc($jc(0, appLayout.hashCode), moduleLayout.hashCode), + menuSidebarMode.hashCode), + historySidebarMode.hashCode), + useSidebarEditor.hashCode), + customColors.hashCode), + isPreviewVisible.hashCode), + isMenuVisible.hashCode), + showKanban.hashCode), + isHistoryVisible.hashCode), + enableDarkMode.hashCode), + isFilterVisible.hashCode), + persistData.hashCode), + persistUI.hashCode), + longPressSelectionIsDefault.hashCode), + requireAuthentication.hashCode), + tapSelectedToEdit.hashCode), rowsPerPage.hashCode), colorTheme.hashCode), sortFields.hashCode), @@ -726,6 +729,7 @@ class _$PrefState extends PrefState { ..add('persistUI', persistUI) ..add('longPressSelectionIsDefault', longPressSelectionIsDefault) ..add('requireAuthentication', requireAuthentication) + ..add('tapSelectedToEdit', tapSelectedToEdit) ..add('rowsPerPage', rowsPerPage) ..add('colorTheme', colorTheme) ..add('sortFields', sortFields) @@ -815,6 +819,11 @@ class PrefStateBuilder implements Builder { set requireAuthentication(bool requireAuthentication) => _$this._requireAuthentication = requireAuthentication; + bool _tapSelectedToEdit; + bool get tapSelectedToEdit => _$this._tapSelectedToEdit; + set tapSelectedToEdit(bool tapSelectedToEdit) => + _$this._tapSelectedToEdit = tapSelectedToEdit; + int _rowsPerPage; int get rowsPerPage => _$this._rowsPerPage; set rowsPerPage(int rowsPerPage) => _$this._rowsPerPage = rowsPerPage; @@ -858,6 +867,7 @@ class PrefStateBuilder implements Builder { _persistUI = $v.persistUI; _longPressSelectionIsDefault = $v.longPressSelectionIsDefault; _requireAuthentication = $v.requireAuthentication; + _tapSelectedToEdit = $v.tapSelectedToEdit; _rowsPerPage = $v.rowsPerPage; _colorTheme = $v.colorTheme; _sortFields = $v.sortFields.toBuilder(); @@ -908,6 +918,7 @@ class PrefStateBuilder implements Builder { persistUI: BuiltValueNullFieldError.checkNotNull(persistUI, 'PrefState', 'persistUI'), longPressSelectionIsDefault: BuiltValueNullFieldError.checkNotNull(longPressSelectionIsDefault, 'PrefState', 'longPressSelectionIsDefault'), requireAuthentication: BuiltValueNullFieldError.checkNotNull(requireAuthentication, 'PrefState', 'requireAuthentication'), + tapSelectedToEdit: BuiltValueNullFieldError.checkNotNull(tapSelectedToEdit, 'PrefState', 'tapSelectedToEdit'), rowsPerPage: BuiltValueNullFieldError.checkNotNull(rowsPerPage, 'PrefState', 'rowsPerPage'), colorTheme: BuiltValueNullFieldError.checkNotNull(colorTheme, 'PrefState', 'colorTheme'), sortFields: sortFields.build(), diff --git a/lib/ui/settings/device_settings.dart b/lib/ui/settings/device_settings.dart index d7c4797ac..bca337a82 100644 --- a/lib/ui/settings/device_settings.dart +++ b/lib/ui/settings/device_settings.dart @@ -144,15 +144,27 @@ class _DeviceSettingsState extends State disabledLabel: localization.showOrHide, ), ], - BoolDropdownButton( - label: localization.listLongPress, - value: !prefState.longPressSelectionIsDefault, - onChanged: (value) { - viewModel.onLongPressSelectionIsDefault(context, !value); - }, - enabledLabel: localization.showActions, - disabledLabel: localization.startMultiselect, - ), + if (isDesktop(context)) + BoolDropdownButton( + label: localization.clickSelected, + value: prefState.tapSelectedToEdit, + onChanged: (value) { + viewModel.onTapSelectedChanged(context, value); + }, + enabledLabel: localization.editRecord, + disabledLabel: localization.noAction, + ) + else + BoolDropdownButton( + label: localization.listLongPress, + value: !prefState.longPressSelectionIsDefault, + onChanged: (value) { + viewModel.onLongPressSelectionIsDefault( + context, !value); + }, + enabledLabel: localization.showActions, + disabledLabel: localization.startMultiselect, + ), AppDropdownButton( blankValue: null, labelText: localization.rowsPerPage, diff --git a/lib/ui/settings/device_settings_vm.dart b/lib/ui/settings/device_settings_vm.dart index 571de1ee2..9f0dff5b7 100644 --- a/lib/ui/settings/device_settings_vm.dart +++ b/lib/ui/settings/device_settings_vm.dart @@ -50,6 +50,7 @@ class DeviceSettingsVM { @required this.onCustomColorsChanged, @required this.onPersistDataChanged, @required this.onPersistUiChanged, + @required this.onTapSelectedChanged, }); static DeviceSettingsVM fromStore(Store store) { @@ -90,6 +91,9 @@ class DeviceSettingsVM { store.dispatch(UpdateUserPreferences(historyMode: value)); }, + onTapSelectedChanged: (context, value) async { + store.dispatch(UpdateUserPreferences(tapSelectedToEdit: value)); + }, onColorThemeChanged: (context, value) async { if (store.state.prefState.colorTheme != value) { store.dispatch(UpdateUserPreferences(colorTheme: value)); @@ -173,6 +177,7 @@ class DeviceSettingsVM { final Function(BuildContext, AppSidebarMode) onHistoryModeChanged; final Function(BuildContext, String) onColorThemeChanged; final Function(BuildContext, bool) onLongPressSelectionIsDefault; + final Function(BuildContext, bool) onTapSelectedChanged; final Function(BuildContext, bool) onRequireAuthenticationChanged; final Function(BuildContext, bool) onPersistDataChanged; final Function(BuildContext, bool) onPersistUiChanged; diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index e2ea91e0a..c54726b3c 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -15,6 +15,9 @@ mixin LocalizationsProvider on LocaleCodeAware { static final Map> _localizedValues = { 'en': { // STARTER: lang key - do not remove comment + 'click_selected': 'Click Selected', + 'no_action': 'No Action', + 'edit_record': 'Edit Record', 'credit_is_more_than_invoice': 'The credit amount can not be more than the invoice amount', 'giropay': 'Giropay', @@ -62813,6 +62816,18 @@ mixin LocalizationsProvider on LocaleCodeAware { _localizedValues[localeCode]['credit_is_more_than_invoice'] ?? _localizedValues['en']['credit_is_more_than_invoice']; + String get clickSelected => + _localizedValues[localeCode]['click_selected'] ?? + _localizedValues['en']['click_selected']; + + String get noAction => + _localizedValues[localeCode]['no_action'] ?? + _localizedValues['en']['no_action']; + + String get editRecord => + _localizedValues[localeCode]['edit_record'] ?? + _localizedValues['en']['edit_record']; + // STARTER: lang field - do not remove comment String lookup(String key) {