better connection to relays when using push notifications

This commit is contained in:
greenart7c3
2024-04-26 09:25:15 -03:00
parent 109e1182ae
commit 01fe09c866
10 changed files with 104 additions and 25 deletions
+1
View File
@@ -115,6 +115,7 @@ dependencies {
implementation libs.material.icons.extended
implementation libs.appcompat
implementation libs.work.runtime.ktx
testImplementation libs.junit
testImplementation libs.mockk
@@ -40,6 +40,17 @@ object Client : RelayPool.Listener {
private var relays = emptyArray<Relay>()
private var subscriptions = mapOf<String, List<TypedFilter>>()
@Synchronized
fun addRelays(relays: Array<Relay>) {
if (isSameRelaySetConfig(relays)) return
RelayPool.disconnect()
RelayPool.unregister(this)
RelayPool.unloadRelays()
RelayPool.register(this)
RelayPool.loadRelays(relays.toList())
Client.relays = relays
}
@Synchronized
fun reconnect(
relays: Array<Relay>?,
@@ -24,10 +24,15 @@ import androidx.compose.runtime.Immutable
import com.greenart7c3.nostrsigner.checkNotInMainThread
import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.events.EventInterface
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
/**
* RelayPool manages the connection to multiple Relays and lets consumers deal with simple events.
@@ -91,6 +96,7 @@ object RelayPool : Relay.Listener {
return listeners.isNotEmpty()
}
@OptIn(DelicateCoroutinesApi::class)
fun sendToSelectedRelays(
list: List<Relay>,
signedEvent: EventInterface,
@@ -100,7 +106,23 @@ object RelayPool : Relay.Listener {
list.forEach { relay ->
relays.filter { it.url == relay.url }.forEach {
it.onLoading = onLoading
it.send(signedEvent, onDone)
if (!it.isConnected()) {
it.connectAndRun {
it.send(signedEvent, onDone)
GlobalScope.launch(Dispatchers.IO) {
delay(60000)
if (relay.isConnected()) {
relay.disconnect()
if (onDone != null) {
onDone()
}
}
}
}
} else {
it.send(signedEvent, onDone)
}
}
}
}
@@ -10,6 +10,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.models.Account
import com.greenart7c3.nostrsigner.models.CompressionType
import com.greenart7c3.nostrsigner.models.IntentData
@@ -23,6 +24,7 @@ import com.greenart7c3.nostrsigner.relays.Relay
import com.greenart7c3.nostrsigner.relays.RelayPool
import com.greenart7c3.nostrsigner.service.model.AmberEvent
import com.greenart7c3.nostrsigner.ui.BunkerResponse
import com.greenart7c3.nostrsigner.ui.NotificationType
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.encoders.toNpub
@@ -172,7 +174,10 @@ object IntentUtils {
}
}
}
Client.reconnect(savedRelays.toTypedArray())
Client.addRelays(relays.toTypedArray())
if (LocalPreferences.getNotificationType() == NotificationType.DIRECT) {
Client.reconnect(relays.toTypedArray())
}
delay(1000)
}
@@ -0,0 +1,31 @@
package com.greenart7c3.nostrsigner.service
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.greenart7c3.nostrsigner.relays.RelayPool
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
class RelayDisconnectService(ctx: Context, params: WorkerParameters) : Worker(ctx, params) {
private val ioScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
override fun doWork(): Result {
val job = ioScope.launch {
val url = inputData.getString("relay")
delay(60000)
url?.let {
val relay = RelayPool.getRelay(it)
if (relay != null && relay.isConnected()) {
relay.disconnect()
}
}
}
runBlocking { job.join() }
return Result.success()
}
}
@@ -80,6 +80,7 @@ fun AccountScreen(
}
}
delay(1000)
Client.addRelays(relays.toTypedArray())
if (LocalPreferences.getNotificationType() == NotificationType.DIRECT && BuildConfig.FLAVOR != "offline") {
nostrsigner.instance.applicationContext.startService(Intent(nostrsigner.instance.applicationContext, ConnectivityService::class.java))
Client.reconnect(relays.toTypedArray())
@@ -274,7 +274,10 @@ fun EditPermission(
}
}
}
Client.reconnect(relays.toTypedArray())
Client.addRelays(relays.toTypedArray())
if (LocalPreferences.getNotificationType() == NotificationType.DIRECT) {
Client.reconnect(relays.toTypedArray())
}
}
scope.launch(Dispatchers.Main) {
@@ -509,7 +512,10 @@ fun EditPermission(
}
}
}
Client.reconnect(relays.toTypedArray())
Client.addRelays(relays.toTypedArray())
if (LocalPreferences.getNotificationType() == NotificationType.DIRECT) {
Client.reconnect(relays.toTypedArray())
}
scope.launch(Dispatchers.Main) {
navController.popBackStack()
@@ -74,6 +74,9 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import androidx.work.Data
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import com.greenart7c3.nostrsigner.BuildConfig
import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.R
@@ -87,12 +90,13 @@ 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.nostrsigner
import com.greenart7c3.nostrsigner.relays.Relay
import com.greenart7c3.nostrsigner.relays.RelayPool
import com.greenart7c3.nostrsigner.service.EventNotificationConsumer
import com.greenart7c3.nostrsigner.service.IntentUtils
import com.greenart7c3.nostrsigner.service.NotificationDataSource
import com.greenart7c3.nostrsigner.service.PushNotificationUtils
import com.greenart7c3.nostrsigner.service.RelayDisconnectService
import com.greenart7c3.nostrsigner.service.getAppCompatActivity
import com.greenart7c3.nostrsigner.service.toShortenHex
import com.greenart7c3.nostrsigner.ui.actions.AccountsBottomSheet
@@ -103,7 +107,6 @@ 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
@@ -139,14 +142,11 @@ fun sendResult(
RelayPool.getAll().forEach { relay ->
if (!relay.isConnected()) {
relay.connectAndRun {
if (!NotificationDataSource.isActive()) {
GlobalScope.launch(Dispatchers.IO) {
delay(60000)
if (relay.isConnected()) {
relay.disconnect()
}
}
}
val builder = OneTimeWorkRequest.Builder(RelayDisconnectService::class.java)
val inputData = Data.Builder()
inputData.putString("relay", relay.url)
builder.setInputData(inputData.build())
WorkManager.getInstance(nostrsigner.instance).enqueue(builder.build())
}
}
}
@@ -39,6 +39,9 @@ import androidx.compose.ui.text.toLowerCase
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.work.Data
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import com.google.gson.GsonBuilder
import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.R
@@ -47,6 +50,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.nostrsigner
import com.greenart7c3.nostrsigner.relays.Relay
import com.greenart7c3.nostrsigner.relays.RelayPool
import com.greenart7c3.nostrsigner.service.AmberUtils
@@ -54,6 +58,7 @@ import com.greenart7c3.nostrsigner.service.ApplicationNameCache
import com.greenart7c3.nostrsigner.service.EventNotificationConsumer
import com.greenart7c3.nostrsigner.service.IntentUtils
import com.greenart7c3.nostrsigner.service.NotificationDataSource
import com.greenart7c3.nostrsigner.service.RelayDisconnectService
import com.greenart7c3.nostrsigner.service.getAppCompatActivity
import com.greenart7c3.nostrsigner.service.model.AmberEvent
import com.greenart7c3.nostrsigner.service.toShortenHex
@@ -64,8 +69,6 @@ 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)
@@ -141,16 +144,13 @@ fun MultiEventHomeScreen(
val results = mutableListOf<Result>()
if (intents.any { it.bunkerRequest != null }) {
RelayPool.getAll().forEach { relay ->
if (!relay.isConnected()) {
if (!relay.isConnected() && !NotificationDataSource.isActive()) {
relay.connectAndRun {
if (!NotificationDataSource.isActive()) {
GlobalScope.launch(Dispatchers.IO) {
delay(60000)
if (relay.isConnected()) {
relay.disconnect()
}
}
}
val builder = OneTimeWorkRequest.Builder(RelayDisconnectService::class.java)
val inputData = Data.Builder()
inputData.putString("relay", relay.url)
builder.setInputData(inputData.build())
WorkManager.getInstance(nostrsigner.instance).enqueue(builder.build())
}
}
}
+2
View File
@@ -25,6 +25,7 @@ securityCryptoKtx = "1.1.0-alpha06"
zxingAndroidEmbedded = "4.3.0"
okhttp = "5.0.0-alpha.14"
kotlin = "1.9.23"
workRuntimeKtx = "2.9.0"
[libraries]
activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
@@ -63,6 +64,7 @@ ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose
ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose_ui" }
zxing-android-embedded = { module = "com.journeyapps:zxing-android-embedded", version.ref = "zxingAndroidEmbedded" }
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "workRuntimeKtx" }
[plugins]
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }