Skip to content

Commit c3fe1b0

Browse files
authored
Backport minor changes from non-ose (#941)
Login: correctly combine input flows for account details UI state (backport bitfireAT/davx5#575)
1 parent 3423143 commit c3fe1b0

File tree

2 files changed

+39
-28
lines changed

2 files changed

+39
-28
lines changed

app/src/main/kotlin/at/bitfire/davdroid/ui/setup/AccountDetailsPage.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import androidx.compose.ui.text.input.KeyboardType
4040
import androidx.compose.ui.tooling.preview.Preview
4141
import androidx.compose.ui.unit.dp
4242
import androidx.compose.ui.window.PopupProperties
43+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
4344
import androidx.lifecycle.viewmodel.compose.viewModel
4445
import at.bitfire.davdroid.R
4546
import at.bitfire.davdroid.ui.composable.Assistant
@@ -52,9 +53,8 @@ fun AccountDetailsPage(
5253
onAccountCreated: (Account) -> Unit,
5354
model: LoginScreenModel = viewModel()
5455
) {
55-
val uiState = model.accountDetailsUiState
56-
if (uiState.createdAccount != null)
57-
onAccountCreated(uiState.createdAccount)
56+
val uiState by model.accountDetailsUiState.collectAsStateWithLifecycle()
57+
uiState.createdAccount?.let(onAccountCreated)
5858

5959
val context = LocalContext.current
6060
LaunchedEffect(uiState.couldNotCreateAccount) {

app/src/main/kotlin/at/bitfire/davdroid/ui/setup/LoginScreenModel.kt

+36-25
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package at.bitfire.davdroid.ui.setup
66

77
import android.accounts.Account
88
import android.content.Context
9-
import androidx.compose.runtime.derivedStateOf
109
import androidx.compose.runtime.getValue
1110
import androidx.compose.runtime.mutableStateOf
1211
import androidx.compose.runtime.setValue
@@ -24,9 +23,12 @@ import dagger.hilt.android.lifecycle.HiltViewModel
2423
import dagger.hilt.android.qualifiers.ApplicationContext
2524
import kotlinx.coroutines.Dispatchers
2625
import kotlinx.coroutines.Job
26+
import kotlinx.coroutines.flow.MutableStateFlow
2727
import kotlinx.coroutines.flow.SharingStarted
28+
import kotlinx.coroutines.flow.combine
2829
import kotlinx.coroutines.flow.map
2930
import kotlinx.coroutines.flow.stateIn
31+
import kotlinx.coroutines.flow.update
3032
import kotlinx.coroutines.launch
3133
import kotlinx.coroutines.runInterruptible
3234
import kotlinx.coroutines.withContext
@@ -246,66 +248,75 @@ class LoginScreenModel @AssistedInject constructor(
246248
else
247249
null
248250
}
249-
.stateIn(viewModelScope, SharingStarted.Eagerly, null)
250251

251252
// backing field that is combined with dynamic content for the resulting UI State
252-
private var _accountDetailsUiState by mutableStateOf(AccountDetailsUiState())
253-
val accountDetailsUiState by derivedStateOf {
254-
val method = forcedGroupMethod.value
255-
253+
private var _accountDetailsUiState = MutableStateFlow(AccountDetailsUiState())
254+
val accountDetailsUiState = combine(_accountDetailsUiState, forcedGroupMethod) { uiState, method ->
256255
// set group type to read-only if group method is forced
257-
var combinedState = _accountDetailsUiState.copy(groupMethodReadOnly = method != null)
256+
var combinedState = uiState.copy(groupMethodReadOnly = method != null)
258257

259258
// apply forced group method, if applicable
260259
if (method != null)
261260
combinedState = combinedState.copy(groupMethod = method)
262261

263262
combinedState
264-
}
263+
}.stateIn(viewModelScope, SharingStarted.Lazily, _accountDetailsUiState.value)
265264

266265
fun updateAccountName(accountName: String) {
267-
_accountDetailsUiState = _accountDetailsUiState.copy(
268-
accountName = accountName,
269-
accountNameExists = accountRepository.exists(accountName)
270-
)
266+
_accountDetailsUiState.update { currentState ->
267+
currentState.copy(
268+
accountName = accountName,
269+
accountNameExists = accountRepository.exists(accountName)
270+
)
271+
}
271272
}
272273

273274
fun updateAccountNameAndEmails(accountName: String, emails: Set<String>) {
274-
_accountDetailsUiState = _accountDetailsUiState.copy(
275-
accountName = accountName,
276-
accountNameExists = accountRepository.exists(accountName),
277-
suggestedAccountNames = emails
278-
)
275+
_accountDetailsUiState.update { currentState ->
276+
currentState.copy(
277+
accountName = accountName,
278+
accountNameExists = accountRepository.exists(accountName),
279+
suggestedAccountNames = emails
280+
)
281+
}
279282
}
280283

281284
fun updateGroupMethod(groupMethod: GroupMethod) {
282-
_accountDetailsUiState = _accountDetailsUiState.copy(groupMethod = groupMethod)
285+
_accountDetailsUiState.update { currentState ->
286+
currentState.copy(groupMethod = groupMethod)
287+
}
283288
}
284289

285290
fun resetCouldNotCreateAccount() {
286-
_accountDetailsUiState = _accountDetailsUiState.copy(couldNotCreateAccount = false)
291+
_accountDetailsUiState.update { currentState ->
292+
currentState.copy(couldNotCreateAccount = false)
293+
}
287294
}
288295

289296
fun createAccount() {
290-
_accountDetailsUiState = _accountDetailsUiState.copy(creatingAccount = true)
297+
_accountDetailsUiState.update { currentState ->
298+
currentState.copy(creatingAccount = true)
299+
}
300+
291301
viewModelScope.launch {
292302
val account = withContext(Dispatchers.Default) {
293303
accountRepository.create(
294-
accountDetailsUiState.accountName,
304+
accountDetailsUiState.value.accountName,
295305
loginInfo.credentials,
296306
foundConfig!!,
297-
accountDetailsUiState.groupMethod
307+
accountDetailsUiState.value.groupMethod
298308
)
299309
}
300310

301-
_accountDetailsUiState =
311+
_accountDetailsUiState.update { currentState ->
302312
if (account != null)
303-
accountDetailsUiState.copy(createdAccount = account)
313+
currentState.copy(createdAccount = account)
304314
else
305-
accountDetailsUiState.copy(
315+
currentState.copy(
306316
creatingAccount = false,
307317
couldNotCreateAccount = true
308318
)
319+
}
309320
}
310321
}
311322

0 commit comments

Comments
 (0)