Skip to content

Commit

Permalink
refactor: use PanResponder
Browse files Browse the repository at this point in the history
  • Loading branch information
CodyJasonBennett committed Sep 3, 2023
1 parent 0e82927 commit 9ab3b97
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 37 deletions.
4 changes: 4 additions & 0 deletions packages/fiber/__mocks__/react-native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,7 @@ export const StyleSheet = {
bottom: 0,
},
}

export const PanResponder = {
create: () => ({ panHandlers: {} }),
}
6 changes: 3 additions & 3 deletions packages/fiber/src/native/Canvas.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react'
import * as THREE from 'three'
import { View, ViewProps, Pressable, ViewStyle, LayoutChangeEvent, StyleSheet, PixelRatio } from 'react-native'
import { View, ViewProps, ViewStyle, LayoutChangeEvent, StyleSheet, PixelRatio } from 'react-native'
import { ExpoWebGLRenderingContext, GLView } from 'expo-gl'
import { useContextBridge, FiberProvider } from 'its-fine'
import { SetBlock, Block, ErrorBoundary, useMutableCallback } from '../core/utils'
Expand Down Expand Up @@ -144,9 +144,9 @@ const CanvasImpl = /*#__PURE__*/ React.forwardRef<View, Props>(
}, [canvas])

return (
<Pressable {...props} ref={viewRef} onLayout={onLayout} style={{ flex: 1, ...style }} {...bind}>
<View {...props} ref={viewRef} onLayout={onLayout} style={{ flex: 1, ...style }} {...bind}>
{width > 0 && <GLView onContextCreate={onContextCreate} style={StyleSheet.absoluteFill} />}
</Pressable>
</View>
)
},
)
Expand Down
58 changes: 24 additions & 34 deletions packages/fiber/src/native/events.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,40 @@
import { UseBoundStore } from 'zustand'
import { RootState } from '../core/store'
import { createEvents, DomEvent, EventManager, Events } from '../core/events'
import type { GestureResponderEvent } from 'react-native'

const EVENTS = {
PRESS: 'onPress',
PRESSIN: 'onPressIn',
PRESSOUT: 'onPressOut',
LONGPRESS: 'onLongPress',

HOVERIN: 'onHoverIn',
HOVEROUT: 'onHoverOut',
PRESSMOVE: 'onPressMove',
}

const DOM_EVENTS = {
[EVENTS.PRESS]: 'onClick',
[EVENTS.PRESSIN]: 'onPointerDown',
[EVENTS.PRESSOUT]: 'onPointerUp',
[EVENTS.LONGPRESS]: 'onDoubleClick',

[EVENTS.HOVERIN]: 'onPointerOver',
[EVENTS.HOVEROUT]: 'onPointerOut',
[EVENTS.PRESSMOVE]: 'onPointerMove',
}
import { type GestureResponderEvent, PanResponder } from 'react-native'

/** Default R3F event manager for react-native */
export function createTouchEvents(store: UseBoundStore<RootState>): EventManager<HTMLElement> {
const { handlePointer } = createEvents(store)

const handleTouch = (event: GestureResponderEvent, name: keyof typeof EVENTS) => {
const handleTouch = (event: GestureResponderEvent, name: string): true => {
event.persist()

// Apply offset
;(event as any).nativeEvent.offsetX = event.nativeEvent.locationX
;(event as any).nativeEvent.offsetY = event.nativeEvent.locationY

// Emulate DOM event
const callback = handlePointer(DOM_EVENTS[name])
return callback(event.nativeEvent as any)
const callback = handlePointer(name)
callback(event.nativeEvent as any)

return true
}

const responder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderTerminationRequest: () => true,
onStartShouldSetPanResponderCapture: (e) => handleTouch(e, 'onPointerCapture'),
onPanResponderStart: (e) => handleTouch(e, 'onPointerDown'),
onPanResponderMove: (e) => handleTouch(e, 'onPointerMove'),
onPanResponderEnd: (e) => handleTouch(e, 'onPointerUp'),
onPanResponderRelease: (e) => handleTouch(e, 'onPointerLeave'),
onPanResponderTerminate: (e) => handleTouch(e, 'onLostPointerCapture'),
onPanResponderReject: (e) => handleTouch(e, 'onLostPointerCapture'),
})

return {
priority: 1,
enabled: true,
Expand All @@ -52,16 +46,12 @@ export function createTouchEvents(store: UseBoundStore<RootState>): EventManager
},

connected: undefined,
handlers: Object.values(EVENTS).reduce(
(acc, name) => ({
...acc,
[name]: (event: GestureResponderEvent) => handleTouch(event, name as keyof typeof EVENTS),
}),
{},
) as unknown as Events,
handlers: responder.panHandlers as unknown as Events,
update: () => {
const { events, internal } = store.getState()
if (internal.lastEvent?.current && events.handlers) events.handlers.onPointerMove(internal.lastEvent.current)
if (internal.lastEvent?.current && events.handlers) {
handlePointer('onPointerMove')(internal.lastEvent.current)
}
},
connect: () => {
const { set, events } = store.getState()
Expand Down

0 comments on commit 9ab3b97

Please sign in to comment.