Skip to content

Commit

Permalink
Pull PopupMenuAndroid out of React Native core
Browse files Browse the repository at this point in the history
Summary:
**History:** This component was originally introduced into React Native core in D52712758, to replace UIManagerModule.showPopupMenu().

**Problem:** But, React Native core should be lean. Adding this component to React Native bloats the core.

**Changes:** So, this diff pulls PopupMenuAndroid out into its own package in the react-native GitHub repository.

In the future, this will be migrated to a community package!

Changelog: [Android][Removed] Move PopupMenu out of React Native core

Reviewed By: NickGerleman

Differential Revision: D53328110

fbshipit-source-id: 469d8dc3e756c06040c72e08fa004aafa1bd6e18
  • Loading branch information
RSNara authored and facebook-github-bot committed Feb 24, 2024
1 parent e6e5822 commit 8bced4b
Show file tree
Hide file tree
Showing 37 changed files with 482 additions and 129 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -42,6 +42,7 @@ project.xcworkspace
/packages/react-native/ReactAndroid/hermes-engine/.cxx/
/packages/react-native/template/android/app/build/
/packages/react-native/template/android/build/
/packages/react-native-popup-menu-android/android/build/

# Buck
.buckd
Expand Down
35 changes: 35 additions & 0 deletions packages/react-native-popup-menu-android/android/build.gradle.kts
@@ -0,0 +1,35 @@
/*
* 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.
*/

plugins {
id("com.facebook.react")
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
}

android {
compileSdk = libs.versions.compileSdk.get().toInt()
buildToolsVersion = libs.versions.buildTools.get()
namespace = "com.facebook.react.popupmenu"

defaultConfig {
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.targetSdk.get().toInt()
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

kotlinOptions { jvmTarget = "17" }
}

dependencies {
// Build React Native from source
implementation(project(":packages:react-native:ReactAndroid"))
}
@@ -0,0 +1,3 @@
# We want to have more fine grained control on the Java version for
# ReactAndroid, therefore we disable RGNP Java version alignment mechanism
react.internal.disableJavaVersionAlignment=true
@@ -0,0 +1,20 @@

/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateComponentDescriptorH.js
*/

#pragma once

#include "ShadowNodes.h"
#include <react/renderer/core/ConcreteComponentDescriptor.h>

namespace facebook::react {

using AndroidPopupMenuComponentDescriptor = ConcreteComponentDescriptor<AndroidPopupMenuShadowNode>;

} // namespace facebook::react
@@ -0,0 +1,24 @@

/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateEventEmitterCpp.js
*/

#include "EventEmitters.h"


namespace facebook::react {

void AndroidPopupMenuEventEmitter::onSelectionChange(OnSelectionChange $event) const {
dispatchEvent("selectionChange", [$event=std::move($event)](jsi::Runtime &runtime) {
auto $payload = jsi::Object(runtime);
$payload.setProperty(runtime, "item", $event.item);
return $payload;
});
}

} // namespace facebook::react
@@ -0,0 +1,25 @@

/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateEventEmitterH.js
*/
#pragma once

#include <react/renderer/components/view/ViewEventEmitter.h>


namespace facebook::react {
class AndroidPopupMenuEventEmitter : public ViewEventEmitter {
public:
using ViewEventEmitter::ViewEventEmitter;

struct OnSelectionChange {
int item;
};
void onSelectionChange(OnSelectionChange value) const;
};
} // namespace facebook::react
@@ -0,0 +1,25 @@

/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GeneratePropsCpp.js
*/

#include "Props.h"
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/propsConversions.h>

namespace facebook::react {

AndroidPopupMenuProps::AndroidPopupMenuProps(
const PropsParserContext &context,
const AndroidPopupMenuProps &sourceProps,
const RawProps &rawProps): ViewProps(context, sourceProps, rawProps),

menuItems(convertRawProp(context, rawProps, "menuItems", sourceProps.menuItems, {}))
{}

} // namespace facebook::react
@@ -0,0 +1,28 @@

/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GeneratePropsH.js
*/
#pragma once

#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/PropsParserContext.h>
#include <vector>

namespace facebook::react {

class AndroidPopupMenuProps final : public ViewProps {
public:
AndroidPopupMenuProps() = default;
AndroidPopupMenuProps(const PropsParserContext& context, const AndroidPopupMenuProps &sourceProps, const RawProps &rawProps);

#pragma mark - Props

std::vector<std::string> menuItems{};
};

} // namespace facebook::react
@@ -0,0 +1,17 @@

/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateShadowNodeCpp.js
*/

#include "ShadowNodes.h"

namespace facebook::react {

extern const char AndroidPopupMenuComponentName[] = "AndroidPopupMenu";

} // namespace facebook::react
@@ -0,0 +1,32 @@

/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateShadowNodeH.js
*/

#pragma once

#include "EventEmitters.h"
#include "Props.h"
#include "States.h"
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
#include <jsi/jsi.h>

namespace facebook::react {

JSI_EXPORT extern const char AndroidPopupMenuComponentName[];

/*
* `ShadowNode` for <AndroidPopupMenu> component.
*/
using AndroidPopupMenuShadowNode = ConcreteViewShadowNode<
AndroidPopupMenuComponentName,
AndroidPopupMenuProps,
AndroidPopupMenuEventEmitter,
AndroidPopupMenuState>;

} // namespace facebook::react
@@ -0,0 +1,16 @@

/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateStateCpp.js
*/
#include "States.h"

namespace facebook::react {



} // namespace facebook::react
@@ -0,0 +1,34 @@
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* @generated by codegen project: GenerateStateH.js
*/
#pragma once

#ifdef ANDROID
#include <folly/dynamic.h>
#include <react/renderer/mapbuffer/MapBuffer.h>
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
#endif

namespace facebook::react {

class AndroidPopupMenuState {
public:
AndroidPopupMenuState() = default;

#ifdef ANDROID
AndroidPopupMenuState(AndroidPopupMenuState const &previousState, folly::dynamic data){};
folly::dynamic getDynamic() const {
return {};
};
MapBuffer getMapBuffer() const {
return MapBufferBuilder::EMPTY();
};
#endif
};

} // namespace facebook::react
@@ -0,0 +1,56 @@
/*
* 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.
*/

package com.facebook.react.popupmenu

import com.facebook.react.BaseReactPackage
import com.facebook.react.ViewManagerOnDemandReactPackage
import com.facebook.react.bridge.ModuleSpec
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.annotations.ReactModuleList
import com.facebook.react.module.model.ReactModuleInfoProvider
import com.facebook.react.uimanager.ViewManager

@ReactModuleList(nativeModules = arrayOf())
class PopupMenuPackage() : BaseReactPackage(), ViewManagerOnDemandReactPackage {
private var viewManagersMap: Map<String, ModuleSpec>? = null

override fun getModule(name: String, context: ReactApplicationContext): NativeModule? {
return null
}

private fun getViewManagersMap(): Map<String, ModuleSpec> {
val viewManagers =
viewManagersMap
?: mapOf(
ReactPopupMenuManager.REACT_CLASS to
ModuleSpec.viewManagerSpec({ ReactPopupMenuManager() }))
viewManagersMap = viewManagers
return viewManagers
}

protected override fun getViewManagers(context: ReactApplicationContext): List<ModuleSpec> {
return ArrayList(getViewManagersMap().values)
}

override fun getViewManagerNames(context: ReactApplicationContext): Collection<String> {
return getViewManagersMap().keys
}

override fun createViewManager(
reactContext: ReactApplicationContext,
viewManagerName: String
): ViewManager<*, *>? {
val spec: ModuleSpec? = getViewManagersMap().get(viewManagerName)
return if (spec != null) (spec.getProvider().get() as ViewManager<*, *>) else null
}

override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
return ReactModuleInfoProvider { emptyMap() }
}
}
Expand Up @@ -5,9 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

@file:Suppress("DEPRECATION") // We want to use RCTEventEmitter for interop purposes

package com.facebook.react.views.popupmenu
package com.facebook.react.popupmenu

import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
Expand Down
Expand Up @@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.views.popupmenu
package com.facebook.react.popupmenu

import android.content.Context
import android.os.Build
Expand Down
Expand Up @@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

package com.facebook.react.views.popupmenu
package com.facebook.react.popupmenu

import com.facebook.react.bridge.ReadableArray
import com.facebook.react.module.annotations.ReactModule
Expand Down

0 comments on commit 8bced4b

Please sign in to comment.