react-native-tvos 0.83.2-0 → 0.83.4-0

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 (64) hide show
  1. package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +1 -0
  2. package/Libraries/Components/ScrollView/ScrollView.d.ts +2 -1
  3. package/Libraries/Components/ScrollView/ScrollView.js +8 -1
  4. package/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +2 -0
  5. package/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js +2 -1
  6. package/Libraries/Components/TV/TVViewPropTypes.js +7 -0
  7. package/Libraries/Components/View/View.js +6 -0
  8. package/Libraries/Core/ReactNativeVersion.js +1 -1
  9. package/Libraries/Core/setUpReactDevTools.js +23 -6
  10. package/Libraries/NativeComponent/TVViewConfig.js +1 -0
  11. package/Libraries/Network/RCTHTTPRequestHandler.h +9 -0
  12. package/Libraries/Network/RCTHTTPRequestHandler.mm +15 -1
  13. package/Libraries/Pressability/Pressability.js +7 -0
  14. package/Libraries/WebSocket/RCTReconnectingWebSocket.m +4 -1
  15. package/React/Base/RCTBundleURLProvider.mm +5 -3
  16. package/React/Base/RCTDevSupportHttpHeaders.h +24 -0
  17. package/React/Base/RCTDevSupportHttpHeaders.m +65 -0
  18. package/React/Base/RCTMultipartDataTask.h +9 -0
  19. package/React/Base/RCTMultipartDataTask.m +16 -1
  20. package/React/Base/RCTVersion.m +1 -1
  21. package/React/CoreModules/RCTWebSocketModule.h +6 -0
  22. package/React/CoreModules/RCTWebSocketModule.mm +14 -1
  23. package/React/DevSupport/RCTInspectorDevServerHelper.mm +33 -22
  24. package/React/DevSupport/RCTInspectorNetworkHelper.mm +2 -0
  25. package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.h +1 -0
  26. package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTEnhancedScrollView.mm +3 -0
  27. package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +110 -4
  28. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +2 -0
  29. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +31 -4
  30. package/React/Inspector/RCTCxxInspectorWebSocketAdapter.mm +5 -1
  31. package/ReactAndroid/api/ReactAndroid.api +1 -0
  32. package/ReactAndroid/gradle.properties +1 -1
  33. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/CxxInspectorPackagerConnection.kt +2 -8
  34. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevServerHelper.kt +17 -13
  35. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/PackagerStatusCheck.kt +10 -19
  36. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/RedBoxContentView.kt +2 -2
  37. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/DevSupportHttpClient.kt +49 -0
  38. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/inspector/InspectorNetworkHelper.kt +1 -12
  39. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
  40. package/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.kt +3 -4
  41. package/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/JSPackagerClient.kt +2 -1
  42. package/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/ReconnectingWebSocket.kt +2 -8
  43. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +49 -5
  44. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.kt +7 -0
  45. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +46 -4
  46. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.kt +69 -0
  47. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.kt +7 -0
  48. package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt +1 -0
  49. package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt +4 -0
  50. package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
  51. package/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.cpp +10 -0
  52. package/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.h +1 -0
  53. package/ReactCommon/react/renderer/components/scrollview/conversions.h +6 -0
  54. package/ReactCommon/react/renderer/components/scrollview/platform/android/react/renderer/components/scrollview/HostPlatformScrollViewProps.cpp +18 -1
  55. package/ReactCommon/react/renderer/components/scrollview/platform/android/react/renderer/components/scrollview/HostPlatformScrollViewProps.h +2 -0
  56. package/ReactCommon/react/renderer/components/scrollview/primitives.h +1 -1
  57. package/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +11 -1
  58. package/ReactCommon/react/renderer/components/view/BaseViewProps.h +4 -0
  59. package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +18 -0
  60. package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h +1 -0
  61. package/package.json +8 -8
  62. package/scripts/replace-rncore-version.js +62 -8
  63. package/settings.gradle.kts +21 -1
  64. package/types/public/ReactNativeTVTypes.d.ts +19 -2
@@ -58,6 +58,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = {
58
58
  borderLeftColor: {
59
59
  process: require('../../StyleSheet/processColor').default,
60
60
  },
61
+ snapToItemPadding: true,
61
62
  pointerEvents: true,
62
63
  },
63
64
  };
@@ -515,8 +515,9 @@ export interface ScrollViewPropsIOS {
515
515
  * - `start` (the default) will align the snap at the left (horizontal) or top (vertical)
516
516
  * - `center` will align the snap in the center
517
517
  * - `end` will align the snap at the right (horizontal) or bottom (vertical)
518
+ * - `item` will align the snap according to the value of `scrollSnapAlign` for individual items in the scroll view (TV platforms only).
518
519
  */
519
- snapToAlignment?: 'start' | 'center' | 'end' | undefined;
520
+ snapToAlignment?: 'start' | 'center' | 'end' | 'item' | undefined;
520
521
 
521
522
  /**
522
523
  * Fires when the scroll view scrolls to top after the status bar has been tapped
@@ -612,8 +612,15 @@ type ScrollViewBaseProps = $ReadOnly<{
612
612
  * - `'start'` (the default) will align the snap at the left (horizontal) or top (vertical)
613
613
  * - `'center'` will align the snap in the center
614
614
  * - `'end'` will align the snap at the right (horizontal) or bottom (vertical)
615
+ * - `'item'` will align the snap according to the value of `scrollSnapAlign` for individual items in the scroll view (TV platforms only).
615
616
  */
616
- snapToAlignment?: ?('start' | 'center' | 'end'),
617
+ snapToAlignment?: ?('start' | 'center' | 'end' | 'item'),
618
+ /**
619
+ * Padding applied when snapping to items using `snapToAlignment="item"`.
620
+ * This is set on the parent scroll view, not directly on child items.
621
+ * Only used when `snapToAlignment` is set to `'item'`.
622
+ */
623
+ snapToItemPadding?: ?number,
617
624
  /**
618
625
  * When set, causes the scroll view to stop at multiples of the value of
619
626
  * `snapToInterval`. This can be used for paginating through children
@@ -86,6 +86,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
86
86
  borderLeftColor: {
87
87
  process: require('../../StyleSheet/processColor').default,
88
88
  },
89
+ snapToItemPadding: true,
89
90
  pointerEvents: true,
90
91
  isInvertedVirtualizedList: true,
91
92
  },
@@ -152,6 +153,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
152
153
  showsHorizontalScrollIndicator: true,
153
154
  showsVerticalScrollIndicator: true,
154
155
  showsScrollIndex: true,
156
+ snapToItemPadding: true,
155
157
  snapToAlignment: true,
156
158
  snapToEnd: true,
157
159
  snapToInterval: true,
@@ -69,11 +69,12 @@ export type ScrollViewNativeProps = $ReadOnly<{
69
69
  scrollPerfTag?: ?string,
70
70
  scrollToOverflowEnabled?: ?boolean,
71
71
  scrollsToTop?: ?boolean,
72
+ snapToItemPadding?: ?number,
72
73
  sendMomentumEvents?: ?boolean,
73
74
  showsHorizontalScrollIndicator?: ?boolean,
74
75
  showsScrollIndex?: ?boolean,
75
76
  showsVerticalScrollIndicator?: ?boolean,
76
- snapToAlignment?: ?('start' | 'center' | 'end'),
77
+ snapToAlignment?: ?('start' | 'center' | 'end' | 'item'),
77
78
  snapToEnd?: ?boolean,
78
79
  snapToInterval?: ?number,
79
80
  snapToOffsets?: ?$ReadOnlyArray<number>,
@@ -124,4 +124,11 @@ export type TVViewProps = $ReadOnly<{|
124
124
  *
125
125
  */
126
126
  nextFocusUp?: ?number,
127
+
128
+ /**
129
+ * Scroll snap alignment (used with snapToAlignment="item" in ScrollView).
130
+ *
131
+ */
132
+ scrollSnapAlign?: ?('start' | 'center' | 'end'),
133
+
127
134
  |}>;
@@ -153,6 +153,12 @@ component View(
153
153
  delete processedProps.isTVSelectable;
154
154
  }
155
155
 
156
+ // Views with scrollSnapAlign must not be flattened by Fabric, otherwise
157
+ // the prop never reaches the native view and scroll snapping breaks.
158
+ if (processedProps.scrollSnapAlign != null) {
159
+ processedProps.collapsable = false;
160
+ }
161
+
156
162
  const actualView =
157
163
  ref == null ? (
158
164
  <ViewNativeComponent {...processedProps} />
@@ -28,7 +28,7 @@
28
28
  export default class ReactNativeVersion {
29
29
  static major: number = 0;
30
30
  static minor: number = 83;
31
- static patch: number = 2;
31
+ static patch: number = 4;
32
32
  static prerelease: string | null = '0';
33
33
 
34
34
  static getVersionString(): string {
@@ -146,17 +146,34 @@ if (__DEV__) {
146
146
  ? guessHostFromDevServerUrl(devServer.url)
147
147
  : 'localhost';
148
148
 
149
- // Read the optional global variable for backward compatibility.
150
- // It was added in https://github.com/facebook/react-native/commit/bf2b435322e89d0aeee8792b1c6e04656c2719a0.
151
- const port =
149
+ // Derive scheme and port from the dev server URL when possible,
150
+ // falling back to ws://host:8097 for local development.
151
+ let wsScheme = 'ws';
152
+ let port = 8097;
153
+
154
+ if (
152
155
  // $FlowFixMe[prop-missing]
153
156
  // $FlowFixMe[incompatible-use]
154
157
  window.__REACT_DEVTOOLS_PORT__ != null
155
- ? window.__REACT_DEVTOOLS_PORT__
156
- : 8097;
158
+ ) {
159
+ // $FlowFixMe[prop-missing]
160
+ port = window.__REACT_DEVTOOLS_PORT__;
161
+ } else if (devServer.bundleLoadedFromServer) {
162
+ try {
163
+ const devUrl = new URL(devServer.url);
164
+ if (devUrl.protocol === 'https:') {
165
+ wsScheme = 'wss';
166
+ }
167
+ if (devUrl.port) {
168
+ port = parseInt(devUrl.port, 10);
169
+ } else if (devUrl.protocol === 'https:') {
170
+ port = 443;
171
+ }
172
+ } catch (e) {}
173
+ }
157
174
 
158
175
  const WebSocket = require('../WebSocket/WebSocket').default;
159
- ws = new WebSocket('ws://' + host + ':' + port);
176
+ ws = new WebSocket(wsScheme + '://' + host + ':' + port);
160
177
  ws.addEventListener('close', event => {
161
178
  isWebSocketOpen = false;
162
179
  });
@@ -25,5 +25,6 @@ export const validAttributesForTVProps = {
25
25
  trapFocusRight: true,
26
26
  trapFocusDown: true,
27
27
  trapFocusUp: true,
28
+ scrollSnapAlign: true,
28
29
  };
29
30
 
@@ -14,6 +14,15 @@ typedef NSURLSessionConfiguration * (^NSURLSessionConfigurationProvider)(void);
14
14
  * app.
15
15
  */
16
16
  RCT_EXTERN void RCTSetCustomNSURLSessionConfigurationProvider(NSURLSessionConfigurationProvider /*provider*/);
17
+
18
+ typedef NSURLRequest *_Nullable (^RCTHTTPRequestInterceptor)(NSURLRequest *request);
19
+ /**
20
+ * The block provided via this function can inspect/modify HTTP requests before
21
+ * they are sent. Return a modified request to override, or nil to use the
22
+ * original request unchanged.
23
+ */
24
+ RCT_EXTERN void RCTSetCustomHTTPRequestInterceptor(RCTHTTPRequestInterceptor /*interceptor*/);
25
+
17
26
  /**
18
27
  * This is the default RCTURLRequestHandler implementation for HTTP requests.
19
28
  */
@@ -25,6 +25,13 @@ void RCTSetCustomNSURLSessionConfigurationProvider(NSURLSessionConfigurationProv
25
25
  urlSessionConfigurationProvider = provider;
26
26
  }
27
27
 
28
+ static RCTHTTPRequestInterceptor httpRequestInterceptor;
29
+
30
+ void RCTSetCustomHTTPRequestInterceptor(RCTHTTPRequestInterceptor interceptor)
31
+ {
32
+ httpRequestInterceptor = interceptor;
33
+ }
34
+
28
35
  @implementation RCTHTTPRequestHandler {
29
36
  NSMapTable *_delegates;
30
37
  NSURLSession *_session;
@@ -99,7 +106,14 @@ RCT_EXPORT_MODULE()
99
106
  valueOptions:NSPointerFunctionsStrongMemory
100
107
  capacity:0];
101
108
  }
102
- NSURLSessionDataTask *task = [_session dataTaskWithRequest:request];
109
+ NSURLRequest *finalRequest = request;
110
+ if (httpRequestInterceptor != nullptr) {
111
+ NSURLRequest *intercepted = httpRequestInterceptor(request);
112
+ if (intercepted != nil) {
113
+ finalRequest = intercepted;
114
+ }
115
+ }
116
+ NSURLSessionDataTask *task = [_session dataTaskWithRequest:finalRequest];
103
117
  [_delegates setObject:delegate forKey:task];
104
118
  [task resume];
105
119
  return task;
@@ -398,6 +398,7 @@ export default class Pressability {
398
398
  _touchActivateTime: ?number;
399
399
  _touchState: TouchState = 'NOT_RESPONDER';
400
400
  _longPressSent: boolean = false;
401
+ _tvPressInReceived: boolean = false;
401
402
 
402
403
  constructor(config: PressabilityConfig) {
403
404
  this.configure(config);
@@ -416,6 +417,7 @@ export default class Pressability {
416
417
  this._cancelLongPressDelayTimeout();
417
418
  this._cancelPressDelayTimeout();
418
419
  this._cancelPressOutDelayTimeout();
420
+ this._tvPressInReceived = false;
419
421
 
420
422
  // Ensure that, if any async event handlers are fired after unmount
421
423
  // due to a race, we don't call any configured callbacks.
@@ -443,6 +445,7 @@ export default class Pressability {
443
445
  return;
444
446
  }
445
447
 
448
+ this._tvPressInReceived = true;
446
449
  this._longPressSent = false;
447
450
 
448
451
  const {onPressIn, onLongPress} = this._config;
@@ -463,6 +466,10 @@ export default class Pressability {
463
466
  if (this._config.disabled === true) {
464
467
  return;
465
468
  }
469
+ if (!this._tvPressInReceived) {
470
+ return;
471
+ }
472
+ this._tvPressInReceived = false;
466
473
  this._cancelLongPressDelayTimeout();
467
474
  const {onPress, onLongPress, onPressOut, android_disableSound} =
468
475
  this._config;
@@ -9,6 +9,7 @@
9
9
 
10
10
  #import <React/RCTConvert.h>
11
11
  #import <React/RCTDefines.h>
12
+ #import <React/RCTDevSupportHttpHeaders.h>
12
13
 
13
14
  #import <SocketRocket/SRWebSocket.h>
14
15
 
@@ -46,7 +47,9 @@
46
47
  {
47
48
  [self stop];
48
49
  _stopped = NO;
49
- _socket = [[SRWebSocket alloc] initWithURL:_url];
50
+ NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:_url];
51
+ [[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:request];
52
+ _socket = [[SRWebSocket alloc] initWithURLRequest:request];
50
53
  _socket.delegate = self;
51
54
  [_socket setDelegateDispatchQueue:_delegateDispatchQueue];
52
55
  [_socket open];
@@ -10,6 +10,7 @@
10
10
  #import "RCTConstants.h"
11
11
  #import "RCTConvert.h"
12
12
  #import "RCTDefines.h"
13
+ #import "RCTDevSupportHttpHeaders.h"
13
14
  #import "RCTLog.h"
14
15
 
15
16
  #import <jsinspector-modern/InspectorFlags.h>
@@ -93,9 +94,10 @@ static NSURL *serverRootWithHostPort(NSString *hostPort, NSString *scheme)
93
94
  NSURL *url = [serverRootWithHostPort(hostPort, scheme) URLByAppendingPathComponent:@"status"];
94
95
 
95
96
  NSURLSession *session = [NSURLSession sharedSession];
96
- NSURLRequest *request = [NSURLRequest requestWithURL:url
97
- cachePolicy:NSURLRequestUseProtocolCachePolicy
98
- timeoutInterval:10];
97
+ NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
98
+ cachePolicy:NSURLRequestUseProtocolCachePolicy
99
+ timeoutInterval:10];
100
+ [[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:request];
99
101
  __block NSURLResponse *response;
100
102
  __block NSData *data;
101
103
 
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #import <Foundation/Foundation.h>
9
+
10
+ /**
11
+ * Thread-safe singleton that holds custom HTTP headers to be applied
12
+ * to all devsupport network requests (bundle fetches, packager status
13
+ * checks, inspector and HMR WebSocket connections).
14
+ */
15
+ @interface RCTDevSupportHttpHeaders : NSObject
16
+
17
+ + (instancetype)sharedInstance;
18
+
19
+ - (void)addRequestHeader:(NSString *)name value:(NSString *)value;
20
+ - (void)removeRequestHeader:(NSString *)name;
21
+ - (NSDictionary<NSString *, NSString *> *)allHeaders;
22
+ - (void)applyHeadersToRequest:(NSMutableURLRequest *)request;
23
+
24
+ @end
@@ -0,0 +1,65 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #import "RCTDevSupportHttpHeaders.h"
9
+
10
+ @implementation RCTDevSupportHttpHeaders {
11
+ NSMutableDictionary<NSString *, NSString *> *_headers;
12
+ dispatch_queue_t _queue;
13
+ }
14
+
15
+ + (instancetype)sharedInstance
16
+ {
17
+ static RCTDevSupportHttpHeaders *sharedInstance;
18
+ static dispatch_once_t onceToken;
19
+ dispatch_once(&onceToken, ^{
20
+ sharedInstance = [[RCTDevSupportHttpHeaders alloc] init];
21
+ });
22
+ return sharedInstance;
23
+ }
24
+
25
+ - (instancetype)init
26
+ {
27
+ if (self = [super init]) {
28
+ _headers = [NSMutableDictionary new];
29
+ _queue = dispatch_queue_create("com.facebook.react.RCTDevSupportHttpHeaders", DISPATCH_QUEUE_SERIAL);
30
+ }
31
+ return self;
32
+ }
33
+
34
+ - (void)addRequestHeader:(NSString *)name value:(NSString *)value
35
+ {
36
+ dispatch_sync(_queue, ^{
37
+ self->_headers[name] = value;
38
+ });
39
+ }
40
+
41
+ - (void)removeRequestHeader:(NSString *)name
42
+ {
43
+ dispatch_sync(_queue, ^{
44
+ [self->_headers removeObjectForKey:name];
45
+ });
46
+ }
47
+
48
+ - (NSDictionary<NSString *, NSString *> *)allHeaders
49
+ {
50
+ __block NSDictionary<NSString *, NSString *> *snapshot;
51
+ dispatch_sync(_queue, ^{
52
+ snapshot = [self->_headers copy];
53
+ });
54
+ return snapshot;
55
+ }
56
+
57
+ - (void)applyHeadersToRequest:(NSMutableURLRequest *)request
58
+ {
59
+ NSDictionary<NSString *, NSString *> *headers = [self allHeaders];
60
+ [headers enumerateKeysAndObjectsUsingBlock:^(NSString *headerName, NSString *headerValue, BOOL *stop) {
61
+ [request setValue:headerValue forHTTPHeaderField:headerName];
62
+ }];
63
+ }
64
+
65
+ @end
@@ -7,6 +7,7 @@
7
7
 
8
8
  #import <Foundation/Foundation.h>
9
9
 
10
+ #import <React/RCTDefines.h>
10
11
  #import <React/RCTMultipartStreamReader.h>
11
12
 
12
13
  typedef void (^RCTMultipartDataTaskCallback)(
@@ -16,6 +17,14 @@ typedef void (^RCTMultipartDataTaskCallback)(
16
17
  NSError *error,
17
18
  BOOL done);
18
19
 
20
+ typedef NSURLRequest * _Nullable (^RCTMultipartDataTaskRequestInterceptor)(NSURLRequest *request);
21
+ /**
22
+ * The block provided via this function can inspect/modify multipart data task
23
+ * requests before they are sent. Return a modified request to override, or nil
24
+ * to use the original request unchanged.
25
+ */
26
+ RCT_EXTERN void RCTSetCustomMultipartDataTaskRequestInterceptor(RCTMultipartDataTaskRequestInterceptor /*interceptor*/);
27
+
19
28
  @interface RCTMultipartDataTask : NSObject
20
29
 
21
30
  - (instancetype)initWithURL:(NSURL *)url
@@ -7,6 +7,13 @@
7
7
 
8
8
  #import "RCTMultipartDataTask.h"
9
9
 
10
+ static RCTMultipartDataTaskRequestInterceptor multipartRequestInterceptor;
11
+
12
+ void RCTSetCustomMultipartDataTaskRequestInterceptor(RCTMultipartDataTaskRequestInterceptor interceptor)
13
+ {
14
+ multipartRequestInterceptor = interceptor;
15
+ }
16
+
10
17
  @interface RCTMultipartDataTask () <NSURLSessionDataDelegate, NSURLSessionDataDelegate>
11
18
 
12
19
  @end
@@ -40,7 +47,15 @@
40
47
  delegateQueue:nil];
41
48
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:_url];
42
49
  [request addValue:@"multipart/mixed" forHTTPHeaderField:@"Accept"];
43
- NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
50
+ NSURLRequest *finalRequest = request;
51
+ if (multipartRequestInterceptor != nil) {
52
+ NSURLRequest *intercepted = multipartRequestInterceptor(request);
53
+ if (intercepted != nil) {
54
+ finalRequest = intercepted;
55
+ }
56
+ }
57
+ NSLog(@"[RCTMultipartDataTask] %@ %@", finalRequest.HTTPMethod ?: @"GET", finalRequest.URL.absoluteString);
58
+ NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:finalRequest];
44
59
  [dataTask resume];
45
60
  [session finishTasksAndInvalidate];
46
61
  }
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
23
23
  __rnVersion = @{
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(83),
26
- RCTVersionPatch: @(2),
26
+ RCTVersionPatch: @(4),
27
27
  RCTVersionPrerelease: @"0",
28
28
  };
29
29
  });
@@ -18,6 +18,12 @@ NS_ASSUME_NONNULL_BEGIN
18
18
 
19
19
  @end
20
20
 
21
+ @class SRWebSocket;
22
+
23
+ typedef SRWebSocket * (^SRWebSocketProvider)(NSURLRequest *request);
24
+
25
+ RCT_EXTERN void RCTSetCustomSRWebSocketProvider(SRWebSocketProvider provider);
26
+
21
27
  @interface RCTWebSocketModule : RCTEventEmitter
22
28
 
23
29
  // Register a custom handler for a specific websocket. The handler will be strongly held by the WebSocketModule.
@@ -34,6 +34,13 @@
34
34
 
35
35
  @end
36
36
 
37
+ static SRWebSocketProvider srWebSocketProvider;
38
+
39
+ void RCTSetCustomSRWebSocketProvider(SRWebSocketProvider provider)
40
+ {
41
+ srWebSocketProvider = provider;
42
+ }
43
+
37
44
  @implementation RCTWebSocketModule {
38
45
  NSMutableDictionary<NSNumber *, SRWebSocket *> *_sockets;
39
46
  NSMutableDictionary<NSNumber *, id<RCTWebSocketContentHandler>> *_contentHandlers;
@@ -88,7 +95,13 @@ RCT_EXPORT_METHOD(
88
95
  }];
89
96
  }
90
97
 
91
- SRWebSocket *webSocket = [[SRWebSocket alloc] initWithURLRequest:request protocols:protocols];
98
+ SRWebSocket *webSocket;
99
+ if (srWebSocketProvider != nullptr) {
100
+ webSocket = srWebSocketProvider(request);
101
+ }
102
+ if (webSocket == nil) {
103
+ webSocket = [[SRWebSocket alloc] initWithURLRequest:request protocols:protocols];
104
+ }
92
105
  [webSocket setDelegateDispatchQueue:[self methodQueue]];
93
106
  webSocket.delegate = self;
94
107
  webSocket.reactTag = @(socketID);
@@ -14,33 +14,39 @@
14
14
 
15
15
  #import <React/RCTCxxInspectorPackagerConnection.h>
16
16
  #import <React/RCTDefines.h>
17
+ #import <React/RCTDevSupportHttpHeaders.h>
17
18
 
18
19
  #import <CommonCrypto/CommonCrypto.h>
19
20
  #import <jsinspector-modern/InspectorFlags.h>
20
21
 
21
22
  static NSString *const kDebuggerMsgDisable = @"{ \"id\":1,\"method\":\"Debugger.disable\" }";
23
+ static const int kDefaultMetroPort = 8081;
22
24
 
23
25
  static NSString *getServerHost(NSURL *bundleURL)
24
26
  {
25
- NSNumber *port = @8081;
26
- NSString *portStr = [[[NSProcessInfo processInfo] environment] objectForKey:@"RCT_METRO_PORT"];
27
- if ((portStr != nullptr) && [portStr length] > 0) {
28
- port = [NSNumber numberWithInt:[portStr intValue]];
29
- }
30
- if ([bundleURL port] != nullptr) {
31
- port = [bundleURL port];
32
- }
33
27
  NSString *host = [bundleURL host];
34
28
  if (host == nullptr) {
35
29
  host = @"localhost";
36
30
  }
37
31
 
38
- // this is consistent with the Android implementation, where http:// is the
39
- // hardcoded implicit scheme for the debug server. Note, packagerURL
40
- // technically looks like it could handle schemes/protocols other than HTTP,
41
- // so rather than force HTTP, leave it be for now, in case someone is relying
42
- // on that ability when developing against iOS.
43
- return [NSString stringWithFormat:@"%@:%@", host, port];
32
+ // Use explicit port from URL if available
33
+ if ([bundleURL port] != nullptr) {
34
+ return [NSString stringWithFormat:@"%@:%@", host, [bundleURL port]];
35
+ }
36
+
37
+ // Check environment variable
38
+ NSString *portStr = [[[NSProcessInfo processInfo] environment] objectForKey:@"RCT_METRO_PORT"];
39
+ if ((portStr != nullptr) && [portStr length] > 0) {
40
+ return [NSString stringWithFormat:@"%@:%@", host, portStr];
41
+ }
42
+
43
+ // For https, omit port — the scheme implies 443
44
+ if ([[bundleURL scheme] isEqualToString:@"https"]) {
45
+ return host;
46
+ }
47
+
48
+ // Default to 8081 for local development (Metro's default port)
49
+ return [NSString stringWithFormat:@"%@:%d", host, kDefaultMetroPort];
44
50
  }
45
51
 
46
52
  static NSString *getSHA256(NSString *string)
@@ -111,13 +117,15 @@ static NSURL *getInspectorDeviceUrl(NSURL *bundleURL)
111
117
  NSString *escapedInspectorDeviceId = [getInspectorDeviceId()
112
118
  stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
113
119
 
114
- return [NSURL
115
- URLWithString:[NSString stringWithFormat:@"http://%@/inspector/device?name=%@&app=%@&device=%@&profiling=%@",
116
- getServerHost(bundleURL),
117
- escapedDeviceName,
118
- escapedAppName,
119
- escapedInspectorDeviceId,
120
- isProfilingBuild ? @"true" : @"false"]];
120
+ NSString *scheme = [bundleURL scheme] != nullptr ? [bundleURL scheme] : @"http";
121
+ return
122
+ [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/inspector/device?name=%@&app=%@&device=%@&profiling=%@",
123
+ scheme,
124
+ getServerHost(bundleURL),
125
+ escapedDeviceName,
126
+ escapedAppName,
127
+ escapedInspectorDeviceId,
128
+ isProfilingBuild ? @"true" : @"false"]];
121
129
  }
122
130
 
123
131
  @implementation RCTInspectorDevServerHelper
@@ -149,11 +157,14 @@ static void sendEventToAllConnections(NSString *event)
149
157
  NSString *escapedInspectorDeviceId = [getInspectorDeviceId()
150
158
  stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
151
159
 
152
- NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/open-debugger?device=%@",
160
+ NSString *scheme = [bundleURL scheme] != nullptr ? [bundleURL scheme] : @"http";
161
+ NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/open-debugger?device=%@",
162
+ scheme,
153
163
  getServerHost(bundleURL),
154
164
  escapedInspectorDeviceId]];
155
165
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
156
166
  [request setHTTPMethod:@"POST"];
167
+ [[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:request];
157
168
 
158
169
  [[[NSURLSession sharedSession]
159
170
  dataTaskWithRequest:request
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  #import "RCTInspectorNetworkHelper.h"
9
+ #import <React/RCTDevSupportHttpHeaders.h>
9
10
  #import <React/RCTLog.h>
10
11
 
11
12
  using ListenerBlock = void (^)(RCTInspectorNetworkListener *);
@@ -47,6 +48,7 @@ using ListenerBlock = void (^)(RCTInspectorNetworkListener *);
47
48
 
48
49
  NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
49
50
  [urlRequest setHTTPMethod:@"GET"];
51
+ [[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:urlRequest];
50
52
  NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:urlRequest];
51
53
  __weak NSURLSessionDataTask *weakDataTask = dataTask;
52
54
 
@@ -51,6 +51,7 @@ NS_ASSUME_NONNULL_BEGIN
51
51
  @property (nonatomic, assign) BOOL snapToStart;
52
52
  @property (nonatomic, assign) BOOL snapToEnd;
53
53
  @property (nonatomic, copy) NSArray<NSNumber *> *snapToOffsets;
54
+ @property (nonatomic, assign) BOOL scrollSnapEnabled;
54
55
 
55
56
  /*
56
57
  * Makes `setContentOffset:` method no-op when given `block` is executed.
@@ -132,6 +132,9 @@
132
132
 
133
133
  - (id<UIScrollViewDelegate>)delegate
134
134
  {
135
+ if (_scrollSnapEnabled) {
136
+ return [super delegate];
137
+ }
135
138
  return _publicDelegate;
136
139
  }
137
140