Skip to content
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 @@ -9,6 +9,7 @@
*/

import UIManager from '../../ReactNative/UIManager';
import nullthrows from 'nullthrows';

/**
* This is a function exposed to the React Renderer that can be used by the
Expand All @@ -19,13 +20,13 @@ function legacySendAccessibilityEvent(
eventType: string,
): void {
if (eventType === 'focus') {
UIManager.sendAccessibilityEvent(
nullthrows(UIManager.sendAccessibilityEvent)(
reactTag,
UIManager.getConstants().AccessibilityEventTypes.typeViewFocused,
);
}
if (eventType === 'click') {
UIManager.sendAccessibilityEvent(
nullthrows(UIManager.sendAccessibilityEvent)(
reactTag,
UIManager.getConstants().AccessibilityEventTypes.typeViewClicked,
);
Expand Down
149 changes: 81 additions & 68 deletions packages/react-native/Libraries/ReactNative/BridgelessUIManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {RootTag} from '../Types/RootTagTypes';
import type {UIManagerJSInterface} from '../Types/UIManagerJSInterface';

import {unstable_hasComponent} from '../NativeComponent/NativeComponentRegistryUnstable';
import Platform from '../Utilities/Platform';
import nullthrows from 'nullthrows';

function raiseSoftError(methodName: string, details?: string): void {
Expand Down Expand Up @@ -96,15 +97,93 @@ const UIManagerJSOverridenAPIs = {
},
};

/**
* Leave Unimplemented: The only thing that called these methods was the paper renderer.
* In OSS, the New Architecture will just use the Fabric renderer, which uses
* different APIs.
*/
const UIManagerJSUnusedAPIs = {
createView: (
reactTag: ?number,
viewName: string,
rootTag: RootTag,
props: Object,
): void => {
raiseSoftError('createView');
},
updateView: (reactTag: number, viewName: string, props: Object): void => {
raiseSoftError('updateView');
},
setChildren: (containerTag: ?number, reactTags: Array<number>): void => {
raiseSoftError('setChildren');
},
manageChildren: (
containerTag: ?number,
moveFromIndices: Array<number>,
moveToIndices: Array<number>,
addChildReactTags: Array<number>,
addAtIndices: Array<number>,
removeAtIndices: Array<number>,
): void => {
raiseSoftError('manageChildren');
},
};

const UIManagerJSPlatformAPIs = Platform.select({
android: {
getConstantsForViewManager: (viewManagerName: string): Object => {
raiseSoftError('getConstantsForViewManager');
return {};
},
getDefaultEventTypes: (): Array<string> => {
raiseSoftError('getDefaultEventTypes');
return [];
},
setLayoutAnimationEnabledExperimental: (enabled: boolean): void => {
raiseSoftError('setLayoutAnimationEnabledExperimental');
},
// Please use AccessibilityInfo.sendAccessibilityEvent instead.
// See SetAccessibilityFocusExample in AccessibilityExample.js for a migration example.
sendAccessibilityEvent: (reactTag: ?number, eventType: number): void => {
raiseSoftError('sendAccessibilityEvent');
},
showPopupMenu: (
reactTag: ?number,
items: Array<string>,
error: (error: Object) => void,
success: (event: string, selected?: number) => void,
): void => {
raiseSoftError('showPopupMenu');
},
dismissPopupMenu: (): void => {
raiseSoftError('dismissPopupMenu');
},
},
ios: {
lazilyLoadView: (name: string): Object => {
raiseSoftError('lazilyLoadView');
return {};
},
focus: (reactTag: ?number): void => {
raiseSoftError('focus');
},
blur: (reactTag: ?number): void => {
raiseSoftError('blur');
},
},
});

const UIManagerJS: UIManagerJSInterface & {[string]: any} = {
...UIManagerJSOverridenAPIs,
...UIManagerJSPlatformAPIs,
...UIManagerJSUnusedAPIs,
getViewManagerConfig: (viewManagerName: string): mixed => {
if (getUIManagerConstants) {
return getUIManagerConstantsCache()[viewManagerName];
} else {
raiseSoftError(
'getViewManagerConfig',
`Use hasViewManagerConfig instead. viewManagerName: ${viewManagerName}`,
`getViewManagerConfig('${viewManagerName}')`,
`If '${viewManagerName}' has a ViewManager and you want to retrieve its native ViewConfig, please turn on the native ViewConfig interop layer. If you want to see if this component is registered with React Native, please call hasViewManagerConfig('${viewManagerName}') instead.`,
);
return null;
}
Expand All @@ -120,35 +199,6 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = {
return null;
}
},
getConstantsForViewManager: (viewManagerName: string): Object => {
raiseSoftError('getConstantsForViewManager');
return {};
},
getDefaultEventTypes: (): Array<string> => {
raiseSoftError('getDefaultEventTypes');
return [];
},
lazilyLoadView: (name: string): Object => {
raiseSoftError('lazilyLoadView');
return {};
},
createView: (
reactTag: ?number,
viewName: string,
rootTag: RootTag,
props: Object,
): void => {
raiseSoftError('createView');
},
updateView: (reactTag: number, viewName: string, props: Object): void => {
raiseSoftError('updateView');
},
focus: (reactTag: ?number): void => {
raiseSoftError('focus');
},
blur: (reactTag: ?number): void => {
raiseSoftError('blur');
},
findSubviewIn: (
reactTag: ?number,
point: Array<number>,
Expand Down Expand Up @@ -182,49 +232,12 @@ const UIManagerJS: UIManagerJSInterface & {[string]: any} = {
): void => {
raiseSoftError('configureNextLayoutAnimation');
},
removeSubviewsFromContainerWithID: (containerID: number): void => {
raiseSoftError('removeSubviewsFromContainerWithID');
},
replaceExistingNonRootView: (
reactTag: ?number,
newReactTag: ?number,
): void => {
raiseSoftError('replaceExistingNonRootView');
},
setChildren: (containerTag: ?number, reactTags: Array<number>): void => {
raiseSoftError('setChildren');
},
manageChildren: (
containerTag: ?number,
moveFromIndices: Array<number>,
moveToIndices: Array<number>,
addChildReactTags: Array<number>,
addAtIndices: Array<number>,
removeAtIndices: Array<number>,
): void => {
raiseSoftError('manageChildren');
},

// Android only
setLayoutAnimationEnabledExperimental: (enabled: boolean): void => {
raiseSoftError('setLayoutAnimationEnabledExperimental');
},
// Please use AccessibilityInfo.sendAccessibilityEvent instead.
// See SetAccessibilityFocusExample in AccessibilityExample.js for a migration example.
sendAccessibilityEvent: (reactTag: ?number, eventType: number): void => {
raiseSoftError('sendAccessibilityEvent');
},
showPopupMenu: (
reactTag: ?number,
items: Array<string>,
error: (error: Object) => void,
success: (event: string, selected?: number) => void,
): void => {
raiseSoftError('showPopupMenu');
},
dismissPopupMenu: (): void => {
raiseSoftError('dismissPopupMenu');
},
};

if (getUIManagerConstants) {
Expand Down
21 changes: 11 additions & 10 deletions packages/react-native/Libraries/ReactNative/NativeUIManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,13 @@ import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';

export interface Spec extends TurboModule {
+getConstants: () => Object;
+getConstantsForViewManager: (viewManagerName: string) => Object;
+getDefaultEventTypes: () => Array<string>;
+lazilyLoadView: (name: string) => Object; // revisit return
+createView: (
reactTag: ?number,
viewName: string,
rootTag: RootTag,
props: Object,
) => void;
+updateView: (reactTag: number, viewName: string, props: Object) => void;
+focus: (reactTag: ?number) => void;
+blur: (reactTag: ?number) => void;
+findSubviewIn: (
reactTag: ?number,
point: Array<number>,
Expand Down Expand Up @@ -91,7 +86,6 @@ export interface Spec extends TurboModule {
callback: () => void, // check what is returned here
errorCallback: (error: Object) => void,
) => void;
+removeSubviewsFromContainerWithID: (containerID: number) => void;
+replaceExistingNonRootView: (
reactTag: ?number,
newReactTag: ?number,
Expand All @@ -107,15 +101,22 @@ export interface Spec extends TurboModule {
) => void;

// Android only
+setLayoutAnimationEnabledExperimental: (enabled: boolean) => void;
+sendAccessibilityEvent: (reactTag: ?number, eventType: number) => void;
+showPopupMenu: (
+getConstantsForViewManager?: (viewManagerName: string) => Object;
+getDefaultEventTypes?: () => Array<string>;
+setLayoutAnimationEnabledExperimental?: (enabled: boolean) => void;
+sendAccessibilityEvent?: (reactTag: ?number, eventType: number) => void;
+showPopupMenu?: (
reactTag: ?number,
items: Array<string>,
error: (error: Object) => void,
success: (event: string, selected?: number) => void,
) => void;
+dismissPopupMenu: () => void;
+dismissPopupMenu?: () => void;

// ios only
+lazilyLoadView?: (name: string) => Object; // revisit return
+focus?: (reactTag: ?number) => void;
+blur?: (reactTag: ?number) => void;
}

export default (TurboModuleRegistry.getEnforcing<Spec>('UIManager'): Spec);
6 changes: 4 additions & 2 deletions packages/react-native/Libraries/ReactNative/PaperUIManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {RootTag} from '../Types/RootTagTypes';
import type {UIManagerJSInterface} from '../Types/UIManagerJSInterface';

import NativeUIManager from './NativeUIManager';
import nullthrows from 'nullthrows';

const NativeModules = require('../BatchedBridge/NativeModules');
const defineLazyObjectProperty = require('../Utilities/defineLazyObjectProperty');
Expand Down Expand Up @@ -67,7 +68,7 @@ function getViewManagerConfig(viewManagerName: string): any {
NativeUIManager.lazilyLoadView &&
!triedLoadingConfig.has(viewManagerName)
) {
const result = NativeUIManager.lazilyLoadView(viewManagerName);
const result = nullthrows(NativeUIManager.lazilyLoadView)(viewManagerName);
triedLoadingConfig.add(viewManagerName);
if (result != null && result.viewConfig != null) {
getConstants()[viewManagerName] = result.viewConfig;
Expand Down Expand Up @@ -161,7 +162,8 @@ if (Platform.OS === 'ios') {
} else if (getConstants().ViewManagerNames) {
NativeUIManager.getConstants().ViewManagerNames.forEach(viewManagerName => {
defineLazyObjectProperty(NativeUIManager, viewManagerName, {
get: () => NativeUIManager.getConstantsForViewManager(viewManagerName),
get: () =>
nullthrows(NativeUIManager.getConstantsForViewManager)(viewManagerName),
});
});
}
Expand Down
18 changes: 11 additions & 7 deletions packages/react-native/Libraries/ReactNative/UIManager.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ export interface UIManagerStatic {
*
* UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
*/
setLayoutAnimationEnabledExperimental(value: boolean): void;
setLayoutAnimationEnabledExperimental?:
| ((value: boolean) => void)
| undefined;

/**
* Used to display an Android PopupMenu. If a menu item is pressed, the success callback will
Expand All @@ -126,12 +128,14 @@ export interface UIManagerStatic {
*
* Note that this works only on Android
*/
showPopupMenu(
node: number,
items: string[],
error: () => void /* currently unused */,
success: (item: string, index: number | undefined) => void,
): void;
showPopupMenu?:
| ((
node: number,
items: string[],
error: () => void /* currently unused */,
success: (item: string, index: number | undefined) => void,
) => void)
| undefined;

getViewManagerConfig: (name: string) => {
Commands: {[key: string]: number};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ module.exports = [
'measureLayout',
'measureLayoutRelativeToParent',
'removeRootView',
'removeSubviewsFromContainerWithID',
'replaceExistingNonRootView',
'sendAccessibilityEvent',
'setChildren',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const pointsDiffer = require('../Utilities/differ/pointsDiffer');
const sizesDiffer = require('../Utilities/differ/sizesDiffer');
const UIManager = require('./UIManager');
const invariant = require('invariant');
const nullthrows = require('nullthrows');

function getNativeComponentAttributes(uiViewClassName: string): any {
const viewConfig = UIManager.getViewManagerConfig(uiViewClassName);
Expand Down Expand Up @@ -105,7 +106,10 @@ function attachDefaultEventTypes(viewConfig: any) {
const constants = UIManager.getConstants();
if (constants.ViewManagerNames || constants.LazyViewManagersEnabled) {
// Lazy view managers enabled.
viewConfig = merge(viewConfig, UIManager.getDefaultEventTypes());
viewConfig = merge(
viewConfig,
nullthrows(UIManager.getDefaultEventTypes)(),
);
} else {
viewConfig.bubblingEventTypes = merge(
viewConfig.bubblingEventTypes,
Expand Down
25 changes: 0 additions & 25 deletions packages/react-native/React/Modules/RCTUIManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -700,31 +700,6 @@ - (RCTViewManagerUIBlock)uiBlockWithLayoutUpdateForRootView:(RCTRootShadowView *
};
}

/**
* A method to be called from JS, which takes a container ID and then releases
* all subviews for that container upon receipt.
*/
RCT_EXPORT_METHOD(removeSubviewsFromContainerWithID : (nonnull NSNumber *)containerID)
{
RCTLogWarn(
@"RCTUIManager.removeSubviewsFromContainerWithID method is deprecated and it will not be implemented in newer versions of RN (Fabric) - T47686450");
id<RCTComponent> container = _shadowViewRegistry[containerID];
RCTAssert(container != nil, @"container view (for ID %@) not found", containerID);

NSUInteger subviewsCount = [container reactSubviews].count;
NSMutableArray<NSNumber *> *indices = [[NSMutableArray alloc] initWithCapacity:subviewsCount];
for (NSUInteger childIndex = 0; childIndex < subviewsCount; childIndex++) {
[indices addObject:@(childIndex)];
}

[self manageChildren:containerID
moveFromIndices:nil
moveToIndices:nil
addChildReactTags:nil
addAtIndices:nil
removeAtIndices:indices];
}

/**
* Disassociates children from container. Doesn't remove from registries.
* TODO: use [NSArray getObjects:buffer] to reuse same fast buffer each time.
Expand Down
Loading