feat: use commas to select a tag in multi-select grid cells (#1158)

* fix: comma to select tags

* chore: support passing multiple option ids

* chore: add more unit tests for single select and multi select

* chore: move to select multiple options using a single payload

* chore: do not unselect the option if insert option ids contain that option

Co-authored-by: appflowy <annie@appflowy.io>
This commit is contained in:
Richard Shiue
2022-10-11 13:43:29 +08:00
committed by GitHub
parent d80a67bdda
commit 295b887cf1
17 changed files with 382 additions and 213 deletions

View File

@ -149,6 +149,7 @@ class _TextField extends StatelessWidget {
distanceToText: _editorPanelWidth * 0.7,
maxLength: 30,
tagController: _tagController,
textSeparators: const [','],
onClick: () => popoverMutex.close(),
newText: (text) {
context
@ -160,6 +161,14 @@ class _TextField extends StatelessWidget {
.read<SelectOptionCellEditorBloc>()
.add(SelectOptionEditorEvent.trySelectOption(tagName));
},
onPaste: (tagNames, remainder) {
context
.read<SelectOptionCellEditorBloc>()
.add(SelectOptionEditorEvent.selectMultipleOptions(
tagNames,
remainder,
));
},
),
);
},

View File

@ -17,9 +17,11 @@ class SelectOptionTextField extends StatefulWidget {
final List<SelectOptionPB> options;
final LinkedHashMap<String, SelectOptionPB> selectedOptionMap;
final double distanceToText;
final List<String> textSeparators;
final Function(String) onSubmitted;
final Function(String) newText;
final Function(List<String>, String) onPaste;
final VoidCallback? onClick;
final int? maxLength;
@ -29,7 +31,9 @@ class SelectOptionTextField extends StatefulWidget {
required this.distanceToText,
required this.tagController,
required this.onSubmitted,
required this.onPaste,
required this.newText,
required this.textSeparators,
this.onClick,
this.maxLength,
TextEditingController? textController,
@ -65,7 +69,7 @@ class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
textfieldTagsController: widget.tagController,
initialTags: widget.selectedOptionMap.keys.toList(),
focusNode: focusNode,
textSeparators: const [','],
textSeparators: widget.textSeparators,
inputfieldBuilder: (
BuildContext context,
editController,
@ -83,7 +87,7 @@ class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
if (onChanged != null) {
onChanged(text);
}
widget.newText(text);
_newText(text, editController);
},
onSubmitted: (text) {
if (onSubmitted != null) {
@ -121,6 +125,40 @@ class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
);
}
void _newText(String text, TextEditingController editingController) {
if (text.isEmpty) {
widget.newText('');
return;
}
final trimmedText = text.trim();
List<String> splits = [];
String currentString = '';
// split the string into tokens
for (final char in trimmedText.split('')) {
if (!widget.textSeparators.contains(char)) {
currentString += char;
continue;
}
if (currentString.isNotEmpty) {
splits.add(currentString);
}
currentString = '';
}
// add the remainder (might be '')
splits.add(currentString);
final submittedOptions =
splits.sublist(0, splits.length - 1).map((e) => e.trim()).toList();
final remainder = splits.elementAt(splits.length - 1).trimLeft();
editingController.text = remainder;
editingController.selection =
TextSelection.collapsed(offset: controller.text.length);
widget.onPaste(submittedOptions, remainder);
}
Widget? _renderTags(BuildContext context, ScrollController sc) {
if (widget.selectedOptionMap.isEmpty) {
return null;