react-native-tvos 0.76.1-0 → 0.76.1-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Components/Pressable/Pressable.d.ts +1 -1
- package/Libraries/Components/Pressable/Pressable.js +0 -15
- package/Libraries/Components/TV/TVViewPropTypes.js +2 -1
- package/Libraries/Components/TextInput/TextInput.d.ts +1 -1
- package/Libraries/Components/Touchable/Touchable.js +0 -43
- package/Libraries/Components/Touchable/TouchableBounce.js +0 -33
- package/Libraries/Components/Touchable/TouchableHighlight.js +12 -47
- package/Libraries/Components/Touchable/TouchableNativeFeedback.js +0 -33
- package/Libraries/Components/Touchable/TouchableOpacity.js +12 -44
- package/Libraries/Components/Touchable/TouchableWithoutFeedback.js +0 -19
- package/Libraries/Components/View/ViewNativeComponent.js +6 -0
- package/Libraries/Components/View/ViewPropTypes.d.ts +12 -1
- package/Libraries/Components/View/ViewPropTypes.js +7 -0
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/NativeComponent/BaseViewConfig.android.js +19 -0
- package/Libraries/NativeComponent/BaseViewConfig.ios.js +6 -0
- package/Libraries/NativeComponent/TVViewConfig.js +4 -0
- package/Libraries/Pressability/Pressability.js +45 -28
- package/Libraries/Types/CoreEventTypes.d.ts +21 -0
- package/Libraries/Types/CoreEventTypes.js +6 -0
- package/React/Base/RCTVersion.m +1 -1
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +39 -25
- package/React/Views/RCTTVView.h +13 -0
- package/React/Views/RCTTVView.m +54 -34
- package/React/Views/RCTViewManager.m +4 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java +16 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java +20 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/BlurEvent.kt +16 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/FocusEvent.kt +16 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PressInEvent.kt +16 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PressOutEvent.kt +16 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +212 -4
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +47 -4
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/react/renderer/components/view/BaseViewEventEmitter.cpp +18 -0
- package/ReactCommon/react/renderer/components/view/BaseViewEventEmitter.h +8 -0
- package/package.json +2 -2
- package/types/public/ReactNativeTVTypes.d.ts +1 -1
- package/Libraries/Components/Touchable/TVTouchable.js +0 -71
|
@@ -157,7 +157,8 @@ export type EventHandlers = $ReadOnly<{|
|
|
|
157
157
|
onResponderTerminate: (event: PressEvent) => void,
|
|
158
158
|
onResponderTerminationRequest: () => boolean,
|
|
159
159
|
onStartShouldSetResponder: () => boolean,
|
|
160
|
-
|
|
160
|
+
onPressIn: (event: any) => void,
|
|
161
|
+
onPressOut: (event: any) => void,
|
|
161
162
|
|}>;
|
|
162
163
|
|
|
163
164
|
type TouchState =
|
|
@@ -397,6 +398,7 @@ export default class Pressability {
|
|
|
397
398
|
|}>;
|
|
398
399
|
_touchActivateTime: ?number;
|
|
399
400
|
_touchState: TouchState = 'NOT_RESPONDER';
|
|
401
|
+
_longPressSent: boolean = false;
|
|
400
402
|
|
|
401
403
|
constructor(config: PressabilityConfig) {
|
|
402
404
|
this.configure(config);
|
|
@@ -436,35 +438,50 @@ export default class Pressability {
|
|
|
436
438
|
}
|
|
437
439
|
|
|
438
440
|
_createEventHandlers(): EventHandlers {
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
if (this._config.disabled
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
441
|
+
const tvPressEventHandlers = {
|
|
442
|
+
onPressIn: (evt: any): void => {
|
|
443
|
+
if (this._config.disabled === false) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
this._longPressSent = false;
|
|
448
|
+
|
|
449
|
+
const {onPressIn, onLongPress} = this._config;
|
|
450
|
+
onPressIn && onPressIn(evt);
|
|
451
|
+
|
|
452
|
+
const delayPressIn = normalizeDelay(this._config.delayPressIn);
|
|
453
|
+
const delayLongPress = normalizeDelay(
|
|
454
|
+
this._config.delayLongPress,
|
|
455
|
+
10,
|
|
456
|
+
DEFAULT_LONG_PRESS_DELAY_MS - delayPressIn,
|
|
457
|
+
);
|
|
458
|
+
this._longPressDelayTimeout = setTimeout(() => {
|
|
459
|
+
onLongPress && onLongPress(evt);
|
|
460
|
+
this._longPressSent = true;
|
|
461
|
+
}, delayLongPress + delayPressIn);
|
|
462
|
+
},
|
|
463
|
+
onPressOut: (evt: any): void => {
|
|
464
|
+
if (this._config.disabled === false) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
this._cancelLongPressDelayTimeout();
|
|
468
|
+
const {onPress, onLongPress, onPressOut, android_disableSound} =
|
|
469
|
+
this._config;
|
|
470
|
+
onPressOut && onPressOut(evt);
|
|
471
|
+
|
|
472
|
+
if (onPress != null) {
|
|
473
|
+
const isPressCanceledByLongPress =
|
|
474
|
+
onLongPress != null && this._longPressSent;
|
|
475
|
+
if (!isPressCanceledByLongPress) {
|
|
476
|
+
if (Platform.OS === 'android' && android_disableSound !== true) {
|
|
477
|
+
SoundManager.playTouchSound();
|
|
478
|
+
}
|
|
479
|
+
onPress(evt);
|
|
464
480
|
}
|
|
465
481
|
}
|
|
466
482
|
},
|
|
467
483
|
};
|
|
484
|
+
|
|
468
485
|
const focusEventHandlers = {
|
|
469
486
|
onBlur: (event: BlurEvent): void => {
|
|
470
487
|
const {onBlur} = this._config;
|
|
@@ -645,7 +662,7 @@ export default class Pressability {
|
|
|
645
662
|
};
|
|
646
663
|
}
|
|
647
664
|
return {
|
|
648
|
-
...
|
|
665
|
+
...tvPressEventHandlers,
|
|
649
666
|
...focusEventHandlers,
|
|
650
667
|
...responderEventHandlers,
|
|
651
668
|
...hoverPointerEvents,
|
|
@@ -698,7 +715,7 @@ export default class Pressability {
|
|
|
698
715
|
},
|
|
699
716
|
};
|
|
700
717
|
return {
|
|
701
|
-
...
|
|
718
|
+
...tvPressEventHandlers,
|
|
702
719
|
...focusEventHandlers,
|
|
703
720
|
...responderEventHandlers,
|
|
704
721
|
...mouseEventHandlers,
|
|
@@ -246,6 +246,15 @@ export interface GestureResponderEvent
|
|
|
246
246
|
|
|
247
247
|
export interface MouseEvent extends NativeSyntheticEvent<NativeMouseEvent> {}
|
|
248
248
|
|
|
249
|
+
export interface NativeFocusEvent {}
|
|
250
|
+
export interface FocusEvent extends NativeSyntheticEvent<NativeFocusEvent> {}
|
|
251
|
+
|
|
252
|
+
export interface NativeBlurEvent {}
|
|
253
|
+
export interface BlurEvent extends NativeSyntheticEvent<NativeBlurEvent> {}
|
|
254
|
+
|
|
255
|
+
export interface NativePressEvent {}
|
|
256
|
+
export interface PressEvent extends NativeSyntheticEvent<NativePressEvent> {}
|
|
257
|
+
|
|
249
258
|
export interface TargetedEvent {
|
|
250
259
|
target: number;
|
|
251
260
|
}
|
|
@@ -265,6 +274,18 @@ export interface PointerEvents {
|
|
|
265
274
|
onPointerUpCapture?: ((event: PointerEvent) => void) | undefined;
|
|
266
275
|
}
|
|
267
276
|
|
|
277
|
+
export interface PressEvents {
|
|
278
|
+
onPressIn?: ((event: PressEvent) => void) | undefined;
|
|
279
|
+
onPressOut?: ((event: PressEvent) => void) | undefined;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export interface FocusEvents {
|
|
283
|
+
onFocus?: ((event: FocusEvent) => void) | undefined;
|
|
284
|
+
onFocusCapture?: ((event: FocusEvent) => void) | undefined;
|
|
285
|
+
onBlur?: ((event: BlurEvent) => void) | undefined;
|
|
286
|
+
onBlurCapture?: ((event: BlurEvent) => void) | undefined;
|
|
287
|
+
}
|
|
288
|
+
|
|
268
289
|
export interface TVRemoteEvent {
|
|
269
290
|
tag?: number | undefined;
|
|
270
291
|
target?: number | undefined;
|
|
@@ -282,6 +282,12 @@ export type FocusEvent = SyntheticEvent<
|
|
|
282
282
|
|}>,
|
|
283
283
|
>;
|
|
284
284
|
|
|
285
|
+
export type RemotePressEvent = SyntheticEvent<
|
|
286
|
+
$ReadOnly<{|
|
|
287
|
+
target: number,
|
|
288
|
+
|}>,
|
|
289
|
+
>;
|
|
290
|
+
|
|
285
291
|
export type MouseEvent = SyntheticEvent<
|
|
286
292
|
$ReadOnly<{|
|
|
287
293
|
clientX: number,
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -63,8 +63,7 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
63
63
|
BOOL _removeClippedSubviews;
|
|
64
64
|
NSMutableArray<UIView *> *_reactSubviews;
|
|
65
65
|
BOOL _motionEffectsAdded;
|
|
66
|
-
|
|
67
|
-
UILongPressGestureRecognizer * _longSelectRecognizer;
|
|
66
|
+
UILongPressGestureRecognizer * _pressRecognizer;
|
|
68
67
|
NSSet<NSString *> *_Nullable _propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN;
|
|
69
68
|
UIView *_containerView;
|
|
70
69
|
BOOL _useCustomContainerView;
|
|
@@ -278,7 +277,7 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
278
277
|
[[NSNotificationCenter defaultCenter] postNavigationPressEventWithType:RCTTVRemoteEventLongSelect keyAction:recognizer.eventKeyAction tag:@(self.tag) target:@(self.tag)];
|
|
279
278
|
}
|
|
280
279
|
|
|
281
|
-
- (void)
|
|
280
|
+
- (void)animatePress
|
|
282
281
|
{
|
|
283
282
|
if (_tvParallaxProperties.enabled == YES) {
|
|
284
283
|
float magnification = _tvParallaxProperties.magnification;
|
|
@@ -302,18 +301,26 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
302
301
|
self.transform = CGAffineTransformMakeScale(magnification, magnification);
|
|
303
302
|
}
|
|
304
303
|
completion:^(__unused BOOL finished2) {
|
|
305
|
-
[self sendSelectNotification:r];
|
|
306
304
|
}];
|
|
307
305
|
}];
|
|
308
306
|
|
|
309
|
-
} else {
|
|
310
|
-
[self sendSelectNotification:r];
|
|
311
307
|
}
|
|
312
308
|
}
|
|
313
309
|
|
|
314
|
-
- (void)
|
|
310
|
+
- (void)handlePress:(UIGestureRecognizer *)r
|
|
315
311
|
{
|
|
316
|
-
|
|
312
|
+
switch (r.state) {
|
|
313
|
+
case UIGestureRecognizerStateBegan:
|
|
314
|
+
_eventEmitter->onPressIn();
|
|
315
|
+
break;
|
|
316
|
+
case UIGestureRecognizerStateEnded:
|
|
317
|
+
case UIGestureRecognizerStateCancelled:
|
|
318
|
+
[self animatePress];
|
|
319
|
+
_eventEmitter->onPressOut();
|
|
320
|
+
break;
|
|
321
|
+
default:
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
317
324
|
}
|
|
318
325
|
|
|
319
326
|
- (void)addParallaxMotionEffects
|
|
@@ -576,6 +583,8 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
576
583
|
}
|
|
577
584
|
|
|
578
585
|
if (context.nextFocusedView == self && self.isUserInteractionEnabled && ![self isTVFocusGuide]) {
|
|
586
|
+
if(_eventEmitter) _eventEmitter->onFocus();
|
|
587
|
+
|
|
579
588
|
[self becomeFirstResponder];
|
|
580
589
|
[self enableDirectionalFocusGuides];
|
|
581
590
|
[coordinator addCoordinatedAnimations:^(void){
|
|
@@ -583,6 +592,8 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
583
592
|
[self sendFocusNotification:context];
|
|
584
593
|
} completion:^(void){}];
|
|
585
594
|
} else {
|
|
595
|
+
if (_eventEmitter) _eventEmitter->onBlur();
|
|
596
|
+
|
|
586
597
|
[self disableDirectionalFocusGuides];
|
|
587
598
|
[coordinator addCoordinatedAnimations:^(void){
|
|
588
599
|
[self removeParallaxMotionEffects];
|
|
@@ -1029,24 +1040,15 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
1029
1040
|
// `isTVSelectable`
|
|
1030
1041
|
if (oldViewProps.isTVSelectable != newViewProps.isTVSelectable) {
|
|
1031
1042
|
if (newViewProps.isTVSelectable && ![self isTVFocusGuide]) {
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
recognizer.allowedPressTypes = @[ @(UIPressTypeSelect) ];
|
|
1039
|
-
[self addGestureRecognizer:longRecognizer];
|
|
1040
|
-
_longSelectRecognizer = longRecognizer;
|
|
1041
|
-
|
|
1042
|
-
[self addGestureRecognizer:_selectRecognizer];
|
|
1043
|
-
[self addGestureRecognizer:_longSelectRecognizer];
|
|
1043
|
+
UILongPressGestureRecognizer *pressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlePress:)];
|
|
1044
|
+
pressRecognizer.allowedPressTypes = @[ @(UIPressTypeSelect) ];
|
|
1045
|
+
pressRecognizer.minimumPressDuration = 0;
|
|
1046
|
+
|
|
1047
|
+
[self addGestureRecognizer:pressRecognizer];
|
|
1048
|
+
_pressRecognizer = pressRecognizer;
|
|
1044
1049
|
} else {
|
|
1045
|
-
if (
|
|
1046
|
-
[self removeGestureRecognizer:
|
|
1047
|
-
}
|
|
1048
|
-
if (_longSelectRecognizer) {
|
|
1049
|
-
[self removeGestureRecognizer:_longSelectRecognizer];
|
|
1050
|
+
if (_pressRecognizer) {
|
|
1051
|
+
[self removeGestureRecognizer:_pressRecognizer];
|
|
1050
1052
|
}
|
|
1051
1053
|
}
|
|
1052
1054
|
}
|
|
@@ -1077,6 +1079,9 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
1077
1079
|
_nextFocusUp = [rootView viewWithTag:newViewProps.nextFocusUp.value()];
|
|
1078
1080
|
[self enableDirectionalFocusGuides];
|
|
1079
1081
|
} else {
|
|
1082
|
+
if (self.focusGuideUp != nil) {
|
|
1083
|
+
[[self containingRootView] removeLayoutGuide:self.focusGuideUp];
|
|
1084
|
+
}
|
|
1080
1085
|
_nextFocusUp = nil;
|
|
1081
1086
|
}
|
|
1082
1087
|
}
|
|
@@ -1087,6 +1092,9 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
1087
1092
|
_nextFocusDown = [rootView viewWithTag:newViewProps.nextFocusDown.value()];
|
|
1088
1093
|
[self enableDirectionalFocusGuides];
|
|
1089
1094
|
} else {
|
|
1095
|
+
if (self.focusGuideDown != nil) {
|
|
1096
|
+
[[self containingRootView] removeLayoutGuide:self.focusGuideDown];
|
|
1097
|
+
}
|
|
1090
1098
|
_nextFocusDown = nil;
|
|
1091
1099
|
}
|
|
1092
1100
|
}
|
|
@@ -1097,6 +1105,9 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
1097
1105
|
_nextFocusLeft = [rootView viewWithTag:newViewProps.nextFocusLeft.value()];
|
|
1098
1106
|
[self enableDirectionalFocusGuides];
|
|
1099
1107
|
} else {
|
|
1108
|
+
if (self.focusGuideLeft != nil) {
|
|
1109
|
+
[[self containingRootView] removeLayoutGuide:self.focusGuideLeft];
|
|
1110
|
+
}
|
|
1100
1111
|
_nextFocusLeft = nil;
|
|
1101
1112
|
}
|
|
1102
1113
|
}
|
|
@@ -1107,6 +1118,9 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f;
|
|
|
1107
1118
|
_nextFocusRight = [rootView viewWithTag:newViewProps.nextFocusRight.value()];
|
|
1108
1119
|
[self enableDirectionalFocusGuides];
|
|
1109
1120
|
} else {
|
|
1121
|
+
if (self.focusGuideRight != nil) {
|
|
1122
|
+
[[self containingRootView] removeLayoutGuide:self.focusGuideRight];
|
|
1123
|
+
}
|
|
1110
1124
|
_nextFocusRight = nil;
|
|
1111
1125
|
}
|
|
1112
1126
|
}
|
package/React/Views/RCTTVView.h
CHANGED
|
@@ -52,6 +52,19 @@
|
|
|
52
52
|
@property (nonatomic, assign) BOOL trapFocusLeft;
|
|
53
53
|
@property (nonatomic, assign) BOOL trapFocusRight;
|
|
54
54
|
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Focus
|
|
58
|
+
*/
|
|
59
|
+
@property (nonatomic, copy) RCTBubblingEventBlock onFocus;
|
|
60
|
+
@property (nonatomic, copy) RCTBubblingEventBlock onBlur;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* TV Press Handlers
|
|
64
|
+
*/
|
|
65
|
+
@property (nonatomic, copy) RCTDirectEventBlock onPressIn;
|
|
66
|
+
@property (nonatomic, copy) RCTDirectEventBlock onPressOut;
|
|
67
|
+
|
|
55
68
|
- (instancetype)initWithBridge:(RCTBridge *)bridge;
|
|
56
69
|
|
|
57
70
|
/**
|
package/React/Views/RCTTVView.m
CHANGED
|
@@ -22,8 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
@implementation RCTTVView {
|
|
24
24
|
__weak RCTBridge *_bridge;
|
|
25
|
-
|
|
26
|
-
UILongPressGestureRecognizer * _longSelectRecognizer;
|
|
25
|
+
UILongPressGestureRecognizer * _pressRecognizer;
|
|
27
26
|
BOOL motionEffectsAdded;
|
|
28
27
|
NSArray* focusDestinations;
|
|
29
28
|
id<UIFocusItem> previouslyFocusedItem;
|
|
@@ -77,29 +76,21 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
|
|
|
77
76
|
{
|
|
78
77
|
self->_isTVSelectable = isTVSelectable;
|
|
79
78
|
if (isTVSelectable && ![self isTVFocusGuide]) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
[self addGestureRecognizer:longRecognizer];
|
|
88
|
-
_longSelectRecognizer = longRecognizer;
|
|
89
|
-
|
|
90
|
-
[self addGestureRecognizer:_selectRecognizer];
|
|
91
|
-
[self addGestureRecognizer:_longSelectRecognizer];
|
|
79
|
+
UILongPressGestureRecognizer *pressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlePress:)];
|
|
80
|
+
pressRecognizer.allowedPressTypes = @[ @(UIPressTypeSelect) ];
|
|
81
|
+
pressRecognizer.minimumPressDuration = 0;
|
|
82
|
+
|
|
83
|
+
_pressRecognizer = pressRecognizer;
|
|
84
|
+
|
|
85
|
+
[self addGestureRecognizer:_pressRecognizer];
|
|
92
86
|
} else {
|
|
93
|
-
if (
|
|
94
|
-
[self removeGestureRecognizer:
|
|
95
|
-
}
|
|
96
|
-
if (_longSelectRecognizer) {
|
|
97
|
-
[self removeGestureRecognizer:_longSelectRecognizer];
|
|
87
|
+
if (_pressRecognizer) {
|
|
88
|
+
[self removeGestureRecognizer:_pressRecognizer];
|
|
98
89
|
}
|
|
99
90
|
}
|
|
100
91
|
}
|
|
101
92
|
|
|
102
|
-
- (void)
|
|
93
|
+
- (void)animatePress
|
|
103
94
|
{
|
|
104
95
|
if ([self.tvParallaxProperties[@"enabled"] boolValue] == YES) {
|
|
105
96
|
float magnification = [self.tvParallaxProperties[@"magnification"] floatValue];
|
|
@@ -123,18 +114,25 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
|
|
|
123
114
|
self.transform = CGAffineTransformMakeScale(magnification, magnification);
|
|
124
115
|
}
|
|
125
116
|
completion:^(__unused BOOL finished2) {
|
|
126
|
-
[self sendSelectNotification:r];
|
|
127
117
|
}];
|
|
128
118
|
}];
|
|
129
|
-
|
|
130
|
-
} else {
|
|
131
|
-
[self sendSelectNotification:r];
|
|
132
119
|
}
|
|
133
120
|
}
|
|
134
121
|
|
|
135
|
-
- (void)
|
|
122
|
+
- (void)handlePress:(UIGestureRecognizer *)r
|
|
136
123
|
{
|
|
137
|
-
|
|
124
|
+
switch (r.state) {
|
|
125
|
+
case UIGestureRecognizerStateBegan:
|
|
126
|
+
if (self.onPressIn) self.onPressIn(nil);
|
|
127
|
+
break;
|
|
128
|
+
case UIGestureRecognizerStateEnded:
|
|
129
|
+
case UIGestureRecognizerStateCancelled:
|
|
130
|
+
[self animatePress];
|
|
131
|
+
if (self.onPressOut) self.onPressOut(nil);
|
|
132
|
+
break;
|
|
133
|
+
default:
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
138
136
|
}
|
|
139
137
|
|
|
140
138
|
- (BOOL)isTVFocusGuide
|
|
@@ -323,6 +321,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
|
|
|
323
321
|
}
|
|
324
322
|
|
|
325
323
|
if (context.nextFocusedView == self && ![self isTVFocusGuide] && self.isTVSelectable ) {
|
|
324
|
+
if (self.onFocus) self.onFocus(nil);
|
|
326
325
|
[self becomeFirstResponder];
|
|
327
326
|
[self enableDirectionalFocusGuides];
|
|
328
327
|
[coordinator addCoordinatedAnimations:^(void){
|
|
@@ -330,6 +329,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
|
|
|
330
329
|
[self sendFocusNotification:context];
|
|
331
330
|
} completion:^(void){}];
|
|
332
331
|
} else {
|
|
332
|
+
if (self.onBlur) self.onBlur(nil);
|
|
333
333
|
[self disableDirectionalFocusGuides];
|
|
334
334
|
[coordinator addCoordinatedAnimations:^(void){
|
|
335
335
|
[self sendBlurNotification:context];
|
|
@@ -458,23 +458,43 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
|
|
|
458
458
|
}
|
|
459
459
|
|
|
460
460
|
- (void)setNextFocusUp:(NSNumber *)nextFocusUp {
|
|
461
|
-
self
|
|
462
|
-
|
|
461
|
+
if (self.focusGuideUp != nil && nextFocusUp == nil) {
|
|
462
|
+
[[self rootView] removeLayoutGuide:self.focusGuideUp];
|
|
463
|
+
self.focusGuideUp = nil;
|
|
464
|
+
} else {
|
|
465
|
+
self->_nextFocusUp = [self getViewById: nextFocusUp];
|
|
466
|
+
[self enableDirectionalFocusGuides];
|
|
467
|
+
}
|
|
463
468
|
}
|
|
464
469
|
|
|
465
470
|
- (void)setNextFocusDown:(NSNumber *)nextFocusDown {
|
|
466
|
-
self
|
|
467
|
-
|
|
471
|
+
if (self.focusGuideDown != nil && nextFocusDown) {
|
|
472
|
+
[[self rootView] removeLayoutGuide:self.focusGuideDown];
|
|
473
|
+
self.focusGuideDown = nil;
|
|
474
|
+
} else {
|
|
475
|
+
self->_nextFocusDown = [self getViewById: nextFocusDown];
|
|
476
|
+
[self enableDirectionalFocusGuides];
|
|
477
|
+
}
|
|
468
478
|
}
|
|
469
479
|
|
|
470
480
|
- (void)setNextFocusLeft:(NSNumber *)nextFocusLeft {
|
|
471
|
-
self
|
|
472
|
-
|
|
481
|
+
if (self.focusGuideLeft != nil && nextFocusLeft == nil) {
|
|
482
|
+
[[self rootView] removeLayoutGuide:self.focusGuideLeft];
|
|
483
|
+
self.focusGuideLeft = nil;
|
|
484
|
+
} else {
|
|
485
|
+
self->_nextFocusLeft = [self getViewById: nextFocusLeft];
|
|
486
|
+
[self enableDirectionalFocusGuides];
|
|
487
|
+
}
|
|
473
488
|
}
|
|
474
489
|
|
|
475
490
|
- (void)setNextFocusRight:(NSNumber *)nextFocusRight {
|
|
476
|
-
self
|
|
477
|
-
|
|
491
|
+
if (self.focusGuideRight != nil && nextFocusRight) {
|
|
492
|
+
[[self rootView] removeLayoutGuide:self.focusGuideRight];
|
|
493
|
+
self.focusGuideRight = nil;
|
|
494
|
+
} else {
|
|
495
|
+
self->_nextFocusRight = [self getViewById: nextFocusRight];
|
|
496
|
+
[self enableDirectionalFocusGuides];
|
|
497
|
+
}
|
|
478
498
|
}
|
|
479
499
|
|
|
480
500
|
- (void)setPreferredFocus:(BOOL)hasTVPreferredFocus
|
|
@@ -197,6 +197,10 @@ RCT_EXPORT_VIEW_PROPERTY(trapFocusUp, BOOL)
|
|
|
197
197
|
RCT_EXPORT_VIEW_PROPERTY(trapFocusDown, BOOL)
|
|
198
198
|
RCT_EXPORT_VIEW_PROPERTY(trapFocusLeft, BOOL)
|
|
199
199
|
RCT_EXPORT_VIEW_PROPERTY(trapFocusRight, BOOL)
|
|
200
|
+
RCT_EXPORT_VIEW_PROPERTY(onFocus, RCTBubblingEventBlock)
|
|
201
|
+
RCT_EXPORT_VIEW_PROPERTY(onBlur, RCTBubblingEventBlock)
|
|
202
|
+
RCT_EXPORT_VIEW_PROPERTY(onPressIn, RCTDirectEventBlock)
|
|
203
|
+
RCT_EXPORT_VIEW_PROPERTY(onPressOut, RCTDirectEventBlock)
|
|
200
204
|
#endif
|
|
201
205
|
|
|
202
206
|
// Accessibility related properties
|
|
@@ -736,6 +736,16 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
|
|
|
736
736
|
MapBuilder.of(
|
|
737
737
|
"phasedRegistrationNames",
|
|
738
738
|
MapBuilder.of("bubbled", "onClick", "captured", "onClickCapture")))
|
|
739
|
+
.put(
|
|
740
|
+
"topFocus",
|
|
741
|
+
MapBuilder.of(
|
|
742
|
+
"phasedRegistrationNames",
|
|
743
|
+
MapBuilder.of("bubbled", "onFocus", "captured", "onFocusCapture")))
|
|
744
|
+
.put(
|
|
745
|
+
"topBlur",
|
|
746
|
+
MapBuilder.of(
|
|
747
|
+
"phasedRegistrationNames",
|
|
748
|
+
MapBuilder.of("bubbled", "onBlur", "captured", "onBlurCapture")))
|
|
739
749
|
.build());
|
|
740
750
|
return eventTypeConstants;
|
|
741
751
|
}
|
|
@@ -751,6 +761,12 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
|
|
|
751
761
|
.put(
|
|
752
762
|
"topAccessibilityAction",
|
|
753
763
|
MapBuilder.of("registrationName", "onAccessibilityAction"))
|
|
764
|
+
.put(
|
|
765
|
+
"topPressIn",
|
|
766
|
+
MapBuilder.of("registrationName", "onPressIn"))
|
|
767
|
+
.put(
|
|
768
|
+
"topPressOut",
|
|
769
|
+
MapBuilder.of("registrationName", "onPressOut"))
|
|
754
770
|
.build());
|
|
755
771
|
return eventTypeConstants;
|
|
756
772
|
}
|
package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java
CHANGED
|
@@ -568,6 +568,26 @@ public class ReactAccessibilityDelegate extends ExploreByTouchHelper {
|
|
|
568
568
|
if (action == AccessibilityNodeInfoCompat.ACTION_EXPAND) {
|
|
569
569
|
host.setTag(R.id.accessibility_state_expanded, true);
|
|
570
570
|
}
|
|
571
|
+
if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
|
|
572
|
+
final WritableMap payload = Arguments.createMap();
|
|
573
|
+
final int reactTag = host.getId();
|
|
574
|
+
payload.putString("eventType", "select");
|
|
575
|
+
payload.putInt("eventKeyAction", 1);
|
|
576
|
+
payload.putInt("tag", reactTag);
|
|
577
|
+
payload.putInt("target", reactTag);
|
|
578
|
+
ReactContext reactContext = (ReactContext) host.getContext();
|
|
579
|
+
reactContext.emitDeviceEvent("onHWKeyEvent", payload);
|
|
580
|
+
}
|
|
581
|
+
if (action == AccessibilityNodeInfoCompat.ACTION_LONG_CLICK) {
|
|
582
|
+
final WritableMap payload = Arguments.createMap();
|
|
583
|
+
final int reactTag = host.getId();
|
|
584
|
+
payload.putString("eventType", "longSelect");
|
|
585
|
+
payload.putInt("eventKeyAction", 1);
|
|
586
|
+
payload.putInt("tag", reactTag);
|
|
587
|
+
payload.putInt("target", reactTag);
|
|
588
|
+
ReactContext reactContext = (ReactContext) host.getContext();
|
|
589
|
+
reactContext.emitDeviceEvent("onHWKeyEvent", payload);
|
|
590
|
+
}
|
|
571
591
|
if (mAccessibilityActionsMap.containsKey(action)) {
|
|
572
592
|
final WritableMap event = Arguments.createMap();
|
|
573
593
|
event.putString("actionName", mAccessibilityActionsMap.get(action));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.facebook.react.uimanager.events
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.WritableMap
|
|
5
|
+
|
|
6
|
+
public class BlurEvent(surfaceId: Int, viewId: Int) :
|
|
7
|
+
Event<BlurEvent>(surfaceId, viewId) {
|
|
8
|
+
|
|
9
|
+
override fun getEventName(): String = EVENT_NAME
|
|
10
|
+
|
|
11
|
+
override fun getEventData(): WritableMap = Arguments.createMap()
|
|
12
|
+
|
|
13
|
+
private companion object {
|
|
14
|
+
private const val EVENT_NAME: String = "topBlur"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.facebook.react.uimanager.events
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.WritableMap
|
|
5
|
+
|
|
6
|
+
public class FocusEvent(surfaceId: Int, viewId: Int) :
|
|
7
|
+
Event<FocusEvent>(surfaceId, viewId) {
|
|
8
|
+
|
|
9
|
+
override fun getEventName(): String = EVENT_NAME
|
|
10
|
+
|
|
11
|
+
override fun getEventData(): WritableMap = Arguments.createMap()
|
|
12
|
+
|
|
13
|
+
private companion object {
|
|
14
|
+
private const val EVENT_NAME: String = "topFocus"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.facebook.react.uimanager.events
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.WritableMap
|
|
5
|
+
|
|
6
|
+
public class PressInEvent(surfaceId: Int, viewId: Int) :
|
|
7
|
+
Event<PressInEvent>(surfaceId, viewId) {
|
|
8
|
+
|
|
9
|
+
override fun getEventName(): String = EVENT_NAME
|
|
10
|
+
|
|
11
|
+
override fun getEventData(): WritableMap = Arguments.createMap()
|
|
12
|
+
|
|
13
|
+
private companion object {
|
|
14
|
+
private const val EVENT_NAME: String = "topPressIn"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.facebook.react.uimanager.events
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.WritableMap
|
|
5
|
+
|
|
6
|
+
public class PressOutEvent(surfaceId: Int, viewId: Int) :
|
|
7
|
+
Event<PressOutEvent>(surfaceId, viewId) {
|
|
8
|
+
|
|
9
|
+
override fun getEventName(): String = EVENT_NAME
|
|
10
|
+
|
|
11
|
+
override fun getEventData(): WritableMap = Arguments.createMap()
|
|
12
|
+
|
|
13
|
+
private companion object {
|
|
14
|
+
private const val EVENT_NAME: String = "topPressOut"
|
|
15
|
+
}
|
|
16
|
+
}
|