Fixes miscaching flows of the relay lists from follows.

This commit is contained in:
Vitor Pamplona
2024-08-14 18:03:25 -04:00
parent 6b193894bd
commit 7478899388
2 changed files with 69 additions and 37 deletions
@@ -119,7 +119,9 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.combineTransform import kotlinx.coroutines.flow.combineTransform
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest import kotlinx.coroutines.flow.transformLatest
@@ -540,17 +542,14 @@ class Account(
} }
fun authorsPerRelay( fun authorsPerRelay(
pubkeyList: Set<HexKey>, followsNIP65RelayLists: Array<NoteState>,
defaultRelayList: List<String>, defaultRelayList: List<String>,
): Flow<Map<String, List<String>>> = ): Map<String, List<HexKey>> {
combine( val test =
pubkeyList.map {
getNIP65RelayListFlow(it)
},
) { followsNIP65RelayLists ->
assembleAuthorsPerWriteRelay( assembleAuthorsPerWriteRelay(
followsNIP65RelayLists followsNIP65RelayLists
.mapNotNull { .mapNotNull
{
val author = (it.note as? AddressableNote)?.address?.pubKeyHex val author = (it.note as? AddressableNote)?.address?.pubKeyHex
val event = (it.note.event as? AdvertisedRelayListEvent) val event = (it.note.event as? AdvertisedRelayListEvent)
@@ -567,23 +566,39 @@ class Account(
}.toMap(), }.toMap(),
hasOnionConnection = proxy != null, hasOnionConnection = proxy != null,
) )
}
return test
}
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
val liveHomeListAuthorsPerRelayFlow: Flow<Map<String, List<String>>?> by lazy { val liveHomeFollowListAdvertizedRelayListFlow: Flow<Array<NoteState>?> =
combineTransform(liveHomeFollowListFlow, connectToRelaysFlow) { followList, existing -> liveHomeFollowLists
if (followList != null) { .transformLatest { followList ->
emit(authorsPerRelay(followList.usersPlusMe, existing.filter { it.feedTypes.contains(FeedType.FOLLOWS) && it.read }.map { it.url })) if (followList != null) {
} else { emitAll(combine(followList.usersPlusMe.map { getNIP65RelayListFlow(it) }) { it })
emit(MutableStateFlow(null)) } else {
emit(null)
}
}
val liveHomeListAuthorsPerRelayFlow: Flow<Map<String, List<HexKey>>?> by lazy {
combineTransform(liveHomeFollowListAdvertizedRelayListFlow, connectToRelays) { adverisedRelayList, existing ->
if (adverisedRelayList != null) {
emit(authorsPerRelay(adverisedRelayList, existing.filter { it.feedTypes.contains(FeedType.FOLLOWS) && it.read }.map { it.url }))
} else {
emit(null)
} }
}.flatMapLatest {
it
} }
} }
val liveHomeListAuthorsPerRelay: StateFlow<Map<String, List<String>>?> by lazy { val liveHomeListAuthorsPerRelay: StateFlow<Map<String, List<HexKey>>?> by lazy {
liveHomeListAuthorsPerRelayFlow.stateIn(scope, SharingStarted.Eagerly, emptyMap()) val currentRelays = connectToRelays.value.filter { it.feedTypes.contains(FeedType.FOLLOWS) && it.read }.map { it.url }
val default =
currentRelays.associate { relayUrl ->
relayUrl to (liveHomeFollowLists.value?.usersPlusMe?.toList() ?: emptyList())
}
liveHomeListAuthorsPerRelayFlow.stateIn(scope, SharingStarted.Eagerly, default)
} }
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
@@ -611,15 +626,23 @@ class Account(
} }
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
val liveStoriesListAuthorsPerRelayFlow: Flow<Map<String, List<String>>?> by lazy { val liveStoriesFollowListAdvertizedRelayListFlow: Flow<Array<NoteState>?> =
combineTransform(liveStoriesFollowLists, connectToRelaysFlow) { followList, existing -> liveStoriesFollowLists
if (followList != null) { .transformLatest { followList ->
emit(authorsPerRelay(followList.usersPlusMe, existing.filter { it.feedTypes.contains(FeedType.FOLLOWS) && it.read }.map { it.url })) if (followList != null) {
} else { emitAll(combine(followList.usersPlusMe.map { getNIP65RelayListFlow(it) }) { it })
emit(MutableStateFlow(null)) } else {
emit(null)
}
}
val liveStoriesListAuthorsPerRelayFlow: Flow<Map<String, List<String>>?> by lazy {
combineTransform(liveStoriesFollowListAdvertizedRelayListFlow, connectToRelays) { adverisedRelayList, existing ->
if (adverisedRelayList != null) {
emit(authorsPerRelay(adverisedRelayList, existing.filter { it.feedTypes.contains(FeedType.FOLLOWS) && it.read }.map { it.url }))
} else {
emit(null)
} }
}.flatMapLatest {
it
} }
} }
@@ -640,15 +663,23 @@ class Account(
} }
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
val liveDiscoveryListAuthorsPerRelayFlow: Flow<Map<String, List<String>>?> by lazy { val liveDiscoveryFollowListAdvertizedRelayListFlow: Flow<Array<NoteState>?> =
combineTransform(liveDiscoveryFollowLists, connectToRelaysFlow) { followList, existing -> liveDiscoveryFollowLists
if (followList != null) { .transformLatest { followList ->
emit(authorsPerRelay(followList.usersPlusMe, existing.filter { it.read }.map { it.url })) if (followList != null) {
} else { emitAll(combine(followList.usersPlusMe.map { getNIP65RelayListFlow(it) }) { it })
emit(MutableStateFlow(null)) } else {
emit(null)
}
}
val liveDiscoveryListAuthorsPerRelayFlow: Flow<Map<String, List<String>>?> by lazy {
combineTransform(liveDiscoveryFollowListAdvertizedRelayListFlow, connectToRelays) { adverisedRelayList, existing ->
if (adverisedRelayList != null) {
emit(authorsPerRelay(adverisedRelayList, existing.filter { it.read }.map { it.url }))
} else {
emit(null)
} }
}.flatMapLatest {
it
} }
} }
@@ -20,14 +20,15 @@
*/ */
package com.vitorpamplona.ammolite.relays.filters package com.vitorpamplona.ammolite.relays.filters
import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.Event
/** /**
* This is a nostr filter with per-relay authors list and since parameters * This is a nostr filter with per-relay authors list and since parameters
*/ */
class SinceAuthorPerRelayFilter( class SinceAuthorPerRelayFilter(
val ids: List<String>? = null, val ids: List<HexKey>? = null,
val authors: Map<String, List<String>>? = null, val authors: Map<String, List<HexKey>>? = null,
val kinds: List<Int>? = null, val kinds: List<Int>? = null,
val tags: Map<String, List<String>>? = null, val tags: Map<String, List<String>>? = null,
val since: Map<String, EOSETime>? = null, val since: Map<String, EOSETime>? = null,