Manages the pool state without having to loop through relays, saving some milliseconds of processing.
This commit is contained in:
@@ -704,7 +704,7 @@ class Account(
|
|||||||
fun computeRelayListToBroadcast(event: Event): Set<NormalizedRelayUrl> {
|
fun computeRelayListToBroadcast(event: Event): Set<NormalizedRelayUrl> {
|
||||||
if (event is MetadataEvent || event is AdvertisedRelayListEvent) {
|
if (event is MetadataEvent || event is AdvertisedRelayListEvent) {
|
||||||
// everywhere
|
// everywhere
|
||||||
return followPlusAllMineWithIndex.flow.value + client.relayStatusFlow().value.available
|
return followPlusAllMineWithIndex.flow.value + client.availableRelaysFlow().value
|
||||||
}
|
}
|
||||||
if (event is GiftWrapEvent) {
|
if (event is GiftWrapEvent) {
|
||||||
val receiver = event.recipientPubKey()
|
val receiver = event.recipientPubKey()
|
||||||
@@ -904,7 +904,7 @@ class Account(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendLiterallyEverywhere(event: Event) {
|
fun sendLiterallyEverywhere(event: Event) {
|
||||||
client.send(event, followPlusAllMineWithIndex.flow.value + client.relayStatusFlow().value.available)
|
client.send(event, followPlusAllMineWithIndex.flow.value + client.availableRelaysFlow().value)
|
||||||
cache.justConsumeMyOwnEvent(event)
|
cache.justConsumeMyOwnEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -154,7 +154,7 @@ class AccountFollowsLoaderSubAssembler(
|
|||||||
|
|
||||||
println("AccountFollowNeeds ${users.size}")
|
println("AccountFollowNeeds ${users.size}")
|
||||||
|
|
||||||
val connectedRelays = client.relayStatusFlow().value.connected
|
val connectedRelays = client.connectedRelaysFlow().value
|
||||||
|
|
||||||
val perRelay = pickRelaysToLoadUsers(users, accounts, connectedRelays, failureTracker.cannotConnectRelays, hasTried)
|
val perRelay = pickRelaysToLoadUsers(users, accounts, connectedRelays, failureTracker.cannotConnectRelays, hasTried)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -96,7 +96,7 @@ class UserOutboxFinderSubAssembler(
|
|||||||
if (noOutboxList.isEmpty()) return null
|
if (noOutboxList.isEmpty()) return null
|
||||||
|
|
||||||
val accounts = keys.mapTo(mutableSetOf()) { it.account }
|
val accounts = keys.mapTo(mutableSetOf()) { it.account }
|
||||||
val connectedRelays = client.relayStatusFlow().value.connected
|
val connectedRelays = client.connectedRelaysFlow().value
|
||||||
|
|
||||||
val perRelayKeysBoth =
|
val perRelayKeysBoth =
|
||||||
pickRelaysToLoadUsers(
|
pickRelaysToLoadUsers(
|
||||||
|
|||||||
+45
-58
@@ -112,11 +112,11 @@ import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.Font18SP
|
import com.vitorpamplona.amethyst.ui.theme.Font18SP
|
||||||
import com.vitorpamplona.amethyst.ui.theme.IconRowModifier
|
import com.vitorpamplona.amethyst.ui.theme.IconRowModifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.IconRowTextModifier
|
import com.vitorpamplona.amethyst.ui.theme.IconRowTextModifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size16dp
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size22Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size22Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size26Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size26Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Width16Space
|
||||||
import com.vitorpamplona.amethyst.ui.theme.bannerModifier
|
import com.vitorpamplona.amethyst.ui.theme.bannerModifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.drawerSpacing
|
import com.vitorpamplona.amethyst.ui.theme.drawerSpacing
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
@@ -124,7 +124,8 @@ import com.vitorpamplona.amethyst.ui.theme.profileContentHeaderModifier
|
|||||||
import com.vitorpamplona.quartz.nip01Core.core.Address
|
import com.vitorpamplona.quartz.nip01Core.core.Address
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.ImmutableListOfLists
|
import com.vitorpamplona.quartz.nip01Core.core.ImmutableListOfLists
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayPool
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DrawerContent(
|
fun DrawerContent(
|
||||||
@@ -537,40 +538,6 @@ fun ListContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun RelayStatus(accountViewModel: AccountViewModel) {
|
|
||||||
val connectedRelaysText by accountViewModel.account.client
|
|
||||||
.relayStatusFlow()
|
|
||||||
.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
RenderRelayStatus(connectedRelaysText)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun RenderRelayStatus(relayPool: RelayPool.RelayPoolStatus) {
|
|
||||||
val text by
|
|
||||||
remember(relayPool) { derivedStateOf { "${relayPool.connected.size}/${relayPool.available.size}" } }
|
|
||||||
|
|
||||||
val placeHolder = MaterialTheme.colorScheme.placeholderText
|
|
||||||
|
|
||||||
val color by
|
|
||||||
remember(relayPool) {
|
|
||||||
derivedStateOf {
|
|
||||||
if (relayPool.isConnected) {
|
|
||||||
placeHolder
|
|
||||||
} else {
|
|
||||||
Color.Red
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = text,
|
|
||||||
color = color,
|
|
||||||
style = MaterialTheme.typography.titleMedium,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NavigationRow(
|
fun NavigationRow(
|
||||||
title: Int,
|
title: Int,
|
||||||
@@ -691,35 +658,55 @@ fun IconRowRelays(
|
|||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable { onClick() },
|
.padding(vertical = 15.dp, horizontal = 25.dp)
|
||||||
|
.clickable(onClick = onClick),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Row(
|
Icon(
|
||||||
modifier =
|
painter = painterRes(R.drawable.relays, 4),
|
||||||
Modifier
|
contentDescription = stringRes(R.string.relay_setup),
|
||||||
.fillMaxWidth()
|
modifier = Size22Modifier,
|
||||||
.padding(vertical = 15.dp, horizontal = 25.dp),
|
tint = MaterialTheme.colorScheme.onSurface,
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
)
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterRes(R.drawable.relays, 4),
|
|
||||||
contentDescription = stringRes(R.string.relay_setup),
|
|
||||||
modifier = Modifier.size(22.dp),
|
|
||||||
tint = MaterialTheme.colorScheme.onSurface,
|
|
||||||
)
|
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.padding(start = 16.dp),
|
modifier = IconRowTextModifier,
|
||||||
text = stringRes(id = R.string.relay_setup),
|
text = stringRes(id = R.string.relay_setup),
|
||||||
fontSize = 18.sp,
|
fontSize = Font18SP,
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(Size16dp))
|
Spacer(modifier = Width16Space)
|
||||||
|
|
||||||
RelayStatus(accountViewModel = accountViewModel)
|
RelayStatus(accountViewModel)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PoolStatus(
|
||||||
|
val share: String,
|
||||||
|
val isConnected: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RelayStatus(accountViewModel: AccountViewModel) {
|
||||||
|
val statusCounterFlow: Flow<PoolStatus> =
|
||||||
|
remember(accountViewModel) {
|
||||||
|
combine(
|
||||||
|
accountViewModel.account.client.connectedRelaysFlow(),
|
||||||
|
accountViewModel.account.client.availableRelaysFlow(),
|
||||||
|
) { connected, available ->
|
||||||
|
PoolStatus("${connected.size}/${available.size}", connected.isNotEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val relayPool by statusCounterFlow.collectAsStateWithLifecycle(PoolStatus("", false))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = relayPool.share,
|
||||||
|
color = if (relayPool.isConnected) MaterialTheme.colorScheme.placeholderText else Color.Red,
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BottomContent(
|
fun BottomContent(
|
||||||
user: User,
|
user: User,
|
||||||
|
|||||||
+2
-2
@@ -50,8 +50,8 @@ class ConnectedRelayListViewModel : BasicRelaySetupInfoModel() {
|
|||||||
|
|
||||||
override fun getRelayList(): List<NormalizedRelayUrl> =
|
override fun getRelayList(): List<NormalizedRelayUrl> =
|
||||||
account.client
|
account.client
|
||||||
.relayStatusFlow()
|
.availableRelaysFlow()
|
||||||
.value.available
|
.value
|
||||||
.sorted()
|
.sorted()
|
||||||
|
|
||||||
override suspend fun saveRelayList(urlList: List<NormalizedRelayUrl>) {
|
override suspend fun saveRelayList(urlList: List<NormalizedRelayUrl>) {
|
||||||
|
|||||||
@@ -255,6 +255,8 @@ val drawerSpacing = Modifier.padding(top = Size10dp, start = Size25dp, end = Siz
|
|||||||
val IconRowTextModifier = Modifier.padding(start = 16.dp)
|
val IconRowTextModifier = Modifier.padding(start = 16.dp)
|
||||||
val IconRowModifier = Modifier.fillMaxWidth().padding(vertical = 15.dp, horizontal = 25.dp)
|
val IconRowModifier = Modifier.fillMaxWidth().padding(vertical = 15.dp, horizontal = 25.dp)
|
||||||
|
|
||||||
|
val Width16Space = Modifier.width(Size16dp)
|
||||||
|
|
||||||
val emptyLineItemModifier = Modifier.height(Size75dp).fillMaxWidth()
|
val emptyLineItemModifier = Modifier.height(Size75dp).fillMaxWidth()
|
||||||
|
|
||||||
val imageHeaderBannerSize = Modifier.fillMaxWidth().height(150.dp)
|
val imageHeaderBannerSize = Modifier.fillMaxWidth().height(150.dp)
|
||||||
|
|||||||
+6
-3
@@ -22,7 +22,6 @@ package com.vitorpamplona.quartz.nip01Core.relay.client
|
|||||||
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayPool
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
|
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
|
||||||
@@ -32,7 +31,9 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
interface INostrClient {
|
interface INostrClient {
|
||||||
fun relayStatusFlow(): StateFlow<RelayPool.RelayPoolStatus>
|
fun connectedRelaysFlow(): StateFlow<Set<NormalizedRelayUrl>>
|
||||||
|
|
||||||
|
fun availableRelaysFlow(): StateFlow<Set<NormalizedRelayUrl>>
|
||||||
|
|
||||||
fun connect()
|
fun connect()
|
||||||
|
|
||||||
@@ -80,7 +81,9 @@ interface INostrClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object EmptyNostrClient : INostrClient {
|
object EmptyNostrClient : INostrClient {
|
||||||
override fun relayStatusFlow() = MutableStateFlow(RelayPool.RelayPoolStatus())
|
override fun connectedRelaysFlow() = MutableStateFlow(emptySet<NormalizedRelayUrl>())
|
||||||
|
|
||||||
|
override fun availableRelaysFlow() = MutableStateFlow(emptySet<NormalizedRelayUrl>())
|
||||||
|
|
||||||
override fun connect() { }
|
override fun connect() { }
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -320,5 +320,7 @@ class NostrClient(
|
|||||||
|
|
||||||
override fun getCountFiltersOrNull(subId: String): Map<NormalizedRelayUrl, List<Filter>>? = activeCounts.getSubscriptionFiltersOrNull(subId)
|
override fun getCountFiltersOrNull(subId: String): Map<NormalizedRelayUrl, List<Filter>>? = activeCounts.getSubscriptionFiltersOrNull(subId)
|
||||||
|
|
||||||
override fun relayStatusFlow() = relayPool.statusFlow
|
override fun connectedRelaysFlow() = relayPool.connectedRelays
|
||||||
|
|
||||||
|
override fun availableRelaysFlow() = relayPool.availableRelays
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-52
@@ -20,7 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.nip01Core.relay.client.pool
|
package com.vitorpamplona.quartz.nip01Core.relay.client.pool
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.EmptyClientListener
|
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.EmptyClientListener
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientListener
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
|
||||||
@@ -31,8 +30,8 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
|||||||
import com.vitorpamplona.quartz.nip01Core.relay.sockets.WebsocketBuilder
|
import com.vitorpamplona.quartz.nip01Core.relay.sockets.WebsocketBuilder
|
||||||
import com.vitorpamplona.quartz.utils.cache.LargeCache
|
import com.vitorpamplona.quartz.utils.cache.LargeCache
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RelayPool manages a collection of Nostr relays, abstracting individual connections and providing
|
* RelayPool manages a collection of Nostr relays, abstracting individual connections and providing
|
||||||
@@ -61,9 +60,11 @@ class RelayPool(
|
|||||||
) : IRelayClientListener {
|
) : IRelayClientListener {
|
||||||
private val relays = LargeCache<NormalizedRelayUrl, IRelayClient>()
|
private val relays = LargeCache<NormalizedRelayUrl, IRelayClient>()
|
||||||
|
|
||||||
// Backing property to avoid flow emissions from other classes
|
private val _connectedRelays = MutableStateFlow<Set<NormalizedRelayUrl>>(emptySet())
|
||||||
private val _statusFlow = MutableStateFlow<RelayPoolStatus>(RelayPoolStatus())
|
val connectedRelays = _connectedRelays.asStateFlow()
|
||||||
val statusFlow: StateFlow<RelayPoolStatus> = _statusFlow.asStateFlow()
|
|
||||||
|
private val _availableRelays = MutableStateFlow<Set<NormalizedRelayUrl>>(emptySet())
|
||||||
|
val availableRelays = _availableRelays.asStateFlow()
|
||||||
|
|
||||||
fun getRelay(url: NormalizedRelayUrl): IRelayClient? = relays.get(url)
|
fun getRelay(url: NormalizedRelayUrl): IRelayClient? = relays.get(url)
|
||||||
|
|
||||||
@@ -87,21 +88,18 @@ class RelayPool(
|
|||||||
relay.connectAndSyncFiltersIfDisconnected(ignoreRetryDelays)
|
relay.connectAndSyncFiltersIfDisconnected(ignoreRetryDelays)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateStatus()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun connect() {
|
fun connect() {
|
||||||
relays.forEach { url, relay ->
|
relays.forEach { url, relay ->
|
||||||
relay.connect()
|
relay.connect()
|
||||||
}
|
}
|
||||||
updateStatus()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun connectIfDisconnected() {
|
fun connectIfDisconnected() {
|
||||||
relays.forEach { url, relay ->
|
relays.forEach { url, relay ->
|
||||||
relay.connectAndSyncFiltersIfDisconnected()
|
relay.connectAndSyncFiltersIfDisconnected()
|
||||||
}
|
}
|
||||||
updateStatus()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun connectIfDisconnected(relay: NormalizedRelayUrl) = relays.get(relay)?.connectAndSyncFiltersIfDisconnected()
|
fun connectIfDisconnected(relay: NormalizedRelayUrl) = relays.get(relay)?.connectAndSyncFiltersIfDisconnected()
|
||||||
@@ -110,7 +108,6 @@ class RelayPool(
|
|||||||
relays.forEach { url, relay ->
|
relays.forEach { url, relay ->
|
||||||
relay.disconnect()
|
relay.disconnect()
|
||||||
}
|
}
|
||||||
updateStatus()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendOrConnectAndSync(
|
fun sendOrConnectAndSync(
|
||||||
@@ -144,7 +141,13 @@ class RelayPool(
|
|||||||
// --------------------
|
// --------------------
|
||||||
// Pool Maintenance
|
// Pool Maintenance
|
||||||
// --------------------
|
// --------------------
|
||||||
fun getOrCreateRelay(relay: NormalizedRelayUrl) = relays.getOrCreate(relay, ::createNewRelay)
|
fun getOrCreateRelay(relay: NormalizedRelayUrl): IRelayClient {
|
||||||
|
val r = relays.getOrCreate(relay, ::createNewRelay)
|
||||||
|
if (_availableRelays.value.size != relays.size()) {
|
||||||
|
_availableRelays.update { relays.keys() }
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
fun createRelayIfAbsent(relay: NormalizedRelayUrl): Boolean = relays.createIfAbsent(relay, ::createNewRelay)
|
fun createRelayIfAbsent(relay: NormalizedRelayUrl): Boolean = relays.createIfAbsent(relay, ::createNewRelay)
|
||||||
|
|
||||||
@@ -155,39 +158,40 @@ class RelayPool(
|
|||||||
val toRemove = relays.keys() - newRelays
|
val toRemove = relays.keys() - newRelays
|
||||||
var atLeastOne = false
|
var atLeastOne = false
|
||||||
|
|
||||||
newRelays.forEach {
|
newRelays.forEach { relay ->
|
||||||
if (createRelayIfAbsent(it)) {
|
if (createRelayIfAbsent(relay)) {
|
||||||
atLeastOne = true
|
atLeastOne = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toRemove.forEach {
|
toRemove.forEach { relay ->
|
||||||
if (removeRelayInner(it)) {
|
if (removeRelayInner(relay)) {
|
||||||
atLeastOne = true
|
atLeastOne = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atLeastOne) {
|
if (atLeastOne) {
|
||||||
updateStatus()
|
_availableRelays.update { relays.keys() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addRelay(relay: NormalizedRelayUrl): IRelayClient {
|
fun addRelay(relay: NormalizedRelayUrl): IRelayClient {
|
||||||
if (createRelayIfAbsent(relay)) {
|
if (createRelayIfAbsent(relay)) {
|
||||||
updateStatus()
|
_availableRelays.update { relays.keys() }
|
||||||
}
|
}
|
||||||
return getOrCreateRelay(relay)
|
return getOrCreateRelay(relay)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addAllRelays(relayList: List<NormalizedRelayUrl>) {
|
fun addAllRelays(relayList: List<NormalizedRelayUrl>) {
|
||||||
var atLeastOne = false
|
var atLeastOne = false
|
||||||
relayList.forEach {
|
relayList.forEach { relay ->
|
||||||
if (createRelayIfAbsent(it)) {
|
if (createRelayIfAbsent(relay)) {
|
||||||
atLeastOne = true
|
atLeastOne = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atLeastOne) {
|
if (atLeastOne) {
|
||||||
updateStatus()
|
_availableRelays.update { relays.keys() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +206,7 @@ class RelayPool(
|
|||||||
|
|
||||||
fun removeRelay(relay: NormalizedRelayUrl) {
|
fun removeRelay(relay: NormalizedRelayUrl) {
|
||||||
if (removeRelayInner(relay)) {
|
if (removeRelayInner(relay)) {
|
||||||
updateStatus()
|
_availableRelays.update { relays.keys() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +214,7 @@ class RelayPool(
|
|||||||
if (relays.size() > 0) {
|
if (relays.size() > 0) {
|
||||||
disconnect()
|
disconnect()
|
||||||
relays.clear()
|
relays.clear()
|
||||||
updateStatus()
|
_availableRelays.update { emptySet() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,12 +228,12 @@ class RelayPool(
|
|||||||
pingMillis: Int,
|
pingMillis: Int,
|
||||||
compressed: Boolean,
|
compressed: Boolean,
|
||||||
) {
|
) {
|
||||||
updateStatus()
|
_connectedRelays.update { it + relay.url }
|
||||||
listener.onConnected(relay, pingMillis, compressed)
|
listener.onConnected(relay, pingMillis, compressed)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDisconnected(relay: IRelayClient) {
|
override fun onDisconnected(relay: IRelayClient) {
|
||||||
updateStatus()
|
_connectedRelays.update { it - relay.url }
|
||||||
listener.onDisconnected(relay)
|
listener.onDisconnected(relay)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,33 +255,5 @@ class RelayPool(
|
|||||||
success: Boolean,
|
success: Boolean,
|
||||||
) = listener.onSent(relay, cmdStr, cmd, success)
|
) = listener.onSent(relay, cmdStr, cmd, success)
|
||||||
|
|
||||||
// ---------------
|
fun connectedRelaysCount(): Int = relays.count { url, relay -> relay.isConnected() }
|
||||||
// STATUS Reports
|
|
||||||
// ---------------
|
|
||||||
|
|
||||||
fun availableRelays(): Set<NormalizedRelayUrl> = relays.keys()
|
|
||||||
|
|
||||||
fun connectedRelays(): Set<NormalizedRelayUrl> =
|
|
||||||
relays.mapNotNullIntoSet { url, relay ->
|
|
||||||
if (relay.isConnected()) {
|
|
||||||
url
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateStatus() {
|
|
||||||
val connected = connectedRelays()
|
|
||||||
val available = availableRelays()
|
|
||||||
if (_statusFlow.value.connected != connected || _statusFlow.value.available != available) {
|
|
||||||
_statusFlow.tryEmit(RelayPoolStatus(connected, available))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class RelayPoolStatus(
|
|
||||||
val connected: Set<NormalizedRelayUrl> = emptySet(),
|
|
||||||
val available: Set<NormalizedRelayUrl> = emptySet(),
|
|
||||||
val isConnected: Boolean = connected.isNotEmpty(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user