Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: migrate GPHGridView to new arch #133

Merged
merged 2 commits into from
Jul 27, 2023
Merged
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
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'com.giphy.sdk:ui:2.3.6-hotfix-grid'
implementation 'com.giphy.sdk:ui:2.3.8'
}

if (isNewArchitectureEnabled()) {
Expand Down
2 changes: 2 additions & 0 deletions android/registration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace facebook {
concreteComponentDescriptorProvider<RTNGiphyMediaViewComponentDescriptor>());
providerRegistry->add(
concreteComponentDescriptorProvider<RTNGiphyVideoViewComponentDescriptor>());
providerRegistry->add(
concreteComponentDescriptorProvider<RTNGiphyGridViewComponentDescriptor>());
}
}
}
Expand Down
125 changes: 125 additions & 0 deletions android/src/main/java/com/giphyreactnativesdk/RTNGiphyGridView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package com.giphyreactnativesdk

import android.content.Context
import android.util.AttributeSet
import android.widget.FrameLayout
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.uimanager.ThemedReactContext
import com.giphy.sdk.core.models.enums.MediaType
import com.giphy.sdk.core.models.enums.RatingType
import com.giphy.sdk.core.models.enums.RenditionType
import com.giphy.sdk.ui.GPHRequestType
import com.giphy.sdk.ui.pagination.GPHContent
import com.giphy.sdk.ui.themes.GPHTheme
import com.giphy.sdk.ui.views.GiphyGridView
import com.giphyreactnativesdk.dto.RTNGiphyRating
import com.giphyreactnativesdk.dto.RTNGiphyRendition

class RTNGiphyGridView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {
companion object {
val DEFAULT_RENDITION_TYPE = RenditionType.fixedWidth
}

lateinit var gridView: GiphyGridView
private var renditionType = DEFAULT_RENDITION_TYPE
private var clipsPreviewRenditionType = DEFAULT_RENDITION_TYPE

init {
prepareLayout()
}

private fun prepareLayout() {
val activity = (context as? ThemedReactContext)?.currentActivity
gridView = GiphyGridView(activity ?: context)
addView(gridView)
}

override fun requestLayout() {
super.requestLayout()
post(measureAndLayout)
}

private val measureAndLayout = Runnable {
measure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
)
layout(left, top, right, bottom)
}

fun setContent(value: ReadableMap?) {
val content = GPHContent()
val query = value?.getString("searchQuery")
val requestType = value?.getString("requestType")
val mediaType = value?.getString("mediaType")

if (requestType != null) {
content.requestType = GPHRequestType.values().firstOrNull { it.name == requestType }
?: GPHRequestType.search

if (content.requestType == GPHRequestType.recents) {
gridView.content = GPHContent.recents
return
}
}

content.rating = RTNGiphyRating.fromRNValue(value?.getString("rating")) ?: RatingType.pg13

if (query != null) {
content.searchQuery = query
}

if (mediaType != null) {
content.mediaType = MediaType.values().firstOrNull { it.name == mediaType } ?: MediaType.gif
}

gridView.content = content
}

fun setCellPadding(value: Int?) {
if (value != null) {
gridView.cellPadding = value
}
}

fun setFixedSizeCells(value: Boolean?) {
if (value != null) {
gridView.fixedSizeCells = value
}
}

fun setOrientation(value: String?) {
gridView.direction = when (value) {
"horizontal" -> GiphyGridView.HORIZONTAL
"vertical" -> GiphyGridView.VERTICAL
else -> GiphyGridView.VERTICAL
}
}

fun setSpanCount(value: Int?) {
if (value != null) {
gridView.spanCount = value
}
}

fun setRenditionType(value: String?) {
renditionType = RTNGiphyRendition.fromRNValue(value) ?: DEFAULT_RENDITION_TYPE
}

fun setClipsPreviewRenditionType(value: String?) {
clipsPreviewRenditionType = RTNGiphyRendition.fromRNValue(value) ?: DEFAULT_RENDITION_TYPE
}

fun setShowCheckeredBackground(value: Boolean?) {
gridView.showCheckeredBackground = value ?: false
}

fun setTheme(value: ReadableMap?) {
RTNGiphyTheme(context, value).applyToGPHCustomTheme()
gridView.theme = GPHTheme.Custom
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package com.giphyreactnativesdk

import com.facebook.react.bridge.JSONArguments
import com.facebook.react.bridge.ReactMethod
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.annotations.ReactProp
import com.giphy.sdk.core.models.Media
import com.giphy.sdk.core.models.enums.MediaType
import com.giphy.sdk.core.models.enums.RenditionType
import com.giphy.sdk.ui.views.GPHGridCallback
import com.giphy.sdk.ui.views.GPHSearchGridCallback
import com.giphy.sdk.ui.views.GifView
import com.giphyreactnativesdk.events.OnGridContentUpdateEvent
import com.giphyreactnativesdk.events.OnGridMediaSelectEvent
import com.giphyreactnativesdk.events.OnGridScrollEvent

@ReactModule(name = RTNGiphyGridViewManager.NAME)
class RTNGiphyGridViewManager :
RTNGiphyGridViewManagerSpec<RTNGiphyGridView>() {
private var _renditionType = RenditionType.downsized
private var _clipsPreviewRenditionType = RenditionType.downsized

override fun getName() = NAME

override fun createViewInstance(context: ThemedReactContext): RTNGiphyGridView {
val view = RTNGiphyGridView(context)
view.gridView.callback = getGridCallback(view, context)
view.gridView.searchCallback = getSearchGridCallback(view, context)
return view
}

@ReactProp(name = "theme")
override fun setTheme(view: RTNGiphyGridView?, value: String?) {
if (value.isNullOrEmpty()) {
view?.setTheme(null)
} else {
view?.setTheme(JSONArguments.fromJSONObjectString(value))
}
}

@ReactProp(name = "spanCount")
override fun setSpanCount(view: RTNGiphyGridView?, value: Int) {
view?.setSpanCount(value)
}

@ReactProp(name = "showCheckeredBackground")
override fun setShowCheckeredBackground(view: RTNGiphyGridView?, value: Boolean) {
view?.setShowCheckeredBackground(value)
}

@ReactProp(name = "renditionType")
override fun setRenditionType(view: RTNGiphyGridView?, value: String?) {
view?.setRenditionType(value)
}

@ReactProp(name = "orientation")
override fun setOrientation(view: RTNGiphyGridView?, value: String?) {
view?.setOrientation(value)
}

@ReactProp(name = "fixedSizeCells")
override fun setFixedSizeCells(view: RTNGiphyGridView?, value: Boolean) {
view?.setFixedSizeCells(value)
}

@ReactProp(name = "content")
override fun setContent(view: RTNGiphyGridView?, value: String?) {
if (value.isNullOrEmpty()) {
view?.setContent(null)
} else {
view?.setContent(JSONArguments.fromJSONObjectString(value))
}
}

@ReactProp(name = "clipsPreviewRenditionType")
override fun setClipsPreviewRenditionType(view: RTNGiphyGridView?, value: String?) {
view?.setClipsPreviewRenditionType(value)
}

@ReactProp(name = "cellPadding")
override fun setCellPadding(view: RTNGiphyGridView?, value: Int) {
view?.setCellPadding(value)
}

private fun getGridCallback(
view: RTNGiphyGridView,
context: ThemedReactContext
): GPHGridCallback {
return object : GPHGridCallback {
override fun contentDidUpdate(resultCount: Int) {
val surfaceId = UIManagerHelper.getSurfaceId(view)
val event = OnGridContentUpdateEvent(surfaceId, view.id, resultCount)
UIManagerHelper.getEventDispatcherForReactTag(context, view.id)?.dispatchEvent(event)
}

override fun didSelectMedia(media: Media) {
val surfaceId = UIManagerHelper.getSurfaceId(view)
val isVideo = media.type == MediaType.video
val mediaRenditionType = if (isVideo) _clipsPreviewRenditionType else _renditionType
val event = OnGridMediaSelectEvent(surfaceId, view.id, media, mediaRenditionType)
UIManagerHelper.getEventDispatcherForReactTag(context, view.id)?.dispatchEvent(event)
}
}
}

private fun getSearchGridCallback(
view: RTNGiphyGridView,
context: ThemedReactContext
): GPHSearchGridCallback {
return object : GPHSearchGridCallback {
override fun didTapUsername(username: String) {
// pass
}

override fun didLongPressCell(cell: GifView) {
// pass
}

override fun didScroll(dx: Int, dy: Int) {
val surfaceId = UIManagerHelper.getSurfaceId(view)
val event = OnGridScrollEvent(surfaceId, view.id, dy.toDouble())
UIManagerHelper.getEventDispatcherForReactTag(context, view.id)?.dispatchEvent(event)
}
}
}

override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
val export = super.getExportedCustomDirectEventTypeConstants() ?: MapBuilder.newHashMap()

export[OnGridContentUpdateEvent.EVENT_NAME] =
MapBuilder.of("registrationName", "onContentUpdate")
export[OnGridMediaSelectEvent.EVENT_NAME] =
MapBuilder.of("registrationName", "onMediaSelect")
export[OnGridScrollEvent.EVENT_NAME] =
MapBuilder.of("registrationName", "onScroll")

return export
}

@Suppress("unused", "UNUSED_PARAMETER")
@ReactMethod
fun addListener(eventName: String?) {
// Keep: Required for RN built in Event Emitter Calls.
}

@Suppress("unused", "UNUSED_PARAMETER")
@ReactMethod
fun removeListeners(count: Int?) {
// Keep: Required for RN built in Event Emitter Calls.
}

companion object {
const val NAME = "RTNGiphyGridView"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.annotations.ReactProp

@Suppress("unused")
@ReactModule(name = RTNGiphyMediaViewManager.NAME)
class RTNGiphyMediaViewManager :
RTNGiphyMediaViewManagerSpec<RTNGiphyMediaView>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class RTNGiphySdkPackage : TurboReactPackage() {
val viewManagers: MutableList<ViewManager<*, *>> = ArrayList()
viewManagers.add(RTNGiphyMediaViewManager())
viewManagers.add(RTNGiphyVideoViewManager())
viewManagers.add(RTNGiphyGridViewManager())
return viewManagers
}

Expand Down
22 changes: 11 additions & 11 deletions android/src/main/java/com/giphyreactnativesdk/RTNGiphyVideoView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import com.giphy.sdk.ui.utils.GPHAbstractVideoPlayer
import com.giphy.sdk.ui.utils.GPHPlayerStateListener
import com.giphy.sdk.ui.utils.GPHVideoPlayerState
import com.giphy.sdk.ui.views.GPHVideoPlayerView
import com.giphyreactnativesdk.events.OnErrorEvent
import com.giphyreactnativesdk.events.OnMuteEvent
import com.giphyreactnativesdk.events.OnPlaybackStateChangeEvent
import com.giphyreactnativesdk.events.OnUnmuteEvent
import com.giphyreactnativesdk.events.OnPlayerErrorEvent
import com.giphyreactnativesdk.events.OnPlayerMuteEvent
import com.giphyreactnativesdk.events.OnPlayerPlaybackStateChangeEvent
import com.giphyreactnativesdk.events.OnPlayerUnmuteEvent
import com.giphyreactnativesdk.events.RTNGiphyVideoPlaybackState
import timber.log.Timber

Expand Down Expand Up @@ -104,7 +104,7 @@ class RTNGiphyVideoView @JvmOverloads constructor(
is GPHVideoPlayerState.Ready -> {
syncRNState()
dispatchEvent(
OnPlaybackStateChangeEvent(
OnPlayerPlaybackStateChangeEvent(
surfaceId,
this.id,
RTNGiphyVideoPlaybackState.ReadyToPlay
Expand All @@ -114,7 +114,7 @@ class RTNGiphyVideoView @JvmOverloads constructor(

is GPHVideoPlayerState.Playing -> {
dispatchEvent(
OnPlaybackStateChangeEvent(
OnPlayerPlaybackStateChangeEvent(
surfaceId,
this.id,
RTNGiphyVideoPlaybackState.Playing
Expand All @@ -124,7 +124,7 @@ class RTNGiphyVideoView @JvmOverloads constructor(

is GPHVideoPlayerState.Error -> {
dispatchEvent(
OnErrorEvent(
OnPlayerErrorEvent(
surfaceId,
this.id, it.details
)
Expand All @@ -133,14 +133,14 @@ class RTNGiphyVideoView @JvmOverloads constructor(

is GPHVideoPlayerState.MuteChanged -> {
if (it.muted) {
dispatchEvent(OnUnmuteEvent(surfaceId, this.id))
dispatchEvent(OnPlayerUnmuteEvent(surfaceId, this.id))
} else {
dispatchEvent(OnMuteEvent(surfaceId, this.id))
dispatchEvent(OnPlayerMuteEvent(surfaceId, this.id))
}
}

is GPHVideoPlayerState.Unknown -> dispatchEvent(
OnPlaybackStateChangeEvent(
OnPlayerPlaybackStateChangeEvent(
surfaceId,
this.id,
RTNGiphyVideoPlaybackState.Unknown
Expand All @@ -153,7 +153,7 @@ class RTNGiphyVideoView @JvmOverloads constructor(

if (videoPlayer?.paused == true) {
dispatchEvent(
OnPlaybackStateChangeEvent(
OnPlayerPlaybackStateChangeEvent(
surfaceId,
this.id,
RTNGiphyVideoPlaybackState.Paused
Expand Down
Loading
Loading