Skip to content

Commit 111ee98

Browse files
committed
chore: ensure email flow shares vm properly
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 0996a58 commit 111ee98

7 files changed

Lines changed: 46 additions & 33 deletions

File tree

apps/flipcash/features/contact-verification/src/main/kotlin/com/flipcash/app/contact/verification/VerificationFlowScreen.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,17 @@ class VerificationFlowScreen(
4848
}
4949
}
5050

51+
LifecycleEffectOnce {
52+
PhoneVerificationFlow.start(origin)
53+
EmailVerificationFlow.start(EmailDeeplinkOrigin.fromScreenProvider(origin))
54+
}
55+
5156
val screens = buildScreenSet(includePhone, includeEmail, emailAddress, emailVerificationCode)
5257
if (screens.isEmpty()) {
5358
goToTargetOrReturn()
5459
return
5560
}
5661

57-
LifecycleEffectOnce {
58-
PhoneVerificationFlow.start(origin)
59-
EmailVerificationFlow.start(EmailDeeplinkOrigin.fromScreenProvider(origin))
60-
}
61-
6262
Navigator(screens.toList()) { navigator ->
6363
val flowNavigator = remember {
6464
VerificationFlowNavigator(
@@ -98,10 +98,11 @@ private fun buildScreenSet(
9898
}
9999

100100
if (includeEmail) {
101+
val vmKey = EmailVerificationFlow.key
101102
return buildSet {
102103
add(EmailVerificationScreen())
103104
if (emailAddress != null && emailVerificationCode != null) {
104-
add(EmailMagicLinkScreen(emailAddress, emailVerificationCode))
105+
add(EmailMagicLinkScreen( emailAddress, emailVerificationCode))
105106
}
106107
}
107108
}

apps/flipcash/features/contact-verification/src/main/kotlin/com/flipcash/app/contact/verification/email/EmailMagicLinkScreen.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class EmailMagicLinkScreen(
6060
BackHandler {
6161
flowNavigator.exit()
6262
}
63+
6364
Column(
6465
modifier = Modifier.fillMaxSize(),
6566
horizontalAlignment = Alignment.CenterHorizontally,

apps/flipcash/features/contact-verification/src/main/kotlin/com/flipcash/app/contact/verification/internal/email/EmailEntryScreen.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,13 @@ import androidx.compose.foundation.text.KeyboardOptions
1616
import androidx.compose.foundation.text.input.TextFieldState
1717
import androidx.compose.material.Text
1818
import androidx.compose.runtime.Composable
19-
import androidx.compose.runtime.SideEffect
2019
import androidx.compose.runtime.getValue
2120
import androidx.compose.runtime.remember
2221
import androidx.compose.ui.Alignment
2322
import androidx.compose.ui.Alignment.Companion.Center
2423
import androidx.compose.ui.Modifier
2524
import androidx.compose.ui.focus.FocusRequester
2625
import androidx.compose.ui.focus.focusRequester
27-
import androidx.compose.ui.layout.onPlaced
2826
import androidx.compose.ui.platform.LocalFocusManager
2927
import androidx.compose.ui.res.stringResource
3028
import androidx.compose.ui.text.input.ImeAction
@@ -58,7 +56,6 @@ private fun EmailEntryScreenContent(
5856
dispatchEvent: (EmailVerificationViewModel.Event) -> Unit,
5957
) {
6058
val focusRequester = remember { FocusRequester() }
61-
val focusManager = LocalFocusManager.current
6259
val keyboard = rememberKeyboardController()
6360

6461
CodeScaffold(

apps/flipcash/features/contact-verification/src/main/kotlin/com/flipcash/app/contact/verification/internal/email/EmailMagicLinkScreen.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.flipcash.app.contact.verification.internal.email
22

33
import androidx.compose.foundation.Image
44
import androidx.compose.foundation.background
5-
import androidx.compose.foundation.layout.Arrangement
65
import androidx.compose.foundation.layout.Box
76
import androidx.compose.foundation.layout.Column
87
import androidx.compose.foundation.layout.Spacer
@@ -31,11 +30,9 @@ import androidx.compose.ui.text.style.TextAlign
3130
import androidx.compose.ui.text.style.TextDecoration
3231
import androidx.compose.ui.tooling.preview.Preview
3332
import androidx.lifecycle.compose.collectAsStateWithLifecycle
34-
import com.flipcash.app.contact.verification.internal.phone.PhoneVerificationViewModel
3533
import com.flipcash.app.theme.FlipcashDesignSystem
3634
import com.flipcash.features.contact.verification.R
3735
import com.getcode.theme.CodeTheme
38-
import com.getcode.ui.core.debugBounds
3936
import com.getcode.ui.theme.ButtonState
4037
import com.getcode.ui.theme.CodeButton
4138
import com.getcode.ui.theme.CodeCircularProgressIndicator

apps/flipcash/features/contact-verification/src/main/kotlin/com/flipcash/app/contact/verification/internal/email/EmailVerificationViewModel.kt

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import com.getcode.util.resources.ResourceHelper
1515
import com.getcode.view.BaseViewModel2
1616
import com.getcode.view.LoadingSuccessState
1717
import dagger.hilt.android.lifecycle.HiltViewModel
18+
import kotlinx.coroutines.Dispatchers
1819
import kotlinx.coroutines.delay
1920
import kotlinx.coroutines.flow.distinctUntilChanged
2021
import kotlinx.coroutines.flow.filterIsInstance
@@ -43,8 +44,8 @@ class EmailVerificationViewModel @Inject constructor(
4344
val email: TextFieldState = TextFieldState(),
4445
val sendingCode: LoadingSuccessState = LoadingSuccessState(),
4546
val verifyingCode: LoadingSuccessState = LoadingSuccessState(),
46-
val isResendTimerRunning: Boolean = true,
47-
val resetTimeRemaining: Int = RESEND_TIMER_MAX,
47+
val isResendTimerRunning: Boolean = false,
48+
val resetTimeRemaining: Int = 0,
4849
val attempts: Int = 0,
4950
) {
5051
val canSendCode: Boolean
@@ -201,22 +202,30 @@ class EmailVerificationViewModel @Inject constructor(
201202
)
202203

203204
timer?.cancel()
204-
timer = fixedRateTimer("timer", false, 0L, 1000) {
205+
timer = fixedRateTimer("email-timer", false, 0L, 1000) {
205206
val remainingTime = stateFlow.value.resetTimeRemaining - 1
206-
if (remainingTime <= 0) cancel()
207-
dispatchEvent(
208-
Event.OnTimerTick(
209-
isRunning = remainingTime > 0,
210-
timeRemaining = remainingTime
207+
if (remainingTime <= 0) stopTimer()
208+
viewModelScope.launch {
209+
dispatchEvent(
210+
Dispatchers.Main,
211+
Event.OnTimerTick(
212+
isRunning = remainingTime > 0,
213+
timeRemaining = remainingTime
214+
)
211215
)
212-
)
216+
}
213217
}
214218
}
215219

216220
private fun stopTimer() {
217221
timer?.cancel()
218222
}
219223

224+
override fun onCleared() {
225+
super.onCleared()
226+
stopTimer()
227+
}
228+
220229
internal companion object {
221230
val updateStateForEvent: (Event) -> ((State) -> State) = { event ->
222231
when (event) {

apps/flipcash/features/contact-verification/src/main/kotlin/com/flipcash/app/contact/verification/internal/phone/PhoneCodeScreen.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ private fun PhoneCodeScreenContent(
122122
)
123123
} else {
124124
val text = buildAnnotatedString {
125-
append(stringResource(R.string.subtitle_didntGetCode))
125+
append(stringResource(R.string.subtitle_didntGetCode)
126+
.replaceParam(state.formattedPhone))
126127
append(" ")
127128
pushLink(
128129
LinkAnnotation.Clickable(

apps/flipcash/features/contact-verification/src/main/kotlin/com/flipcash/app/contact/verification/internal/phone/PhoneVerificationViewModel.kt

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package com.flipcash.app.contact.verification.internal.phone
33
import androidx.compose.foundation.text.input.TextFieldState
44
import androidx.compose.runtime.snapshotFlow
55
import androidx.lifecycle.viewModelScope
6-
import com.flipcash.app.contact.verification.internal.email.EmailVerificationViewModel
76
import com.flipcash.app.core.extensions.onResult
87
import com.flipcash.app.phone.CountryLocale
98
import com.flipcash.app.phone.PhoneUtils
@@ -17,6 +16,7 @@ import com.getcode.util.resources.ResourceHelper
1716
import com.getcode.view.BaseViewModel2
1817
import com.getcode.view.LoadingSuccessState
1918
import dagger.hilt.android.lifecycle.HiltViewModel
19+
import kotlinx.coroutines.Dispatchers
2020
import kotlinx.coroutines.delay
2121
import kotlinx.coroutines.flow.distinctUntilChanged
2222
import kotlinx.coroutines.flow.filterIsInstance
@@ -25,7 +25,6 @@ import kotlinx.coroutines.flow.launchIn
2525
import kotlinx.coroutines.flow.map
2626
import kotlinx.coroutines.flow.mapNotNull
2727
import kotlinx.coroutines.flow.onEach
28-
import kotlinx.coroutines.flow.update
2928
import kotlinx.coroutines.launch
3029
import java.util.Timer
3130
import javax.inject.Inject
@@ -52,8 +51,8 @@ internal class PhoneVerificationViewModel @Inject constructor(
5251
val selectedLocale: CountryLocale = CountryLocale.Stub,
5352
val sendingCode: LoadingSuccessState = LoadingSuccessState(),
5453
val verifyingCode: LoadingSuccessState = LoadingSuccessState(),
55-
val isResendTimerRunning: Boolean = true,
56-
val resetTimeRemaining: Int = RESEND_TIMER_MAX,
54+
val isResendTimerRunning: Boolean = false,
55+
val resetTimeRemaining: Int = 0,
5756
val attempts: Int = 0,
5857
) {
5958
internal val otpLength = 6
@@ -278,22 +277,30 @@ internal class PhoneVerificationViewModel @Inject constructor(
278277
)
279278

280279
timer?.cancel()
281-
timer = fixedRateTimer("timer", false, 0L, 1000) {
280+
timer = fixedRateTimer("phone-timer", false, 0L, 1000) {
282281
val remainingTime = stateFlow.value.resetTimeRemaining - 1
283-
if (remainingTime <= 0) cancel()
284-
dispatchEvent(
285-
Event.OnTimerTick(
286-
isRunning = remainingTime > 0,
287-
timeRemaining = remainingTime
282+
if (remainingTime <= 0) stopTimer()
283+
viewModelScope.launch {
284+
dispatchEvent(
285+
Dispatchers.Main,
286+
Event.OnTimerTick(
287+
isRunning = remainingTime > 0,
288+
timeRemaining = remainingTime
289+
)
288290
)
289-
)
291+
}
290292
}
291293
}
292294

293295
private fun stopTimer() {
294296
timer?.cancel()
295297
}
296298

299+
override fun onCleared() {
300+
super.onCleared()
301+
stopTimer()
302+
}
303+
297304
internal companion object {
298305
val updateStateForEvent: (Event) -> ((State) -> State) = { event ->
299306
when (event) {

0 commit comments

Comments
 (0)