浏览代码

chore: filter out number format

appflowy 3 年之前
父节点
当前提交
1488caa97e

+ 4 - 1
frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart

@@ -96,7 +96,10 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
 
   List<SelectOption> _makeOptions(String filter, List<SelectOption> allOptions) {
     final List<SelectOption> 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;
   }
 

+ 142 - 0
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<NumberFormatEvent, NumberFormatState> {
+  NumberFormatBloc() : super(NumberFormatState.initial()) {
+    on<NumberFormatEvent>(
+      (event, emit) async {
+        event.map(setFilter: (_SetFilter value) {
+          final List<NumberFormat> 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<void> 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<NumberFormat> 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;
+  //   }
+  // }
+}

+ 1 - 1
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(

+ 1 - 1
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';

+ 22 - 11
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart → 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<NameTextField> createState() => _NameTextFieldState();
+  State<InputTextField> createState() => _InputTextFieldState();
 }
 
-class _NameTextFieldState extends State<NameTextField> {
+class _InputTextFieldState extends State<InputTextField> {
   late FocusNode _focusNode;
   var isEdited = false;
   late TextEditingController _controller;
@@ -27,7 +29,7 @@ class _NameTextFieldState extends State<NameTextField> {
   @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<NameTextField> {
       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<NameTextField> {
       if (_controller.text.isEmpty) {
         widget.onCanceled();
       } else {
-        widget.onDone(_controller.text);
+        if (widget.onDone != null) {
+          widget.onDone!(_controller.text);
+        }
       }
     }
   }

+ 0 - 2
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';

+ 3 - 3
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) {

+ 3 - 3
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<SelectOption> options;
@@ -222,8 +222,8 @@ class _OptionNameTextField extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return NameTextField(
-      name: "",
+    return InputTextField(
+      text: "",
       onCanceled: () {
         context.read<FieldOptionPannelBloc>().add(const FieldOptionPannelEvent.endAddingOption());
       },

+ 52 - 115
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<NumberFormatBloc, NumberFormatState>(
+              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<NumberFormatBloc>().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;
-  //   }
-  // }
 }

+ 1 - 0
frontend/app_flowy/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart

@@ -176,6 +176,7 @@ class FlowyOverlayState extends State<FlowyOverlay> {
     FlowyOverlayStyle? style,
     Offset? anchorOffset,
   }) {
+    debugPrint("Show overlay: $identifier");
     this.style = style ?? FlowyOverlayStyle();
 
     _showOverlay(