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: feat: migrate GPHDialog to new arch #132

Merged
merged 3 commits into from
Jul 25, 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
205 changes: 205 additions & 0 deletions android/src/main/java/com/giphyreactnativesdk/RTNGiphyDialogModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package com.giphyreactnativesdk

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.WritableMap
import com.facebook.react.modules.core.DeviceEventManagerModule
import com.giphy.sdk.core.models.Media
import com.giphy.sdk.core.models.enums.RatingType
import com.giphy.sdk.ui.GPHContentType
import com.giphy.sdk.ui.GPHSettings
import com.giphy.sdk.ui.themes.GPHTheme
import com.giphy.sdk.ui.views.GiphyDialogFragment
import com.giphyreactnativesdk.dto.RTNGiphyContentType
import com.giphyreactnativesdk.dto.RTNGiphyMedia
import com.giphyreactnativesdk.dto.RTNGiphyRating
import com.giphyreactnativesdk.dto.RTNGiphyRendition
import com.giphyreactnativesdk.utils.getVideoPlayerFactory
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch


private enum class RTNDialogProps(val key: String) {
CLIPS_PREVIEW_RENDITION_TYPE("clipsPreviewRenditionType"),
CONFIRMATION_RENDITION_TYPE("confirmationRenditionType"),
ENABLE_DYNAMIC_TEXT("enableDynamicText"),
MEDIA_TYPE_CONFIG("mediaTypeConfig"),
RATING("rating"),
RENDITION_TYPE("renditionType"),
SELECTED_CONTENT_TYPE("selectedContentType"),
SHOW_CHECKERED_BACKGROUND("showCheckeredBackground"),
SHOW_CONFIRMATION_SCREEN("showConfirmationScreen"),
SHOW_SUGGESTIONS_BAR("showSuggestionsBar"),
STICKER_COLUMN_COUNT("stickerColumnCount"),
}

private fun giphyDialogSettingsFromRNValue(
options: ReadableMap,
context: Context,
initialSettings: GPHSettings? = null
): GPHSettings {
val settings = initialSettings?.copy() ?: GPHSettings()

RTNGiphyTheme(context, options.getMap("theme")).applyToGPHCustomTheme()
settings.theme = GPHTheme.Custom

if (options.hasKey(RTNDialogProps.RENDITION_TYPE.key)) {
settings.renditionType = RTNGiphyRendition.fromRNValue(
options.getString(RTNDialogProps.RENDITION_TYPE.key)
)
}

if (options.hasKey(RTNDialogProps.CONFIRMATION_RENDITION_TYPE.key)) {
settings.confirmationRenditionType = RTNGiphyRendition.fromRNValue(
options.getString(RTNDialogProps.CONFIRMATION_RENDITION_TYPE.key)
)
}

if (options.hasKey(RTNDialogProps.RATING.key)) {
val rawRating = options.getString(RTNDialogProps.RATING.key)
settings.rating = RTNGiphyRating.fromRNValue(rawRating) ?: RatingType.pg13
}

if (options.hasKey(RTNDialogProps.SHOW_CONFIRMATION_SCREEN.key)) {
settings.showConfirmationScreen = options.getBoolean(
RTNDialogProps.SHOW_CONFIRMATION_SCREEN.key
)
}

if (options.hasKey(RTNDialogProps.SHOW_SUGGESTIONS_BAR.key)) {
settings.showSuggestionsBar = options.getBoolean(RTNDialogProps.SHOW_SUGGESTIONS_BAR.key)
}

if (options.hasKey(RTNDialogProps.SELECTED_CONTENT_TYPE.key)) {
settings.selectedContentType = RTNGiphyContentType.fromRNValue(
options.getString(RTNDialogProps.SELECTED_CONTENT_TYPE.key)
)
}

if (options.hasKey(RTNDialogProps.MEDIA_TYPE_CONFIG.key)) {
val typeConfig =
options.getArray(RTNDialogProps.MEDIA_TYPE_CONFIG.key)?.toArrayList()?.map { ctype ->
RTNGiphyContentType.fromRNValue(ctype.toString())
}?.toTypedArray()

if (typeConfig != null) {
settings.mediaTypeConfig = typeConfig
}
}

if (options.hasKey(RTNDialogProps.ENABLE_DYNAMIC_TEXT.key)) {
settings.enableDynamicText = options.getBoolean(
RTNDialogProps.ENABLE_DYNAMIC_TEXT.key
)
}

if (options.hasKey(RTNDialogProps.SHOW_CHECKERED_BACKGROUND.key)) {
settings.showCheckeredBackground = options.getBoolean(
RTNDialogProps.SHOW_CHECKERED_BACKGROUND.key
)
}

if (options.hasKey(RTNDialogProps.STICKER_COLUMN_COUNT.key)) {
settings.stickerColumnCount = options.getInt(RTNDialogProps.STICKER_COLUMN_COUNT.key)
}

if (options.hasKey(RTNDialogProps.CLIPS_PREVIEW_RENDITION_TYPE.key)) {
settings.clipsPreviewRenditionType = RTNGiphyRendition.fromRNValue(
options.getString(RTNDialogProps.CLIPS_PREVIEW_RENDITION_TYPE.key)
)
}

return settings
}

class RTNGiphyDialogModule internal constructor(context: ReactApplicationContext) :
RTNGiphyDialogModuleSpec(context) {
private var settings: GPHSettings = GPHSettings()
private var gifsDialog: GiphyDialogFragment? = null

override fun getName() = NAME

private fun initializeDialog() {
gifsDialog = GiphyDialogFragment.newInstance(
settings,
videoPlayer = getVideoPlayerFactory()
)
}

@ReactMethod
override fun configure(options: ReadableMap?) {
if (options == null) {
return
}
settings = giphyDialogSettingsFromRNValue(
options,
reactApplicationContext,
settings
)
}

@ReactMethod
override fun show() {
GlobalScope.launch(Dispatchers.Main) {
initializeDialog()

val compatActivity: AppCompatActivity = currentActivity as AppCompatActivity
val fragmentManager = compatActivity.supportFragmentManager

gifsDialog!!.gifSelectionListener = getGifSelectionListener()
gifsDialog!!.show(fragmentManager, "giphy_view")
}
}

@ReactMethod
override fun hide() {
GlobalScope.launch(Dispatchers.Main) {
gifsDialog!!.dismiss()
}
}

private fun getGifSelectionListener() = object : GiphyDialogFragment.GifSelectionListener {
override fun onGifSelected(
media: Media,
searchTerm: String?,
selectedContentType: GPHContentType
) {
val params = Arguments.createMap()
params.putMap("media", RTNGiphyMedia.toRNValue(media, settings.renditionType))
sendEvent("onMediaSelect", params)
}

override fun onDismissed(selectedContentType: GPHContentType) {
sendEvent("onDismiss", Arguments.createMap())
}

override fun didSearchTerm(term: String) {}
}

private fun sendEvent(eventName: String, params: WritableMap) {
if (!reactApplicationContext.hasActiveReactInstance()) {
return
}
reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit(eventName, params)
}

@ReactMethod
override fun addListener(eventType: String?) {
// Keep: Required for RN RCTEventEmitter class (iOS).
}

@ReactMethod
override fun removeListeners(count: Double) {
// Keep: Required for RN RCTEventEmitter class (iOS).
}

companion object {
const val NAME = "RTNGiphyDialogModule"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.giphy.sdk.ui.Giphy
import com.giphyreactnativesdk.utils.getVideoPlayerFactory
import com.giphyreactnativesdk.utils.initializeVideoCache

class RTNGiphySDKModuleImpl internal constructor(context: ReactApplicationContext) :
class RTNGiphySdkModule internal constructor(context: ReactApplicationContext) :
RTNGiphySdkModuleSpec(context) {
override fun getName() = NAME

Expand Down
33 changes: 23 additions & 10 deletions android/src/main/java/com/giphyreactnativesdk/RTNGiphySdkPackage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ import com.facebook.react.uimanager.ViewManager
class RTNGiphySdkPackage : TurboReactPackage() {
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
return when (name) {
RTNGiphySDKModuleImpl.NAME -> {
RTNGiphySDKModuleImpl(reactContext)
RTNGiphySdkModule.NAME -> {
RTNGiphySdkModule(reactContext)
}

RTNGiphyVideoManagerImpl.NAME -> {
RTNGiphyVideoManagerImpl(reactContext)
RTNGiphyDialogModule.NAME -> {
RTNGiphyDialogModule(reactContext)
}

RTNGiphyVideoManager.NAME -> {
RTNGiphyVideoManager(reactContext)
}

else -> {
Expand All @@ -36,18 +40,27 @@ class RTNGiphySdkPackage : TurboReactPackage() {
return ReactModuleInfoProvider {
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
moduleInfos[RTNGiphySDKModuleImpl.NAME] = ReactModuleInfo(
RTNGiphySDKModuleImpl.NAME,
RTNGiphySDKModuleImpl.NAME,
moduleInfos[RTNGiphySdkModule.NAME] = ReactModuleInfo(
RTNGiphySdkModule.NAME,
RTNGiphySdkModule.NAME,
false,
false,
true,
false,
isTurboModule
)
moduleInfos[RTNGiphyDialogModule.NAME] = ReactModuleInfo(
RTNGiphyDialogModule.NAME,
RTNGiphyDialogModule.NAME,
false,
false,
true,
false,
isTurboModule
)
moduleInfos[RTNGiphyVideoManagerImpl.NAME] = ReactModuleInfo(
RTNGiphyVideoManagerImpl.NAME,
RTNGiphyVideoManagerImpl.NAME,
moduleInfos[RTNGiphyVideoManager.NAME] = ReactModuleInfo(
RTNGiphyVideoManager.NAME,
RTNGiphyVideoManager.NAME,
false,
false,
true,
Expand Down
125 changes: 125 additions & 0 deletions android/src/main/java/com/giphyreactnativesdk/RTNGiphyTheme.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package com.giphyreactnativesdk

import android.content.Context
import com.facebook.react.bridge.ReadableMap
import com.giphy.sdk.ui.themes.GPHCustomTheme
import com.giphy.sdk.ui.themes.GPHTheme
import com.giphy.sdk.ui.themes.Theme
import com.giphyreactnativesdk.utils.CaseConverter

val DEFAULT_PRESET = GPHTheme.Light

class RTNGiphyTheme(context: Context, private var config: ReadableMap?) {
private var preset: Theme

init {
val presetTheme = gphThemeByName(config?.getString("preset")) ?: DEFAULT_PRESET
preset = presetTheme.getThemeResources(context)
}

fun applyToGPHCustomTheme() {
GPHCustomTheme.apply {
// region dialog's handle

handleBarColor = getIntOrPreset("handleBarColor")

// endregion

// region emoji drawer
emojiDrawerGradientTopColor = getIntOrPreset("emojiDrawerGradientTopColor")
emojiDrawerGradientBottomColor = getIntOrPreset("emojiDrawerGradientBottomColor")
emojiDrawerSeparatorColor = getIntOrPreset("emojiDrawerSeparatorColor")
// endregion

// region search bar
searchBackButtonColor = getIntOrPreset("searchBackButtonColor")
searchBarBackgroundColor = getIntOrPreset("searchBarBackgroundColor")
searchTextColor = getIntOrPreset("searchTextColor")
searchPlaceholderTextColor = getIntOrPreset("searchPlaceholderTextColor")
// endregion

// region suggestions
suggestionCellBackgroundColor = getIntOrPreset("suggestionCellBackgroundColor")
suggestionCellTextColor = getIntOrPreset("suggestionCellTextColor")
// endregion

// region tab bar
tabBarSwitchDefaultColor = getIntOrPreset("tabBarSwitchDefaultColor")
tabBarSwitchSelectedColor = getIntOrPreset("tabBarSwitchSelectedColor")
// endregion

// region confirmation
confirmationSelectButtonColor = getIntOrPreset("confirmationSelectButtonColor")
confirmationSelectButtonTextColor = getIntOrPreset("confirmationSelectButtonTextColor")
confirmationBackButtonColor = getIntOrPreset("confirmationBackButtonColor")
confirmationViewOnGiphyColor = getIntOrPreset("confirmationViewOnGiphyColor")
// endregion

// region other
defaultTextColor = getIntOrPreset("defaultTextColor")
dialogOverlayBackgroundColor = getIntOrPreset("dialogOverlayBackgroundColor")
backgroundColor = getIntOrPreset("backgroundColor")
usernameColor = getIntOrPreset("usernameColor")
retryButtonBackgroundColor = getIntOrOptionalPreset("retryButtonBackgroundColor")
retryButtonTextColor = getIntOrOptionalPreset("retryButtonTextColor")
// endregion
}
}

private fun getInt(field: String): Int? {
if (config == null || config?.hasKey(field) == false) {
return null
}
return config!!.getInt(field)
}

private fun getIntOrPreset(field: String): Int {
return getInt(field) ?: getPresetField(field) as Int
}

private fun getIntOrOptionalPreset(field: String): Int? {
return getInt(field) ?: getPresetField(field) as Int?
}

private fun getPresetField(field: String): Any? {
return when (field) {
"handleBarColor" -> preset.handleBarColor
"emojiDrawerGradientTopColor" -> preset.emojiDrawerGradientTopColor
"emojiDrawerGradientBottomColor" -> preset.emojiDrawerGradientBottomColor
"emojiDrawerSeparatorColor" -> preset.emojiDrawerSeparatorColor
"searchBarBackgroundColor" -> preset.searchBarBackgroundColor
"searchTextColor" -> preset.searchTextColor
"searchButtonIcon" -> preset.searchButtonIcon
"searchBackButtonColor" -> preset.searchBackButtonColor
"searchPlaceholderTextColor" -> preset.searchPlaceholderTextColor
"suggestionCellBackgroundColor" -> preset.suggestionCellBackgroundColor
"suggestionCellTextColor" -> preset.suggestionCellTextColor
"tabBarSwitchDefaultColor" -> preset.tabBarSwitchDefaultColor
"tabBarSwitchSelectedColor" -> preset.tabBarSwitchSelectedColor
"confirmationSelectButtonColor" -> preset.confirmationSelectButtonColor
"confirmationSelectButtonTextColor" -> preset.confirmationSelectButtonTextColor
"confirmationBackButtonColor" -> preset.confirmationBackButtonColor
"confirmationViewOnGiphyColor" -> preset.confirmationViewOnGiphyColor
"backgroundColor" -> preset.backgroundColor
"dialogOverlayBackgroundColor" -> preset.dialogOverlayBackgroundColor
"defaultTextColor" -> preset.defaultTextColor
"usernameColor" -> preset.usernameColor
"retryButtonBackgroundColor" -> preset.retryButtonBackgroundColor
"retryButtonTextColor" -> preset.retryButtonTextColor
else -> {
throw IllegalArgumentException("Unknown field: $field")
}
}
}

companion object {
private fun gphThemeByName(name: String?): GPHTheme? {
if (name == null) {
return null
}
return GPHTheme.values().firstOrNull {
it.name == CaseConverter.capitalize(name)
}
}
}
}
Loading
Loading