Updated on 2026-08-14

This commit is contained in:
Tangem 2023-01-10 14:56:49 +03:00
parent cdebec35d0
commit 64de5b2599
7 changed files with 105 additions and 2 deletions

View file

@ -48,6 +48,7 @@ android {
dependencies {
/** Core modules */
implementation(project(":core:analytics"))
implementation(project(":core:res"))
implementation(project(":core:utils"))
implementation(project(":core:ui"))

View file

@ -30,6 +30,7 @@ class ReferralFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
activity?.window?.let { WindowCompat.setDecorFitsSystemWindows(it, true) }
viewModel.setRouter(ReferralRouter(fragmentManager = WeakReference(parentFragmentManager)))
viewModel.onScreenOpened()
return ComposeView(inflater.context).apply {
isTransitionGroup = true
setContent {

View file

@ -0,0 +1,16 @@
package com.tangem.feature.referral.analytics
import com.tangem.core.analytics.AnalyticsEvent
sealed class ReferralEvents(
event: String,
) : AnalyticsEvent(REFERRAL_PROGRAM_CATEGORY, event) {
object ReferralScreenOpened : ReferralEvents(event = "Referral Screen Opened")
object ClickParticipate : ReferralEvents(event = "Button - Participate")
object ClickCopy : ReferralEvents(event = "Button - Copy")
object ClickShare : ReferralEvents(event = "Button - Share")
object ClickTaC : ReferralEvents(event = "Link - TaC")
}
private const val REFERRAL_PROGRAM_CATEGORY = "Referral program"

View file

@ -4,6 +4,7 @@ internal data class ReferralStateHolder(
val headerState: HeaderState,
val referralInfoState: ReferralInfoState,
val errorSnackbar: ErrorSnackbar? = null,
val analytics: Analytics,
) {
data class HeaderState(val onBackClicked: () -> Unit)
@ -42,4 +43,10 @@ internal data class ReferralStateHolder(
val throwable: Throwable,
val onOkClicked: () -> Unit,
)
data class Analytics(
val onAgreementClicked: () -> Unit,
val onCopyClicked: () -> Unit,
val onShareClicked: () -> Unit,
)
}

View file

@ -37,6 +37,8 @@ internal fun ParticipateBottomBlock(
shareLink: String,
onAgreementClicked: () -> Unit,
showCopySnackbar: () -> Unit,
onCopyClicked: () -> Unit,
onShareClicked: () -> Unit,
) {
Column(
modifier = Modifier
@ -56,7 +58,13 @@ internal fun ParticipateBottomBlock(
),
)
PersonalCodeCard(code = code)
AdditionalButtons(code = code, shareLink = shareLink, showCopySnackbar = showCopySnackbar)
AdditionalButtons(
code = code,
shareLink = shareLink,
showCopySnackbar = showCopySnackbar,
onCopyClicked = onCopyClicked,
onShareClicked = onShareClicked,
)
AgreementText(firstPartResId = R.string.referral_tos_enroled_prefix, onClicked = onAgreementClicked)
}
}
@ -94,7 +102,13 @@ private fun PersonalCodeCard(code: String) {
}
@Composable
private fun AdditionalButtons(code: String, shareLink: String, showCopySnackbar: () -> Unit) {
private fun AdditionalButtons(
code: String,
shareLink: String,
showCopySnackbar: () -> Unit,
onCopyClicked: () -> Unit,
onShareClicked: () -> Unit,
) {
val clipboardManager = LocalClipboardManager.current
val hapticFeedback = LocalHapticFeedback.current
@ -107,6 +121,7 @@ private fun AdditionalButtons(code: String, shareLink: String, showCopySnackbar:
text = stringResource(id = R.string.common_copy),
iconResId = R.drawable.ic_copy,
onClicked = {
onCopyClicked.invoke()
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
clipboardManager.setText(AnnotatedString(code))
showCopySnackbar()
@ -119,6 +134,7 @@ private fun AdditionalButtons(code: String, shareLink: String, showCopySnackbar:
text = stringResource(id = R.string.common_share),
iconResId = R.drawable.ic_share,
onClicked = {
onShareClicked.invoke()
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
context.shareText(context.getString(R.string.referral_share_link, shareLink))
},
@ -147,6 +163,8 @@ fun Preview_ParticipateBottomBlock_InLightTheme() {
shareLink = "",
onAgreementClicked = {},
showCopySnackbar = {},
onCopyClicked = {},
onShareClicked = {},
)
}
}
@ -163,6 +181,8 @@ fun Preview_ParticipateBottomBlock_InDarkTheme() {
shareLink = "",
onAgreementClicked = {},
showCopySnackbar = {},
onCopyClicked = {},
onShareClicked = {},
)
}
}

View file

@ -102,6 +102,7 @@ internal fun ReferralScreen(stateHolder: ReferralStateHolder) {
ReferralContent(
stateHolder = stateHolder,
onAgreementClicked = {
stateHolder.analytics.onAgreementClicked.invoke()
coroutineScope.launch {
if (bottomSheetScaffoldState.bottomSheetState.isCollapsed) {
bottomSheetScaffoldState.bottomSheetState.expand()
@ -191,6 +192,8 @@ private fun ReferralInfo(
shareLink = state.shareLink,
onAgreementClicked = onAgreementClicked,
showCopySnackbar = showCopySnackbar,
onCopyClicked = stateHolder.analytics.onCopyClicked,
onShareClicked = stateHolder.analytics.onShareClicked,
)
}
is ReferralInfoState.NonParticipantContent -> {
@ -479,6 +482,11 @@ fun Preview_ReferralScreen_Participant_InLightTheme() {
url = "",
),
errorSnackbar = null,
analytics = ReferralStateHolder.Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
),
),
)
}
@ -502,6 +510,11 @@ fun Preview_ReferralScreen_Participant_InDarkTheme() {
url = "",
),
errorSnackbar = null,
analytics = ReferralStateHolder.Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
),
),
)
}
@ -522,6 +535,11 @@ fun Preview_ReferralScreen_NonParticipant_InLightTheme() {
onParticipateClicked = {},
),
errorSnackbar = null,
analytics = ReferralStateHolder.Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
),
),
)
}
@ -542,6 +560,11 @@ fun Preview_ReferralScreen_NonParticipant_InDarkTheme() {
onParticipateClicked = {},
),
errorSnackbar = null,
analytics = ReferralStateHolder.Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
),
),
)
}
@ -556,6 +579,11 @@ fun Preview_ReferralScreen_Loading_InLightTheme() {
headerState = ReferralStateHolder.HeaderState(onBackClicked = {}),
referralInfoState = ReferralInfoState.Loading,
errorSnackbar = null,
analytics = ReferralStateHolder.Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
),
),
)
}
@ -570,6 +598,11 @@ fun Preview_ReferralScreen_Loading_InDarkTheme() {
headerState = ReferralStateHolder.HeaderState(onBackClicked = {}),
referralInfoState = ReferralInfoState.Loading,
errorSnackbar = null,
analytics = ReferralStateHolder.Analytics(
onAgreementClicked = {},
onCopyClicked = {},
onShareClicked = {},
),
),
)
}

View file

@ -5,6 +5,8 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.feature.referral.analytics.ReferralEvents
import com.tangem.feature.referral.domain.ReferralInteractor
import com.tangem.feature.referral.domain.models.DiscountType
import com.tangem.feature.referral.domain.models.ReferralData
@ -24,6 +26,7 @@ import kotlin.properties.Delegates
internal class ReferralViewModel @Inject constructor(
private val referralInteractor: ReferralInteractor,
private val dispatchers: CoroutineDispatcherProvider,
private val analyticsEventHandler: AnalyticsEventHandler,
) : ViewModel() {
var uiState: ReferralStateHolder by mutableStateOf(createInitiallyUiState())
@ -40,10 +43,19 @@ internal class ReferralViewModel @Inject constructor(
uiState = uiState.copy(headerState = ReferralStateHolder.HeaderState(onBackClicked = router::back))
}
fun onScreenOpened() {
analyticsEventHandler.send(ReferralEvents.ReferralScreenOpened)
}
private fun createInitiallyUiState() = ReferralStateHolder(
headerState = ReferralStateHolder.HeaderState(onBackClicked = { }),
referralInfoState = ReferralInfoState.Loading,
errorSnackbar = null,
analytics = ReferralStateHolder.Analytics(
onAgreementClicked = ::onAgreementClicked,
onCopyClicked = ::onCopyClicked,
onShareClicked = ::onShareClicked,
),
)
private fun loadReferralData() {
@ -56,6 +68,7 @@ internal class ReferralViewModel @Inject constructor(
}
private fun participate() {
analyticsEventHandler.send(ReferralEvents.ClickParticipate)
uiState = uiState.copy(referralInfoState = ReferralInfoState.Loading)
viewModelScope.launch(dispatchers.main) {
runCatching(dispatchers.io) { referralInteractor.startReferral() }
@ -74,6 +87,18 @@ internal class ReferralViewModel @Inject constructor(
)
}
private fun onAgreementClicked() {
analyticsEventHandler.send(ReferralEvents.ClickTaC)
}
private fun onCopyClicked() {
analyticsEventHandler.send(ReferralEvents.ClickCopy)
}
private fun onShareClicked() {
analyticsEventHandler.send(ReferralEvents.ClickShare)
}
private fun ReferralData.convertToReferralInfoState(): ReferralInfoState = when (this) {
is ReferralData.ParticipantData -> ReferralInfoState.ParticipantContent(
award = getAwardValue(),