2023-11-21 18:35:37 +00:00
|
|
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
2023-11-21 03:37:57 +00:00
|
|
|
import { quote as quoteMd } from '../lib/md'
|
|
|
|
|
|
|
|
export function useQuoteReply ({ text }) {
|
|
|
|
const ref = useRef(null)
|
|
|
|
const [quote, setQuote] = useState(null)
|
2023-11-21 18:35:37 +00:00
|
|
|
const [selection, setSelection] = useState(null)
|
|
|
|
const to = useRef(null)
|
2023-11-21 03:37:57 +00:00
|
|
|
|
2023-11-21 18:35:37 +00:00
|
|
|
const onSelectionChange = useCallback(e => {
|
|
|
|
clearTimeout(to.current)
|
2023-11-21 03:37:57 +00:00
|
|
|
const selection = window.getSelection()
|
|
|
|
const selectedText = selection.isCollapsed ? undefined : selection.toString()
|
|
|
|
const isSelectedTextInTarget = ref?.current?.contains(selection.anchorNode)
|
|
|
|
|
2023-11-21 18:35:37 +00:00
|
|
|
if ((selection.isCollapsed || !isSelectedTextInTarget || !selectedText)) {
|
|
|
|
// selection is collapsed or not in target or empty
|
|
|
|
// but on button click we don't want to immediately clear selection
|
|
|
|
to.current = setTimeout(() => setSelection(null), 1000)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
setSelection(selectedText)
|
|
|
|
}, [ref?.current, setSelection])
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
document.addEventListener('selectionchange', onSelectionChange)
|
|
|
|
return () => document.removeEventListener('selectionchange', onSelectionChange)
|
|
|
|
}, [])
|
2023-11-21 03:37:57 +00:00
|
|
|
|
2023-11-21 18:35:37 +00:00
|
|
|
const quoteReply = useCallback(({ selectionOnly }) => {
|
|
|
|
if (selectionOnly && !selection) return
|
|
|
|
const textToQuote = selection || text
|
2023-11-21 03:37:57 +00:00
|
|
|
setQuote(quoteMd(textToQuote))
|
2023-11-21 18:35:37 +00:00
|
|
|
}, [selection, text])
|
2023-11-21 03:37:57 +00:00
|
|
|
|
|
|
|
const cancelQuote = useCallback(() => {
|
|
|
|
setQuote(null)
|
2023-11-21 18:35:37 +00:00
|
|
|
setSelection(null)
|
|
|
|
}, [setQuote, setSelection])
|
2023-11-21 03:37:57 +00:00
|
|
|
|
|
|
|
return { ref, quote, quoteReply, cancelQuote }
|
|
|
|
}
|