/* * 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(), AndroidSwipeRefreshLayoutManagerInterface { private val delegate: ViewManagerDelegate = 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.. 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 = mutableMapOf( "SIZE" to mutableMapOf( "DEFAULT" to SwipeRefreshLayout.DEFAULT, "LARGE" to SwipeRefreshLayout.LARGE)) override fun getExportedCustomDirectEventTypeConstants(): MutableMap { val baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants() val eventTypeConstants: MutableMap = baseEventTypeConstants ?: HashMap() eventTypeConstants.putAll( mutableMapOf("topRefresh" to mutableMapOf("registrationName" to "onRefresh"))) return eventTypeConstants } override fun getDelegate(): ViewManagerDelegate = delegate companion object { const val REACT_CLASS: String = "AndroidSwipeRefreshLayout" } }