react-native-tvos 0.74.0-0rc2 → 0.74.0-0rc3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/React-Native +214 -0
- package/Libraries/ReactNative/AppContainer-dev.js +6 -1
- package/React/Base/RCTVersion.m +1 -1
- package/React/CoreModules/RCTDevMenu.mm +1 -1
- package/React/CoreModules/RCTDevSettings.mm +9 -4
- package/React/CoreModules/RCTTVNavigationEventEmitter.mm +4 -0
- package/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.h +4 -0
- package/React/Fabric/Mounting/ComponentViews/Modal/RCTFabricModalHostViewController.mm +16 -6
- package/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +45 -0
- package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +2 -2
- package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +2 -0
- package/React/Views/RCTModalHostViewController.m +26 -0
- package/React/Views/ScrollView/RCTScrollView.m +1 -1
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt +4 -4
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/package.json +9 -9
- package/scripts/cocoapods/utils.rb +56 -3
- package/scripts/react_native_pods.rb +1 -0
- package/sdks/.hermesversion +1 -1
- package/sdks/hermesc/osx-bin/hermes +0 -0
- package/sdks/hermesc/osx-bin/hermesc +0 -0
- package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
- package/template/package.json +5 -5
|
@@ -0,0 +1,214 @@
|
|
|
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
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
* @oncall react_native
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type {
|
|
13
|
+
ReactDevToolsAgent,
|
|
14
|
+
ReactDevToolsGlobalHook,
|
|
15
|
+
} from '../Types/ReactDevToolsTypes';
|
|
16
|
+
import type {Props} from './AppContainer';
|
|
17
|
+
|
|
18
|
+
import ReactNativeStyleAttributes from '../Components/View/ReactNativeStyleAttributes';
|
|
19
|
+
import View from '../Components/View/View';
|
|
20
|
+
import Platform from '../Utilities/Platform';
|
|
21
|
+
// import DebuggingOverlay from '../Debugging/DebuggingOverlay';
|
|
22
|
+
// import useSubscribeToDebuggingOverlayRegistry from '../Debugging/useSubscribeToDebuggingOverlayRegistry';
|
|
23
|
+
import RCTDeviceEventEmitter from '../EventEmitter/RCTDeviceEventEmitter';
|
|
24
|
+
import LogBoxNotificationContainer from '../LogBox/LogBoxNotificationContainer';
|
|
25
|
+
import StyleSheet from '../StyleSheet/StyleSheet';
|
|
26
|
+
import {RootTagContext, createRootTag} from './RootTag';
|
|
27
|
+
import * as React from 'react';
|
|
28
|
+
|
|
29
|
+
const {useEffect, useState, useCallback} = React;
|
|
30
|
+
|
|
31
|
+
const reactDevToolsHook: ReactDevToolsGlobalHook =
|
|
32
|
+
window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
33
|
+
|
|
34
|
+
// Required for React DevTools to view / edit React Native styles in Flipper.
|
|
35
|
+
// Flipper doesn't inject these values when initializing DevTools.
|
|
36
|
+
if (reactDevToolsHook) {
|
|
37
|
+
reactDevToolsHook.resolveRNStyle = require('../StyleSheet/flattenStyle');
|
|
38
|
+
reactDevToolsHook.nativeStyleEditorValidAttributes = Object.keys(
|
|
39
|
+
ReactNativeStyleAttributes,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type InspectorDeferredProps = {
|
|
44
|
+
inspectedViewRef: InspectedViewRef,
|
|
45
|
+
onInspectedViewRerenderRequest: () => void,
|
|
46
|
+
reactDevToolsAgent?: ReactDevToolsAgent,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const InspectorDeferred = ({
|
|
50
|
+
inspectedViewRef,
|
|
51
|
+
onInspectedViewRerenderRequest,
|
|
52
|
+
reactDevToolsAgent,
|
|
53
|
+
}: InspectorDeferredProps) => {
|
|
54
|
+
// D39382967 adds a require cycle: InitializeCore -> AppContainer -> Inspector -> InspectorPanel -> ScrollView -> InitializeCore
|
|
55
|
+
// We can't remove it yet, fallback to dynamic require for now. This is the only reason why this logic is in a separate function.
|
|
56
|
+
const Inspector = require('../Inspector/Inspector');
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<Inspector
|
|
60
|
+
inspectedViewRef={inspectedViewRef}
|
|
61
|
+
onRequestRerenderApp={onInspectedViewRerenderRequest}
|
|
62
|
+
reactDevToolsAgent={reactDevToolsAgent}
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
type ReactDevToolsOverlayDeferredProps = {
|
|
68
|
+
inspectedViewRef: InspectedViewRef,
|
|
69
|
+
reactDevToolsAgent: ReactDevToolsAgent,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const ReactDevToolsOverlayDeferred = ({
|
|
73
|
+
inspectedViewRef,
|
|
74
|
+
reactDevToolsAgent,
|
|
75
|
+
}: ReactDevToolsOverlayDeferredProps) => {
|
|
76
|
+
const ReactDevToolsOverlay =
|
|
77
|
+
require('../Inspector/ReactDevToolsOverlay').default;
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<ReactDevToolsOverlay
|
|
81
|
+
inspectedViewRef={inspectedViewRef}
|
|
82
|
+
reactDevToolsAgent={reactDevToolsAgent}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const AppContainer = ({
|
|
88
|
+
children,
|
|
89
|
+
fabric,
|
|
90
|
+
initialProps,
|
|
91
|
+
internal_excludeInspector = false,
|
|
92
|
+
internal_excludeLogBox = false,
|
|
93
|
+
rootTag,
|
|
94
|
+
showArchitectureIndicator,
|
|
95
|
+
WrapperComponent,
|
|
96
|
+
}: Props): React.Node => {
|
|
97
|
+
const appContainerRootViewRef: AppContainerRootViewRef = React.useRef(null);
|
|
98
|
+
const innerViewRef: InspectedViewRef = React.useRef(null);
|
|
99
|
+
const debuggingOverlayRef: DebuggingOverlayRef = React.useRef(null);
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
useSubscribeToDebuggingOverlayRegistry(
|
|
103
|
+
appContainerRootViewRef,
|
|
104
|
+
debuggingOverlayRef,
|
|
105
|
+
);
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
const [key, setKey] = useState(0);
|
|
109
|
+
const [shouldRenderInspector, setShouldRenderInspector] = useState(false);
|
|
110
|
+
const [reactDevToolsAgent, setReactDevToolsAgent] =
|
|
111
|
+
useState<ReactDevToolsAgent | void>(reactDevToolsHook?.reactDevtoolsAgent);
|
|
112
|
+
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
let inspectorSubscription = null;
|
|
115
|
+
if (!internal_excludeInspector) {
|
|
116
|
+
inspectorSubscription = RCTDeviceEventEmitter.addListener(
|
|
117
|
+
'toggleElementInspector',
|
|
118
|
+
() => setShouldRenderInspector(value => !value),
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let reactDevToolsAgentListener = null;
|
|
123
|
+
// If this is first render, subscribe to the event from React DevTools hook
|
|
124
|
+
if (reactDevToolsHook != null && reactDevToolsAgent == null) {
|
|
125
|
+
reactDevToolsAgentListener = setReactDevToolsAgent;
|
|
126
|
+
reactDevToolsHook.on?.('react-devtools', reactDevToolsAgentListener);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return () => {
|
|
130
|
+
inspectorSubscription?.remove();
|
|
131
|
+
|
|
132
|
+
if (
|
|
133
|
+
reactDevToolsHook?.off != null &&
|
|
134
|
+
reactDevToolsAgentListener != null
|
|
135
|
+
) {
|
|
136
|
+
reactDevToolsHook.off('react-devtools', reactDevToolsAgentListener);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
140
|
+
}, []);
|
|
141
|
+
|
|
142
|
+
let innerView: React.Node = (
|
|
143
|
+
<View
|
|
144
|
+
collapsable={reactDevToolsAgent == null && !shouldRenderInspector}
|
|
145
|
+
pointerEvents="box-none"
|
|
146
|
+
key={key}
|
|
147
|
+
style={styles.container}
|
|
148
|
+
ref={innerViewRef}>
|
|
149
|
+
{children}
|
|
150
|
+
</View>
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
if (WrapperComponent != null) {
|
|
154
|
+
innerView = (
|
|
155
|
+
<WrapperComponent
|
|
156
|
+
initialProps={initialProps}
|
|
157
|
+
fabric={fabric === true}
|
|
158
|
+
showArchitectureIndicator={showArchitectureIndicator === true}>
|
|
159
|
+
{innerView}
|
|
160
|
+
</WrapperComponent>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const onInspectedViewRerenderRequest = useCallback(
|
|
165
|
+
() => setKey(k => k + 1),
|
|
166
|
+
[],
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<RootTagContext.Provider value={createRootTag(rootTag)}>
|
|
171
|
+
<View
|
|
172
|
+
ref={appContainerRootViewRef}
|
|
173
|
+
style={styles.container}
|
|
174
|
+
pointerEvents="box-none">
|
|
175
|
+
{innerView}
|
|
176
|
+
|
|
177
|
+
{/* <DebuggingOverlay ref={debuggingOverlayRef} /> */}
|
|
178
|
+
|
|
179
|
+
{reactDevToolsAgent != null && (
|
|
180
|
+
<ReactDevToolsOverlayDeferred
|
|
181
|
+
inspectedViewRef={innerViewRef}
|
|
182
|
+
reactDevToolsAgent={reactDevToolsAgent}
|
|
183
|
+
/>
|
|
184
|
+
)}
|
|
185
|
+
|
|
186
|
+
{shouldRenderInspector && (
|
|
187
|
+
<InspectorDeferred
|
|
188
|
+
inspectedViewRef={innerViewRef}
|
|
189
|
+
onInspectedViewRerenderRequest={onInspectedViewRerenderRequest}
|
|
190
|
+
reactDevToolsAgent={reactDevToolsAgent}
|
|
191
|
+
/>
|
|
192
|
+
)}
|
|
193
|
+
|
|
194
|
+
{!internal_excludeLogBox && <LogBoxNotificationContainer />}
|
|
195
|
+
</View>
|
|
196
|
+
</RootTagContext.Provider>
|
|
197
|
+
);
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const styles = StyleSheet.create({
|
|
201
|
+
container: {flex: 1},
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
export type AppContainerRootViewRef = React.RefObject<React.ElementRef<
|
|
205
|
+
typeof View,
|
|
206
|
+
> | null>;
|
|
207
|
+
export type InspectedViewRef = React.RefObject<React.ElementRef<
|
|
208
|
+
typeof View,
|
|
209
|
+
> | null>;
|
|
210
|
+
export type DebuggingOverlayRef = React.RefObject<React.ElementRef<
|
|
211
|
+
typeof DebuggingOverlay,
|
|
212
|
+
> | null>;
|
|
213
|
+
|
|
214
|
+
export default AppContainer;
|
|
@@ -18,8 +18,11 @@ import type {Props} from './AppContainer';
|
|
|
18
18
|
import ReactNativeStyleAttributes from '../Components/View/ReactNativeStyleAttributes';
|
|
19
19
|
import View from '../Components/View/View';
|
|
20
20
|
import Platform from '../Utilities/Platform';
|
|
21
|
+
/*
|
|
22
|
+
// Stub out DebuggingOverlay from TV for now
|
|
21
23
|
import DebuggingOverlay from '../Debugging/DebuggingOverlay';
|
|
22
24
|
import useSubscribeToDebuggingOverlayRegistry from '../Debugging/useSubscribeToDebuggingOverlayRegistry';
|
|
25
|
+
*/
|
|
23
26
|
import RCTDeviceEventEmitter from '../EventEmitter/RCTDeviceEventEmitter';
|
|
24
27
|
import LogBoxNotificationContainer from '../LogBox/LogBoxNotificationContainer';
|
|
25
28
|
import StyleSheet from '../StyleSheet/StyleSheet';
|
|
@@ -96,12 +99,14 @@ const AppContainer = ({
|
|
|
96
99
|
}: Props): React.Node => {
|
|
97
100
|
const appContainerRootViewRef: AppContainerRootViewRef = React.useRef(null);
|
|
98
101
|
const innerViewRef: InspectedViewRef = React.useRef(null);
|
|
102
|
+
/*
|
|
99
103
|
const debuggingOverlayRef: DebuggingOverlayRef = React.useRef(null);
|
|
100
104
|
|
|
101
105
|
useSubscribeToDebuggingOverlayRegistry(
|
|
102
106
|
appContainerRootViewRef,
|
|
103
107
|
debuggingOverlayRef,
|
|
104
108
|
);
|
|
109
|
+
*/
|
|
105
110
|
|
|
106
111
|
const [key, setKey] = useState(0);
|
|
107
112
|
const [shouldRenderInspector, setShouldRenderInspector] = useState(false);
|
|
@@ -172,7 +177,7 @@ const AppContainer = ({
|
|
|
172
177
|
pointerEvents="box-none">
|
|
173
178
|
{innerView}
|
|
174
179
|
|
|
175
|
-
{
|
|
180
|
+
{/* <DebuggingOverlay ref={debuggingOverlayRef} /> */}
|
|
176
181
|
|
|
177
182
|
{reactDevToolsAgent != null && (
|
|
178
183
|
<ReactDevToolsOverlayDeferred
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -396,7 +396,7 @@ RCT_EXPORT_METHOD(show)
|
|
|
396
396
|
? UIAlertControllerStyleActionSheet
|
|
397
397
|
: UIAlertControllerStyleAlert;
|
|
398
398
|
|
|
399
|
-
NSString *devMenuType = self.bridge ? @"Bridge" : @"Bridgeless";
|
|
399
|
+
NSString *devMenuType = [self.bridge isKindOfClass:RCTBridge.class] ? @"Bridge" : @"Bridgeless";
|
|
400
400
|
NSString *devMenuTitle = [NSString stringWithFormat:@"React Native Dev Menu (%@)", devMenuType];
|
|
401
401
|
|
|
402
402
|
_actionSheet = [UIAlertController alertControllerWithTitle:devMenuTitle message:description preferredStyle:style];
|
|
@@ -158,6 +158,11 @@ RCT_EXPORT_MODULE()
|
|
|
158
158
|
return NO;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
- (BOOL)_isBridgeMode
|
|
162
|
+
{
|
|
163
|
+
return [self.bridge isKindOfClass:[RCTBridge class]];
|
|
164
|
+
}
|
|
165
|
+
|
|
161
166
|
- (instancetype)initWithDataSource:(id<RCTDevSettingsDataSource>)dataSource
|
|
162
167
|
{
|
|
163
168
|
if (self = [super init]) {
|
|
@@ -178,7 +183,7 @@ RCT_EXPORT_MODULE()
|
|
|
178
183
|
- (void)initialize
|
|
179
184
|
{
|
|
180
185
|
#if RCT_DEV_SETTINGS_ENABLE_PACKAGER_CONNECTION
|
|
181
|
-
if (self
|
|
186
|
+
if ([self _isBridgeMode]) {
|
|
182
187
|
RCTBridge *__weak weakBridge = self.bridge;
|
|
183
188
|
_bridgeExecutorOverrideToken = [[RCTPackagerConnection sharedPackagerConnection]
|
|
184
189
|
addNotificationHandler:^(id params) {
|
|
@@ -209,7 +214,7 @@ RCT_EXPORT_MODULE()
|
|
|
209
214
|
#endif
|
|
210
215
|
|
|
211
216
|
#if RCT_ENABLE_INSPECTOR
|
|
212
|
-
if (self
|
|
217
|
+
if ([self _isBridgeMode]) {
|
|
213
218
|
// We need this dispatch to the main thread because the bridge is not yet
|
|
214
219
|
// finished with its initialisation. By the time it relinquishes control of
|
|
215
220
|
// the main thread, this operation can be performed.
|
|
@@ -250,7 +255,7 @@ RCT_EXPORT_MODULE()
|
|
|
250
255
|
{
|
|
251
256
|
[super invalidate];
|
|
252
257
|
#if RCT_DEV_SETTINGS_ENABLE_PACKAGER_CONNECTION
|
|
253
|
-
if (self
|
|
258
|
+
if ([self _isBridgeMode]) {
|
|
254
259
|
[[RCTPackagerConnection sharedPackagerConnection] removeHandler:_bridgeExecutorOverrideToken];
|
|
255
260
|
}
|
|
256
261
|
|
|
@@ -281,7 +286,7 @@ RCT_EXPORT_MODULE()
|
|
|
281
286
|
- (BOOL)isDeviceDebuggingAvailable
|
|
282
287
|
{
|
|
283
288
|
#if RCT_ENABLE_INSPECTOR
|
|
284
|
-
if (self
|
|
289
|
+
if ([self _isBridgeMode]) {
|
|
285
290
|
return self.bridge.isInspectable;
|
|
286
291
|
} else {
|
|
287
292
|
return self.isInspectable;
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
#import "RCTTVNavigationEventEmitter.h"
|
|
9
|
+
#if TARGET_OS_TV
|
|
9
10
|
#import "RCTTVNavigationEventNotificationConstants.h"
|
|
11
|
+
#endif
|
|
10
12
|
|
|
11
13
|
#import <FBReactNativeSpec/FBReactNativeSpec.h>
|
|
12
14
|
#import "CoreModulesPlugins.h"
|
|
@@ -28,10 +30,12 @@ RCT_EXPORT_MODULE()
|
|
|
28
30
|
- (instancetype)init
|
|
29
31
|
{
|
|
30
32
|
if (self = [super init]) {
|
|
33
|
+
#if TARGET_OS_TV
|
|
31
34
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
32
35
|
selector:@selector(handleTVNavigationEventNotification:)
|
|
33
36
|
name:RCTTVNavigationEventNotificationName
|
|
34
37
|
object:nil];
|
|
38
|
+
#endif
|
|
35
39
|
}
|
|
36
40
|
return self;
|
|
37
41
|
}
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
|
|
10
10
|
@protocol RCTFabricModalHostViewControllerDelegate <NSObject>
|
|
11
11
|
- (void)boundsDidChange:(CGRect)newBounds;
|
|
12
|
+
#if TARGET_OS_TV
|
|
13
|
+
- (void)enableEventHandlers;
|
|
14
|
+
- (void)disableEventHandlers;
|
|
15
|
+
#endif
|
|
12
16
|
@end
|
|
13
17
|
|
|
14
18
|
@interface RCTFabricModalHostViewController : UIViewController
|
|
@@ -42,18 +42,28 @@
|
|
|
42
42
|
[_touchHandler attachToView:self.view];
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
#if !TARGET_OS_TV
|
|
46
|
-
- (UIStatusBarStyle)preferredStatusBarStyle
|
|
47
|
-
{
|
|
48
|
-
return [RCTUIStatusBarManager() statusBarStyle];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
45
|
- (void)viewDidDisappear:(BOOL)animated
|
|
52
46
|
{
|
|
53
47
|
[super viewDidDisappear:animated];
|
|
54
48
|
_lastViewBounds = CGRectZero;
|
|
55
49
|
}
|
|
56
50
|
|
|
51
|
+
#if TARGET_OS_TV
|
|
52
|
+
- (void)viewDidAppear:(BOOL)animated
|
|
53
|
+
{
|
|
54
|
+
[self.delegate enableEventHandlers];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
- (void)viewWillDisappear:(BOOL)animated
|
|
58
|
+
{
|
|
59
|
+
[self.delegate disableEventHandlers];
|
|
60
|
+
}
|
|
61
|
+
#else
|
|
62
|
+
- (UIStatusBarStyle)preferredStatusBarStyle
|
|
63
|
+
{
|
|
64
|
+
return [RCTUIStatusBarManager() statusBarStyle];
|
|
65
|
+
}
|
|
66
|
+
|
|
57
67
|
- (BOOL)prefersStatusBarHidden
|
|
58
68
|
{
|
|
59
69
|
return [RCTUIStatusBarManager() isStatusBarHidden];
|
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
|
|
20
20
|
#import "RCTFabricModalHostViewController.h"
|
|
21
21
|
|
|
22
|
+
#if TARGET_OS_TV
|
|
23
|
+
#import <React/RCTTVRemoteHandler.h>
|
|
24
|
+
#endif
|
|
25
|
+
|
|
22
26
|
using namespace facebook::react;
|
|
23
27
|
|
|
24
28
|
#if !TARGET_OS_TV
|
|
@@ -115,6 +119,10 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
|
|
115
119
|
BOOL _shouldPresent;
|
|
116
120
|
BOOL _isPresented;
|
|
117
121
|
UIView *_modalContentsSnapshot;
|
|
122
|
+
#if TARGET_OS_TV
|
|
123
|
+
UITapGestureRecognizer *_menuButtonGestureRecognizer;
|
|
124
|
+
RCTTVRemoteHandler *_tvRemoteHandler;
|
|
125
|
+
#endif
|
|
118
126
|
}
|
|
119
127
|
|
|
120
128
|
- (instancetype)initWithFrame:(CGRect)frame
|
|
@@ -122,6 +130,11 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
|
|
122
130
|
if (self = [super initWithFrame:frame]) {
|
|
123
131
|
_props = ModalHostViewShadowNode::defaultSharedProps();
|
|
124
132
|
_shouldAnimatePresentation = YES;
|
|
133
|
+
#if TARGET_OS_TV
|
|
134
|
+
_menuButtonGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
|
|
135
|
+
action:@selector(menuButtonPressed)];
|
|
136
|
+
_menuButtonGestureRecognizer.allowedPressTypes = @[ @(UIPressTypeMenu) ];
|
|
137
|
+
#endif
|
|
125
138
|
|
|
126
139
|
_isPresented = NO;
|
|
127
140
|
}
|
|
@@ -129,6 +142,38 @@ static ModalHostViewEventEmitter::OnOrientationChange onOrientationChangeStruct(
|
|
|
129
142
|
return self;
|
|
130
143
|
}
|
|
131
144
|
|
|
145
|
+
#if TARGET_OS_TV
|
|
146
|
+
- (void)menuButtonPressed {
|
|
147
|
+
UIView *snapshot = _modalContentsSnapshot;
|
|
148
|
+
[self.viewController.view addSubview:snapshot];
|
|
149
|
+
[self dismissViewController:self.viewController
|
|
150
|
+
animated:_shouldAnimatePresentation
|
|
151
|
+
completion:^{
|
|
152
|
+
[snapshot removeFromSuperview];
|
|
153
|
+
auto eventEmitter = [self modalEventEmitter];
|
|
154
|
+
if (eventEmitter) {
|
|
155
|
+
eventEmitter->onDismiss(ModalHostViewEventEmitter::OnDismiss{});
|
|
156
|
+
eventEmitter->onRequestClose(ModalHostViewEventEmitter::OnRequestClose{});
|
|
157
|
+
}
|
|
158
|
+
}];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
- (void)enableEventHandlers
|
|
162
|
+
{
|
|
163
|
+
_tvRemoteHandler = [[RCTTVRemoteHandler alloc] initWithView:_viewController.view];
|
|
164
|
+
[_tvRemoteHandler disableTVMenuKey];
|
|
165
|
+
|
|
166
|
+
[_viewController.view addGestureRecognizer:_menuButtonGestureRecognizer];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
- (void)disableEventHandlers
|
|
170
|
+
{
|
|
171
|
+
_tvRemoteHandler = nil;
|
|
172
|
+
[_viewController.view removeGestureRecognizer:_menuButtonGestureRecognizer];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
#endif
|
|
176
|
+
|
|
132
177
|
- (RCTFabricModalHostViewController *)viewController
|
|
133
178
|
{
|
|
134
179
|
if (!_viewController) {
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
#import <React/RCTBridge+Private.h>
|
|
12
12
|
#import <React/RCTConstants.h>
|
|
13
13
|
#import <React/RCTScrollEvent.h>
|
|
14
|
-
#import <React/RCTTVNavigationEventNotification.h>
|
|
15
14
|
|
|
16
15
|
#import <react/renderer/components/scrollview/RCTComponentViewHelpers.h>
|
|
17
16
|
#import <react/renderer/components/scrollview/ScrollViewComponentDescriptor.h>
|
|
@@ -26,7 +25,8 @@
|
|
|
26
25
|
#import "RCTFabricComponentsPlugins.h"
|
|
27
26
|
|
|
28
27
|
#if TARGET_OS_TV
|
|
29
|
-
#import
|
|
28
|
+
#import <React/RCTTVRemoteHandler.h>
|
|
29
|
+
#import <React/RCTTVNavigationEventNotification.h>
|
|
30
30
|
#endif
|
|
31
31
|
|
|
32
32
|
using namespace facebook::react;
|
|
@@ -19,7 +19,9 @@
|
|
|
19
19
|
#import <React/RCTLog.h>
|
|
20
20
|
|
|
21
21
|
#import <React/RCTSurfaceHostingProxyRootView.h>
|
|
22
|
+
#if TARGET_OS_TV
|
|
22
23
|
#import <React/RCTTVNavigationEventNotification.h>
|
|
24
|
+
#endif
|
|
23
25
|
|
|
24
26
|
#import <react/renderer/components/view/ViewComponentDescriptor.h>
|
|
25
27
|
#import <react/renderer/components/view/ViewEventEmitter.h>
|
|
@@ -34,6 +34,32 @@
|
|
|
34
34
|
return self;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
- (void)viewDidAppear:(BOOL)animated
|
|
38
|
+
{
|
|
39
|
+
#if TARGET_OS_TV
|
|
40
|
+
[self.modalHostView enableEventHandlers];
|
|
41
|
+
#endif
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
- (void)viewWillDisappear:(BOOL)animated
|
|
45
|
+
{
|
|
46
|
+
#if TARGET_OS_TV
|
|
47
|
+
[self.modalHostView disableEventHandlers];
|
|
48
|
+
if (self.modalHostView.onRequestClose) {
|
|
49
|
+
self.modalHostView.onRequestClose(nil);
|
|
50
|
+
}
|
|
51
|
+
#endif
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
- (void)viewDidDisappear:(BOOL)animated
|
|
55
|
+
{
|
|
56
|
+
#if TARGET_OS_TV
|
|
57
|
+
if (self.modalHostView.onDismiss) {
|
|
58
|
+
self.modalHostView.onDismiss(nil);
|
|
59
|
+
}
|
|
60
|
+
#endif
|
|
61
|
+
}
|
|
62
|
+
|
|
37
63
|
- (void)viewDidLayoutSubviews
|
|
38
64
|
{
|
|
39
65
|
[super viewDidLayoutSubviews];
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
#import "RCTConvert.h"
|
|
13
13
|
#import "RCTLog.h"
|
|
14
14
|
#import "RCTScrollEvent.h"
|
|
15
|
-
#import "RCTTVNavigationEventNotification.h"
|
|
16
15
|
#import "RCTUIManager.h"
|
|
17
16
|
#import "RCTUIManagerObserverCoordinator.h"
|
|
18
17
|
#import "RCTUIManagerUtils.h"
|
|
@@ -23,6 +22,7 @@
|
|
|
23
22
|
|
|
24
23
|
#if TARGET_OS_TV
|
|
25
24
|
#import "RCTTVRemoteHandler.h"
|
|
25
|
+
#import "RCTTVNavigationEventNotification.h"
|
|
26
26
|
#endif
|
|
27
27
|
|
|
28
28
|
#if !TARGET_OS_TV
|
|
@@ -145,12 +145,12 @@ public class BridgelessCatalystInstance(private val reactHost: ReactHostImpl) :
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
@Deprecated(message = "This API is unsupported in the New Architecture.")
|
|
148
|
-
override fun getJavaScriptContextHolder(): JavaScriptContextHolder {
|
|
149
|
-
|
|
148
|
+
override fun getJavaScriptContextHolder(): JavaScriptContextHolder? {
|
|
149
|
+
return reactHost.getJavaScriptContextHolder()
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
override fun getRuntimeExecutor(): RuntimeExecutor {
|
|
153
|
-
|
|
152
|
+
override fun getRuntimeExecutor(): RuntimeExecutor? {
|
|
153
|
+
return reactHost.getRuntimeExecutor()
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
override fun getRuntimeScheduler(): RuntimeScheduler {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-tvos",
|
|
3
|
-
"version": "0.74.0-
|
|
3
|
+
"version": "0.74.0-0rc3",
|
|
4
4
|
"description": "A framework for building native apps using React",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -111,13 +111,13 @@
|
|
|
111
111
|
"@react-native-community/cli": "13.6.4",
|
|
112
112
|
"@react-native-community/cli-platform-android": "13.6.4",
|
|
113
113
|
"@react-native-community/cli-platform-ios": "13.6.4",
|
|
114
|
-
"@react-native/assets-registry": "0.74.
|
|
115
|
-
"@react-native/codegen": "0.74.
|
|
116
|
-
"@react-native/community-cli-plugin": "0.74.
|
|
117
|
-
"@react-native/gradle-plugin": "0.74.
|
|
118
|
-
"@react-native/js-polyfills": "0.74.
|
|
119
|
-
"@react-native/normalize-colors": "0.74.
|
|
120
|
-
"@react-native-tvos/virtualized-lists": "0.74.0-
|
|
114
|
+
"@react-native/assets-registry": "0.74.80",
|
|
115
|
+
"@react-native/codegen": "0.74.80",
|
|
116
|
+
"@react-native/community-cli-plugin": "0.74.80",
|
|
117
|
+
"@react-native/gradle-plugin": "0.74.80",
|
|
118
|
+
"@react-native/js-polyfills": "0.74.80",
|
|
119
|
+
"@react-native/normalize-colors": "0.74.80",
|
|
120
|
+
"@react-native-tvos/virtualized-lists": "0.74.0-0rc3",
|
|
121
121
|
"abort-controller": "^3.0.0",
|
|
122
122
|
"anser": "^1.4.9",
|
|
123
123
|
"ansi-regex": "^5.0.0",
|
|
@@ -166,4 +166,4 @@
|
|
|
166
166
|
"devDependencies": {
|
|
167
167
|
"react-native-core": "npm:react-native@0.74.0-rc.8"
|
|
168
168
|
}
|
|
169
|
-
}
|
|
169
|
+
}
|
|
@@ -98,11 +98,12 @@ class ReactNativePodsUtils
|
|
|
98
98
|
Pod::UI.puts("#{message_prefix}: Ccache found at #{ccache_path}")
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
+
# Using scripts wrapping the ccache executable, to allow injection of configurations
|
|
102
|
+
ccache_clang_sh = File.join("$(REACT_NATIVE_PATH)", 'scripts', 'xcode', 'ccache-clang.sh')
|
|
103
|
+
ccache_clangpp_sh = File.join("$(REACT_NATIVE_PATH)", 'scripts', 'xcode', 'ccache-clang++.sh')
|
|
104
|
+
|
|
101
105
|
if ccache_available and ccache_enabled
|
|
102
106
|
Pod::UI.puts("#{message_prefix}: Setting CC, LD, CXX & LDPLUSPLUS build settings")
|
|
103
|
-
# Using scripts wrapping the ccache executable, to allow injection of configurations
|
|
104
|
-
ccache_clang_sh = File.join("$(REACT_NATIVE_PATH)", 'scripts', 'xcode', 'ccache-clang.sh')
|
|
105
|
-
ccache_clangpp_sh = File.join("$(REACT_NATIVE_PATH)", 'scripts', 'xcode', 'ccache-clang++.sh')
|
|
106
107
|
|
|
107
108
|
projects.each do |project|
|
|
108
109
|
project.build_configurations.each do |config|
|
|
@@ -119,6 +120,20 @@ class ReactNativePodsUtils
|
|
|
119
120
|
Pod::UI.puts("#{message_prefix}: Pass ':ccache_enabled => true' to 'react_native_post_install' in your Podfile or set environment variable 'USE_CCACHE=1' to increase the speed of subsequent builds")
|
|
120
121
|
elsif !ccache_available and ccache_enabled
|
|
121
122
|
Pod::UI.warn("#{message_prefix}: Install ccache or ensure your neither passing ':ccache_enabled => true' nor setting environment variable 'USE_CCACHE=1'")
|
|
123
|
+
else
|
|
124
|
+
Pod::UI.puts("#{message_prefix}: Removing Ccache from CC, LD, CXX & LDPLUSPLUS build settings")
|
|
125
|
+
|
|
126
|
+
projects.each do |project|
|
|
127
|
+
project.build_configurations.each do |config|
|
|
128
|
+
# Using the un-qualified names means you can swap in different implementations, for example ccache
|
|
129
|
+
config.build_settings["CC"] = config.build_settings["CC"] ? config.build_settings["CC"].gsub(/#{Regexp.escape(ccache_clang_sh)}/, '') : ""
|
|
130
|
+
config.build_settings["LD"] = config.build_settings["LD"] ? config.build_settings["LD"].gsub(/#{Regexp.escape(ccache_clang_sh)}/, "") : ""
|
|
131
|
+
config.build_settings["CXX"] = config.build_settings["CXX"] ? config.build_settings["CXX"].gsub(/#{Regexp.escape(ccache_clangpp_sh)}/, "") : ""
|
|
132
|
+
config.build_settings["LDPLUSPLUS"] = config.build_settings["LDPLUSPLUS"] ? config.build_settings["LDPLUSPLUS"].gsub(/#{Regexp.escape(ccache_clangpp_sh)}/, "") : ""
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
project.save()
|
|
136
|
+
end
|
|
122
137
|
end
|
|
123
138
|
end
|
|
124
139
|
|
|
@@ -580,6 +595,44 @@ class ReactNativePodsUtils
|
|
|
580
595
|
ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "React-ImageManager", header_search_paths)
|
|
581
596
|
end
|
|
582
597
|
|
|
598
|
+
def self.get_privacy_manifest_paths_from(user_project)
|
|
599
|
+
privacy_manifests = user_project
|
|
600
|
+
.files
|
|
601
|
+
.select { |p|
|
|
602
|
+
p.path&.end_with?('PrivacyInfo.xcprivacy')
|
|
603
|
+
}
|
|
604
|
+
return privacy_manifests
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
def self.add_privacy_manifest_if_needed(installer)
|
|
608
|
+
user_project = installer.aggregate_targets
|
|
609
|
+
.map{ |t| t.user_project }
|
|
610
|
+
.first
|
|
611
|
+
privacy_manifest = self.get_privacy_manifest_paths_from(user_project).first
|
|
612
|
+
if privacy_manifest.nil?
|
|
613
|
+
file_timestamp_reason = {
|
|
614
|
+
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryFileTimestamp",
|
|
615
|
+
"NSPrivacyAccessedAPITypeReasons" => ["C617.1"],
|
|
616
|
+
}
|
|
617
|
+
user_defaults_reason = {
|
|
618
|
+
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryUserDefaults",
|
|
619
|
+
"NSPrivacyAccessedAPITypeReasons" => ["CA92.1"],
|
|
620
|
+
}
|
|
621
|
+
boot_time_reason = {
|
|
622
|
+
"NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategorySystemBootTime",
|
|
623
|
+
"NSPrivacyAccessedAPITypeReasons" => ["35F9.1"],
|
|
624
|
+
}
|
|
625
|
+
privacy_manifest = {
|
|
626
|
+
"NSPrivacyCollectedDataTypes" => [],
|
|
627
|
+
"NSPrivacyTracking" => false,
|
|
628
|
+
"NSPrivacyAccessedAPITypes" => [file_timestamp_reason, user_defaults_reason, boot_time_reason]
|
|
629
|
+
}
|
|
630
|
+
path = File.join(user_project.path.parent, "PrivacyInfo.xcprivacy")
|
|
631
|
+
Xcodeproj::Plist.write_to_path(privacy_manifest, path)
|
|
632
|
+
Pod::UI.puts "Your app does not have a privacy manifest! A template has been generated containing Required Reasons API usage in the core React Native library. Please add the PrivacyInfo.xcprivacy file to your project and complete data use, tracking and any additional required reasons your app is using according to Apple's guidance: https://developer.apple.com/.../privacy_manifest_files. Then, you will need to manually add this file to your project in Xcode.".red
|
|
633
|
+
end
|
|
634
|
+
end
|
|
635
|
+
|
|
583
636
|
def self.react_native_pods
|
|
584
637
|
return [
|
|
585
638
|
"DoubleConversion",
|
|
@@ -297,6 +297,7 @@ def react_native_post_install(
|
|
|
297
297
|
ReactNativePodsUtils.updateOSDeploymentTarget(installer)
|
|
298
298
|
ReactNativePodsUtils.set_dynamic_frameworks_flags(installer)
|
|
299
299
|
ReactNativePodsUtils.add_ndebug_flag_to_pods_in_release(installer)
|
|
300
|
+
ReactNativePodsUtils.add_privacy_manifest_if_needed(installer)
|
|
300
301
|
|
|
301
302
|
NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer)
|
|
302
303
|
NewArchitectureHelper.modify_flags_for_new_architecture(installer, NewArchitectureHelper.new_arch_enabled)
|
package/sdks/.hermesversion
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
hermes-2024-
|
|
1
|
+
hermes-2024-04-19-RNv0.74.0-165ff0ee4154834c995b80227ecd67e94a031035
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/template/package.json
CHANGED
|
@@ -13,16 +13,16 @@
|
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"expo": "^50.0.11",
|
|
15
15
|
"react": "18.2.0",
|
|
16
|
-
"react-native": "npm:react-native-tvos@0.74.0-
|
|
16
|
+
"react-native": "npm:react-native-tvos@0.74.0-0rc3"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@babel/core": "^7.20.0",
|
|
20
20
|
"@babel/preset-env": "^7.20.0",
|
|
21
21
|
"@babel/runtime": "^7.20.0",
|
|
22
|
-
"@react-native/babel-preset": "0.74.
|
|
23
|
-
"@react-native/eslint-config": "0.74.
|
|
24
|
-
"@react-native/metro-config": "0.74.
|
|
25
|
-
"@react-native/typescript-config": "0.74.
|
|
22
|
+
"@react-native/babel-preset": "0.74.80",
|
|
23
|
+
"@react-native/eslint-config": "0.74.80",
|
|
24
|
+
"@react-native/metro-config": "0.74.80",
|
|
25
|
+
"@react-native/typescript-config": "0.74.80",
|
|
26
26
|
"@types/react": "^18.2.6",
|
|
27
27
|
"@types/react-test-renderer": "^18.0.0",
|
|
28
28
|
"babel-jest": "^29.6.3",
|