Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package com.flipcash.app.contact.verification.internal.phone
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.runtime.snapshotFlow
import androidx.lifecycle.viewModelScope
import com.flipcash.app.analytics.Action
import com.flipcash.app.analytics.FlipcashAnalyticsService
import com.flipcash.app.core.extensions.onResult
import com.flipcash.app.featureflags.FeatureFlag
import com.flipcash.app.featureflags.FeatureFlagController
import com.flipcash.app.phone.CountryLocale
import com.flipcash.app.phone.PhoneUtils
Expand Down Expand Up @@ -50,6 +51,7 @@ internal class PhoneVerificationViewModel @Inject constructor(
private val featureFlags: FeatureFlagController,
private val resources: ResourceHelper,
private val dispatchers: DispatcherProvider,
private val analytics: FlipcashAnalyticsService,
) : BaseViewModel<PhoneVerificationViewModel.State, PhoneVerificationViewModel.Event>(
initialState = State(),
updateStateForEvent = updateStateForEvent,
Expand Down Expand Up @@ -140,7 +142,7 @@ internal class PhoneVerificationViewModel @Inject constructor(
val cleanedNumber = phoneUtils.cleanNumber(number, locale)
ContactMethod.Phone(cleanedNumber)
}
.onEach { handleSendVerificationCode(it) }
.onEach { handleSendVerificationCode(it, false) }
.launchIn(viewModelScope)

eventFlow
Expand All @@ -151,7 +153,7 @@ internal class PhoneVerificationViewModel @Inject constructor(
val cleanedNumber = phoneUtils.cleanNumber(number, locale)
ContactMethod.Phone(cleanedNumber)
}
.onEach { handleSendVerificationCode(it) }
.onEach { handleSendVerificationCode(it, true) }
.launchIn(viewModelScope)

eventFlow
Expand Down Expand Up @@ -179,6 +181,7 @@ internal class PhoneVerificationViewModel @Inject constructor(

viewModelScope.launch {
delay(1.seconds)
analytics.action(Action.VerifiedPhoneNumber)
dispatchEvent(Event.OnCodeVerified)
dispatchEvent(Event.OnVerifyingCodeChanged())
}
Expand Down Expand Up @@ -228,6 +231,7 @@ internal class PhoneVerificationViewModel @Inject constructor(
.onResult(
onSuccess = {
trace(message = "linkForPayment succeeded", type = TraceType.Process)
analytics.action(Action.LinkedPhoneNumber)
dispatchEvent(Event.OnPhoneVerificationComplete)
},
onError = {
Expand Down Expand Up @@ -288,7 +292,7 @@ internal class PhoneVerificationViewModel @Inject constructor(
}.launchIn(viewModelScope)
}

private suspend fun handleSendVerificationCode(method: ContactMethod) {
private suspend fun handleSendVerificationCode(method: ContactMethod, isResend: Boolean) {
dispatchEvent(Event.OnSendingCodeChanged(loading = true))
if (stateFlow.value.attempts >= 3) {
dispatchEvent(Event.OnSendingCodeChanged())
Expand All @@ -301,6 +305,10 @@ internal class PhoneVerificationViewModel @Inject constructor(
return
}

if (!isResend) {
analytics.action(Action.EnteredPhoneNumber)
}

verificationController.sendVerificationCode(method)
.onSuccess {
dispatchEvent(Event.OnSendingCodeChanged(success = true))
Expand Down Expand Up @@ -336,17 +344,6 @@ internal class PhoneVerificationViewModel @Inject constructor(
}
}

suspend fun awaitLinkForPayment() {
val isEnabled = featureFlags.observe(FeatureFlag.PhoneNumberSend).value ||
userManager.state.value.flags?.enablePhoneNumberSend == true
if (!isEnabled) return

val number = stateFlow.value.numberTextFieldState.text.toString()
val locale = stateFlow.value.selectedLocale
val cleanedNumber = phoneUtils.cleanNumber(number, locale)
verificationController.linkForPayment(ContactMethod.Phone(cleanedNumber))
}

private fun startTimer() {
dispatchEvent(
Event.OnTimerTick(
Expand Down Expand Up @@ -376,7 +373,6 @@ internal class PhoneVerificationViewModel @Inject constructor(
}

override fun onCleared() {
super.onCleared()
stopTimer()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ package com.flipcash.app.analytics
import com.getcode.libs.analytics.AppAction

sealed interface Action : AppAction {
data object EnteredPhoneNumber : Action {
override val value: String = "Entered Phone Number"
}
data object VerifiedPhoneNumber: Action {
override val value: String = "Verified Phone Number"
}

data object LinkedPhoneNumber: Action {
override val value: String = "Linked Phone Number"
}

data object CompletedOnboarding : Action {
override val value: String = "Complete Onboarding"
}
Expand Down
1 change: 1 addition & 0 deletions apps/flipcash/shared/contacts/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies {

implementation(project(":services:flipcash"))
implementation(project(":services:opencode"))
implementation(project(":apps:flipcash:shared:analytics"))
implementation(project(":apps:flipcash:shared:persistence:db"))
implementation(project(":apps:flipcash:shared:persistence:sources"))
implementation(project(":apps:flipcash:shared:phone"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import androidx.datastore.preferences.preferencesDataStoreFile
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import com.flipcash.app.analytics.Action
import com.flipcash.app.analytics.FlipcashAnalyticsService
import com.flipcash.app.contacts.device.DeviceContactLookup
import com.flipcash.app.contacts.device.PickedContactData
import com.flipcash.app.contacts.device.ScopeAwareContactReader
Expand Down Expand Up @@ -55,6 +57,7 @@ import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
Expand All @@ -79,6 +82,7 @@ class ContactCoordinator @Inject constructor(
private val userManager: UserManager,
private val featureFlagController: FeatureFlagController,
private val dispatchers: DispatcherProvider,
private val analytics: FlipcashAnalyticsService,
) : SessionListener, DefaultLifecycleObserver {

companion object {
Expand Down Expand Up @@ -265,14 +269,16 @@ class ContactCoordinator @Inject constructor(
// Profile may not be loaded yet on the first Ready transition;
// wait for the verified phone number to arrive.
val phone = userManager.state
.map { it.userProfile?.verifiedPhoneNumber }
.filterNotNull()
.first()

contactVerificationController.linkForPayment(ContactMethod.Phone(phone))
.onSuccess {
contactPrefs.edit { it[KEY_LINKED_FOR_PAYMENT] = true }
}
.mapNotNull { it.userProfile?.verifiedPhoneNumber }
.firstOrNull()

if (phone != null) {
contactVerificationController.linkForPayment(ContactMethod.Phone(phone))
.onSuccess {
analytics.action(Action.LinkedPhoneNumber)
contactPrefs.edit { it[KEY_LINKED_FOR_PAYMENT] = true }
}
}
} finally {
linkMutex.unlock()
}
Expand Down
Loading