appflowy-editor
appflowy-editor copied to clipboard
[FR] Hover on textspan with specific attribute
Description
Hi I am trying to create note taking functionality in my app. The user needs to be able to select a specific text and insert a note. When the user hovers over the text that has the note attached a popover should show.
I gotten to the point where I add a custom attribute and render it using a custom textSpan decorator. This works I can even attach a click handler but I cant get it to detect hover events.
Here is my current approach. This works for the most part but the hover events are not recognized.
Is this the right direction or am I missing something. Are there other ways I can do this?
InlineSpan customDecorator(
BuildContext context, Node node, int index, TextInsert text, TextSpan before, TextSpan after) {
final attributes = text.attributes;
if (attributes == null) {
return after;
}
final noteId = attributes[TiroRichTextKeys.note] as String?;
if (noteId != null) {
return noteText(noteId, editorState, context, node, index, text, before, after);
}
return after;
}
InlineSpan noteText(String noteId, EditorState state, BuildContext context, Node node, int index, TextInsert text,
TextSpan before, TextSpan after) {
return NoteTextSpan(
text: text.text,
state: state,
node: node,
after: after,
);
}
class NoteTextSpan extends TextSpan {
NoteTextSpan({
required String text,
required EditorState state,
required Node node,
required TextSpan after,
}) : super(
text: text,
style: after.style?.copyWith(
backgroundColor: Colors.amber.withValues(alpha: 0.3), // Apply background
),
mouseCursor: SystemMouseCursors.text,
recognizer: NoteTextRecognizer(
onTap: () {
print("Note clicked");
},
onHover: (bool value) {
print("Note hover:$value");
},
), // Handle clicks
);
}
class NoteTextRecognizer extends OneSequenceGestureRecognizer {
final VoidCallback onTap;
final ValueChanged<bool> onHover;
NoteTextRecognizer({required this.onTap, required this.onHover});
bool _isHovered = false;
@override
void addPointer(PointerDownEvent event) {
GestureBinding.instance.pointerRouter.addRoute(event.pointer, _handlePointer);
super.addPointer(event);
}
void _handlePointer(PointerEvent event) {
if (event is PointerUpEvent) {
onTap();
GestureBinding.instance.pointerRouter.removeRoute(event.pointer, _handlePointer);
} else if (event is PointerHoverEvent) {
if (!_isHovered) {
_isHovered = true;
onHover(true);
}
} else if (event is PointerExitEvent) {
if (_isHovered) {
_isHovered = false;
onHover(false);
}
}
}
@override
void handleEvent(PointerEvent event) {
if (event is PointerHoverEvent) {
onHover(true);
} else if (event is PointerExitEvent) {
onHover(false);
}
}
@override
String get debugDescription => 'note_text_recognizer';
@override
void didStopTrackingLastPointer(int pointer) {}
}
Impact
Users that want to customize there app
Additional Context
No response