mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: highlight selection when tap on the link menu
This commit is contained in:
parent
c07af9007c
commit
dd9cac9c1d
@ -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(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ void main() async {
|
|||||||
onOpenLink: () {},
|
onOpenLink: () {},
|
||||||
onCopyLink: () {},
|
onCopyLink: () {},
|
||||||
onRemoveLink: () {},
|
onRemoveLink: () {},
|
||||||
|
onFocusChange: (value) {},
|
||||||
onSubmitted: (text) {
|
onSubmitted: (text) {
|
||||||
submittedText = text;
|
submittedText = text;
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user