react-native-tvos 0.73.4-0rc1 → 0.73.6-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.
Files changed (31) hide show
  1. package/Libraries/Components/TV/TVFocusGuideView.js +23 -5
  2. package/Libraries/Core/ReactNativeVersion.js +2 -2
  3. package/Libraries/LogBox/Data/parseLogBoxLog.js +1 -1
  4. package/Libraries/Text/TextInput/RCTBaseTextInputShadowView.mm +48 -0
  5. package/README.md +24 -14
  6. package/React/Base/RCTVersion.m +2 -2
  7. package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +246 -0
  8. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +39 -16
  9. package/React/React-RCTFabric.podspec +3 -2
  10. package/React/Views/RCTTVView.m +21 -2
  11. package/ReactAndroid/gradle.properties +1 -1
  12. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +2 -2
  13. package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +1 -1
  14. package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +4 -0
  15. package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
  16. package/package.json +7 -7
  17. package/scripts/cocoapods/new_architecture.rb +5 -1
  18. package/scripts/cocoapods/utils.rb +21 -0
  19. package/scripts/codegen/generate-artifacts-executor.js +18 -11
  20. package/scripts/react_native_pods.rb +1 -0
  21. package/scripts/xcode/with-environment.sh +1 -1
  22. package/sdks/.hermesversion +1 -1
  23. package/sdks/hermes-engine/hermes-utils.rb +4 -3
  24. package/sdks/hermesc/linux64-bin/hermesc +0 -0
  25. package/sdks/hermesc/osx-bin/hermes +0 -0
  26. package/sdks/hermesc/osx-bin/hermesc +0 -0
  27. package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
  28. package/sdks/hermesc/win64-bin/msvcp140.dll +0 -0
  29. package/sdks/hermesc/win64-bin/vcruntime140.dll +0 -0
  30. package/sdks/hermesc/win64-bin/vcruntime140_1.dll +0 -0
  31. package/template/package.json +1 -1
@@ -8,13 +8,14 @@
8
8
  * @format
9
9
  */
10
10
 
11
- const React = require('react');
12
- const ReactNative = require('react-native');
13
-
14
- import {Commands} from '../View/ViewNativeComponent';
15
- import type {ViewProps} from '../View/ViewPropTypes';
16
11
  import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
12
+ import type {ViewProps} from '../View/ViewPropTypes';
13
+
17
14
  import setAndForwardRef from '../../Utilities/setAndForwardRef';
15
+ import {Commands} from '../View/ViewNativeComponent';
16
+
17
+ const React = require('react');
18
+ const ReactNative = require('react-native');
18
19
 
19
20
  const {View} = ReactNative;
20
21
 
@@ -44,6 +45,11 @@ type TVFocusGuideViewProps = $ReadOnly<{
44
45
  trapFocusDown?: boolean,
45
46
  trapFocusLeft?: boolean,
46
47
  trapFocusRight?: boolean,
48
+
49
+ /**
50
+ * When set to false, this view and all its subviews will be NOT focusable.
51
+ */
52
+ focusable?: boolean | undefined,
47
53
  }>;
48
54
 
49
55
  export type TVFocusGuideViewImperativeMethods = $ReadOnly<{
@@ -57,6 +63,8 @@ function TVFocusGuideView(
57
63
  enabled = true,
58
64
  safePadding,
59
65
  destinations: destinationsProp,
66
+ autoFocus,
67
+ focusable,
60
68
  ...props
61
69
  }: TVFocusGuideViewProps,
62
70
  forwardedRef,
@@ -106,6 +114,11 @@ function TVFocusGuideView(
106
114
  const enabledStyle = {display: enabled ? 'flex' : 'none'};
107
115
  const style = [styles.container, props.style, enabledStyle];
108
116
 
117
+ // If there are no destinations and the autoFocus is false the the default value of focusable should be false
118
+ // It is then properly handled by the native code
119
+ const tvOSSelectable =
120
+ destinationsProp || autoFocus ? focusable !== false : false;
121
+
109
122
  return (
110
123
  // $FlowFixMe[prop-missing]
111
124
  <ReactNative.View
@@ -113,6 +126,11 @@ function TVFocusGuideView(
113
126
  style={style}
114
127
  ref={_setNativeRef}
115
128
  collapsable={false}
129
+ autoFocus={autoFocus}
130
+ // tvOS only prop
131
+ isTVSelectable={tvOSSelectable}
132
+ // Android TV only prop
133
+ tvFocusable={focusable}
116
134
  />
117
135
  );
118
136
  }
@@ -12,6 +12,6 @@
12
12
  exports.version = {
13
13
  major: 0,
14
14
  minor: 73,
15
- patch: 4,
16
- prerelease: '0rc1',
15
+ patch: 6,
16
+ prerelease: '1',
17
17
  };
@@ -192,7 +192,7 @@ export function parseComponentStack(message: string): ComponentStack {
192
192
  if (!s) {
193
193
  return null;
194
194
  }
195
- const match = s.match(/(.*) \(at (.*\.js):([\d]+)\)/);
195
+ const match = s.match(/(.*) \(at (.*\.(?:js|jsx|ts|tsx)):([\d]+)\)/);
196
196
  if (!match) {
197
197
  return null;
198
198
  }
@@ -158,6 +158,8 @@
158
158
  [attributedText insertAttributedString:propertyAttributedText atIndex:0];
159
159
  }
160
160
 
161
+ [self postprocessAttributedText:attributedText];
162
+
161
163
  NSAttributedString *newAttributedText;
162
164
  if (![_previousAttributedText isEqualToAttributedString:attributedText]) {
163
165
  // We have to follow `set prop` pattern:
@@ -191,6 +193,52 @@
191
193
  }];
192
194
  }
193
195
 
196
+ - (void)postprocessAttributedText:(NSMutableAttributedString *)attributedText
197
+ {
198
+ __block CGFloat maximumLineHeight = 0;
199
+
200
+ [attributedText enumerateAttribute:NSParagraphStyleAttributeName
201
+ inRange:NSMakeRange(0, attributedText.length)
202
+ options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
203
+ usingBlock:^(NSParagraphStyle *paragraphStyle, __unused NSRange range, __unused BOOL *stop) {
204
+ if (!paragraphStyle) {
205
+ return;
206
+ }
207
+
208
+ maximumLineHeight = MAX(paragraphStyle.maximumLineHeight, maximumLineHeight);
209
+ }];
210
+
211
+ if (maximumLineHeight == 0) {
212
+ // `lineHeight` was not specified, nothing to do.
213
+ return;
214
+ }
215
+
216
+ __block CGFloat maximumFontLineHeight = 0;
217
+
218
+ [attributedText enumerateAttribute:NSFontAttributeName
219
+ inRange:NSMakeRange(0, attributedText.length)
220
+ options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
221
+ usingBlock:^(UIFont *font, NSRange range, __unused BOOL *stop) {
222
+ if (!font) {
223
+ return;
224
+ }
225
+
226
+ if (maximumFontLineHeight <= font.lineHeight) {
227
+ maximumFontLineHeight = font.lineHeight;
228
+ }
229
+ }];
230
+
231
+ if (maximumLineHeight < maximumFontLineHeight) {
232
+ return;
233
+ }
234
+
235
+ CGFloat baseLineOffset = maximumLineHeight / 2.0 - maximumFontLineHeight / 2.0;
236
+
237
+ [attributedText addAttribute:NSBaselineOffsetAttributeName
238
+ value:@(baseLineOffset)
239
+ range:NSMakeRange(0, attributedText.length)];
240
+ }
241
+
194
242
  #pragma mark -
195
243
 
196
244
  - (NSAttributedString *)measurableAttributedText
package/README.md CHANGED
@@ -59,12 +59,12 @@ yarn create react-native-app TestApp --template https://github.com/react-native-
59
59
  cd TestApp
60
60
  # Now build and start the app in the tvOS Simulator - this will only work on a macOS machine.
61
61
  # This command can also be run via "yarn tvos".
62
- npx expo run:ios --scheme MyApp-tvOS --device "Apple TV"
62
+ npx expo run:ios --scheme TestApp-tvOS --device "Apple TV"
63
63
  # You can also build and start the app on an iOS phone simulator.
64
64
  # This command can also be run via "yarn ios".
65
65
  npx expo run:ios
66
66
  # or specify a simulator:
67
- npx expo run:ios --scheme MyApp --device "iPhone 15"
67
+ npx expo run:ios --scheme TestApp --device "iPhone 15"
68
68
  # This command builds and starts the app in an Android TV emulator or a phone emulator (needs to be created in advance).
69
69
  # This command can also be run via "yarn android".
70
70
  npx expo run:android --device tv_api_31
@@ -204,15 +204,25 @@ class Game2048 extends React.Component {
204
204
 
205
205
  - _TVFocusGuideView_: This component provides support for Apple's `UIFocusGuide` API and is implemented in the same way for Android TV, to help ensure that focusable controls can be navigated to, even if they are not directly in line with other controls. An example is provided in `RNTester` that shows two different ways of using this component.
206
206
 
207
- | Prop | Value | Description |
208
- |---|---|---|
209
- | destinations | any[]? | Array of `Component`s to register as destinations of the FocusGuideView |
210
- | autoFocus | boolean? | If true, `TVFocusGuide` will automatically manage focus for you. It will redirect the focus to the first focusable child on the first visit. It also remembers the last focused child and redirects the focus to it on the subsequent visits. `destinations` prop takes precedence over this prop when used together. |
211
- | trapFocus* (Up, Down, Left, Right) | Prevents focus escaping from the container for the given directions. |
212
-
213
- More information on the focus handling improvements above can be found in [this article](https://medium.com/xite-engineering/revolutionizing-focus-management-in-tv-applications-with-react-native-10ba69bd90).
214
-
215
- - _Next Focus Direction_: the props `nextFocus*` on `View` should work as expected on iOS too (previously android only). One caveat is that if there is no focusable in the `nextFocusable*` direction next to the starting view, iOS doesn't check if we want to override the destination.
216
-
217
- - _TVTextScrollView_: On Apple TV, a ScrollView will not scroll unless there are focusable items inside it or above/below it. This component wraps ScrollView and uses tvOS-specific native code to allow scrolling using swipe gestures from the remote control.
218
-
207
+ | Prop | Value | Description |
208
+ |---|---|---|
209
+ | destinations | any[]? | Array of `Component`s to register as destinations of the FocusGuideView |
210
+ | autoFocus | boolean? | If true, `TVFocusGuide` will automatically manage focus for you. It will redirect the focus to the first focusable child on the first visit. It also remembers the last focused child and redirects the focus to it on the subsequent visits. `destinations` prop takes precedence over this prop when used together. |
211
+ | focusable | boolean? | When set to false, this view and all its subviews will be NOT focusable. |
212
+ | trapFocus* (Up, Down, Left, Right) | Prevents focus escaping from the container for the given directions. |
213
+
214
+ More information on the focus handling improvements above can be found in [this article](https://medium.com/xite-engineering/revolutionizing-focus-management-in-tv-applications-with-react-native-10ba69bd90).
215
+
216
+ - _Next Focus Direction_: the props `nextFocus*` on `View` should work as expected on iOS too (previously android only). One caveat is that if there is no focusable in the `nextFocusable*` direction next to the starting view, iOS doesn't check if we want to override the destination.
217
+
218
+ - _TVTextScrollView_: On Apple TV, a ScrollView will not scroll unless there are focusable items inside it or above/below it. This component wraps ScrollView and uses tvOS-specific native code to allow scrolling using swipe gestures from the remote control.
219
+
220
+ - VirtualizedList: We extend `VirtualizedList` to make virtualization work well with focus management in mind. All of the improvements that we made are automatically available to all the VirtualizedList based components such as `FlatList`.
221
+ - Defaults
222
+ - VirtualizeList contents are automatically wrapped with a `TVFocusGuideView` with `trapFocus*` properties enabled depending on the orientation of the list. This default makes sure that focus doesn't leave the list accidentally due to a virtualization issue etc. until reaching the beginning or the end of the list.
223
+
224
+ New Props:
225
+
226
+ | Prop | Value | Description |
227
+ |---|---|---|
228
+ | additionalRenderRegions | {first: number; last: number;}[]? | Array of `RenderRegions` that allows you to define regions in the list that are not subject to virtualization, ensuring they are always rendered. This is particularly useful for preventing blank areas in critical parts of the list. These regions are rendered lazily after the initial render and are specified as an array of objects, each with `first` and `last` indices marking the beginning and end of the non-virtualized region based on index. See the [feature proposal](https://github.com/react-native-tvos/react-native-tvos/discussions/663) for more context. |
@@ -23,8 +23,8 @@ NSDictionary* RCTGetReactNativeVersion(void)
23
23
  __rnVersion = @{
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(73),
26
- RCTVersionPatch: @(4),
27
- RCTVersionPrerelease: @"0rc1",
26
+ RCTVersionPatch: @(6),
27
+ RCTVersionPrerelease: @"1",
28
28
  };
29
29
  });
30
30
  return __rnVersion;
@@ -24,9 +24,14 @@
24
24
  #import "RCTEnhancedScrollView.h"
25
25
  #import "RCTFabricComponentsPlugins.h"
26
26
 
27
+ #if TARGET_OS_TV
28
+ #import "RCTTVRemoteHandler.h"
29
+ #endif
30
+
27
31
  using namespace facebook::react;
28
32
 
29
33
  static const CGFloat kClippingLeeway = 44.0;
34
+ static const float TV_DEFAULT_SWIPE_DURATION = 0.3;
30
35
 
31
36
  static UIScrollViewKeyboardDismissMode RCTUIKeyboardDismissModeFromProps(const ScrollViewProps &props)
32
37
  {
@@ -105,6 +110,9 @@ static void RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrol
105
110
 
106
111
  CGRect _prevFirstVisibleFrame;
107
112
  __weak UIView *_firstVisibleView;
113
+
114
+ BOOL _blockFirstTouch;
115
+ NSMutableDictionary *_tvRemoteGestureRecognizers;
108
116
  }
109
117
 
110
118
  + (RCTScrollViewComponentView *_Nullable)findScrollViewComponentViewForView:(UIView *)view
@@ -139,6 +147,8 @@ static void RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrol
139
147
  } else {
140
148
  _scrollEventThrottle = INFINITY;
141
149
  }
150
+
151
+ _tvRemoteGestureRecognizers = [NSMutableDictionary new];
142
152
  }
143
153
 
144
154
  return self;
@@ -792,6 +802,242 @@ static void RCTSendScrollEventForNativeAnimations_DEPRECATED(UIScrollView *scrol
792
802
  }
793
803
  }
794
804
 
805
+ #pragma mark Apple TV swipe and focus handling
806
+
807
+ #if TARGET_OS_TV
808
+ - (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context
809
+ withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
810
+ {
811
+ if (context.previouslyFocusedView == context.nextFocusedView || !_props->isTVSelectable) {
812
+ return;
813
+ }
814
+ if (context.nextFocusedView == self) {
815
+ [self becomeFirstResponder];
816
+ [self addSwipeGestureRecognizers];
817
+ [self sendFocusNotification];
818
+ // if we enter the scroll view from different view then block first touch event since it is the event that triggered the focus
819
+ _blockFirstTouch = (unsigned long)context.focusHeading != 0;
820
+ [self addArrowsListeners];
821
+ } else if (context.previouslyFocusedView == self) {
822
+ [self removeArrowsListeners];
823
+ [self sendBlurNotification];
824
+ [self removeSwipeGestureRecognizers];
825
+ [self resignFirstResponder];
826
+ // if we leave the scroll view and go up, then scroll to top; if going down,
827
+ // scroll to bottom
828
+ // Similarly for left and right
829
+ RCTEnhancedScrollView *scrollView = (RCTEnhancedScrollView *)_scrollView;
830
+ if (context.focusHeading == UIFocusHeadingUp && scrollView.snapToStart) {
831
+ [self swipeVerticalScrollToOffset:0.0];
832
+ } else if(context.focusHeading == UIFocusHeadingDown && scrollView.snapToEnd) {
833
+ [self swipeVerticalScrollToOffset:scrollView.contentSize.height];
834
+ } else if(context.focusHeading == UIFocusHeadingLeft && scrollView.snapToStart) {
835
+ [self swipeHorizontalScrollToOffset:0.0];
836
+ } else if(context.focusHeading == UIFocusHeadingRight && scrollView.snapToEnd) {
837
+ [self swipeHorizontalScrollToOffset:scrollView.contentSize.width];
838
+ }
839
+ }
840
+ }
841
+
842
+ - (void)addArrowsListeners
843
+ {
844
+ [[NSNotificationCenter defaultCenter] addObserver:self
845
+ selector:@selector(handleTVNavigationEventNotification:)
846
+ name:@"RCTTVNavigationEventNotification"
847
+ object:nil];
848
+ }
849
+
850
+ - (void)removeArrowsListeners
851
+ {
852
+ [[NSNotificationCenter defaultCenter] removeObserver:self
853
+ name:@"RCTTVNavigationEventNotification"
854
+ object:nil];
855
+ }
856
+
857
+ - (void)handleTVNavigationEventNotification:(NSNotification *)notif
858
+ {
859
+ NSArray *supportedEvents = [NSArray arrayWithObjects:@"up", @"down", @"left", @"right", nil];
860
+
861
+ if (notif.object == nil || notif.object[@"eventType"] == nil || ![supportedEvents containsObject:notif.object[@"eventType"]] ) {
862
+ return;
863
+ }
864
+
865
+ if (_blockFirstTouch) {
866
+ _blockFirstTouch = NO;
867
+ return;
868
+ }
869
+
870
+ BOOL isHorizontal = _scrollView.contentSize.width > self.frame.size.width;
871
+ if (!isHorizontal) {
872
+ if ([notif.object[@"eventType"] isEqual: @"down"]) {
873
+ [self swipedDown];
874
+ return;
875
+ }
876
+
877
+ if ([notif.object[@"eventType"] isEqual: @"up"]) {
878
+ [self swipedUp];
879
+ return;
880
+ }
881
+ }
882
+
883
+ if ([notif.object[@"eventType"] isEqual: @"left"]) {
884
+ [self swipedLeft];
885
+ return;
886
+ }
887
+
888
+ if ([notif.object[@"eventType"] isEqual: @"right"]) {
889
+ [self swipedRight];
890
+ return;
891
+ }
892
+ }
893
+
894
+ - (BOOL)shouldUpdateFocusInContext:(UIFocusUpdateContext *)context
895
+ {
896
+ BOOL isHorizontal = _scrollView.contentSize.width > self.frame.size.width;
897
+ // Keep focus inside the scroll view till the end of the content
898
+ if (isHorizontal) {
899
+ if ((context.focusHeading == UIFocusHeadingLeft && self.scrollView.contentOffset.x > 0)
900
+ || (context.focusHeading == UIFocusHeadingRight && self.scrollView.contentOffset.x < self.scrollView.contentSize.width - self.scrollView.visibleSize.width)
901
+ ) {
902
+ return [UIFocusSystem environment:self containsEnvironment:context.nextFocusedItem];
903
+ }
904
+ } else {
905
+ if ((context.focusHeading == UIFocusHeadingUp && self.scrollView.contentOffset.y > 0)
906
+ || (context.focusHeading == UIFocusHeadingDown && self.scrollView.contentOffset.y < self.scrollView.contentSize.height - self.scrollView.visibleSize.height)
907
+ ) {
908
+ return [UIFocusSystem environment:self containsEnvironment:context.nextFocusedItem];
909
+ }
910
+ }
911
+
912
+ return [super shouldUpdateFocusInContext:context];
913
+ }
914
+
915
+ - (void)sendFocusNotification
916
+ {
917
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"RCTTVNavigationEventNotification"
918
+ object:@{ @"eventType": @"focus", @"tag": @([self tag]) }];
919
+ }
920
+
921
+ - (void)sendBlurNotification
922
+ {
923
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"RCTTVNavigationEventNotification"
924
+ object:@{ @"eventType": @"blur", @"tag": @([self tag]) }];
925
+ }
926
+
927
+ - (NSInteger)swipeVerticalInterval
928
+ {
929
+ RCTEnhancedScrollView *scrollView = (RCTEnhancedScrollView *)_scrollView;
930
+ if (scrollView.snapToInterval) {
931
+ return scrollView.snapToInterval;
932
+ }
933
+ return scrollView.visibleSize.height / 2;
934
+ }
935
+
936
+ - (NSInteger)swipeHorizontalInterval
937
+ {
938
+ RCTEnhancedScrollView *scrollView = (RCTEnhancedScrollView *)_scrollView;
939
+ if (scrollView.snapToInterval) {
940
+ return scrollView.snapToInterval;
941
+ }
942
+ return scrollView.visibleSize.width / 2;
943
+ }
944
+
945
+ - (NSTimeInterval)swipeDuration
946
+ {
947
+ auto pressDuration = _props->tvParallaxProperties.pressDuration;
948
+ auto duration = pressDuration.has_value() ? pressDuration.value() : TV_DEFAULT_SWIPE_DURATION;
949
+ if (duration == 0.0) {
950
+ duration = TV_DEFAULT_SWIPE_DURATION;
951
+ }
952
+ return duration;
953
+ }
954
+
955
+ - (void)swipeVerticalScrollToOffset:(CGFloat)yOffset
956
+ {
957
+ _blockFirstTouch = NO;
958
+ dispatch_async(dispatch_get_main_queue(), ^{
959
+ CGFloat limitedOffset = yOffset;
960
+ limitedOffset = MAX(limitedOffset, 0.0);
961
+ limitedOffset = MIN(limitedOffset, self.scrollView.contentSize.height - self.scrollView.visibleSize.height);
962
+ [UIView animateWithDuration:[self swipeDuration] animations:^{
963
+ self.scrollView.contentOffset =
964
+ CGPointMake(self.scrollView.contentOffset.x, limitedOffset);
965
+ }];
966
+ });
967
+ }
968
+
969
+ - (void)swipeHorizontalScrollToOffset:(CGFloat)xOffset
970
+ {
971
+ _blockFirstTouch = NO;
972
+ dispatch_async(dispatch_get_main_queue(), ^{
973
+ CGFloat limitedOffset = xOffset;
974
+ limitedOffset = MAX(limitedOffset, 0.0);
975
+ limitedOffset = MIN(limitedOffset, self.scrollView.contentSize.width - self.scrollView.visibleSize.width);
976
+ [UIView animateWithDuration:[self swipeDuration] animations:^{
977
+ self.scrollView.contentOffset =
978
+ CGPointMake(limitedOffset, self.scrollView.contentOffset.y);
979
+ }];
980
+ });
981
+ }
982
+
983
+ - (void)swipedUp
984
+ {
985
+ CGFloat newOffset = self.scrollView.contentOffset.y - [self swipeVerticalInterval];
986
+ NSLog(@"Swiped up to %f", newOffset);
987
+ [self swipeVerticalScrollToOffset:newOffset];
988
+ }
989
+
990
+ - (void)swipedDown
991
+ {
992
+ CGFloat newOffset = self.scrollView.contentOffset.y + [self swipeVerticalInterval];
993
+ NSLog(@"Swiped down to %f", newOffset);
994
+ [self swipeVerticalScrollToOffset:newOffset];
995
+ }
996
+
997
+ - (void)swipedLeft
998
+ {
999
+ CGFloat newOffset = self.scrollView.contentOffset.x - [self swipeHorizontalInterval];
1000
+ NSLog(@"Swiped left to %f", newOffset);
1001
+ [self swipeHorizontalScrollToOffset:newOffset];
1002
+ }
1003
+
1004
+ - (void)swipedRight
1005
+ {
1006
+ CGFloat newOffset = self.scrollView.contentOffset.x + [self swipeHorizontalInterval];
1007
+ NSLog(@"Swiped right to %f", newOffset);
1008
+ [self swipeHorizontalScrollToOffset:newOffset];
1009
+ }
1010
+
1011
+ - (void)addSwipeGestureRecognizers
1012
+ {
1013
+ [self addSwipeGestureRecognizerWithSelector:@selector(swipedUp) direction:UISwipeGestureRecognizerDirectionUp name:RCTTVRemoteEventSwipeUp];
1014
+ [self addSwipeGestureRecognizerWithSelector:@selector(swipedDown) direction:UISwipeGestureRecognizerDirectionDown name:RCTTVRemoteEventSwipeDown];
1015
+ [self addSwipeGestureRecognizerWithSelector:@selector(swipedLeft) direction:UISwipeGestureRecognizerDirectionLeft name:RCTTVRemoteEventSwipeLeft];
1016
+ [self addSwipeGestureRecognizerWithSelector:@selector(swipedRight) direction:UISwipeGestureRecognizerDirectionRight name:RCTTVRemoteEventSwipeRight];
1017
+ }
1018
+
1019
+ - (void)addSwipeGestureRecognizerWithSelector:(nonnull SEL)selector
1020
+ direction:(UISwipeGestureRecognizerDirection)direction
1021
+ name:(NSString *)name
1022
+ {
1023
+ UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:selector];
1024
+ recognizer.direction = direction;
1025
+
1026
+ _tvRemoteGestureRecognizers[name] = recognizer;
1027
+ [self.scrollView addGestureRecognizer:recognizer];
1028
+ }
1029
+
1030
+ - (void)removeSwipeGestureRecognizers
1031
+ {
1032
+ NSArray *names = [self->_tvRemoteGestureRecognizers allKeys];
1033
+ for (NSString *name in names) {
1034
+ UIGestureRecognizer *r = self->_tvRemoteGestureRecognizers[name];
1035
+ [self.scrollView removeGestureRecognizer:r];
1036
+ [self->_tvRemoteGestureRecognizers removeObjectForKey:name];
1037
+ }
1038
+ }
1039
+ #endif // TARGET_OS_TV
1040
+
795
1041
  @end
796
1042
 
797
1043
  Class<RCTComponentViewProtocol> RCTScrollViewCls(void)
@@ -45,7 +45,7 @@ using namespace facebook::react;
45
45
 
46
46
  @implementation RCTViewComponentView {
47
47
  UIColor *_backgroundColor;
48
- CALayer *_borderLayer;
48
+ __weak CALayer *_borderLayer;
49
49
  BOOL _needsInvalidateLayer;
50
50
  BOOL _isJSResponder;
51
51
  BOOL _removeClippedSubviews;
@@ -415,13 +415,29 @@ using namespace facebook::react;
415
415
  }
416
416
 
417
417
 
418
+ - (BOOL)isTVFocusGuide
419
+ {
420
+ #if TARGET_OS_TV
421
+ return self.focusGuide != nil;
422
+ #endif
423
+
424
+ return NO;
425
+ }
426
+
427
+
418
428
  - (BOOL)isUserInteractionEnabled
419
429
  {
420
- return YES;
430
+ if ([self isTVFocusGuide]) {
431
+ return _props->isTVSelectable;
432
+ }
433
+ return YES;
421
434
  }
422
435
 
423
436
  - (BOOL)canBecomeFocused
424
437
  {
438
+ if ([self isTVFocusGuide]) {
439
+ return NO;
440
+ }
425
441
  return _props->isTVSelectable;
426
442
  }
427
443
 
@@ -433,6 +449,9 @@ using namespace facebook::react;
433
449
  //
434
450
  - (void)enableDirectionalFocusGuides
435
451
  {
452
+ if (!self.isFocused) {
453
+ return;
454
+ }
436
455
  if (self->_nextFocusUp != nil) {
437
456
  if (self.focusGuideUp == nil) {
438
457
  self.focusGuideUp = [UIFocusGuide new];
@@ -545,7 +564,7 @@ using namespace facebook::react;
545
564
  [self handleFocusGuide];
546
565
  }
547
566
 
548
- if (context.nextFocusedView == self && self.isUserInteractionEnabled ) {
567
+ if (context.nextFocusedView == self && self.isUserInteractionEnabled && ![self isTVFocusGuide]) {
549
568
  [self becomeFirstResponder];
550
569
  [self enableDirectionalFocusGuides];
551
570
  [coordinator addCoordinatedAnimations:^(void){
@@ -895,7 +914,7 @@ using namespace facebook::react;
895
914
  #if TARGET_OS_TV
896
915
  // `isTVSelectable`
897
916
  if (oldViewProps.isTVSelectable != newViewProps.isTVSelectable) {
898
- if (newViewProps.isTVSelectable) {
917
+ if (newViewProps.isTVSelectable && ![self isTVFocusGuide]) {
899
918
  UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
900
919
  action:@selector(handleSelect:)];
901
920
  recognizer.allowedPressTypes = @[ @(UIPressTypeSelect) ];
@@ -942,6 +961,7 @@ using namespace facebook::react;
942
961
  if (newViewProps.nextFocusUp.has_value()) {
943
962
  UIView *rootView = [self containingRootView];
944
963
  _nextFocusUp = [rootView viewWithTag:newViewProps.nextFocusUp.value()];
964
+ [self enableDirectionalFocusGuides];
945
965
  } else {
946
966
  _nextFocusUp = nil;
947
967
  }
@@ -951,6 +971,7 @@ using namespace facebook::react;
951
971
  if (newViewProps.nextFocusDown.has_value()) {
952
972
  UIView *rootView = [self containingRootView];
953
973
  _nextFocusDown = [rootView viewWithTag:newViewProps.nextFocusDown.value()];
974
+ [self enableDirectionalFocusGuides];
954
975
  } else {
955
976
  _nextFocusDown = nil;
956
977
  }
@@ -960,6 +981,7 @@ using namespace facebook::react;
960
981
  if (newViewProps.nextFocusLeft.has_value()) {
961
982
  UIView *rootView = [self containingRootView];
962
983
  _nextFocusLeft = [rootView viewWithTag:newViewProps.nextFocusLeft.value()];
984
+ [self enableDirectionalFocusGuides];
963
985
  } else {
964
986
  _nextFocusLeft = nil;
965
987
  }
@@ -969,6 +991,7 @@ using namespace facebook::react;
969
991
  if (newViewProps.nextFocusRight.has_value()) {
970
992
  UIView *rootView = [self containingRootView];
971
993
  _nextFocusRight = [rootView viewWithTag:newViewProps.nextFocusRight.value()];
994
+ [self enableDirectionalFocusGuides];
972
995
  } else {
973
996
  _nextFocusRight = nil;
974
997
  }
@@ -1013,9 +1036,7 @@ using namespace facebook::react;
1013
1036
  _layoutMetrics = layoutMetrics;
1014
1037
  _needsInvalidateLayer = YES;
1015
1038
 
1016
- if (_borderLayer) {
1017
- _borderLayer.frame = self.layer.bounds;
1018
- }
1039
+ _borderLayer.frame = self.layer.bounds;
1019
1040
 
1020
1041
  if (_contentView) {
1021
1042
  _contentView.frame = RCTCGRectFromRect(_layoutMetrics.getContentFrame());
@@ -1232,10 +1253,7 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle)
1232
1253
 
1233
1254
  if (useCoreAnimationBorderRendering) {
1234
1255
  layer.mask = nil;
1235
- if (_borderLayer) {
1236
- [_borderLayer removeFromSuperlayer];
1237
- _borderLayer = nil;
1238
- }
1256
+ [_borderLayer removeFromSuperlayer];
1239
1257
 
1240
1258
  layer.borderWidth = (CGFloat)borderMetrics.borderWidths.left;
1241
1259
  CGColorRef borderColor = RCTCreateCGColorRefFromSharedColor(borderMetrics.borderColors.left);
@@ -1248,11 +1266,12 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle)
1248
1266
  layer.backgroundColor = _backgroundColor.CGColor;
1249
1267
  } else {
1250
1268
  if (!_borderLayer) {
1251
- _borderLayer = [CALayer new];
1252
- _borderLayer.zPosition = -1024.0f;
1253
- _borderLayer.frame = layer.bounds;
1254
- _borderLayer.magnificationFilter = kCAFilterNearest;
1255
- [layer addSublayer:_borderLayer];
1269
+ CALayer *borderLayer = [CALayer new];
1270
+ borderLayer.zPosition = -1024.0f;
1271
+ borderLayer.frame = layer.bounds;
1272
+ borderLayer.magnificationFilter = kCAFilterNearest;
1273
+ [layer addSublayer:borderLayer];
1274
+ _borderLayer = borderLayer;
1256
1275
  }
1257
1276
 
1258
1277
  layer.backgroundColor = nil;
@@ -1293,6 +1312,10 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle)
1293
1312
  }
1294
1313
  }
1295
1314
 
1315
+ // If mutations are applied inside of Animation block, it may cause _borderLayer to be animated.
1316
+ // To stop that, imperatively remove all animations from _borderLayer.
1317
+ [_borderLayer removeAllAnimations];
1318
+
1296
1319
  // Stage 2.5. Custom Clipping Mask
1297
1320
  CAShapeLayer *maskLayer = nil;
1298
1321
  CGFloat cornerRadius = 0;
@@ -20,6 +20,7 @@ folly_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_C
20
20
  folly_compiler_flags = folly_flags + ' ' + '-Wno-comma -Wno-shorten-64-to-32'
21
21
  folly_version = '2022.05.16.00'
22
22
  boost_compiler_flags = '-Wno-documentation'
23
+ new_arch_flags = ENV['RCT_NEW_ARCH_ENABLED'] == '1' ? ' -DRCT_NEW_ARCH_ENABLED=1' : ''
23
24
 
24
25
  header_search_paths = [
25
26
  "\"$(PODS_TARGET_SRCROOT)/ReactCommon\"",
@@ -56,13 +57,13 @@ Pod::Spec.new do |s|
56
57
  "Fabric/**/RCTSurfacePointerHandler.mm"
57
58
  s.ios.exclude_files = "Fabric/**/RCTSurfaceTouchHandlerTV.mm",
58
59
  "Fabric/**/RCTSurfacePointerHandlerTV.mm"
59
- s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
60
+ s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags + new_arch_flags
60
61
  s.header_dir = header_dir
61
62
  s.module_name = module_name
62
63
  s.framework = ["JavaScriptCore", "MobileCoreServices"]
63
64
  s.pod_target_xcconfig = {
64
65
  "HEADER_SEARCH_PATHS" => header_search_paths,
65
- "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED" + " " + folly_flags,
66
+ "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED" + " " + folly_flags + new_arch_flags,
66
67
  "CLANG_CXX_LANGUAGE_STANDARD" => "c++20"
67
68
  }.merge!(ENV['USE_FRAMEWORKS'] != nil ? {
68
69
  "PUBLIC_HEADERS_FOLDER_PATH" => "#{module_name}.framework/Headers/#{header_dir}"
@@ -75,7 +75,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
75
75
  - (void)setIsTVSelectable:(BOOL)isTVSelectable
76
76
  {
77
77
  self->_isTVSelectable = isTVSelectable;
78
- if (isTVSelectable) {
78
+ if (isTVSelectable && ![self isTVFocusGuide]) {
79
79
  UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
80
80
  action:@selector(handleSelect:)];
81
81
  recognizer.allowedPressTypes = @[ @(UIPressTypeSelect) ];
@@ -138,13 +138,25 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
138
138
  }
139
139
  }
140
140
 
141
+ - (BOOL)isTVFocusGuide
142
+ {
143
+ return self.focusGuide != nil;
144
+ }
145
+
141
146
  - (BOOL)isUserInteractionEnabled
142
147
  {
148
+ if ([self isTVFocusGuide]) {
149
+ return (self.isTVSelectable);
150
+ }
143
151
  return YES;
144
152
  }
145
153
 
146
154
  - (BOOL)canBecomeFocused
147
155
  {
156
+ if ([self isTVFocusGuide]) {
157
+ return NO;
158
+ }
159
+
148
160
  return (self.isTVSelectable);
149
161
  }
150
162
 
@@ -311,7 +323,7 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
311
323
  [self handleFocusGuide];
312
324
  }
313
325
 
314
- if (context.nextFocusedView == self && self.isTVSelectable ) {
326
+ if (context.nextFocusedView == self && ![self isTVFocusGuide] && self.isTVSelectable ) {
315
327
  [self becomeFirstResponder];
316
328
  [self enableDirectionalFocusGuides];
317
329
  [coordinator addCoordinatedAnimations:^(void){
@@ -336,6 +348,9 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
336
348
  //
337
349
  - (void)enableDirectionalFocusGuides
338
350
  {
351
+ if (!self.isFocused) {
352
+ return;
353
+ }
339
354
  if (self->_nextFocusUp != nil) {
340
355
  if (self.focusGuideUp == nil) {
341
356
  self.focusGuideUp = [UIFocusGuide new];
@@ -455,18 +470,22 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : unused)
455
470
 
456
471
  - (void)setNextFocusUp:(NSNumber *)nextFocusUp {
457
472
  self->_nextFocusUp = [self getViewById: nextFocusUp];
473
+ [self enableDirectionalFocusGuides];
458
474
  }
459
475
 
460
476
  - (void)setNextFocusDown:(NSNumber *)nextFocusDown {
461
477
  self->_nextFocusDown = [self getViewById: nextFocusDown];
478
+ [self enableDirectionalFocusGuides];
462
479
  }
463
480
 
464
481
  - (void)setNextFocusLeft:(NSNumber *)nextFocusLeft {
465
482
  self->_nextFocusLeft = [self getViewById: nextFocusLeft];
483
+ [self enableDirectionalFocusGuides];
466
484
  }
467
485
 
468
486
  - (void)setNextFocusRight:(NSNumber *)nextFocusRight {
469
487
  self->_nextFocusRight = [self getViewById: nextFocusRight];
488
+ [self enableDirectionalFocusGuides];
470
489
  }
471
490
 
472
491
  - (void)setPreferredFocus:(BOOL)hasTVPreferredFocus
@@ -1,4 +1,4 @@
1
- VERSION_NAME=0.73.4-0rc1
1
+ VERSION_NAME=0.73.6-1
2
2
 
3
3
  # react.internal.publishingGroup=com.facebook.react
4
4
  # For TV use this group
@@ -17,6 +17,6 @@ public class ReactNativeVersion {
17
17
  public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
18
18
  "major", 0,
19
19
  "minor", 73,
20
- "patch", 4,
21
- "prerelease", "0rc1");
20
+ "patch", 6,
21
+ "prerelease", "1");
22
22
  }
@@ -1216,7 +1216,7 @@ public class ReactViewGroup extends ViewGroup
1216
1216
  * `mRecoverFocus` flag indicates a temporary focus recovery mode it's in which
1217
1217
  * requires full access to children focusable elements.
1218
1218
  */
1219
- if (isTVFocusGuide() && !mRecoverFocus) {
1219
+ if (isTVFocusGuide() && !mRecoverFocus && this.getDescendantFocusability() != ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
1220
1220
  View focusedChild = getFocusedChildOfFocusGuide();
1221
1221
 
1222
1222
  /*
@@ -12,6 +12,7 @@ import android.graphics.Rect;
12
12
  import android.os.Build;
13
13
  import android.util.Log;
14
14
  import android.view.View;
15
+ import android.view.ViewGroup;
15
16
  import androidx.annotation.NonNull;
16
17
  import androidx.annotation.Nullable;
17
18
  import com.facebook.common.logging.FLog;
@@ -306,6 +307,9 @@ public class ReactViewManager extends ReactClippingViewManager<ReactViewGroup> {
306
307
  setFocusable(view, focusable);
307
308
  if (!focusable) {
308
309
  view.setFocusable(false);
310
+ view.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
311
+ } else {
312
+ view.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
309
313
  }
310
314
  }
311
315
 
@@ -17,8 +17,8 @@ namespace facebook::react {
17
17
  constexpr struct {
18
18
  int32_t Major = 0;
19
19
  int32_t Minor = 73;
20
- int32_t Patch = 4;
21
- std::string_view Prerelease = "0rc1";
20
+ int32_t Patch = 6;
21
+ std::string_view Prerelease = "1";
22
22
  } ReactNativeVersion;
23
23
 
24
24
  } // namespace facebook::react
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-tvos",
3
- "version": "0.73.4-0rc1",
3
+ "version": "0.73.6-1",
4
4
  "description": "A framework for building native apps using React",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -94,16 +94,16 @@
94
94
  },
95
95
  "dependencies": {
96
96
  "@jest/create-cache-key-function": "^29.6.3",
97
- "@react-native-community/cli": "12.3.2",
98
- "@react-native-community/cli-platform-android": "12.3.2",
99
- "@react-native-community/cli-platform-ios": "12.3.2",
97
+ "@react-native-community/cli": "12.3.6",
98
+ "@react-native-community/cli-platform-android": "12.3.6",
99
+ "@react-native-community/cli-platform-ios": "12.3.6",
100
100
  "@react-native/assets-registry": "0.73.1",
101
- "@react-native/community-cli-plugin": "0.73.16",
101
+ "@react-native/community-cli-plugin": "0.73.17",
102
102
  "@react-native/codegen": "0.73.3",
103
103
  "@react-native/gradle-plugin": "0.73.4",
104
104
  "@react-native/js-polyfills": "0.73.1",
105
105
  "@react-native/normalize-colors": "0.73.2",
106
- "@react-native-tvos/virtualized-lists": "0.73.4-0rc1",
106
+ "@react-native-tvos/virtualized-lists": "0.73.6-1",
107
107
  "abort-controller": "^3.0.0",
108
108
  "anser": "^1.4.9",
109
109
  "ansi-regex": "^5.0.0",
@@ -151,6 +151,6 @@
151
151
  ]
152
152
  },
153
153
  "devDependencies": {
154
- "react-native-core": "npm:react-native@0.73.4"
154
+ "react-native-core": "npm:react-native@0.73.6"
155
155
  }
156
156
  }
@@ -104,6 +104,10 @@ class NewArchitectureHelper
104
104
  current_config = hash["pod_target_xcconfig"] != nil ? hash["pod_target_xcconfig"] : {}
105
105
  current_headers = current_config["HEADER_SEARCH_PATHS"] != nil ? current_config["HEADER_SEARCH_PATHS"] : ""
106
106
 
107
+ flags_to_add = new_arch_enabled ?
108
+ "#{@@folly_compiler_flags} -DRCT_NEW_ARCH_ENABLED=1" :
109
+ "#{@@folly_compiler_flags}"
110
+
107
111
  header_search_paths = ["\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/Headers/Private/Yoga\""]
108
112
  if ENV['USE_FRAMEWORKS']
109
113
  header_search_paths << "\"$(PODS_ROOT)/DoubleConversion\""
@@ -123,7 +127,7 @@ class NewArchitectureHelper
123
127
  }
124
128
  end
125
129
  header_search_paths_string = header_search_paths.join(" ")
126
- spec.compiler_flags = compiler_flags.empty? ? @@folly_compiler_flags : "#{compiler_flags} #{@@folly_compiler_flags}"
130
+ spec.compiler_flags = compiler_flags.empty? ? "$(inherited) #{flags_to_add}" : "$(inherited) #{compiler_flags} #{flags_to_add}"
127
131
  current_config["HEADER_SEARCH_PATHS"] = current_headers.empty? ?
128
132
  header_search_paths_string :
129
133
  "#{current_headers} #{header_search_paths_string}"
@@ -86,6 +86,27 @@ class ReactNativePodsUtils
86
86
  end
87
87
  end
88
88
 
89
+ def self.fix_flipper_for_xcode_15_3(installer)
90
+ installer.pods_project.targets.each do |target|
91
+ if target.name == 'Flipper'
92
+ file_path = 'Pods/Flipper/xplat/Flipper/FlipperTransportTypes.h'
93
+ if !File.exist?(file_path)
94
+ return
95
+ end
96
+
97
+ contents = File.read(file_path)
98
+ if contents.include?('#include <functional>')
99
+ return
100
+ end
101
+ mod_content = contents.gsub("#pragma once", "#pragma once\n#include <functional>")
102
+ File.chmod(0755, file_path)
103
+ File.open(file_path, 'w') do |file|
104
+ file.puts(mod_content)
105
+ end
106
+ end
107
+ end
108
+ end
109
+
89
110
  def self.set_use_hermes_build_setting(installer, hermes_enabled)
90
111
  Pod::UI.puts("Setting USE_HERMES build settings")
91
112
  projects = self.extract_projects(installer)
@@ -32,7 +32,13 @@ const REACT_NATIVE_PACKAGE_ROOT_FOLDER = path.join(__dirname, '..', '..');
32
32
 
33
33
  const CODEGEN_DEPENDENCY_NAME = '@react-native/codegen';
34
34
  const CODEGEN_REPO_PATH = `${REACT_NATIVE_REPOSITORY_ROOT}/packages/react-native-codegen`;
35
- const CODEGEN_NPM_PATH = `${REACT_NATIVE_PACKAGE_ROOT_FOLDER}/../${CODEGEN_DEPENDENCY_NAME}`;
35
+ // This is a change for 0.73-stable only since this piece of code was replaced:
36
+ // https://github.com/facebook/react-native/commit/9071a3a0b0e11ad711927651bcb2412f553b6fe9
37
+ const CODEGEN_NPM_PATH = path.dirname(
38
+ require.resolve(path.join(CODEGEN_DEPENDENCY_NAME, 'package.json'), {
39
+ paths: [REACT_NATIVE_PACKAGE_ROOT_FOLDER],
40
+ }),
41
+ );
36
42
  const CORE_LIBRARIES_WITH_OUTPUT_FOLDER = {
37
43
  rncore: path.join(REACT_NATIVE_PACKAGE_ROOT_FOLDER, 'ReactCommon'),
38
44
  FBReactNativeSpec: null,
@@ -189,33 +195,34 @@ function handleThirdPartyLibraries(
189
195
  codegenConfigKey,
190
196
  ) {
191
197
  // Determine which of these are codegen-enabled libraries
192
- const configDir =
193
- baseCodegenConfigFileDir ||
194
- path.join(REACT_NATIVE_PACKAGE_ROOT_FOLDER, '..');
198
+ const configDir = baseCodegenConfigFileDir || process.cwd();
195
199
  console.log(
196
200
  `\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in ${configDir}`,
197
201
  );
198
202
 
199
203
  // Handle third-party libraries
204
+ const resolveOptions = {paths: [configDir]};
200
205
  Object.keys(dependencies).forEach(dependency => {
201
206
  if (dependency === REACT_NATIVE_DEPENDENCY_NAME) {
202
207
  // react-native should already be added.
203
208
  return;
204
209
  }
205
- const codegenConfigFileDir = path.join(configDir, dependency);
206
- const configFilePath = path.join(
207
- codegenConfigFileDir,
208
- codegenConfigFilename,
209
- );
210
- if (fs.existsSync(configFilePath)) {
210
+
211
+ try {
212
+ const configFilePath = require.resolve(
213
+ `${dependency}/${codegenConfigFilename}`,
214
+ resolveOptions,
215
+ );
211
216
  const configFile = JSON.parse(fs.readFileSync(configFilePath));
212
217
  extractLibrariesFromJSON(
213
218
  configFile,
214
219
  libraries,
215
220
  codegenConfigKey,
216
221
  dependency,
217
- codegenConfigFileDir,
222
+ path.dirname(configFilePath),
218
223
  );
224
+ } catch (_) {
225
+ // ignore
219
226
  }
220
227
  });
221
228
  }
@@ -313,6 +313,7 @@ def react_native_post_install(
313
313
  ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: fabric_enabled)
314
314
  ReactNativePodsUtils.apply_xcode_15_patch(installer)
315
315
  ReactNativePodsUtils.updateOSDeploymentTarget(installer)
316
+ ReactNativePodsUtils.fix_flipper_for_xcode_15_3(installer)
316
317
 
317
318
  NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer)
318
319
  NewArchitectureHelper.modify_flags_for_new_architecture(installer, NewArchitectureHelper.new_arch_enabled)
@@ -13,7 +13,7 @@
13
13
  # ./with-environment.sh command
14
14
 
15
15
  # Start with a default
16
- NODE_BINARY=$(command -v node)
16
+ NODE_BINARY=$(command -v node || echo "")
17
17
  export NODE_BINARY
18
18
 
19
19
  # Override the default with the global environment
@@ -1 +1 @@
1
- hermes-2024-01-31-RNv0.73.3-398783c198253f61e0a5eb603f1eb7b55af6baa4
1
+ hermes-2024-03-01-RNv0.73.5-5e3ba8a5ff73efc46f4570492176b0605de77ed6
@@ -7,6 +7,7 @@ require 'net/http'
7
7
  require 'rexml/document'
8
8
 
9
9
  HERMES_GITHUB_URL = "https://github.com/facebook/hermes.git"
10
+ ENV_BUILD_FROM_SOURCE = "RCT_BUILD_HERMES_FROM_SOURCE"
10
11
 
11
12
  module HermesEngineSourceType
12
13
  LOCAL_PREBUILT_TARBALL = :local_prebuilt_tarball
@@ -30,7 +31,7 @@ end
30
31
  # - To use a specific tarball, install the dependencies with:
31
32
  # `HERMES_ENGINE_TARBALL_PATH=<path_to_tarball> bundle exec pod install`
32
33
  # - To force a build from source, install the dependencies with:
33
- # `BUILD_FROM_SOURCE=true bundle exec pod install`
34
+ # `RCT_BUILD_HERMES_FROM_SOURCE=true bundle exec pod install`
34
35
  # If none of the two are provided, Cocoapods will check whether there is a tarball for the current version
35
36
  # (either release or nightly). If not, it will fall back to building from source (the latest commit on main).
36
37
  #
@@ -85,11 +86,11 @@ def hermes_commit_envvar_defined()
85
86
  end
86
87
 
87
88
  def force_build_from_tag(react_native_path)
88
- return ENV['BUILD_FROM_SOURCE'] === 'true' && File.exist?(hermestag_file(react_native_path))
89
+ return ENV[ENV_BUILD_FROM_SOURCE] === 'true' && File.exist?(hermestag_file(react_native_path))
89
90
  end
90
91
 
91
92
  def force_build_from_main(react_native_path)
92
- return ENV['BUILD_FROM_SOURCE'] === 'true' && !File.exist?(hermestag_file(react_native_path))
93
+ return ENV[ENV_BUILD_FROM_SOURCE] === 'true' && !File.exist?(hermestag_file(react_native_path))
93
94
  end
94
95
 
95
96
  def release_artifact_exists(version)
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -13,7 +13,7 @@
13
13
  "dependencies": {
14
14
  "expo": "^50.0.2",
15
15
  "react": "18.2.0",
16
- "react-native": "npm:react-native-tvos@0.73.4-0rc1"
16
+ "react-native": "npm:react-native-tvos@0.73.6-1"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@babel/core": "^7.20.0",