From dd9cac9c1d4a681d6fdb859d0bc199fe7c12c189 Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Mon, 29 Aug 2022 12:02:47 +0800 Subject: [PATCH] feat: highlight selection when tap on the link menu --- .../lib/src/render/editor/editor_entry.dart | 43 ++++++++++--------- .../lib/src/render/link_menu/link_menu.dart | 8 ++++ .../src/render/rich_text/flowy_rich_text.dart | 7 ++- .../lib/src/render/toolbar/toolbar_item.dart | 29 ++++++++++--- .../test/render/link_menu/link_menu_test.dart | 1 + 5 files changed, 59 insertions(+), 29 deletions(-) diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/editor/editor_entry.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/editor/editor_entry.dart index e71dc7c79b..d14d44613f 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/editor/editor_entry.dart +++ b/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( - context: context, - node: child, - editorState: editorState, - ) - : NodeWidgetContext( - 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( + context: context, + node: child, + editorState: editorState, + ) + : NodeWidgetContext( + context: context, + node: child, + editorState: editorState, + ), + ), + ) + .toList(), + ), ); } } diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/link_menu/link_menu.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/link_menu/link_menu.dart index 07e1b947eb..13396a33c4 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/link_menu/link_menu.dart +++ b/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 createState() => _LinkMenuState(); @@ -29,11 +31,13 @@ class _LinkMenuState extends State { 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 { onPressed: onPressed, ); } + + void _onFocusChange() { + widget.onFocusChange(_focusNode.hasFocus); + } } diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/flowy_rich_text.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/flowy_rich_text.dart index 517f7dd4b8..473f29eaa7 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/flowy_rich_text.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/flowy_rich_text.dart @@ -257,8 +257,11 @@ class _FlowyRichTextState extends State 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, + ); }); }); }; diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/toolbar/toolbar_item.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/toolbar/toolbar_item.dart index 979f86cdd1..34b38c0444 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/toolbar/toolbar_item.dart +++ b/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; diff --git a/frontend/app_flowy/packages/appflowy_editor/test/render/link_menu/link_menu_test.dart b/frontend/app_flowy/packages/appflowy_editor/test/render/link_menu/link_menu_test.dart index 5b102b9ec1..cef16a1cec 100644 --- a/frontend/app_flowy/packages/appflowy_editor/test/render/link_menu/link_menu_test.dart +++ b/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; },