Added flexible search

This commit is contained in:
Hillel Coren 2022-06-30 17:56:28 +03:00
parent 42fe93b39b
commit 49d1370aac
8 changed files with 78 additions and 11 deletions

View File

@ -160,6 +160,7 @@ class UpdateUserPreferences implements PersistPrefs {
this.editAfterSaving, this.editAfterSaving,
this.enableTouchEvents, this.enableTouchEvents,
this.enableTooltips, this.enableTooltips,
this.flexibleSearch,
}); });
final AppLayout appLayout; final AppLayout appLayout;
@ -186,6 +187,7 @@ class UpdateUserPreferences implements PersistPrefs {
final bool editAfterSaving; final bool editAfterSaving;
final bool enableTouchEvents; final bool enableTouchEvents;
final bool enableTooltips; final bool enableTooltips;
final bool flexibleSearch;
} }
class LoadAccountSuccess implements StopLoading { class LoadAccountSuccess implements StopLoading {

View File

@ -66,6 +66,8 @@ PrefState prefReducer(
..enableDarkMode = darkModeReducer(state.enableDarkMode, action) ..enableDarkMode = darkModeReducer(state.enableDarkMode, action)
..enableJSPDF = enableJspdfReducer(state.enableJSPDF, action) ..enableJSPDF = enableJspdfReducer(state.enableJSPDF, action)
..enableTooltips = enableTooltipsReducer(state.enableTooltips, action) ..enableTooltips = enableTooltipsReducer(state.enableTooltips, action)
..enableFlexibleSearch =
enableFlexibleSearchReducer(state.enableFlexibleSearch, action)
..persistData = persistDataReducer(state.persistData, action) ..persistData = persistDataReducer(state.persistData, action)
..persistUI = persistUIReducer(state.persistUI, action) ..persistUI = persistUIReducer(state.persistUI, action)
..showKanban = showKanbanReducer(state.showKanban, action) ..showKanban = showKanbanReducer(state.showKanban, action)
@ -311,6 +313,12 @@ Reducer<bool> enableTooltipsReducer = combineReducers([
}), }),
]); ]);
Reducer<bool> enableFlexibleSearchReducer = combineReducers([
TypedReducer<bool, UpdateUserPreferences>((enableFlexibleSearch, action) {
return action.flexibleSearch ?? enableFlexibleSearch;
}),
]);
Reducer<bool> persistDataReducer = combineReducers([ Reducer<bool> persistDataReducer = combineReducers([
TypedReducer<bool, UpdateUserPreferences>((persistData, action) { TypedReducer<bool, UpdateUserPreferences>((persistData, action) {
return action.persistData ?? persistData; return action.persistData ?? persistData;

View File

@ -27,6 +27,7 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
isMenuVisible: true, isMenuVisible: true,
isHistoryVisible: false, isHistoryVisible: false,
enableDarkMode: false, enableDarkMode: false,
enableFlexibleSearch: true,
editAfterSaving: true, editAfterSaving: true,
requireAuthentication: false, requireAuthentication: false,
colorTheme: kColorThemeLight, colorTheme: kColorThemeLight,
@ -117,6 +118,8 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
bool get enableTouchEvents; bool get enableTouchEvents;
bool get enableFlexibleSearch;
bool get isHistoryVisible; bool get isHistoryVisible;
bool get enableDarkMode; bool get enableDarkMode;
@ -232,6 +235,7 @@ abstract class PrefState implements Built<PrefState, PrefStateBuilder> {
..editAfterSaving = true ..editAfterSaving = true
..showPdfPreview = true ..showPdfPreview = true
..enableTouchEvents = true ..enableTouchEvents = true
..enableFlexibleSearch = true
..enableJSPDF = false ..enableJSPDF = false
..enableTooltips = true ..enableTooltips = true
..textScaleFactor = 1 ..textScaleFactor = 1

View File

@ -152,6 +152,9 @@ class _$PrefStateSerializer implements StructuredSerializer<PrefState> {
'enableTouchEvents', 'enableTouchEvents',
serializers.serialize(object.enableTouchEvents, serializers.serialize(object.enableTouchEvents,
specifiedType: const FullType(bool)), specifiedType: const FullType(bool)),
'enableFlexibleSearch',
serializers.serialize(object.enableFlexibleSearch,
specifiedType: const FullType(bool)),
'isHistoryVisible', 'isHistoryVisible',
serializers.serialize(object.isHistoryVisible, serializers.serialize(object.isHistoryVisible,
specifiedType: const FullType(bool)), specifiedType: const FullType(bool)),
@ -279,6 +282,10 @@ class _$PrefStateSerializer implements StructuredSerializer<PrefState> {
result.enableTouchEvents = serializers.deserialize(value, result.enableTouchEvents = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool; specifiedType: const FullType(bool)) as bool;
break; break;
case 'enableFlexibleSearch':
result.enableFlexibleSearch = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool;
break;
case 'isHistoryVisible': case 'isHistoryVisible':
result.isHistoryVisible = serializers.deserialize(value, result.isHistoryVisible = serializers.deserialize(value,
specifiedType: const FullType(bool)) as bool; specifiedType: const FullType(bool)) as bool;
@ -612,6 +619,8 @@ class _$PrefState extends PrefState {
@override @override
final bool enableTouchEvents; final bool enableTouchEvents;
@override @override
final bool enableFlexibleSearch;
@override
final bool isHistoryVisible; final bool isHistoryVisible;
@override @override
final bool enableDarkMode; final bool enableDarkMode;
@ -664,6 +673,7 @@ class _$PrefState extends PrefState {
this.showKanban, this.showKanban,
this.showPdfPreview, this.showPdfPreview,
this.enableTouchEvents, this.enableTouchEvents,
this.enableFlexibleSearch,
this.isHistoryVisible, this.isHistoryVisible,
this.enableDarkMode, this.enableDarkMode,
this.isFilterVisible, this.isFilterVisible,
@ -706,6 +716,8 @@ class _$PrefState extends PrefState {
showPdfPreview, 'PrefState', 'showPdfPreview'); showPdfPreview, 'PrefState', 'showPdfPreview');
BuiltValueNullFieldError.checkNotNull( BuiltValueNullFieldError.checkNotNull(
enableTouchEvents, 'PrefState', 'enableTouchEvents'); enableTouchEvents, 'PrefState', 'enableTouchEvents');
BuiltValueNullFieldError.checkNotNull(
enableFlexibleSearch, 'PrefState', 'enableFlexibleSearch');
BuiltValueNullFieldError.checkNotNull( BuiltValueNullFieldError.checkNotNull(
isHistoryVisible, 'PrefState', 'isHistoryVisible'); isHistoryVisible, 'PrefState', 'isHistoryVisible');
BuiltValueNullFieldError.checkNotNull( BuiltValueNullFieldError.checkNotNull(
@ -766,6 +778,7 @@ class _$PrefState extends PrefState {
showKanban == other.showKanban && showKanban == other.showKanban &&
showPdfPreview == other.showPdfPreview && showPdfPreview == other.showPdfPreview &&
enableTouchEvents == other.enableTouchEvents && enableTouchEvents == other.enableTouchEvents &&
enableFlexibleSearch == other.enableFlexibleSearch &&
isHistoryVisible == other.isHistoryVisible && isHistoryVisible == other.isHistoryVisible &&
enableDarkMode == other.enableDarkMode && enableDarkMode == other.enableDarkMode &&
isFilterVisible == other.isFilterVisible && isFilterVisible == other.isFilterVisible &&
@ -807,8 +820,8 @@ class _$PrefState extends PrefState {
$jc( $jc(
$jc( $jc(
$jc( $jc(
$jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, appLayout.hashCode), moduleLayout.hashCode), menuSidebarMode.hashCode), historySidebarMode.hashCode), useSidebarEditor.hashCode), useSidebarViewer.hashCode), customColors.hashCode), isPreviewVisible.hashCode), isMenuVisible.hashCode), showKanban.hashCode), showPdfPreview.hashCode), $jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc($jc(0, appLayout.hashCode), moduleLayout.hashCode), menuSidebarMode.hashCode), historySidebarMode.hashCode), useSidebarEditor.hashCode), useSidebarViewer.hashCode), customColors.hashCode), isPreviewVisible.hashCode), isMenuVisible.hashCode), showKanban.hashCode), showPdfPreview.hashCode), enableTouchEvents.hashCode),
enableTouchEvents.hashCode), enableFlexibleSearch.hashCode),
isHistoryVisible.hashCode), isHistoryVisible.hashCode),
enableDarkMode.hashCode), enableDarkMode.hashCode),
isFilterVisible.hashCode), isFilterVisible.hashCode),
@ -844,6 +857,7 @@ class _$PrefState extends PrefState {
..add('showKanban', showKanban) ..add('showKanban', showKanban)
..add('showPdfPreview', showPdfPreview) ..add('showPdfPreview', showPdfPreview)
..add('enableTouchEvents', enableTouchEvents) ..add('enableTouchEvents', enableTouchEvents)
..add('enableFlexibleSearch', enableFlexibleSearch)
..add('isHistoryVisible', isHistoryVisible) ..add('isHistoryVisible', isHistoryVisible)
..add('enableDarkMode', enableDarkMode) ..add('enableDarkMode', enableDarkMode)
..add('isFilterVisible', isFilterVisible) ..add('isFilterVisible', isFilterVisible)
@ -930,6 +944,11 @@ class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
set enableTouchEvents(bool enableTouchEvents) => set enableTouchEvents(bool enableTouchEvents) =>
_$this._enableTouchEvents = enableTouchEvents; _$this._enableTouchEvents = enableTouchEvents;
bool _enableFlexibleSearch;
bool get enableFlexibleSearch => _$this._enableFlexibleSearch;
set enableFlexibleSearch(bool enableFlexibleSearch) =>
_$this._enableFlexibleSearch = enableFlexibleSearch;
bool _isHistoryVisible; bool _isHistoryVisible;
bool get isHistoryVisible => _$this._isHistoryVisible; bool get isHistoryVisible => _$this._isHistoryVisible;
set isHistoryVisible(bool isHistoryVisible) => set isHistoryVisible(bool isHistoryVisible) =>
@ -1036,6 +1055,7 @@ class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
_showKanban = $v.showKanban; _showKanban = $v.showKanban;
_showPdfPreview = $v.showPdfPreview; _showPdfPreview = $v.showPdfPreview;
_enableTouchEvents = $v.enableTouchEvents; _enableTouchEvents = $v.enableTouchEvents;
_enableFlexibleSearch = $v.enableFlexibleSearch;
_isHistoryVisible = $v.isHistoryVisible; _isHistoryVisible = $v.isHistoryVisible;
_enableDarkMode = $v.enableDarkMode; _enableDarkMode = $v.enableDarkMode;
_isFilterVisible = $v.isFilterVisible; _isFilterVisible = $v.isFilterVisible;
@ -1096,6 +1116,7 @@ class PrefStateBuilder implements Builder<PrefState, PrefStateBuilder> {
showPdfPreview: showPdfPreview:
BuiltValueNullFieldError.checkNotNull(showPdfPreview, 'PrefState', 'showPdfPreview'), BuiltValueNullFieldError.checkNotNull(showPdfPreview, 'PrefState', 'showPdfPreview'),
enableTouchEvents: BuiltValueNullFieldError.checkNotNull(enableTouchEvents, 'PrefState', 'enableTouchEvents'), enableTouchEvents: BuiltValueNullFieldError.checkNotNull(enableTouchEvents, 'PrefState', 'enableTouchEvents'),
enableFlexibleSearch: BuiltValueNullFieldError.checkNotNull(enableFlexibleSearch, 'PrefState', 'enableFlexibleSearch'),
isHistoryVisible: BuiltValueNullFieldError.checkNotNull(isHistoryVisible, 'PrefState', 'isHistoryVisible'), isHistoryVisible: BuiltValueNullFieldError.checkNotNull(isHistoryVisible, 'PrefState', 'isHistoryVisible'),
enableDarkMode: BuiltValueNullFieldError.checkNotNull(enableDarkMode, 'PrefState', 'enableDarkMode'), enableDarkMode: BuiltValueNullFieldError.checkNotNull(enableDarkMode, 'PrefState', 'enableDarkMode'),
isFilterVisible: BuiltValueNullFieldError.checkNotNull(isFilterVisible, 'PrefState', 'isFilterVisible'), isFilterVisible: BuiltValueNullFieldError.checkNotNull(isFilterVisible, 'PrefState', 'isFilterVisible'),

View File

@ -232,6 +232,15 @@ class _DeviceSettingsState extends State<DeviceSettings>
} }
}, },
), ),
SwitchListTile(
title: Text(localization.enableFlexibleSearch),
subtitle: Text(localization.enableFlexibleSearchHelp),
value: prefState.enableFlexibleSearch,
onChanged: (value) =>
viewModel.onEnableFlexibleSearchChanged(context, value),
activeColor: Theme.of(context).colorScheme.secondary,
secondary: Icon(Icons.search),
),
if (isDesktop(context)) ...[ if (isDesktop(context)) ...[
SwitchListTile( SwitchListTile(
title: Text(localization.enableTooltips), title: Text(localization.enableTooltips),

View File

@ -60,6 +60,7 @@ class DeviceSettingsVM {
@required this.onEditAfterSavingChanged, @required this.onEditAfterSavingChanged,
@required this.onEnableTouchEventsChanged, @required this.onEnableTouchEventsChanged,
@required this.onEnableTooltipsChanged, @required this.onEnableTooltipsChanged,
@required this.onEnableFlexibleSearchChanged,
}); });
static DeviceSettingsVM fromStore(Store<AppState> store) { static DeviceSettingsVM fromStore(Store<AppState> store) {
@ -120,6 +121,9 @@ class DeviceSettingsVM {
onEnableTooltipsChanged: (context, value) { onEnableTooltipsChanged: (context, value) {
store.dispatch(UpdateUserPreferences(enableTooltips: value)); store.dispatch(UpdateUserPreferences(enableTooltips: value));
}, },
onEnableFlexibleSearchChanged: (context, value) {
store.dispatch(UpdateUserPreferences(flexibleSearch: 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));
@ -212,6 +216,7 @@ class DeviceSettingsVM {
final Function(BuildContext, bool) onEnableJSPDFChanged; final Function(BuildContext, bool) onEnableJSPDFChanged;
final Function(BuildContext, bool) onEnableTouchEventsChanged; final Function(BuildContext, bool) onEnableTouchEventsChanged;
final Function(BuildContext, bool) onEnableTooltipsChanged; final Function(BuildContext, bool) onEnableTooltipsChanged;
final Function(BuildContext, bool) onEnableFlexibleSearchChanged;
final Function(BuildContext, double) onTextScaleFactorChanged; final Function(BuildContext, double) onTextScaleFactorChanged;
final Future<bool> authenticationSupported; final Future<bool> authenticationSupported;
} }

View File

@ -16,6 +16,9 @@ mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = { static final Map<String, Map<String, String>> _localizedValues = {
'en': { 'en': {
// STARTER: lang key - do not remove comment // STARTER: lang key - do not remove comment
'enable_flexible_search': 'Enable Flexible Search',
'enable_flexible_search_help':
'Match non-contiguous characters, ie. \'ct\' matches \'cat\'',
'vendor_details': 'Vendor Details', 'vendor_details': 'Vendor Details',
'purchase_order_details': 'Purchase Order Details', 'purchase_order_details': 'Purchase Order Details',
'qr_iban': 'QR IBAN', 'qr_iban': 'QR IBAN',
@ -70840,6 +70843,14 @@ mixin LocalizationsProvider on LocaleCodeAware {
_localizedValues[localeCode]['purchase_order_details'] ?? _localizedValues[localeCode]['purchase_order_details'] ??
_localizedValues['en']['purchase_order_details']; _localizedValues['en']['purchase_order_details'];
String get enableFlexibleSearch =>
_localizedValues[localeCode]['enable_flexible_search'] ??
_localizedValues['en']['enable_flexible_search'];
String get enableFlexibleSearchHelp =>
_localizedValues[localeCode]['enable_flexible_search_help'] ??
_localizedValues['en']['enable_flexible_search_help'];
// STARTER: lang field - do not remove comment // STARTER: lang field - do not remove comment
String lookup(String key) { String lookup(String key) {

View File

@ -1,3 +1,7 @@
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/main_app.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
bool isAllDigits(String value) { bool isAllDigits(String value) {
return value.replaceAll(RegExp('[^\\d]'), '') == value; return value.replaceAll(RegExp('[^\\d]'), '') == value;
} }
@ -119,16 +123,19 @@ bool matchesString({String haystack, String needle}) {
return true; return true;
} }
return haystack.toLowerCase().contains(needle.toLowerCase()); final store = StoreProvider.of<AppState>(navigatorKey.currentContext);
final state = store.state;
/* if (state.prefState.enableFlexibleSearch) {
String regExp = ''; String regExp = '';
needle.toLowerCase().runes.forEach((int rune) { needle.toLowerCase().runes.forEach((int rune) {
final character = RegExp.escape(String.fromCharCode(rune)); final character = RegExp.escape(String.fromCharCode(rune));
regExp += character + '.*?'; regExp += character + '.*?';
}); });
return RegExp(regExp).hasMatch(haystack.toLowerCase()); return RegExp(regExp).hasMatch(haystack.toLowerCase());
*/ } else {
return haystack.toLowerCase().contains(needle.toLowerCase());
}
} }
String matchesStringsValue({ String matchesStringsValue({