react-native-tvos 0.66.3-1 → 0.66.3-2

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.
Files changed (60) hide show
  1. package/Libraries/Components/AppleTV/TVFocusGuideView.js +30 -35
  2. package/Libraries/Components/AppleTV/TVViewPropTypes.js +0 -27
  3. package/Libraries/Components/Pressable/Pressable.js +2 -0
  4. package/Libraries/Components/View/ViewNativeComponent.js +6 -1
  5. package/Libraries/LogBox/UI/LogBoxButton.js +1 -0
  6. package/React/Base/RCTTVRemoteHandler.h +3 -0
  7. package/React/Base/RCTTVRemoteHandler.m +24 -0
  8. package/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm +1 -1
  9. package/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.h +9 -0
  10. package/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm +18 -0
  11. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +4 -0
  12. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +416 -2
  13. package/React/Fabric/Mounting/RCTComponentViewFactory.mm +2 -0
  14. package/React/Views/RCTTVView.h +5 -0
  15. package/React/Views/RCTTVView.m +16 -0
  16. package/React/Views/RCTViewManager.m +17 -0
  17. package/ReactAndroid/gradle.properties +1 -1
  18. package/ReactCommon/hermes/inspector/tools/msggen/yarn.lock +37 -73
  19. package/ReactCommon/react/renderer/components/view/ViewProps.cpp +28 -0
  20. package/ReactCommon/react/renderer/components/view/ViewProps.h +10 -0
  21. package/ReactCommon/react/renderer/components/view/primitives.h +34 -0
  22. package/ReactCommon/react/renderer/components/view/propsConversions.h +66 -0
  23. package/android/com/facebook/react/react-native/{0.66.3-1/react-native-0.66.3-1.aar → 0.66.3-2/react-native-0.66.3-2.aar} +0 -0
  24. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.aar.md5 +1 -0
  25. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.aar.sha1 +1 -0
  26. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.aar.sha256 +1 -0
  27. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.aar.sha512 +1 -0
  28. package/android/com/facebook/react/react-native/{0.66.3-1/react-native-0.66.3-1.module → 0.66.3-2/react-native-0.66.3-2.module} +16 -16
  29. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.module.md5 +1 -0
  30. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.module.sha1 +1 -0
  31. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.module.sha256 +1 -0
  32. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.module.sha512 +1 -0
  33. package/android/com/facebook/react/react-native/{0.66.3-1/react-native-0.66.3-1.pom → 0.66.3-2/react-native-0.66.3-2.pom} +1 -1
  34. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.pom.md5 +1 -0
  35. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.pom.sha1 +1 -0
  36. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.pom.sha256 +1 -0
  37. package/android/com/facebook/react/react-native/0.66.3-2/react-native-0.66.3-2.pom.sha512 +1 -0
  38. package/android/com/facebook/react/react-native/maven-metadata.xml +4 -4
  39. package/android/com/facebook/react/react-native/maven-metadata.xml.md5 +1 -1
  40. package/android/com/facebook/react/react-native/maven-metadata.xml.sha1 +1 -1
  41. package/android/com/facebook/react/react-native/maven-metadata.xml.sha256 +1 -1
  42. package/android/com/facebook/react/react-native/maven-metadata.xml.sha512 +1 -1
  43. package/package.json +2 -2
  44. package/template/package.json +1 -1
  45. package/React/Views/RCTTVFocusGuideView.h +0 -22
  46. package/React/Views/RCTTVFocusGuideView.m +0 -60
  47. package/React/Views/RCTTVFocusGuideViewManager.h +0 -12
  48. package/React/Views/RCTTVFocusGuideViewManager.m +0 -30
  49. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.aar.md5 +0 -1
  50. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.aar.sha1 +0 -1
  51. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.aar.sha256 +0 -1
  52. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.aar.sha512 +0 -1
  53. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.module.md5 +0 -1
  54. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.module.sha1 +0 -1
  55. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.module.sha256 +0 -1
  56. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.module.sha512 +0 -1
  57. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.pom.md5 +0 -1
  58. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.pom.sha1 +0 -1
  59. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.pom.sha256 +0 -1
  60. package/android/com/facebook/react/react-native/0.66.3-1/react-native-0.66.3-1.pom.sha512 +0 -1
@@ -13,10 +13,26 @@
13
13
  #import <React/RCTAssert.h>
14
14
  #import <React/RCTBorderDrawing.h>
15
15
  #import <React/RCTConversions.h>
16
+ #import <React/RCTDefines.h>
17
+ #import <React/RCTLog.h>
18
+
19
+ #import <React/RCTRootComponentView.h>
20
+
16
21
  #import <react/renderer/components/view/ViewComponentDescriptor.h>
17
22
  #import <react/renderer/components/view/ViewEventEmitter.h>
18
23
  #import <react/renderer/components/view/ViewProps.h>
19
24
 
25
+ typedef struct {
26
+ BOOL enabled;
27
+ float shiftDistanceX;
28
+ float shiftDistanceY;
29
+ float tiltAngle;
30
+ float magnification;
31
+ float pressMagnification;
32
+ float pressDuration;
33
+ float pressDelay;
34
+ } ParallaxProperties;
35
+
20
36
  using namespace facebook::react;
21
37
 
22
38
  @implementation RCTViewComponentView {
@@ -26,7 +42,16 @@ using namespace facebook::react;
26
42
  BOOL _isJSResponder;
27
43
  BOOL _removeClippedSubviews;
28
44
  NSMutableArray<UIView *> *_reactSubviews;
45
+ BOOL _motionEffectsAdded;
46
+ UITapGestureRecognizer *_selectRecognizer;
29
47
  NSSet<NSString *> *_Nullable _propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN;
48
+ ParallaxProperties _tvParallaxProperties;
49
+ BOOL _hasTVPreferredFocus;
50
+ UIView *_nextFocusUp;
51
+ UIView *_nextFocusDown;
52
+ UIView *_nextFocusLeft;
53
+ UIView *_nextFocusRight;
54
+ UIView *_nextFocusActiveTarget;
30
55
  }
31
56
 
32
57
  - (instancetype)initWithFrame:(CGRect)frame
@@ -35,7 +60,18 @@ using namespace facebook::react;
35
60
  static auto const defaultProps = std::make_shared<ViewProps const>();
36
61
  _props = defaultProps;
37
62
  _reactSubviews = [NSMutableArray new];
38
- #if !TARGET_OS_TV
63
+ #if TARGET_OS_TV
64
+ _tvParallaxProperties.enabled = NO;
65
+ _tvParallaxProperties.shiftDistanceX = 0.0f;
66
+ _tvParallaxProperties.shiftDistanceY = 0.0f;
67
+ _tvParallaxProperties.tiltAngle = 0.0f;
68
+ _tvParallaxProperties.magnification = 0.0f;
69
+ _tvParallaxProperties.pressMagnification = 0.0f;
70
+ _tvParallaxProperties.pressDuration = 0.0f;
71
+ _tvParallaxProperties.pressDelay = 0.0f;
72
+ self.focusGuide = [UIFocusGuide new];
73
+ [self addLayoutGuide:self.focusGuide];
74
+ #else
39
75
  self.multipleTouchEnabled = YES;
40
76
  #endif
41
77
  }
@@ -60,7 +96,6 @@ using namespace facebook::react;
60
96
  _contentView.frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame());
61
97
  }
62
98
  }
63
-
64
99
  - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
65
100
  {
66
101
  if (UIEdgeInsetsEqualToEdgeInsets(self.hitTestEdgeInsets, UIEdgeInsetsZero)) {
@@ -80,6 +115,290 @@ using namespace facebook::react;
80
115
  _backgroundColor = backgroundColor;
81
116
  }
82
117
 
118
+ #if TARGET_OS_TV
119
+
120
+ #pragma mark - Apple TV methods
121
+
122
+ - (RCTRootComponentView *)containingRootView
123
+ {
124
+ UIView *rootview = self;
125
+ if ([rootview class] == [RCTRootComponentView class]) {
126
+ return (RCTRootComponentView *)rootview;
127
+ }
128
+ do {
129
+ rootview = [rootview superview];
130
+ } while (([rootview class] != [RCTRootComponentView class]) && rootview != nil);
131
+ return (RCTRootComponentView *)rootview;
132
+ }
133
+
134
+ - (void)addFocusDestinations:(NSArray*)destinations {
135
+
136
+ self.focusGuide.preferredFocusEnvironments = destinations;
137
+ }
138
+
139
+ - (void)sendFocusNotification:(__unused UIFocusUpdateContext *)context
140
+ {
141
+ [self sendNotificationWithEventType:@"focus"];
142
+ }
143
+
144
+ - (void)sendBlurNotification:(__unused UIFocusUpdateContext *)context
145
+ {
146
+ [self sendNotificationWithEventType:@"blur"];
147
+ }
148
+
149
+ - (void)sendSelectNotification:(UIGestureRecognizer *)recognizer
150
+ {
151
+ [self sendNotificationWithEventType:@"select"];
152
+ }
153
+
154
+ - (void)sendNotificationWithEventType:(NSString * __nonnull)eventType
155
+ {
156
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"RCTTVNavigationEventNotification"
157
+ object:@{
158
+ @"eventType":eventType,
159
+ @"tag":@([self tag]),
160
+ @"target":@([self tag])
161
+ }];
162
+ }
163
+
164
+ - (void)handleSelect:(__unused UIGestureRecognizer *)r
165
+ {
166
+ if (_tvParallaxProperties.enabled == YES) {
167
+ float magnification = _tvParallaxProperties.magnification;
168
+ float pressMagnification = _tvParallaxProperties.pressMagnification;
169
+
170
+ // Duration of press animation
171
+ float pressDuration = _tvParallaxProperties.pressDuration;
172
+
173
+ // Delay of press animation
174
+ float pressDelay = _tvParallaxProperties.pressDelay;
175
+
176
+ [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:pressDelay]];
177
+
178
+ [UIView animateWithDuration:(pressDuration/2)
179
+ animations:^{
180
+ self.transform = CGAffineTransformMakeScale(pressMagnification, pressMagnification);
181
+ }
182
+ completion:^(__unused BOOL finished1){
183
+ [UIView animateWithDuration:(pressDuration/2)
184
+ animations:^{
185
+ self.transform = CGAffineTransformMakeScale(magnification, magnification);
186
+ }
187
+ completion:^(__unused BOOL finished2) {
188
+ [self sendSelectNotification:r];
189
+ }];
190
+ }];
191
+
192
+ } else {
193
+ [self sendSelectNotification:r];
194
+ }
195
+ }
196
+
197
+ - (void)addParallaxMotionEffects
198
+ {
199
+ if(!_tvParallaxProperties.enabled) {
200
+ return;
201
+ }
202
+
203
+ if(_motionEffectsAdded == YES) {
204
+ return;
205
+ }
206
+
207
+ // Size of shift movements
208
+ CGFloat const shiftDistanceX = _tvParallaxProperties.shiftDistanceX;
209
+ CGFloat const shiftDistanceY = _tvParallaxProperties.shiftDistanceY;
210
+
211
+ // Make horizontal movements shift the centre left and right
212
+ UIInterpolatingMotionEffect *xShift =
213
+ [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x"
214
+ type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
215
+ xShift.minimumRelativeValue = @(shiftDistanceX * -1.0f);
216
+ xShift.maximumRelativeValue = @(shiftDistanceX);
217
+
218
+ // Make vertical movements shift the centre up and down
219
+ UIInterpolatingMotionEffect *yShift =
220
+ [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y"
221
+ type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
222
+ yShift.minimumRelativeValue = @(shiftDistanceY * -1.0f);
223
+ yShift.maximumRelativeValue = @(shiftDistanceY);
224
+
225
+ // Size of tilt movements
226
+ CGFloat const tiltAngle = _tvParallaxProperties.tiltAngle;
227
+
228
+ // Now make horizontal movements effect a rotation about the Y axis for side-to-side rotation.
229
+ UIInterpolatingMotionEffect *xTilt =
230
+ [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"layer.transform"
231
+ type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
232
+
233
+ // CATransform3D value for minimumRelativeValue
234
+ CATransform3D transMinimumTiltAboutY = CATransform3DIdentity;
235
+ transMinimumTiltAboutY.m34 = 1.0 / 500;
236
+ transMinimumTiltAboutY = CATransform3DRotate(transMinimumTiltAboutY, tiltAngle * -1.0, 0, 1, 0);
237
+
238
+ // CATransform3D value for minimumRelativeValue
239
+ CATransform3D transMaximumTiltAboutY = CATransform3DIdentity;
240
+ transMaximumTiltAboutY.m34 = 1.0 / 500;
241
+ transMaximumTiltAboutY = CATransform3DRotate(transMaximumTiltAboutY, tiltAngle, 0, 1, 0);
242
+
243
+ // Set the transform property boundaries for the interpolation
244
+ xTilt.minimumRelativeValue = [NSValue valueWithCATransform3D:transMinimumTiltAboutY];
245
+ xTilt.maximumRelativeValue = [NSValue valueWithCATransform3D:transMaximumTiltAboutY];
246
+
247
+ // Now make vertical movements effect a rotation about the X axis for up and down rotation.
248
+ UIInterpolatingMotionEffect *yTilt =
249
+ [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"layer.transform"
250
+ type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis];
251
+
252
+ // CATransform3D value for minimumRelativeValue
253
+ CATransform3D transMinimumTiltAboutX = CATransform3DIdentity;
254
+ transMinimumTiltAboutX.m34 = 1.0 / 500;
255
+ transMinimumTiltAboutX = CATransform3DRotate(transMinimumTiltAboutX, tiltAngle * -1.0, 1, 0, 0);
256
+
257
+ // CATransform3D value for minimumRelativeValue
258
+ CATransform3D transMaximumTiltAboutX = CATransform3DIdentity;
259
+ transMaximumTiltAboutX.m34 = 1.0 / 500;
260
+ transMaximumTiltAboutX = CATransform3DRotate(transMaximumTiltAboutX, tiltAngle, 1, 0, 0);
261
+
262
+ // Set the transform property boundaries for the interpolation
263
+ yTilt.minimumRelativeValue = [NSValue valueWithCATransform3D:transMinimumTiltAboutX];
264
+ yTilt.maximumRelativeValue = [NSValue valueWithCATransform3D:transMaximumTiltAboutX];
265
+
266
+ // Add all of the motion effects to this group
267
+ self.motionEffects = @[ xShift, yShift, xTilt, yTilt ];
268
+
269
+ float magnification = _tvParallaxProperties.magnification;
270
+
271
+ [UIView animateWithDuration:0.2 animations:^{
272
+ self.transform = CGAffineTransformScale(self.transform, magnification, magnification);
273
+ }];
274
+
275
+ _motionEffectsAdded = YES;
276
+ }
277
+
278
+ - (void)removeParallaxMotionEffects
279
+ {
280
+ if(_motionEffectsAdded == NO) {
281
+ return;
282
+ }
283
+
284
+ [UIView animateWithDuration:0.2 animations:^{
285
+ float magnification = self->_tvParallaxProperties.magnification;
286
+ BOOL enabled = self->_tvParallaxProperties.enabled;
287
+ if (enabled && magnification) {
288
+ self.transform = CGAffineTransformScale(self.transform, 1.0/magnification, 1.0/magnification);
289
+ }
290
+ }];
291
+
292
+ for (UIMotionEffect *effect in [self.motionEffects copy]){
293
+ [self removeMotionEffect:effect];
294
+ }
295
+
296
+ _motionEffectsAdded = NO;
297
+ }
298
+
299
+
300
+ - (BOOL)isUserInteractionEnabled
301
+ {
302
+ return YES;
303
+ }
304
+
305
+ - (BOOL)canBecomeFocused
306
+ {
307
+ return _props->isTVSelectable;
308
+ }
309
+
310
+ - (NSArray<id<UIFocusEnvironment>> *)preferredFocusEnvironments {
311
+ if (_nextFocusActiveTarget == nil) return [super preferredFocusEnvironments];
312
+ UIView * nextFocusActiveTarget = _nextFocusActiveTarget;
313
+ _nextFocusActiveTarget = nil;
314
+ NSArray<id<UIFocusEnvironment>> * focusEnvironment = @[nextFocusActiveTarget];
315
+ return focusEnvironment;
316
+ }
317
+
318
+ - (BOOL) shouldUpdateFocusInContext:(UIFocusUpdateContext *)context {
319
+ if (self.isFocused) {
320
+ if (_nextFocusUp != nil && context.focusHeading == UIFocusHeadingUp) {
321
+ self->_nextFocusActiveTarget = _nextFocusUp;
322
+ [self setNeedsFocusUpdate];
323
+ return false;
324
+ }
325
+ if (_nextFocusDown != nil && context.focusHeading == UIFocusHeadingDown) {
326
+ self->_nextFocusActiveTarget = _nextFocusDown;
327
+ [self setNeedsFocusUpdate];
328
+ return false;
329
+ }
330
+ if (_nextFocusLeft != nil && context.focusHeading == UIFocusHeadingLeft) {
331
+ self->_nextFocusActiveTarget = _nextFocusLeft;
332
+ [self setNeedsFocusUpdate];
333
+ return false;
334
+ }
335
+ if (_nextFocusRight != nil && context.focusHeading == UIFocusHeadingRight) {
336
+ self->_nextFocusActiveTarget = _nextFocusRight;
337
+ [self setNeedsFocusUpdate];
338
+ return false;
339
+ }
340
+ self->_nextFocusActiveTarget = nil;
341
+ return true;
342
+ }
343
+ self->_nextFocusActiveTarget = nil;
344
+ return true;
345
+ }
346
+
347
+ - (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
348
+ {
349
+ if (context.previouslyFocusedView == context.nextFocusedView) {
350
+ return;
351
+ }
352
+ if (context.nextFocusedView == self && self.isUserInteractionEnabled ) {
353
+ [self becomeFirstResponder];
354
+ [coordinator addCoordinatedAnimations:^(void){
355
+ [self addParallaxMotionEffects];
356
+ [self sendFocusNotification:context];
357
+ } completion:^(void){}];
358
+ } else {
359
+ [coordinator addCoordinatedAnimations:^(void){
360
+ [self removeParallaxMotionEffects];
361
+ [self sendBlurNotification:context];
362
+ } completion:^(void){}];
363
+ [self resignFirstResponder];
364
+ }
365
+ }
366
+
367
+ #endif
368
+
369
+ #pragma mark - Native Commands
370
+
371
+ - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
372
+ {
373
+ NSLog(@"RCTViewComponentView handleCommand: %@", commandName);
374
+ if ([commandName isEqualToString:@"setDestinations"]) {
375
+ #if TARGET_OS_TV
376
+ if ([args count] != 1) {
377
+ RCTLogError(
378
+ @"%@ command %@ received %d arguments, expected %d.", @"View", commandName, (int)[args count], 1);
379
+ return;
380
+ }
381
+ if (!RCTValidateTypeOfViewCommandArgument(args[0], [NSArray class], @"number", @"View", commandName, @"1st")) {
382
+ return;
383
+ }
384
+ NSArray *destinationTags = (NSArray<NSNumber *> *)args[0];
385
+ NSMutableArray *destinations = [NSMutableArray new];
386
+ RCTRootComponentView *rootView = [self containingRootView];
387
+ for (NSNumber *tag in destinationTags) {
388
+ UIView *view = [rootView viewWithTag:[tag intValue]];
389
+ if (view != nil) {
390
+ [destinations addObject:view];
391
+ }
392
+ }
393
+ [self addFocusDestinations:destinations];
394
+ return;
395
+ #endif
396
+ }
397
+ #if RCT_DEBUG
398
+ RCTLogError(@"%@ received command %@, which is not a supported command.", @"View", commandName);
399
+ #endif
400
+ }
401
+
83
402
  #pragma mark - RCTComponentViewProtocol
84
403
 
85
404
  + (ComponentDescriptorProvider)componentDescriptorProvider
@@ -361,11 +680,87 @@ using namespace facebook::react;
361
680
  self.accessibilityIdentifier = RCTNSStringFromString(newViewProps.testId);
362
681
  }
363
682
 
683
+ #if TARGET_OS_TV
684
+ // `isTVSelectable`
685
+ if (oldViewProps.isTVSelectable != newViewProps.isTVSelectable) {
686
+ if (newViewProps.isTVSelectable) {
687
+ UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
688
+ action:@selector(handleSelect:)];
689
+ recognizer.allowedPressTypes = @[ @(UIPressTypeSelect) ];
690
+ _selectRecognizer = recognizer;
691
+ [self addGestureRecognizer:_selectRecognizer];
692
+ } else {
693
+ if (_selectRecognizer) {
694
+ [self removeGestureRecognizer:_selectRecognizer];
695
+ }
696
+ }
697
+ }
698
+ // `tvParallaxProperties
699
+ if (oldViewProps.tvParallaxProperties != newViewProps.tvParallaxProperties) {
700
+ _tvParallaxProperties.enabled = newViewProps.tvParallaxProperties.enabled.has_value() ?
701
+ newViewProps.tvParallaxProperties.enabled.value() :
702
+ newViewProps.isTVSelectable;
703
+ _tvParallaxProperties.shiftDistanceX = [self getFloat:newViewProps.tvParallaxProperties.shiftDistanceX orDefault:2.0];
704
+ _tvParallaxProperties.shiftDistanceY = [self getFloat:newViewProps.tvParallaxProperties.shiftDistanceY orDefault:2.0];
705
+ _tvParallaxProperties.tiltAngle = [self getFloat:newViewProps.tvParallaxProperties.tiltAngle orDefault:0.05];
706
+ _tvParallaxProperties.magnification = [self getFloat:newViewProps.tvParallaxProperties.magnification orDefault:1.0];
707
+ _tvParallaxProperties.pressMagnification = [self getFloat:newViewProps.tvParallaxProperties.pressMagnification orDefault:1.0];
708
+ _tvParallaxProperties.pressDuration = [self getFloat:newViewProps.tvParallaxProperties.pressDuration orDefault:0.3];
709
+ _tvParallaxProperties.pressDelay = [self getFloat:newViewProps.tvParallaxProperties.pressDelay orDefault:0.0];
710
+ }
711
+ // `hasTVPreferredFocus
712
+ if (oldViewProps.hasTVPreferredFocus != newViewProps.hasTVPreferredFocus) {
713
+ _hasTVPreferredFocus = newViewProps.hasTVPreferredFocus;
714
+ }
715
+ // `nextFocusUp`
716
+ if (oldViewProps.nextFocusUp != newViewProps.nextFocusUp) {
717
+ if (newViewProps.nextFocusUp.has_value()) {
718
+ UIView *rootView = [self containingRootView];
719
+ _nextFocusUp = [rootView viewWithTag:newViewProps.nextFocusUp.value()];
720
+ } else {
721
+ _nextFocusUp = nil;
722
+ }
723
+ }
724
+ // `nextFocusDown`
725
+ if (oldViewProps.nextFocusDown != newViewProps.nextFocusDown) {
726
+ if (newViewProps.nextFocusDown.has_value()) {
727
+ UIView *rootView = [self containingRootView];
728
+ _nextFocusDown = [rootView viewWithTag:newViewProps.nextFocusDown.value()];
729
+ } else {
730
+ _nextFocusDown = nil;
731
+ }
732
+ }
733
+ // `nextFocusLeft`
734
+ if (oldViewProps.nextFocusLeft != newViewProps.nextFocusLeft) {
735
+ if (newViewProps.nextFocusLeft.has_value()) {
736
+ UIView *rootView = [self containingRootView];
737
+ _nextFocusLeft = [rootView viewWithTag:newViewProps.nextFocusLeft.value()];
738
+ } else {
739
+ _nextFocusLeft = nil;
740
+ }
741
+ }
742
+ // `nextFocusRight`
743
+ if (oldViewProps.nextFocusRight != newViewProps.nextFocusRight) {
744
+ if (newViewProps.nextFocusRight.has_value()) {
745
+ UIView *rootView = [self containingRootView];
746
+ _nextFocusRight = [rootView viewWithTag:newViewProps.nextFocusRight.value()];
747
+ } else {
748
+ _nextFocusRight = nil;
749
+ }
750
+ }
751
+ #endif
752
+
753
+
364
754
  _needsInvalidateLayer = _needsInvalidateLayer || needsInvalidateLayer;
365
755
 
366
756
  _props = std::static_pointer_cast<ViewProps const>(props);
367
757
  }
368
758
 
759
+ - (float)getFloat:(better::optional<float>)property orDefault:(float)defaultValue
760
+ {
761
+ return property.has_value() ? (float)property.value() : defaultValue;
762
+ }
763
+
369
764
  - (void)updateEventEmitter:(EventEmitter::Shared const &)eventEmitter
370
765
  {
371
766
  assert(std::dynamic_pointer_cast<ViewEventEmitter const>(eventEmitter));
@@ -389,6 +784,25 @@ using namespace facebook::react;
389
784
  if (_contentView) {
390
785
  _contentView.frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame());
391
786
  }
787
+
788
+ #if TARGET_OS_TV
789
+ [self.focusGuide.topAnchor constraintEqualToAnchor:self.topAnchor].active = YES;
790
+ [self.focusGuide.bottomAnchor constraintEqualToAnchor:self.bottomAnchor].active = YES;
791
+ [self.focusGuide.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES;
792
+ [self.focusGuide.heightAnchor constraintEqualToAnchor:self.heightAnchor].active = YES;
793
+
794
+ if (_hasTVPreferredFocus) {
795
+ RCTRootComponentView *rootview = [self containingRootView];
796
+ if (rootview != nil && rootview.reactPreferredFocusedView != self) {
797
+ rootview.reactPreferredFocusedView = self;
798
+ [rootview setNeedsFocusUpdate];
799
+ [rootview updateFocusIfNeeded];
800
+ }
801
+ }
802
+
803
+ #endif
804
+
805
+
392
806
  }
393
807
 
394
808
  - (BOOL)isJSResponder
@@ -30,6 +30,7 @@
30
30
  #import "RCTFabricComponentsPlugins.h"
31
31
  #import "RCTImageComponentView.h"
32
32
  #import "RCTLegacyViewManagerInteropComponentView.h"
33
+ #import "RCTModalHostViewComponentView.h"
33
34
  #import "RCTMountingTransactionObserving.h"
34
35
  #import "RCTParagraphComponentView.h"
35
36
  #import "RCTRootComponentView.h"
@@ -73,6 +74,7 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
73
74
  [componentViewFactory registerComponentViewClass:[RCTViewComponentView class]];
74
75
  [componentViewFactory registerComponentViewClass:[RCTParagraphComponentView class]];
75
76
  [componentViewFactory registerComponentViewClass:[RCTTextInputComponentView class]];
77
+ [componentViewFactory registerComponentViewClass:[RCTModalHostViewComponentView class]];
76
78
 
77
79
  Class<RCTComponentViewProtocol> imageClass = RCTComponentViewClassWithName("Image");
78
80
  [componentViewFactory registerComponentViewClass:imageClass];
@@ -65,4 +65,9 @@
65
65
  */
66
66
  - (void)removeParallaxMotionEffects;
67
67
 
68
+
69
+ - (void)addFocusGuide:(NSArray*)destinations;
70
+
71
+ @property (nonatomic, strong) UIFocusGuide * focusGuide;
72
+
68
73
  @end
@@ -375,4 +375,20 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
375
375
  }
376
376
  }
377
377
 
378
+ - (void)addFocusGuide:(NSArray*)destinations {
379
+
380
+ UIView *origin = [self reactSuperview];
381
+ if (self.focusGuide == nil && origin != nil) {
382
+ self.focusGuide = [UIFocusGuide new];
383
+ [self addLayoutGuide:self.focusGuide];
384
+
385
+ [self.focusGuide.widthAnchor constraintEqualToAnchor:origin.widthAnchor].active = YES;
386
+ [self.focusGuide.heightAnchor constraintEqualToAnchor:origin.heightAnchor].active = YES;
387
+ [self.focusGuide.topAnchor constraintEqualToAnchor:origin.topAnchor].active = YES;
388
+ [self.focusGuide.leftAnchor constraintEqualToAnchor:origin.leftAnchor].active = YES;
389
+ }
390
+
391
+ self.focusGuide.preferredFocusEnvironments = destinations;
392
+ }
393
+
378
394
  @end
@@ -435,4 +435,21 @@ RCT_EXPORT_SHADOW_PROPERTY(onLayout, RCTDirectEventBlock)
435
435
 
436
436
  RCT_EXPORT_SHADOW_PROPERTY(direction, YGDirection)
437
437
 
438
+ #if TARGET_OS_TV
439
+ RCT_EXPORT_METHOD(setDestinations : (nonnull NSNumber *)viewTag reactTags : (NSArray<NSNumber *> *)destinationTags)
440
+ {
441
+ [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
442
+ RCTTVView *view = (RCTTVView *)viewRegistry[viewTag];
443
+ NSMutableArray* destinations = [NSMutableArray array];
444
+ for (NSNumber * tag in destinationTags) {
445
+ RCTTVView *destination = (RCTTVView*)viewRegistry[tag];
446
+ if (destination != nil) {
447
+ [destinations addObject:destination];
448
+ }
449
+ }
450
+ [view addFocusGuide:destinations];
451
+ }];
452
+ }
453
+ #endif
454
+
438
455
  @end
@@ -1,4 +1,4 @@
1
- VERSION_NAME=0.66.3-1
1
+ VERSION_NAME=0.66.3-2
2
2
  GROUP=com.facebook.react
3
3
 
4
4
  POM_NAME=ReactNative