@@ -87,6 +87,154 @@ - (CGPoint)getLastLocation
8787
8888@end
8989
90+ #else
91+
92+ @interface RNBetterSwipeGestureRecognizer : NSGestureRecognizer {
93+ dispatch_block_t failFlingAction;
94+ int maxDuration;
95+ int minVelocity;
96+ double defaultAlignmentCone;
97+ double axialDeviationCosine;
98+ double diagonalDeviationCosine;
99+ }
100+
101+ @property (atomic , assign ) RNGestureHandlerDirection direction;
102+ @property (atomic , assign ) int numberOfTouchesRequired;
103+
104+ - (id )initWithGestureHandler : (RNGestureHandler *)gestureHandler ;
105+
106+ @end
107+
108+ @implementation RNBetterSwipeGestureRecognizer {
109+ __weak RNGestureHandler *_gestureHandler;
110+
111+ NSPoint startPosition;
112+ double startTime;
113+ }
114+
115+ - (id )initWithGestureHandler : (RNGestureHandler *)gestureHandler
116+ {
117+ if ((self = [super initWithTarget: self action: @selector (handleGesture: )])) {
118+ _gestureHandler = gestureHandler;
119+
120+ maxDuration = 1.0 ;
121+ minVelocity = 700 ;
122+
123+ defaultAlignmentCone = 30 ;
124+ axialDeviationCosine = [self coneToDeviation: defaultAlignmentCone];
125+ diagonalDeviationCosine = [self coneToDeviation: (90 - defaultAlignmentCone)];
126+ }
127+ return self;
128+ }
129+
130+ - (void )handleGesture : (NSPanGestureRecognizer *)gestureRecognizer
131+ {
132+ [_gestureHandler handleGesture: self ];
133+ }
134+
135+ - (void )mouseDown : (NSEvent *)event
136+ {
137+ [super mouseDown: event];
138+
139+ startPosition = [self locationInView: self .view];
140+ startTime = CACurrentMediaTime ();
141+
142+ self.state = NSGestureRecognizerStatePossible;
143+
144+ __weak typeof (self) weakSelf = self;
145+
146+ failFlingAction = dispatch_block_create (0 , ^{
147+ __strong typeof (self) strongSelf = weakSelf;
148+
149+ if (strongSelf) {
150+ strongSelf.state = NSGestureRecognizerStateFailed;
151+ }
152+ });
153+
154+ dispatch_after (
155+ dispatch_time (DISPATCH_TIME_NOW, (int64_t )(maxDuration * NSEC_PER_SEC)),
156+ dispatch_get_main_queue (),
157+ failFlingAction);
158+ }
159+
160+ - (void )mouseDragged : (NSEvent *)event
161+ {
162+ [super mouseDragged: event];
163+
164+ NSPoint currentPosition = [self locationInView: self .view];
165+ double currentTime = CACurrentMediaTime ();
166+
167+ NSPoint distance;
168+ distance.x = currentPosition.x - startPosition.x ;
169+ distance.y = startPosition.y - currentPosition.y ;
170+
171+ double timeDelta = currentTime - startTime;
172+
173+ Vector *velocityVector = [Vector fromVelocityX: (distance.x / timeDelta) withVelocityY: (distance.y / timeDelta)];
174+
175+ [self tryActivate: velocityVector];
176+ }
177+
178+ - (void )mouseUp : (NSEvent *)event
179+ {
180+ [super mouseUp: event];
181+
182+ dispatch_block_cancel (failFlingAction);
183+
184+ self.state =
185+ self.state == NSGestureRecognizerStateChanged ? NSGestureRecognizerStateEnded : NSGestureRecognizerStateFailed;
186+ }
187+
188+ - (void )tryActivate : (Vector *)velocityVector
189+ {
190+ bool isAligned = NO ;
191+
192+ for (int i = 0 ; i < directionsSize; ++i) {
193+ if ([self getAlignment: axialDirections[i]
194+ withMinimalAlignmentCosine: axialDeviationCosine
195+ withVelocityVector: velocityVector]) {
196+ isAligned = YES ;
197+ break ;
198+ }
199+ }
200+
201+ if (!isAligned) {
202+ for (int i = 0 ; i < directionsSize; ++i) {
203+ if ([self getAlignment: diagonalDirections[i]
204+ withMinimalAlignmentCosine: diagonalDeviationCosine
205+ withVelocityVector: velocityVector]) {
206+ isAligned = YES ;
207+ break ;
208+ }
209+ }
210+ }
211+
212+ bool isFastEnough = velocityVector.magnitude >= minVelocity;
213+
214+ if (isAligned && isFastEnough) {
215+ self.state = NSGestureRecognizerStateChanged;
216+ }
217+ }
218+
219+ - (BOOL )getAlignment : (RNGestureHandlerDirection)direction
220+ withMinimalAlignmentCosine : (double )minimalAlignmentCosine
221+ withVelocityVector : (Vector *)velocityVector
222+ {
223+ Vector *directionVector = [Vector fromDirection: direction];
224+ return ((self.direction & direction) == direction) &&
225+ [velocityVector isSimilar: directionVector withThreshold: minimalAlignmentCosine];
226+ }
227+
228+ - (double )coneToDeviation : (double )degrees
229+ {
230+ double radians = (degrees * M_PI) / 180 ;
231+ return cos (radians / 2 );
232+ }
233+
234+ @end
235+
236+ #endif
237+
90238@implementation RNFlingGestureHandler
91239
92240- (instancetype )initWithTag : (NSNumber *)tag
@@ -100,8 +248,8 @@ - (instancetype)initWithTag:(NSNumber *)tag
100248- (void )resetConfig
101249{
102250 [super resetConfig ];
103- UISwipeGestureRecognizer *recognizer = (UISwipeGestureRecognizer *)_recognizer;
104- recognizer.direction = UISwipeGestureRecognizerDirectionRight ;
251+ RNBetterSwipeGestureRecognizer *recognizer = (RNBetterSwipeGestureRecognizer *)_recognizer;
252+ recognizer.direction = RNGestureHandlerDirectionRight ;
105253#if !TARGET_OS_TV
106254 recognizer.numberOfTouchesRequired = 1 ;
107255#endif
@@ -110,7 +258,7 @@ - (void)resetConfig
110258- (void )configure : (NSDictionary *)config
111259{
112260 [super configure: config];
113- UISwipeGestureRecognizer *recognizer = (UISwipeGestureRecognizer *)_recognizer;
261+ RNBetterSwipeGestureRecognizer *recognizer = (RNBetterSwipeGestureRecognizer *)_recognizer;
114262
115263 id prop = config[@" direction" ];
116264 if (prop != nil ) {
@@ -125,6 +273,7 @@ - (void)configure:(NSDictionary *)config
125273#endif
126274}
127275
276+ #if !TARGET_OS_OSX
128277- (BOOL )gestureRecognizerShouldBegin : (UIGestureRecognizer *)gestureRecognizer
129278{
130279 RNGestureHandlerState savedState = _lastState;
@@ -154,21 +303,6 @@ - (RNGestureHandlerEventExtraData *)eventExtraData:(id)_recognizer
154303 withNumberOfTouches: recognizer.numberOfTouches
155304 withPointerType: _pointerType];
156305}
157- @end
158-
159- #else
160-
161- @implementation RNFlingGestureHandler
162-
163- - (instancetype )initWithTag : (NSNumber *)tag
164- {
165- RCTLogWarn (@" FlingGestureHandler is not supported on macOS" );
166- if ((self = [super initWithTag: tag])) {
167- _recognizer = [NSGestureRecognizer alloc ];
168- }
169- return self;
170- }
306+ #endif
171307
172308@end
173-
174- #endif
0 commit comments