mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: more select option cell editor improvements (#5019)
This commit is contained in:
parent
129d56e494
commit
53dbef25ab
@ -6,6 +6,7 @@ import 'package:appflowy/plugins/database/domain/field_service.dart';
|
|||||||
import 'package:appflowy/plugins/database/domain/select_option_cell_service.dart';
|
import 'package:appflowy/plugins/database/domain/select_option_cell_service.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
@ -56,15 +57,20 @@ class SelectOptionCellEditorBloc
|
|||||||
|
|
||||||
VoidCallback? _onCellChangedFn;
|
VoidCallback? _onCellChangedFn;
|
||||||
|
|
||||||
|
final List<SelectOptionPB> allOptions = [];
|
||||||
|
String filter = "";
|
||||||
|
|
||||||
void _dispatch() {
|
void _dispatch() {
|
||||||
on<SelectOptionCellEditorEvent>(
|
on<SelectOptionCellEditorEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.when(
|
await event.when(
|
||||||
didReceiveOptions: (options, selectedOptions) {
|
didReceiveOptions: (options, selectedOptions) {
|
||||||
final result = _makeOptions(state.filter, options);
|
final result = _getVisibleOptions(options);
|
||||||
|
allOptions
|
||||||
|
..clear()
|
||||||
|
..addAll(options);
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
allOptions: options,
|
|
||||||
options: result.options,
|
options: result.options,
|
||||||
createSelectOptionSuggestion:
|
createSelectOptionSuggestion:
|
||||||
result.createSelectOptionSuggestion,
|
result.createSelectOptionSuggestion,
|
||||||
@ -76,22 +82,19 @@ class SelectOptionCellEditorBloc
|
|||||||
if (state.createSelectOptionSuggestion == null) {
|
if (state.createSelectOptionSuggestion == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
filter = "";
|
||||||
await _createOption(
|
await _createOption(
|
||||||
name: state.createSelectOptionSuggestion!.name,
|
name: state.createSelectOptionSuggestion!.name,
|
||||||
color: state.createSelectOptionSuggestion!.color,
|
color: state.createSelectOptionSuggestion!.color,
|
||||||
);
|
);
|
||||||
emit(
|
emit(state.copyWith(clearFilter: true));
|
||||||
state.copyWith(
|
|
||||||
filter: null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
deleteOption: (option) async {
|
deleteOption: (option) async {
|
||||||
await _deleteOption([option]);
|
await _deleteOption([option]);
|
||||||
},
|
},
|
||||||
deleteAllOptions: () async {
|
deleteAllOptions: () async {
|
||||||
if (state.allOptions.isNotEmpty) {
|
if (allOptions.isNotEmpty) {
|
||||||
await _deleteOption(state.allOptions);
|
await _deleteOption(allOptions);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateOption: (option) async {
|
updateOption: (option) async {
|
||||||
@ -99,27 +102,17 @@ class SelectOptionCellEditorBloc
|
|||||||
},
|
},
|
||||||
selectOption: (optionId) async {
|
selectOption: (optionId) async {
|
||||||
await _selectOptionService.select(optionIds: [optionId]);
|
await _selectOptionService.select(optionIds: [optionId]);
|
||||||
final selectedOption = [
|
|
||||||
...state.selectedOptions,
|
|
||||||
state.options.firstWhere(
|
|
||||||
(element) => element.id == optionId,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
emit(
|
|
||||||
state.copyWith(
|
|
||||||
selectedOptions: selectedOption,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
unSelectOption: (optionId) async {
|
unSelectOption: (optionId) async {
|
||||||
await _selectOptionService.unSelect(optionIds: [optionId]);
|
await _selectOptionService.unSelect(optionIds: [optionId]);
|
||||||
final selectedOptions = [...state.selectedOptions]
|
},
|
||||||
..removeWhere((e) => e.id == optionId);
|
unSelectLastOption: () async {
|
||||||
emit(
|
if (state.selectedOptions.isEmpty) {
|
||||||
state.copyWith(
|
return;
|
||||||
selectedOptions: selectedOptions,
|
}
|
||||||
),
|
final lastSelectedOptionId = state.selectedOptions.last.id;
|
||||||
);
|
await _selectOptionService
|
||||||
|
.unSelect(optionIds: [lastSelectedOptionId]);
|
||||||
},
|
},
|
||||||
submitTextField: () {
|
submitTextField: () {
|
||||||
_submitTextFieldValue(emit);
|
_submitTextFieldValue(emit);
|
||||||
@ -132,64 +125,31 @@ class SelectOptionCellEditorBloc
|
|||||||
},
|
},
|
||||||
reorderOption: (fromOptionId, toOptionId) {
|
reorderOption: (fromOptionId, toOptionId) {
|
||||||
final options = _typeOptionAction.reorderOption(
|
final options = _typeOptionAction.reorderOption(
|
||||||
state.allOptions,
|
allOptions,
|
||||||
fromOptionId,
|
fromOptionId,
|
||||||
toOptionId,
|
toOptionId,
|
||||||
);
|
);
|
||||||
final result = _makeOptions(state.filter, options);
|
allOptions
|
||||||
emit(
|
..clear()
|
||||||
state.copyWith(
|
..addAll(options);
|
||||||
allOptions: options,
|
final result = _getVisibleOptions(options);
|
||||||
options: result.options,
|
emit(state.copyWith(options: result.options));
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
filterOption: (optionName) {
|
filterOption: (filterText) {
|
||||||
_filterOption(optionName, emit);
|
_filterOption(filterText, emit);
|
||||||
},
|
},
|
||||||
focusPreviousOption: () {
|
focusPreviousOption: () {
|
||||||
if (state.options.isEmpty) {
|
_focusOption(true, emit);
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (state.focusedOptionId == null) {
|
|
||||||
emit(state.copyWith(focusedOptionId: state.options.last.id));
|
|
||||||
} else {
|
|
||||||
final currentIndex = state.options
|
|
||||||
.indexWhere((option) => option.id == state.focusedOptionId);
|
|
||||||
|
|
||||||
if (currentIndex != -1) {
|
|
||||||
final newIndex = (currentIndex - 1) % state.options.length;
|
|
||||||
emit(
|
|
||||||
state.copyWith(
|
|
||||||
focusedOptionId: state.options[newIndex].id,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
focusNextOption: () {
|
focusNextOption: () {
|
||||||
if (state.options.isEmpty) {
|
_focusOption(false, emit);
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (state.focusedOptionId == null) {
|
|
||||||
emit(state.copyWith(focusedOptionId: state.options.first.id));
|
|
||||||
} else {
|
|
||||||
final currentIndex = state.options
|
|
||||||
.indexWhere((option) => option.id == state.focusedOptionId);
|
|
||||||
|
|
||||||
if (currentIndex != -1) {
|
|
||||||
final newIndex = (currentIndex + 1) % state.options.length;
|
|
||||||
emit(
|
|
||||||
state.copyWith(
|
|
||||||
focusedOptionId: state.options[newIndex].id,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
updateFocusedOption: (optionId) {
|
updateFocusedOption: (optionId) {
|
||||||
emit(state.copyWith(focusedOptionId: optionId));
|
emit(state.copyWith(focusedOptionId: optionId));
|
||||||
},
|
},
|
||||||
|
resetClearFilterFlag: () {
|
||||||
|
emit(state.copyWith(clearFilter: false));
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -233,59 +193,57 @@ class SelectOptionCellEditorBloc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final optionId = state.focusedOptionId!;
|
final focusedOptionId = state.focusedOptionId!;
|
||||||
|
|
||||||
if (optionId == createSelectOptionSuggestionId) {
|
if (focusedOptionId == createSelectOptionSuggestionId) {
|
||||||
|
filter = "";
|
||||||
_createOption(
|
_createOption(
|
||||||
name: state.createSelectOptionSuggestion!.name,
|
name: state.createSelectOptionSuggestion!.name,
|
||||||
color: state.createSelectOptionSuggestion!.color,
|
color: state.createSelectOptionSuggestion!.color,
|
||||||
);
|
);
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
filter: null,
|
|
||||||
createSelectOptionSuggestion: null,
|
createSelectOptionSuggestion: null,
|
||||||
|
clearFilter: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else if (!state.selectedOptions.any((option) => option.id == optionId)) {
|
} else if (!state.selectedOptions
|
||||||
_selectOptionService.select(optionIds: [optionId]);
|
.any((option) => option.id == focusedOptionId)) {
|
||||||
|
_selectOptionService.select(optionIds: [focusedOptionId]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _selectMultipleOptions(List<String> optionNames) {
|
void _selectMultipleOptions(List<String> optionNames) {
|
||||||
// The options are unordered. So in order to keep the inserted [optionNames]
|
final optionIds = optionNames
|
||||||
// order, it needs to get the option id in the [optionNames] order.
|
.map(
|
||||||
final lowerCaseNames = optionNames.map((e) => e.toLowerCase());
|
(name) => allOptions.firstWhereOrNull(
|
||||||
final Map<String, String> optionIdsMap = {};
|
(option) => option.name.toLowerCase() == name.toLowerCase(),
|
||||||
for (final option in state.options) {
|
),
|
||||||
optionIdsMap[option.name.toLowerCase()] = option.id;
|
)
|
||||||
}
|
.nonNulls
|
||||||
|
.map((option) => option.id)
|
||||||
final optionIds = lowerCaseNames
|
|
||||||
.where((name) => optionIdsMap[name] != null)
|
|
||||||
.map((name) => optionIdsMap[name]!)
|
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
_selectOptionService.select(optionIds: optionIds);
|
_selectOptionService.select(optionIds: optionIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _filterOption(
|
void _filterOption(
|
||||||
String optionName,
|
String filterText,
|
||||||
Emitter<SelectOptionCellEditorState> emit,
|
Emitter<SelectOptionCellEditorState> emit,
|
||||||
) {
|
) {
|
||||||
final _MakeOptionResult result = _makeOptions(
|
filter = filterText;
|
||||||
optionName,
|
final _MakeOptionResult result = _getVisibleOptions(
|
||||||
state.allOptions,
|
allOptions,
|
||||||
);
|
);
|
||||||
final focusedOptionId = result.options.isEmpty
|
final focusedOptionId = result.options.isEmpty
|
||||||
? result.createSelectOptionSuggestion == null
|
? result.createSelectOptionSuggestion == null
|
||||||
? null
|
? null
|
||||||
: createSelectOptionSuggestionId
|
: createSelectOptionSuggestionId
|
||||||
: result.options.length != state.options.length
|
: result.options.any((option) => option.id == state.focusedOptionId)
|
||||||
? result.options.first.id
|
? state.focusedOptionId
|
||||||
: state.focusedOptionId;
|
: result.options.first.id;
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
filter: optionName,
|
|
||||||
options: result.options,
|
options: result.options,
|
||||||
createSelectOptionSuggestion: result.createSelectOptionSuggestion,
|
createSelectOptionSuggestion: result.createSelectOptionSuggestion,
|
||||||
focusedOptionId: focusedOptionId,
|
focusedOptionId: focusedOptionId,
|
||||||
@ -314,39 +272,66 @@ class SelectOptionCellEditorBloc
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_MakeOptionResult _makeOptions(
|
_MakeOptionResult _getVisibleOptions(
|
||||||
String? filter,
|
|
||||||
List<SelectOptionPB> allOptions,
|
List<SelectOptionPB> allOptions,
|
||||||
) {
|
) {
|
||||||
final List<SelectOptionPB> options = List.from(allOptions);
|
final List<SelectOptionPB> options = List.from(allOptions);
|
||||||
String? newOptionName = filter;
|
String newOptionName = filter;
|
||||||
|
|
||||||
if (filter != null && filter.isNotEmpty) {
|
if (filter.isNotEmpty) {
|
||||||
options.retainWhere((option) {
|
options.retainWhere((option) {
|
||||||
final name = option.name.toLowerCase();
|
final name = option.name.toLowerCase();
|
||||||
final lFilter = filter.toLowerCase();
|
final lFilter = filter.toLowerCase();
|
||||||
|
|
||||||
if (name == lFilter) {
|
if (name == lFilter) {
|
||||||
newOptionName = null;
|
newOptionName = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return name.contains(lFilter);
|
return name.contains(lFilter);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
newOptionName = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _MakeOptionResult(
|
return _MakeOptionResult(
|
||||||
options: options,
|
options: options,
|
||||||
createSelectOptionSuggestion: newOptionName != null
|
createSelectOptionSuggestion: newOptionName.isEmpty
|
||||||
? CreateSelectOptionSuggestion(
|
? null
|
||||||
name: newOptionName!,
|
: CreateSelectOptionSuggestion(
|
||||||
|
name: newOptionName,
|
||||||
color: newSelectOptionColor(allOptions),
|
color: newSelectOptionColor(allOptions),
|
||||||
)
|
),
|
||||||
: null,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _focusOption(bool previous, Emitter<SelectOptionCellEditorState> emit) {
|
||||||
|
if (state.options.isEmpty && state.createSelectOptionSuggestion == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final optionIds = [
|
||||||
|
...state.options.map((e) => e.id),
|
||||||
|
if (state.createSelectOptionSuggestion != null)
|
||||||
|
createSelectOptionSuggestionId,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (state.focusedOptionId == null) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
focusedOptionId: previous ? optionIds.last : optionIds.first,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final currentIndex =
|
||||||
|
optionIds.indexWhere((id) => id == state.focusedOptionId);
|
||||||
|
|
||||||
|
final newIndex = currentIndex == -1
|
||||||
|
? 0
|
||||||
|
: (currentIndex + (previous ? -1 : 1)) % optionIds.length;
|
||||||
|
|
||||||
|
emit(state.copyWith(focusedOptionId: optionIds[newIndex]));
|
||||||
|
}
|
||||||
|
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
_onCellChangedFn = cellController.addListener(
|
_onCellChangedFn = cellController.addListener(
|
||||||
onCellChanged: (selectOptionContext) {
|
onCellChanged: (selectOptionContext) {
|
||||||
@ -370,6 +355,8 @@ class SelectOptionCellEditorEvent with _$SelectOptionCellEditorEvent {
|
|||||||
_SelectOption;
|
_SelectOption;
|
||||||
const factory SelectOptionCellEditorEvent.unSelectOption(String optionId) =
|
const factory SelectOptionCellEditorEvent.unSelectOption(String optionId) =
|
||||||
_UnSelectOption;
|
_UnSelectOption;
|
||||||
|
const factory SelectOptionCellEditorEvent.unSelectLastOption() =
|
||||||
|
_UnSelectLastOption;
|
||||||
const factory SelectOptionCellEditorEvent.updateOption(
|
const factory SelectOptionCellEditorEvent.updateOption(
|
||||||
SelectOptionPB option,
|
SelectOptionPB option,
|
||||||
) = _UpdateOption;
|
) = _UpdateOption;
|
||||||
@ -382,7 +369,7 @@ class SelectOptionCellEditorEvent with _$SelectOptionCellEditorEvent {
|
|||||||
String fromOptionId,
|
String fromOptionId,
|
||||||
String toOptionId,
|
String toOptionId,
|
||||||
) = _ReorderOption;
|
) = _ReorderOption;
|
||||||
const factory SelectOptionCellEditorEvent.filterOption(String optionName) =
|
const factory SelectOptionCellEditorEvent.filterOption(String filterText) =
|
||||||
_SelectOptionFilter;
|
_SelectOptionFilter;
|
||||||
const factory SelectOptionCellEditorEvent.submitTextField() =
|
const factory SelectOptionCellEditorEvent.submitTextField() =
|
||||||
_SubmitTextField;
|
_SubmitTextField;
|
||||||
@ -397,17 +384,18 @@ class SelectOptionCellEditorEvent with _$SelectOptionCellEditorEvent {
|
|||||||
const factory SelectOptionCellEditorEvent.updateFocusedOption(
|
const factory SelectOptionCellEditorEvent.updateFocusedOption(
|
||||||
String? optionId,
|
String? optionId,
|
||||||
) = _UpdateFocusedOption;
|
) = _UpdateFocusedOption;
|
||||||
|
const factory SelectOptionCellEditorEvent.resetClearFilterFlag() =
|
||||||
|
_ResetClearFilterFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class SelectOptionCellEditorState with _$SelectOptionCellEditorState {
|
class SelectOptionCellEditorState with _$SelectOptionCellEditorState {
|
||||||
const factory SelectOptionCellEditorState({
|
const factory SelectOptionCellEditorState({
|
||||||
required List<SelectOptionPB> options,
|
required List<SelectOptionPB> options,
|
||||||
required List<SelectOptionPB> allOptions,
|
|
||||||
required List<SelectOptionPB> selectedOptions,
|
required List<SelectOptionPB> selectedOptions,
|
||||||
required CreateSelectOptionSuggestion? createSelectOptionSuggestion,
|
required CreateSelectOptionSuggestion? createSelectOptionSuggestion,
|
||||||
required String? filter,
|
|
||||||
required String? focusedOptionId,
|
required String? focusedOptionId,
|
||||||
|
required bool clearFilter,
|
||||||
}) = _SelectOptionEditorState;
|
}) = _SelectOptionEditorState;
|
||||||
|
|
||||||
factory SelectOptionCellEditorState.initial(
|
factory SelectOptionCellEditorState.initial(
|
||||||
@ -416,11 +404,10 @@ class SelectOptionCellEditorState with _$SelectOptionCellEditorState {
|
|||||||
final data = context.getCellData(loadIfNotExist: false);
|
final data = context.getCellData(loadIfNotExist: false);
|
||||||
return SelectOptionCellEditorState(
|
return SelectOptionCellEditorState(
|
||||||
options: data?.options ?? [],
|
options: data?.options ?? [],
|
||||||
allOptions: data?.options ?? [],
|
|
||||||
selectedOptions: data?.selectOptions ?? [],
|
selectedOptions: data?.selectOptions ?? [],
|
||||||
createSelectOptionSuggestion: null,
|
createSelectOptionSuggestion: null,
|
||||||
filter: null,
|
|
||||||
focusedOptionId: null,
|
focusedOptionId: null,
|
||||||
|
clearFilter: false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ class SelectOptionFilterListBloc<T>
|
|||||||
emit: emit,
|
emit: emit,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
unselectOption: (option) {
|
unSelectOption: (option) {
|
||||||
final selectedOptionIds = Set<String>.from(state.selectedOptionIds);
|
final selectedOptionIds = Set<String>.from(state.selectedOptionIds);
|
||||||
selectedOptionIds.remove(option.id);
|
selectedOptionIds.remove(option.id);
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ class SelectOptionFilterListEvent with _$SelectOptionFilterListEvent {
|
|||||||
SelectOptionPB option,
|
SelectOptionPB option,
|
||||||
SelectOptionFilterConditionPB condition,
|
SelectOptionFilterConditionPB condition,
|
||||||
) = _SelectOption;
|
) = _SelectOption;
|
||||||
const factory SelectOptionFilterListEvent.unselectOption(
|
const factory SelectOptionFilterListEvent.unSelectOption(
|
||||||
SelectOptionPB option,
|
SelectOptionPB option,
|
||||||
) = _UnSelectOption;
|
) = _UnSelectOption;
|
||||||
const factory SelectOptionFilterListEvent.didReceiveOptions(
|
const factory SelectOptionFilterListEvent.didReceiveOptions(
|
||||||
|
@ -89,7 +89,7 @@ class _SelectOptionFilterCellState extends State<SelectOptionFilterCell> {
|
|||||||
if (widget.isSelected) {
|
if (widget.isSelected) {
|
||||||
context
|
context
|
||||||
.read<SelectOptionFilterListBloc>()
|
.read<SelectOptionFilterListBloc>()
|
||||||
.add(SelectOptionFilterListEvent.unselectOption(widget.option));
|
.add(SelectOptionFilterListEvent.unSelectOption(widget.option));
|
||||||
} else {
|
} else {
|
||||||
context.read<SelectOptionFilterListBloc>().add(
|
context.read<SelectOptionFilterListBloc>().add(
|
||||||
SelectOptionFilterListEvent.selectOption(
|
SelectOptionFilterListEvent.selectOption(
|
||||||
|
@ -45,21 +45,20 @@ class _SelectOptionCellEditorState extends State<SelectOptionCellEditor> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
focusNode = FocusNode(
|
focusNode = FocusNode(
|
||||||
onKeyEvent: (node, event) {
|
onKeyEvent: (node, event) {
|
||||||
if (event is KeyUpEvent) {
|
|
||||||
return KeyEventResult.ignored;
|
|
||||||
}
|
|
||||||
switch (event.logicalKey) {
|
switch (event.logicalKey) {
|
||||||
case LogicalKeyboardKey.arrowUp:
|
case LogicalKeyboardKey.arrowUp when event is! KeyUpEvent:
|
||||||
if (textEditingController.value.composing.isCollapsed) {
|
if (textEditingController.value.composing.isCollapsed) {
|
||||||
bloc.add(const SelectOptionCellEditorEvent.focusPreviousOption());
|
bloc.add(const SelectOptionCellEditorEvent.focusPreviousOption());
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.handled;
|
||||||
}
|
}
|
||||||
case LogicalKeyboardKey.arrowDown:
|
break;
|
||||||
|
case LogicalKeyboardKey.arrowDown when event is! KeyUpEvent:
|
||||||
if (textEditingController.value.composing.isCollapsed) {
|
if (textEditingController.value.composing.isCollapsed) {
|
||||||
bloc.add(const SelectOptionCellEditorEvent.focusNextOption());
|
bloc.add(const SelectOptionCellEditorEvent.focusNextOption());
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.handled;
|
||||||
}
|
}
|
||||||
case LogicalKeyboardKey.escape:
|
break;
|
||||||
|
case LogicalKeyboardKey.escape when event is! KeyUpEvent:
|
||||||
if (!textEditingController.value.composing.isCollapsed) {
|
if (!textEditingController.value.composing.isCollapsed) {
|
||||||
final end = textEditingController.value.composing.end;
|
final end = textEditingController.value.composing.end;
|
||||||
final text = textEditingController.text;
|
final text = textEditingController.text;
|
||||||
@ -70,6 +69,13 @@ class _SelectOptionCellEditorState extends State<SelectOptionCellEditor> {
|
|||||||
);
|
);
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.handled;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case LogicalKeyboardKey.backspace when event is KeyUpEvent:
|
||||||
|
if (!textEditingController.text.isNotEmpty) {
|
||||||
|
bloc.add(const SelectOptionCellEditorEvent.unSelectLastOption());
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return KeyEventResult.ignored;
|
return KeyEventResult.ignored;
|
||||||
},
|
},
|
||||||
@ -126,7 +132,18 @@ class _OptionList extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<SelectOptionCellEditorBloc, SelectOptionCellEditorState>(
|
return BlocConsumer<SelectOptionCellEditorBloc,
|
||||||
|
SelectOptionCellEditorState>(
|
||||||
|
listenWhen: (previous, current) =>
|
||||||
|
previous.clearFilter != current.clearFilter,
|
||||||
|
listener: (context, state) {
|
||||||
|
if (state.clearFilter) {
|
||||||
|
textEditingController.clear();
|
||||||
|
context
|
||||||
|
.read<SelectOptionCellEditorBloc>()
|
||||||
|
.add(const SelectOptionCellEditorEvent.resetClearFilterFlag());
|
||||||
|
}
|
||||||
|
},
|
||||||
buildWhen: (previous, current) =>
|
buildWhen: (previous, current) =>
|
||||||
!listEquals(previous.options, current.options) ||
|
!listEquals(previous.options, current.options) ||
|
||||||
previous.createSelectOptionSuggestion !=
|
previous.createSelectOptionSuggestion !=
|
||||||
@ -231,7 +248,6 @@ class _TextField extends StatelessWidget {
|
|||||||
context
|
context
|
||||||
.read<SelectOptionCellEditorBloc>()
|
.read<SelectOptionCellEditorBloc>()
|
||||||
.add(const SelectOptionCellEditorEvent.submitTextField());
|
.add(const SelectOptionCellEditorEvent.submitTextField());
|
||||||
textEditingController.clear();
|
|
||||||
focusNode.requestFocus();
|
focusNode.requestFocus();
|
||||||
},
|
},
|
||||||
onPaste: (tagNames, remainder) {
|
onPaste: (tagNames, remainder) {
|
||||||
|
@ -184,7 +184,7 @@ void main() {
|
|||||||
|
|
||||||
assert(bloc.state.selectedOptions.length == 1);
|
assert(bloc.state.selectedOptions.length == 1);
|
||||||
expect(bloc.state.selectedOptions[0].name, "A");
|
expect(bloc.state.selectedOptions[0].name, "A");
|
||||||
expect(bloc.state.filter, "x");
|
expect(bloc.filter, "x");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('filter options', () async {
|
test('filter options', () async {
|
||||||
@ -234,12 +234,12 @@ void main() {
|
|||||||
reason: "Options: ${bloc.state.options}",
|
reason: "Options: ${bloc.state.options}",
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
bloc.state.allOptions.length,
|
bloc.allOptions.length,
|
||||||
3,
|
3,
|
||||||
reason: "Options: ${bloc.state.options}",
|
reason: "Options: ${bloc.state.options}",
|
||||||
);
|
);
|
||||||
expect(bloc.state.createSelectOptionSuggestion!.name, "a");
|
expect(bloc.state.createSelectOptionSuggestion!.name, "a");
|
||||||
expect(bloc.state.filter, "a");
|
expect(bloc.filter, "a");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user