diff --git a/personalization-sdk/build.gradle b/personalization-sdk/build.gradle index cc291585..c62d71e5 100644 --- a/personalization-sdk/build.gradle +++ b/personalization-sdk/build.gradle @@ -96,6 +96,9 @@ dependencies { implementation("androidx.test:rules:1.6.1") implementation("androidx.test.ext:junit:1.2.1") + implementation("androidx.navigation:navigation-fragment-ktx:2.7.5") + implementation("androidx.navigation:navigation-ui-ktx:2.7.5") + implementation("com.google.android.gms:play-services-ads-identifier:17.0.0") kapt 'com.google.dagger:dagger-compiler:2.48' diff --git a/personalization-sdk/src/main/kotlin/com/personalization/api/managers/InAppNotificationManager.kt b/personalization-sdk/src/main/kotlin/com/personalization/api/managers/InAppNotificationManager.kt index e82919a9..721ecc08 100644 --- a/personalization-sdk/src/main/kotlin/com/personalization/api/managers/InAppNotificationManager.kt +++ b/personalization-sdk/src/main/kotlin/com/personalization/api/managers/InAppNotificationManager.kt @@ -13,54 +13,54 @@ interface InAppNotificationManager { fun showAlertDialog( title: String, message: String, - imageUrl: String, - buttonPositiveText: String, - buttonNegativeText: String, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - onPositiveClick: () -> Unit + imageUrl: String? = null, + buttonConfirmText: String? = null, + buttonDeclineText: String? = null, + buttonConfirmColor: Int? = null, + buttonDeclineColor: Int? = null, + onConfirmClick: (() -> Unit)? = null ) fun showFullScreenDialog( title: String, message: String, - imageUrl: String?, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - buttonPositiveText: String, - buttonNegativeText: String, - onPositiveClick: () -> Unit + imageUrl: String? = null, + buttonConfirmText: String? = null, + buttonDeclineText: String? = null, + buttonConfirmColor: Int? = null, + buttonDeclineColor: Int? = null, + onConfirmClick: (() -> Unit)? = null ) - fun showBottomSheetDialog( + fun showBottomDialog( title: String, message: String, - imageUrl: String?, - buttonPositiveText: String, - buttonNegativeText: String?, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - onPositiveClick: () -> Unit + imageUrl: String? = null, + buttonConfirmText: String? = null, + buttonDeclineText: String? = null, + buttonConfirmColor: Int? = null, + buttonDeclineColor: Int? = null, + onConfirmClick: (() -> Unit)? = null ) - fun showTopSheetDialog( + fun showTopDialog( title: String, message: String, - imageUrl: String?, - buttonPositiveText: String, - buttonNegativeText: String?, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - onPositiveClick: () -> Unit + imageUrl: String? = null, + buttonConfirmText: String? = null, + buttonDeclineText: String? = null, + buttonConfirmColor: Int? = null, + buttonDeclineColor: Int? = null, + onConfirmClick: (() -> Unit)? = null ) fun showSnackBar( view: View, message: String, - buttonPositiveText: String, - buttonNegativeText: String, - onPositiveClick: () -> Unit, - onNegativeClick: () -> Unit + buttonConfirmText: String, + buttonDeclineText: String, + onConfirmClick: () -> Unit, + onDeclineClick: () -> Unit ) } diff --git a/personalization-sdk/src/main/kotlin/com/personalization/features/inAppNotification/impl/InAppNotificationManagerImpl.kt b/personalization-sdk/src/main/kotlin/com/personalization/features/inAppNotification/impl/InAppNotificationManagerImpl.kt index 3c5e1c98..4e48c228 100644 --- a/personalization-sdk/src/main/kotlin/com/personalization/features/inAppNotification/impl/InAppNotificationManagerImpl.kt +++ b/personalization-sdk/src/main/kotlin/com/personalization/features/inAppNotification/impl/InAppNotificationManagerImpl.kt @@ -14,16 +14,22 @@ import androidx.fragment.app.FragmentManager import com.personalization.R import com.personalization.api.managers.InAppNotificationManager import com.personalization.errors.EmptyFieldError -import com.personalization.inAppNotification.view.component.dialog.AlertDialog -import com.personalization.inAppNotification.view.component.dialog.BottomSheetDialog -import com.personalization.inAppNotification.view.component.dialog.FullScreenDialog -import com.personalization.inAppNotification.view.component.dialog.TopSheetDialog +import com.personalization.inAppNotification.view.component.dialog.fullScreen.FULL_SCREEN_DIALOG_TAG +import com.personalization.inAppNotification.view.component.dialog.alert.ALERT_DIALOG_TAG +import com.personalization.inAppNotification.view.component.dialog.alert.AlertDialog +import com.personalization.inAppNotification.view.component.dialog.bottomSheet.BOTTOM_SHEET_TAG +import com.personalization.inAppNotification.view.component.dialog.bottomSheet.BottomSheetDialog +import com.personalization.inAppNotification.view.component.dialog.fullScreen.FullScreenDialog +import com.personalization.inAppNotification.view.component.dialog.topSheet.TOP_SHEET_DIALOG +import com.personalization.inAppNotification.view.component.dialog.topSheet.TopSheetDialog import com.personalization.inAppNotification.view.component.snackbar.Snackbar import com.personalization.sdk.data.models.dto.popUp.DialogDataDto import com.personalization.sdk.data.models.dto.popUp.PopupDto import com.personalization.sdk.data.models.dto.popUp.Position import com.personalization.ui.click.NotificationClickListener import javax.inject.Inject +import androidx.navigation.fragment.NavHostFragment + class InAppNotificationManagerImpl @Inject constructor( private val context: Context @@ -31,29 +37,70 @@ class InAppNotificationManagerImpl @Inject constructor( private lateinit var fragmentManager: FragmentManager + private lateinit var targetScreen: String + private var pendingPopupDto: PopupDto? = null + override fun initFragmentManager(fragmentManager: FragmentManager) { this.fragmentManager = fragmentManager + this.fragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true) } override fun shopPopUp(popupDto: PopupDto) { + targetScreen = popupDto.targetScreen.orEmpty() val dialogData = extractDialogData(popupDto) - showDialog(dialogData) + + if (targetScreen.isEmpty()) { + showDialog(dialogData) + } else { + pendingPopupDto = popupDto + } + } + + private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() { + override fun onFragmentResumed(fm: FragmentManager, f: androidx.fragment.app.Fragment) { + super.onFragmentResumed(fm, f) + logCurrentFragment() + } + } + private fun logCurrentFragment() { + if (!::fragmentManager.isInitialized) return + + val navHostFragment = fragmentManager.fragments + .filterNot { it is androidx.fragment.app.DialogFragment } + .firstOrNull { it is NavHostFragment } + + val currentFragment = (navHostFragment as? NavHostFragment) + ?.childFragmentManager + ?.fragments + ?.lastOrNull { it.isVisible } + + val fragmentName: String = currentFragment?.javaClass?.simpleName ?: "No visible fragment" + + val popupDto = pendingPopupDto + + if (fragmentName == popupDto?.targetScreen) { + val dialogData = extractDialogData(popupDto) + showDialog(dialogData) + pendingPopupDto = null + } + + android.util.Log.d("SDKSDK", "Current visible fragment: $fragmentName") } private fun extractDialogData(popupDto: PopupDto): DialogDataDto { val deepLink = popupDto.popupActions?.link?.linkAndroid ?: popupDto.popupActions?.link?.linkWeb - val buttonPositiveColor = ContextCompat.getColor(context, R.color.buttonAcceptColor) - val buttonNegativeColor = ContextCompat.getColor(context, R.color.colorGray) + val buttonConfirmColor = ContextCompat.getColor(context, R.color.buttonConfirmColor) + val buttonDeclineColor = ContextCompat.getColor(context, R.color.colorGray) val buttonSubscription = popupDto.popupActions?.pushSubscribe?.buttonText - val buttonNegativeText = popupDto.popupActions?.close?.buttonText - val buttonPositiveText = buttonSubscription ?: popupDto.popupActions?.link?.buttonText + val buttonDeclineText = popupDto.popupActions?.close?.buttonText + val buttonConfirmText = buttonSubscription ?: popupDto.popupActions?.link?.buttonText val imageUrl: String? = popupDto.components?.image val title: String? = popupDto.components?.header val message: String? = popupDto.components?.text val position: Position = popupDto.position - val onPositiveClick = if (buttonSubscription != null) { + val onConfirmClick = if (buttonSubscription != null) { { requestPushNotifications() } } else { { openUrlInBrowser(url = deepLink) } @@ -63,11 +110,11 @@ class InAppNotificationManagerImpl @Inject constructor( title = title.orEmpty(), message = message.orEmpty(), imageUrl = imageUrl.orEmpty(), - buttonPositiveColor = buttonPositiveColor, - buttonNegativeColor = buttonNegativeColor, - buttonPositiveText = buttonPositiveText.orEmpty(), - buttonNegativeText = buttonNegativeText.orEmpty(), - onPositiveClick = onPositiveClick, + buttonConfirmColor = buttonConfirmColor, + buttonDeclineColor = buttonDeclineColor, + buttonConfirmText = buttonConfirmText.orEmpty(), + buttonDeclineText = buttonDeclineText.orEmpty(), + onConfirmClick = onConfirmClick, position = position ) } @@ -78,44 +125,44 @@ class InAppNotificationManagerImpl @Inject constructor( title = dialogData.title, message = dialogData.message, imageUrl = dialogData.imageUrl, - buttonPositiveColor = dialogData.buttonPositiveColor, - buttonNegativeColor = dialogData.buttonNegativeColor, - buttonPositiveText = dialogData.buttonPositiveText, - buttonNegativeText = dialogData.buttonNegativeText, - onPositiveClick = dialogData.onPositiveClick + buttonConfirmColor = dialogData.buttonConfirmColor, + buttonDeclineColor = dialogData.buttonDeclineColor, + buttonConfirmText = dialogData.buttonConfirmText, + buttonDeclineText = dialogData.buttonDeclineText, + onConfirmClick = dialogData.onConfirmClick ) - Position.BOTTOM -> showBottomSheetDialog( + Position.BOTTOM -> showBottomDialog( title = dialogData.title, message = dialogData.message, imageUrl = dialogData.imageUrl, - buttonPositiveColor = dialogData.buttonPositiveColor, - buttonNegativeColor = dialogData.buttonNegativeColor, - buttonPositiveText = dialogData.buttonPositiveText, - buttonNegativeText = dialogData.buttonNegativeText, - onPositiveClick = dialogData.onPositiveClick + buttonConfirmColor = dialogData.buttonConfirmColor, + buttonDeclineColor = dialogData.buttonDeclineColor, + buttonConfirmText = dialogData.buttonConfirmText, + buttonDeclineText = dialogData.buttonDeclineText, + onConfirmClick = dialogData.onConfirmClick ) - Position.TOP -> showTopSheetDialog( + Position.TOP -> showTopDialog( title = dialogData.title, message = dialogData.message, imageUrl = dialogData.imageUrl, - buttonPositiveColor = dialogData.buttonPositiveColor, - buttonNegativeColor = dialogData.buttonNegativeColor, - buttonPositiveText = dialogData.buttonPositiveText, - buttonNegativeText = dialogData.buttonNegativeText, - onPositiveClick = dialogData.onPositiveClick + buttonConfirmColor = dialogData.buttonConfirmColor, + buttonDeclineColor = dialogData.buttonDeclineColor, + buttonConfirmText = dialogData.buttonConfirmText, + buttonDeclineText = dialogData.buttonDeclineText, + onConfirmClick = dialogData.onConfirmClick ) else -> showFullScreenDialog( title = dialogData.title, message = dialogData.message, imageUrl = dialogData.imageUrl, - buttonPositiveColor = dialogData.buttonPositiveColor, - buttonNegativeColor = dialogData.buttonNegativeColor, - buttonPositiveText = dialogData.buttonPositiveText, - buttonNegativeText = dialogData.buttonNegativeText, - onPositiveClick = dialogData.onPositiveClick + buttonConfirmColor = dialogData.buttonConfirmColor, + buttonDeclineColor = dialogData.buttonDeclineColor, + buttonConfirmText = dialogData.buttonConfirmText, + buttonDeclineText = dialogData.buttonDeclineText, + onConfirmClick = dialogData.onConfirmClick ) } } @@ -123,35 +170,37 @@ class InAppNotificationManagerImpl @Inject constructor( override fun showAlertDialog( title: String, message: String, - imageUrl: String, - buttonPositiveText: String, - buttonNegativeText: String, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - onPositiveClick: () -> Unit + imageUrl: String?, + buttonConfirmText: String?, + buttonDeclineText: String?, + buttonConfirmColor: Int?, + buttonDeclineColor: Int?, + onConfirmClick: (() -> Unit)? ) { val dialog = AlertDialog.newInstance( title = title, message = message, imageUrl = imageUrl, - buttonPositiveColor = buttonPositiveColor, - buttonNegativeColor = buttonNegativeColor, - buttonPositiveText = buttonPositiveText, - buttonNegativeText = buttonNegativeText, + buttonConfirmColor = buttonConfirmColor, + buttonDeclineColor = buttonDeclineColor, + buttonConfirmText = buttonConfirmText, + buttonDeclineText = buttonDeclineText ) - dialog.setListener( + dialog.listener = ( object : NotificationClickListener { - override fun onPositiveClick() = onPositiveClick() - override fun onNegativeClick() { + override fun onConfirmClick() { + onConfirmClick?.invoke() + } + override fun onDeclineClick() { dialog.dismiss() } } - ) + ) dialog.show( /* manager = */ fragmentManager, - /* tag = */ AlertDialog.TAG + /* tag = */ ALERT_DIALOG_TAG ) } @@ -159,121 +208,127 @@ class InAppNotificationManagerImpl @Inject constructor( title: String, message: String, imageUrl: String?, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - buttonPositiveText: String, - buttonNegativeText: String, - onPositiveClick: () -> Unit + buttonConfirmText: String?, + buttonDeclineText: String?, + buttonConfirmColor: Int?, + buttonDeclineColor: Int?, + onConfirmClick: (() -> Unit)? ) { val dialog = FullScreenDialog.newInstance( title = title, message = message, imageUrl = imageUrl, - buttonPositiveColor = buttonPositiveColor, - buttonNegativeColor = buttonNegativeColor, - buttonPositiveText = buttonPositiveText, - buttonNegativeText = buttonNegativeText, + buttonConfirmColor = buttonConfirmColor, + buttonDeclineColor = buttonDeclineColor, + buttonConfirmText = buttonConfirmText, + buttonDeclineText = buttonDeclineText, ) - dialog.setListener( + dialog.listener = ( object : NotificationClickListener { - override fun onPositiveClick() = onPositiveClick() - override fun onNegativeClick() { + override fun onConfirmClick() { + onConfirmClick?.invoke() + } + override fun onDeclineClick() { dialog.dismiss() } } - ) + ) dialog.show( /* manager = */ fragmentManager, - /* tag = */ FullScreenDialog.TAG + /* tag = */ FULL_SCREEN_DIALOG_TAG ) } - override fun showBottomSheetDialog( + override fun showBottomDialog( title: String, message: String, imageUrl: String?, - buttonPositiveText: String, - buttonNegativeText: String?, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - onPositiveClick: () -> Unit + buttonConfirmText: String?, + buttonDeclineText: String?, + buttonConfirmColor: Int?, + buttonDeclineColor: Int?, + onConfirmClick: (() -> Unit)? ) { val dialog = BottomSheetDialog.newInstance( title = title, message = message, imageUrl = imageUrl, - buttonPositiveColor = buttonPositiveColor, - buttonNegativeColor = buttonNegativeColor, - buttonPositiveText = buttonPositiveText, - buttonNegativeText = buttonNegativeText, + buttonConfirmColor = buttonConfirmColor, + buttonDeclineColor = buttonDeclineColor, + buttonConfirmText = buttonConfirmText, + buttonDeclineText = buttonDeclineText, ) - dialog.setListener( + dialog.listener = ( object : NotificationClickListener { - override fun onPositiveClick() = onPositiveClick() - override fun onNegativeClick() { + override fun onConfirmClick() { + onConfirmClick?.invoke() + } + override fun onDeclineClick() { dialog.dismiss() } } - ) + ) dialog.show( /* manager = */ fragmentManager, - /* tag = */ BottomSheetDialog.TAG + /* tag = */ BOTTOM_SHEET_TAG ) } - override fun showTopSheetDialog( + override fun showTopDialog( title: String, message: String, imageUrl: String?, - buttonPositiveText: String, - buttonNegativeText: String?, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - onPositiveClick: () -> Unit + buttonConfirmText: String?, + buttonDeclineText: String?, + buttonConfirmColor: Int?, + buttonDeclineColor: Int?, + onConfirmClick: (() -> Unit)? ) { val dialog = TopSheetDialog.newInstance( title = title, message = message, imageUrl = imageUrl, - buttonPositiveColor = buttonPositiveColor, - buttonNegativeColor = buttonNegativeColor, - buttonPositiveText = buttonPositiveText, - buttonNegativeText = buttonNegativeText, + buttonConfirmColor = buttonConfirmColor, + buttonDeclineColor = buttonDeclineColor, + buttonConfirmText = buttonConfirmText, + buttonDeclineText = buttonDeclineText, ) - dialog.setListener( + dialog.listener = ( object : NotificationClickListener { - override fun onPositiveClick() = onPositiveClick() - override fun onNegativeClick() { + override fun onConfirmClick() { + onConfirmClick?.invoke() + } + override fun onDeclineClick() { dialog.dismiss() } } - ) + ) dialog.show( /* manager = */ fragmentManager, - /* tag = */ TopSheetDialog.TAG + /* tag = */ TOP_SHEET_DIALOG ) } override fun showSnackBar( view: View, message: String, - buttonPositiveText: String, - buttonNegativeText: String, - onPositiveClick: () -> Unit, - onNegativeClick: () -> Unit + buttonConfirmText: String, + buttonDeclineText: String, + onConfirmClick: () -> Unit, + onDeclineClick: () -> Unit ) { Snackbar(view).show( message = message, - buttonPositiveText = buttonPositiveText, - buttonNegativeText = buttonNegativeText, - onPositiveClick = onPositiveClick, - onNegativeClick = onNegativeClick + buttonConfirmText = buttonConfirmText, + buttonDeclineText = buttonDeclineText, + onConfirmClick = onConfirmClick, + onDeclineClick = onDeclineClick ) } diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/container/InAppViewContainer.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/container/InAppViewContainer.kt new file mode 100644 index 00000000..561444c1 --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/container/InAppViewContainer.kt @@ -0,0 +1,18 @@ +package com.personalization.inAppNotification.view.component.container + +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import com.personalization.inAppNotification.view.component.image.ImageView + +interface InAppViewContainer { + val backgroundImageView: ImageView + val imageContainer: ViewGroup + val titleTextView: TextView + val messageTextView: TextView + val buttonConfirmContainer: ViewGroup + val buttonConfirm: TextView + val buttonDeclineContainer: ViewGroup + val buttonDecline: TextView + val closeButton: View +} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/AlertDialog.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/AlertDialog.kt deleted file mode 100644 index 3b572051..00000000 --- a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/AlertDialog.kt +++ /dev/null @@ -1,157 +0,0 @@ -package com.personalization.inAppNotification.view.component.dialog - -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.view.isVisible -import androidx.fragment.app.DialogFragment -import com.personalization.databinding.AlertDialogBinding -import com.personalization.ui.animation.button.addPressEffectDeclarative -import com.personalization.ui.click.NotificationClickListener - -class AlertDialog : DialogFragment() { - - private var listener: NotificationClickListener? = null - - fun setListener(listener: NotificationClickListener) { - this.listener = listener - } - - private var _binding: AlertDialogBinding? = null - private val binding get() = _binding!! - - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = AlertDialogBinding.inflate(inflater, container, false) - return binding.root - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - initImage() - initTextBlock() - initAcceptButton() - initDeclineButton() - handleClosingButton() - } - - private fun initTextBlock() { - with(binding) { - textContainer.apply { - title.text = arguments?.getString(TITLE_KEY).orEmpty() - message.text = arguments?.getString(MESSAGE_KEY).orEmpty() - } - } - } - - private fun initImage() { - val imageUrl = arguments?.getString(IMAGE_URL_KEY).orEmpty() - if (imageUrl.isNotBlank()) { - binding.backgroundImageView.loadImage(imageUrl) - } else { - binding.imageContainer.isVisible = false - } - } - - private fun initDeclineButton() { - val buttonText = arguments?.getString(BUTTON_NEGATIVE_TEXT_KEY).orEmpty() - val negativeButtonColor = arguments?.getInt(BUTTON_NEGATIVE_COLOR_KEY) - with(binding) { - buttonContainer.apply { - if(buttonText.isEmpty()) { - buttonDeclineContainer.isVisible = false - return - } - buttonDeclineContainer.addPressEffectDeclarative() - buttonDecline.text = buttonText - if (negativeButtonColor != null) { - buttonDecline.setBackgroundColor(negativeButtonColor) - } - buttonDeclineContainer.setOnClickListener { - onButtonClick(isPositiveClick = false) - } - } - } - } - - private fun initAcceptButton() { - val buttonText = arguments?.getString(BUTTON_POSITIVE_TEXT_KEY).orEmpty() - val positiveButtonColor = arguments?.getInt(BUTTON_POSITIVE_COLOR_KEY) - with(binding) { - buttonContainer.apply { - if(buttonText.isEmpty()){ - buttonAcceptContainer.isVisible = false - return - } - buttonAcceptContainer.addPressEffectDeclarative() - buttonAccept.text = buttonText - if (positiveButtonColor != null) { - buttonAccept.setBackgroundColor(positiveButtonColor) - } - buttonAcceptContainer.setOnClickListener { - onButtonClick(isPositiveClick = true) - } - } - } - } - - private fun handleClosingButton() { - with(binding) { - closeButton.addPressEffectDeclarative() - closeButton.setOnClickListener { dismiss() } - } - } - - private fun onButtonClick(isPositiveClick: Boolean) { - when (isPositiveClick) { - true -> listener?.onPositiveClick() - else -> listener?.onNegativeClick() - } - dismiss() - } - - companion object { - const val TAG = "AlertDialog" - const val TITLE_KEY = "TITLE_KEY" - const val MESSAGE_KEY = "MESSAGE_KEY" - const val IMAGE_URL_KEY = "IMAGE_URL_KEY" - const val BUTTON_POSITIVE_COLOR_KEY = "BUTTON_POSITIVE_COLOR_KEY" - const val BUTTON_NEGATIVE_COLOR_KEY = "BUTTON_NEGATIVE_COLOR_KEY" - const val BUTTON_POSITIVE_TEXT_KEY = "BUTTON_POSITIVE_TEXT_KEY" - const val BUTTON_NEGATIVE_TEXT_KEY = "BUTTON_NEGATIVE_TEXT_KEY" - - fun newInstance( - title: String, - message: String, - imageUrl: String, - buttonPositiveText: String, - buttonNegativeText: String, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - ): AlertDialog { - val dialog = AlertDialog() - val args = Bundle().apply { - putString(TITLE_KEY, title) - putString(MESSAGE_KEY, message) - putString(IMAGE_URL_KEY, imageUrl) - putInt(BUTTON_POSITIVE_COLOR_KEY, buttonPositiveColor) - putInt(BUTTON_NEGATIVE_COLOR_KEY, buttonNegativeColor) - putString(BUTTON_POSITIVE_TEXT_KEY, buttonPositiveText) - putString(BUTTON_NEGATIVE_TEXT_KEY, buttonNegativeText) - } - dialog.arguments = args - return dialog - } - } -} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/BaseInAppDialog.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/BaseInAppDialog.kt new file mode 100644 index 00000000..20365255 --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/BaseInAppDialog.kt @@ -0,0 +1,104 @@ +package com.personalization.inAppNotification.view.component.dialog + +import android.os.Bundle +import android.view.View +import androidx.core.view.isVisible +import androidx.fragment.app.DialogFragment +import com.personalization.inAppNotification.view.component.container.InAppViewContainer +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_DECLINE_COLOR_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_DECLINE_TEXT_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_CONFIRM_COLOR_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_CONFIRM_TEXT_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.IMAGE_URL_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.MESSAGE_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.TITLE_KEY +import com.personalization.ui.animation.button.addPressEffectDeclarative +import com.personalization.ui.click.NotificationClickListener +import com.personalization.utils.BundleUtils.getOptionalInt + +abstract class BaseInAppDialog : DialogFragment() { + + protected abstract val container: InAppViewContainer + private var _listener: NotificationClickListener? = null + + var listener: NotificationClickListener? + get() = _listener + set(value) { + _listener = value + } + + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setupDialog() + } + + private fun setupDialog() { + initImage() + initTextBlock() + initConfirmButton() + initDeclineButton() + handleCloseButton() + } + + private fun initImage() { + val imageUrl = arguments?.getString(IMAGE_URL_KEY).orEmpty() + if (imageUrl.isNotBlank()) { + container.backgroundImageView.loadImage(imageUrl) + } else { + container.imageContainer.visibility = View.GONE + } + } + + private fun initTextBlock() { + container.titleTextView.text = arguments?.getString(TITLE_KEY).orEmpty() + container.messageTextView.text = arguments?.getString(MESSAGE_KEY).orEmpty() + } + + private fun initConfirmButton() { + val buttonText = arguments?.getString(BUTTON_CONFIRM_TEXT_KEY).orEmpty() + val confirmColor = arguments?.getOptionalInt(BUTTON_CONFIRM_COLOR_KEY) + + if (buttonText.isEmpty()) { + container.buttonConfirmContainer.isVisible = false + return + } + + container.buttonConfirmContainer.addPressEffectDeclarative() + container.buttonConfirm.text = buttonText + confirmColor?.let { container.buttonConfirm.setBackgroundColor(it) } + container.buttonConfirmContainer.setOnClickListener { + onButtonClick(true) + } + } + + private fun initDeclineButton() { + val buttonText = arguments?.getString(BUTTON_DECLINE_TEXT_KEY).orEmpty() + val declineColor = arguments?.getOptionalInt(BUTTON_DECLINE_COLOR_KEY) + + if (buttonText.isEmpty()) { + container.buttonDeclineContainer.isVisible = false + return + } + + container.buttonDeclineContainer.addPressEffectDeclarative() + container.buttonDecline.text = buttonText + declineColor?.let { container.buttonDecline.setBackgroundColor(it) } + container.buttonDeclineContainer.setOnClickListener { + onButtonClick(false) + } + } + + private fun handleCloseButton() { + container.closeButton.addPressEffectDeclarative() + container.closeButton.setOnClickListener { dismiss() } + } + + private fun onButtonClick(isConfirmClick: Boolean) { + when (isConfirmClick) { + true -> listener?.onConfirmClick() + false -> listener?.onDeclineClick() + } + dismiss() + } +} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/BottomSheetDialog.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/BottomSheetDialog.kt deleted file mode 100644 index cd96fefa..00000000 --- a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/BottomSheetDialog.kt +++ /dev/null @@ -1,166 +0,0 @@ -@file:Suppress("NewApi") - -package com.personalization.inAppNotification.view.component.dialog - -import android.content.res.ColorStateList -import android.graphics.Color -import android.graphics.PorterDuff -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.view.isVisible -import com.google.android.material.bottomsheet.BottomSheetDialogFragment -import com.personalization.databinding.BottomSheetDialogBinding -import com.personalization.ui.animation.button.addPressEffectDeclarative -import com.personalization.ui.click.NotificationClickListener - -class BottomSheetDialog : BottomSheetDialogFragment() { - - private var listener: NotificationClickListener? = null - - fun setListener(listener: NotificationClickListener) { - this.listener = listener - } - - private var _binding: BottomSheetDialogBinding? = null - private val binding get() = _binding!! - - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = BottomSheetDialogBinding.inflate(inflater, container, false) - return binding.root - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - initImage() - initTextBlock() - initAcceptButton() - initDeclineButton() - handleClosingButton() - - (view.parent as View).apply { - backgroundTintMode = PorterDuff.Mode.CLEAR - backgroundTintList = ColorStateList.valueOf(Color.TRANSPARENT) - setBackgroundColor(Color.TRANSPARENT) - } - } - - private fun initImage() { - val imageUrl = arguments?.getString(IMAGE_URL_KEY).orEmpty() - if (imageUrl.isNotBlank()) { - binding.backgroundImageView.loadImage(imageUrl) - } else { - binding.imageContainer.isVisible = false - } - } - - private fun initTextBlock() { - with(binding) { - textContainer.apply { - title.text = arguments?.getString(TITLE_KEY).orEmpty() - message.text = arguments?.getString(MESSAGE_KEY).orEmpty() - } - } - } - - private fun initAcceptButton() { - val buttonText = arguments?.getString(BUTTON_POSITIVE_TEXT_KEY)?:"" - val positiveButtonColor = arguments?.getInt(BUTTON_POSITIVE_COLOR_KEY) - with(binding) { - buttonContainer.apply { - if(buttonText.isEmpty()) { - buttonAcceptContainer.isVisible = false - return - } - buttonAcceptContainer.addPressEffectDeclarative() - buttonAccept.text = buttonText - if (positiveButtonColor != null) { - buttonAccept.setBackgroundColor(positiveButtonColor) - } - buttonAcceptContainer.setOnClickListener { - onButtonClick(isPositiveClick = true) - } - } - } - } - - private fun initDeclineButton() { - val buttonText = arguments?.getString(BUTTON_NEGATIVE_TEXT_KEY)?:"" - val negativeButtonColor = arguments?.getInt(BUTTON_NEGATIVE_COLOR_KEY) - with(binding) { - buttonContainer.apply { - if(buttonText.isEmpty()) { - buttonDeclineContainer.isVisible = false - return - } - buttonDeclineContainer.addPressEffectDeclarative() - buttonDecline.text = buttonText - if (negativeButtonColor != null) { - buttonDecline.setBackgroundColor(negativeButtonColor) - } - buttonDeclineContainer.setOnClickListener { - onButtonClick(isPositiveClick = false) - } - } - } - } - - private fun handleClosingButton() { - with(binding) { - closeButton.addPressEffectDeclarative() - closeButton.setOnClickListener { dismiss() } - } - } - - private fun onButtonClick(isPositiveClick: Boolean) { - when (isPositiveClick) { - true -> listener?.onPositiveClick() - else -> listener?.onNegativeClick() - } - dismiss() - } - - companion object { - const val TAG = "BottomSheetDialog" - const val TITLE_KEY = "TITLE_KEY" - const val IMAGE_URL_KEY = "IMAGE_URL_KEY" - const val MESSAGE_KEY = "MESSAGE_KEY" - const val BUTTON_POSITIVE_COLOR_KEY = "BUTTON_POSITIVE_COLOR_KEY" - const val BUTTON_NEGATIVE_COLOR_KEY = "BUTTON_NEGATIVE_COLOR_KEY" - const val BUTTON_POSITIVE_TEXT_KEY = "BUTTON_POSITIVE_TEXT_KEY" - const val BUTTON_NEGATIVE_TEXT_KEY = "BUTTON_NEGATIVE_TEXT_KEY" - - fun newInstance( - title: String, - message: String, - imageUrl: String?, - buttonPositiveText: String, - buttonNegativeText: String?, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - ): BottomSheetDialog { - val dialog = BottomSheetDialog() - val args = Bundle().apply { - putString(TITLE_KEY, title) - putString(MESSAGE_KEY, message) - putString(IMAGE_URL_KEY, imageUrl) - putInt(BUTTON_POSITIVE_COLOR_KEY, buttonPositiveColor) - putInt(BUTTON_NEGATIVE_COLOR_KEY, buttonNegativeColor) - putString(BUTTON_POSITIVE_TEXT_KEY, buttonPositiveText) - putString(BUTTON_NEGATIVE_TEXT_KEY, buttonNegativeText) - } - dialog.arguments = args - return dialog - } - } -} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/FullScreenDialog.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/FullScreenDialog.kt deleted file mode 100644 index 27ad6fae..00000000 --- a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/FullScreenDialog.kt +++ /dev/null @@ -1,147 +0,0 @@ -package com.personalization.inAppNotification.view.component.dialog - -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.WindowManager -import androidx.fragment.app.DialogFragment -import com.personalization.databinding.FullScreenDialogBinding -import com.personalization.ui.animation.button.addPressEffectDeclarative -import com.personalization.ui.click.NotificationClickListener - -class FullScreenDialog : DialogFragment() { - - private val binding: FullScreenDialogBinding by lazy { - FullScreenDialogBinding.inflate(layoutInflater) - } - - private var listener: NotificationClickListener? = null - - fun setListener(listener: NotificationClickListener) { - this.listener = listener - } - - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - dialog?.window?.apply { - setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - setLayout( - WindowManager.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.MATCH_PARENT - ) - } - - initImage() - initTextBlock() - initAcceptButton() - initDeclineButton() - handleClosingButton() - } - - private fun initTextBlock() { - with(binding) { - textContainer.apply { - title.text = arguments?.getString(TITLE_KEY).orEmpty() - message.text = arguments?.getString(MESSAGE_KEY).orEmpty() - } - } - } - - private fun initImage() { - val imageUrl = arguments?.getString(IMAGE_URL_KEY).orEmpty() - if (imageUrl.isNotBlank()) { - binding.backgroundImageView.loadImage(imageUrl) - } - } - - private fun initDeclineButton() { - val negativeButtonColor = arguments?.getInt(BUTTON_NEGATIVE_COLOR_KEY) - with(binding) { - buttonContainer.apply { - buttonDeclineContainer.addPressEffectDeclarative() - buttonDecline.text = arguments?.getString(BUTTON_NEGATIVE_TEXT_KEY).orEmpty() - if (negativeButtonColor != null) { - buttonDecline.setBackgroundColor(negativeButtonColor) - } - buttonDeclineContainer.setOnClickListener { - onButtonClick(isPositiveClick = false) - } - } - } - } - - private fun initAcceptButton() { - val positiveButtonColor = arguments?.getInt(BUTTON_POSITIVE_COLOR_KEY) - with(binding) { - buttonContainer.apply { - buttonAcceptContainer.addPressEffectDeclarative() - buttonAccept.text = arguments?.getString(BUTTON_POSITIVE_TEXT_KEY).orEmpty() - if (positiveButtonColor != null) { - buttonAccept.setBackgroundColor(positiveButtonColor) - } - buttonAcceptContainer.setOnClickListener { - onButtonClick(isPositiveClick = true) - } - } - } - } - - private fun handleClosingButton() { - with(binding) { - closeButton.addPressEffectDeclarative() - closeButton.setOnClickListener { dismiss() } - } - } - - private fun onButtonClick(isPositiveClick: Boolean) { - when (isPositiveClick) { - true -> listener?.onPositiveClick() - else -> listener?.onNegativeClick() - } - dismiss() - } - - companion object { - const val TAG = "FullScreenDialog" - const val TITLE_KEY = "TITLE_KEY" - const val MESSAGE_KEY = "MESSAGE_KEY" - const val IMAGE_URL_KEY = "IMAGE_URL_KEY" - const val BUTTON_POSITIVE_TEXT_KEY = "BUTTON_POSITIVE_TEXT_KEY" - const val BUTTON_NEGATIVE_TEXT_KEY = "BUTTON_NEGATIVE_TEXT_KEY" - const val BUTTON_POSITIVE_COLOR_KEY = "BUTTON_POSITIVE_COLOR_KEY" - const val BUTTON_NEGATIVE_COLOR_KEY = "BUTTON_NEGATIVE_COLOR_KEY" - - fun newInstance( - title: String, - message: String, - imageUrl: String?, - buttonPositiveText: String, - buttonNegativeText: String, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - ): FullScreenDialog { - val dialog = FullScreenDialog() - val args = Bundle().apply { - putString(TITLE_KEY, title) - putString(MESSAGE_KEY, message) - putString(IMAGE_URL_KEY, imageUrl) - putInt(BUTTON_POSITIVE_COLOR_KEY, buttonPositiveColor) - putInt(BUTTON_NEGATIVE_COLOR_KEY, buttonNegativeColor) - putString(BUTTON_POSITIVE_TEXT_KEY, buttonPositiveText) - putString(BUTTON_NEGATIVE_TEXT_KEY, buttonNegativeText) - } - dialog.arguments = args - return dialog - } - } -} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/TopSheetDialog.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/TopSheetDialog.kt deleted file mode 100644 index d5a0b135..00000000 --- a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/TopSheetDialog.kt +++ /dev/null @@ -1,172 +0,0 @@ -@file:Suppress("NewApi") - -package com.personalization.inAppNotification.view.component.dialog - -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.view.Gravity -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.view.isVisible -import androidx.fragment.app.DialogFragment -import com.personalization.databinding.TopSheetDialogBinding -import com.personalization.ui.animation.button.addPressEffectDeclarative -import com.personalization.ui.click.NotificationClickListener - -const val AMOUNT = 0.5f -const val TITLE_KEY = "TITLE_KEY" -const val IMAGE_URL_KEY = "IMAGE_URL_KEY" -const val MESSAGE_KEY = "MESSAGE_KEY" -const val BUTTON_POSITIVE_COLOR_KEY = "BUTTON_POSITIVE_COLOR_KEY" -const val BUTTON_NEGATIVE_COLOR_KEY = "BUTTON_NEGATIVE_COLOR_KEY" -const val BUTTON_POSITIVE_TEXT_KEY = "BUTTON_POSITIVE_TEXT_KEY" -const val BUTTON_NEGATIVE_TEXT_KEY = "BUTTON_NEGATIVE_TEXT_KEY" - -class TopSheetDialog : DialogFragment() { - - private var listener: NotificationClickListener? = null - - fun setListener(listener: NotificationClickListener) { - this.listener = listener - } - - private var _binding: TopSheetDialogBinding? = null - private val binding get() = _binding!! - - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = TopSheetDialogBinding.inflate(inflater, container, false) - return binding.root - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - initImage() - initTextBlock() - initAcceptButton() - initDeclineButton() - handleClosingButton() - } - - override fun onStart() { - super.onStart() - dialog?.window?.apply { - setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - setGravity(Gravity.TOP) - setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - setDimAmount(AMOUNT) - } - } - - private fun initImage() { - val imageUrl = arguments?.getString(IMAGE_URL_KEY).orEmpty() - if (imageUrl.isNotBlank()) { - binding.backgroundImageView.loadImage(imageUrl) - } else { - binding.imageContainer.isVisible = false - } - } - - private fun initTextBlock() { - with(binding) { - textContainer.apply { - title.text = arguments?.getString(TITLE_KEY).orEmpty() - message.text = arguments?.getString(MESSAGE_KEY).orEmpty() - } - } - } - - private fun initAcceptButton() { - val buttonText = arguments?.getString(BUTTON_POSITIVE_TEXT_KEY) ?: "" - val positiveButtonColor = arguments?.getInt(BUTTON_POSITIVE_COLOR_KEY) - with(binding) { - buttonContainer.apply { - if (buttonText.isEmpty()) { - buttonAcceptContainer.isVisible = false - return - } - buttonAcceptContainer.addPressEffectDeclarative() - buttonAccept.text = buttonText - if (positiveButtonColor != null) { - buttonAccept.setBackgroundColor(positiveButtonColor) - } - buttonAcceptContainer.setOnClickListener { - onButtonClick(isPositiveClick = true) - } - } - } - } - - private fun initDeclineButton() { - val buttonText = arguments?.getString(BUTTON_NEGATIVE_TEXT_KEY) ?: "" - val negativeButtonColor = arguments?.getInt(BUTTON_NEGATIVE_COLOR_KEY) - with(binding) { - buttonContainer.apply { - if (buttonText.isEmpty()) { - buttonDeclineContainer.isVisible = false - return - } - buttonDeclineContainer.addPressEffectDeclarative() - buttonDecline.text = buttonText - if (negativeButtonColor != null) { - buttonDecline.setBackgroundColor(negativeButtonColor) - } - buttonDeclineContainer.setOnClickListener { - onButtonClick(isPositiveClick = false) - } - } - } - } - - private fun handleClosingButton() { - with(binding) { - closeButton.addPressEffectDeclarative() - closeButton.setOnClickListener { dismiss() } - } - } - - private fun onButtonClick(isPositiveClick: Boolean) { - when (isPositiveClick) { - true -> listener?.onPositiveClick() - else -> listener?.onNegativeClick() - } - dismiss() - } - - companion object { - const val TAG = "TopSheetDialog" - - fun newInstance( - title: String, - message: String, - imageUrl: String?, - buttonPositiveText: String, - buttonNegativeText: String?, - buttonPositiveColor: Int, - buttonNegativeColor: Int, - ): TopSheetDialog { - val dialog = TopSheetDialog() - val args = Bundle().apply { - putString(TITLE_KEY, title) - putString(MESSAGE_KEY, message) - putString(IMAGE_URL_KEY, imageUrl) - putInt(BUTTON_POSITIVE_COLOR_KEY, buttonPositiveColor) - putInt(BUTTON_NEGATIVE_COLOR_KEY, buttonNegativeColor) - putString(BUTTON_POSITIVE_TEXT_KEY, buttonPositiveText) - putString(BUTTON_NEGATIVE_TEXT_KEY, buttonNegativeText) - } - dialog.arguments = args - return dialog - } - } -} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/alert/AlertDialog.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/alert/AlertDialog.kt new file mode 100644 index 00000000..52f84d81 --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/alert/AlertDialog.kt @@ -0,0 +1,80 @@ +package com.personalization.inAppNotification.view.component.dialog.alert + +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.personalization.databinding.AlertDialogBinding +import com.personalization.inAppNotification.view.component.container.InAppViewContainer +import com.personalization.inAppNotification.view.component.dialog.BaseInAppDialog +import com.personalization.inAppNotification.view.component.dialog.alert.container.AlertDialogViewContainer +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_DECLINE_COLOR_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_DECLINE_TEXT_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_CONFIRM_COLOR_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_CONFIRM_TEXT_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.IMAGE_URL_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.MESSAGE_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.TITLE_KEY + +const val ALERT_DIALOG_TAG = "AlertDialog" + +class AlertDialog : BaseInAppDialog() { + + private var _binding: AlertDialogBinding? = null + private val binding get() = _binding!! + + override val container: InAppViewContainer by lazy { + AlertDialogViewContainer(binding) + } + + override fun onStart() { + super.onStart() + dialog?.window?.apply { + setGravity(Gravity.CENTER) + setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + setDimAmount(0.5f) + } + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = AlertDialogBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + + companion object { + fun newInstance( + title: String, + message: String, + imageUrl: String?, + buttonConfirmText: String?, + buttonDeclineText: String?, + buttonConfirmColor: Int?, + buttonDeclineColor: Int?, + ): AlertDialog { + val dialog = AlertDialog() + val args = Bundle().apply { + putString(TITLE_KEY, title) + putString(MESSAGE_KEY, message) + putString(IMAGE_URL_KEY, imageUrl) + putString(BUTTON_CONFIRM_TEXT_KEY, buttonConfirmText) + putString(BUTTON_DECLINE_TEXT_KEY, buttonDeclineText) + buttonConfirmColor?.let { putInt(BUTTON_CONFIRM_COLOR_KEY, it) } + buttonDeclineColor?.let { putInt(BUTTON_DECLINE_COLOR_KEY, it) } + } + dialog.arguments = args + return dialog + } + } +} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/alert/container/AlertDialogViewContainer.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/alert/container/AlertDialogViewContainer.kt new file mode 100644 index 00000000..22d6446e --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/alert/container/AlertDialogViewContainer.kt @@ -0,0 +1,16 @@ +package com.personalization.inAppNotification.view.component.dialog.alert.container + +import com.personalization.databinding.AlertDialogBinding +import com.personalization.inAppNotification.view.component.container.InAppViewContainer + +class AlertDialogViewContainer(binding: AlertDialogBinding) : InAppViewContainer { + override val backgroundImageView = binding.backgroundImageView + override val imageContainer = binding.imageContainer + override val titleTextView = binding.textContainer.title + override val messageTextView = binding.textContainer.message + override val buttonConfirmContainer = binding.buttonContainer.buttonConfirmContainer + override val buttonConfirm = binding.buttonContainer.buttonConfirm + override val buttonDeclineContainer = binding.buttonContainer.buttonDeclineContainer + override val buttonDecline = binding.buttonContainer.buttonDecline + override val closeButton = binding.closeButton +} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/bottomSheet/BottomSheetDialog.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/bottomSheet/BottomSheetDialog.kt new file mode 100644 index 00000000..9bf5e88f --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/bottomSheet/BottomSheetDialog.kt @@ -0,0 +1,82 @@ +@file:Suppress("NewApi") + +package com.personalization.inAppNotification.view.component.dialog.bottomSheet + +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.personalization.databinding.BottomSheetDialogBinding +import com.personalization.inAppNotification.view.component.container.InAppViewContainer +import com.personalization.inAppNotification.view.component.dialog.BaseInAppDialog +import com.personalization.inAppNotification.view.component.dialog.bottomSheet.container.BottomSheetDialogViewContainer +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_DECLINE_COLOR_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_DECLINE_TEXT_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_CONFIRM_COLOR_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_CONFIRM_TEXT_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.IMAGE_URL_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.MESSAGE_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.TITLE_KEY + +const val BOTTOM_SHEET_TAG = "BottomSheetDialog" + +class BottomSheetDialog : BaseInAppDialog() { + + private var _binding: BottomSheetDialogBinding? = null + private val binding get() = _binding!! + + override val container: InAppViewContainer by lazy { + BottomSheetDialogViewContainer(binding) + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = BottomSheetDialogBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + override fun onStart() { + super.onStart() + dialog?.window?.apply { + setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + setGravity(Gravity.BOTTOM) + setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + setDimAmount(0.5f) + } + } + + companion object { + fun newInstance( + title: String, + message: String, + imageUrl: String?, + buttonConfirmText: String?, + buttonDeclineText: String?, + buttonConfirmColor: Int?, + buttonDeclineColor: Int?, + ): BottomSheetDialog { + val dialog = BottomSheetDialog() + val args = Bundle().apply { + putString(TITLE_KEY, title) + putString(MESSAGE_KEY, message) + putString(IMAGE_URL_KEY, imageUrl) + putString(BUTTON_CONFIRM_TEXT_KEY, buttonConfirmText) + putString(BUTTON_DECLINE_TEXT_KEY, buttonDeclineText) + buttonConfirmColor?.let { putInt(BUTTON_CONFIRM_COLOR_KEY, it) } + buttonDeclineColor?.let { putInt(BUTTON_DECLINE_COLOR_KEY, it) } + } + dialog.arguments = args + return dialog + } + } +} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/bottomSheet/container/BottomSheetDialogViewContainer.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/bottomSheet/container/BottomSheetDialogViewContainer.kt new file mode 100644 index 00000000..643f4f53 --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/bottomSheet/container/BottomSheetDialogViewContainer.kt @@ -0,0 +1,16 @@ +package com.personalization.inAppNotification.view.component.dialog.bottomSheet.container + +import com.personalization.databinding.BottomSheetDialogBinding +import com.personalization.inAppNotification.view.component.container.InAppViewContainer + +class BottomSheetDialogViewContainer(binding: BottomSheetDialogBinding) : InAppViewContainer { + override val backgroundImageView = binding.backgroundImageView + override val imageContainer = binding.imageContainer + override val titleTextView = binding.textContainer.title + override val messageTextView = binding.textContainer.message + override val buttonConfirmContainer = binding.buttonContainer.buttonConfirmContainer + override val buttonConfirm = binding.buttonContainer.buttonConfirm + override val buttonDeclineContainer = binding.buttonContainer.buttonDeclineContainer + override val buttonDecline = binding.buttonContainer.buttonDecline + override val closeButton = binding.closeButton +} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/fullScreen/FullScreenDialog.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/fullScreen/FullScreenDialog.kt new file mode 100644 index 00000000..18b1feca --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/fullScreen/FullScreenDialog.kt @@ -0,0 +1,80 @@ +package com.personalization.inAppNotification.view.component.dialog.fullScreen + +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.personalization.databinding.FullScreenDialogBinding +import com.personalization.inAppNotification.view.component.container.InAppViewContainer +import com.personalization.inAppNotification.view.component.dialog.BaseInAppDialog +import com.personalization.inAppNotification.view.component.dialog.fullScreen.container.FullScreenDialogViewContainer +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_DECLINE_COLOR_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_DECLINE_TEXT_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_CONFIRM_COLOR_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_CONFIRM_TEXT_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.IMAGE_URL_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.MESSAGE_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.TITLE_KEY + +const val FULL_SCREEN_DIALOG_TAG = "FullScreenDialog" + +class FullScreenDialog : BaseInAppDialog() { + + private var _binding: FullScreenDialogBinding? = null + private val binding get() = _binding!! + + override val container: InAppViewContainer by lazy { + FullScreenDialogViewContainer(binding) + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FullScreenDialogBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onStart() { + super.onStart() + dialog?.window?.apply { + setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + setGravity(Gravity.CENTER) + setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + setDimAmount(0.5f) + } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + companion object { + fun newInstance( + title: String, + message: String, + imageUrl: String?, + buttonConfirmText: String?, + buttonDeclineText: String?, + buttonConfirmColor: Int?, + buttonDeclineColor: Int? + ): FullScreenDialog { + val dialog = FullScreenDialog() + val args = Bundle().apply { + putString(TITLE_KEY, title) + putString(MESSAGE_KEY, message) + putString(IMAGE_URL_KEY, imageUrl) + putString(BUTTON_CONFIRM_TEXT_KEY, buttonConfirmText) + putString(BUTTON_DECLINE_TEXT_KEY, buttonDeclineText) + buttonConfirmColor?.let { putInt(BUTTON_CONFIRM_COLOR_KEY, it) } + buttonDeclineColor?.let { putInt(BUTTON_DECLINE_COLOR_KEY, it) } + } + dialog.arguments = args + return dialog + } + } +} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/fullScreen/container/FullScreenDialogContainer.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/fullScreen/container/FullScreenDialogContainer.kt new file mode 100644 index 00000000..042f11fb --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/fullScreen/container/FullScreenDialogContainer.kt @@ -0,0 +1,16 @@ +package com.personalization.inAppNotification.view.component.dialog.fullScreen.container + +import com.personalization.databinding.FullScreenDialogBinding +import com.personalization.inAppNotification.view.component.container.InAppViewContainer + +class FullScreenDialogViewContainer(binding: FullScreenDialogBinding) : InAppViewContainer { + override val backgroundImageView = binding.backgroundImageView + override val imageContainer = binding.imageContainer + override val titleTextView = binding.textContainer.title + override val messageTextView = binding.textContainer.message + override val buttonConfirmContainer = binding.buttonContainer.buttonConfirmContainer + override val buttonConfirm = binding.buttonContainer.buttonConfirm + override val buttonDeclineContainer = binding.buttonContainer.buttonDeclineContainer + override val buttonDecline = binding.buttonContainer.buttonDecline + override val closeButton = binding.closeButton +} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/topSheet/TopSheetDialog.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/topSheet/TopSheetDialog.kt new file mode 100644 index 00000000..20cc2138 --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/topSheet/TopSheetDialog.kt @@ -0,0 +1,82 @@ +@file:Suppress("NewApi") + +package com.personalization.inAppNotification.view.component.dialog.topSheet + +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.personalization.databinding.TopSheetDialogBinding +import com.personalization.inAppNotification.view.component.container.InAppViewContainer +import com.personalization.inAppNotification.view.component.dialog.BaseInAppDialog +import com.personalization.inAppNotification.view.component.dialog.topSheet.container.TopSheetDialogViewContainer +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_DECLINE_COLOR_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_DECLINE_TEXT_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_CONFIRM_COLOR_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.BUTTON_CONFIRM_TEXT_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.IMAGE_URL_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.MESSAGE_KEY +import com.personalization.inAppNotification.view.component.utils.InAppConsts.TITLE_KEY + +const val TOP_SHEET_DIALOG = "TopSheetDialog" + +class TopSheetDialog : BaseInAppDialog() { + + private var _binding: TopSheetDialogBinding? = null + private val binding get() = _binding!! + + override val container: InAppViewContainer by lazy { + TopSheetDialogViewContainer(binding) + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = TopSheetDialogBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + override fun onStart() { + super.onStart() + dialog?.window?.apply { + setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + setGravity(Gravity.TOP) + setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + setDimAmount(0.5f) + } + } + + companion object { + fun newInstance( + title: String, + message: String, + imageUrl: String?, + buttonConfirmText: String?, + buttonDeclineText: String?, + buttonConfirmColor: Int?, + buttonDeclineColor: Int?, + ): TopSheetDialog { + val dialog = TopSheetDialog() + val args = Bundle().apply { + putString(TITLE_KEY, title) + putString(MESSAGE_KEY, message) + putString(IMAGE_URL_KEY, imageUrl) + putString(BUTTON_CONFIRM_TEXT_KEY, buttonConfirmText) + putString(BUTTON_DECLINE_TEXT_KEY, buttonDeclineText) + buttonConfirmColor?.let { putInt(BUTTON_CONFIRM_COLOR_KEY, it) } + buttonDeclineColor?.let { putInt(BUTTON_DECLINE_COLOR_KEY, it) } + } + dialog.arguments = args + return dialog + } + } +} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/topSheet/container/TopSheetDialogViewContainer.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/topSheet/container/TopSheetDialogViewContainer.kt new file mode 100644 index 00000000..92f49fc5 --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/dialog/topSheet/container/TopSheetDialogViewContainer.kt @@ -0,0 +1,16 @@ +package com.personalization.inAppNotification.view.component.dialog.topSheet.container + +import com.personalization.databinding.TopSheetDialogBinding +import com.personalization.inAppNotification.view.component.container.InAppViewContainer + +class TopSheetDialogViewContainer(binding: TopSheetDialogBinding) : InAppViewContainer { + override val backgroundImageView = binding.backgroundImageView + override val imageContainer = binding.imageContainer + override val titleTextView = binding.textContainer.title + override val messageTextView = binding.textContainer.message + override val buttonConfirmContainer = binding.buttonContainer.buttonConfirmContainer + override val buttonConfirm = binding.buttonContainer.buttonConfirm + override val buttonDeclineContainer = binding.buttonContainer.buttonDeclineContainer + override val buttonDecline = binding.buttonContainer.buttonDecline + override val closeButton = binding.closeButton +} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/snackbar/Snackbar.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/snackbar/Snackbar.kt index 2fa2eaee..ab7656da 100644 --- a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/snackbar/Snackbar.kt +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/snackbar/Snackbar.kt @@ -11,10 +11,10 @@ class Snackbar(private val rootView: View) { fun show( message: String, - buttonPositiveText: String, - buttonNegativeText: String, - onPositiveClick: () -> Unit, - onNegativeClick: () -> Unit + buttonConfirmText: String, + buttonDeclineText: String, + onConfirmClick: () -> Unit, + onDeclineClick: () -> Unit ) { val snackbar = Snackbar.make( /* view = */ rootView, @@ -26,16 +26,16 @@ class Snackbar(private val rootView: View) { with(binding) { title.text = message - positiveButton.text = buttonPositiveText - negativeButton.text = buttonNegativeText + confirmButton.text = buttonConfirmText + declineButton.text = buttonDeclineText - positiveButton.setOnClickListener { - onPositiveClick() + confirmButton.setOnClickListener { + onConfirmClick() snackbar.dismiss() } - negativeButton.setOnClickListener { - onNegativeClick() + declineButton.setOnClickListener { + onDeclineClick() snackbar.dismiss() } } diff --git a/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/utils/InAppConsts.kt b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/utils/InAppConsts.kt new file mode 100644 index 00000000..e05d05d7 --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/inAppNotification/view/component/utils/InAppConsts.kt @@ -0,0 +1,11 @@ +package com.personalization.inAppNotification.view.component.utils + +object InAppConsts { + const val TITLE_KEY = "TITLE_KEY" + const val MESSAGE_KEY = "MESSAGE_KEY" + const val IMAGE_URL_KEY = "IMAGE_URL_KEY" + const val BUTTON_CONFIRM_COLOR_KEY = "BUTTON_CONFIRM_COLOR_KEY" + const val BUTTON_DECLINE_COLOR_KEY = "BUTTON_DECLINE_COLOR_KEY" + const val BUTTON_CONFIRM_TEXT_KEY = "BUTTON_CONFIRM_TEXT_KEY" + const val BUTTON_DECLINE_TEXT_KEY = "BUTTON_DECLINE_TEXT_KEY" +} diff --git a/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/mappers/popup/PopupDtoMapper.kt b/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/mappers/popup/PopupDtoMapper.kt index a9a1ebd7..47963d77 100644 --- a/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/mappers/popup/PopupDtoMapper.kt +++ b/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/mappers/popup/PopupDtoMapper.kt @@ -28,6 +28,7 @@ object PopupDtoMapper { components = json.optString(PARAM_COMPONENTS)?.let { ComponentsMapper.map(JSONObject(it)) }, + targetScreen = "CategoryFragment", webPushSystem = json.optBoolean(PARAM_WEB_PUSH_SYSTEM), popupActions = json.optString(PARAM_POPUP_ACTIONS)?.let { PopupActionsMapper.map(JSONObject(it)) diff --git a/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/models/dto/popUp/DialogDataDto.kt b/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/models/dto/popUp/DialogDataDto.kt index 5ee7f2ad..17e92a20 100644 --- a/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/models/dto/popUp/DialogDataDto.kt +++ b/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/models/dto/popUp/DialogDataDto.kt @@ -4,10 +4,10 @@ data class DialogDataDto( val title: String, val message: String, val imageUrl: String, - val buttonPositiveColor: Int, - val buttonNegativeColor: Int, - val buttonPositiveText: String, - val buttonNegativeText: String, - val onPositiveClick: () -> Unit, + val buttonConfirmColor: Int, + val buttonDeclineColor: Int, + val buttonConfirmText: String, + val buttonDeclineText: String, + val onConfirmClick: () -> Unit, val position: Position ) diff --git a/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/models/dto/popUp/PopupDto.kt b/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/models/dto/popUp/PopupDto.kt index e27a0e1c..5f568a63 100644 --- a/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/models/dto/popUp/PopupDto.kt +++ b/personalization-sdk/src/main/kotlin/com/personalization/sdk/data/models/dto/popUp/PopupDto.kt @@ -8,5 +8,6 @@ data class PopupDto( val html: String, val components: Components?, val webPushSystem: Boolean, + val targetScreen: String?, val popupActions: PopupActions? ) diff --git a/personalization-sdk/src/main/kotlin/com/personalization/ui/click/NotificationClickListener.kt b/personalization-sdk/src/main/kotlin/com/personalization/ui/click/NotificationClickListener.kt index 8aa8ed03..c5df06cc 100644 --- a/personalization-sdk/src/main/kotlin/com/personalization/ui/click/NotificationClickListener.kt +++ b/personalization-sdk/src/main/kotlin/com/personalization/ui/click/NotificationClickListener.kt @@ -1,6 +1,6 @@ package com.personalization.ui.click interface NotificationClickListener { - fun onPositiveClick() - fun onNegativeClick() + fun onConfirmClick() + fun onDeclineClick() } diff --git a/personalization-sdk/src/main/kotlin/com/personalization/utils/BundleUtils.kt b/personalization-sdk/src/main/kotlin/com/personalization/utils/BundleUtils.kt new file mode 100644 index 00000000..5a21f5d9 --- /dev/null +++ b/personalization-sdk/src/main/kotlin/com/personalization/utils/BundleUtils.kt @@ -0,0 +1,9 @@ +package com.personalization.utils + +import android.os.Bundle + +object BundleUtils { + fun Bundle.getOptionalInt(key: String): Int? { + return if (containsKey(key)) getInt(key) else null + } +} diff --git a/personalization-sdk/src/main/res/layout/alert_button_container.xml b/personalization-sdk/src/main/res/layout/alert_button_container.xml index 04a51887..f3dba914 100644 --- a/personalization-sdk/src/main/res/layout/alert_button_container.xml +++ b/personalization-sdk/src/main/res/layout/alert_button_container.xml @@ -27,7 +27,7 @@ diff --git a/personalization-sdk/src/main/res/layout/custom_snackbar.xml b/personalization-sdk/src/main/res/layout/custom_snackbar.xml index 4ad7ac6f..34eee862 100644 --- a/personalization-sdk/src/main/res/layout/custom_snackbar.xml +++ b/personalization-sdk/src/main/res/layout/custom_snackbar.xml @@ -17,7 +17,7 @@ tools:text="Some snackbar text" />