Skip to content

Commit

Permalink
Make UIManager.measure* compatible with Fabric
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sammy-SC authored and facebook-github-bot committed Dec 13, 2022
1 parent 326109b commit 455ca8c
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 1 deletion.
1 change: 1 addition & 0 deletions Libraries/ReactNative/FabricUIManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
144 changes: 143 additions & 1 deletion Libraries/ReactNative/UIManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;

0 comments on commit 455ca8c

Please sign in to comment.