瀏覽代碼

feat: highlight selection when tap on the link menu

Lucas.Xu 2 年之前
父節點
當前提交
dd9cac9c1d

+ 23 - 20
frontend/app_flowy/packages/appflowy_editor/lib/src/render/editor/editor_entry.dart

@@ -32,26 +32,29 @@ class EditorNodeWidget extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return Column(
-      crossAxisAlignment: CrossAxisAlignment.center,
-      children: node.children
-          .map(
-            (child) =>
-                editorState.service.renderPluginService.buildPluginWidget(
-              child is TextNode
-                  ? NodeWidgetContext<TextNode>(
-                      context: context,
-                      node: child,
-                      editorState: editorState,
-                    )
-                  : NodeWidgetContext<Node>(
-                      context: context,
-                      node: child,
-                      editorState: editorState,
-                    ),
-            ),
-          )
-          .toList(),
+    return Container(
+      color: Colors.red.withOpacity(0.1),
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.center,
+        children: node.children
+            .map(
+              (child) =>
+                  editorState.service.renderPluginService.buildPluginWidget(
+                child is TextNode
+                    ? NodeWidgetContext<TextNode>(
+                        context: context,
+                        node: child,
+                        editorState: editorState,
+                      )
+                    : NodeWidgetContext<Node>(
+                        context: context,
+                        node: child,
+                        editorState: editorState,
+                      ),
+              ),
+            )
+            .toList(),
+      ),
     );
   }
 }

+ 8 - 0
frontend/app_flowy/packages/appflowy_editor/lib/src/render/link_menu/link_menu.dart

@@ -9,6 +9,7 @@ class LinkMenu extends StatefulWidget {
     required this.onOpenLink,
     required this.onCopyLink,
     required this.onRemoveLink,
+    required this.onFocusChange,
   }) : super(key: key);
 
   final String? linkText;
@@ -16,6 +17,7 @@ class LinkMenu extends StatefulWidget {
   final VoidCallback onOpenLink;
   final VoidCallback onCopyLink;
   final VoidCallback onRemoveLink;
+  final void Function(bool value) onFocusChange;
 
   @override
   State<LinkMenu> createState() => _LinkMenuState();
@@ -29,11 +31,13 @@ class _LinkMenuState extends State<LinkMenu> {
   void initState() {
     super.initState();
     _textEditingController.text = widget.linkText ?? '';
+    _focusNode.addListener(_onFocusChange);
   }
 
   @override
   void dispose() {
     _textEditingController.dispose();
+    _focusNode.removeListener(_onFocusChange);
     super.dispose();
   }
 
@@ -157,4 +161,8 @@ class _LinkMenuState extends State<LinkMenu> {
       onPressed: onPressed,
     );
   }
+
+  void _onFocusChange() {
+    widget.onFocusChange(_focusNode.hasFocus);
+  }
 }

+ 5 - 2
frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/flowy_rich_text.dart

@@ -257,8 +257,11 @@ class _FlowyRichTextState extends State<FlowyRichText> with Selectable {
         timer = Timer(const Duration(milliseconds: 200), () {
           tapCount = 0;
           WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
-            showLinkMenu(context, widget.editorState,
-                customSelection: selection);
+            showLinkMenu(
+              context,
+              widget.editorState,
+              customSelection: selection,
+            );
           });
         });
       };

+ 22 - 7
frontend/app_flowy/packages/appflowy_editor/lib/src/render/toolbar/toolbar_item.dart

@@ -158,6 +158,7 @@ ToolbarShowValidator _showInTextSelection = (editorState) {
 
 OverlayEntry? _linkMenuOverlay;
 EditorState? _editorState;
+bool _changeSelectionInner = false;
 void showLinkMenu(
   BuildContext context,
   EditorState editorState, {
@@ -180,17 +181,17 @@ void showLinkMenu(
   // We get the text node directly instead of judging details again.
   final selection = customSelection ??
       editorState.service.selectionService.currentSelection.value;
-  if (selection == null) {
+  final node = editorState.service.selectionService.currentSelectedNodes;
+  if (selection == null || node.isEmpty || node.first is! TextNode) {
     return;
   }
   final index =
       selection.isBackward ? selection.start.offset : selection.end.offset;
   final length = (selection.start.offset - selection.end.offset).abs();
-  final node = editorState.service.selectionService.currentSelectedNodes.first
-      as TextNode;
+  final textNode = node.first as TextNode;
   String? linkText;
-  if (node.allSatisfyLinkInSelection(selection)) {
-    linkText = node.getAttributeInSelection(selection, StyleKey.href);
+  if (textNode.allSatisfyLinkInSelection(selection)) {
+    linkText = textNode.getAttributeInSelection(selection, StyleKey.href);
   }
   _linkMenuOverlay = OverlayEntry(builder: (context) {
     return Positioned(
@@ -204,7 +205,7 @@ void showLinkMenu(
           },
           onSubmitted: (text) {
             TransactionBuilder(editorState)
-              ..formatText(node, index, length, {StyleKey.href: text})
+              ..formatText(textNode, index, length, {StyleKey.href: text})
               ..commit();
             _dismissLinkMenu();
           },
@@ -214,10 +215,17 @@ void showLinkMenu(
           },
           onRemoveLink: () {
             TransactionBuilder(editorState)
-              ..formatText(node, index, length, {StyleKey.href: null})
+              ..formatText(textNode, index, length, {StyleKey.href: null})
               ..commit();
             _dismissLinkMenu();
           },
+          onFocusChange: (value) {
+            if (value && customSelection != null) {
+              _changeSelectionInner = true;
+              editorState.service.selectionService
+                  .updateSelection(customSelection);
+            }
+          },
         ),
       ),
     );
@@ -230,6 +238,13 @@ void showLinkMenu(
 }
 
 void _dismissLinkMenu() {
+  if (_editorState?.service.selectionService.currentSelection.value == null) {
+    return;
+  }
+  if (_changeSelectionInner) {
+    _changeSelectionInner = false;
+    return;
+  }
   _linkMenuOverlay?.remove();
   _linkMenuOverlay = null;
 

+ 1 - 0
frontend/app_flowy/packages/appflowy_editor/test/render/link_menu/link_menu_test.dart

@@ -15,6 +15,7 @@ void main() async {
         onOpenLink: () {},
         onCopyLink: () {},
         onRemoveLink: () {},
+        onFocusChange: (value) {},
         onSubmitted: (text) {
           submittedText = text;
         },