Fix quote selection reply in iOS Safari (#544)

* Handle quote reply of selections in iOS Safari

Approach borrowed from https://stackoverflow.com/a/72537632

Basically this makes a copy of the selection when the "touchend" event
occurs, so we can use it for processing later

This code listens to that event for each instance of the reply component,
removing the event listener on unmount

* Update docker-compose up command in dev notes

---------

Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
This commit is contained in:
SatsAllDay 2023-10-05 20:32:54 -04:00 committed by GitHub
parent 707fa33552
commit 6b8820b7ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 4 deletions

View File

@ -40,15 +40,42 @@ export default forwardRef(function Reply ({ item, onSuccess, replyOpen, children
const parentId = item.id
const replyInput = useRef(null)
const formInnerRef = useRef()
// Start block to handle iOS Safari's weird selection clearing behavior
const savedRange = useRef()
const savedRangeNode = useRef()
const onTouchEnd = useCallback(() => {
const selection = document.getSelection()
if (!selection || selection.rangeCount === 0 || selection.getRangeAt(0).length === 0) {
return
}
const range = selection.getRangeAt(0)
savedRangeNode.current = range.commonAncestorContainer
savedRange.current = range.cloneContents()
}, [])
useEffect(() => {
document.addEventListener('touchend', onTouchEnd)
return () => document.removeEventListener('touchend', onTouchEnd)
}, [])
// End block to handle iOS Safari's weird selection clearing behavior
useImperativeHandle(ref, () => ({
quoteReply: ({ selectionOnly }) => {
if (!reply) {
setReply(true)
}
const selection = window.getSelection()
const selectedText = selection.isCollapsed ? undefined : selection.toString()
const isSelectedTextInTarget = contentContainerRef?.current?.contains(selection.anchorNode)
if ((selection.isCollapsed || !isSelectedTextInTarget) && selectionOnly) return
let selectedText = selection.isCollapsed ? undefined : selection.toString()
let isSelectedTextInTarget = contentContainerRef?.current?.contains(selection.anchorNode)
// Start block to handle iOS Safari's weird selection clearing behavior
if (!selectedText && savedRange.current && savedRangeNode.current) {
selectedText = savedRange.current.textContent
isSelectedTextInTarget = contentContainerRef?.current?.contains(savedRangeNode.current)
}
// End block to handle iOS Safari's weird selection clearing behavior
if ((selection.isCollapsed || !isSelectedTextInTarget || !selectedText) && selectionOnly) return
const textToQuote = isSelectedTextInTarget ? selectedText : item.text
let updatedValue
if (formInnerRef.current && formInnerRef.current.values && !formInnerRef.current.values.text) {

View File

@ -3,7 +3,7 @@
### `nvm use 18`
Switch to use nodejs version 18 in your current shell
### `docker-compose up -d`
### `docker-compose up --build -d`
Bring up stacker news app via local docker services
### `docker-compose down`