Skip to content

Commit

Permalink
feat[DebuggingOverlayRegistry]: basic implementation (facebook#41743)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#41743

Changelog: [Internal]

There will be a single DebuggingRegistry instance per runtime, which will be responsible for finding lowest AppContainer ancestor for highligthed component.

It will receive refs to root views (ancestors, AppContainers) as subscriptions and later will call all necessary methods.

In the next series of diffs, subscriber will also provide reference to the DebuggingOverlay, on which DebuggingRegistry can call all necessary methods to highlight elements.

Differential Revision: D51536787

Reviewed By: rshest

fbshipit-source-id: 95bac8098e293bfa13afae755706fbfc4f520e2e
  • Loading branch information
Ruslan Lesiutin authored and facebook-github-bot committed Jan 15, 2024
1 parent bdc3714 commit 54671d9
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -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.
*
* @flow strict-local
* @format
* @oncall react_native
*/

import type {AppContainerRootViewRef} from '../ReactNative/AppContainer-dev';

export type DebuggingOverlayRegistrySubscriberProtocol = {
rootViewRef: AppContainerRootViewRef,
};

class DebuggingOverlayRegistry {
#registry: Set<DebuggingOverlayRegistrySubscriberProtocol> = new Set();

subscribe(subscriber: DebuggingOverlayRegistrySubscriberProtocol) {
this.#registry.add(subscriber);
}

unsubscribe(subscriber: DebuggingOverlayRegistrySubscriberProtocol) {
const wasPresent = this.#registry.delete(subscriber);
if (!wasPresent) {
console.error(
'[DebuggingOverlayRegistry] Unexpected argument for unsubscription, which was not previously subscribed:',
subscriber,
);
}
}
}

const debuggingOverlayRegistryInstance: DebuggingOverlayRegistry =
new DebuggingOverlayRegistry();
export default debuggingOverlayRegistryInstance;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* 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.
*
* @flow strict-local
* @format
* @oncall react_native
*/

import type {AppContainerRootViewRef} from '../ReactNative/AppContainer-dev';

import DebuggingOverlayRegistry from './DebuggingOverlayRegistry';
import {useEffect} from 'react';

const useSubscribeToDebuggingOverlayRegistry = (
rootViewRef: AppContainerRootViewRef,
) => {
useEffect(() => {
const subscriber = {rootViewRef};

DebuggingOverlayRegistry.subscribe(subscriber);
return () => DebuggingOverlayRegistry.unsubscribe(subscriber);
}, [rootViewRef]);
};

export default useSubscribeToDebuggingOverlayRegistry;
3 changes: 2 additions & 1 deletion packages/react-native/Libraries/Inspector/Inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

'use strict';

import type {InspectedViewRef} from '../ReactNative/AppContainer-dev';
import type {
InspectorData,
TouchedViewDataAtPoint,
Expand Down Expand Up @@ -46,7 +47,7 @@ export type InspectedElement = $ReadOnly<{
export type ElementsHierarchy = InspectorData['hierarchy'];

type Props = {
inspectedViewRef: React.RefObject<React.ElementRef<typeof View> | null>,
inspectedViewRef: InspectedViewRef,
onRequestRerenderApp: () => void,
reactDevToolsAgent?: ReactDevToolsAgent,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* @flow
*/

import type {InspectedViewRef} from '../ReactNative/AppContainer-dev';
import type {PointerEvent} from '../Types/CoreEventTypes';
import type {PressEvent} from '../Types/CoreEventTypes';
import type {
Expand All @@ -29,7 +30,7 @@ const getInspectorDataForViewAtPoint = require('./getInspectorDataForViewAtPoint
const {useEffect, useState, useCallback} = React;

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

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

type InspectorDeferredProps = {
inspectedViewRef: React.RefObject<React.ElementRef<typeof View> | null>,
inspectedViewRef: InspectedViewRef,
onInspectedViewRerenderRequest: () => void,
reactDevToolsAgent?: ReactDevToolsAgent,
};
Expand Down Expand Up @@ -73,7 +74,9 @@ const AppContainer = ({
showArchitectureIndicator,
WrapperComponent,
}: Props): React.Node => {
const innerViewRef = React.useRef<React.ElementRef<typeof View> | null>(null);
const appContainerRootViewRef: AppContainerRootViewRef = React.useRef(null);
const innerViewRef: InspectedViewRef = React.useRef(null);
useSubscribeToDebuggingOverlayRegistry(appContainerRootViewRef);

const [key, setKey] = useState(0);
const [shouldRenderInspector, setShouldRenderInspector] = useState(false);
Expand Down Expand Up @@ -138,7 +141,10 @@ const AppContainer = ({

return (
<RootTagContext.Provider value={createRootTag(rootTag)}>
<View style={styles.container} pointerEvents="box-none">
<View
ref={appContainerRootViewRef}
style={styles.container}
pointerEvents="box-none">
{innerView}

{reactDevToolsAgent != null && (
Expand Down Expand Up @@ -169,4 +175,10 @@ const styles = StyleSheet.create({
container: {flex: 1},
});

export type AppContainerRootViewRef = React.RefObject<React.ElementRef<
typeof View,
> | null>;
export type InspectedViewRef = React.RefObject<React.ElementRef<
typeof View,
> | null>;
export default AppContainer;

0 comments on commit 54671d9

Please sign in to comment.