More moves to react-query for key library functions

This commit is contained in:
Jackson Harper
2024-07-29 17:30:47 +08:00
parent 457d1d9de9
commit 137283db0a
33 changed files with 697 additions and 755 deletions

View File

@ -54,7 +54,7 @@ export async function createHighlight(
if (!input.selection.selection) {
return {}
}
console.log(' overlapping: ', input.selection.overlapHighlights)
const shouldMerge = input.selection.overlapHighlights.length > 0
const { range, selection } = input.selection

View File

@ -8,19 +8,20 @@ import type { SelectionAttributes } from './highlightHelpers'
/**
* Get the range of text with {@link SelectionAttributes} that user has selected
*
*
* Event Handlers for detecting/using new highlight selection are registered
*
*
* If the new highlight selection overlaps with existing highlights, the new selection is merged.
*
*
* @param highlightLocations existing highlights
* @returns selection range and its setter
*/
export function useSelection(
highlightLocations: HighlightLocation[]
): [SelectionAttributes | null, (x: SelectionAttributes | null) => void] {
const [touchStartPos, setTouchStartPos] =
useState<{ x: number; y: number } | undefined>(undefined)
const [touchStartPos, setTouchStartPos] = useState<
{ x: number; y: number } | undefined
>(undefined)
const [selectionAttributes, setSelectionAttributes] =
useState<SelectionAttributes | null>(null)
@ -246,32 +247,38 @@ async function makeSelectionRange(): Promise<
/**
* Edge case:
* If the selection ends on range endContainer (or startContainer in reverse select) but no text is selected (i.e. selection ends at
* an empty area), the preceding text is highlighted due to range normalizing.
* If the selection ends on range endContainer (or startContainer in reverse select) but no text is selected (i.e. selection ends at
* an empty area), the preceding text is highlighted due to range normalizing.
* This is a visual bug and would sometimes lead to weird highlight behavior during removal.
*/
const selectionEndNode = selection.focusNode
const selectionEndOffset = selection.focusOffset
const selectionStartNode = isReverseSelected ? range.endContainer : range.startContainer
const selectionStartNode = isReverseSelected
? range.endContainer
: range.startContainer
if (selectionEndNode?.nodeType === Node.TEXT_NODE) {
const selectionEndNodeEdgeIndex = isReverseSelected ? selectionEndNode.textContent?.length : 0
const selectionEndNodeEdgeIndex = isReverseSelected
? selectionEndNode.textContent?.length
: 0
if (selectionStartNode !== selectionEndNode &&
selectionEndOffset == selectionEndNodeEdgeIndex) {
clipRangeToNearestAnchor(range, selectionEndNode, isReverseSelected)
if (
selectionStartNode !== selectionEndNode &&
selectionEndOffset == selectionEndNodeEdgeIndex
) {
clipRangeToNearestAnchor(range, selectionEndNode, isReverseSelected)
}
}
}
return isRangeAllowed ? { range, isReverseSelected, selection } : undefined
}
/**
* Clip selection range to the beginning/end of the adjacent anchor element
*
*
* @param range selection range
* @param selectionEndNode the node where the selection ended at
* @param isReverseSelected
* @param isReverseSelected
*/
const clipRangeToNearestAnchor = (
range: Range,
@ -279,30 +286,44 @@ const clipRangeToNearestAnchor = (
isReverseSelected: boolean
) => {
let nearestAnchorElement = selectionEndNode.parentElement
while (nearestAnchorElement !== null && !nearestAnchorElement.hasAttribute('data-omnivore-anchor-idx')) {
nearestAnchorElement = nearestAnchorElement.parentElement;
while (
nearestAnchorElement !== null &&
!nearestAnchorElement.hasAttribute('data-omnivore-anchor-idx')
) {
nearestAnchorElement = nearestAnchorElement.parentElement
}
if (!nearestAnchorElement) {
throw Error('Unable to find nearest anchor element for node: ' + selectionEndNode)
throw Error(
'Unable to find nearest anchor element for node: ' + selectionEndNode
)
}
let anchorId = Number(nearestAnchorElement.getAttribute('data-omnivore-anchor-idx')!)
let anchorId = Number(
nearestAnchorElement.getAttribute('data-omnivore-anchor-idx')!
)
let adjacentAnchorId, adjacentAnchor, adjacentAnchorOffset
if (isReverseSelected) {
// move down to find adjacent anchor node and clip at its beginning
adjacentAnchorId = anchorId + 1
adjacentAnchor = document.querySelectorAll(`[data-omnivore-anchor-idx='${adjacentAnchorId}']`)[0]
adjacentAnchor = document.querySelectorAll(
`[data-omnivore-anchor-idx='${adjacentAnchorId}']`
)[0]
adjacentAnchorOffset = 0
range.setStart(adjacentAnchor, adjacentAnchorOffset)
} else {
// move up to find adjacent anchor node and clip at its end
do {
adjacentAnchorId = --anchorId
adjacentAnchor = document.querySelectorAll(`[data-omnivore-anchor-idx='${adjacentAnchorId}']`)[0]
adjacentAnchor = document.querySelectorAll(
`[data-omnivore-anchor-idx='${adjacentAnchorId}']`
)[0]
} while (adjacentAnchor.contains(selectionEndNode))
if (adjacentAnchor.textContent) {
let lastTextNodeChild = adjacentAnchor.lastChild
while (!!lastTextNodeChild && lastTextNodeChild.nodeType !== Node.TEXT_NODE) {
lastTextNodeChild = lastTextNodeChild.previousSibling;
while (
!!lastTextNodeChild &&
lastTextNodeChild.nodeType !== Node.TEXT_NODE
) {
lastTextNodeChild = lastTextNodeChild.previousSibling
}
adjacentAnchor = lastTextNodeChild
adjacentAnchorOffset = adjacentAnchor?.nodeValue?.length ?? 0
@ -326,7 +347,7 @@ export type RangeEndPos = {
/**
* Return coordinates of the screen area occupied by the last line of user selection
*
*
* @param range range of user selection
* @param getFirst whether to get first line of user selection. Get last if false (default)
* @returns {RangeEndPos} selection coordinates