Use EventSink lambda in state instead of Flow in Presenter
This commit is contained in:
parent
56e54bb172
commit
1a0c9df1da
43 changed files with 277 additions and 490 deletions
|
|
@ -22,14 +22,6 @@ class ChangeServerNode @AssistedInject constructor(
|
|||
|
||||
private val presenterConnector = presenterConnector(presenter)
|
||||
|
||||
private fun onChangeServer(server: String) {
|
||||
presenterConnector.emitEvent(ChangeServerEvents.SetServer(server))
|
||||
}
|
||||
|
||||
private fun onSubmit() {
|
||||
presenterConnector.emitEvent(ChangeServerEvents.Submit)
|
||||
}
|
||||
|
||||
private fun onSuccess() {
|
||||
navigateUp()
|
||||
}
|
||||
|
|
@ -39,8 +31,6 @@ class ChangeServerNode @AssistedInject constructor(
|
|||
val state by presenterConnector.stateFlow.collectAsState()
|
||||
ChangeServerView(
|
||||
state = state,
|
||||
onChangeServer = this::onChangeServer,
|
||||
onChangeServerSubmit = this::onSubmit,
|
||||
onChangeServerSuccess = this::onSuccess,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,42 @@
|
|||
package io.element.android.x.features.login.changeserver
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import io.element.android.x.architecture.Async
|
||||
import io.element.android.x.architecture.Presenter
|
||||
import io.element.android.x.architecture.execute
|
||||
import io.element.android.x.matrix.Matrix
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class ChangeServerPresenter @Inject constructor(private val matrix: Matrix) : Presenter<ChangeServerState, ChangeServerEvents> {
|
||||
class ChangeServerPresenter @Inject constructor(private val matrix: Matrix) : Presenter<ChangeServerState> {
|
||||
|
||||
@Composable
|
||||
override fun present(events: Flow<ChangeServerEvents>): ChangeServerState {
|
||||
override fun present(): ChangeServerState {
|
||||
val localCoroutineScope = rememberCoroutineScope()
|
||||
val homeserver = rememberSaveable {
|
||||
mutableStateOf(matrix.getHomeserverOrDefault())
|
||||
}
|
||||
val changeServerAction: MutableState<Async<Unit>> = remember {
|
||||
mutableStateOf(Async.Uninitialized)
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
events.collect { event ->
|
||||
when (event) {
|
||||
is ChangeServerEvents.SetServer -> homeserver.value = event.server
|
||||
ChangeServerEvents.Submit -> submit(homeserver.value, changeServerAction)
|
||||
}
|
||||
|
||||
fun handleEvents(event: ChangeServerEvents) {
|
||||
when (event) {
|
||||
is ChangeServerEvents.SetServer -> homeserver.value = event.server
|
||||
ChangeServerEvents.Submit -> localCoroutineScope.submit(homeserver.value, changeServerAction)
|
||||
}
|
||||
}
|
||||
|
||||
return ChangeServerState(
|
||||
homeserver = homeserver.value,
|
||||
changeServerAction = changeServerAction.value
|
||||
changeServerAction = changeServerAction.value,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import io.element.android.x.architecture.Async
|
|||
data class ChangeServerState(
|
||||
val homeserver: String = "",
|
||||
val changeServerAction: Async<Unit> = Async.Uninitialized,
|
||||
val eventSink: (ChangeServerEvents) -> Unit = {},
|
||||
) {
|
||||
val submitEnabled = homeserver.isNotEmpty() && changeServerAction !is Async.Loading
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,14 +64,13 @@ import io.element.android.x.features.login.error.changeServerError
|
|||
fun ChangeServerView(
|
||||
state: ChangeServerState,
|
||||
modifier: Modifier = Modifier,
|
||||
onChangeServer: (String) -> Unit = {},
|
||||
onChangeServerSubmit: () -> Unit = {},
|
||||
onChangeServerSuccess: () -> Unit = {},
|
||||
) {
|
||||
Surface(
|
||||
modifier = modifier,
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
) {
|
||||
val eventSink = state.eventSink
|
||||
val scrollState = rememberScrollState()
|
||||
Box(
|
||||
modifier = Modifier
|
||||
|
|
@ -135,7 +134,7 @@ fun ChangeServerView(
|
|||
.padding(top = 200.dp),
|
||||
onValueChange = {
|
||||
homeserverFieldState = it
|
||||
onChangeServer(it)
|
||||
eventSink(ChangeServerEvents.SetServer(it))
|
||||
},
|
||||
label = {
|
||||
Text(text = "Server")
|
||||
|
|
@ -146,7 +145,7 @@ fun ChangeServerView(
|
|||
imeAction = ImeAction.Done,
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = { onChangeServerSubmit() }
|
||||
onDone = { eventSink(ChangeServerEvents.Submit) }
|
||||
)
|
||||
)
|
||||
if (state.changeServerAction is Async.Failure) {
|
||||
|
|
@ -161,7 +160,7 @@ fun ChangeServerView(
|
|||
)
|
||||
}
|
||||
Button(
|
||||
onClick = onChangeServerSubmit,
|
||||
onClick = { eventSink(ChangeServerEvents.Submit) },
|
||||
enabled = state.submitEnabled,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import com.bumble.appyx.core.lifecycle.subscribe
|
||||
import com.bumble.appyx.core.modality.BuildContext
|
||||
import com.bumble.appyx.core.node.Node
|
||||
|
|
@ -13,6 +14,7 @@ import dagger.assisted.Assisted
|
|||
import dagger.assisted.AssistedInject
|
||||
import io.element.android.x.anvilannotations.ContributesNode
|
||||
import io.element.android.x.architecture.presenterConnector
|
||||
import io.element.android.x.core.compose.OnLifecycleEvent
|
||||
import io.element.android.x.di.AppScope
|
||||
|
||||
@ContributesNode(AppScope::class)
|
||||
|
|
@ -24,12 +26,6 @@ class LoginRootNode @AssistedInject constructor(
|
|||
|
||||
private val presenterConnector = presenterConnector(presenter)
|
||||
|
||||
init {
|
||||
lifecycle.subscribe(
|
||||
onResume = { presenterConnector.emitEvent(LoginRootEvents.RefreshHomeServer) }
|
||||
)
|
||||
}
|
||||
|
||||
interface Callback : Plugin {
|
||||
fun onChangeHomeServer()
|
||||
}
|
||||
|
|
@ -38,27 +34,18 @@ class LoginRootNode @AssistedInject constructor(
|
|||
plugins<Callback>().forEach { it.onChangeHomeServer() }
|
||||
}
|
||||
|
||||
private fun onLoginChanged(login: String) {
|
||||
presenterConnector.emitEvent(LoginRootEvents.SetLogin(login))
|
||||
}
|
||||
|
||||
private fun onPasswordChanged(password: String) {
|
||||
presenterConnector.emitEvent(LoginRootEvents.SetPassword(password))
|
||||
}
|
||||
|
||||
private fun onSubmit() {
|
||||
presenterConnector.emitEvent(LoginRootEvents.Submit)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
val state by presenterConnector.stateFlow.collectAsState()
|
||||
OnLifecycleEvent { _, event ->
|
||||
when (event) {
|
||||
Lifecycle.Event.ON_RESUME -> state.eventSink(LoginRootEvents.RefreshHomeServer)
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
LoginRootScreen(
|
||||
state = state,
|
||||
onChangeServer = this::onChangeHomeServer,
|
||||
onLoginChanged = this::onLoginChanged,
|
||||
onPasswordChanged = this::onPasswordChanged,
|
||||
onSubmitClicked = this::onSubmit
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import io.element.android.x.architecture.Presenter
|
||||
import io.element.android.x.matrix.Matrix
|
||||
|
|
@ -13,10 +14,11 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class LoginRootPresenter @Inject constructor(private val matrix: Matrix) : Presenter<LoginRootState, LoginRootEvents> {
|
||||
class LoginRootPresenter @Inject constructor(private val matrix: Matrix) : Presenter<LoginRootState> {
|
||||
|
||||
@Composable
|
||||
override fun present(events: Flow<LoginRootEvents>): LoginRootState {
|
||||
override fun present(): LoginRootState {
|
||||
val localCoroutineScope = rememberCoroutineScope()
|
||||
val homeserver = rememberSaveable {
|
||||
mutableStateOf(matrix.getHomeserverOrDefault())
|
||||
}
|
||||
|
|
@ -27,24 +29,24 @@ class LoginRootPresenter @Inject constructor(private val matrix: Matrix) : Prese
|
|||
mutableStateOf(LoginFormState.Default)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
events.collect { event ->
|
||||
when (event) {
|
||||
LoginRootEvents.RefreshHomeServer -> refreshHomeServer(homeserver)
|
||||
is LoginRootEvents.SetLogin -> updateFormState(formState) {
|
||||
copy(login = event.login)
|
||||
}
|
||||
is LoginRootEvents.SetPassword -> updateFormState(formState) {
|
||||
copy(password = event.password)
|
||||
}
|
||||
LoginRootEvents.Submit -> submit(homeserver.value, formState.value, loggedInState)
|
||||
fun handleEvents(event: LoginRootEvents){
|
||||
when (event) {
|
||||
LoginRootEvents.RefreshHomeServer -> refreshHomeServer(homeserver)
|
||||
is LoginRootEvents.SetLogin -> updateFormState(formState) {
|
||||
copy(login = event.login)
|
||||
}
|
||||
is LoginRootEvents.SetPassword -> updateFormState(formState) {
|
||||
copy(password = event.password)
|
||||
}
|
||||
LoginRootEvents.Submit -> localCoroutineScope.submit(homeserver.value, formState.value, loggedInState)
|
||||
}
|
||||
}
|
||||
|
||||
return LoginRootState(
|
||||
homeserver = homeserver.value,
|
||||
loggedInState = loggedInState.value,
|
||||
formState = formState.value
|
||||
formState = formState.value,
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,11 +68,9 @@ fun LoginRootScreen(
|
|||
state: LoginRootState,
|
||||
modifier: Modifier = Modifier,
|
||||
onChangeServer: () -> Unit = {},
|
||||
onLoginChanged: (String) -> Unit = {},
|
||||
onPasswordChanged: (String) -> Unit = {},
|
||||
onSubmitClicked: () -> Unit = {},
|
||||
onLoginWithSuccess: (SessionId) -> Unit = {},
|
||||
) {
|
||||
val eventSink = state.eventSink
|
||||
Surface(
|
||||
modifier = modifier,
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
|
|
@ -144,7 +142,7 @@ fun LoginRootScreen(
|
|||
},
|
||||
onValueChange = {
|
||||
loginFieldState = it
|
||||
onLoginChanged(it)
|
||||
eventSink(LoginRootEvents.SetLogin(it))
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Email,
|
||||
|
|
@ -163,7 +161,7 @@ fun LoginRootScreen(
|
|||
.padding(top = 24.dp),
|
||||
onValueChange = {
|
||||
passwordFieldState = it
|
||||
onPasswordChanged(it)
|
||||
eventSink(LoginRootEvents.SetPassword(it))
|
||||
},
|
||||
label = {
|
||||
Text(text = "Password")
|
||||
|
|
@ -185,7 +183,7 @@ fun LoginRootScreen(
|
|||
imeAction = ImeAction.Done,
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = { onSubmitClicked() }
|
||||
onDone = { eventSink(LoginRootEvents.Submit) }
|
||||
),
|
||||
)
|
||||
if (state.loggedInState is LoggedInState.ErrorLoggingIn) {
|
||||
|
|
@ -199,7 +197,7 @@ fun LoginRootScreen(
|
|||
}
|
||||
// Submit
|
||||
Button(
|
||||
onClick = onSubmitClicked,
|
||||
onClick = { eventSink(LoginRootEvents.Submit) },
|
||||
enabled = state.submitEnabled,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ data class LoginRootState(
|
|||
val homeserver: String = "",
|
||||
val loggedInState: LoggedInState = LoggedInState.NotLoggedIn,
|
||||
val formState: LoginFormState = LoginFormState.Default,
|
||||
val eventSink: (LoginRootEvents) -> Unit = {}
|
||||
) {
|
||||
val submitEnabled =
|
||||
formState.login.isNotEmpty() && formState.password.isNotEmpty() && loggedInState != LoggedInState.LoggingIn
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue