show relay error messages to the user

This commit is contained in:
greenart7c3
2024-05-20 09:08:37 -03:00
parent a73079fb5f
commit ef8ca5e4cb
5 changed files with 128 additions and 1 deletions
@@ -309,7 +309,11 @@ class Relay(
Log.w("Relay", "Relay on OK $url, $eventId, $success, $message")
it.onSendResponse(this@Relay, eventId, success, message)
onOk?.let { it() }
if (success) {
onOk?.let { it() }
} else if (message.isNotEmpty()) {
RelayPool.accountStateViewModel?.toast("Relay", message)
}
}
"AUTH" ->
listeners.forEach {
@@ -22,6 +22,7 @@ package com.greenart7c3.nostrsigner.relays
import androidx.compose.runtime.Immutable
import com.greenart7c3.nostrsigner.checkNotInMainThread
import com.greenart7c3.nostrsigner.ui.AccountStateViewModel
import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.events.EventInterface
import kotlinx.coroutines.DelicateCoroutinesApi
@@ -36,6 +37,7 @@ import kotlinx.coroutines.launch
* RelayPool manages the connection to multiple Relays and lets consumers deal with simple events.
*/
object RelayPool : Relay.Listener {
var accountStateViewModel: AccountStateViewModel? = null
private var relays = listOf<Relay>()
private var listeners = setOf<Listener>()
@@ -5,6 +5,19 @@ import android.content.Intent
import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Done
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
@@ -14,12 +27,20 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.greenart7c3.nostrsigner.BuildConfig
import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.NostrSigner
import com.greenart7c3.nostrsigner.R
import com.greenart7c3.nostrsigner.models.IntentData
import com.greenart7c3.nostrsigner.relays.Client
import com.greenart7c3.nostrsigner.relays.Relay
import com.greenart7c3.nostrsigner.relays.RelayPool
import com.greenart7c3.nostrsigner.service.ConnectivityService
import com.greenart7c3.nostrsigner.service.IntentUtils
import com.greenart7c3.nostrsigner.service.NotificationDataSource
@@ -120,9 +141,79 @@ fun AccountScreen(
}
}
RelayPool.accountStateViewModel = accountStateViewModel
DisplayErrorMessages(accountStateViewModel)
MainScreen(state.account, accountStateViewModel, newIntents, packageName, appName, localRoute, database)
}
}
}
}
}
@Composable
private fun DisplayErrorMessages(accountViewModel: AccountStateViewModel) {
val context = LocalContext.current
val openDialogMsg = accountViewModel.toasts.collectAsStateWithLifecycle(null)
openDialogMsg.value?.let { obj ->
when (obj) {
is ResourceToastMsg ->
if (obj.params != null) {
InformationDialog(
context.getString(obj.titleResId),
context.getString(obj.resourceId, *obj.params),
) {
accountViewModel.clearToasts()
}
} else {
InformationDialog(
context.getString(obj.titleResId),
context.getString(obj.resourceId),
) {
accountViewModel.clearToasts()
}
}
is StringToastMsg ->
InformationDialog(
obj.title,
obj.msg,
) {
accountViewModel.clearToasts()
}
}
}
}
@Composable
fun InformationDialog(
title: String,
textContent: String,
buttonColors: ButtonColors = ButtonDefaults.buttonColors(),
onDismiss: () -> Unit,
) {
AlertDialog(
onDismissRequest = onDismiss,
title = { Text(title) },
text = { SelectionContainer { Text(textContent) } },
confirmButton = {
Button(
onClick = onDismiss,
colors = buttonColors,
contentPadding = PaddingValues(horizontal = 16.dp),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.Outlined.Done,
contentDescription = null,
)
Spacer(Modifier.width(5.dp))
Text(stringResource(R.string.ok))
}
}
},
)
}
@@ -1,7 +1,9 @@
package com.greenart7c3.nostrsigner.ui
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.models.Account
import com.vitorpamplona.quartz.crypto.CryptoUtils
@@ -11,20 +13,47 @@ import fr.acinq.secp256k1.Hex
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
@Immutable
open class ToastMsg()
@Immutable
class StringToastMsg(val title: String, val msg: String) : ToastMsg()
@Immutable
class ResourceToastMsg(
val titleResId: Int,
val resourceId: Int,
val params: Array<out String>? = null,
) : ToastMsg()
@Stable
class AccountStateViewModel(npub: String?) : ViewModel() {
private val _accountContent = MutableStateFlow<AccountState>(AccountState.LoggedOff)
val accountContent = _accountContent.asStateFlow()
val toasts = MutableSharedFlow<ToastMsg?>(0, 3, onBufferOverflow = BufferOverflow.DROP_OLDEST)
init {
tryLoginExistingAccount(null, npub)
}
fun clearToasts() {
viewModelScope.launch { toasts.emit(null) }
}
fun toast(
title: String,
message: String,
) {
viewModelScope.launch { toasts.emit(StringToastMsg(title, message)) }
}
private fun tryLoginExistingAccount(
route: String?,
npub: String?,
+1
View File
@@ -127,4 +127,5 @@
<string name="no_activities_found">No activities found</string>
<string name="home">Home</string>
<string name="settings">Settings</string>
<string name="ok">OK</string>
</resources>