mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Enable highlight on selection behavior on iOS
This commit is contained in:
parent
4f2d05d3be
commit
92d5851aa9
6 changed files with 54 additions and 15 deletions
File diff suppressed because one or more lines are too long
|
|
@ -99,6 +99,7 @@ const App = () => {
|
|||
margin={window.margin}
|
||||
maxWidthPercentage={window.maxWidthPercentage}
|
||||
lineHeight={window.lineHeight}
|
||||
highlightOnRelease={true}
|
||||
highContrastFont={window.prefersHighContrastFont ?? true}
|
||||
articleMutations={{
|
||||
createHighlightMutation: (input) =>
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ type ArticleContainerProps = {
|
|||
maxWidthPercentage?: number
|
||||
highContrastFont?: boolean
|
||||
showHighlightsModal: boolean
|
||||
highlightOnRelease?: boolean
|
||||
setShowHighlightsModal: React.Dispatch<React.SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
|
|
@ -380,6 +381,7 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element {
|
|||
highlightBarDisabled={props.highlightBarDisabled}
|
||||
showHighlightsModal={props.showHighlightsModal}
|
||||
setShowHighlightsModal={props.setShowHighlightsModal}
|
||||
highlightOnRelease={props.highlightOnRelease}
|
||||
articleMutations={props.articleMutations}
|
||||
/>
|
||||
{showReportIssuesModal ? (
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ type HighlightsLayerProps = {
|
|||
isAppleAppEmbed: boolean
|
||||
highlightBarDisabled: boolean
|
||||
showHighlightsModal: boolean
|
||||
highlightOnRelease?: boolean
|
||||
scrollToHighlight: MutableRefObject<string | null>
|
||||
setShowHighlightsModal: React.Dispatch<React.SetStateAction<boolean>>
|
||||
articleMutations: ArticleMutations
|
||||
|
|
@ -262,7 +263,6 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
|||
}
|
||||
},
|
||||
[
|
||||
handleNativeShare,
|
||||
highlights,
|
||||
openNoteModal,
|
||||
props.articleId,
|
||||
|
|
@ -386,14 +386,14 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
|||
)
|
||||
|
||||
if (focusedHighlight) {
|
||||
if (canShareNative) {
|
||||
handleNativeShare(focusedHighlight.shortId)
|
||||
} else {
|
||||
setHighlightModalAction({
|
||||
highlight: focusedHighlight,
|
||||
highlightModalAction: 'share',
|
||||
})
|
||||
}
|
||||
// if (canShareNative) {
|
||||
// handleNativeShare(focusedHighlight.shortId)
|
||||
// } else {
|
||||
// setHighlightModalAction({
|
||||
// highlight: focusedHighlight,
|
||||
// highlightModalAction: 'share',
|
||||
// })
|
||||
// }
|
||||
} else {
|
||||
await createHighlightCallback('share')
|
||||
}
|
||||
|
|
@ -416,7 +416,6 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
|||
[
|
||||
createHighlightCallback,
|
||||
focusedHighlight,
|
||||
handleNativeShare,
|
||||
openNoteModal,
|
||||
props.highlightBarDisabled,
|
||||
props.isAppleAppEmbed,
|
||||
|
|
@ -425,6 +424,12 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
|
|||
]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (props.highlightOnRelease && selectionData?.wasDragEvent) {
|
||||
handleAction('create')
|
||||
}
|
||||
}, [selectionData])
|
||||
|
||||
const dispatchHighlightError = (action: string, error: unknown) => {
|
||||
if (props.isAppleAppEmbed) {
|
||||
window?.webkit?.messageHandlers.highlightAction?.postMessage({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
export type SelectionAttributes = {
|
||||
selection: Selection
|
||||
mouseEvent: React.MouseEvent
|
||||
range: Range
|
||||
focusPosition: {
|
||||
x: number
|
||||
|
|
@ -8,6 +7,7 @@ export type SelectionAttributes = {
|
|||
isReverseSelected: boolean
|
||||
}
|
||||
overlapHighlights: string[]
|
||||
wasDragEvent: boolean
|
||||
}
|
||||
|
||||
export const highlightIdAttribute = 'omnivore-highlight-id'
|
||||
|
|
|
|||
|
|
@ -9,16 +9,39 @@ import type { SelectionAttributes } from './highlightHelpers'
|
|||
export function useSelection(
|
||||
highlightLocations: HighlightLocation[]
|
||||
): [SelectionAttributes | null, (x: SelectionAttributes | null) => void] {
|
||||
const [touchStartPos, setTouchStartPos] = useState<
|
||||
{ x: number; y: number } | undefined
|
||||
>(undefined)
|
||||
const [selectionAttributes, setSelectionAttributes] =
|
||||
useState<SelectionAttributes | null>(null)
|
||||
|
||||
const handleTouchStart = useCallback(
|
||||
(event: TouchEvent) => {
|
||||
setTouchStartPos({
|
||||
x: event.touches[0].pageX,
|
||||
y: event.touches[0].pageY,
|
||||
})
|
||||
},
|
||||
[touchStartPos, setTouchStartPos]
|
||||
)
|
||||
|
||||
const handleFinishTouch = useCallback(
|
||||
async (mouseEvent) => {
|
||||
var wasDragEvent = false
|
||||
const tapAttributes = {
|
||||
tapX: mouseEvent.screenX,
|
||||
tapY: mouseEvent.screenY,
|
||||
}
|
||||
|
||||
if (touchStartPos) {
|
||||
if (
|
||||
Math.abs(touchStartPos.x - mouseEvent.pageX) > 10 ||
|
||||
Math.abs(touchStartPos.y - mouseEvent.pageY) > 10
|
||||
) {
|
||||
wasDragEvent = true
|
||||
}
|
||||
}
|
||||
|
||||
window?.AndroidWebKitMessenger?.handleIdentifiableMessage(
|
||||
'userTap',
|
||||
JSON.stringify(tapAttributes)
|
||||
|
|
@ -117,7 +140,7 @@ export function useSelection(
|
|||
|
||||
return setSelectionAttributes({
|
||||
selection,
|
||||
mouseEvent,
|
||||
wasDragEvent,
|
||||
range: mergedRange ?? range,
|
||||
focusPosition: {
|
||||
x: rangeRect[isReverseSelected ? 'left' : 'right'],
|
||||
|
|
@ -127,7 +150,7 @@ export function useSelection(
|
|||
overlapHighlights: overlapHighlights.map(({ id }) => id),
|
||||
})
|
||||
},
|
||||
[highlightLocations]
|
||||
[highlightLocations, touchStartPos, setTouchStartPos]
|
||||
)
|
||||
|
||||
const copyTextSelection = useCallback(async () => {
|
||||
|
|
@ -141,17 +164,25 @@ export function useSelection(
|
|||
|
||||
useEffect(() => {
|
||||
document.addEventListener('mouseup', handleFinishTouch)
|
||||
document.addEventListener('touchstart', handleTouchStart)
|
||||
document.addEventListener('touchend', handleFinishTouch)
|
||||
document.addEventListener('contextmenu', handleFinishTouch)
|
||||
document.addEventListener('copyTextSelection', copyTextSelection)
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mouseup', handleFinishTouch)
|
||||
document.removeEventListener('touchstart', handleTouchStart)
|
||||
document.removeEventListener('touchend', handleFinishTouch)
|
||||
document.removeEventListener('contextmenu', handleFinishTouch)
|
||||
document.removeEventListener('copyTextSelection', copyTextSelection)
|
||||
}
|
||||
}, [highlightLocations, handleFinishTouch, copyTextSelection])
|
||||
}, [
|
||||
highlightLocations,
|
||||
handleFinishTouch,
|
||||
copyTextSelection,
|
||||
touchStartPos,
|
||||
setTouchStartPos,
|
||||
])
|
||||
|
||||
return [selectionAttributes, setSelectionAttributes]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue