Backport minor changes from non-ose (#941)

Login: correctly combine input flows for account details UI state (backport bitfireAT/davx5#575)
This commit is contained in:
Ricki Hirner
2024-07-26 12:04:19 +02:00
committed by GitHub
parent 342314363b
commit c3fe1b04e5
2 changed files with 39 additions and 28 deletions

View File

@@ -40,6 +40,7 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.PopupProperties
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import at.bitfire.davdroid.R
import at.bitfire.davdroid.ui.composable.Assistant
@@ -52,9 +53,8 @@ fun AccountDetailsPage(
onAccountCreated: (Account) -> Unit,
model: LoginScreenModel = viewModel()
) {
val uiState = model.accountDetailsUiState
if (uiState.createdAccount != null)
onAccountCreated(uiState.createdAccount)
val uiState by model.accountDetailsUiState.collectAsStateWithLifecycle()
uiState.createdAccount?.let(onAccountCreated)
val context = LocalContext.current
LaunchedEffect(uiState.couldNotCreateAccount) {

View File

@@ -6,7 +6,6 @@ package at.bitfire.davdroid.ui.setup
import android.accounts.Account
import android.content.Context
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
@@ -24,9 +23,12 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.runInterruptible
import kotlinx.coroutines.withContext
@@ -246,66 +248,75 @@ class LoginScreenModel @AssistedInject constructor(
else
null
}
.stateIn(viewModelScope, SharingStarted.Eagerly, null)
// backing field that is combined with dynamic content for the resulting UI State
private var _accountDetailsUiState by mutableStateOf(AccountDetailsUiState())
val accountDetailsUiState by derivedStateOf {
val method = forcedGroupMethod.value
private var _accountDetailsUiState = MutableStateFlow(AccountDetailsUiState())
val accountDetailsUiState = combine(_accountDetailsUiState, forcedGroupMethod) { uiState, method ->
// set group type to read-only if group method is forced
var combinedState = _accountDetailsUiState.copy(groupMethodReadOnly = method != null)
var combinedState = uiState.copy(groupMethodReadOnly = method != null)
// apply forced group method, if applicable
if (method != null)
combinedState = combinedState.copy(groupMethod = method)
combinedState
}
}.stateIn(viewModelScope, SharingStarted.Lazily, _accountDetailsUiState.value)
fun updateAccountName(accountName: String) {
_accountDetailsUiState = _accountDetailsUiState.copy(
accountName = accountName,
accountNameExists = accountRepository.exists(accountName)
)
_accountDetailsUiState.update { currentState ->
currentState.copy(
accountName = accountName,
accountNameExists = accountRepository.exists(accountName)
)
}
}
fun updateAccountNameAndEmails(accountName: String, emails: Set<String>) {
_accountDetailsUiState = _accountDetailsUiState.copy(
accountName = accountName,
accountNameExists = accountRepository.exists(accountName),
suggestedAccountNames = emails
)
_accountDetailsUiState.update { currentState ->
currentState.copy(
accountName = accountName,
accountNameExists = accountRepository.exists(accountName),
suggestedAccountNames = emails
)
}
}
fun updateGroupMethod(groupMethod: GroupMethod) {
_accountDetailsUiState = _accountDetailsUiState.copy(groupMethod = groupMethod)
_accountDetailsUiState.update { currentState ->
currentState.copy(groupMethod = groupMethod)
}
}
fun resetCouldNotCreateAccount() {
_accountDetailsUiState = _accountDetailsUiState.copy(couldNotCreateAccount = false)
_accountDetailsUiState.update { currentState ->
currentState.copy(couldNotCreateAccount = false)
}
}
fun createAccount() {
_accountDetailsUiState = _accountDetailsUiState.copy(creatingAccount = true)
_accountDetailsUiState.update { currentState ->
currentState.copy(creatingAccount = true)
}
viewModelScope.launch {
val account = withContext(Dispatchers.Default) {
accountRepository.create(
accountDetailsUiState.accountName,
accountDetailsUiState.value.accountName,
loginInfo.credentials,
foundConfig!!,
accountDetailsUiState.groupMethod
accountDetailsUiState.value.groupMethod
)
}
_accountDetailsUiState =
_accountDetailsUiState.update { currentState ->
if (account != null)
accountDetailsUiState.copy(createdAccount = account)
currentState.copy(createdAccount = account)
else
accountDetailsUiState.copy(
currentState.copy(
creatingAccount = false,
couldNotCreateAccount = true
)
}
}
}