From 455ca8cfaf8060def528425e2a58b19930009fdd Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 13 Dec 2022 11:43:05 -0800 Subject: [PATCH] Make UIManager.measure* compatible with Fabric Summary: changelog: [internal] To make migration to the new architecture more straight forward, this change makes `UIManager.measure`, `UIManager.measureInWindow`, `UIManager.measureLayout` and `UIManager.measureLayoutRelativeToParent` functions backwards compatible. Users will not have to make any change to continue using the APIs. This will make [Migrating .measure*() ](https://reactnative.dev/docs/new-architecture-library-intro#migrating-measure) in the migration guide optional. Reviewed By: yungsters Differential Revision: D41613050 fbshipit-source-id: 3c65ced231590243d118fbc120a87b08d5261da0 --- Libraries/ReactNative/FabricUIManager.js | 1 + Libraries/ReactNative/UIManager.js | 144 ++++++++++++++++++++++- 2 files changed, 144 insertions(+), 1 deletion(-) diff --git a/Libraries/ReactNative/FabricUIManager.js b/Libraries/ReactNative/FabricUIManager.js index b73fc1eae0610a..5cff1bd376990c 100644 --- a/Libraries/ReactNative/FabricUIManager.js +++ b/Libraries/ReactNative/FabricUIManager.js @@ -58,6 +58,7 @@ export type Spec = {| errorCallback: (error: Object) => void, ) => void, +sendAccessibilityEvent: (node: Node, eventType: string) => void, + +findShadowNodeByTag_DEPRECATED: (reactTag: number) => ?Node, |}; const FabricUIManager: ?Spec = global.nativeFabricUIManager; diff --git a/Libraries/ReactNative/UIManager.js b/Libraries/ReactNative/UIManager.js index ffead4967c84e9..ac28590f23deef 100644 --- a/Libraries/ReactNative/UIManager.js +++ b/Libraries/ReactNative/UIManager.js @@ -9,6 +9,7 @@ */ import type {RootTag} from '../Types/RootTagTypes'; +import type {Spec as FabricUIManagerSpec} from './FabricUIManager'; import type {Spec} from './NativeUIManager'; export interface UIManagerJSInterface extends Spec { @@ -31,9 +32,150 @@ export interface UIManagerJSInterface extends Spec { ) => void; } -const UIManager: UIManagerJSInterface = +function isFabricReactTag(reactTag: number): boolean { + // React reserves even numbers for Fabric. + return reactTag % 2 === 0; +} + +const UIManagerImpl: UIManagerJSInterface = global.RN$Bridgeless === true ? require('./BridgelessUIManager') : require('./PaperUIManager'); +// $FlowFixMe[cannot-spread-interface] +const UIManager = { + ...UIManagerImpl, + measure( + reactTag: number, + callback: ( + left: number, + top: number, + width: number, + height: number, + pageX: number, + pageY: number, + ) => void, + ): void { + if (isFabricReactTag(reactTag)) { + const FabricUIManager: FabricUIManagerSpec = + global?.nativeFabricUIManager; + const shadowNode = + FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); + if (shadowNode) { + FabricUIManager.measure(shadowNode, callback); + } else { + console.warn(`measure cannot find view with tag #${reactTag}`); + // $FlowFixMe[incompatible-call] + callback(); + } + } else { + // Paper + UIManagerImpl.measure(reactTag, callback); + } + }, + + measureInWindow( + reactTag: number, + callback: ( + left: number, + top: number, + width: number, + height: number, + ) => void, + ): void { + if (isFabricReactTag(reactTag)) { + const FabricUIManager: FabricUIManagerSpec = + global?.nativeFabricUIManager; + const shadowNode = + FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); + if (shadowNode) { + FabricUIManager.measureInWindow(shadowNode, callback); + } else { + console.warn(`measure cannot find view with tag #${reactTag}`); + // $FlowFixMe[incompatible-call] + callback(); + } + } else { + // Paper + UIManagerImpl.measureInWindow(reactTag, callback); + } + }, + + measureLayout( + reactTag: number, + ancestorReactTag: number, + errorCallback: (error: Object) => void, + callback: ( + left: number, + top: number, + width: number, + height: number, + ) => void, + ): void { + if (isFabricReactTag(reactTag)) { + const FabricUIManager: FabricUIManagerSpec = + global?.nativeFabricUIManager; + const shadowNode = + FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); + const ancestorShadowNode = + FabricUIManager.findShadowNodeByTag_DEPRECATED(ancestorReactTag); + + if (!shadowNode || !ancestorShadowNode) { + return; + } + + FabricUIManager.measureLayout( + shadowNode, + ancestorShadowNode, + errorCallback, + callback, + ); + } else { + // Paper + UIManagerImpl.measureLayout( + reactTag, + ancestorReactTag, + errorCallback, + callback, + ); + } + }, + + measureLayoutRelativeToParent( + reactTag: number, + errorCallback: (error: Object) => void, + callback: ( + left: number, + top: number, + width: number, + height: number, + ) => void, + ): void { + if (isFabricReactTag(reactTag)) { + console.warn( + 'RCTUIManager.measureLayoutRelativeToParent method is deprecated and it will not be implemented in newer versions of RN (Fabric) - T47686450', + ); + const FabricUIManager: FabricUIManagerSpec = + global?.nativeFabricUIManager; + const shadowNode = + FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); + if (shadowNode) { + FabricUIManager.measure( + shadowNode, + (left, top, width, height, pageX, pageY) => { + callback(left, top, width, height); + }, + ); + } + } else { + // Paper + UIManagerImpl.measureLayoutRelativeToParent( + reactTag, + errorCallback, + callback, + ); + } + }, +}; + module.exports = UIManager;