From 1e94fbb84bc3270c9f705fe2336744c81a4b8c28 Mon Sep 17 00:00:00 2001 From: greenart7c3 Date: Fri, 19 Apr 2024 09:46:44 -0300 Subject: [PATCH] improve connection to relay, better handling of response from relay, better handling of the loading screen --- .../greenart7c3/nostrsigner/relays/Relay.kt | 12 +++++++++- .../nostrsigner/relays/RelayPool.kt | 4 ++++ .../nostrsigner/ui/AccountScreen.kt | 21 ++++++++++++++++ .../greenart7c3/nostrsigner/ui/MainScreen.kt | 23 ++++++++++++++++++ .../ui/components/MultiEventHomeScreen.kt | 24 +++++++++++++++++++ 5 files changed, 83 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/relays/Relay.kt b/app/src/main/java/com/greenart7c3/nostrsigner/relays/Relay.kt index 3fe16859..7fca5253 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/relays/Relay.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/relays/Relay.kt @@ -167,8 +167,10 @@ class Relay( try { processNewRelayMessage(text) + onLoading(false) } catch (e: Throwable) { if (e is CancellationException) throw e + onLoading(false) e.printStackTrace() text.chunked(2000) { chunked -> listeners.forEach { it.onError(this@Relay, "", Error("Problem with $chunked")) } @@ -325,6 +327,10 @@ class Relay( } } + fun isReady(): Boolean { + return this.isReady + } + fun disconnect() { Log.d("Relay", "Relay.disconnect $url") checkNotInMainThread() @@ -436,7 +442,11 @@ class Relay( authResponse[signedEvent.id] = false // specific protocol for this event. val event = """["AUTH",${signedEvent.toJson()}]""" - socket?.send(event) + var result = socket?.send(event) + while (result == false || result == null) { + Log.d("Relay", "Relay.send failed trying again $url $event") + result = socket?.send(event) + } eventUploadCounterInBytes += event.bytesUsedInMemory() } else { if (write) { diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/relays/RelayPool.kt b/app/src/main/java/com/greenart7c3/nostrsigner/relays/RelayPool.kt index d3b13fc9..14387cb9 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/relays/RelayPool.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/relays/RelayPool.kt @@ -46,6 +46,10 @@ object RelayPool : Relay.Listener { return relays.size } + fun getAll(): List { + return relays + } + fun connectedRelays(): Int { return relays.count { it.isConnected() } } diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountScreen.kt index 48603d73..f19f684b 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountScreen.kt @@ -6,14 +6,20 @@ import androidx.compose.animation.Crossfade import androidx.compose.animation.core.tween import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.rememberCoroutineScope import com.greenart7c3.nostrsigner.models.IntentData import com.greenart7c3.nostrsigner.nostrsigner +import com.greenart7c3.nostrsigner.relays.Relay +import com.greenart7c3.nostrsigner.relays.RelayPool import com.greenart7c3.nostrsigner.service.IntentUtils import com.vitorpamplona.quartz.encoders.toNpub +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch @SuppressLint("StateFlowValueCalledInComposition", "UnrememberedMutableState") @Composable @@ -54,6 +60,21 @@ fun AccountScreen( } val database = nostrsigner.instance.getDatabase(state.account.keyPair.pubKey.toNpub()) val localRoute = mutableStateOf(newIntents.firstNotNullOfOrNull { it.route } ?: state.route) + val scope = rememberCoroutineScope() + + SideEffect { + scope.launch(Dispatchers.IO) { + database.applicationDao().getAllApplications().forEach { + it.application.relays.forEach { url -> + if (url.isNotBlank()) { + if (RelayPool.getRelays(url).isEmpty()) { + RelayPool.addRelay(Relay(url)) + } + } + } + } + } + } MainScreen(state.account, accountStateViewModel, newIntents, packageName, appName, localRoute, database) } diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt index f21f6c5d..00629e07 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt @@ -87,6 +87,7 @@ import com.greenart7c3.nostrsigner.models.IntentData import com.greenart7c3.nostrsigner.models.Permission import com.greenart7c3.nostrsigner.models.ReturnType import com.greenart7c3.nostrsigner.models.SignerType +import com.greenart7c3.nostrsigner.relays.RelayPool import com.greenart7c3.nostrsigner.service.EventNotificationConsumer import com.greenart7c3.nostrsigner.service.IntentUtils import com.greenart7c3.nostrsigner.service.PushNotificationUtils @@ -100,6 +101,7 @@ import com.vitorpamplona.quartz.encoders.toNpub import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import java.io.ByteArrayOutputStream import java.util.Base64 @@ -129,7 +131,28 @@ fun sendResult( permissions: List? = null, appName: String? = null ) { + onLoading(true) GlobalScope.launch(Dispatchers.IO) { + if (intentData.bunkerRequest != null) { + RelayPool.getAll().forEach { relay -> + if (!relay.isConnected()) { + relay.connectAndRun { + GlobalScope.launch(Dispatchers.IO) { + delay(60000) + if (relay.isConnected()) { + relay.disconnect() + } + } + } + } + } + var count = 0 + while (RelayPool.getAll().any { !it.isReady() } && count < 10) { + count++ + Thread.sleep(1000) + } + } + if (intentData.bunkerRequest != null && intentData.bunkerRequest.secret.isNotBlank()) { val application = database.applicationDao().getBySecret(intentData.bunkerRequest.secret) application?.let { diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/MultiEventHomeScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/MultiEventHomeScreen.kt index c29c92cb..e5ce8de3 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/MultiEventHomeScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/MultiEventHomeScreen.kt @@ -47,6 +47,7 @@ import com.greenart7c3.nostrsigner.models.Account import com.greenart7c3.nostrsigner.models.IntentData import com.greenart7c3.nostrsigner.models.Permission import com.greenart7c3.nostrsigner.models.SignerType +import com.greenart7c3.nostrsigner.relays.RelayPool import com.greenart7c3.nostrsigner.service.AmberUtils import com.greenart7c3.nostrsigner.service.ApplicationNameCache import com.greenart7c3.nostrsigner.service.EventNotificationConsumer @@ -59,9 +60,13 @@ import com.greenart7c3.nostrsigner.ui.Result import com.greenart7c3.nostrsigner.ui.theme.ButtonBorder import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.LnZapRequestEvent +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.delay import kotlinx.coroutines.launch +@OptIn(DelicateCoroutinesApi::class) @Composable fun MultiEventHomeScreen( intents: List, @@ -132,6 +137,25 @@ fun MultiEventHomeScreen( try { val activity = context.getAppCompatActivity() val results = mutableListOf() + if (intents.any { it.bunkerRequest != null }) { + RelayPool.getAll().forEach { relay -> + if (!relay.isConnected()) { + relay.connectAndRun { + GlobalScope.launch(Dispatchers.IO) { + delay(60000) + if (relay.isConnected()) { + relay.disconnect() + } + } + } + } + } + var count = 0 + while (RelayPool.getAll().any { !it.isReady() } && count < 10) { + count++ + Thread.sleep(1000) + } + } for (intentData in intents) { val localAccount =