feat: highlight selection when tap on the link menu

This commit is contained in:
Lucas.Xu 2022-08-29 12:02:47 +08:00
parent c07af9007c
commit dd9cac9c1d
5 changed files with 59 additions and 29 deletions

View File

@ -32,7 +32,9 @@ class EditorNodeWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Container(
color: Colors.red.withOpacity(0.1),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: node.children children: node.children
.map( .map(
@ -52,6 +54,7 @@ class EditorNodeWidget extends StatelessWidget {
), ),
) )
.toList(), .toList(),
),
); );
} }
} }

View File

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

View File

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

View File

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

View File

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