Browse Source

Merge branch 'main' into feat_1624

Lucas.Xu 2 years ago
parent
commit
06c5f6a790

+ 13 - 18
.github/workflows/flutter_ci.yaml

@@ -24,17 +24,17 @@ jobs:
     strategy:
     strategy:
       fail-fast: false
       fail-fast: false
       matrix:
       matrix:
-        job:
-          - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest,}
-          - { target: x86_64-apple-darwin, os: macos-latest, }
-          - { target: x86_64-pc-windows-msvc, os: windows-latest, }
+        os: [ubuntu-latest, macos-latest, windows-latest]
         include:
         include:
           - os: ubuntu-latest
           - os: ubuntu-latest
             flutter_profile: development-linux-x86_64
             flutter_profile: development-linux-x86_64
+            target: x86_64-unknown-linux-gnu
           - os: macos-latest
           - os: macos-latest
             flutter_profile: development-mac-x86_64
             flutter_profile: development-mac-x86_64
+            target: x86_64-apple-darwin
           - os: windows-latest
           - os: windows-latest
             flutter_profile: development-windows-x86
             flutter_profile: development-windows-x86
+            target: x86_64-pc-windows-msvc
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
 
 
     steps:
     steps:
@@ -46,9 +46,8 @@ jobs:
         uses: actions-rs/toolchain@v1
         uses: actions-rs/toolchain@v1
         with:
         with:
           toolchain: ${{ env.RUST_TOOLCHAIN }}
           toolchain: ${{ env.RUST_TOOLCHAIN }}
-          target: ${{ matrix.job.target }}
+          target: ${{ matrix.target }}
           override: true
           override: true
-          components: rustfmt
           profile: minimal
           profile: minimal
 
 
       - name: Install flutter
       - name: Install flutter
@@ -68,18 +67,18 @@ jobs:
         run: |
         run: |
           cargo install --force cargo-make
           cargo install --force cargo-make
           cargo install --force duckscript_cli
           cargo install --force duckscript_cli
-          cargo make appflowy-deps-tools
           if [ "$RUNNER_OS" == "Linux" ]; then
           if [ "$RUNNER_OS" == "Linux" ]; then
             sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
             sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub
             sudo wget -qO /etc/apt/sources.list.d/dart_stable.list https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list
             sudo wget -qO /etc/apt/sources.list.d/dart_stable.list https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list
             sudo apt-get update
             sudo apt-get update
-            sudo apt-get install -y dart curl build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
+            sudo apt-get install -y dart curl build-essential libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev
             sudo apt-get install keybinder-3.0
             sudo apt-get install keybinder-3.0
           elif [ "$RUNNER_OS" == "Windows" ]; then
           elif [ "$RUNNER_OS" == "Windows" ]; then
             vcpkg integrate install
             vcpkg integrate install
           elif [ "$RUNNER_OS" == "macOS" ]; then
           elif [ "$RUNNER_OS" == "macOS" ]; then
             echo 'do nothing'
             echo 'do nothing'
           fi
           fi
+          cargo make appflowy-deps-tools
         shell: bash
         shell: bash
 
 
       - name: Enable Flutter Desktop
       - name: Enable Flutter Desktop
@@ -102,16 +101,12 @@ jobs:
         working-directory: frontend/app_flowy
         working-directory: frontend/app_flowy
         run: flutter analyze
         run: flutter analyze
 
 
-      - name: Build Flutter unit test lib
-        working-directory: frontend
-        run: |
-          cargo make build-test-lib
-
       - name: Run Flutter unit tests
       - name: Run Flutter unit tests
-        working-directory: frontend/app_flowy
+        working-directory: frontend
         run: |
         run: |
-          if [ "$RUNNER_OS" == "Linux" ]; then
-            flutter pub get
-            flutter test
+          if [ "$RUNNER_OS" == "macOS" ]; then
+            cargo make dart_unit_test
+          elif [ "$RUNNER_OS" == "Windows" ]; then
+            cargo make dart_unit_test
           fi
           fi
-        shell: bash
+        shell: bash

+ 32 - 6
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/extension.dart

@@ -1,6 +1,8 @@
+import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
+import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
@@ -62,13 +64,13 @@ extension SelectOptionColorExtension on SelectOptionColorPB {
 class SelectOptionTag extends StatelessWidget {
 class SelectOptionTag extends StatelessWidget {
   final String name;
   final String name;
   final Color color;
   final Color color;
-  final bool isSelected;
   final VoidCallback? onSelected;
   final VoidCallback? onSelected;
+  final void Function(String)? onRemove;
   const SelectOptionTag({
   const SelectOptionTag({
     required this.name,
     required this.name,
     required this.color,
     required this.color,
     this.onSelected,
     this.onSelected,
-    this.isSelected = false,
+    this.onRemove,
     Key? key,
     Key? key,
   }) : super(key: key);
   }) : super(key: key);
 
 
@@ -76,25 +78,49 @@ class SelectOptionTag extends StatelessWidget {
     required BuildContext context,
     required BuildContext context,
     required SelectOptionPB option,
     required SelectOptionPB option,
     VoidCallback? onSelected,
     VoidCallback? onSelected,
-    bool isSelected = false,
+    Function(String)? onRemove,
   }) {
   }) {
     return SelectOptionTag(
     return SelectOptionTag(
       name: option.name,
       name: option.name,
       color: option.color.make(context),
       color: option.color.make(context),
-      isSelected: isSelected,
       onSelected: onSelected,
       onSelected: onSelected,
+      onRemove: onRemove,
     );
     );
   }
   }
 
 
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
+    EdgeInsets padding =
+        const EdgeInsets.symmetric(vertical: 2.0, horizontal: 8.0);
+    if (onRemove != null) {
+      padding = padding.copyWith(right: 2.0);
+    }
+
     return Container(
     return Container(
-      padding: const EdgeInsets.symmetric(vertical: 2.0, horizontal: 8.0),
+      padding: padding,
       decoration: BoxDecoration(
       decoration: BoxDecoration(
         color: color,
         color: color,
         borderRadius: Corners.s6Border,
         borderRadius: Corners.s6Border,
       ),
       ),
-      child: FlowyText.medium(name, overflow: TextOverflow.ellipsis),
+      child: Row(
+        mainAxisSize: MainAxisSize.min,
+        children: [
+          Flexible(
+            child: FlowyText.medium(name, overflow: TextOverflow.ellipsis),
+          ),
+          if (onRemove != null)
+            FlowyIconButton(
+              width: 18.0,
+              onPressed: () => onRemove?.call(name),
+              fillColor: Colors.transparent,
+              hoverColor: Colors.transparent,
+              icon: svgWidget(
+                'home/close',
+                color: Theme.of(context).colorScheme.onSurface,
+              ),
+            ),
+        ],
+      ),
     );
     );
   }
   }
 }
 }

+ 8 - 0
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_editor.dart

@@ -159,6 +159,13 @@ class _TextField extends StatelessWidget {
                     remainder,
                     remainder,
                   ));
                   ));
             },
             },
+            onRemove: (optionName) {
+              context
+                  .read<SelectOptionCellEditorBloc>()
+                  .add(SelectOptionEditorEvent.unSelectOption(
+                    optionMap[optionName]!.id,
+                  ));
+            },
           ),
           ),
         );
         );
       },
       },
@@ -297,6 +304,7 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
             context
             context
                 .read<SelectOptionCellEditorBloc>()
                 .read<SelectOptionCellEditorBloc>()
                 .add(SelectOptionEditorEvent.deleteOption(widget.option));
                 .add(SelectOptionEditorEvent.deleteOption(widget.option));
+            PopoverContainer.of(popoverContext).close();
           },
           },
           onUpdated: (updatedOption) {
           onUpdated: (updatedOption) {
             context
             context

+ 26 - 18
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/text_field.dart

@@ -22,6 +22,7 @@ class SelectOptionTextField extends StatefulWidget {
   final Function(String) onSubmitted;
   final Function(String) onSubmitted;
   final Function(String) newText;
   final Function(String) newText;
   final Function(List<String>, String) onPaste;
   final Function(List<String>, String) onPaste;
+  final Function(String) onRemove;
   final VoidCallback? onClick;
   final VoidCallback? onClick;
   final int? maxLength;
   final int? maxLength;
 
 
@@ -32,6 +33,7 @@ class SelectOptionTextField extends StatefulWidget {
     required this.tagController,
     required this.tagController,
     required this.onSubmitted,
     required this.onSubmitted,
     required this.onPaste,
     required this.onPaste,
+    required this.onRemove,
     required this.newText,
     required this.newText,
     required this.textSeparators,
     required this.textSeparators,
     this.onClick,
     this.onClick,
@@ -163,25 +165,31 @@ class _SelectOptionTextFieldState extends State<SelectOptionTextField> {
     }
     }
 
 
     final children = widget.selectedOptionMap.values
     final children = widget.selectedOptionMap.values
-        .map((option) =>
-            SelectOptionTag.fromOption(context: context, option: option))
+        .map((option) => SelectOptionTag.fromOption(
+              context: context,
+              option: option,
+              onRemove: (option) => widget.onRemove(option),
+            ))
         .toList();
         .toList();
-    return Padding(
-      padding: const EdgeInsets.all(8.0),
-      child: ScrollConfiguration(
-        behavior: ScrollConfiguration.of(context).copyWith(
-          dragDevices: {
-            PointerDeviceKind.mouse,
-            PointerDeviceKind.touch,
-            PointerDeviceKind.trackpad,
-            PointerDeviceKind.stylus,
-            PointerDeviceKind.invertedStylus,
-          },
-        ),
-        child: SingleChildScrollView(
-          controller: sc,
-          scrollDirection: Axis.horizontal,
-          child: Wrap(spacing: 4, children: children),
+    return MouseRegion(
+      cursor: SystemMouseCursors.basic,
+      child: Padding(
+        padding: const EdgeInsets.all(8.0),
+        child: ScrollConfiguration(
+          behavior: ScrollConfiguration.of(context).copyWith(
+            dragDevices: {
+              PointerDeviceKind.mouse,
+              PointerDeviceKind.touch,
+              PointerDeviceKind.trackpad,
+              PointerDeviceKind.stylus,
+              PointerDeviceKind.invertedStylus,
+            },
+          ),
+          child: SingleChildScrollView(
+            controller: sc,
+            scrollDirection: Axis.horizontal,
+            child: Wrap(spacing: 4, children: children),
+          ),
         ),
         ),
       ),
       ),
     );
     );

+ 6 - 2
frontend/app_flowy/lib/workspace/presentation/home/menu/app/section/section.dart

@@ -40,7 +40,8 @@ class ViewSection extends StatelessWidget {
     );
     );
   }
   }
 
 
-  ReorderableColumn _reorderableColum(BuildContext context, ViewSectionState state) {
+  ReorderableColumn _reorderableColum(
+      BuildContext context, ViewSectionState state) {
     final children = state.views.map((view) {
     final children = state.views.map((view) {
       return ViewSectionItem(
       return ViewSectionItem(
         key: ValueKey(view.id),
         key: ValueKey(view.id),
@@ -53,8 +54,11 @@ class ViewSection extends StatelessWidget {
     return ReorderableColumn(
     return ReorderableColumn(
       needsLongPressDraggable: false,
       needsLongPressDraggable: false,
       onReorder: (oldIndex, index) {
       onReorder: (oldIndex, index) {
-        context.read<ViewSectionBloc>().add(ViewSectionEvent.moveView(oldIndex, index));
+        context
+            .read<ViewSectionBloc>()
+            .add(ViewSectionEvent.moveView(oldIndex, index));
       },
       },
+      ignorePrimaryScrollController: true,
       children: children,
       children: children,
     );
     );
   }
   }

+ 1 - 0
frontend/app_flowy/test/widget_test/select_option_text_field_test.dart

@@ -28,6 +28,7 @@ void main() {
         remainder = remaining;
         remainder = remaining;
         select = options;
         select = options;
       },
       },
+      onRemove: (_) {},
       newText: (text) => remainder = text,
       newText: (text) => remainder = text,
       textSeparators: const [','],
       textSeparators: const [','],
       textController: TextEditingController(),
       textController: TextEditingController(),

+ 4 - 0
frontend/rust-lib/flowy-grid/src/services/field/type_options/checkbox_type_option/checkbox_tests.rs

@@ -16,11 +16,15 @@ mod tests {
         // the checkout value will be checked if the value is "1", "true" or "yes"
         // the checkout value will be checked if the value is "1", "true" or "yes"
         assert_checkbox(&type_option, "1", CHECK, &field_type, &field_rev);
         assert_checkbox(&type_option, "1", CHECK, &field_type, &field_rev);
         assert_checkbox(&type_option, "true", CHECK, &field_type, &field_rev);
         assert_checkbox(&type_option, "true", CHECK, &field_type, &field_rev);
+        assert_checkbox(&type_option, "TRUE", CHECK, &field_type, &field_rev);
         assert_checkbox(&type_option, "yes", CHECK, &field_type, &field_rev);
         assert_checkbox(&type_option, "yes", CHECK, &field_type, &field_rev);
+        assert_checkbox(&type_option, "YES", CHECK, &field_type, &field_rev);
 
 
         // the checkout value will be uncheck if the value is "false" or "No"
         // the checkout value will be uncheck if the value is "false" or "No"
         assert_checkbox(&type_option, "false", UNCHECK, &field_type, &field_rev);
         assert_checkbox(&type_option, "false", UNCHECK, &field_type, &field_rev);
         assert_checkbox(&type_option, "No", UNCHECK, &field_type, &field_rev);
         assert_checkbox(&type_option, "No", UNCHECK, &field_type, &field_rev);
+        assert_checkbox(&type_option, "NO", UNCHECK, &field_type, &field_rev);
+        assert_checkbox(&type_option, "0", UNCHECK, &field_type, &field_rev);
 
 
         // the checkout value will be empty if the value is letters or empty string
         // the checkout value will be empty if the value is letters or empty string
         assert_checkbox(&type_option, "abc", "", &field_type, &field_rev);
         assert_checkbox(&type_option, "abc", "", &field_type, &field_rev);