From c2e8a12427ba231e375b02c20d897b6d439bd7b7 Mon Sep 17 00:00:00 2001 From: Mathias Mogensen <42929161+Xazin@users.noreply.github.com> Date: Thu, 1 Aug 2024 23:28:05 +0200 Subject: [PATCH] fix: select option chip size (#5859) --- .../bloc/select_option_cell_editor_bloc.dart | 19 +- .../domain/select_option_cell_service.dart | 2 +- .../mobile_select_option_editor.dart | 5 +- .../select_option_cell_editor.dart | 232 ++++++++---------- .../src/flowy_overlay/appflowy_popover.dart | 5 +- .../cell/select_option_cell_test.dart | 2 +- 6 files changed, 126 insertions(+), 139 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/cell/bloc/select_option_cell_editor_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/application/cell/bloc/select_option_cell_editor_bloc.dart index c0bfa48a85..f8ed915b62 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/cell/bloc/select_option_cell_editor_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/cell/bloc/select_option_cell_editor_bloc.dart @@ -1,5 +1,7 @@ import 'dart:async'; +import 'package:flutter/widgets.dart'; + import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart'; import 'package:appflowy/plugins/database/application/field/field_info.dart'; import 'package:appflowy/plugins/database/application/field/type_option/select_type_option_actions.dart'; @@ -9,7 +11,6 @@ import 'package:appflowy/plugins/database/domain/select_option_cell_service.dart import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:collection/collection.dart'; -import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -109,16 +110,16 @@ class SelectOptionCellEditorBloc selectOption: (optionId) async { await _selectOptionService.select(optionIds: [optionId]); }, - unSelectOption: (optionId) async { - await _selectOptionService.unSelect(optionIds: [optionId]); + unselectOption: (optionId) async { + await _selectOptionService.unselect(optionIds: [optionId]); }, - unSelectLastOption: () async { + unselectLastOption: () async { if (state.selectedOptions.isEmpty) { return; } final lastSelectedOptionId = state.selectedOptions.last.id; await _selectOptionService - .unSelect(optionIds: [lastSelectedOptionId]); + .unselect(optionIds: [lastSelectedOptionId]); }, submitTextField: () { _submitTextFieldValue(emit); @@ -353,10 +354,10 @@ class SelectOptionCellEditorEvent with _$SelectOptionCellEditorEvent { const factory SelectOptionCellEditorEvent.createOption() = _CreateOption; const factory SelectOptionCellEditorEvent.selectOption(String optionId) = _SelectOption; - const factory SelectOptionCellEditorEvent.unSelectOption(String optionId) = - _UnSelectOption; - const factory SelectOptionCellEditorEvent.unSelectLastOption() = - _UnSelectLastOption; + const factory SelectOptionCellEditorEvent.unselectOption(String optionId) = + _UnselectOption; + const factory SelectOptionCellEditorEvent.unselectLastOption() = + _UnselectLastOption; const factory SelectOptionCellEditorEvent.updateOption( SelectOptionPB option, ) = _UpdateOption; diff --git a/frontend/appflowy_flutter/lib/plugins/database/domain/select_option_cell_service.dart b/frontend/appflowy_flutter/lib/plugins/database/domain/select_option_cell_service.dart index 93db3c703d..2e0c24718e 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/domain/select_option_cell_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/domain/select_option_cell_service.dart @@ -70,7 +70,7 @@ class SelectOptionCellBackendService { return DatabaseEventUpdateSelectOptionCell(payload).send(); } - Future> unSelect({ + Future> unselect({ required Iterable optionIds, }) { final payload = SelectOptionCellChangesetPB() diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_select_option_editor.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_select_option_editor.dart index 3750a9294b..cba7194a99 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_select_option_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_select_option_editor.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/mobile/presentation/base/app_bar/app_bar_actions.dart'; @@ -12,7 +14,6 @@ import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum. import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import 'package:protobuf/protobuf.dart'; @@ -176,7 +177,7 @@ class _MobileSelectOptionEditorState extends State { } else { context .read() - .add(SelectOptionCellEditorEvent.unSelectOption(option.id)); + .add(SelectOptionCellEditorEvent.unselectOption(option.id)); } }, onMoreOptions: (option) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_cell_editor.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_cell_editor.dart index 8fdb99769a..8f6f14f714 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_cell_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_cell_editor.dart @@ -1,6 +1,10 @@ import 'dart:collection'; import 'dart:io'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/application/cell/bloc/select_option_cell_editor_bloc.dart'; @@ -10,14 +14,11 @@ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import '../../grid/presentation/layout/sizes.dart'; import '../../grid/presentation/widgets/common/type_option_separator.dart'; import '../field/type_option_editor/select/select_option_editor.dart'; + import 'extension.dart'; import 'select_option_text_field.dart'; @@ -73,7 +74,7 @@ class _SelectOptionCellEditorState extends State { break; case LogicalKeyboardKey.backspace when event is KeyUpEvent: if (!textEditingController.text.isNotEmpty) { - bloc.add(const SelectOptionCellEditorEvent.unSelectLastOption()); + bloc.add(const SelectOptionCellEditorEvent.unselectLastOption()); return KeyEventResult.handled; } break; @@ -137,8 +138,7 @@ class _OptionList extends StatelessWidget { Widget build(BuildContext context) { return BlocConsumer( - listenWhen: (previous, current) => - previous.clearFilter != current.clearFilter, + listenWhen: (prev, curr) => prev.clearFilter != curr.clearFilter, listener: (context, state) { if (state.clearFilter) { textEditingController.clear(); @@ -151,60 +151,66 @@ class _OptionList extends StatelessWidget { !listEquals(previous.options, current.options) || previous.createSelectOptionSuggestion != current.createSelectOptionSuggestion, - builder: (context, state) { - return ReorderableListView.builder( - shrinkWrap: true, - proxyDecorator: (child, index, _) => Material( - color: Colors.transparent, - child: Stack( - children: [ - BlocProvider.value( - value: context.read(), - child: child, - ), - MouseRegion( - cursor: Platform.isWindows - ? SystemMouseCursors.click - : SystemMouseCursors.grabbing, - child: const SizedBox.expand(), - ), - ], - ), + builder: (context, state) => ReorderableListView.builder( + shrinkWrap: true, + proxyDecorator: (child, index, _) => Material( + color: Colors.transparent, + child: Stack( + children: [ + BlocProvider.value( + value: context.read(), + child: child, + ), + MouseRegion( + cursor: Platform.isWindows + ? SystemMouseCursors.click + : SystemMouseCursors.grabbing, + child: const SizedBox.expand(), + ), + ], ), - buildDefaultDragHandles: false, - itemCount: state.options.length, - onReorderStart: (_) => popoverMutex.close(), - itemBuilder: (_, int index) { - final option = state.options[index]; - return _SelectOptionCell( - key: ValueKey("select_cell_option_list_${option.id}"), - index: index, - option: option, - popoverMutex: popoverMutex, - ); - }, - onReorder: (oldIndex, newIndex) { - if (oldIndex < newIndex) { - newIndex--; - } - final fromOptionId = state.options[oldIndex].id; - final toOptionId = state.options[newIndex].id; - context.read().add( - SelectOptionCellEditorEvent.reorderOption( - fromOptionId, - toOptionId, - ), - ); - }, - header: const _Title(), - footer: state.createSelectOptionSuggestion == null - ? null - : _CreateOptionCell( - suggestion: state.createSelectOptionSuggestion!, + ), + buildDefaultDragHandles: false, + itemCount: state.options.length, + onReorderStart: (_) => popoverMutex.close(), + itemBuilder: (_, int index) { + final option = state.options[index]; + return _SelectOptionCell( + key: ValueKey("select_cell_option_list_${option.id}"), + index: index, + option: option, + popoverMutex: popoverMutex, + ); + }, + onReorder: (oldIndex, newIndex) { + if (oldIndex < newIndex) { + newIndex--; + } + final fromOptionId = state.options[oldIndex].id; + final toOptionId = state.options[newIndex].id; + context.read().add( + SelectOptionCellEditorEvent.reorderOption( + fromOptionId, + toOptionId, ), - padding: const EdgeInsets.symmetric(vertical: 8.0), - ); - }, + ); + }, + header: Padding( + padding: EdgeInsets.only( + bottom: state.createSelectOptionSuggestion != null || + state.options.isNotEmpty + ? 12 + : 0, + ), + child: const _Title(), + ), + footer: state.createSelectOptionSuggestion != null + ? _CreateOptionCell( + suggestion: state.createSelectOptionSuggestion!, + ) + : null, + padding: const EdgeInsets.symmetric(vertical: 8), + ), ); } } @@ -245,11 +251,9 @@ class _TextField extends StatelessWidget { scrollController: scrollController, textSeparators: const [','], onClick: () => popoverMutex.close(), - newText: (text) { - context - .read() - .add(SelectOptionCellEditorEvent.filterOption(text)); - }, + newText: (text) => context + .read() + .add(SelectOptionCellEditorEvent.filterOption(text)), onSubmitted: () { context .read() @@ -264,13 +268,12 @@ class _TextField extends StatelessWidget { ), ); }, - onRemove: (optionName) { - context.read().add( - SelectOptionCellEditorEvent.unSelectOption( - optionMap[optionName]!.id, + onRemove: (name) => + context.read().add( + SelectOptionCellEditorEvent.unselectOption( + optionMap[name]!.id, + ), ), - ); - }, ), ), ); @@ -286,12 +289,9 @@ class _Title extends StatelessWidget { Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: SizedBox( - height: GridSize.popoverItemHeight, - child: FlowyText.regular( - LocaleKeys.grid_selectOption_panelTitle.tr(), - color: Theme.of(context).hintColor, - ), + child: FlowyText.regular( + LocaleKeys.grid_selectOption_panelTitle.tr(), + color: Theme.of(context).hintColor, ), ); } @@ -326,16 +326,27 @@ class _SelectOptionCellState extends State<_SelectOptionCell> { constraints: BoxConstraints.loose(const Size(200, 470)), mutex: widget.popoverMutex, clickHandler: PopoverClickHandler.gestureDetector, + popupBuilder: (popoverContext) => SelectOptionEditor( + key: ValueKey(widget.option.id), + option: widget.option, + onDeleted: () { + context + .read() + .add(SelectOptionCellEditorEvent.deleteOption(widget.option)); + PopoverContainer.of(popoverContext).close(); + }, + onUpdated: (updatedOption) => context + .read() + .add(SelectOptionCellEditorEvent.updateOption(updatedOption)), + ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 2.0), child: MouseRegion( - onEnter: (_) { - context.read().add( - SelectOptionCellEditorEvent.updateFocusedOption( - widget.option.id, - ), - ); - }, + onEnter: (_) => context.read().add( + SelectOptionCellEditorEvent.updateFocusedOption( + widget.option.id, + ), + ), child: Container( height: 28, decoration: BoxDecoration( @@ -382,42 +393,16 @@ class _SelectOptionCellState extends State<_SelectOptionCell> { ), ), ), - popupBuilder: (BuildContext popoverContext) { - return SelectOptionEditor( - option: widget.option, - onDeleted: () { - context - .read() - .add(SelectOptionCellEditorEvent.deleteOption(widget.option)); - PopoverContainer.of(popoverContext).close(); - }, - onUpdated: (updatedOption) { - context - .read() - .add(SelectOptionCellEditorEvent.updateOption(updatedOption)); - }, - key: ValueKey( - widget.option.id, - ), // Use ValueKey to refresh the UI, otherwise, it will remain the old value. - ); - }, ); } void _onTap() { widget.popoverMutex.close(); - if (context - .read() - .state - .selectedOptions - .contains(widget.option)) { - context - .read() - .add(SelectOptionCellEditorEvent.unSelectOption(widget.option.id)); + final bloc = context.read(); + if (bloc.state.selectedOptions.contains(widget.option)) { + bloc.add(SelectOptionCellEditorEvent.unselectOption(widget.option.id)); } else { - context - .read() - .add(SelectOptionCellEditorEvent.selectOption(widget.option.id)); + bloc.add(SelectOptionCellEditorEvent.selectOption(widget.option.id)); } } } @@ -472,13 +457,14 @@ class SelectOptionTagCell extends StatelessWidget { child: Align( alignment: AlignmentDirectional.centerStart, child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 6.0, - ), + padding: const EdgeInsets.symmetric(horizontal: 6.0), child: SelectOptionTag( + fontSize: 14, option: option, - padding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 2, + ), ), ), ), @@ -492,16 +478,14 @@ class SelectOptionTagCell extends StatelessWidget { } class _CreateOptionCell extends StatelessWidget { - const _CreateOptionCell({ - required this.suggestion, - }); + const _CreateOptionCell({required this.suggestion}); final CreateSelectOptionSuggestion suggestion; @override Widget build(BuildContext context) { return Container( - height: 28, + height: 32, margin: const EdgeInsets.symmetric(horizontal: 8.0), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( @@ -537,10 +521,10 @@ class _CreateOptionCell extends StatelessWidget { child: SelectOptionTag( name: suggestion.name, color: suggestion.color.toColor(context), - fontSize: 11, + fontSize: 14, padding: const EdgeInsets.symmetric( horizontal: 8, - vertical: 1, + vertical: 2, ), ), ), diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_popover.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_popover.dart index 0564fc2a2f..035f41f359 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_popover.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/appflowy_popover.dart @@ -1,6 +1,7 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/colorscheme/default_colorscheme.dart'; -import 'package:flutter/material.dart'; class AppFlowyPopover extends StatelessWidget { final Widget child; @@ -152,7 +153,7 @@ extension on BuildContext { side: BorderSide( width: 1, strokeAlign: BorderSide.strokeAlignOutside, - color: borderColor, + color: color != Colors.transparent ? borderColor : color!, ), borderRadius: borderRadius ?? BorderRadius.circular(10), ), diff --git a/frontend/appflowy_flutter/test/bloc_test/grid_test/cell/select_option_cell_test.dart b/frontend/appflowy_flutter/test/bloc_test/grid_test/cell/select_option_cell_test.dart index cb5a652c7c..fa2e6fb71c 100644 --- a/frontend/appflowy_flutter/test/bloc_test/grid_test/cell/select_option_cell_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/grid_test/cell/select_option_cell_test.dart @@ -123,7 +123,7 @@ void main() { await gridResponseFuture(); final optionId = bloc.state.options[0].id; - bloc.add(SelectOptionCellEditorEvent.unSelectOption(optionId)); + bloc.add(SelectOptionCellEditorEvent.unselectOption(optionId)); await gridResponseFuture(); assert(bloc.state.selectedOptions.isEmpty);