electrolobzik
01/04/2024, 2:41 PMArkadii Ivanov
01/04/2024, 5:00 PMinterface PhoneComponent : Store<Intent, State, Nothing> {
sealed interface Intent {
data class SetPhone(val phone: String) : Intent
}
data class State(val phone: String = "")
}
class DefaultPhoneComponent(
componentContext: ComponentContext,
storeFactory: StoreFactory,
) : PhoneComponent, Store<Intent, State, Nothing> by componentContext.instanceKeeper.getStore(
factory = {
storeFactory.create(
name = "PhoneStore",
initialState = State(),
reducer = { reduce(it) },
)
},
)
private fun State.reduce(intent: Intent): State =
when (intent) {
is Intent.SetPhone -> copy(phone = intent.phone)
}
@Composable
fun PhoneContent(component: PhoneComponent) {
val state by component.stateFlow.collectAsState()
TextField(
value = state.phone,
onValueChange = { component.accept(Intent.SetPhone(phone = it)) },
)
}
electrolobzik
01/04/2024, 9:45 PMA
for EnterPhone screen and it’s state, containing phone number (and some other things like is number invalid, is the submit button enabled and so on).
2. Next there is store-component B
for the next EnterOtpCode screen, which state contains OTP code and things related to it’s validation, but also it contains the phone number, because it should be displayed in the UI and needs to be the part of the UI model.
3. The parent store P
which as you said will communicate with the backend also needs the phone number in its state, at least because it should pass this phone number to screen/store B
and to some other screens like “Resend Code” screen.
So I would like to have some sort of synchronisation between this components in terms of state.Arkadii Ivanov
01/04/2024, 10:28 PMinterface PhoneComponent {
val model: StateFlow<Model>
fun onPhoneChanged(phone: String)
data class Model(
val phone: String,
)
}
class DefaultPhoneComponent(
private val onConfirmed: (String) -> Unit,
) : PhoneComponent {
// ...
}
Also EnterOtpCodeComponent in a similar way.
interface EnterOtpCodeComponent {
val model: StateFlow<Model>
fun onCodeChanged(code: String)
data class Model(
val phone: String,
val code: String,
)
}
class DefaultEnterOtpCodeComponent(
private val phone: String,
private val onConfirmed: (String) -> Unit,
) : EnterOtpCodeComponent {
// ...
}
And then the parent just switching the children. Once DefaultEnterOtpCodeComponent#onConfirmed
is called, the parent has both the phone and the code, and can perform further steps.Arkadii Ivanov
01/04/2024, 10:28 PMelectrolobzik
01/05/2024, 10:28 AMArkadii Ivanov
01/05/2024, 10:34 AMelectrolobzik
01/05/2024, 11:55 AMArkadii Ivanov
01/05/2024, 12:30 PMelectrolobzik
01/05/2024, 12:31 PMArkadii Ivanov
01/05/2024, 1:33 PMelectrolobzik
01/05/2024, 2:09 PMelectrolobzik
01/05/2024, 8:12 PMArkadii Ivanov
01/05/2024, 8:30 PMelectrolobzik
01/05/2024, 8:36 PMArkadii Ivanov
01/05/2024, 9:11 PMArkadii Ivanov
01/05/2024, 9:13 PMelectrolobzik
01/05/2024, 9:22 PMelectrolobzik
01/07/2024, 3:51 PMinstanceKeeper.remove(EnterCodeStore::class)
manually in exit points of the component. Is there any better way to do that?
I am getting the store with the following code:
private val store = instanceKeeper.getStore<EnterCodeStore> {
object : EnterCodeStore, Store<Intent, State, Nothing> by storeFactory.create(
name = "EnterCodeStore",
initialState = State(
registrationProgressPercent = registrationProgressPercent,
country = country,
phoneNumber = phoneNumber
),
reducer = { reduce(it) },
executorFactory = ::ExecutorImpl,
) {}
}
Arkadii Ivanov
01/07/2024, 3:53 PMpop
the OTP component when the user goes back, everything should automatically work as you expect, as long as you properly supply the child ComponentContext.Arkadii Ivanov
01/07/2024, 3:54 PMelectrolobzik
01/07/2024, 3:56 PMArkadii Ivanov
01/07/2024, 3:57 PMelectrolobzik
01/07/2024, 4:04 PMprivate val enterPhoneComponent by lazy { createEnterPhoneNumberComponent() }
And now createEnterPhoneNumberComponent
function receives a parameter for ComponentContext. I should replace val with lateinit var
or is there any better approach? I didn’t find any handy function for accessing a child in the stack by it’s type. Should I create one? I am not sure if it’s the right direction. 🙂Arkadii Ivanov
01/07/2024, 4:05 PMelectrolobzik
01/07/2024, 4:41 PMArkadii Ivanov
01/07/2024, 4:45 PMValue<ChildStack>
returned by childStack
function.