mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-06 16:16:42 +08:00
fix(glass): support pointer input in Safari (#599)
This commit is contained in:
@@ -263,6 +263,37 @@ describe('glass optical surface discovery', () => {
|
|||||||
scope.stop()
|
scope.stop()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('routes desktop pointer input when the browser does not expose TouchEvent', () => {
|
||||||
|
vi.stubGlobal('TouchEvent', undefined)
|
||||||
|
const scrollListener = vi.fn()
|
||||||
|
const scope = effectScope()
|
||||||
|
scope.run(() => {
|
||||||
|
const source = useGlassOpticalInteractionSource()
|
||||||
|
source.subscribe('scroll', scrollListener)
|
||||||
|
})
|
||||||
|
|
||||||
|
window.dispatchEvent(new MouseEvent('pointermove', { clientX: 400, clientY: 400 }))
|
||||||
|
|
||||||
|
expect(scrollListener).toHaveBeenCalledOnce()
|
||||||
|
scope.stop()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('keeps touch ownership when the browser does not expose TouchEvent', () => {
|
||||||
|
vi.stubGlobal('TouchEvent', undefined)
|
||||||
|
const scrollListener = vi.fn()
|
||||||
|
const scope = effectScope()
|
||||||
|
scope.run(() => {
|
||||||
|
const source = useGlassOpticalInteractionSource()
|
||||||
|
source.subscribe('scroll', scrollListener)
|
||||||
|
})
|
||||||
|
|
||||||
|
dispatchTouchEvent('touchstart', [{ clientX: 400, clientY: 400, identifier: 7 }])
|
||||||
|
dispatchTouchEvent('touchmove', [{ clientX: 420, clientY: 420, identifier: 7 }])
|
||||||
|
|
||||||
|
expect(scrollListener).toHaveBeenCalledTimes(2)
|
||||||
|
scope.stop()
|
||||||
|
})
|
||||||
|
|
||||||
it('detects a target surface added directly', () => {
|
it('detects a target surface added directly', () => {
|
||||||
const surface = document.createElement('section')
|
const surface = document.createElement('section')
|
||||||
surface.dataset.glassOpticalSurface = ''
|
surface.dataset.glassOpticalSurface = ''
|
||||||
|
|||||||
@@ -193,15 +193,17 @@ export function useGlassOpticalInteractionSource(): GlassOpticalInteractionSourc
|
|||||||
return touchOwners.get(changedTouch.identifier) ?? null
|
return touchOwners.get(changedTouch.identifier) ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isTouchInteractionEvent = (event: PointerEvent | TouchEvent): event is TouchEvent =>
|
||||||
|
event.type.startsWith('touch')
|
||||||
|
|
||||||
const dispatch = (event: PointerEvent | TouchEvent) => {
|
const dispatch = (event: PointerEvent | TouchEvent) => {
|
||||||
const owner =
|
const owner = isTouchInteractionEvent(event)
|
||||||
event instanceof TouchEvent
|
? resolveTouchOwner(event)
|
||||||
? resolveTouchOwner(event)
|
: resolvePointOwner(event.clientX, event.clientY)
|
||||||
: resolvePointOwner((event as PointerEvent).clientX, (event as PointerEvent).clientY)
|
|
||||||
if (!owner) return
|
if (!owner) return
|
||||||
|
|
||||||
for (const listener of listeners[owner]) listener(event)
|
for (const listener of listeners[owner]) listener(event)
|
||||||
if (event instanceof TouchEvent && (event.type === 'touchend' || event.type === 'touchcancel')) {
|
if (isTouchInteractionEvent(event) && (event.type === 'touchend' || event.type === 'touchcancel')) {
|
||||||
for (const touch of Array.from(event.changedTouches)) touchOwners.delete(touch.identifier)
|
for (const touch of Array.from(event.changedTouches)) touchOwners.delete(touch.identifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1901,8 +1903,7 @@ export function useGlassOpticalRenderer(options: UseGlassOpticalRendererOptions)
|
|||||||
? candidates.findIndex(candidate => candidate.key === activeInteractionClip)
|
? candidates.findIndex(candidate => candidate.key === activeInteractionClip)
|
||||||
: -1
|
: -1
|
||||||
if (activeIndex > 0) candidates.unshift(...candidates.splice(activeIndex, 1))
|
if (activeIndex > 0) candidates.unshift(...candidates.splice(activeIndex, 1))
|
||||||
const maxCount =
|
const maxCount = window.innerWidth <= 600 ? GLASS_OPTICAL_MAX_SURFACES_MOBILE : GLASS_OPTICAL_MAX_SURFACES_DESKTOP
|
||||||
window.innerWidth <= 600 ? GLASS_OPTICAL_MAX_SURFACES_MOBILE : GLASS_OPTICAL_MAX_SURFACES_DESKTOP
|
|
||||||
interactionClips = candidates.slice(0, maxCount)
|
interactionClips = candidates.slice(0, maxCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user