nandi/gleanpublic Fork 0
baffbf4
Commits
Clone
git clone https://git.rickub.com/nandi/glean.git
git clone ssh://git@rickub.com/nandi/glean.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

fix(web): handle text selection on mobileUnverified

Julien Robert committed 2026-07-12T23:08:59+02:00 Browse files
baffbf4 parent: dea5ae5
modified web/src/routes/articles/[id]/+page.svelte +24 -1
@@ -103,6 +103,25 @@
103103 if (text) openForSelection();
104104 }
105105
106+ // Mobile browsers (e.g. Chrome on Android) finalize text selections via
107+ // the selection handles and do not reliably emit mouseup afterwards. Poll
108+ // selectionchange so the popover appears once a selection inside the
109+ // article body becomes available.
110+ let selectionTimer: ReturnType<typeof setTimeout> | undefined;
111+ function onSelectionChange() {
112+ if (popoverEl?.contains(document.activeElement)) return;
113+ clearTimeout(selectionTimer);
114+ selectionTimer = setTimeout(() => {
115+ const sel = window.getSelection();
116+ if (!sel || sel.rangeCount === 0) return;
117+ const text = sel.toString().trim();
118+ if (!text) return;
119+ const range = sel.getRangeAt(0);
120+ if (!bodyEl?.contains(range.commonAncestorContainer)) return;
121+ openForSelection();
122+ }, 200);
123+ }
124+
106125 function closePopover() {
107126 popoverOpen = false;
108127 quoteValue = "";
@@ -195,7 +214,11 @@
195214 }
196215 </script>
197216
198-<svelte:window onmouseup={onMouseUp} onkeydown={onKeydown} />
217+<svelte:window
218+ onmouseup={onMouseUp}
219+ onkeydown={onKeydown}
220+/>
221+<svelte:document onselectionchange={onSelectionChange} />
199222
200223 <div class="mx-auto max-w-3xl">
201224 <!-- Top nav -->
@@ -103,6 +103,25 @@
103 if (text) openForSelection();103 if (text) openForSelection();
104 }104 }
105 105
106+ // Mobile browsers (e.g. Chrome on Android) finalize text selections via
107+ // the selection handles and do not reliably emit mouseup afterwards. Poll
108+ // selectionchange so the popover appears once a selection inside the
109+ // article body becomes available.
110+ let selectionTimer: ReturnType<typeof setTimeout> | undefined;
111+ function onSelectionChange() {
112+ if (popoverEl?.contains(document.activeElement)) return;
113+ clearTimeout(selectionTimer);
114+ selectionTimer = setTimeout(() => {
115+ const sel = window.getSelection();
116+ if (!sel || sel.rangeCount === 0) return;
117+ const text = sel.toString().trim();
118+ if (!text) return;
119+ const range = sel.getRangeAt(0);
120+ if (!bodyEl?.contains(range.commonAncestorContainer)) return;
121+ openForSelection();
122+ }, 200);
123+ }
124+
106 function closePopover() {125 function closePopover() {
107 popoverOpen = false;126 popoverOpen = false;
108 quoteValue = "";127 quoteValue = "";
@@ -195,7 +214,11 @@
195 }214 }
196 </script>215 </script>
197 216
198-<svelte:window onmouseup={onMouseUp} onkeydown={onKeydown} />217+<svelte:window
218+ onmouseup={onMouseUp}
219+ onkeydown={onKeydown}
220+/>
221+<svelte:document onselectionchange={onSelectionChange} />
199 222
200 <div class="mx-auto max-w-3xl">223 <div class="mx-auto max-w-3xl">
201 <!-- Top nav -->224 <!-- Top nav -->