Fix loading state in New Message Fragment

This commit is contained in:
Andrew 2024-06-12 13:59:40 +09:30
parent 60d41ad10d
commit f8e3bc7d9a
3 changed files with 31 additions and 13 deletions

View File

@ -183,6 +183,7 @@ fun EnterAccountId(
.padding(horizontal = LocalDimensions.current.marginLarge)
.fillMaxWidth()
.contentDescription(R.string.next),
enabled = state.isNextButtonEnabled,
onClick = { callbacks.onContinue() }
) {
LoadingArcOr(state.loading) {

View File

@ -4,27 +4,29 @@ import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import network.loki.messenger.R
import nl.komponents.kovenant.ui.failUi
import nl.komponents.kovenant.ui.successUi
import org.session.libsession.snode.SnodeAPI
import org.session.libsignal.utilities.PublicKeyValidation
import org.thoughtcrime.securesms.ui.GetString
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
@HiltViewModel
class NewMessageViewModel @Inject constructor(
private val application: Application
): AndroidViewModel(application), Callbacks {
private val _state = MutableStateFlow(State())
val state = _state.asStateFlow()
@ -34,11 +36,13 @@ class NewMessageViewModel @Inject constructor(
private val _qrErrors = Channel<String>()
val qrErrors: Flow<String> = _qrErrors.receiveAsFlow()
private var job: Job? = null
override fun onChange(value: String) {
_state.update { it.copy(
newMessageIdOrOns = value,
error = null
) }
job?.cancel()
job = null
_state.update { State(newMessageIdOrOns = value) }
}
override fun onContinue() {
@ -54,6 +58,8 @@ class NewMessageViewModel @Inject constructor(
}
private fun createPrivateChatIfPossible(onsNameOrPublicKey: String) {
if (job?.isActive == true) return
if (PublicKeyValidation.isValid(onsNameOrPublicKey, isPrefixRequired = false)) {
if (PublicKeyValidation.hasValidPrefix(onsNameOrPublicKey)) {
onPublicKey(onsNameOrPublicKey)
@ -64,11 +70,18 @@ class NewMessageViewModel @Inject constructor(
// This could be an ONS name
_state.update { it.copy(error = null, loading = true) }
SnodeAPI.getSessionID(onsNameOrPublicKey).successUi { hexEncodedPublicKey ->
_state.update { it.copy(loading = false) }
onPublicKey(onsNameOrPublicKey)
}.failUi { exception ->
_state.update { it.copy(loading = false, error = GetString(exception) { it.toMessage() }) }
job = viewModelScope.launch(Dispatchers.IO) {
try {
withTimeout(5.seconds) {
SnodeAPI.getSessionID(onsNameOrPublicKey).get()
}
if (isActive) {
_state.update { it.copy(loading = false) }
onPublicKey(onsNameOrPublicKey)
}
} catch (e: Exception) {
if (isActive) _state.update { it.copy(loading = false, error = GetString(e) { it.toMessage() }) }
}
}
}
}
@ -87,7 +100,9 @@ data class State(
val newMessageIdOrOns: String = "",
val error: GetString? = null,
val loading: Boolean = false
)
) {
val isNextButtonEnabled: Boolean get() = newMessageIdOrOns.isNotBlank()
}
sealed interface Event {
data class Success(val key: String): Event

View File

@ -93,12 +93,14 @@ fun OutlineButton(
@Composable
fun OutlineButton(
modifier: Modifier = Modifier,
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
onClick: () -> Unit,
content: @Composable () -> Unit = {}
) {
OutlinedButton(
modifier = modifier.applyButtonSize(),
enabled = enabled,
interactionSource = interactionSource,
onClick = onClick,
border = BorderStroke(1.dp, LocalButtonColor.current),