Convert + Internalize SwipeRefreshLayoutManager (#47470)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/47470

Convert to Kotlin and formalize it being an internal class (some methods were already `protected` in Java)

Changelog:
[Android] [Breaking] - Stable API - Make SwipeRefreshLayoutManager internal

Reviewed By: cortinico

Differential Revision: D65481861

fbshipit-source-id: afc5c624373fbcd3ca2d28b2834d2682de672997
This commit is contained in:
Thomas Nardone
2024-11-07 11:39:35 -08:00
committed by Facebook GitHub Bot
parent 8b053a4fca
commit d02da992a4
4 changed files with 155 additions and 227 deletions
@@ -7155,37 +7155,6 @@ public class com/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout : and
public fun setRefreshing (Z)V
}
public class com/facebook/react/views/swiperefresh/SwipeRefreshLayoutManager : com/facebook/react/uimanager/ViewGroupManager, com/facebook/react/viewmanagers/AndroidSwipeRefreshLayoutManagerInterface {
public static final field REACT_CLASS Ljava/lang/String;
public fun <init> ()V
protected synthetic fun addEventEmitters (Lcom/facebook/react/uimanager/ThemedReactContext;Landroid/view/View;)V
protected fun addEventEmitters (Lcom/facebook/react/uimanager/ThemedReactContext;Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;)V
protected synthetic fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View;
protected fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;
protected fun getDelegate ()Lcom/facebook/react/uimanager/ViewManagerDelegate;
public fun getExportedCustomDirectEventTypeConstants ()Ljava/util/Map;
public fun getExportedViewConstants ()Ljava/util/Map;
public fun getName ()Ljava/lang/String;
public synthetic fun receiveCommand (Landroid/view/View;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
public fun receiveCommand (Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V
public synthetic fun setColors (Landroid/view/View;Lcom/facebook/react/bridge/ReadableArray;)V
public fun setColors (Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;Lcom/facebook/react/bridge/ReadableArray;)V
public synthetic fun setEnabled (Landroid/view/View;Z)V
public fun setEnabled (Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;Z)V
public synthetic fun setNativeRefreshing (Landroid/view/View;Z)V
public fun setNativeRefreshing (Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;Z)V
public synthetic fun setProgressBackgroundColor (Landroid/view/View;Ljava/lang/Integer;)V
public fun setProgressBackgroundColor (Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;Ljava/lang/Integer;)V
public synthetic fun setProgressViewOffset (Landroid/view/View;F)V
public fun setProgressViewOffset (Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;F)V
public synthetic fun setRefreshing (Landroid/view/View;Z)V
public fun setRefreshing (Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;Z)V
public synthetic fun setSize (Landroid/view/View;Ljava/lang/String;)V
public fun setSize (Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;I)V
public fun setSize (Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;Lcom/facebook/react/bridge/Dynamic;)V
public fun setSize (Lcom/facebook/react/views/swiperefresh/ReactSwipeRefreshLayout;Ljava/lang/String;)V
}
public class com/facebook/react/views/switchview/ReactSwitchManager : com/facebook/react/uimanager/SimpleViewManager, com/facebook/react/viewmanagers/AndroidSwitchManagerInterface {
public static final field REACT_CLASS Ljava/lang/String;
public fun <init> ()V
@@ -15,9 +15,9 @@ import com.facebook.react.uimanager.events.Event
internal class RefreshEvent : Event<RefreshEvent> {
@Deprecated("Use constructor with surfaceId", ReplaceWith("RefreshEvent(surfaceId, viewTag)"))
protected constructor(viewTag: Int) : this(ViewUtil.NO_SURFACE_ID, viewTag)
constructor(viewTag: Int) : this(ViewUtil.NO_SURFACE_ID, viewTag)
protected constructor(surfaceId: Int, viewTag: Int) : super(surfaceId, viewTag)
constructor(surfaceId: Int, viewTag: Int) : super(surfaceId, viewTag)
override public fun getEventName(): String {
return "topRefresh"
@@ -1,194 +0,0 @@
/*
* 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.views.swiperefresh;
import static com.facebook.react.views.swiperefresh.SwipeRefreshLayoutManager.REACT_CLASS;
import android.graphics.Color;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener;
import com.facebook.react.bridge.ColorPropConverter;
import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableType;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.ViewManagerDelegate;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.viewmanagers.AndroidSwipeRefreshLayoutManagerDelegate;
import com.facebook.react.viewmanagers.AndroidSwipeRefreshLayoutManagerInterface;
import java.util.HashMap;
import java.util.Map;
/**
* ViewManager for {@link ReactSwipeRefreshLayout} which allows the user to "pull to refresh" a
* child view. Emits an {@code onRefresh} event when this happens.
*/
@ReactModule(name = REACT_CLASS)
public class SwipeRefreshLayoutManager extends ViewGroupManager<ReactSwipeRefreshLayout>
implements AndroidSwipeRefreshLayoutManagerInterface<ReactSwipeRefreshLayout> {
public static final String REACT_CLASS = "AndroidSwipeRefreshLayout";
private final ViewManagerDelegate<ReactSwipeRefreshLayout> mDelegate;
public SwipeRefreshLayoutManager() {
mDelegate = new AndroidSwipeRefreshLayoutManagerDelegate<>(this);
}
@Override
protected ReactSwipeRefreshLayout createViewInstance(ThemedReactContext reactContext) {
return new ReactSwipeRefreshLayout(reactContext);
}
@Override
public String getName() {
return REACT_CLASS;
}
@Override
@ReactProp(name = ViewProps.ENABLED, defaultBoolean = true)
public void setEnabled(ReactSwipeRefreshLayout view, boolean enabled) {
view.setEnabled(enabled);
}
@Override
@ReactProp(name = "colors", customType = "ColorArray")
public void setColors(ReactSwipeRefreshLayout view, @Nullable ReadableArray colors) {
if (colors != null) {
int[] colorValues = new int[colors.size()];
for (int i = 0; i < colors.size(); i++) {
if (colors.getType(i) == ReadableType.Map) {
colorValues[i] = ColorPropConverter.getColor(colors.getMap(i), view.getContext());
} else {
colorValues[i] = colors.getInt(i);
}
}
view.setColorSchemeColors(colorValues);
} else {
view.setColorSchemeColors();
}
}
@Override
@ReactProp(name = "progressBackgroundColor", customType = "Color")
public void setProgressBackgroundColor(ReactSwipeRefreshLayout view, Integer color) {
view.setProgressBackgroundColorSchemeColor(color == null ? Color.TRANSPARENT : color);
}
// TODO(T46143833): Remove this method once the 'size' prop has been migrated to String in JS.
public void setSize(ReactSwipeRefreshLayout view, int value) {
view.setSize(value);
}
@Override
public void setSize(ReactSwipeRefreshLayout view, String size) {
if (size == null || size.equals("default")) {
view.setSize(SwipeRefreshLayout.DEFAULT);
} else if (size.equals("large")) {
view.setSize(SwipeRefreshLayout.LARGE);
} else {
throw new IllegalArgumentException("Size must be 'default' or 'large', received: " + size);
}
}
// This prop temporarily takes both 0 and 1 as well as 'default' and 'large'.
// 0 and 1 are deprecated and will be removed in a future release.
// See T46143833
@ReactProp(name = "size")
public void setSize(ReactSwipeRefreshLayout view, Dynamic size) {
if (size.isNull()) {
view.setSize(SwipeRefreshLayout.DEFAULT);
} else if (size.getType() == ReadableType.Number) {
view.setSize(size.asInt());
} else if (size.getType() == ReadableType.String) {
setSize(view, size.asString());
} else {
throw new IllegalArgumentException("Size must be 'default' or 'large'");
}
}
@Override
@ReactProp(name = "refreshing")
public void setRefreshing(ReactSwipeRefreshLayout view, boolean refreshing) {
view.setRefreshing(refreshing);
}
@Override
@ReactProp(name = "progressViewOffset", defaultFloat = 0)
public void setProgressViewOffset(final ReactSwipeRefreshLayout view, final float offset) {
view.setProgressViewOffset(offset);
}
@Override
public void setNativeRefreshing(ReactSwipeRefreshLayout view, boolean value) {
setRefreshing(view, value);
}
@Override
protected void addEventEmitters(
final ThemedReactContext reactContext, final ReactSwipeRefreshLayout view) {
view.setOnRefreshListener(
new OnRefreshListener() {
@Override
public void onRefresh() {
EventDispatcher eventDispatcher =
UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.getId());
if (eventDispatcher != null) {
eventDispatcher.dispatchEvent(
new RefreshEvent(UIManagerHelper.getSurfaceId(view), view.getId()));
}
}
});
}
@Override
public void receiveCommand(
@NonNull ReactSwipeRefreshLayout root, String commandId, @Nullable ReadableArray args) {
switch (commandId) {
case "setNativeRefreshing":
if (args != null) {
setRefreshing(root, args.getBoolean(0));
}
break;
}
}
@Nullable
@Override
public Map<String, Object> getExportedViewConstants() {
return MapBuilder.<String, Object>of(
"SIZE",
MapBuilder.of("DEFAULT", SwipeRefreshLayout.DEFAULT, "LARGE", SwipeRefreshLayout.LARGE));
}
@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
@Nullable
Map<String, Object> baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants();
Map<String, Object> eventTypeConstants =
baseEventTypeConstants == null ? new HashMap<String, Object>() : baseEventTypeConstants;
eventTypeConstants.putAll(
MapBuilder.<String, Object>builder()
.put("topRefresh", MapBuilder.of("registrationName", "onRefresh"))
.build());
return eventTypeConstants;
}
@Override
protected ViewManagerDelegate<ReactSwipeRefreshLayout> getDelegate() {
return mDelegate;
}
}
@@ -0,0 +1,153 @@
/*
* 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.views.swiperefresh
import android.graphics.Color
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.facebook.react.bridge.ColorPropConverter
import com.facebook.react.bridge.Dynamic
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableType
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.ViewManagerDelegate
import com.facebook.react.uimanager.ViewProps
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.viewmanagers.AndroidSwipeRefreshLayoutManagerDelegate
import com.facebook.react.viewmanagers.AndroidSwipeRefreshLayoutManagerInterface
import java.util.HashMap
/**
* ViewManager for [ReactSwipeRefreshLayout] which allows the user to "pull to refresh" a child
* view. Emits an `onRefresh` event when this happens.
*/
@ReactModule(name = SwipeRefreshLayoutManager.REACT_CLASS)
internal open class SwipeRefreshLayoutManager :
ViewGroupManager<ReactSwipeRefreshLayout>(),
AndroidSwipeRefreshLayoutManagerInterface<ReactSwipeRefreshLayout> {
private val delegate: ViewManagerDelegate<ReactSwipeRefreshLayout> =
AndroidSwipeRefreshLayoutManagerDelegate(this)
override fun createViewInstance(reactContext: ThemedReactContext): ReactSwipeRefreshLayout =
ReactSwipeRefreshLayout(reactContext)
override fun getName(): String = REACT_CLASS
@ReactProp(name = ViewProps.ENABLED, defaultBoolean = true)
override fun setEnabled(view: ReactSwipeRefreshLayout, enabled: Boolean) {
view.isEnabled = enabled
}
@ReactProp(name = "colors", customType = "ColorArray")
override fun setColors(view: ReactSwipeRefreshLayout, colors: ReadableArray?) {
if (colors != null) {
val colorValues = IntArray(colors.size())
for (i in 0..<colors.size()) {
if (colors.getType(i) == ReadableType.Map) {
colorValues[i] = ColorPropConverter.getColor(colors.getMap(i), view.context)
} else {
colorValues[i] = colors.getInt(i)
}
}
view.setColorSchemeColors(*colorValues)
} else {
view.setColorSchemeColors()
}
}
@ReactProp(name = "progressBackgroundColor", customType = "Color")
override fun setProgressBackgroundColor(view: ReactSwipeRefreshLayout, color: Int?) {
view.setProgressBackgroundColorSchemeColor(color ?: Color.TRANSPARENT)
}
// TODO(T46143833): Remove this method once the 'size' prop has been migrated to String in JS.
fun setSize(view: ReactSwipeRefreshLayout, value: Int): Unit {
view.setSize(value)
}
override fun setSize(view: ReactSwipeRefreshLayout, size: String?) {
if (size == null || size.equals("default")) {
view.setSize(SwipeRefreshLayout.DEFAULT)
} else if (size.equals("large")) {
view.setSize(SwipeRefreshLayout.LARGE)
} else {
throw IllegalArgumentException("Size must be 'default' or 'large', received: $size")
}
}
// This prop temporarily takes both 0 and 1 as well as 'default' and 'large'.
// 0 and 1 are deprecated and will be removed in a future release.
// See T46143833
@ReactProp(name = "size")
fun setSize(view: ReactSwipeRefreshLayout, size: Dynamic): Unit {
when {
size.isNull -> view.setSize(SwipeRefreshLayout.DEFAULT)
size.type == ReadableType.Number -> view.setSize(size.asInt())
size.type == ReadableType.String -> this.setSize(view, size.asString())
else -> throw IllegalArgumentException("Size must be 'default' or 'large'")
}
}
@ReactProp(name = "refreshing")
override fun setRefreshing(view: ReactSwipeRefreshLayout, refreshing: Boolean) {
view.isRefreshing = refreshing
}
@ReactProp(name = "progressViewOffset", defaultFloat = 0f)
override fun setProgressViewOffset(view: ReactSwipeRefreshLayout, offset: Float) {
view.setProgressViewOffset(offset)
}
override fun setNativeRefreshing(view: ReactSwipeRefreshLayout, value: Boolean) {
setRefreshing(view, value)
}
override fun addEventEmitters(reactContext: ThemedReactContext, view: ReactSwipeRefreshLayout) {
view.setOnRefreshListener {
val eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.id)
eventDispatcher?.dispatchEvent(RefreshEvent(UIManagerHelper.getSurfaceId(view), view.id))
}
}
override fun receiveCommand(
root: ReactSwipeRefreshLayout,
commandId: String,
args: ReadableArray?
) {
when (commandId) {
"setNativeRefreshing" ->
if (args != null) {
setRefreshing(root, args.getBoolean(0))
}
else -> {}
}
}
override fun getExportedViewConstants(): MutableMap<String, Any> =
mutableMapOf(
"SIZE" to
mutableMapOf(
"DEFAULT" to SwipeRefreshLayout.DEFAULT, "LARGE" to SwipeRefreshLayout.LARGE))
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
val baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants()
val eventTypeConstants: MutableMap<String, Any> = baseEventTypeConstants ?: HashMap()
eventTypeConstants.putAll(
mutableMapOf("topRefresh" to mutableMapOf("registrationName" to "onRefresh")))
return eventTypeConstants
}
override fun getDelegate(): ViewManagerDelegate<ReactSwipeRefreshLayout> = delegate
companion object {
const val REACT_CLASS: String = "AndroidSwipeRefreshLayout"
}
}