Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor[AppContainer]: remove innerView ref from state #41613

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,21 @@
* @format
*/

import type {Overlay} from '../../Debugging/DebuggingOverlayNativeComponent';
import type {
InstanceFromReactDevTools,
ReactDevToolsAgent,
} from '../../Types/ReactDevToolsTypes';
import type {Overlay} from './TraceUpdateOverlayNativeComponent';

import UIManager from '../../ReactNative/UIManager';
import TraceUpdateOverlayNativeComponent, {
Commands,
} from '../../Debugging/DebuggingOverlayNativeComponent';
import processColor from '../../StyleSheet/processColor';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Platform from '../../Utilities/Platform';
import View from '../View/View';
import TraceUpdateOverlayNativeComponent, {
Commands,
} from './TraceUpdateOverlayNativeComponent';
import * as React from 'react';

const {useEffect, useRef, useState} = React;
const isNativeComponentReady =
Platform.OS === 'android' &&
UIManager.hasViewManagerConfig('TraceUpdateOverlay');

type Props = {
reactDevToolsAgent: ReactDevToolsAgent,
Expand All @@ -39,10 +34,6 @@ export default function TraceUpdateOverlay({
const [overlayDisabled, setOverlayDisabled] = useState(false);

useEffect(() => {
if (!isNativeComponentReady) {
return;
}

const drawTraceUpdates = (
nodesToDraw: Array<{node: InstanceFromReactDevTools, color: string}> = [],
) => {
Expand Down Expand Up @@ -116,8 +107,7 @@ export default function TraceUpdateOverlay({
useRef<?React.ElementRef<typeof TraceUpdateOverlayNativeComponent>>(null);

return (
!overlayDisabled &&
isNativeComponentReady && (
!overlayDisabled && (
<View pointerEvents="none" style={styles.overlay}>
<TraceUpdateOverlayNativeComponent
ref={nativeComponentRef}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@
* @format
*/

import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
import type {ProcessedColorValue} from '../../StyleSheet/processColor';
import type {ViewProps} from '../View/ViewPropTypes';
import type {ViewProps} from '../Components/View/ViewPropTypes';
import type {HostComponent} from '../Renderer/shims/ReactNativeTypes';
import type {ProcessedColorValue} from '../StyleSheet/processColor';

import codegenNativeCommands from '../../Utilities/codegenNativeCommands';
import codegenNativeComponent from '../../Utilities/codegenNativeComponent';
import codegenNativeCommands from '../Utilities/codegenNativeCommands';
import codegenNativeComponent from '../Utilities/codegenNativeComponent';
import * as React from 'react';

type NativeProps = $ReadOnly<{|
...ViewProps,
|}>;
export type TraceUpdateOverlayNativeComponentType = HostComponent<NativeProps>;
export type DebuggingOverlayNativeComponentType = HostComponent<NativeProps>;
export type Overlay = {
rect: {left: number, top: number, width: number, height: number},
color: ?ProcessedColorValue,
};

interface NativeCommands {
+draw: (
viewRef: React.ElementRef<TraceUpdateOverlayNativeComponentType>,
viewRef: React.ElementRef<DebuggingOverlayNativeComponentType>,
// TODO(T144046177): Ideally we can pass array of Overlay, but currently
// Array type is not supported in RN codegen for building native commands.
overlays: string,
Expand All @@ -38,6 +38,6 @@ export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
supportedCommands: ['draw'],
});

export default (codegenNativeComponent<NativeProps>(
'TraceUpdateOverlay',
): HostComponent<NativeProps>);
export default (codegenNativeComponent<NativeProps>('DebuggingOverlay', {
paperComponentName: 'RCTDebuggingOverlay',
}): HostComponent<NativeProps>);
7 changes: 3 additions & 4 deletions packages/react-native/Libraries/Inspector/Inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import type {
} from '../Renderer/shims/ReactNativeTypes';
import type {ViewStyleProp} from '../StyleSheet/StyleSheet';
import type {ReactDevToolsAgent} from '../Types/ReactDevToolsTypes';
import type {HostRef} from './getInspectorDataForViewAtPoint';

const View = require('../Components/View/View');
const PressabilityDebug = require('../Pressability/PressabilityDebug');
Expand Down Expand Up @@ -47,13 +46,13 @@ export type InspectedElement = $ReadOnly<{
export type ElementsHierarchy = InspectorData['hierarchy'];

type Props = {
inspectedView: ?HostRef,
inspectedViewRef: React.RefObject<React.ElementRef<typeof View> | null>,
onRequestRerenderApp: () => void,
reactDevToolsAgent?: ReactDevToolsAgent,
};

function Inspector({
inspectedView,
inspectedViewRef,
onRequestRerenderApp,
reactDevToolsAgent,
}: Props): React.Node {
Expand Down Expand Up @@ -126,7 +125,7 @@ function Inspector({
};

getInspectorDataForViewAtPoint(
inspectedView,
inspectedViewRef.current,
locationX,
locationY,
viewData => {
Expand Down
42 changes: 23 additions & 19 deletions packages/react-native/Libraries/Inspector/ReactDevToolsOverlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import type {
InstanceFromReactDevTools,
ReactDevToolsAgent,
} from '../Types/ReactDevToolsTypes';
import type {HostRef} from './getInspectorDataForViewAtPoint';
import type {InspectedElement} from './Inspector';

import View from '../Components/View/View';
Expand All @@ -30,12 +29,12 @@ const getInspectorDataForViewAtPoint = require('./getInspectorDataForViewAtPoint
const {useEffect, useState, useCallback} = React;

type Props = {
inspectedView: ?HostRef,
inspectedViewRef: React.RefObject<React.ElementRef<typeof View> | null>,
reactDevToolsAgent: ReactDevToolsAgent,
};

export default function ReactDevToolsOverlay({
inspectedView,
inspectedViewRef,
reactDevToolsAgent,
}: Props): React.Node {
const [inspected, setInspected] = useState<?InspectedElement>(null);
Expand Down Expand Up @@ -125,24 +124,29 @@ export default function ReactDevToolsOverlay({

const findViewForLocation = useCallback(
(x: number, y: number) => {
getInspectorDataForViewAtPoint(inspectedView, x, y, viewData => {
const {touchedViewTag, closestInstance, frame} = viewData;
if (closestInstance != null || touchedViewTag != null) {
// We call `selectNode` for both non-fabric(viewTag) and fabric(instance),
// this makes sure it works for both architectures.
reactDevToolsAgent.selectNode(findNodeHandle(touchedViewTag));
if (closestInstance != null) {
reactDevToolsAgent.selectNode(closestInstance);
getInspectorDataForViewAtPoint(
inspectedViewRef.current,
x,
y,
viewData => {
const {touchedViewTag, closestInstance, frame} = viewData;
if (closestInstance != null || touchedViewTag != null) {
// We call `selectNode` for both non-fabric(viewTag) and fabric(instance),
// this makes sure it works for both architectures.
reactDevToolsAgent.selectNode(findNodeHandle(touchedViewTag));
if (closestInstance != null) {
reactDevToolsAgent.selectNode(closestInstance);
}
setInspected({
frame,
});
return true;
}
setInspected({
frame,
});
return true;
}
return false;
});
return false;
},
);
},
[inspectedView, reactDevToolsAgent],
[inspectedViewRef, reactDevToolsAgent],
);

const stopInspecting = useCallback(() => {
Expand Down
17 changes: 7 additions & 10 deletions packages/react-native/Libraries/ReactNative/AppContainer-dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import type {Props} from './AppContainer';
import TraceUpdateOverlay from '../Components/TraceUpdateOverlay/TraceUpdateOverlay';
import ReactNativeStyleAttributes from '../Components/View/ReactNativeStyleAttributes';
import View from '../Components/View/View';
import ViewNativeComponent from '../Components/View/ViewNativeComponent';
import RCTDeviceEventEmitter from '../EventEmitter/RCTDeviceEventEmitter';
import ReactDevToolsOverlay from '../Inspector/ReactDevToolsOverlay';
import LogBoxNotificationContainer from '../LogBox/LogBoxNotificationContainer';
Expand All @@ -41,13 +40,13 @@ if (reactDevToolsHook) {
}

type InspectorDeferredProps = {
inspectedView: React.ElementRef<typeof ViewNativeComponent> | null,
inspectedViewRef: React.RefObject<React.ElementRef<typeof View> | null>,
onInspectedViewRerenderRequest: () => void,
reactDevToolsAgent?: ReactDevToolsAgent,
};

const InspectorDeferred = ({
inspectedView,
inspectedViewRef,
onInspectedViewRerenderRequest,
reactDevToolsAgent,
}: InspectorDeferredProps) => {
Expand All @@ -57,7 +56,7 @@ const InspectorDeferred = ({

return (
<Inspector
inspectedView={inspectedView}
inspectedViewRef={inspectedViewRef}
onRequestRerenderApp={onInspectedViewRerenderRequest}
reactDevToolsAgent={reactDevToolsAgent}
/>
Expand All @@ -74,9 +73,7 @@ const AppContainer = ({
showArchitectureIndicator,
WrapperComponent,
}: Props): React.Node => {
const [mainRef, setMainRef] = useState<React.ElementRef<
typeof ViewNativeComponent,
> | null>(null);
const innerViewRef = React.useRef<React.ElementRef<typeof View> | null>(null);

const [key, setKey] = useState(0);
const [shouldRenderInspector, setShouldRenderInspector] = useState(false);
Expand Down Expand Up @@ -118,7 +115,7 @@ const AppContainer = ({
pointerEvents="box-none"
key={key}
style={styles.container}
ref={setMainRef}>
ref={innerViewRef}>
{children}
</View>
);
Expand Down Expand Up @@ -149,14 +146,14 @@ const AppContainer = ({
)}
{reactDevToolsAgent != null && (
<ReactDevToolsOverlay
inspectedView={mainRef}
inspectedViewRef={innerViewRef}
reactDevToolsAgent={reactDevToolsAgent}
/>
)}

{shouldRenderInspector && (
<InspectorDeferred
inspectedView={mainRef}
inspectedViewRef={innerViewRef}
onInspectedViewRerenderRequest={onInspectedViewRerenderRequest}
reactDevToolsAgent={reactDevToolsAgent}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <UIKit/UIKit.h>

#import <React/RCTViewComponentView.h>

@interface RCTDebuggingOverlayComponentView : RCTViewComponentView

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import "RCTDebuggingOverlayComponentView.h"

#import <React/RCTDebuggingOverlay.h>
#import <React/RCTDefines.h>
#import <React/RCTLog.h>

#import <react/renderer/components/rncore/ComponentDescriptors.h>
#import <react/renderer/components/rncore/EventEmitters.h>
#import <react/renderer/components/rncore/Props.h>

#import "RCTFabricComponentsPlugins.h"

using namespace facebook::react;

@implementation RCTDebuggingOverlayComponentView {
RCTDebuggingOverlay *_overlay;
}

- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const DebuggingOverlayProps>();
_props = defaultProps;

_overlay = [[RCTDebuggingOverlay alloc] initWithFrame:self.bounds];

self.contentView = _overlay;
}

return self;
}

#pragma mark - RCTComponentViewProtocol

+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<DebuggingOverlayComponentDescriptor>();
}

#pragma mark - Native commands

- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
{
if (![commandName isEqualToString:@"draw"]) {
RCTLogError(@"%@ received unsupported command %@", @"DebuggingOverlay", commandName);
return;
}

NSObject *arg0 = args[0];
#if RCT_DEBUG
if (!RCTValidateTypeOfViewCommandArgument(
arg0, [NSString class], @"string", @"DebuggingOverlay", commandName, @"1st")) {
return;
}
#endif

NSString *serializedNodes = (NSString *)arg0;
[_overlay draw:serializedNodes];
}

@end

Class<RCTComponentViewProtocol> RCTDebuggingOverlayCls(void)
{
return RCTDebuggingOverlayComponentView.class;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Class<RCTComponentViewProtocol> RCTFabricComponentsProvider(const char *name);

// Lookup functions
Class<RCTComponentViewProtocol> RCTActivityIndicatorViewCls(void) __attribute__((used));
Class<RCTComponentViewProtocol> RCTDebuggingOverlayCls(void) __attribute__((used));
Class<RCTComponentViewProtocol> RCTInputAccessoryCls(void) __attribute__((used));
Class<RCTComponentViewProtocol> RCTParagraphCls(void) __attribute__((used));
Class<RCTComponentViewProtocol> RCTPullToRefreshViewCls(void) __attribute__((used));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
Class<RCTComponentViewProtocol> RCTFabricComponentsProvider(const char *name) {
static std::unordered_map<std::string, Class (*)(void)> sFabricComponentsClassMap = {
{"ActivityIndicatorView", RCTActivityIndicatorViewCls},
{"DebuggingOverlay", RCTDebuggingOverlayCls},
{"InputAccessoryView", RCTInputAccessoryCls},
{"Paragraph", RCTParagraphCls},
{"PullToRefreshView", RCTPullToRefreshViewCls},
Expand Down
16 changes: 16 additions & 0 deletions packages/react-native/React/Views/RCTDebuggingOverlay.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <UIKit/UIKit.h>

#import <React/RCTView.h>

@interface RCTDebuggingOverlay : RCTView

- (void)draw:(NSString *)serializedNodes;

@end
Loading