reverse penny drop (#5399)

* reverse penny drop

* id key

* removed unused file
This commit is contained in:
Ashutosh Y
2023-02-17 17:19:54 +05:30
committed by GitHub Enterprise
parent 3b4fb0e4e9
commit 60dc080f04
32 changed files with 1231 additions and 16 deletions

View File

@@ -23,10 +23,12 @@ kapt {
}
def VERSION_CODE = 295
def VERSION_NAME = "3.3.2"
android {
namespace 'com.naviapp'
compileSdk 32

View File

@@ -0,0 +1,86 @@
package com.navi.amc.common.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.RecyclerView
import com.navi.amc.R
import com.navi.amc.common.model.PennyDropOption
import com.navi.amc.databinding.PennyDropOptionBinding
import com.navi.amc.utils.ColorUtils
import com.navi.amc.utils.orFalse
import com.navi.base.utils.isValidIndex
import com.navi.design.utils.*
class PennyDropOptionsAdapter(
private val items: List<PennyDropOption>,
val listener: ((PennyDropOption) -> Unit)? = null
) : RecyclerView.Adapter<PennyDropOptionsViewHolder>() {
var lastCheckedPosition = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PennyDropOptionsViewHolder {
return PennyDropOptionsViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.penny_drop_option,
parent,
false
)
)
}
override fun getItemCount(): Int {
return items.size
}
override fun onBindViewHolder(holder: PennyDropOptionsViewHolder, position: Int) {
if (!isValidIndex(position, itemCount)) return
val itemData = items[position]
holder.binding.apply {
title.setSpannableString(itemData.title)
subtitle.setSpannableString(itemData.subTitle)
root.background =
ColorUtils.getDarkGreyBorder8StrokeDrawable(holder.binding.root.context)
label.isVisible = itemData.label?.let {
label.setSpannableString(it.title)
label.background = getNaviDrawable(
radii = CornerRadius(
leftBottom = dpToPx(4),
rightTop = dpToPx(8)
), backgroundColor = it.bgColor.parseColorSafe()
)
true
} ?: run {
false
}
if (lastCheckedPosition == -1 && itemData.isSelected.orFalse()) {
lastCheckedPosition = position
listener?.invoke(itemData)
}
radio.isChecked = (lastCheckedPosition == position)
if (radio.isChecked || itemData.toShowNote.orFalse()) {
note.setSpannableString(itemData.note?.title)
note.background = getNaviDrawable(
radii = CornerRadius(
leftBottom = dpToPx(8),
rightBottom = dpToPx(8)
), backgroundColor = itemData.note?.bgColor.parseColorSafe()
)
} else {
note.isVisible = false
}
radio.setOnClickListener {
val tempLastCheckedPosition = lastCheckedPosition
lastCheckedPosition = position
notifyItemChanged(tempLastCheckedPosition)
notifyItemChanged(lastCheckedPosition)
listener?.invoke(itemData)
}
}
}
}
class PennyDropOptionsViewHolder(val binding: PennyDropOptionBinding) :
RecyclerView.ViewHolder(binding.root)

View File

@@ -0,0 +1,244 @@
package com.navi.amc.common.fragment
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.DividerItemDecoration
import com.navi.amc.R
import com.navi.amc.common.activity.CheckerActivity
import com.navi.amc.common.adapter.PennyDropOptionsAdapter
import com.navi.amc.common.model.AdditionalDataAsyncResponse
import com.navi.amc.common.model.NextCtaResponse
import com.navi.amc.common.viewmodel.PennyDropOptionsViewModel
import com.navi.amc.databinding.PennyDropOptionsLayoutBinding
import com.navi.amc.utils.AmcAnalytics.BANK_VERIFICATION_OPTIONS
import com.navi.amc.utils.AmcAnalytics.CHANGE_BANK
import com.navi.amc.utils.AmcAnalytics.PENNY_DROP_OPTIONS
import com.navi.amc.utils.Constant.RPD
import com.navi.amc.utils.Constant.TOKEN
import com.navi.amc.utils.Constant.UPILINK
import com.navi.amc.utils.orValue
import com.navi.base.model.ActionData
import com.navi.base.model.CtaData
import com.navi.common.firebasedb.FirebaseStatusType
import com.navi.common.listeners.FragmentInterchangeListener
import com.navi.common.listeners.HeaderInteractionListener
import com.navi.common.model.RequestConfig
import com.navi.common.utils.ApiPollScheduler
import com.navi.common.utils.log
import com.navi.common.utils.observeNonNull
import com.navi.design.textview.model.NaviSpan
import com.navi.design.textview.model.TextWithStyle
import com.navi.design.utils.parseColorSafe
import com.navi.design.utils.setSpannableString
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class PennyDropOptionsFragment() : AmcBaseFragment() {
private lateinit var binding: PennyDropOptionsLayoutBinding
private val viewModel by viewModels<PennyDropOptionsViewModel>()
private lateinit var adapter: PennyDropOptionsAdapter
private var apiPollScheduler: ApiPollScheduler? = null
override val screenName: String
get() = BANK_VERIFICATION_OPTIONS
override fun onAttach(context: Context) {
super.onAttach(context)
headerInteractionListener = context as? HeaderInteractionListener
fragmentInterchangeListener = context as? FragmentInterchangeListener
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding =
DataBindingUtil.inflate(inflater, R.layout.penny_drop_options_layout, container, false)
sendInitEvent()
initError(viewModel, showNewDesignSystemFragment = true, buttonListener = {
when(it){
CHANGE_BANK -> {
fragmentInterchangeListener?.navigateToNextScreen(actionData = ActionData(url = "bank_details"))
}
else ->{
}
}
})
initObservers()
fetchData()
return binding.root
}
private fun sendInitEvent(){
sendEvent(PENNY_DROP_OPTIONS)
}
private fun initObservers() {
viewModel.asyncResponse.observeNonNull(viewLifecycleOwner){
if (it != null) {
onPollingResponse(it)
}
}
viewModel.requestConfig.observeNonNull(viewLifecycleOwner){
hideLoader()
apiPollInit(it?.requestConfig)
}
viewModel.rpdPaymentDetails.observeNonNull(viewLifecycleOwner){
it?.methodDetails?.get(UPILINK)?.let{
upiIntent(it)
}
it?.tokenDetails?.requestId?.let{
viewModel.requestId = it
}
}
viewModel.tokenExpire.observeNonNull(viewLifecycleOwner){
activity?.finish()
}
viewModel.pennyDropOptionsData.observeNonNull(viewLifecycleOwner) { data ->
hideLoader()
data?.header?.let {
headerInteractionListener?.setProperties(it)
}
data?.content?.let {
binding.title.setSpannableString(it.title)
binding.subtitle.setSpannableString(it.subTitle)
}
data?.content?.items?.let { items ->
adapter = PennyDropOptionsAdapter(
items = items
) {
viewModel.paymentMethod = it
}
val itemDecorator = DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
context?.let {
ContextCompat.getDrawable(it, R.drawable.empty_space_divider)?.let { drawable ->
itemDecorator.setDrawable(drawable)
}
}
binding.options.addItemDecoration(itemDecorator)
binding.options.adapter = adapter
}
data?.footer?.let {
val termsText = it.title?.text + it.name?.text
val style: MutableList<NaviSpan> = ArrayList()
it.name?.style?.let { it1 -> style.addAll(it1) }
it.title?.style?.let { it1 -> style.addAll(it1) }
binding.terms.setSpannableString(TextWithStyle(text = termsText, style = style))
binding.footer.btn.apply {
text = it.nextCta?.title
setTextColor(it.nextCta?.titleColor.parseColorSafe())
setOnClickListener {
if (viewModel.paymentMethod?.id.orEmpty() == RPD)
arguments?.getString(TOKEN)
?.let { it -> viewModel.fetchInitPaymentMethodDetails(token = it, methodId = RPD) }
else {
val action = viewModel.paymentMethod?.actionData
fragmentInterchangeListener?.navigateToNextScreen(action)
}
}
}
}
val method = data?.content?.autoSelectMethod
val list = data?.content?.items
if (method.isNullOrEmpty().not()) {
val item = list?.singleOrNull { it.id == method }
if (item?.id.orEmpty() == RPD)
arguments?.getString(TOKEN)
?.let { it -> viewModel.fetchInitPaymentMethodDetails(token = it, methodId = RPD) }
else {
activity?.supportFragmentManager?.popBackStack()
fragmentInterchangeListener?.navigateToNextScreen(actionData = item?.actionData)
}
}
}
}
private fun apiPollInit(
requestConfig : RequestConfig?
) {
apiPollScheduler =
ApiPollScheduler(
initialDelay =
requestConfig?.initialDelay.orValue(0).toLong(),
numberOfRetry = requestConfig
?.numOfRetries
.orValue(CheckerActivity.DEFAULT_RETRY_COUNT),
pollInterval =
requestConfig
?.interval
.orValue(ApiPollScheduler.API_POLL_REPEAT_PERIOD_SECONDS.toInt())
.toLong(),
doOnTimeout = { activity?.runOnUiThread { apiPollScheduler?.stopApiPoll()
} }
) {
showLoader()
viewModel.checkApiPollStatus()
}
apiPollScheduler?.scheduleApiPoll()
}
private fun upiIntent(link: String) {
try {
val intent = Intent().apply {
setAction(Intent.ACTION_VIEW)
setData(Uri.parse(link))
}
startActivityForResult(intent, REQUEST_CODE)
} catch (ex: Exception) {
ex.log()
}
}
private fun onPollingResponse(additonalData: AdditionalDataAsyncResponse<NextCtaResponse?>) {
when {
TextUtils.equals(additonalData.status, FirebaseStatusType.SUCCESS) -> {
hideLoader()
apiPollScheduler?.stopApiPoll()
fragmentInterchangeListener?.navigateToNextScreen(additonalData.data?.nextCTA)
}
TextUtils.equals(additonalData.status, FirebaseStatusType.FAILURE) -> {
hideLoader()
apiPollScheduler?.stopApiPoll()
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
showLoader()
viewModel.getRequestConfig()
arguments?.getString(TOKEN)?.let{
viewModel.postPaymentSignal(it, RPD)
}
}
private fun fetchData() {
showLoader()
arguments?.getString(TOKEN)?.let{
viewModel.fetchData(it)
}
}
companion object {
const val REQUEST_CODE = 5001
fun newInstance(bundle: Bundle): PennyDropOptionsFragment {
return PennyDropOptionsFragment().apply {
arguments = bundle
}
}
}
}

View File

@@ -0,0 +1,137 @@
package com.navi.amc.common.fragment
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.viewModels
import com.navi.amc.R
import com.navi.amc.common.listener.FooterInteractionListener
import com.navi.amc.common.view.ShimmerNoteView
import com.navi.amc.common.viewmodel.RpdSuccessViewModel
import com.navi.amc.databinding.KeyValueItemLayoutBinding
import com.navi.amc.databinding.RpdSuccessLayoutBinding
import com.navi.amc.utils.AmcAnalytics.RPD_SUCCESS_SCREEN
import com.navi.amc.utils.Constant.CHANGE_BANK
import com.navi.amc.utils.Constant.CONFIRMED
import com.navi.amc.utils.SubPageStatusType.RPD_SUCCESS
import com.navi.base.model.ActionData
import com.navi.common.listeners.FragmentInterchangeListener
import com.navi.common.listeners.HeaderInteractionListener
import com.navi.common.utils.observeNonNull
import com.navi.design.utils.dpToPxInInt
import com.navi.design.utils.setSpannableString
import com.navi.naviwidgets.extensions.showWhenDataIsAvailable
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class RpdSuccessFragment() : AmcBaseFragment(), FooterInteractionListener {
private lateinit var binding: RpdSuccessLayoutBinding
private val viewModel by viewModels<RpdSuccessViewModel>()
override val screenName: String
get() = RPD_SUCCESS
override fun onAttach(context: Context) {
super.onAttach(context)
headerInteractionListener = context as HeaderInteractionListener?
fragmentInterchangeListener = context as FragmentInterchangeListener?
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.rpd_success_layout, container, false)
sendInitEvent()
initError(viewModel, showNewDesignSystemFragment = true)
initObservers()
fetchData()
return binding.root
}
private fun fetchData() {
showLoader()
viewModel.fetchData()
}
private fun sendInitEvent(){
sendEvent(RPD_SUCCESS_SCREEN)
}
private fun initObservers() {
viewModel.rpdSuccessData.observeNonNull(viewLifecycleOwner) {
hideLoader()
it.header?.let {
headerInteractionListener?.setProperties(it)
headerInteractionListener?.hideDivider()
}
it.content?.let {
binding.icon.showWhenDataIsAvailable(it.iconCode)
binding.title.setSpannableString(it.title)
binding.subtitle.setSpannableString(it.subtitle)
binding.container.removeAllViews()
it.detailsData?.items?.forEach { data ->
val inflater = LayoutInflater.from(context)
val view = inflater.inflate(
R.layout.key_value_item_layout,
binding.container,
false
)
view.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
val childBinding = DataBindingUtil.bind<KeyValueItemLayoutBinding>(view)
childBinding?.key?.setSpannableString(data.key)
childBinding?.value?.setSpannableString(data.value)
binding.container.addView(view)
}
val view = View(context)
view.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
dpToPxInInt(24)
)
binding.container.addView(view)
it.detailsData?.note?.let { note ->
val view = context?.let { it -> ShimmerNoteView(it) }
view?.setProperties(note)
binding.container.addView(view)
}
it.detailsData?.dataSafeWidget?.let {
binding.dataSafe.data = it
}
val space = View(context)
space.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
dpToPxInInt(16)
)
binding.container.addView(space)
}
it.footer?.let {
binding.footer.setProperties(it, this)
}
}
}
companion object {
fun newInstance(bundle: Bundle): RpdSuccessFragment {
return RpdSuccessFragment().apply {
arguments = bundle
}
}
}
override fun onFooterBackPress(actionData: ActionData?) {
viewModel.postStatus(CHANGE_BANK)
fragmentInterchangeListener?.navigateToNextScreen(actionData)
}
override fun onFooterNextPress(actionData: ActionData?, skipValidation: Boolean?) {
viewModel.postStatus(CONFIRMED)
fragmentInterchangeListener?.navigateToNextScreen(actionData)
}
}

View File

@@ -15,6 +15,7 @@ import kotlinx.parcelize.Parcelize
@Parcelize
data class Footer(
@SerializedName("customerName") var name: TextWithStyle? = null,
@SerializedName("title") var title: TextWithStyle? = null,
@SerializedName("nextCta") var nextCta: ActionData? = null,
@SerializedName("backCta") var backCta: ActionData? = null,

View File

@@ -0,0 +1,47 @@
package com.navi.amc.common.model
import com.google.gson.annotations.SerializedName
import com.navi.amc.kyc.model.Note
import com.navi.base.model.ActionData
import com.navi.common.model.Header
import com.navi.common.model.LabelData
import com.navi.design.textview.model.TextWithStyle
data class PennyDropOptionsScreenData(
@SerializedName("header")
val header: Header? = null,
@SerializedName("content")
val content: PennyDropOptionsContent? = null,
@SerializedName("footer")
val footer: Footer? = null
)
data class PennyDropOptionsContent(
@SerializedName("title")
val title: TextWithStyle? = null,
@SerializedName("subTitle")
val subTitle: TextWithStyle? = null,
@SerializedName("items")
val items: List<PennyDropOption>? = null,
@SerializedName("autoSelectMethod")
val autoSelectMethod: String? = null
)
data class PennyDropOption(
@SerializedName("label")
val label: LabelData? = null,
@SerializedName("title")
val title: TextWithStyle? = null,
@SerializedName("isSelected")
val isSelected: Boolean? = null,
@SerializedName("id")
val id: String? = null,
@SerializedName("subTitle")
val subTitle: TextWithStyle? = null,
@SerializedName("toShowNote")
val toShowNote: Boolean? = null,
@SerializedName("note")
val note: Note? = null,
@SerializedName("actionData")
val actionData : ActionData ?= null
)

View File

@@ -0,0 +1,15 @@
package com.navi.amc.common.model
import com.google.gson.annotations.SerializedName
data class RpdPaymentDetails(
@SerializedName("tokenDetails")
val tokenDetails: TokenDetails? = null,
@SerializedName("methodDetails")
val methodDetails: Map<String, String>? = null
)
data class TokenDetails(
@SerializedName("requestId")
val requestId: String? = null
)

View File

@@ -0,0 +1,43 @@
package com.navi.amc.common.model
import com.google.gson.annotations.SerializedName
import com.navi.amc.kyc.model.Note
import com.navi.common.model.Header
import com.navi.design.textview.model.TextWithStyle
import com.navi.naviwidgets.models.response.DataSafeWidget
data class RpdSuccessScreenData(
@SerializedName("header")
val header: Header? = null,
@SerializedName("content")
val content: RpdSuccessContentData? = null,
@SerializedName("footer")
val footer: Footer? = null
)
data class RpdSuccessContentData(
@SerializedName("iconCode")
val iconCode: String? = null,
@SerializedName("title")
val title: TextWithStyle? = null,
@SerializedName("subTitle")
val subtitle: TextWithStyle? = null,
@SerializedName("details")
val detailsData: DetailsData? =null
)
data class DetailsData(
@SerializedName("items")
val items: List<KeyValueData>? = null,
@SerializedName("note")
val note: Note? = null,
@SerializedName("dataSafeWidget")
val dataSafeWidget: DataSafeWidget? = null
)
data class KeyValueData(
@SerializedName("key")
val key: TextWithStyle? = null,
@SerializedName("value")
val value: TextWithStyle? = null
)

View File

@@ -0,0 +1,50 @@
package com.navi.amc.common.repo
import com.google.gson.reflect.TypeToken
import com.navi.amc.common.model.PennyDropOptionsScreenData
import com.navi.amc.network.retrofit.RetrofitService
import com.navi.amc.utils.Constant.PAYMENTS
import com.navi.amc.utils.mockApiResponse
import com.navi.common.network.models.RepoResult
import com.navi.common.network.retrofit.ResponseCallback
import javax.inject.Inject
class PennyDropOptionsRepository @Inject constructor(private val retrofitService: RetrofitService) :
ResponseCallback() {
/*suspend fun fetchPennyDropOptions(
token: String,
xTarget: String = PAYMENTS
): RepoResult<PennyDropOptionsScreenData> {
val type = object : TypeToken<PennyDropOptionsScreenData>() {}.type
return mockApiResponse(type, "penny_drop")
}*/
suspend fun fetchPennyDropOptions(
token: String,
xTarget: String = PAYMENTS
) = apiResponseCallback(retrofitService.fetchPennyDropOptions(token, xTarget))
/*suspend fun fetchInitPaymentMethodDetails(
token:String,
xTarget: String = PAYMENTS
) :RepoResult<>{
val type = object : TypeToken<PennyDropOptionsScreenData>() {}.type
return mockApiResponse(type, "penny_drop")
}*/
suspend fun fetchInitPaymentMethodDetails(
methodId: String,
token: String,
xTarget: String = PAYMENTS
) = apiResponseCallback(retrofitService.fetchInitPaymentMethodDetails(methodId, token, xTarget))
suspend fun postSignal(token: String, method: String, xTarget: String = PAYMENTS) =
retrofitService.postPaymentStatus(token, method, xTarget)
suspend fun getRequestConfig(requestId: String?) =
apiResponseCallback(retrofitService.fetchRequestConfig(requestId))
suspend fun checkApiPollStatus(requestId: String?) = apiResponseCallback(retrofitService.checkApiPollStatus(requestId))
}

View File

@@ -0,0 +1,18 @@
package com.navi.amc.common.repo
import com.navi.amc.network.retrofit.RetrofitService
import com.navi.common.network.retrofit.ResponseCallback
import javax.inject.Inject
class RpdSuccessRepository @Inject constructor(private val retrofitService: RetrofitService) :
ResponseCallback() {
/*suspend fun fetchRpdSuccess() : RepoResult<RpdSuccessScreenData> {
val type = object : TypeToken<RpdSuccessScreenData>() {}.type
return mockApiResponse(type, "penny_success")
}*/
suspend fun fetchRpdSuccess() = apiResponseCallback(retrofitService.fetchRpdConfirmDetails())
suspend fun postStatus(status : String) = apiResponseCallback(retrofitService.postStatus(status))
}

View File

@@ -0,0 +1,45 @@
package com.navi.amc.common.view
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import androidx.databinding.DataBindingUtil
import com.navi.amc.R
import com.navi.amc.databinding.ShimmerNoteViewBinding
import com.navi.amc.kyc.model.Note
import com.navi.base.utils.orFalse
import com.navi.design.utils.*
import com.navi.naviwidgets.utils.REWARDS_TOOLTIP_ANIMATION_DELAY
class ShimmerNoteView(context: Context, attributes: AttributeSet? = null) :
ConstraintLayout(context, attributes) {
private var binding: ShimmerNoteViewBinding
init {
val inflater = LayoutInflater.from(context)
layoutParams = LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT)
binding = DataBindingUtil.inflate(inflater, R.layout.shimmer_note_view, this, true)
}
fun setProperties(data: Note) {
binding.title.setSpannableString(data.title)
if (data.toShowShimmer.orFalse()) {
binding.shimmer.isVisible = true
binding.root.post {
moveViewWithDistance(
binding.shimmer,
binding.root.width,
REWARDS_TOOLTIP_ANIMATION_DELAY
)
}
}
binding.root.background = getNaviDrawable(
cornerRadius = dpToPxInInt(8),
backgroundColor = data.bgColor.parseColorSafe()
)
}
}

View File

@@ -0,0 +1,99 @@
package com.navi.amc.common.viewmodel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.navi.amc.common.model.*
import com.navi.amc.common.repo.PennyDropOptionsRepository
import com.navi.amc.utils.Constant.INVALID_TOKEN
import com.navi.common.model.UploadDataAsyncResponse
import com.navi.common.network.models.RepoResult
import com.navi.common.viewmodel.BaseVM
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class PennyDropOptionsViewModel @Inject constructor(private val repository: PennyDropOptionsRepository) :
BaseVM() {
var requestId: String? = null
private val _pennyDropOptionsData = MutableLiveData<PennyDropOptionsScreenData?>()
val pennyDropOptionsData: LiveData<PennyDropOptionsScreenData?>
get() = _pennyDropOptionsData
private val _rpdPaymentDetails = MutableLiveData<RpdPaymentDetails?>()
val rpdPaymentDetails: LiveData<RpdPaymentDetails?>
get() = _rpdPaymentDetails
private val _tokenExpire = MutableLiveData<Boolean>()
val tokenExpire: LiveData<Boolean>
get() = _tokenExpire
private val _requestConfig = MutableLiveData<UploadDataAsyncResponse?>()
val requestConfig: LiveData<UploadDataAsyncResponse?>
get() = _requestConfig
private val _asyncResponse = MutableLiveData<AdditionalDataAsyncResponse<NextCtaResponse?>?>()
val asyncResponse: LiveData<AdditionalDataAsyncResponse<NextCtaResponse?>?>
get() = _asyncResponse
var paymentMethod: PennyDropOption? = null
fun fetchData(token: String) {
viewModelScope.launch {
val response = repository.fetchPennyDropOptions(token = token)
if (response.error == null && response.errors.isNullOrEmpty())
_pennyDropOptionsData.value = response.data
else {
if (response.errors?.singleOrNull { it.code == INVALID_TOKEN } != null) {
_tokenExpire.value = true
} else {
setErrorData(response.errors, response.error)
}
}
}
}
fun fetchInitPaymentMethodDetails(token: String, methodId: String) {
viewModelScope.launch {
val response =
repository.fetchInitPaymentMethodDetails(token = token, methodId = methodId)
if (response.error == null && response.errors.isNullOrEmpty()) {
_rpdPaymentDetails.value = response.data
} else {
setErrorData(response.errors, response.error)
}
}
}
fun postPaymentSignal(token: String, method: String) {
viewModelScope.launch {
repository.postSignal(token, method)
}
}
fun getRequestConfig() {
viewModelScope.launch {
val response = repository.getRequestConfig(requestId)
if (response.error == null && response.errors.isNullOrEmpty()) {
_requestConfig.value = response.data
} else {
setErrorData(response.errors, response.error)
}
}
}
fun checkApiPollStatus() {
viewModelScope.launch {
val response = repository.checkApiPollStatus(requestId)
if (response.error == null && response.errors.isNullOrEmpty()) {
_asyncResponse.value = response.data
} else {
setErrorData(response.errors, response.error)
}
}
}
}

View File

@@ -0,0 +1,45 @@
package com.navi.amc.common.viewmodel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.navi.amc.common.model.RpdSuccessScreenData
import com.navi.amc.common.repo.RpdSuccessRepository
import com.navi.common.constants.API_SUCCESS_CODE
import com.navi.common.viewmodel.BaseVM
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class RpdSuccessViewModel @Inject constructor(private val repository: RpdSuccessRepository) :
BaseVM() {
private val _rpdSuccessData = MutableLiveData<RpdSuccessScreenData>()
val rpdSuccessData: LiveData<RpdSuccessScreenData>
get() = _rpdSuccessData
private val _success = MutableLiveData<Boolean>()
val success: LiveData<Boolean>
get() = _success
fun fetchData() {
viewModelScope.launch {
val response = repository.fetchRpdSuccess()
if (response.error == null && response.errors.isNullOrEmpty()) {
_rpdSuccessData.value = response.data!!
} else {
setErrorData(response.errors, response.error)
}
}
}
fun postStatus(status : String){
viewModelScope.launch{
val response = repository.postStatus(status)
if(response.statusCode == API_SUCCESS_CODE){
_success.value = true
}
}
}
}

View File

@@ -7,12 +7,6 @@
package com.navi.amc.fundbuy.fragments
/*
*
* * Copyright © 2022 by Navi Technologies Limited
* * All rights reserved. Strictly confidential
*
*/
import android.content.Context
import android.net.Uri

View File

@@ -27,6 +27,7 @@ import com.navi.amc.kyc.model.BankDetailsResponse
import com.navi.amc.kyc.viewmodel.BankDetailsVM
import com.navi.amc.utils.*
import com.navi.base.model.ActionData
import com.navi.base.model.LineItem
import com.navi.base.model.NaviClickAction
import com.navi.base.model.NaviWidgetClickWithActionData
import com.navi.common.listeners.FragmentInterchangeListener

View File

@@ -34,4 +34,5 @@ data class Note(
@SerializedName("bgColor") val bgColor: String? = null,
@SerializedName("iconCode") val iconCode: String? = null,
@SerializedName("title") val title: TextWithStyle? = null,
@SerializedName("toShowShimmer") val toShowShimmer: Boolean? = null
) : Parcelable

View File

@@ -33,6 +33,27 @@ class NaviHttpClient(networkInfo: NetworkInfo, private val context: Context) :
)
}
}
okHttpClientBuilder.addInterceptor {
val oldRequest = it.request()
val newRequest = oldRequest.newBuilder()
val newHeaders = oldRequest.headers.newBuilder()
val multiMap = oldRequest.headers.toMultimap()
for (pair in multiMap) {
if (pair.value.size > 1) {
newHeaders.removeAll(pair.key)
newHeaders.add(pair.key, pair.value.first())
}
}
newRequest.headers(newHeaders.build())
it.proceed(newRequest.build())
}
return okHttpClientBuilder
}

View File

@@ -368,4 +368,36 @@ interface RetrofitService {
@GET("/fund/fund-details-nfo")
suspend fun fetchNfoDetails(@Query("isin") isin: String): Response<GenericResponse<NfoDetailsScreenData>>
@GET("/payment-method")
suspend fun fetchPennyDropOptions(
@Header("X-Payments-SDK-Token") token: String,
@Header("X-Target") header: String
): Response<GenericResponse<PennyDropOptionsScreenData>>
@GET("/payment-method/details/{methodId}")
suspend fun fetchInitPaymentMethodDetails(
@Path("methodId") methodId: String,
@Header("X-Payments-SDK-Token") token: String,
@Header("X-Target") header: String
): Response<GenericResponse<RpdPaymentDetails>>
@POST("payment-method/signal/{method}")
suspend fun postPaymentStatus(
@Header("X-Payments-SDK-Token") token: String,
@Path("method") method: String,
@Header("X-Target") xTarget: String
): Response<Any>
@GET("/kyc/rpd-confirm-page")
suspend fun fetchRpdConfirmDetails(): Response<GenericResponse<RpdSuccessScreenData>>
@GET("/requests/{requestId}/request-details-config")
suspend fun fetchRequestConfig(@Path("requestId") requestId: String?): Response<GenericResponse<UploadDataAsyncResponse>>
@GET("/requests/{requestId}")
suspend fun checkApiPollStatus(@Path("requestId") requestId: String?): Response<GenericResponse<AdditionalDataAsyncResponse<NextCtaResponse?>?>>
@POST("/kyc/rpd/bank-status/{status}")
suspend fun postStatus(@Path("status") status : String):Response<GenericResponse<Any>>
}

View File

@@ -156,6 +156,10 @@ object AmcAnalytics {
const val COARSE_LOCATION_PERMISSION_ALLOWED = "amc_btn_permission_coarse_location_allow"
const val COARSE_LOCATION_PERMISSION_DENIED = "amc_btn_permission_coarse_location_deny"
const val NFO_SCREEN = "nfoScreen"
const val BANK_VERIFICATION_OPTIONS = "bank_verification_options"
const val PENNY_DROP_OPTIONS = "amc_init_kyc_bank_verify"
const val CHANGE_BANK = "changeBank"
const val RPD_SUCCESS_SCREEN = "amc_init_kyc_bank_verify_success"
const val AMC_INIT_SIMPLIFIED_LUMPSUM = "amc_init_simplified_lumpsum"
const val AMC_INIT_SIMPLIFIED_SIP = "amc_init_simplified_sip"

View File

@@ -81,6 +81,13 @@ object Constant {
const val DOWNLOADING = "Downloading"
const val V2 ="v2"
const val PACKAGE = "package:"
const val TOKEN = "token"
const val PAYMENTS = "PAYMENTS"
const val RPD = "RPD"
const val UPILINK= "upiLink"
const val INVALID_TOKEN = "INVALID_TOKEN"
const val CHANGE_BANK = "CHANGE_BANK"
const val CONFIRMED = "CONFIRMED"
const val BUSINESS_VERTICAL_AMC = "AMC"
const val UPI = "UPI"
}

View File

@@ -197,6 +197,8 @@ fun getFragment(screen: String, bundle: Bundle): Fragment? {
SubPageStatusType.SIP_DETAILS_MODIFY -> ModifySipDetailsFragment.newInstance(bundle)
SubPageStatusType.SIP_MODIFICATION -> SipModifyFragment.newInstance(bundle)
SubPageStatusType.NFO_DETAILS -> NfoDetailsFragment.newInstance(bundle)
SubPageStatusType.BANK_ADDITION_OPTIONS -> PennyDropOptionsFragment.newInstance(bundle)
SubPageStatusType.RPD_SUCCESS -> RpdSuccessFragment.newInstance(bundle)
else -> null
}
}

View File

@@ -53,4 +53,6 @@ object SubPageStatusType {
const val AMC_COMMON_BOTTOMSHEET = "AMC_COMMON_BOTTOMSHEET"
const val BANNER_HORIZONTAL_BOTTOMSHEET = "BANNER_HORIZONTAL_BOTTOMSHEET"
const val NFO_DETAILS = "nfo_details"
const val BANK_ADDITION_OPTIONS = "bank_addition_options"
const val RPD_SUCCESS = "rpd_success"
}

View File

@@ -27,7 +27,7 @@
layout="@layout/amc_fund_list_reward"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dp_8"/>
android:layout_marginBottom="@dimen/dp_8" />
<com.navi.amc.fundbuy.views.AmcHeaderView
android:id="@+id/header"

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.navi.design.textview.NaviTextView
android:id="@+id/key"
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_16"
android:gravity="start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/value"
app:layout_constraintStart_toStartOf="parent"
tools:text="Bank name"
app:layout_constraintTop_toTopOf="parent" />
<com.navi.design.textview.NaviTextView
android:id="@+id/value"
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_16"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="HDFC"
android:gravity="end"
app:layout_constraintStart_toEndOf="@id/key"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.navi.design.textview.NaviTextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:letterSpacing="0.16"
android:paddingStart="@dimen/dp_8"
android:paddingTop="@dimen/dp_2"
android:paddingEnd="@dimen/dp_8"
android:paddingBottom="@dimen/dp_2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="RECOMMENDED" />
<com.navi.design.textview.NaviTextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_16"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Via UPI" />
<com.navi.design.textview.NaviTextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_4"
android:layout_marginBottom="@dimen/dp_16"
app:layout_constraintBottom_toTopOf="@id/note"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title"
tools:text="Deposit ₹1 via Gpay, Phonepe etc." />
<RadioButton
android:id="@+id/radio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/dp_16"
android:button="@drawable/radio_selector"
app:layout_constraintBottom_toTopOf="@id/note"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.navi.design.textview.NaviTextView
android:id="@+id/note"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_1"
android:layout_marginEnd="@dimen/dp_1"
android:layout_marginBottom="@dimen/dp_1"
android:gravity="center"
android:paddingStart="@dimen/dp_16"
android:paddingTop="@dimen/dp_8"
android:paddingEnd="@dimen/dp_16"
android:paddingBottom="@dimen/dp_8"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/subtitle"
tools:text="Amount will be refunded within 24-48 hours" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.navi.design.textview.NaviTextView
android:id="@+id/title"
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_8"
android:layout_marginEnd="@dimen/dp_16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Bank Verification" />
<com.navi.design.textview.NaviTextView
android:id="@+id/subtitle"
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_4"
android:layout_marginEnd="@dimen/dp_16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title"
tools:text="Choose options to verify your bank details" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/options"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_0"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_26"
android:layout_marginEnd="@dimen/dp_16"
android:orientation="vertical"
android:visibility="visible"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@id/terms"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/subtitle" />
<com.navi.design.textview.NaviTextView
android:id="@+id/terms"
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginEnd="@dimen/dp_16"
app:layout_constraintBottom_toTopOf="@id/footer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<include
android:id="@+id/footer"
layout="@layout/footer_btn"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_96"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="@dimen/dp_0"
app:layout_constraintBottom_toTopOf="@id/footer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/dp_100">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon"
android:layout_width="@dimen/dp_60"
android:layout_height="@dimen/dp_60"
android:layout_marginTop="@dimen/dp_32"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.navi.design.textview.NaviTextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_30"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/icon"
tools:text="Verification successful" />
<com.navi.design.textview.NaviTextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_8"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title"
tools:text="Please confirm your bank details to proceed." />
<androidx.cardview.widget.CardView
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_24"
android:layout_marginEnd="@dimen/dp_16"
android:layout_marginBottom="@dimen/dp_2"
app:cardCornerRadius="@dimen/dp_8"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/subtitle">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dp_16"
android:layout_marginTop="@dimen/dp_24"
android:layout_marginEnd="@dimen/dp_16"
android:orientation="vertical" />
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<include
android:id="@+id/data_safe"
layout="@layout/data_safe_layout"
app:layout_constraintBottom_toTopOf="@id/footer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.navi.amc.common.view.FooterView
android:id="@+id/footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.navi.design.textview.NaviTextView
android:id="@+id/title"
android:layout_width="@dimen/dp_0"
android:layout_height="wrap_content"
android:padding="@dimen/dp_16"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Note: Please use ONLY this account for all future transactions to avoid payment failures." />
<com.navi.design.customview.ParallelogramView
android:id="@+id/shimmer"
android:layout_width="@dimen/dp_32"
android:layout_height="@dimen/dp_0"
android:layout_gravity="start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tilt_direction="forward" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -37,7 +37,8 @@ interface ApiCallListener {
showFullScreenError: Boolean = false,
container: Int? = null,
showNewDesignSystemFragment: Boolean = false,
actionErrorV2Enabled: Boolean = false
actionErrorV2Enabled: Boolean = false,
buttonListener: ((String) -> Unit)? = null
)
fun onWarning(

View File

@@ -170,7 +170,8 @@ abstract class BaseActivity :
showFullScreenError: Boolean = false,
container: Int? = null,
showNewDesignSystemFragment: Boolean = false,
actionErrorV2Enabled: Boolean = false
actionErrorV2Enabled: Boolean = false,
buttonListener: ((String) -> Unit)? = null
) {
if (viewModel.errorResponse.hasActiveObservers()) return
viewModel.errorResponse.observeNonNull(this) { response ->
@@ -218,8 +219,9 @@ abstract class BaseActivity :
sourceScreenName = eventTrackingScreenName
?: getCurrentFragmentScreenName(),
secondaryAction = actions?.getOrNull(1)?.first,
moduleName = getCurrentModuleName()
)
moduleName = getCurrentModuleName(),
buttonListener = buttonListener
)
ft.add(errorFragment, NewActionErrorFragment.TAG)
ft.commitAllowingStateLoss()
} else {
@@ -442,7 +444,8 @@ abstract class BaseActivity :
showFullScreenError: Boolean,
container: Int?,
showNewDesignSystemFragment: Boolean,
actionErrorV2Enabled: Boolean
actionErrorV2Enabled: Boolean,
buttonListener: ((String) -> Unit)?
) {
initError(
viewModel,
@@ -453,7 +456,8 @@ abstract class BaseActivity :
showFullScreenError,
container,
showNewDesignSystemFragment,
actionErrorV2Enabled
actionErrorV2Enabled,
buttonListener
)
}

View File

@@ -76,7 +76,8 @@ abstract class BaseFragment : Fragment() {
showFullScreenError: Boolean = false,
container: Int? = null,
showNewDesignSystemFragment: Boolean = false,
actionErrorV2Enabled: Boolean = false
actionErrorV2Enabled: Boolean = false ,
buttonListener: ((String) -> Unit)? = null
) {
apiCallListener?.onError(
viewModel,
@@ -87,7 +88,8 @@ abstract class BaseFragment : Fragment() {
showFullScreenError,
container,
showNewDesignSystemFragment,
actionErrorV2Enabled
actionErrorV2Enabled,
buttonListener
)
}

View File

@@ -37,6 +37,7 @@ class NewActionErrorFragment : BaseBottomSheet() {
private var cancelableDialog: Boolean = true
private var error: GenericErrorResponse? = null
private val analyticsTracker = CommonNaviAnalytics.naviAnalytics.ErrorBottomSheet()
private var buttonListener: ((String) -> Unit)? = null
override fun setContainerView(viewStub: ViewStub) {
viewStub.layoutResource = R.layout.new_action_error_fragment
@@ -108,12 +109,18 @@ class NewActionErrorFragment : BaseBottomSheet() {
view.tag = error?.code
action?.let { action?.onClick(view) }
?: kotlin.run { openErrorCta(error?.actions?.firstOrNull()) }
error?.actions?.getOrNull(0)?.url?.let {
buttonListener?.invoke(it)
}
dismissDialog()
}
if (error?.actions?.size.orZero() > 1) {
binding.secondaryAbv.visibility = View.VISIBLE
binding.secondaryAbv.setOnClickListener { view ->
view.tag = error?.code
error?.actions?.getOrNull(1)?.url?.let{
buttonListener?.invoke(it)
}
secondaryAction?.let { secondaryAction?.onClick(view) }
?: kotlin.run { openErrorCta(error?.actions?.getOrNull(1)) }
dismissDialog()
@@ -205,11 +212,13 @@ class NewActionErrorFragment : BaseBottomSheet() {
cancelable: Boolean = true,
sourceScreenName: String?,
secondaryAction: View.OnClickListener? = null,
moduleName: String? = null
moduleName: String? = null,
buttonListener: ((String) -> Unit)? = null
) =
NewActionErrorFragment().apply {
this.action = action
this.secondaryAction = secondaryAction
this.buttonListener = buttonListener
arguments =
Bundle().apply {
error?.let { putParcelable(ERROR_DATA, it) }