Update useCoarsePointer.ts

pull/3572/head
Steve Ruiz 2024-04-25 09:12:05 +01:00
rodzic 02404227d6
commit daca65d159
1 zmienionych plików z 53 dodań i 29 usunięć

Wyświetl plik

@ -5,44 +5,68 @@ import { useEditor } from './useEditor'
export function useCoarsePointer() {
const previousCursor = useRef<boolean | undefined>(undefined)
const editor = useEditor()
useEffect(() => {
// We'll track our own state for the pointer type
let isCoarse = editor.getInstanceState().isCoarsePointer
// 1.
// We'll use touch events / mouse events to detect coarse pointer.
// When the user touches the screen, we assume they have a coarse pointer
const handleTouchStart = () => {
if (isCoarse) return
isCoarse = true
editor.updateInstanceState({ isCoarsePointer: true })
}
// When the user moves the mouse, we assume they have a fine pointer
const handleMouseMove = () => {
if (!isCoarse) return
isCoarse = false
editor.updateInstanceState({ isCoarsePointer: false })
}
// Set up the listeners for touch and mouse events
window.addEventListener('touchstart', handleTouchStart)
window.addEventListener('mousemove', handleMouseMove)
// 2.
// We can also use the media query to detect / set the initial pointer type
// and update the state if the pointer type changes.
// We want the touch / mouse events to run even if the browser does not
// support matchMedia. We'll have to handle the media query changes
// conditionally in the code below.
const mql = window.matchMedia && window.matchMedia('(any-pointer: coarse)')
// This is a workaround for a Firefox bug where we don't correctly
// detect coarse VS fine pointer. For now, let's assume that you have a fine
// pointer if you're on Firefox on desktop.
if (
editor.environment.isFirefox &&
!editor.environment.isAndroid &&
!editor.environment.isIos
) {
editor.updateInstanceState({ isCoarsePointer: false })
return
const isForcedFinePointer =
editor.environment.isFirefox && !editor.environment.isAndroid && !editor.environment.isIos
const handleMediaQueryChange = () => {
const next = isForcedFinePointer ? false : mql.matches // get the value from the media query
if (isCoarse !== next) return // bail if the value hasn't changed
isCoarse = next // update the local value
editor.updateInstanceState({ isCoarsePointer: next }) // update the value in state
}
if (window.matchMedia) {
// Some devices have a touch screen but also a fine pointer (e.g. a mouse).
// If any pointer is coarse, we consider the device to have a coarse pointer.
// This is dynamically updated as the user switches between input devices.
const mql = window.matchMedia('(any-pointer: coarse)')
const handler = (coarse?: boolean) => {
const isCoarsePointer = coarse ?? !!mql.matches
if (isCoarsePointer === previousCursor.current) return
editor.updateInstanceState({ isCoarsePointer: coarse ?? !!mql.matches })
previousCursor.current = isCoarsePointer
}
if (mql) {
// set up the listener
mql.addEventListener('change', handleMediaQueryChange)
const touchStartHandler = () => handler(true)
const mouseMoveHandler = () => handler(false)
// and run the handler once to set the initial value
handleMediaQueryChange()
}
return () => {
window.removeEventListener('touchstart', handleTouchStart)
window.removeEventListener('mousemove', handleMouseMove)
handler()
if (mql) {
mql.addEventListener('change', () => handler())
window.addEventListener('touchstart', touchStartHandler)
window.addEventListener('mousemove', mouseMoveHandler)
return () => {
mql.removeEventListener('change', () => handler())
window.removeEventListener('touchstart', touchStartHandler)
window.removeEventListener('mousemove', mouseMoveHandler)
}
mql.removeEventListener('change', handleMediaQueryChange)
}
}
}, [editor])