From 1ec21b67df64992bf472fc17bc3842369aa313a7 Mon Sep 17 00:00:00 2001
From: Mohamed Bassem <me@mbassem.com>
Date: Sun, 12 Jan 2025 13:38:09 +0000
Subject: fix: Keep user selection on text highlight

---
 .../dashboard/preview/BookmarkHtmlHighlighter.tsx  | 34 +++++++++++++++++++---
 1 file changed, 30 insertions(+), 4 deletions(-)

(limited to 'apps/web/components/dashboard/preview/BookmarkHtmlHighlighter.tsx')

diff --git a/apps/web/components/dashboard/preview/BookmarkHtmlHighlighter.tsx b/apps/web/components/dashboard/preview/BookmarkHtmlHighlighter.tsx
index 89472184..bed229a6 100644
--- a/apps/web/components/dashboard/preview/BookmarkHtmlHighlighter.tsx
+++ b/apps/web/components/dashboard/preview/BookmarkHtmlHighlighter.tsx
@@ -136,11 +136,30 @@ function BookmarkHTMLHighlighter({
     highlights.forEach((highlight) => {
       applyHighlightByOffset(highlight);
     });
-    if (pendingHighlight) {
-      applyHighlightByOffset(pendingHighlight);
-    }
   });
 
+  // Re-apply the selection when the pending range changes
+  useEffect(() => {
+    if (!pendingHighlight) {
+      return;
+    }
+    if (!contentRef.current) {
+      return;
+    }
+    const ranges = getRangeFromHighlight(pendingHighlight);
+    if (!ranges) {
+      return;
+    }
+    const newRange = document.createRange();
+    newRange.setStart(ranges[0].node, ranges[0].start);
+    newRange.setEnd(
+      ranges[ranges.length - 1].node,
+      ranges[ranges.length - 1].end,
+    );
+    window.getSelection()?.removeAllRanges();
+    window.getSelection()?.addRange(newRange);
+  }, [pendingHighlight, contentRef]);
+
   const handleMouseUp = (e: React.MouseEvent) => {
     const selection = window.getSelection();
 
@@ -250,7 +269,7 @@ function BookmarkHTMLHighlighter({
     return highlight;
   };
 
-  const applyHighlightByOffset = (highlight: Highlight) => {
+  const getRangeFromHighlight = (highlight: Highlight) => {
     if (!contentRef.current) return;
 
     let currentOffset = 0;
@@ -279,7 +298,14 @@ function BookmarkHTMLHighlighter({
 
       currentOffset += nodeLength;
     }
+    return ranges;
+  };
 
+  const applyHighlightByOffset = (highlight: Highlight) => {
+    const ranges = getRangeFromHighlight(highlight);
+    if (!ranges) {
+      return;
+    }
     // Apply highlights to found ranges
     ranges.forEach(({ node, start, end }) => {
       if (start > 0) {
-- 
cgit v1.2.3-70-g09d2

