Browse Source

fix: unable to cancel the inline math equation format (#2974)

* fix: unable to cancel the inline math equation format

* fix: bold font style used in the document is not suitable

* chore: add flutter clean before executing the release task

* fix: integration test
Lucas.Xu 1 năm trước cách đây
mục cha
commit
b9976b072e
15 tập tin đã thay đổi với 136 bổ sung39 xóa
  1. 56 0
      frontend/appflowy_flutter/integration_test/document/document_with_inline_math_equation_test.dart
  2. 8 4
      frontend/appflowy_flutter/integration_test/open_ai_smart_menu_test.dart
  3. 1 1
      frontend/appflowy_flutter/integration_test/util/editor_test_operations.dart
  4. 1 1
      frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart
  5. 2 2
      frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/callout/callout_block_component.dart
  6. 2 2
      frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_component.dart
  7. 27 5
      frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/inline_math_equation/inline_math_equation_toolbar_item.dart
  8. 6 5
      frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart
  9. 2 2
      frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/migration/editor_migration.dart
  10. 1 1
      frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/smart_edit_node_widget.dart
  11. 2 2
      frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/toggle/toggle_block_component.dart
  12. 17 10
      frontend/appflowy_flutter/lib/plugins/document/presentation/editor_style.dart
  13. 2 2
      frontend/appflowy_flutter/pubspec.lock
  14. 1 1
      frontend/appflowy_flutter/pubspec.yaml
  15. 8 1
      frontend/scripts/makefile/flutter.toml

+ 56 - 0
frontend/appflowy_flutter/integration_test/document/document_with_inline_math_equation_test.dart

@@ -61,5 +61,61 @@ void main() {
       );
       );
       await tester.pumpAndSettle();
       await tester.pumpAndSettle();
     });
     });
+
+    testWidgets('remove the inline math equation format', (tester) async {
+      await tester.initializeAppFlowy();
+      await tester.tapGoButton();
+
+      // create a new document
+      await tester.createNewPageWithName(
+        ViewLayoutPB.Document,
+        LocaleKeys.document_plugins_createInlineMathEquation.tr(),
+      );
+
+      // tap the first line of the document
+      await tester.editor.tapLineOfEditorAt(0);
+      // insert a inline page
+      const formula = 'E = MC ^ 2';
+      await tester.ime.insertText(formula);
+      await tester.editor.updateSelection(
+        Selection.single(path: [0], startOffset: 0, endOffset: formula.length),
+      );
+
+      // tap the inline math equation button
+      var inlineMathEquationButton = find.byTooltip(
+        LocaleKeys.document_plugins_createInlineMathEquation.tr(),
+      );
+      await tester.tapButton(inlineMathEquationButton);
+
+      // expect to see the math equation block
+      var inlineMathEquation = find.byType(InlineMathEquation);
+      expect(inlineMathEquation, findsOneWidget);
+
+      // highlight the math equation block
+      await tester.editor.updateSelection(
+        Selection.single(path: [0], startOffset: 0, endOffset: 1),
+      );
+
+      // expect to the see the inline math equation button is highlighted
+      inlineMathEquationButton = find.byWidgetPredicate(
+        (widget) =>
+            widget is IconItemWidget &&
+            widget.tooltip ==
+                LocaleKeys.document_plugins_createInlineMathEquation.tr(),
+      );
+      expect(
+        tester.widget<IconItemWidget>(inlineMathEquationButton).isHighlight,
+        isTrue,
+      );
+
+      // cancel the format
+      await tester.tapButton(inlineMathEquationButton);
+
+      // expect to see the math equation block is removed
+      inlineMathEquation = find.byType(InlineMathEquation);
+      expect(inlineMathEquation, findsNothing);
+
+      tester.expectToSeeText(formula);
+    });
   });
   });
 }
 }

+ 8 - 4
frontend/appflowy_flutter/integration_test/open_ai_smart_menu_test.dart

@@ -17,7 +17,8 @@ void main() {
     setUpAll(() async => await service.setUpAll());
     setUpAll(() async => await service.setUpAll());
     setUp(() async => await service.setUp());
     setUp(() async => await service.setUp());
 
 
-    testWidgets('testing selection on open-ai smart menu replace', (tester) async {
+    testWidgets('testing selection on open-ai smart menu replace',
+        (tester) async {
       final appFlowyEditor = await setUpOpenAITesting(tester);
       final appFlowyEditor = await setUpOpenAITesting(tester);
       final editorState = appFlowyEditor.editorState;
       final editorState = appFlowyEditor.editorState;
 
 
@@ -38,7 +39,8 @@ void main() {
       await tester.tap(find.text('Summarize'));
       await tester.tap(find.text('Summarize'));
       await tester.pumpAndSettle();
       await tester.pumpAndSettle();
 
 
-      await tester.tap(find.byType(FlowyRichTextButton, skipOffstage: false).first);
+      await tester
+          .tap(find.byType(FlowyRichTextButton, skipOffstage: false).first);
       await tester.pumpAndSettle();
       await tester.pumpAndSettle();
 
 
       expect(
       expect(
@@ -49,7 +51,8 @@ void main() {
         ),
         ),
       );
       );
     });
     });
-    testWidgets('testing selection on open-ai smart menu insert', (tester) async {
+    testWidgets('testing selection on open-ai smart menu insert',
+        (tester) async {
       final appFlowyEditor = await setUpOpenAITesting(tester);
       final appFlowyEditor = await setUpOpenAITesting(tester);
       final editorState = appFlowyEditor.editorState;
       final editorState = appFlowyEditor.editorState;
 
 
@@ -69,7 +72,8 @@ void main() {
       await tester.tap(find.text('Summarize'));
       await tester.tap(find.text('Summarize'));
       await tester.pumpAndSettle();
       await tester.pumpAndSettle();
 
 
-      await tester.tap(find.byType(FlowyRichTextButton, skipOffstage: false).at(1));
+      await tester
+          .tap(find.byType(FlowyRichTextButton, skipOffstage: false).at(1));
       await tester.pumpAndSettle();
       await tester.pumpAndSettle();
 
 
       expect(
       expect(

+ 1 - 1
frontend/appflowy_flutter/integration_test/util/editor_test_operations.dart

@@ -32,7 +32,7 @@ class EditorOperations {
 
 
   /// Tap the line of editor at [index]
   /// Tap the line of editor at [index]
   Future<void> tapLineOfEditorAt(int index) async {
   Future<void> tapLineOfEditorAt(int index) async {
-    final textBlocks = find.byType(FlowyRichText);
+    final textBlocks = find.byType(AppFlowyRichText);
     index = index.clamp(0, textBlocks.evaluate().length - 1);
     index = index.clamp(0, textBlocks.evaluate().length - 1);
     await tester.tapAt(tester.getTopRight(textBlocks.at(index)));
     await tester.tapAt(tester.getTopRight(textBlocks.at(index)));
     await tester.pumpAndSettle();
     await tester.pumpAndSettle();

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_page.dart

@@ -126,7 +126,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
     final (bool autoFocus, Selection? selection) =
     final (bool autoFocus, Selection? selection) =
         _computeAutoFocusParameters();
         _computeAutoFocusParameters();
 
 
-    final editor = AppFlowyEditor.custom(
+    final editor = AppFlowyEditor(
       editorState: widget.editorState,
       editorState: widget.editorState,
       editable: true,
       editable: true,
       shrinkWrap: widget.shrinkWrap,
       shrinkWrap: widget.shrinkWrap,

+ 2 - 2
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/callout/callout_block_component.dart

@@ -105,7 +105,7 @@ class CalloutBlockComponentWidget extends BlockComponentStatefulWidget {
 
 
 class _CalloutBlockComponentWidgetState
 class _CalloutBlockComponentWidgetState
     extends State<CalloutBlockComponentWidget>
     extends State<CalloutBlockComponentWidget>
-    with SelectableMixin, DefaultSelectable, BlockComponentConfigurable {
+    with SelectableMixin, DefaultSelectableMixin, BlockComponentConfigurable {
   // the key used to forward focus to the richtext child
   // the key used to forward focus to the richtext child
   @override
   @override
   final forwardKey = GlobalKey(debugLabel: 'flowy_rich_text');
   final forwardKey = GlobalKey(debugLabel: 'flowy_rich_text');
@@ -192,7 +192,7 @@ class _CalloutBlockComponentWidgetState
   Widget buildCalloutBlockComponent(BuildContext context) {
   Widget buildCalloutBlockComponent(BuildContext context) {
     return Padding(
     return Padding(
       padding: padding,
       padding: padding,
-      child: FlowyRichText(
+      child: AppFlowyRichText(
         key: forwardKey,
         key: forwardKey,
         node: widget.node,
         node: widget.node,
         editorState: editorState,
         editorState: editorState,

+ 2 - 2
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/code_block/code_block_component.dart

@@ -96,7 +96,7 @@ class CodeBlockComponentWidget extends BlockComponentStatefulWidget {
 }
 }
 
 
 class _CodeBlockComponentWidgetState extends State<CodeBlockComponentWidget>
 class _CodeBlockComponentWidgetState extends State<CodeBlockComponentWidget>
-    with SelectableMixin, DefaultSelectable, BlockComponentConfigurable {
+    with SelectableMixin, DefaultSelectableMixin, BlockComponentConfigurable {
   // the key used to forward focus to the richtext child
   // the key used to forward focus to the richtext child
   @override
   @override
   final forwardKey = GlobalKey(debugLabel: 'flowy_rich_text');
   final forwardKey = GlobalKey(debugLabel: 'flowy_rich_text');
@@ -216,7 +216,7 @@ class _CodeBlockComponentWidgetState extends State<CodeBlockComponentWidget>
     final codeTextSpans = _convert(codeNodes);
     final codeTextSpans = _convert(codeNodes);
     return Padding(
     return Padding(
       padding: widget.padding,
       padding: widget.padding,
-      child: FlowyRichText(
+      child: AppFlowyRichText(
         key: forwardKey,
         key: forwardKey,
         node: widget.node,
         node: widget.node,
         editorState: editorState,
         editorState: editorState,

+ 27 - 5
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/inline_math_equation/inline_math_equation_toolbar_item.dart

@@ -21,7 +21,7 @@ final ToolbarItem inlineMathEquationItem = ToolbarItem(
       iconBuilder: (_) => svgWidget(
       iconBuilder: (_) => svgWidget(
         'editor/math',
         'editor/math',
         size: const Size.square(16),
         size: const Size.square(16),
-        color: Colors.white,
+        color: isHighlight ? Colors.lightBlue : Colors.white,
       ),
       ),
       isHighlight: isHighlight,
       isHighlight: isHighlight,
       tooltip: LocaleKeys.document_plugins_createInlineMathEquation.tr(),
       tooltip: LocaleKeys.document_plugins_createInlineMathEquation.tr(),
@@ -31,12 +31,33 @@ final ToolbarItem inlineMathEquationItem = ToolbarItem(
           return;
           return;
         }
         }
         final node = editorState.getNodeAtPath(selection.start.path);
         final node = editorState.getNodeAtPath(selection.start.path);
-        if (node == null) {
+        final delta = node?.delta;
+        if (node == null || delta == null) {
           return;
           return;
         }
         }
-        final text = editorState.getTextInSelection(selection).join();
-        final transaction = editorState.transaction
-          ..replaceText(
+
+        final transaction = editorState.transaction;
+        if (isHighlight) {
+          final formula = delta
+              .slice(selection.startIndex, selection.endIndex)
+              .whereType<TextInsert>()
+              .firstOrNull
+              ?.attributes?[InlineMathEquationKeys.formula];
+          assert(formula != null);
+          if (formula == null) {
+            return;
+          }
+          // clear the format
+          transaction.replaceText(
+            node,
+            selection.startIndex,
+            selection.length,
+            formula,
+            attributes: {},
+          );
+        } else {
+          final text = editorState.getTextInSelection(selection).join();
+          transaction.replaceText(
             node,
             node,
             selection.startIndex,
             selection.startIndex,
             selection.length,
             selection.length,
@@ -45,6 +66,7 @@ final ToolbarItem inlineMathEquationItem = ToolbarItem(
               InlineMathEquationKeys.formula: text,
               InlineMathEquationKeys.formula: text,
             },
             },
           );
           );
+        }
         await editorState.apply(transaction);
         await editorState.apply(transaction);
       },
       },
     );
     );

+ 6 - 5
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart

@@ -32,7 +32,7 @@ class MentionPageBlock extends StatefulWidget {
 
 
 class _MentionPageBlockState extends State<MentionPageBlock> {
 class _MentionPageBlockState extends State<MentionPageBlock> {
   late final EditorState editorState;
   late final EditorState editorState;
-  late final Future<ViewPB?> viewPBFuture;
+  late Future<ViewPB?> viewPBFuture;
   ViewListener? viewListener;
   ViewListener? viewListener;
 
 
   @override
   @override
@@ -45,6 +45,7 @@ class _MentionPageBlockState extends State<MentionPageBlock> {
       ..start(
       ..start(
         onViewUpdated: (p0) {
         onViewUpdated: (p0) {
           pageMemorizer[p0.id] = p0;
           pageMemorizer[p0.id] = p0;
+          viewPBFuture = fetchView(widget.pageId);
           editorState.reload();
           editorState.reload();
         },
         },
       );
       );
@@ -111,11 +112,10 @@ class _MentionPageBlockState extends State<MentionPageBlock> {
   }
   }
 
 
   Future<ViewPB?> fetchView(String pageId) async {
   Future<ViewPB?> fetchView(String pageId) async {
-    final views = await ViewBackendService().fetchViews((_, __) => true);
-    final flattenViews = views.expand((e) => [e.$1, ...e.$2]).toList();
-    final view = flattenViews.firstWhereOrNull(
-      (element) => element.id == pageId,
+    final view = await ViewBackendService.getView(pageId).then(
+      (value) => value.swap().toOption().toNullable(),
     );
     );
+
     if (view == null) {
     if (view == null) {
       // try to fetch from trash
       // try to fetch from trash
       final trashViews = await TrashService().readTrash();
       final trashViews = await TrashService().readTrash();
@@ -129,6 +129,7 @@ class _MentionPageBlockState extends State<MentionPageBlock> {
           ..name = trash.name;
           ..name = trash.name;
       }
       }
     }
     }
+
     return view;
     return view;
   }
   }
 
 

+ 2 - 2
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/migration/editor_migration.dart

@@ -141,13 +141,13 @@ class EditorMigration {
     }
     }
     const backgroundColor = 'backgroundColor';
     const backgroundColor = 'backgroundColor';
     if (attributes.containsKey(backgroundColor)) {
     if (attributes.containsKey(backgroundColor)) {
-      attributes[FlowyRichTextKeys.highlightColor] =
+      attributes[AppFlowyRichTextKeys.highlightColor] =
           attributes[backgroundColor];
           attributes[backgroundColor];
       attributes.remove(backgroundColor);
       attributes.remove(backgroundColor);
     }
     }
     const color = 'color';
     const color = 'color';
     if (attributes.containsKey(color)) {
     if (attributes.containsKey(color)) {
-      attributes[FlowyRichTextKeys.textColor] = attributes[color];
+      attributes[AppFlowyRichTextKeys.textColor] = attributes[color];
       attributes.remove(color);
       attributes.remove(color);
     }
     }
     return attributes;
     return attributes;

+ 1 - 1
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/smart_edit_node_widget.dart

@@ -157,7 +157,7 @@ class _SmartEditBlockComponentWidgetState
     var width = double.infinity;
     var width = double.infinity;
     final editorSize = editorState.renderBox?.size;
     final editorSize = editorState.renderBox?.size;
     final padding = editorState.editorStyle.padding;
     final padding = editorState.editorStyle.padding;
-    if (editorSize != null && padding != null) {
+    if (editorSize != null) {
       width = editorSize.width - padding.left - padding.right;
       width = editorSize.width - padding.left - padding.right;
     }
     }
     return width;
     return width;

+ 2 - 2
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/toggle/toggle_block_component.dart

@@ -84,7 +84,7 @@ class _ToggleListBlockComponentWidgetState
     extends State<ToggleListBlockComponentWidget>
     extends State<ToggleListBlockComponentWidget>
     with
     with
         SelectableMixin,
         SelectableMixin,
-        DefaultSelectable,
+        DefaultSelectableMixin,
         BlockComponentConfigurable,
         BlockComponentConfigurable,
         BackgroundColorMixin {
         BackgroundColorMixin {
   // the key used to forward focus to the richtext child
   // the key used to forward focus to the richtext child
@@ -141,7 +141,7 @@ class _ToggleListBlockComponentWidgetState
           width: 4.0,
           width: 4.0,
         ),
         ),
         Expanded(
         Expanded(
-          child: FlowyRichText(
+          child: AppFlowyRichText(
             key: forwardKey,
             key: forwardKey,
             node: widget.node,
             node: widget.node,
             editorState: editorState,
             editorState: editorState,

+ 17 - 10
frontend/appflowy_flutter/lib/plugins/document/presentation/editor_style.dart

@@ -40,15 +40,18 @@ class EditorStyleCustomizer {
           color: theme.colorScheme.onBackground,
           color: theme.colorScheme.onBackground,
           height: 1.5,
           height: 1.5,
         ),
         ),
-        bold: baseTextStyle(fontFamily).copyWith(
+        bold: baseTextStyle(fontFamily, fontWeight: FontWeight.bold).copyWith(
           fontWeight: FontWeight.w600,
           fontWeight: FontWeight.w600,
         ),
         ),
-        italic: baseTextStyle(fontFamily).copyWith(fontStyle: FontStyle.italic),
-        underline: baseTextStyle(fontFamily)
-            .copyWith(decoration: TextDecoration.underline),
-        strikethrough:
-            baseTextStyle(fontFamily)
-            .copyWith(decoration: TextDecoration.lineThrough),
+        italic: baseTextStyle(fontFamily).copyWith(
+          fontStyle: FontStyle.italic,
+        ),
+        underline: baseTextStyle(fontFamily).copyWith(
+          decoration: TextDecoration.underline,
+        ),
+        strikethrough: baseTextStyle(fontFamily).copyWith(
+          decoration: TextDecoration.lineThrough,
+        ),
         href: baseTextStyle(fontFamily).copyWith(
         href: baseTextStyle(fontFamily).copyWith(
           color: theme.colorScheme.primary,
           color: theme.colorScheme.primary,
           decoration: TextDecoration.underline,
           decoration: TextDecoration.underline,
@@ -87,8 +90,7 @@ class EditorStyleCustomizer {
         italic: baseTextStyle(fontFamily).copyWith(fontStyle: FontStyle.italic),
         italic: baseTextStyle(fontFamily).copyWith(fontStyle: FontStyle.italic),
         underline: baseTextStyle(fontFamily)
         underline: baseTextStyle(fontFamily)
             .copyWith(decoration: TextDecoration.underline),
             .copyWith(decoration: TextDecoration.underline),
-        strikethrough:
-            baseTextStyle(fontFamily)
+        strikethrough: baseTextStyle(fontFamily)
             .copyWith(decoration: TextDecoration.lineThrough),
             .copyWith(decoration: TextDecoration.lineThrough),
         href: baseTextStyle(fontFamily).copyWith(
         href: baseTextStyle(fontFamily).copyWith(
           color: theme.colorScheme.primary,
           color: theme.colorScheme.primary,
@@ -163,10 +165,14 @@ class EditorStyleCustomizer {
     );
     );
   }
   }
 
 
-  TextStyle baseTextStyle(String fontFamily) {
+  TextStyle baseTextStyle(
+    String fontFamily, {
+    FontWeight? fontWeight,
+  }) {
     try {
     try {
       return GoogleFonts.getFont(
       return GoogleFonts.getFont(
         fontFamily,
         fontFamily,
+        fontWeight: fontWeight,
       );
       );
     } on Exception {
     } on Exception {
       return GoogleFonts.getFont('Poppins');
       return GoogleFonts.getFont('Poppins');
@@ -174,6 +180,7 @@ class EditorStyleCustomizer {
   }
   }
 
 
   InlineSpan customizeAttributeDecorator(
   InlineSpan customizeAttributeDecorator(
+    BuildContext context,
     Node node,
     Node node,
     int index,
     int index,
     TextInsert text,
     TextInsert text,

+ 2 - 2
frontend/appflowy_flutter/pubspec.lock

@@ -53,8 +53,8 @@ packages:
     dependency: "direct main"
     dependency: "direct main"
     description:
     description:
       path: "."
       path: "."
-      ref: c5b5e64
-      resolved-ref: c5b5e641fe11ae634f02db112e71f40a119e9c44
+      ref: "35394cd"
+      resolved-ref: "35394cd4f45f3f98afbec8d23d12fe0bf3cd3f6d"
       url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
       url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
     source: git
     source: git
     version: "1.1.0"
     version: "1.1.0"

+ 1 - 1
frontend/appflowy_flutter/pubspec.yaml

@@ -46,7 +46,7 @@ dependencies:
   appflowy_editor:
   appflowy_editor:
     git:
     git:
       url: https://github.com/AppFlowy-IO/appflowy-editor.git
       url: https://github.com/AppFlowy-IO/appflowy-editor.git
-      ref: c5b5e64
+      ref: 35394cd
   appflowy_popover:
   appflowy_popover:
     path: packages/appflowy_popover
     path: packages/appflowy_popover
 
 

+ 8 - 1
frontend/scripts/makefile/flutter.toml

@@ -184,6 +184,10 @@ script_runner = "@duckscript"
 script_runner = "@shell"
 script_runner = "@shell"
 script = [
 script = [
   """
   """
+  cd appflowy_flutter
+  flutter clean
+  flutter pub get
+  cd ../
   sh scripts/code_generation/generate.sh
   sh scripts/code_generation/generate.sh
   """
   """
 ]
 ]
@@ -192,11 +196,14 @@ script = [
 script_runner = "@duckscript"
 script_runner = "@duckscript"
 script = [
 script = [
   """
   """
+  cd ./appflowy_flutter/
+  exec cmd.exe /c flutter clean
+  exec cmd.exe /c flutter pub get
+  cd ../
   exec scripts/code_generation/generate.cmd
   exec scripts/code_generation/generate.cmd
   """,
   """,
 ]
 ]
 
 
-
 [tasks.dry_code_generation]
 [tasks.dry_code_generation]
 script_runner = "@shell"
 script_runner = "@shell"
 script = [
 script = [