diff --git a/core/lib/utils/html/html_utils.dart b/core/lib/utils/html/html_utils.dart
index 7272fde12..1afac120f 100644
--- a/core/lib/utils/html/html_utils.dart
+++ b/core/lib/utils/html/html_utils.dart
@@ -61,56 +61,94 @@ class HtmlUtils {
viewId: '$viewId',
name: 'onSelectionChange',
}),
- "*"
- )
+ '*'
+ );
}
// When WebView
if (window.flutter_inappwebview) {
window.flutter_inappwebview.callHandler('onSelectionChange', data);
}
+ };
+
+ function getEditableFromSelection(selection) {
+ const node = selection?.focusNode || selection?.anchorNode;
+ const el = node?.nodeType === Node.ELEMENT_NODE ? node : node?.parentElement;
+ return (
+ el?.closest('.note-editor .note-editable') ||
+ document.querySelector('.note-editor .note-editable')
+ );
+ }
+
+ function clamp(v, min, max) {
+ return Math.max(min, Math.min(max, v));
}
document.addEventListener('selectionchange', function() {
const selection = window.getSelection();
const selectedText = selection ? selection.toString().trim() : '';
-
- if (selectedText === lastSelectedText) {
+
+ if (selectedText === lastSelectedText) return;
+ lastSelectedText = selectedText;
+
+ if (!selectedText || !selection || selection.rangeCount === 0) {
+ sendSelectionChangeMessage({ hasSelection: false });
return;
}
- lastSelectedText = selectedText;
-
- if (selectedText.length > 0 && selection.rangeCount > 0) {
- try {
- const range = selection.getRangeAt(0);
- const rects = range.getClientRects();
-
- if (rects.length > 0) {
- const rect = rects[rects.length - 1];
-
- sendSelectionChangeMessage({
- hasSelection: true,
- selectedText: selectedText,
- coordinates: {
- x: rect.right,
- y: rect.bottom,
- width: rect.width,
- height: rect.height
- }
- })
- }
- } catch (error) {
- console.error('Selection change error:', error);
- sendSelectionChangeMessage({
- hasSelection: false
- })
+
+ try {
+ const editable = getEditableFromSelection(selection);
+ if (!editable) {
+ sendSelectionChangeMessage({ hasSelection: false });
+ return;
}
- } else {
+
+ const editableRect = editable.getBoundingClientRect();
+ const padding = 8;
+ const safeHeight = Math.max(editableRect.height, padding * 2);
+
+ const range = selection.getRangeAt(0);
+ const rects = range.getClientRects();
+ if (!rects || rects.length === 0) {
+ sendSelectionChangeMessage({ hasSelection: false });
+ return;
+ }
+
+ const lastRect = rects[rects.length - 1];
+
+ let x = lastRect.right - editableRect.left;
+ let y = lastRect.bottom - editableRect.top;
+
+ const isInside =
+ lastRect.bottom >= editableRect.top &&
+ lastRect.top <= editableRect.bottom &&
+ lastRect.right >= editableRect.left &&
+ lastRect.left <= editableRect.right;
+
+ if (!isInside) {
+ x = padding;
+ y = safeHeight / 2;
+ }
+
+ x = clamp(x, padding, editableRect.width - padding);
+ y = clamp(y, padding, safeHeight - padding);
+
sendSelectionChangeMessage({
- hasSelection: false
- })
+ hasSelection: true,
+ selectedText,
+ coordinates: {
+ x,
+ y,
+ width: lastRect.width,
+ height: lastRect.height,
+ },
+ });
+ } catch (error) {
+ console.error('Selection change error:', error);
+ sendSelectionChangeMessage({ hasSelection: false });
}
- });''',
+ });
+ ''',
name: 'onSelectionChange');
static const collapseSelectionToEnd = (