diff --git a/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js b/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js index 57c70fd5f28c75..94ded259e1249e 100644 --- a/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js +++ b/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js @@ -8,26 +8,24 @@ * @format */ +import type {Overlay} from '../../Debugging/DebuggingOverlayNativeComponent'; import type { InstanceFromReactDevTools, ReactDevToolsAgent, } from '../../Types/ReactDevToolsTypes'; -import type {Overlay} from './TraceUpdateOverlayNativeComponent'; +import DebuggingOverlayNativeComponent, { + Commands, +} from '../../Debugging/DebuggingOverlayNativeComponent'; import UIManager from '../../ReactNative/UIManager'; 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'); + UIManager.hasViewManagerConfig('DebuggingOverlay'); type Props = { reactDevToolsAgent: ReactDevToolsAgent, @@ -39,13 +37,13 @@ export default function TraceUpdateOverlay({ const [overlayDisabled, setOverlayDisabled] = useState(false); useEffect(() => { - if (!isNativeComponentReady) { - return; - } - const drawTraceUpdates = ( nodesToDraw: Array<{node: InstanceFromReactDevTools, color: string}> = [], ) => { + if (!isNativeComponentReady) { + return; + } + // If overlay is disabled before, now it's enabled. setOverlayDisabled(false); @@ -113,13 +111,13 @@ export default function TraceUpdateOverlay({ }, [reactDevToolsAgent]); const nativeComponentRef = - useRef>(null); + useRef>(null); return ( !overlayDisabled && isNativeComponentReady && ( - diff --git a/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlayNativeComponent.js b/packages/react-native/Libraries/Debugging/DebuggingOverlayNativeComponent.js similarity index 62% rename from packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlayNativeComponent.js rename to packages/react-native/Libraries/Debugging/DebuggingOverlayNativeComponent.js index 837223e3774b2d..0e2f95514583e9 100644 --- a/packages/react-native/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlayNativeComponent.js +++ b/packages/react-native/Libraries/Debugging/DebuggingOverlayNativeComponent.js @@ -8,18 +8,18 @@ * @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; +export type DebuggingOverlayNativeComponentType = HostComponent; export type Overlay = { rect: {left: number, top: number, width: number, height: number}, color: ?ProcessedColorValue, @@ -27,7 +27,7 @@ export type Overlay = { interface NativeCommands { +draw: ( - viewRef: React.ElementRef, + viewRef: React.ElementRef, // 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, @@ -39,5 +39,5 @@ export const Commands: NativeCommands = codegenNativeCommands({ }); export default (codegenNativeComponent( - 'TraceUpdateOverlay', + 'DebuggingOverlay', ): HostComponent); diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.h b/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.h new file mode 100644 index 00000000000000..9ee08512265621 --- /dev/null +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.h @@ -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 + +#import + +#import + +@interface RCTDebuggingOverlayComponentView : RCTViewComponentView + +@end diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.mm new file mode 100644 index 00000000000000..31d1dcb5f77962 --- /dev/null +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/DebuggingOverlay/RCTDebuggingOverlayComponentView.mm @@ -0,0 +1,65 @@ +/* + * 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 +#import +#import + +#import +#import +#import +#import + +#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(); + _props = defaultProps; + + _overlay = [[RCTDebuggingOverlay alloc] initWithFrame:self.bounds]; + + self.contentView = _overlay; + } + + return self; +} + +#pragma mark - RCTComponentViewProtocol + ++ (ComponentDescriptorProvider)componentDescriptorProvider +{ + return concreteComponentDescriptorProvider(); +} + +#pragma mark - Native commands + +- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args +{ + RCTDebuggingOverlayHandleCommand(self, commandName, args); +} + +- (void)draw:(NSString *)overlays +{ + [_overlay draw:overlays]; +} + +@end + +Class RCTDebuggingOverlayCls(void) +{ + return RCTDebuggingOverlayComponentView.class; +} diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h index ca5f395c3141a8..54936a93de7c5c 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h @@ -31,6 +31,7 @@ Class RCTFabricComponentsProvider(const char *name); // Lookup functions Class RCTActivityIndicatorViewCls(void) __attribute__((used)); +Class RCTDebuggingOverlayCls(void) __attribute__((used)); Class RCTInputAccessoryCls(void) __attribute__((used)); Class RCTParagraphCls(void) __attribute__((used)); Class RCTPullToRefreshViewCls(void) __attribute__((used)); diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm index 02d1dc1a125af7..f07b0301cd28a5 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.mm @@ -19,6 +19,7 @@ Class RCTFabricComponentsProvider(const char *name) { static std::unordered_map sFabricComponentsClassMap = { {"ActivityIndicatorView", RCTActivityIndicatorViewCls}, + {"DebuggingOverlay", RCTDebuggingOverlayCls}, {"InputAccessoryView", RCTInputAccessoryCls}, {"Paragraph", RCTParagraphCls}, {"PullToRefreshView", RCTPullToRefreshViewCls}, diff --git a/packages/react-native/React/Views/RCTDebuggingOverlay.h b/packages/react-native/React/Views/RCTDebuggingOverlay.h new file mode 100644 index 00000000000000..64b7d1feb03e45 --- /dev/null +++ b/packages/react-native/React/Views/RCTDebuggingOverlay.h @@ -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 + +#import + +@interface RCTDebuggingOverlay : RCTView + +- (void)draw:(NSString *)serializedNodes; + +@end diff --git a/packages/react-native/React/Views/RCTDebuggingOverlay.m b/packages/react-native/React/Views/RCTDebuggingOverlay.m new file mode 100644 index 00000000000000..992862bd5ec2f0 --- /dev/null +++ b/packages/react-native/React/Views/RCTDebuggingOverlay.m @@ -0,0 +1,57 @@ +/* + * 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 "RCTDebuggingOverlay.h" + +#import +#import +#import + +@implementation RCTDebuggingOverlay + +- (void)draw:(NSString *)serializedNodes +{ + NSArray *subViewsToRemove = [self subviews]; + for (UIView *v in subViewsToRemove) { + [v removeFromSuperview]; + } + + NSError *error = nil; + id deserializedNodes = RCTJSONParse(serializedNodes, &error); + + if (error) { + RCTLogError(@"Failed to parse serialized nodes passed to RCTDebuggingOverlay"); + return; + } + + if (![deserializedNodes isKindOfClass:[NSArray class]]) { + RCTLogError(@"Expected to receive nodes as an array, got %@", NSStringFromClass([deserializedNodes class])); + return; + } + + for (NSDictionary *node in deserializedNodes) { + NSDictionary *nodeRectangle = node[@"rect"]; + NSNumber *nodeColor = node[@"color"]; + + NSNumber *x = nodeRectangle[@"left"]; + NSNumber *y = nodeRectangle[@"top"]; + NSNumber *width = nodeRectangle[@"width"]; + NSNumber *height = nodeRectangle[@"height"]; + + CGRect rect = CGRectMake(x.doubleValue, y.doubleValue, width.doubleValue, height.doubleValue); + + UIView *box = [[UIView alloc] initWithFrame:rect]; + box.backgroundColor = [UIColor clearColor]; + + box.layer.borderWidth = 2.0f; + box.layer.borderColor = [RCTConvert UIColor:nodeColor].CGColor; + + [self addSubview:box]; + } +} + +@end diff --git a/packages/react-native/React/Views/RCTDebuggingOverlayManager.h b/packages/react-native/React/Views/RCTDebuggingOverlayManager.h new file mode 100644 index 00000000000000..a852cc81883e19 --- /dev/null +++ b/packages/react-native/React/Views/RCTDebuggingOverlayManager.h @@ -0,0 +1,12 @@ +/* + * 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 + +@interface RCTDebuggingOverlayManager : RCTViewManager + +@end diff --git a/packages/react-native/React/Views/RCTDebuggingOverlayManager.m b/packages/react-native/React/Views/RCTDebuggingOverlayManager.m new file mode 100644 index 00000000000000..ae00c27ac2e23a --- /dev/null +++ b/packages/react-native/React/Views/RCTDebuggingOverlayManager.m @@ -0,0 +1,38 @@ +/* + * 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 "RCTDebuggingOverlayManager.h" +#import "RCTDebuggingOverlay.h" + +#import +#import + +#import "RCTBridge.h" + +@implementation RCTDebuggingOverlayManager + +RCT_EXPORT_MODULE(DebuggingOverlay) + +- (UIView *)view +{ + return [RCTDebuggingOverlay new]; +} + +RCT_EXPORT_METHOD(draw : (nonnull NSNumber *)viewTag nodes : (NSString *)serializedNodes) +{ + [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { + UIView *view = viewRegistry[viewTag]; + + if ([view isKindOfClass:[RCTDebuggingOverlay class]]) { + [(RCTDebuggingOverlay *)view draw:serializedNodes]; + } else { + RCTLogError(@"Expected view to be RCTDebuggingOverlay, got %@", NSStringFromClass([view class])); + } + }]; +} + +@end diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java index 398b69ac1a5684..69471937ab8501 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java @@ -19,7 +19,7 @@ import com.facebook.react.module.model.ReactModuleInfoProvider; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.ViewManager; -import com.facebook.react.views.traceupdateoverlay.TraceUpdateOverlayManager; +import com.facebook.react.views.debuggingoverlay.DebuggingOverlayManager; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -96,8 +96,7 @@ private static void appendMap( private Map getViewManagersMap() { if (mViewManagers == null) { Map viewManagers = new HashMap<>(); - appendMap( - viewManagers, TraceUpdateOverlayManager.REACT_CLASS, TraceUpdateOverlayManager::new); + appendMap(viewManagers, DebuggingOverlayManager.REACT_CLASS, DebuggingOverlayManager::new); mViewManagers = viewManagers; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlay.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlay.java similarity index 92% rename from packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlay.java rename to packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlay.java index 6799848284828f..0ebaf4b8743866 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlay.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlay.java @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -package com.facebook.react.views.traceupdateoverlay; +package com.facebook.react.views.debuggingoverlay; import android.content.Context; import android.graphics.Canvas; @@ -17,7 +17,7 @@ import java.util.ArrayList; import java.util.List; -public class TraceUpdateOverlay extends View { +public class DebuggingOverlay extends View { private final Paint mOverlayPaint = new Paint(); private List mOverlays = new ArrayList(); @@ -43,7 +43,7 @@ public RectF getPixelRect() { } } - public TraceUpdateOverlay(Context context) { + public DebuggingOverlay(Context context) { super(context); mOverlayPaint.setStyle(Paint.Style.STROKE); mOverlayPaint.setStrokeWidth(6); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlayManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlayManager.java similarity index 76% rename from packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlayManager.java rename to packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlayManager.java index 434be098b1a2fa..cacdd5c4dbfeda 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlayManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/debuggingoverlay/DebuggingOverlayManager.java @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -package com.facebook.react.views.traceupdateoverlay; +package com.facebook.react.views.debuggingoverlay; import android.graphics.RectF; import androidx.annotation.Nullable; @@ -16,22 +16,22 @@ import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.views.traceupdateoverlay.TraceUpdateOverlay.Overlay; +import com.facebook.react.views.debuggingoverlay.DebuggingOverlay.Overlay; import java.util.ArrayList; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -@ReactModule(name = TraceUpdateOverlayManager.REACT_CLASS) -public class TraceUpdateOverlayManager extends SimpleViewManager { - public static final String REACT_CLASS = "TraceUpdateOverlay"; +@ReactModule(name = DebuggingOverlayManager.REACT_CLASS) +public class DebuggingOverlayManager extends SimpleViewManager { + public static final String REACT_CLASS = "DebuggingOverlay"; - public TraceUpdateOverlayManager() {} + public DebuggingOverlayManager() {} @Override public void receiveCommand( - TraceUpdateOverlay view, String commandId, @Nullable ReadableArray args) { + DebuggingOverlay view, String commandId, @Nullable ReadableArray args) { switch (commandId) { case "draw": if (args == null) { @@ -67,13 +67,13 @@ public void receiveCommand( ReactSoftExceptionLogger.logSoftException( REACT_CLASS, new ReactNoCrashSoftException( - "Received unexpected command in TraceUpdateOverlayManager")); + "Received unexpected command in DebuggingOverlayManager")); } } @Override - public TraceUpdateOverlay createViewInstance(ThemedReactContext context) { - return new TraceUpdateOverlay(context); + public DebuggingOverlay createViewInstance(ThemedReactContext context) { + return new DebuggingOverlay(context); } @Override diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp index 5cc5aae68d5bff..99ddee8b3b1dd1 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/CoreComponentsRegistry.cpp @@ -66,7 +66,7 @@ CoreComponentsRegistry::sharedProviderRegistry() { providerRegistry->add(concreteComponentDescriptorProvider< AndroidDrawerLayoutComponentDescriptor>()); providerRegistry->add(concreteComponentDescriptorProvider< - TraceUpdateOverlayComponentDescriptor>()); + DebuggingOverlayComponentDescriptor>()); return providerRegistry; }();