diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart index cb734c60d6..3254368086 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart @@ -96,7 +96,10 @@ class SelectOptionEditorBloc extends Bloc _makeOptions(String filter, List allOptions) { final List options = List.from(allOptions); - options.retainWhere((option) => option.name.contains(filter)); + if (filter.isNotEmpty) { + options.retainWhere((option) => option.name.toLowerCase().contains(filter.toLowerCase())); + } + return options; } diff --git a/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_format_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_format_bloc.dart new file mode 100644 index 0000000000..74f1531ce3 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_format_bloc.dart @@ -0,0 +1,142 @@ +import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'dart:async'; +part 'number_format_bloc.freezed.dart'; + +class NumberFormatBloc extends Bloc { + NumberFormatBloc() : super(NumberFormatState.initial()) { + on( + (event, emit) async { + event.map(setFilter: (_SetFilter value) { + final List formats = List.from(NumberFormat.values); + if (value.filter.isNotEmpty) { + formats.retainWhere((element) => element.title().toLowerCase().contains(value.filter.toLowerCase())); + } + emit(state.copyWith(formats: formats, filter: value.filter)); + }); + }, + ); + } + + @override + Future close() async { + return super.close(); + } +} + +@freezed +class NumberFormatEvent with _$NumberFormatEvent { + const factory NumberFormatEvent.setFilter(String filter) = _SetFilter; +} + +@freezed +class NumberFormatState with _$NumberFormatState { + const factory NumberFormatState({ + required List formats, + required String filter, + }) = _NumberFormatState; + + factory NumberFormatState.initial() { + return const NumberFormatState( + formats: NumberFormat.values, + filter: "", + ); + } +} + +extension NumberFormatExtension on NumberFormat { + String title() { + switch (this) { + case NumberFormat.ArgentinePeso: + return "Argentine peso"; + case NumberFormat.Baht: + return "Baht"; + case NumberFormat.CanadianDollar: + return "Canadian dollar"; + case NumberFormat.ChileanPeso: + return "Chilean peso"; + case NumberFormat.ColombianPeso: + return "Colombian peso"; + case NumberFormat.DanishKrone: + return "Danish krone"; + case NumberFormat.Dirham: + return "Dirham"; + case NumberFormat.EUR: + return "Euro"; + case NumberFormat.Forint: + return "Forint"; + case NumberFormat.Franc: + return "Franc"; + case NumberFormat.HongKongDollar: + return "Hone Kong dollar"; + case NumberFormat.Koruna: + return "Koruna"; + case NumberFormat.Krona: + return "Krona"; + case NumberFormat.Leu: + return "Leu"; + case NumberFormat.Lira: + return "Lira"; + case NumberFormat.MexicanPeso: + return "Mexican Peso"; + case NumberFormat.NewTaiwanDollar: + return "New Taiwan dollar"; + case NumberFormat.NewZealandDollar: + return "New Zealand dollar"; + case NumberFormat.NorwegianKrone: + return "Norwegian krone"; + case NumberFormat.Number: + return "Number"; + case NumberFormat.Percent: + return "Percent"; + case NumberFormat.PhilippinePeso: + return "Percent"; + case NumberFormat.Pound: + return "Pound"; + case NumberFormat.Rand: + return "Rand"; + case NumberFormat.Real: + return "Real"; + case NumberFormat.Ringgit: + return "Ringgit"; + case NumberFormat.Riyal: + return "Riyal"; + case NumberFormat.Ruble: + return "Ruble"; + case NumberFormat.Rupee: + return "Rupee"; + case NumberFormat.Rupiah: + return "Rupiah"; + case NumberFormat.Shekel: + return "Skekel"; + case NumberFormat.USD: + return "US Dollar"; + case NumberFormat.UruguayanPeso: + return "Uruguayan peso"; + case NumberFormat.Won: + return "Uruguayan peso"; + case NumberFormat.Yen: + return "Yen"; + case NumberFormat.Yuan: + return "Yuan"; + default: + throw UnimplementedError; + } + } + + // String iconName() { + // switch (this) { + // case NumberFormat.CNY: + // return "grid/field/yen"; + // case NumberFormat.EUR: + // return "grid/field/euro"; + // case NumberFormat.Number: + // return "grid/field/numbers"; + // case NumberFormat.USD: + // return "grid/field/us_dollar"; + // default: + // throw UnimplementedError; + // } + // } +} diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart index c7ec279f19..61e8e0151c 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/layout/sizes.dart @@ -12,7 +12,7 @@ class GridSize { static double get cellHPadding => 10 * scale; static double get cellVPadding => 10 * scale; static double get typeOptionItemHeight => 32 * scale; - static double get typeOptionSeparatorHeight => 6 * scale; + static double get typeOptionSeparatorHeight => 4 * scale; // static EdgeInsets get headerContentInsets => EdgeInsets.symmetric( diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart index 9fe4a67034..46d06e86cb 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart @@ -3,7 +3,7 @@ import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart'; import 'package:app_flowy/workspace/application/grid/cell/selection_editor_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart similarity index 70% rename from frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart rename to frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart index 12c1d4997b..5a06dbfd46 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart @@ -3,23 +3,25 @@ import 'package:flowy_infra_ui/widget/rounded_input_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -class NameTextField extends StatefulWidget { - final void Function(String) onDone; +class InputTextField extends StatefulWidget { + final void Function(String)? onDone; + final void Function(String)? onChanged; final void Function() onCanceled; - final String name; + final String text; - const NameTextField({ - required this.name, - required this.onDone, + const InputTextField({ + required this.text, + this.onDone, required this.onCanceled, + this.onChanged, Key? key, }) : super(key: key); @override - State createState() => _NameTextFieldState(); + State createState() => _InputTextFieldState(); } -class _NameTextFieldState extends State { +class _InputTextFieldState extends State { late FocusNode _focusNode; var isEdited = false; late TextEditingController _controller; @@ -27,7 +29,7 @@ class _NameTextFieldState extends State { @override void initState() { _focusNode = FocusNode(); - _controller = TextEditingController(text: widget.name); + _controller = TextEditingController(text: widget.text); _focusNode.addListener(notifyDidEndEditing); super.initState(); @@ -46,8 +48,15 @@ class _NameTextFieldState extends State { normalBorderColor: theme.shader4, focusBorderColor: theme.main1, cursorColor: theme.main1, + onChanged: (text) { + if (widget.onChanged != null) { + widget.onChanged!(text); + } + }, onEditingComplete: () { - widget.onDone(_controller.text); + if (widget.onDone != null) { + widget.onDone!(_controller.text); + } }, ); } @@ -64,7 +73,9 @@ class _NameTextFieldState extends State { if (_controller.text.isEmpty) { widget.onCanceled(); } else { - widget.onDone(_controller.text); + if (widget.onDone != null) { + widget.onDone!(_controller.text); + } } } } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart index 9e03c9bbb6..1a44f439e2 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart @@ -14,13 +14,11 @@ import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pbserver.dart import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; - import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/prelude.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_type_list.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/date.dart'; - import 'field_type_extension.dart'; import 'type_option/multi_select.dart'; import 'type_option/number.dart'; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart index f8805b7180..62c4eca7e5 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart @@ -1,7 +1,7 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/edit_select_option_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/extension.dart'; -import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; @@ -95,8 +95,8 @@ class _OptionNameTextField extends StatelessWidget { @override Widget build(BuildContext context) { - return NameTextField( - name: name, + return InputTextField( + text: name, onCanceled: () {}, onDone: (optionName) { if (name != optionName) { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart index 359d0427c9..5e85ba9474 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/field_option_pannel.dart @@ -1,5 +1,6 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -13,7 +14,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'edit_option_pannel.dart'; -import 'widget.dart'; class FieldSelectOptionPannel extends StatelessWidget { final List options; @@ -222,8 +222,8 @@ class _OptionNameTextField extends StatelessWidget { @override Widget build(BuildContext context) { - return NameTextField( - name: "", + return InputTextField( + text: "", onCanceled: () { context.read().add(const FieldOptionPannelEvent.endAddingOption()); }, diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart index bdcc887a03..591b54187f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart @@ -1,6 +1,8 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/workspace/application/grid/field/type_option/number_bloc.dart'; +import 'package:app_flowy/workspace/application/grid/field/type_option/number_format_bloc.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; +import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; @@ -67,7 +69,10 @@ class NumberTypeOptionWidget extends TypeOptionWidget { }, selectedFormat: state.typeOption.format, ); - overlayDelegate.showOverlay(context, list); + overlayDelegate.showOverlay( + context, + list, + ); }, rightIcon: svgWidget("grid/more", color: theme.iconColor), ); @@ -87,28 +92,42 @@ class NumberFormatList extends StatelessWidget { @override Widget build(BuildContext context) { - final cells = NumberFormat.values.map((format) { - return NumberFormatCell( - isSelected: format == selectedFormat, - format: format, - onSelected: (format) { - onSelected(format); - FlowyOverlay.of(context).remove(NumberFormatList.identifier()); - }); - }).toList(); + return BlocProvider( + create: (context) => NumberFormatBloc(), + child: SizedBox( + width: 180, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const _FilterTextField(), + BlocBuilder( + builder: (context, state) { + final cells = state.formats.map((format) { + return NumberFormatCell( + isSelected: format == selectedFormat, + format: format, + onSelected: (format) { + onSelected(format); + FlowyOverlay.of(context).remove(NumberFormatList.identifier()); + }); + }).toList(); - return SizedBox( - width: 180, - child: ListView.separated( - shrinkWrap: true, - controller: ScrollController(), - separatorBuilder: (context, index) { - return VSpace(GridSize.typeOptionSeparatorHeight); - }, - itemCount: cells.length, - itemBuilder: (BuildContext context, int index) { - return cells[index]; - }, + final list = ListView.separated( + shrinkWrap: true, + controller: ScrollController(), + separatorBuilder: (context, index) { + return VSpace(GridSize.typeOptionSeparatorHeight); + }, + itemCount: cells.length, + itemBuilder: (BuildContext context, int index) { + return cells[index]; + }, + ); + return Expanded(child: list); + }, + ), + ], + ), ), ); } @@ -149,98 +168,16 @@ class NumberFormatCell extends StatelessWidget { } } -extension NumberFormatExtension on NumberFormat { - String title() { - switch (this) { - case NumberFormat.ArgentinePeso: - return "Argentine peso"; - case NumberFormat.Baht: - return "Baht"; - case NumberFormat.CanadianDollar: - return "Canadian dollar"; - case NumberFormat.ChileanPeso: - return "Chilean peso"; - case NumberFormat.ColombianPeso: - return "Colombian peso"; - case NumberFormat.DanishKrone: - return "Danish krone"; - case NumberFormat.Dirham: - return "Dirham"; - case NumberFormat.EUR: - return "Euro"; - case NumberFormat.Forint: - return "Forint"; - case NumberFormat.Franc: - return "Franc"; - case NumberFormat.HongKongDollar: - return "Hone Kong dollar"; - case NumberFormat.Koruna: - return "Koruna"; - case NumberFormat.Krona: - return "Krona"; - case NumberFormat.Leu: - return "Leu"; - case NumberFormat.Lira: - return "Lira"; - case NumberFormat.MexicanPeso: - return "Mexican Peso"; - case NumberFormat.NewTaiwanDollar: - return "New Taiwan dollar"; - case NumberFormat.NewZealandDollar: - return "New Zealand dollar"; - case NumberFormat.NorwegianKrone: - return "Norwegian krone"; - case NumberFormat.Number: - return "Number"; - case NumberFormat.Percent: - return "Percent"; - case NumberFormat.PhilippinePeso: - return "Percent"; - case NumberFormat.Pound: - return "Pound"; - case NumberFormat.Rand: - return "Rand"; - case NumberFormat.Real: - return "Real"; - case NumberFormat.Ringgit: - return "Ringgit"; - case NumberFormat.Riyal: - return "Riyal"; - case NumberFormat.Ruble: - return "Ruble"; - case NumberFormat.Rupee: - return "Rupee"; - case NumberFormat.Rupiah: - return "Rupiah"; - case NumberFormat.Shekel: - return "Skekel"; - case NumberFormat.USD: - return "US Dollar"; - case NumberFormat.UruguayanPeso: - return "Uruguayan peso"; - case NumberFormat.Won: - return "Uruguayan peso"; - case NumberFormat.Yen: - return "Yen"; - case NumberFormat.Yuan: - return "Yuan"; - default: - throw UnimplementedError; - } +class _FilterTextField extends StatelessWidget { + const _FilterTextField({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return InputTextField( + text: "", + onCanceled: () {}, + onChanged: (text) { + context.read().add(NumberFormatEvent.setFilter(text)); + }, + ); } - - // String iconName() { - // switch (this) { - // case NumberFormat.CNY: - // return "grid/field/yen"; - // case NumberFormat.EUR: - // return "grid/field/euro"; - // case NumberFormat.Number: - // return "grid/field/numbers"; - // case NumberFormat.USD: - // return "grid/field/us_dollar"; - // default: - // throw UnimplementedError; - // } - // } } diff --git a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 91412df599..0f6cecf0bc 100644 --- a/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart @@ -176,6 +176,7 @@ class FlowyOverlayState extends State { FlowyOverlayStyle? style, Offset? anchorOffset, }) { + debugPrint("Show overlay: $identifier"); this.style = style ?? FlowyOverlayStyle(); _showOverlay(