Skip to content

Commit

Permalink
Remove circular dependencies on web (#2783)
Browse files Browse the repository at this point in the history
## Description

While working on problems with scroll we discovered that Gesture Handler has many circular dependencies. This PR removes them from web implementation (the only one that's left is related to `hammer`). It also adds `madge` - tool to find circular dependencies in our project.

## Test plan

Run `yarn madge --extensions js,ts,tsx --circular src | grep web` from root.
  • Loading branch information
m-bert authored Mar 12, 2024
1 parent 489f6c2 commit 6c924a4
Show file tree
Hide file tree
Showing 19 changed files with 819 additions and 130 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"husky": "^8.0.1",
"jest": "^26.6.3",
"lint-staged": "^12.3.2",
"madge": "^6.1.0",
"prettier": "^2.7.1",
"react": "18.2.0",
"react-dom": "^16.12.0",
Expand Down
47 changes: 3 additions & 44 deletions src/RNGestureHandlerModule.web.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,14 @@
import React from 'react';

import { ActionType } from './ActionType';
import type { ActionType } from './ActionType';
import { isNewWebImplementationEnabled } from './EnableNewWebImplementation';

//GestureHandlers
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 PanGestureHandler from './web/handlers/PanGestureHandler';
import TapGestureHandler from './web/handlers/TapGestureHandler';
import LongPressGestureHandler from './web/handlers/LongPressGestureHandler';
import PinchGestureHandler from './web/handlers/PinchGestureHandler';
import RotationGestureHandler from './web/handlers/RotationGestureHandler';
import FlingGestureHandler from './web/handlers/FlingGestureHandler';
import NativeViewGestureHandler from './web/handlers/NativeViewGestureHandler';
import ManualGestureHandler from './web/handlers/ManualGestureHandler';
import HoverGestureHandler from './web/handlers/HoverGestureHandler';

//Hammer Handlers
import * as HammerNodeManager from './web_hammer/NodeManager';
import HammerNativeViewGestureHandler from './web_hammer/NativeViewGestureHandler';
import HammerPanGestureHandler from './web_hammer/PanGestureHandler';
import HammerTapGestureHandler from './web_hammer/TapGestureHandler';
import HammerLongPressGestureHandler from './web_hammer/LongPressGestureHandler';
import HammerPinchGestureHandler from './web_hammer/PinchGestureHandler';
import HammerRotationGestureHandler from './web_hammer/RotationGestureHandler';
import HammerFlingGestureHandler from './web_hammer/FlingGestureHandler';
import { Config } from './web/interfaces';
import { GestureHandlerWebDelegate } from './web/tools/GestureHandlerWebDelegate';

export const Gestures = {
NativeViewGestureHandler,
PanGestureHandler,
TapGestureHandler,
LongPressGestureHandler,
PinchGestureHandler,
RotationGestureHandler,
FlingGestureHandler,
ManualGestureHandler,
HoverGestureHandler,
};

export const HammerGestures = {
NativeViewGestureHandler: HammerNativeViewGestureHandler,
PanGestureHandler: HammerPanGestureHandler,
TapGestureHandler: HammerTapGestureHandler,
LongPressGestureHandler: HammerLongPressGestureHandler,
PinchGestureHandler: HammerPinchGestureHandler,
RotationGestureHandler: HammerRotationGestureHandler,
FlingGestureHandler: HammerFlingGestureHandler,
};

export default {
handleSetJSResponder(tag: number, blockNativeResponder: boolean) {
console.warn('handleSetJSResponder: ', tag, blockNativeResponder);
Expand Down
2 changes: 1 addition & 1 deletion src/components/DrawerLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
HandlerStateChangeEvent,
UserSelect,
ActiveCursor,
MouseButton,
} from '../handlers/gestureHandlerCommon';
import {
PanGestureHandler,
Expand All @@ -38,7 +39,6 @@ import {
TapGestureHandlerEventPayload,
} from '../handlers/TapGestureHandler';
import { State } from '../State';
import { MouseButton } from '../web/interfaces';

const DRAG_TOSS = 0.05;

Expand Down
11 changes: 9 additions & 2 deletions src/handlers/createHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { customDirectEventTypes } from './customDirectEventTypes';
// @ts-ignore - it isn't typed by TS & don't have definitelyTyped types
import deepEqual from 'lodash/isEqual';
import RNGestureHandlerModule from '../RNGestureHandlerModule';
import type RNGestureHandlerModuleWeb from '../RNGestureHandlerModule.web';
import { State } from '../State';
import {
handlerIDToTag,
Expand Down Expand Up @@ -154,6 +153,14 @@ type InternalEventHandlers = {
onGestureHandlerStateChange?: (event: any) => void;
};

type AttachGestureHandlerWeb = (
handlerTag: number,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
newView: any,
_actionType: ActionType,
propsRef: React.RefObject<unknown>
) => void;

const UNRESOLVED_REFS_RETRY_LIMIT = 1;

// TODO(TS) - make sure that BaseGestureHandlerProps doesn't need other generic parameter to work with custom properties.
Expand Down Expand Up @@ -320,7 +327,7 @@ export default function createHandler<
if (Platform.OS === 'web') {
// typecast due to dynamic resolution, attachGestureHandler should have web version signature in this branch
(
RNGestureHandlerModule.attachGestureHandler as typeof RNGestureHandlerModuleWeb.attachGestureHandler
RNGestureHandlerModule.attachGestureHandler as AttachGestureHandlerWeb
)(
this.handlerTag,
newViewTag,
Expand Down
10 changes: 9 additions & 1 deletion src/handlers/gestureHandlerCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { handlerIDToTag } from './handlersRegistry';
import { toArray } from '../utils';
import RNGestureHandlerModule from '../RNGestureHandlerModule';
import { ghQueueMicrotask } from '../ghQueueMicrotask';
import { MouseButton } from '../web/interfaces';
import { PointerType } from '../PointerType';

const commonProps = [
Expand Down Expand Up @@ -114,6 +113,15 @@ export type ActiveCursor =
| 'zoom-in'
| 'zoom-out';

export enum MouseButton {
LEFT = 1,
RIGHT = 2,
MIDDLE = 4,
BUTTON_4 = 8,
BUTTON_5 = 16,
ALL = 31,
}

export type TouchAction =
| 'auto'
| 'none'
Expand Down
2 changes: 1 addition & 1 deletion src/handlers/gestures/gesture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
GestureStateChangeEvent,
GestureUpdateEvent,
ActiveCursor,
MouseButton,
} from '../gestureHandlerCommon';
import { getNextHandlerTag } from '../handlersRegistry';
import { GestureStateManagerType } from './gestureStateManager';
Expand All @@ -17,7 +18,6 @@ import { RotationGestureHandlerEventPayload } from '../RotationGestureHandler';
import { TapGestureHandlerEventPayload } from '../TapGestureHandler';
import { NativeViewGestureHandlerPayload } from '../NativeViewGestureHandler';
import { isRemoteDebuggingEnabled } from '../../utils';
import { MouseButton } from '../../web/interfaces';

export type GestureType =
| BaseGesture<Record<string, unknown>>
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { initialize } from './init';

export { Directions } from './Directions';
export { State } from './State';
export { MouseButton } from './web/interfaces';
export { PointerType } from './PointerType';
export { default as gestureHandlerRootHOC } from './components/gestureHandlerRootHOC';
export { default as GestureHandlerRootView } from './components/GestureHandlerRootView';
Expand All @@ -19,6 +18,7 @@ export type {
// new api event types
GestureUpdateEvent,
GestureStateChangeEvent,
MouseButton,
} from './handlers/gestureHandlerCommon';
export type { GestureType } from './handlers/gestures/gesture';
export type {
Expand Down
41 changes: 41 additions & 0 deletions src/web/Gestures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Gesture Handlers
import PanGestureHandler from './handlers/PanGestureHandler';
import TapGestureHandler from './handlers/TapGestureHandler';
import LongPressGestureHandler from './handlers/LongPressGestureHandler';
import PinchGestureHandler from './handlers/PinchGestureHandler';
import RotationGestureHandler from './handlers/RotationGestureHandler';
import FlingGestureHandler from './handlers/FlingGestureHandler';
import NativeViewGestureHandler from './handlers/NativeViewGestureHandler';
import ManualGestureHandler from './handlers/ManualGestureHandler';
import HoverGestureHandler from './handlers/HoverGestureHandler';

//Hammer Handlers
import HammerNativeViewGestureHandler from '../web_hammer/NativeViewGestureHandler';
import HammerPanGestureHandler from '../web_hammer/PanGestureHandler';
import HammerTapGestureHandler from '../web_hammer/TapGestureHandler';
import HammerLongPressGestureHandler from '../web_hammer/LongPressGestureHandler';
import HammerPinchGestureHandler from '../web_hammer/PinchGestureHandler';
import HammerRotationGestureHandler from '../web_hammer/RotationGestureHandler';
import HammerFlingGestureHandler from '../web_hammer/FlingGestureHandler';

export const Gestures = {
NativeViewGestureHandler,
PanGestureHandler,
TapGestureHandler,
LongPressGestureHandler,
PinchGestureHandler,
RotationGestureHandler,
FlingGestureHandler,
ManualGestureHandler,
HoverGestureHandler,
};

export const HammerGestures = {
NativeViewGestureHandler: HammerNativeViewGestureHandler,
PanGestureHandler: HammerPanGestureHandler,
TapGestureHandler: HammerTapGestureHandler,
LongPressGestureHandler: HammerLongPressGestureHandler,
PinchGestureHandler: HammerPinchGestureHandler,
RotationGestureHandler: HammerRotationGestureHandler,
FlingGestureHandler: HammerFlingGestureHandler,
};
21 changes: 12 additions & 9 deletions src/web/handlers/GestureHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ import {
ResultTouchEvent,
TouchEventType,
EventTypes,
MouseButton,
} from '../interfaces';
import EventManager from '../tools/EventManager';
import GestureHandlerOrchestrator from '../tools/GestureHandlerOrchestrator';
import InteractionManager from '../tools/InteractionManager';
import PointerTracker, { TrackerElement } from '../tools/PointerTracker';
import { GestureHandlerDelegate } from '../tools/GestureHandlerDelegate';
import IGestureHandler from './IGestureHandler';
import { MouseButton } from '../../handlers/gestureHandlerCommon';
import { PointerType } from '../../PointerType';

export default abstract class GestureHandler {
export default abstract class GestureHandler implements IGestureHandler {
private lastSentState: State | null = null;
protected currentState: State = State.UNDETERMINED;

Expand All @@ -40,9 +41,11 @@ export default abstract class GestureHandler {
protected shouldResetProgress = false;
protected pointerType: PointerType = PointerType.MOUSE;

protected delegate: GestureHandlerDelegate<unknown>;
protected delegate: GestureHandlerDelegate<unknown, IGestureHandler>;

public constructor(delegate: GestureHandlerDelegate<unknown>) {
public constructor(
delegate: GestureHandlerDelegate<unknown, IGestureHandler>
) {
this.delegate = delegate;
}

Expand Down Expand Up @@ -229,7 +232,7 @@ export default abstract class GestureHandler {
this.activationIndex = value;
}

public shouldWaitForHandlerFailure(handler: GestureHandler): boolean {
public shouldWaitForHandlerFailure(handler: IGestureHandler): boolean {
if (handler === this) {
return false;
}
Expand All @@ -240,7 +243,7 @@ export default abstract class GestureHandler {
);
}

public shouldRequireToWaitForFailure(handler: GestureHandler): boolean {
public shouldRequireToWaitForFailure(handler: IGestureHandler): boolean {
if (handler === this) {
return false;
}
Expand All @@ -251,7 +254,7 @@ export default abstract class GestureHandler {
);
}

public shouldRecognizeSimultaneously(handler: GestureHandler): boolean {
public shouldRecognizeSimultaneously(handler: IGestureHandler): boolean {
if (handler === this) {
return true;
}
Expand All @@ -262,7 +265,7 @@ export default abstract class GestureHandler {
);
}

public shouldBeCancelledByOther(handler: GestureHandler): boolean {
public shouldBeCancelledByOther(handler: IGestureHandler): boolean {
if (handler === this) {
return false;
}
Expand Down Expand Up @@ -772,7 +775,7 @@ export default abstract class GestureHandler {
return this.config;
}

public getDelegate(): GestureHandlerDelegate<unknown> {
public getDelegate(): GestureHandlerDelegate<unknown, IGestureHandler> {
return this.delegate;
}

Expand Down
50 changes: 50 additions & 0 deletions src/web/handlers/IGestureHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { PointerType } from '../../PointerType';
import type { MouseButton } from '../../handlers/gestureHandlerCommon';
import type { State } from '../../State';
import type { Config } from '../interfaces';
import type EventManager from '../tools/EventManager';
import type { GestureHandlerDelegate } from '../tools/GestureHandlerDelegate';
import type PointerTracker from '../tools/PointerTracker';

export default interface IGestureHandler {
getTag: () => number;
getState: () => State;
getConfig: () => Config;
getDelegate: () => GestureHandlerDelegate<unknown, this>;

attachEventManager: (manager: EventManager<unknown>) => void;

isButtonInConfig: (
mouseButton: MouseButton | undefined
) => boolean | number | undefined;
getPointerType: () => PointerType;

getTracker: () => PointerTracker;
getTrackedPointersID: () => number[];

begin: () => void;
activate: () => void;
end: () => void;
fail: () => void;
cancel: () => void;

reset: () => void;
isEnabled: () => boolean;
isActive: () => boolean;
setActive: (value: boolean) => void;
isAwaiting: () => boolean;
setAwaiting: (value: boolean) => void;
setActivationIndex: (value: number) => void;
setShouldResetProgress: (value: boolean) => void;

shouldWaitForHandlerFailure: (handler: IGestureHandler) => boolean;
shouldRequireToWaitForFailure: (handler: IGestureHandler) => boolean;
shouldRecognizeSimultaneously: (handler: IGestureHandler) => boolean;
shouldBeCancelledByOther: (handler: IGestureHandler) => boolean;

sendEvent: (newState: State, oldState: State) => void;

updateGestureConfig: (config: Config) => void;

isButton?: () => boolean;
}
10 changes: 1 addition & 9 deletions src/web/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
UserSelect,
ActiveCursor,
MouseButton,
TouchAction,
} from '../handlers/gestureHandlerCommon';
import { Directions } from '../Directions';
Expand Down Expand Up @@ -139,15 +140,6 @@ export interface AdaptedEvent {
touchEventType?: TouchEventType;
}

export enum MouseButton {
LEFT = 1,
RIGHT = 2,
MIDDLE = 4,
BUTTON_4 = 8,
BUTTON_5 = 16,
ALL = 31,
}

export enum EventTypes {
DOWN,
ADDITIONAL_POINTER_DOWN,
Expand Down
7 changes: 3 additions & 4 deletions src/web/tools/GestureHandlerDelegate.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type GestureHandler from '../handlers/GestureHandler';
import { Config } from '../interfaces';

export interface MeasureResult {
Expand All @@ -8,10 +7,10 @@ export interface MeasureResult {
height: number;
}

export interface GestureHandlerDelegate<T> {
getView(): T;
export interface GestureHandlerDelegate<TComponent, THandler> {
getView(): TComponent;

init(viewRef: number, handler: GestureHandler): void;
init(viewRef: number, handler: THandler): void;
isPointerInBounds({ x, y }: { x: number; y: number }): boolean;
measureView(): MeasureResult;
reset(): void;
Expand Down
Loading

0 comments on commit 6c924a4

Please sign in to comment.