mirror of
https://github.com/dergigi/boris.git
synced 2025-12-17 06:34:24 +01:00
Merge pull request #36 from dergigi/mobile-highlighting
Fix mobile text selection detection for highlighting
This commit is contained in:
@@ -133,7 +133,7 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
|
||||
return selectedUrl || `${title || ''}:${(markdown || html || '').length}`
|
||||
}, [selectedUrl, title, markdown, html])
|
||||
|
||||
const { contentRef, handleSelectionEnd } = useHighlightInteractions({
|
||||
const { contentRef } = useHighlightInteractions({
|
||||
onHighlightClick,
|
||||
selectedHighlightId,
|
||||
onTextSelection,
|
||||
@@ -815,8 +815,6 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
|
||||
html={finalHtml}
|
||||
renderVideoLinksAsEmbeds={settings?.renderVideoLinksAsEmbeds === true}
|
||||
className="reader-markdown"
|
||||
onMouseUp={handleSelectionEnd}
|
||||
onTouchEnd={handleSelectionEnd}
|
||||
/>
|
||||
) : (
|
||||
<div className="reader-markdown">
|
||||
@@ -830,8 +828,6 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
|
||||
html={finalHtml || html || ''}
|
||||
renderVideoLinksAsEmbeds={settings?.renderVideoLinksAsEmbeds === true}
|
||||
className="reader-html"
|
||||
onMouseUp={handleSelectionEnd}
|
||||
onTouchEnd={handleSelectionEnd}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, forwardRef } from 'react'
|
||||
import { useMemo, forwardRef } from 'react'
|
||||
import ReactPlayer from 'react-player'
|
||||
import { classifyUrl } from '../utils/helpers'
|
||||
|
||||
@@ -6,8 +6,6 @@ interface VideoEmbedProcessorProps {
|
||||
html: string
|
||||
renderVideoLinksAsEmbeds: boolean
|
||||
className?: string
|
||||
onMouseUp?: (e: React.MouseEvent) => void
|
||||
onTouchEnd?: (e: React.TouchEvent) => void
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -17,9 +15,7 @@ interface VideoEmbedProcessorProps {
|
||||
const VideoEmbedProcessor = forwardRef<HTMLDivElement, VideoEmbedProcessorProps>(({
|
||||
html,
|
||||
renderVideoLinksAsEmbeds,
|
||||
className,
|
||||
onMouseUp,
|
||||
onTouchEnd
|
||||
className
|
||||
}, ref) => {
|
||||
// Process HTML and extract video URLs in a single pass to keep them in sync
|
||||
const { processedHtml, videoUrls } = useMemo(() => {
|
||||
@@ -109,8 +105,6 @@ const VideoEmbedProcessor = forwardRef<HTMLDivElement, VideoEmbedProcessorProps>
|
||||
ref={ref}
|
||||
className={className}
|
||||
dangerouslySetInnerHTML={{ __html: processedHtml }}
|
||||
onMouseUp={onMouseUp}
|
||||
onTouchEnd={onTouchEnd}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -119,7 +113,7 @@ const VideoEmbedProcessor = forwardRef<HTMLDivElement, VideoEmbedProcessorProps>
|
||||
const parts = processedHtml.split(/(__VIDEO_EMBED_\d+__)/)
|
||||
|
||||
return (
|
||||
<div ref={ref} className={className} onMouseUp={onMouseUp} onTouchEnd={onTouchEnd}>
|
||||
<div ref={ref} className={className}>
|
||||
{parts.map((part, index) => {
|
||||
const videoMatch = part.match(/^__VIDEO_EMBED_(\d+)__$/)
|
||||
if (videoMatch) {
|
||||
|
||||
@@ -93,9 +93,8 @@ export const useHighlightInteractions = ({
|
||||
return () => clearTimeout(timeoutId)
|
||||
}, [selectedHighlightId, contentVersion])
|
||||
|
||||
// Handle text selection (works for both mouse and touch)
|
||||
const handleSelectionEnd = useCallback(() => {
|
||||
setTimeout(() => {
|
||||
// Shared function to check and handle text selection
|
||||
const checkSelection = useCallback(() => {
|
||||
const selection = window.getSelection()
|
||||
if (!selection || selection.rangeCount === 0) {
|
||||
onClearSelection?.()
|
||||
@@ -110,9 +109,21 @@ export const useHighlightInteractions = ({
|
||||
} else {
|
||||
onClearSelection?.()
|
||||
}
|
||||
}, 10)
|
||||
}, [onTextSelection, onClearSelection])
|
||||
|
||||
return { contentRef, handleSelectionEnd }
|
||||
// Listen to selectionchange events for immediate detection (works reliably on mobile)
|
||||
useEffect(() => {
|
||||
const handleSelectionChange = () => {
|
||||
// Use requestAnimationFrame to ensure selection is checked after browser updates
|
||||
requestAnimationFrame(checkSelection)
|
||||
}
|
||||
|
||||
document.addEventListener('selectionchange', handleSelectionChange)
|
||||
return () => {
|
||||
document.removeEventListener('selectionchange', handleSelectionChange)
|
||||
}
|
||||
}, [checkSelection])
|
||||
|
||||
return { contentRef }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user