Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change .web files to default and add .native #2835

Merged
merged 4 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/RNGestureHandlerModule.native.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Reexport the native module spec used by codegen. The relevant files are inluded on Android
// to ensure the compatibility with the old arch, while iOS doesn't require those at all.

import Module from './specs/NativeRNGestureHandlerModule';
export default Module;
108 changes: 104 additions & 4 deletions src/RNGestureHandlerModule.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,105 @@
// Reexport the native module spec used by codegen. The relevant files are inluded on Android
// to ensure the compatibility with the old arch, while iOS doesn't require those at all.
import React from 'react';

import Module from './specs/NativeRNGestureHandlerModule';
export default Module;
import type { ActionType } from './ActionType';
import { isNewWebImplementationEnabled } from './EnableNewWebImplementation';
import { Gestures, HammerGestures } from './web/Gestures';
import type { Config } from './web/interfaces';
import InteractionManager from './web/tools/InteractionManager';
import NodeManager from './web/tools/NodeManager';
import * as HammerNodeManager from './web_hammer/NodeManager';
import { GestureHandlerWebDelegate } from './web/tools/GestureHandlerWebDelegate';

export default {
handleSetJSResponder(tag: number, blockNativeResponder: boolean) {
console.warn('handleSetJSResponder: ', tag, blockNativeResponder);
},
handleClearJSResponder() {
console.warn('handleClearJSResponder: ');
},
createGestureHandler<T>(
handlerName: keyof typeof Gestures,
handlerTag: number,
config: T
) {
if (isNewWebImplementationEnabled()) {
if (!(handlerName in Gestures)) {
throw new Error(
`react-native-gesture-handler: ${handlerName} is not supported on web.`
);
}

const GestureClass = Gestures[handlerName];
NodeManager.createGestureHandler(
handlerTag,
new GestureClass(new GestureHandlerWebDelegate())
);
InteractionManager.getInstance().configureInteractions(
NodeManager.getHandler(handlerTag),
config as unknown as Config
);
} else {
if (!(handlerName in HammerGestures)) {
throw new Error(
`react-native-gesture-handler: ${handlerName} is not supported on web.`
);
}

// @ts-ignore If it doesn't exist, the error is thrown
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const GestureClass = HammerGestures[handlerName];
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
HammerNodeManager.createGestureHandler(handlerTag, new GestureClass());
}

this.updateGestureHandler(handlerTag, config as unknown as Config);
},
attachGestureHandler(
handlerTag: number,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
newView: any,
_actionType: ActionType,
propsRef: React.RefObject<unknown>
) {
if (
!(newView instanceof HTMLElement || newView instanceof React.Component)
) {
return;
}

if (isNewWebImplementationEnabled()) {
//@ts-ignore Types should be HTMLElement or React.Component
NodeManager.getHandler(handlerTag).init(newView, propsRef);

Check warning on line 71 in src/RNGestureHandlerModule.ts

View workflow job for this annotation

GitHub Actions / check

Unsafe call of an `any` typed value
} else {
//@ts-ignore Types should be HTMLElement or React.Component
HammerNodeManager.getHandler(handlerTag).setView(newView, propsRef);
}
},
updateGestureHandler(handlerTag: number, newConfig: Config) {
if (isNewWebImplementationEnabled()) {
NodeManager.getHandler(handlerTag).updateGestureConfig(newConfig);

InteractionManager.getInstance().configureInteractions(
NodeManager.getHandler(handlerTag),
newConfig
);
} else {
HammerNodeManager.getHandler(handlerTag).updateGestureConfig(newConfig);
}
},
getGestureHandlerNode(handlerTag: number) {
if (isNewWebImplementationEnabled()) {
return NodeManager.getHandler(handlerTag);
} else {
return HammerNodeManager.getHandler(handlerTag);
}
},
dropGestureHandler(handlerTag: number) {
if (isNewWebImplementationEnabled()) {
NodeManager.dropGestureHandler(handlerTag);
} else {
HammerNodeManager.dropGestureHandler(handlerTag);
}
},
// eslint-disable-next-line @typescript-eslint/no-empty-function
flushOperations() {},
};
105 changes: 0 additions & 105 deletions src/RNGestureHandlerModule.web.ts

This file was deleted.

3 changes: 3 additions & 0 deletions src/RNRenderer.native.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
export { default as RNRenderer } from 'react-native/Libraries/Renderer/shims/ReactNative';
6 changes: 3 additions & 3 deletions src/RNRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
export { default as RNRenderer } from 'react-native/Libraries/Renderer/shims/ReactNative';
export const RNRenderer = {
findHostInstance_DEPRECATED: (_ref: any) => null,

Check warning on line 2 in src/RNRenderer.ts

View workflow job for this annotation

GitHub Actions / check

Unexpected any. Specify a different type
};
3 changes: 0 additions & 3 deletions src/RNRenderer.web.ts

This file was deleted.

148 changes: 148 additions & 0 deletions src/components/GestureComponents.native.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import * as React from 'react';
import {
PropsWithChildren,
ForwardedRef,
RefAttributes,
ReactElement,
} from 'react';
import {
ScrollView as RNScrollView,
ScrollViewProps as RNScrollViewProps,
Switch as RNSwitch,
SwitchProps as RNSwitchProps,
TextInput as RNTextInput,
TextInputProps as RNTextInputProps,
DrawerLayoutAndroid as RNDrawerLayoutAndroid,
DrawerLayoutAndroidProps as RNDrawerLayoutAndroidProps,
FlatList as RNFlatList,
FlatListProps as RNFlatListProps,
RefreshControl as RNRefreshControl,
} from 'react-native';

import createNativeWrapper from '../handlers/createNativeWrapper';

import {
NativeViewGestureHandlerProps,
nativeViewProps,
} from '../handlers/NativeViewGestureHandler';

import { toArray } from '../utils';

export const RefreshControl = createNativeWrapper(RNRefreshControl, {
disallowInterruption: true,
shouldCancelWhenOutside: false,
});
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type RefreshControl = typeof RefreshControl & RNRefreshControl;

const GHScrollView = createNativeWrapper<PropsWithChildren<RNScrollViewProps>>(
RNScrollView,
{
disallowInterruption: true,
shouldCancelWhenOutside: false,
}
);
export const ScrollView = React.forwardRef<
RNScrollView,
RNScrollViewProps & NativeViewGestureHandlerProps
>((props, ref) => {
const refreshControlGestureRef = React.useRef<RefreshControl>(null);
const { refreshControl, waitFor, ...rest } = props;

return (
<GHScrollView
{...rest}
// @ts-ignore `ref` exists on `GHScrollView`
ref={ref}
waitFor={[...toArray(waitFor ?? []), refreshControlGestureRef]}
// @ts-ignore we don't pass `refreshing` prop as we only want to override the ref
refreshControl={
refreshControl
? React.cloneElement(refreshControl, {
// @ts-ignore for reasons unknown to me, `ref` doesn't exist on the type inferred by TS
ref: refreshControlGestureRef,
})
: undefined
}
/>
);
});
// backward type compatibility with https://github.com/software-mansion/react-native-gesture-handler/blob/db78d3ca7d48e8ba57482d3fe9b0a15aa79d9932/react-native-gesture-handler.d.ts#L440-L457
// include methods of wrapped components by creating an intersection type with the RN component instead of duplicating them.
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type ScrollView = typeof GHScrollView & RNScrollView;

export const Switch = createNativeWrapper<RNSwitchProps>(RNSwitch, {
shouldCancelWhenOutside: false,
shouldActivateOnStart: true,
disallowInterruption: true,
});
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type Switch = typeof Switch & RNSwitch;

export const TextInput = createNativeWrapper<RNTextInputProps>(RNTextInput);
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type TextInput = typeof TextInput & RNTextInput;

export const DrawerLayoutAndroid = createNativeWrapper<
PropsWithChildren<RNDrawerLayoutAndroidProps>
>(RNDrawerLayoutAndroid, { disallowInterruption: true });
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type DrawerLayoutAndroid = typeof DrawerLayoutAndroid &
RNDrawerLayoutAndroid;

export const FlatList = React.forwardRef((props, ref) => {
const refreshControlGestureRef = React.useRef<RefreshControl>(null);

const { waitFor, refreshControl, ...rest } = props;

const flatListProps = {};
const scrollViewProps = {};
for (const [propName, value] of Object.entries(rest)) {
// https://github.com/microsoft/TypeScript/issues/26255
if ((nativeViewProps as readonly string[]).includes(propName)) {
// @ts-ignore - this function cannot have generic type so we have to ignore this error
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
scrollViewProps[propName] = value;
} else {
// @ts-ignore - this function cannot have generic type so we have to ignore this error
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
flatListProps[propName] = value;
}
}

return (
// @ts-ignore - this function cannot have generic type so we have to ignore this error
<RNFlatList
ref={ref}
{...flatListProps}
renderScrollComponent={(scrollProps) => (
<ScrollView
{...{
...scrollProps,
...scrollViewProps,
waitFor: [...toArray(waitFor ?? []), refreshControlGestureRef],
}}
/>
)}
// @ts-ignore we don't pass `refreshing` prop as we only want to override the ref
refreshControl={
refreshControl
? React.cloneElement(refreshControl, {
// @ts-ignore for reasons unknown to me, `ref` doesn't exist on the type inferred by TS
ref: refreshControlGestureRef,
})
: undefined
}
/>
);
}) as <ItemT = any>(
props: PropsWithChildren<
RNFlatListProps<ItemT> &
RefAttributes<FlatList<ItemT>> &
NativeViewGestureHandlerProps
>,
ref: ForwardedRef<FlatList<ItemT>>
) => ReactElement | null;
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type FlatList<ItemT = any> = typeof FlatList & RNFlatList<ItemT>;
Loading
Loading