Adds Proxy relay list and adds support for fixed list of relays.
This commit is contained in:
@@ -34,7 +34,7 @@ import com.vitorpamplona.amethyst.model.localRelays.LocalRelayListState
|
||||
import com.vitorpamplona.amethyst.model.nip01UserMetadata.AccountOutboxRelayState
|
||||
import com.vitorpamplona.amethyst.model.nip01UserMetadata.NotificationInboxRelayState
|
||||
import com.vitorpamplona.amethyst.model.nip01UserMetadata.UserMetadataState
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListOutboxRelays
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListOutboxOrProxyRelays
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListState
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowsPerOutboxRelay
|
||||
import com.vitorpamplona.amethyst.model.nip03Timestamp.OtsState
|
||||
@@ -64,6 +64,8 @@ import com.vitorpamplona.amethyst.model.nip51Lists.indexerRelays.IndexerRelayLis
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.indexerRelays.IndexerRelayListState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.muteList.MuteListDecryptionCache
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.muteList.MuteListState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.proxyRelays.ProxyRelayListDecryptionCache
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.proxyRelays.ProxyRelayListState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.searchRelays.SearchRelayListDecryptionCache
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.searchRelays.SearchRelayListState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.trustedRelays.TrustedRelayListDecryptionCache
|
||||
@@ -246,6 +248,9 @@ class Account(
|
||||
val trustedRelayListDecryptionCache = TrustedRelayListDecryptionCache(signer)
|
||||
val trustedRelayList = TrustedRelayListState(signer, cache, trustedRelayListDecryptionCache, scope, settings)
|
||||
|
||||
val proxyRelayListDecryptionCache = ProxyRelayListDecryptionCache(signer)
|
||||
val proxyRelayList = ProxyRelayListState(signer, cache, proxyRelayListDecryptionCache, scope, settings)
|
||||
|
||||
val broadcastRelayListDecryptionCache = BroadcastRelayListDecryptionCache(signer)
|
||||
val broadcastRelayList = BroadcastRelayListState(signer, cache, broadcastRelayListDecryptionCache, scope, settings)
|
||||
|
||||
@@ -297,11 +302,11 @@ class Account(
|
||||
val trustedRelays = TrustedRelayListsState(nip65RelayList, privateStorageRelayList, localRelayList, dmRelayList, searchRelayList, trustedRelayList, broadcastRelayList, scope)
|
||||
|
||||
// Follows Relays
|
||||
val followOutboxes = FollowListOutboxRelays(kind3FollowList, blockedRelayList, cache, scope)
|
||||
val followPlusAllMine = MergedFollowPlusMineRelayListsState(followOutboxes, nip65RelayList, privateStorageRelayList, localRelayList, trustedRelayList, broadcastRelayList, indexerRelayList, scope)
|
||||
val followOutboxesOrProxy = FollowListOutboxOrProxyRelays(kind3FollowList, blockedRelayList, proxyRelayList, cache, scope)
|
||||
val followPlusAllMine = MergedFollowPlusMineRelayListsState(followOutboxesOrProxy, nip65RelayList, privateStorageRelayList, localRelayList, broadcastRelayList, indexerRelayList, scope)
|
||||
|
||||
// keeps a cache of the outbox relays for each author
|
||||
val followsPerRelay = FollowsPerOutboxRelay(kind3FollowList, blockedRelayList, cache, scope).flow
|
||||
val followsPerRelay = FollowsPerOutboxRelay(kind3FollowList, blockedRelayList, proxyRelayList, cache, scope).flow
|
||||
|
||||
// Merges all follow lists to create a single All Follows feed.
|
||||
val allFollows = MergedFollowListsState(kind3FollowList, hashtagList, geohashList, communityList, scope)
|
||||
@@ -341,6 +346,7 @@ class Account(
|
||||
locationFlow = geolocationFlow,
|
||||
followsRelays = followPlusAllMine.flow,
|
||||
blockedRelays = blockedRelayList.flow,
|
||||
proxyRelays = proxyRelayList.flow,
|
||||
caches = feedDecryptionCaches,
|
||||
signer = signer,
|
||||
scope = scope,
|
||||
@@ -355,6 +361,7 @@ class Account(
|
||||
locationFlow = geolocationFlow,
|
||||
followsRelays = followPlusAllMine.flow,
|
||||
blockedRelays = blockedRelayList.flow,
|
||||
proxyRelays = proxyRelayList.flow,
|
||||
caches = feedDecryptionCaches,
|
||||
signer = signer,
|
||||
scope = scope,
|
||||
@@ -369,6 +376,7 @@ class Account(
|
||||
locationFlow = geolocationFlow,
|
||||
followsRelays = followPlusAllMine.flow,
|
||||
blockedRelays = blockedRelayList.flow,
|
||||
proxyRelays = proxyRelayList.flow,
|
||||
caches = feedDecryptionCaches,
|
||||
signer = signer,
|
||||
scope = scope,
|
||||
@@ -383,6 +391,7 @@ class Account(
|
||||
locationFlow = geolocationFlow,
|
||||
followsRelays = followPlusAllMine.flow,
|
||||
blockedRelays = blockedRelayList.flow,
|
||||
proxyRelays = proxyRelayList.flow,
|
||||
caches = feedDecryptionCaches,
|
||||
signer = signer,
|
||||
scope = scope,
|
||||
@@ -1728,6 +1737,8 @@ class Account(
|
||||
|
||||
suspend fun saveBroadcastRelayList(trustedRelays: List<NormalizedRelayUrl>) = sendMyPublicAndPrivateOutbox(broadcastRelayList.saveRelayList(trustedRelays))
|
||||
|
||||
suspend fun saveProxyRelayList(trustedRelays: List<NormalizedRelayUrl>) = sendMyPublicAndPrivateOutbox(proxyRelayList.saveRelayList(trustedRelays))
|
||||
|
||||
suspend fun saveTrustedRelayList(trustedRelays: List<NormalizedRelayUrl>) = sendMyPublicAndPrivateOutbox(trustedRelayList.saveRelayList(trustedRelays))
|
||||
|
||||
suspend fun saveBlockedRelayList(blockedRelays: List<NormalizedRelayUrl>) = sendMyPublicAndPrivateOutbox(blockedRelayList.saveRelayList(blockedRelays))
|
||||
|
||||
@@ -140,6 +140,7 @@ import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BroadcastRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.IndexerRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relaySets.RelaySetEvent
|
||||
import com.vitorpamplona.quartz.nip52Calendar.CalendarDateSlotEvent
|
||||
@@ -959,6 +960,12 @@ object LocalCache : ILocalCache {
|
||||
wasVerified: Boolean,
|
||||
) = consumeBaseReplaceable(event, relay, wasVerified)
|
||||
|
||||
private fun consume(
|
||||
event: ProxyRelayListEvent,
|
||||
relay: NormalizedRelayUrl?,
|
||||
wasVerified: Boolean,
|
||||
) = consumeBaseReplaceable(event, relay, wasVerified)
|
||||
|
||||
private fun consume(
|
||||
event: IndexerRelayListEvent,
|
||||
relay: NormalizedRelayUrl?,
|
||||
@@ -2790,6 +2797,7 @@ object LocalCache : ILocalCache {
|
||||
is PictureEvent -> consume(event, relay, wasVerified)
|
||||
is PrivateDmEvent -> consume(event, relay, wasVerified)
|
||||
is PrivateOutboxRelayListEvent -> consume(event, relay, wasVerified)
|
||||
is ProxyRelayListEvent -> consume(event, relay, wasVerified)
|
||||
is PinListEvent -> consume(event, relay, wasVerified)
|
||||
is PeopleListEvent -> consume(event, relay, wasVerified)
|
||||
is PollNoteEvent -> consume(event, relay, wasVerified)
|
||||
|
||||
+58
-29
@@ -24,6 +24,7 @@ import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.NoteState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.blockedRelays.BlockedRelayListState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.proxyRelays.ProxyRelayListState
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
||||
@@ -31,19 +32,24 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.combineTransform
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
import kotlin.collections.flatten
|
||||
|
||||
class FollowListOutboxRelays(
|
||||
class FollowListOutboxOrProxyRelays(
|
||||
kind3Follows: FollowListState,
|
||||
blockedRelayList: BlockedRelayListState,
|
||||
proxyRelayList: ProxyRelayListState,
|
||||
val cache: LocalCache,
|
||||
scope: CoroutineScope,
|
||||
) {
|
||||
@@ -57,34 +63,63 @@ class FollowListOutboxRelays(
|
||||
|
||||
fun allRelayListFlows(followList: Set<HexKey>): List<StateFlow<NoteState>> = followList.map { getNIP65RelayListFlow(it) }
|
||||
|
||||
fun combineAllFlows(
|
||||
flows: List<StateFlow<NoteState>>,
|
||||
blockedRelays: Set<NormalizedRelayUrl>,
|
||||
): Flow<Set<NormalizedRelayUrl>> =
|
||||
fun combineAllFlows(flows: List<StateFlow<NoteState>>): Flow<Set<NormalizedRelayUrl>> =
|
||||
combine(flows) { relayListNotes: Array<NoteState> ->
|
||||
relayListNotes.mapNotNull {
|
||||
relayListNotes
|
||||
.mapNotNull {
|
||||
(it.note.event as? AdvertisedRelayListEvent)?.writeRelaysNorm()
|
||||
}
|
||||
}.map {
|
||||
it.flatten().toSet().minus(blockedRelays)
|
||||
}.flatten()
|
||||
.toSet()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val flow: StateFlow<Set<NormalizedRelayUrl>> =
|
||||
combineTransform(kind3Follows.flow, blockedRelayList.flow) { followList, blockedRelays ->
|
||||
val flows: List<StateFlow<NoteState>> = allRelayListFlows(followList.authors)
|
||||
val relayListFlows = combineAllFlows(flows, blockedRelays)
|
||||
emitAll(relayListFlows)
|
||||
val outboxRelayFlow: StateFlow<Set<NormalizedRelayUrl>> =
|
||||
kind3Follows.flow
|
||||
.transformLatest {
|
||||
emitAll(combineAllFlows(allRelayListFlows(it.authors)))
|
||||
}.onStart {
|
||||
val blocked = blockedRelayList.flow.value.toSet()
|
||||
val authors = kind3Follows.flow.value.authors
|
||||
val perRelay =
|
||||
authors
|
||||
emit(
|
||||
kind3Follows.flow.value.authors
|
||||
.mapNotNull {
|
||||
getNIP65RelayList(it)?.writeRelaysNorm()?.minus(blocked)
|
||||
getNIP65RelayList(it)?.writeRelaysNorm()
|
||||
}.flatten()
|
||||
.toSet()
|
||||
emit(perRelay)
|
||||
.toSet(),
|
||||
)
|
||||
}.distinctUntilChanged()
|
||||
.flowOn(Dispatchers.Default)
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.Eagerly,
|
||||
emptySet(),
|
||||
)
|
||||
|
||||
val outboxRelayMinusBlockedFlow: StateFlow<Set<NormalizedRelayUrl>> =
|
||||
combine(outboxRelayFlow, blockedRelayList.flow) { followList, blockedRelays ->
|
||||
followList.minus(blockedRelays)
|
||||
}.onStart {
|
||||
emit(outboxRelayFlow.value.minus(blockedRelayList.flow.value.toSet()))
|
||||
}.flowOn(Dispatchers.Default)
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.Eagerly,
|
||||
emptySet(),
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val flow: StateFlow<Set<NormalizedRelayUrl>> =
|
||||
proxyRelayList.flow
|
||||
.flatMapLatest { proxyRelays ->
|
||||
if (proxyRelays.isEmpty()) {
|
||||
outboxRelayMinusBlockedFlow
|
||||
} else {
|
||||
MutableStateFlow(proxyRelays)
|
||||
}
|
||||
}.onStart {
|
||||
emit(
|
||||
proxyRelayList.flow.value.ifEmpty {
|
||||
outboxRelayMinusBlockedFlow.value
|
||||
},
|
||||
)
|
||||
}.flowOn(Dispatchers.Default)
|
||||
.stateIn(
|
||||
scope,
|
||||
@@ -98,13 +133,7 @@ class FollowListOutboxRelays(
|
||||
.map { relayList ->
|
||||
relayList.map { it.url }.toSet()
|
||||
}.onStart {
|
||||
emit(
|
||||
kind3Follows.flow.value.authors
|
||||
.mapNotNull {
|
||||
getNIP65RelayList(it)?.writeRelaysNorm()?.map { it.url }?.toSet()
|
||||
}.flatten()
|
||||
.toSet(),
|
||||
)
|
||||
emit(flow.value.map { it.url }.toSet())
|
||||
}.flowOn(Dispatchers.Default)
|
||||
.stateIn(
|
||||
scope,
|
||||
+49
-14
@@ -24,6 +24,8 @@ import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.NoteState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.blockedRelays.BlockedRelayListState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.proxyRelays.ProxyRelayListState
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav.scope
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
||||
@@ -35,15 +37,19 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.combineTransform
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
|
||||
class FollowsPerOutboxRelay(
|
||||
kind3Follows: FollowListState,
|
||||
blockedRelayList: BlockedRelayListState,
|
||||
proxyRelayList: ProxyRelayListState,
|
||||
val cache: LocalCache,
|
||||
scope: CoroutineScope,
|
||||
) {
|
||||
@@ -57,42 +63,71 @@ class FollowsPerOutboxRelay(
|
||||
|
||||
fun allRelayListFlows(followList: Set<HexKey>): List<StateFlow<NoteState>> = followList.map { getNIP65RelayListFlow(it) }
|
||||
|
||||
fun combineAllFlows(
|
||||
flows: List<StateFlow<NoteState>>,
|
||||
blockedList: Set<NormalizedRelayUrl>,
|
||||
): Flow<Map<NormalizedRelayUrl, Set<HexKey>>> =
|
||||
fun combineAllRelayListFlows(flows: List<StateFlow<NoteState>>): Flow<Map<NormalizedRelayUrl, Set<HexKey>>> =
|
||||
combine(flows) { relayListNotes: Array<NoteState> ->
|
||||
mapOfSet {
|
||||
relayListNotes.forEach { noteState ->
|
||||
noteState.note.author?.pubkeyHex?.let { authorHex ->
|
||||
(noteState.note.event as? AdvertisedRelayListEvent)?.writeRelaysNorm()?.forEach { relay ->
|
||||
if (relay !in blockedList) {
|
||||
add(relay, authorHex)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val flow: StateFlow<Map<NormalizedRelayUrl, Set<HexKey>>> =
|
||||
combineTransform(kind3Follows.flow, blockedRelayList.flow) { followList, blockedList ->
|
||||
val flows: List<StateFlow<NoteState>> = allRelayListFlows(followList.authors)
|
||||
val relayListFlows = combineAllFlows(flows, blockedList)
|
||||
emitAll(relayListFlows)
|
||||
val outboxPerRelayFlow: StateFlow<Map<NormalizedRelayUrl, Set<HexKey>>> =
|
||||
kind3Follows.flow
|
||||
.transformLatest {
|
||||
emitAll(combineAllRelayListFlows(allRelayListFlows(it.authors)))
|
||||
}.onStart {
|
||||
emit(
|
||||
mapOfSet {
|
||||
kind3Follows.flow.value.authors.map { authorHex ->
|
||||
getNIP65RelayList(authorHex)?.writeRelaysNorm()?.forEach { relay ->
|
||||
if (relay !in blockedRelayList.flow.value) {
|
||||
add(relay, authorHex)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}.distinctUntilChanged()
|
||||
.flowOn(Dispatchers.Default)
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.Eagerly,
|
||||
emptyMap(),
|
||||
)
|
||||
|
||||
val outboxPerRelayMinusBlockedFlow: StateFlow<Map<NormalizedRelayUrl, Set<HexKey>>> =
|
||||
combine(outboxPerRelayFlow, blockedRelayList.flow) { followList, blockedRelays ->
|
||||
followList.minus(blockedRelays)
|
||||
}.onStart {
|
||||
emit(outboxPerRelayFlow.value.minus(blockedRelayList.flow.value.toSet()))
|
||||
}.flowOn(Dispatchers.Default)
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.Eagerly,
|
||||
emptyMap(),
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val flow: StateFlow<Map<NormalizedRelayUrl, Set<HexKey>>> =
|
||||
proxyRelayList.flow
|
||||
.flatMapLatest { proxyRelays ->
|
||||
if (proxyRelays.isEmpty()) {
|
||||
outboxPerRelayMinusBlockedFlow
|
||||
} else {
|
||||
kind3Follows.flow.map { follows ->
|
||||
proxyRelays.associateWith { follows.authors }
|
||||
}
|
||||
}
|
||||
}.onStart {
|
||||
if (proxyRelayList.flow.value.isEmpty()) {
|
||||
emit(outboxPerRelayMinusBlockedFlow.value)
|
||||
} else {
|
||||
emit(proxyRelayList.flow.value.associateWith { kind3Follows.flow.value.authors })
|
||||
}
|
||||
}.flowOn(Dispatchers.Default)
|
||||
.stateIn(
|
||||
scope,
|
||||
|
||||
+7
-6
@@ -49,7 +49,7 @@ class BlockedRelayListState(
|
||||
val scope: CoroutineScope,
|
||||
val settings: AccountSettings,
|
||||
) {
|
||||
fun getBlockedRelayListAddress() = BlockedRelayListEvent.Companion.createAddress(signer.pubKey)
|
||||
fun getBlockedRelayListAddress() = BlockedRelayListEvent.createAddress(signer.pubKey)
|
||||
|
||||
fun getBlockedRelayListNote(): AddressableNote = LocalCache.getOrCreateAddressableNote(getBlockedRelayListAddress())
|
||||
|
||||
@@ -64,12 +64,13 @@ class BlockedRelayListState(
|
||||
|
||||
val flow =
|
||||
getBlockedRelayListFlow()
|
||||
.map { normalizeBlockedRelayListWithBackup(it.note) }
|
||||
.onStart { emit(normalizeBlockedRelayListWithBackup(getBlockedRelayListNote())) }
|
||||
.map {
|
||||
normalizeBlockedRelayListWithBackup(it.note)
|
||||
}.onStart { emit(normalizeBlockedRelayListWithBackup(getBlockedRelayListNote())) }
|
||||
.flowOn(Dispatchers.Default)
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.Companion.Eagerly,
|
||||
SharingStarted.Eagerly,
|
||||
emptySet(),
|
||||
)
|
||||
|
||||
@@ -78,13 +79,13 @@ class BlockedRelayListState(
|
||||
val relayListForBlocked = getBlockedRelayList()
|
||||
|
||||
return if (relayListForBlocked != null && relayListForBlocked.tags.isNotEmpty()) {
|
||||
BlockedRelayListEvent.Companion.updateRelayList(
|
||||
BlockedRelayListEvent.updateRelayList(
|
||||
earlierVersion = relayListForBlocked,
|
||||
relays = blockedRelays,
|
||||
signer = signer,
|
||||
)
|
||||
} else {
|
||||
BlockedRelayListEvent.Companion.create(
|
||||
BlockedRelayListEvent.create(
|
||||
relays = blockedRelays,
|
||||
signer = signer,
|
||||
)
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ class HashtagListState(
|
||||
val scope: CoroutineScope,
|
||||
val settings: AccountSettings,
|
||||
) {
|
||||
fun getHashtagListAddress() = HashtagListEvent.Companion.createAddress(signer.pubKey)
|
||||
fun getHashtagListAddress() = HashtagListEvent.createAddress(signer.pubKey)
|
||||
|
||||
fun getHashtagListNote(): AddressableNote = cache.getOrCreateAddressableNote(getHashtagListAddress())
|
||||
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.model.nip51Lists.proxyRelays
|
||||
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.relayLists.GenericRelayListCache
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
|
||||
|
||||
class ProxyRelayListDecryptionCache(
|
||||
signer: NostrSigner,
|
||||
) : GenericRelayListCache<ProxyRelayListEvent>(signer)
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.model.nip51Lists.proxyRelays
|
||||
|
||||
import com.vitorpamplona.amethyst.model.AccountSettings
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.NoteState
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class ProxyRelayListState(
|
||||
val signer: NostrSigner,
|
||||
val cache: LocalCache,
|
||||
val decryptionCache: ProxyRelayListDecryptionCache,
|
||||
val scope: CoroutineScope,
|
||||
val settings: AccountSettings,
|
||||
) {
|
||||
fun getProxyRelayListAddress() = ProxyRelayListEvent.createAddress(signer.pubKey)
|
||||
|
||||
fun getProxyRelayListNote(): AddressableNote = cache.getOrCreateAddressableNote(getProxyRelayListAddress())
|
||||
|
||||
fun getProxyRelayListFlow(): StateFlow<NoteState> = getProxyRelayListNote().flow().metadata.stateFlow
|
||||
|
||||
fun getProxyRelayList(): ProxyRelayListEvent? = getProxyRelayListNote().event as? ProxyRelayListEvent
|
||||
|
||||
suspend fun normalizeProxyRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
|
||||
val event = note.event as? ProxyRelayListEvent
|
||||
return event?.let { decryptionCache.relays(it) } ?: emptySet()
|
||||
}
|
||||
|
||||
val flow =
|
||||
getProxyRelayListFlow()
|
||||
.map { normalizeProxyRelayListWithBackup(it.note) }
|
||||
.onStart { emit(normalizeProxyRelayListWithBackup(getProxyRelayListNote())) }
|
||||
.flowOn(Dispatchers.Default)
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.Eagerly,
|
||||
emptySet(),
|
||||
)
|
||||
|
||||
suspend fun saveRelayList(proxyRelays: List<NormalizedRelayUrl>): ProxyRelayListEvent {
|
||||
val relayListForProxy = getProxyRelayList()
|
||||
|
||||
return if (relayListForProxy != null && relayListForProxy.tags.isNotEmpty()) {
|
||||
ProxyRelayListEvent.updateRelayList(
|
||||
earlierVersion = relayListForProxy,
|
||||
relays = proxyRelays,
|
||||
signer = signer,
|
||||
)
|
||||
} else {
|
||||
ProxyRelayListEvent.create(
|
||||
relays = proxyRelays,
|
||||
signer = signer,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -32,6 +32,7 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlin.collections.map
|
||||
|
||||
@@ -44,14 +45,14 @@ class MergedFollowListsState(
|
||||
) {
|
||||
fun mergeLists(
|
||||
kind3: FollowListState.Kind3Follows,
|
||||
hashtages: Set<String>,
|
||||
hashtags: Set<String>,
|
||||
geohashes: Set<String>,
|
||||
community: Set<CommunityTag>,
|
||||
): FollowListState.Kind3Follows =
|
||||
FollowListState.Kind3Follows(
|
||||
kind3.authors,
|
||||
kind3.authorsPlusMe,
|
||||
kind3.hashtags + hashtages,
|
||||
kind3.hashtags + hashtags,
|
||||
kind3.geotags + geohashes,
|
||||
kind3.communities + community.map { it.address.toValue() },
|
||||
)
|
||||
@@ -73,7 +74,8 @@ class MergedFollowListsState(
|
||||
communityList.flow.value,
|
||||
),
|
||||
)
|
||||
}.flowOn(Dispatchers.Default)
|
||||
}.sample(200)
|
||||
.flowOn(Dispatchers.Default)
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.Eagerly,
|
||||
|
||||
+5
-10
@@ -22,10 +22,9 @@ package com.vitorpamplona.amethyst.model.serverList
|
||||
|
||||
import com.vitorpamplona.amethyst.model.edits.PrivateStorageRelayListState
|
||||
import com.vitorpamplona.amethyst.model.localRelays.LocalRelayListState
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListOutboxRelays
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListOutboxOrProxyRelays
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.broadcastRelays.BroadcastRelayListState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.indexerRelays.IndexerRelayListState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.trustedRelays.TrustedRelayListState
|
||||
import com.vitorpamplona.amethyst.model.nip65RelayList.Nip65RelayListState
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -38,11 +37,10 @@ import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class MergedFollowPlusMineRelayListsState(
|
||||
val followsOutboxRelayList: FollowListOutboxRelays,
|
||||
val followsOutboxOrProxyRelayList: FollowListOutboxOrProxyRelays,
|
||||
val nip65RelayList: Nip65RelayListState,
|
||||
val privateOutboxRelayList: PrivateStorageRelayListState,
|
||||
val localRelayList: LocalRelayListState,
|
||||
val trustedRelayList: TrustedRelayListState,
|
||||
val broadcastRelayList: BroadcastRelayListState,
|
||||
val indexerRelayList: IndexerRelayListState,
|
||||
val scope: CoroutineScope,
|
||||
@@ -52,12 +50,11 @@ class MergedFollowPlusMineRelayListsState(
|
||||
val flow: StateFlow<Set<NormalizedRelayUrl>> =
|
||||
combine(
|
||||
listOf(
|
||||
followsOutboxRelayList.flow,
|
||||
followsOutboxOrProxyRelayList.flow,
|
||||
nip65RelayList.outboxFlow,
|
||||
nip65RelayList.inboxFlow,
|
||||
privateOutboxRelayList.flow,
|
||||
localRelayList.flow,
|
||||
trustedRelayList.flow,
|
||||
broadcastRelayList.flow,
|
||||
indexerRelayList.flow,
|
||||
),
|
||||
@@ -66,12 +63,11 @@ class MergedFollowPlusMineRelayListsState(
|
||||
emit(
|
||||
mergeLists(
|
||||
arrayOf(
|
||||
followsOutboxRelayList.flow.value,
|
||||
followsOutboxOrProxyRelayList.flow.value,
|
||||
nip65RelayList.outboxFlow.value,
|
||||
nip65RelayList.inboxFlow.value,
|
||||
privateOutboxRelayList.flow.value,
|
||||
localRelayList.flow.value,
|
||||
trustedRelayList.flow.value,
|
||||
broadcastRelayList.flow.value,
|
||||
indexerRelayList.flow.value,
|
||||
),
|
||||
@@ -83,12 +79,11 @@ class MergedFollowPlusMineRelayListsState(
|
||||
SharingStarted.Eagerly,
|
||||
mergeLists(
|
||||
arrayOf(
|
||||
followsOutboxRelayList.flow.value,
|
||||
followsOutboxOrProxyRelayList.flow.value,
|
||||
nip65RelayList.outboxFlow.value,
|
||||
nip65RelayList.inboxFlow.value,
|
||||
privateOutboxRelayList.flow.value,
|
||||
localRelayList.flow.value,
|
||||
trustedRelayList.flow.value,
|
||||
broadcastRelayList.flow.value,
|
||||
indexerRelayList.flow.value,
|
||||
),
|
||||
|
||||
+5
-4
@@ -51,19 +51,20 @@ class FeedTopNavFilterState(
|
||||
val locationFlow: StateFlow<LocationState.LocationResult>,
|
||||
val followsRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val blockedRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val proxyRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val caches: FeedDecryptionCaches,
|
||||
val signer: NostrSigner,
|
||||
val scope: CoroutineScope,
|
||||
) {
|
||||
fun loadFlowsFor(listName: String): IFeedFlowsType =
|
||||
when (listName) {
|
||||
GLOBAL_FOLLOWS -> GlobalFeedFlow(followsRelays)
|
||||
ALL_FOLLOWS -> AllFollowsFeedFlow(allFollows, followsRelays, blockedRelays)
|
||||
AROUND_ME -> AroundMeFeedFlow(locationFlow, followsRelays)
|
||||
GLOBAL_FOLLOWS -> GlobalFeedFlow(followsRelays, proxyRelays)
|
||||
ALL_FOLLOWS -> AllFollowsFeedFlow(allFollows, followsRelays, blockedRelays, proxyRelays)
|
||||
AROUND_ME -> AroundMeFeedFlow(locationFlow, followsRelays, proxyRelays)
|
||||
else -> {
|
||||
val note = LocalCache.checkGetOrCreateAddressableNote(listName)
|
||||
if (note != null) {
|
||||
NoteFeedFlow(note.flow().metadata.stateFlow, signer, followsRelays, blockedRelays, caches)
|
||||
NoteFeedFlow(note.flow().metadata.stateFlow, signer, followsRelays, blockedRelays, proxyRelays, caches)
|
||||
} else {
|
||||
UnknownFeedFlow(listName)
|
||||
}
|
||||
|
||||
+6
-6
@@ -20,14 +20,14 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.model.topNavFeeds
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.LocationTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.utils.mapOfSet
|
||||
@@ -50,12 +50,12 @@ class MergedTopFeedAuthorListsState(
|
||||
fun authorList(navFilter: IFeedTopNavPerRelayFilterSet): Map<NormalizedRelayUrl, Set<HexKey>?> =
|
||||
when (navFilter) {
|
||||
is AllCommunitiesTopNavPerRelayFilterSet -> emptyMap()
|
||||
is AllFollowsByOutboxTopNavPerRelayFilterSet -> navFilter.set.mapValues { it.value.authors }
|
||||
is AuthorsByOutboxTopNavPerRelayFilterSet -> navFilter.set.mapValues { it.value.authors }
|
||||
is AllFollowsTopNavPerRelayFilterSet -> navFilter.set.mapValues { it.value.authors }
|
||||
is AuthorsTopNavPerRelayFilterSet -> navFilter.set.mapValues { it.value.authors }
|
||||
is GlobalTopNavPerRelayFilterSet -> emptyMap()
|
||||
is HashtagTopNavPerRelayFilterSet -> emptyMap()
|
||||
is LocationTopNavPerRelayFilterSet -> emptyMap()
|
||||
is MutedAuthorsByOutboxTopNavPerRelayFilterSet -> navFilter.set.mapValues { it.value.authors }
|
||||
is MutedAuthorsTopNavPerRelayFilterSet -> navFilter.set.mapValues { it.value.authors }
|
||||
is SingleCommunityTopNavPerRelayFilterSet -> navFilter.set.mapValues { it.value.authors }
|
||||
else -> emptyMap()
|
||||
}
|
||||
|
||||
+7
-6
@@ -39,6 +39,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlin.collections.associateWith
|
||||
|
||||
/**
|
||||
* This is a big OR filter on all fields.
|
||||
@@ -78,7 +79,7 @@ class AllFollowsByOutboxTopNavFilter(
|
||||
(communities != null && noteEvent.isTaggedAddressableNotes(communities))
|
||||
}
|
||||
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<AllFollowsByOutboxTopNavPerRelayFilterSet> {
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<AllFollowsTopNavPerRelayFilterSet> {
|
||||
val authorsPerRelay =
|
||||
if (authors != null) {
|
||||
OutboxRelayLoader.toAuthorsPerRelayFlow(authors, cache) { it }
|
||||
@@ -95,9 +96,9 @@ class AllFollowsByOutboxTopNavFilter(
|
||||
return combine(authorsPerRelay, communitiesPerRelay, defaultRelays, blockedRelays) { perRelayAuthors, perRelayCommunities, default, blockedRelays ->
|
||||
val allRelays = (perRelayAuthors.keys + perRelayCommunities.keys).filter { it !in blockedRelays }.ifEmpty { default }
|
||||
|
||||
AllFollowsByOutboxTopNavPerRelayFilterSet(
|
||||
AllFollowsTopNavPerRelayFilterSet(
|
||||
allRelays.associateWith {
|
||||
AllFollowsByOutboxTopNavPerRelayFilter(
|
||||
AllFollowsTopNavPerRelayFilter(
|
||||
authors = perRelayAuthors[it],
|
||||
hashtags = hashtags,
|
||||
geotags = geotags,
|
||||
@@ -108,7 +109,7 @@ class AllFollowsByOutboxTopNavFilter(
|
||||
}
|
||||
}
|
||||
|
||||
override fun startValue(cache: LocalCache): AllFollowsByOutboxTopNavPerRelayFilterSet {
|
||||
override fun startValue(cache: LocalCache): AllFollowsTopNavPerRelayFilterSet {
|
||||
val authorsPerRelay =
|
||||
if (authors != null) {
|
||||
OutboxRelayLoader.authorsPerRelaySnapshot(authors, cache) { it }
|
||||
@@ -124,9 +125,9 @@ class AllFollowsByOutboxTopNavFilter(
|
||||
|
||||
val allRelays = (authorsPerRelay.keys + communitiesPerRelay.keys).filter { it !in blockedRelays.value }.ifEmpty { defaultRelays.value }
|
||||
|
||||
return AllFollowsByOutboxTopNavPerRelayFilterSet(
|
||||
return AllFollowsTopNavPerRelayFilterSet(
|
||||
allRelays.associateWith {
|
||||
AllFollowsByOutboxTopNavPerRelayFilter(
|
||||
AllFollowsTopNavPerRelayFilter(
|
||||
authors = authorsPerRelay[it],
|
||||
hashtags = hashtags,
|
||||
geotags = geotags,
|
||||
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.model.topNavFeeds.allFollows
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.isTaggedAddressableNotes
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.isTaggedGeoHashes
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHashes
|
||||
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
||||
import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId
|
||||
import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlin.collections.associateWith
|
||||
|
||||
/**
|
||||
* This is a big OR filter on all fields.
|
||||
*/
|
||||
@Immutable
|
||||
class AllFollowsByProxyTopNavFilter(
|
||||
val authors: Set<String>? = null,
|
||||
val hashtags: Set<String>? = null,
|
||||
val geotags: Set<String>? = null,
|
||||
val communities: Set<String>? = null,
|
||||
val proxyRelays: Set<NormalizedRelayUrl>,
|
||||
) : IFeedTopNavFilter {
|
||||
val geotagScopes: Set<String>? = geotags?.mapTo(mutableSetOf<String>()) { GeohashId.Companion.toScope(it) }
|
||||
val hashtagScopes: Set<String>? = hashtags?.mapTo(mutableSetOf<String>()) { HashtagId.Companion.toScope(it) }
|
||||
|
||||
override fun matchAuthor(pubkey: HexKey): Boolean = authors == null || pubkey in authors
|
||||
|
||||
override fun match(noteEvent: Event): Boolean =
|
||||
if (noteEvent is LiveActivitiesEvent) {
|
||||
(authors != null && noteEvent.participantsIntersect(authors)) ||
|
||||
(hashtags != null && noteEvent.isTaggedHashes(hashtags)) ||
|
||||
(geotags != null && noteEvent.isTaggedGeoHashes(geotags)) ||
|
||||
(communities != null && noteEvent.isTaggedAddressableNotes(communities))
|
||||
} else if (noteEvent is CommentEvent) {
|
||||
// ignore follows and checks only the root scope
|
||||
(authors != null && noteEvent.pubKey in authors) ||
|
||||
(hashtags != null && noteEvent.isTaggedHashes(hashtags)) ||
|
||||
(hashtagScopes != null && noteEvent.isTaggedScopes(hashtagScopes)) ||
|
||||
(geotags != null && noteEvent.isTaggedGeoHashes(geotags)) ||
|
||||
(geotagScopes != null && noteEvent.isTaggedScopes(geotagScopes)) ||
|
||||
(communities != null && noteEvent.isTaggedAddressableNotes(communities))
|
||||
} else {
|
||||
(authors != null && noteEvent.pubKey in authors) ||
|
||||
(hashtags != null && noteEvent.isTaggedHashes(hashtags)) ||
|
||||
(geotags != null && noteEvent.isTaggedGeoHashes(geotags)) ||
|
||||
(communities != null && noteEvent.isTaggedAddressableNotes(communities))
|
||||
}
|
||||
|
||||
// forces the use of the Proxy on all connections, replacing the outbox model.
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<AllFollowsTopNavPerRelayFilterSet> =
|
||||
MutableStateFlow(
|
||||
AllFollowsTopNavPerRelayFilterSet(
|
||||
proxyRelays.associateWith {
|
||||
AllFollowsTopNavPerRelayFilter(
|
||||
authors = authors,
|
||||
hashtags = hashtags,
|
||||
geotags = geotags,
|
||||
communities = communities,
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
override fun startValue(cache: LocalCache): AllFollowsTopNavPerRelayFilterSet {
|
||||
// forces the use of the Proxy on all connections, replacing the outbox model.
|
||||
return AllFollowsTopNavPerRelayFilterSet(
|
||||
proxyRelays.associateWith {
|
||||
AllFollowsTopNavPerRelayFilter(
|
||||
authors = authors,
|
||||
hashtags = hashtags,
|
||||
geotags = geotags,
|
||||
communities = communities,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
+18
-4
@@ -26,15 +26,20 @@ import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import kotlinx.coroutines.flow.FlowCollector
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
||||
class AllFollowsFeedFlow(
|
||||
val allFollows: StateFlow<FollowListState.Kind3Follows?>,
|
||||
val followsRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val blockedRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val proxyRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
) : IFeedFlowsType {
|
||||
fun convert(kind3: FollowListState.Kind3Follows?): AllFollowsByOutboxTopNavFilter =
|
||||
fun convert(
|
||||
kind3: FollowListState.Kind3Follows?,
|
||||
proxyRelays: Set<NormalizedRelayUrl>,
|
||||
): IFeedTopNavFilter =
|
||||
if (kind3 != null) {
|
||||
if (proxyRelays.isEmpty()) {
|
||||
AllFollowsByOutboxTopNavFilter(
|
||||
authors = kind3.authors,
|
||||
hashtags = kind3.hashtags,
|
||||
@@ -43,6 +48,15 @@ class AllFollowsFeedFlow(
|
||||
defaultRelays = followsRelays,
|
||||
blockedRelays = blockedRelays,
|
||||
)
|
||||
} else {
|
||||
AllFollowsByProxyTopNavFilter(
|
||||
authors = kind3.authors,
|
||||
hashtags = kind3.hashtags,
|
||||
geotags = kind3.geotags,
|
||||
communities = kind3.communities,
|
||||
proxyRelays = proxyRelays,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
AllFollowsByOutboxTopNavFilter(
|
||||
authors = emptySet(),
|
||||
@@ -51,9 +65,9 @@ class AllFollowsFeedFlow(
|
||||
)
|
||||
}
|
||||
|
||||
override fun flow() = allFollows.map(::convert)
|
||||
override fun flow() = combine(allFollows, proxyRelays, ::convert)
|
||||
|
||||
override fun startValue(): AllFollowsByOutboxTopNavFilter = convert(allFollows.value)
|
||||
override fun startValue(): IFeedTopNavFilter = convert(allFollows.value, proxyRelays.value)
|
||||
|
||||
override suspend fun startValue(collector: FlowCollector<IFeedTopNavFilter>) {
|
||||
collector.emit(startValue())
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId
|
||||
* This is a big OR filter.
|
||||
*/
|
||||
@Immutable
|
||||
class AllFollowsByOutboxTopNavPerRelayFilter(
|
||||
class AllFollowsTopNavPerRelayFilter(
|
||||
val authors: Set<String>? = null,
|
||||
val hashtags: Set<String>? = null,
|
||||
val geotags: Set<String>? = null,
|
||||
+2
-2
@@ -23,6 +23,6 @@ package com.vitorpamplona.amethyst.model.topNavFeeds.allFollows
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
|
||||
class AllFollowsByOutboxTopNavPerRelayFilterSet(
|
||||
val set: Map<NormalizedRelayUrl, AllFollowsByOutboxTopNavPerRelayFilter>,
|
||||
class AllFollowsTopNavPerRelayFilterSet(
|
||||
val set: Map<NormalizedRelayUrl, AllFollowsTopNavPerRelayFilter>,
|
||||
) : IFeedTopNavPerRelayFilterSet
|
||||
+12
-7
@@ -26,30 +26,35 @@ import com.vitorpamplona.amethyst.service.location.LocationState
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import kotlinx.coroutines.flow.FlowCollector
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
||||
class AroundMeFeedFlow(
|
||||
val location: StateFlow<LocationState.LocationResult>,
|
||||
val allFollowRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val outboxRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val proxyRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
) : IFeedFlowsType {
|
||||
fun convert(result: LocationState.LocationResult): LocationTopNavFilter =
|
||||
fun convert(
|
||||
result: LocationState.LocationResult,
|
||||
outboxRelays: Set<NormalizedRelayUrl>,
|
||||
proxyRelays: Set<NormalizedRelayUrl>,
|
||||
): LocationTopNavFilter =
|
||||
if (result is LocationState.LocationResult.Success) {
|
||||
// 2 neighbors deep = 25x25km
|
||||
LocationTopNavFilter(
|
||||
geotags = compute50kmRange(result.geoHash).toSet(),
|
||||
relays = allFollowRelays,
|
||||
relayList = proxyRelays.ifEmpty { outboxRelays },
|
||||
)
|
||||
} else {
|
||||
// empty feed until we have a successful geohash
|
||||
LocationTopNavFilter(
|
||||
geotags = emptySet(),
|
||||
relays = allFollowRelays,
|
||||
relayList = proxyRelays.ifEmpty { outboxRelays },
|
||||
)
|
||||
}
|
||||
|
||||
override fun flow() = location.map(::convert)
|
||||
override fun flow() = combine(location, outboxRelays, proxyRelays, ::convert)
|
||||
|
||||
override fun startValue(): LocationTopNavFilter = convert(location.value)
|
||||
override fun startValue(): LocationTopNavFilter = convert(location.value, outboxRelays.value, proxyRelays.value)
|
||||
|
||||
override suspend fun startValue(collector: FlowCollector<IFeedTopNavFilter>) {
|
||||
collector.emit(startValue())
|
||||
|
||||
+10
-8
@@ -30,15 +30,14 @@ import com.vitorpamplona.quartz.nip01Core.tags.geohash.isTaggedGeoHashes
|
||||
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
|
||||
import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
@Immutable
|
||||
class LocationTopNavFilter(
|
||||
val geotags: Set<String>,
|
||||
val relays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val relayList: Set<NormalizedRelayUrl>,
|
||||
) : IFeedTopNavFilter {
|
||||
val geotagScopes: Set<String> = geotags.mapTo(mutableSetOf<String>()) { GeohashId.Companion.toScope(it) }
|
||||
val geotagScopes: Set<String> = geotags.mapTo(mutableSetOf<String>()) { GeohashId.toScope(it) }
|
||||
|
||||
override fun matchAuthor(pubkey: HexKey): Boolean = true
|
||||
|
||||
@@ -54,9 +53,12 @@ class LocationTopNavFilter(
|
||||
}
|
||||
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<LocationTopNavPerRelayFilterSet> =
|
||||
relays.map {
|
||||
LocationTopNavPerRelayFilterSet(it.associateWith { LocationTopNavPerRelayFilter(geotags) })
|
||||
}
|
||||
MutableStateFlow(
|
||||
LocationTopNavPerRelayFilterSet(relayList.associateWith { LocationTopNavPerRelayFilter(geotags) }),
|
||||
)
|
||||
|
||||
override fun startValue(cache: LocalCache): LocationTopNavPerRelayFilterSet = LocationTopNavPerRelayFilterSet(relays.value.associateWith { LocationTopNavPerRelayFilter(geotags) })
|
||||
override fun startValue(cache: LocalCache): LocationTopNavPerRelayFilterSet =
|
||||
LocationTopNavPerRelayFilterSet(
|
||||
relayList.associateWith { LocationTopNavPerRelayFilter(geotags) },
|
||||
)
|
||||
}
|
||||
|
||||
+3
-2
@@ -28,9 +28,10 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
class GlobalFeedFlow(
|
||||
val relays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val outboxRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val proxyRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
) : IFeedFlowsType {
|
||||
val default = GlobalTopNavFilter(relays)
|
||||
val default = GlobalTopNavFilter(outboxRelays, proxyRelays)
|
||||
|
||||
override fun flow() = MutableStateFlow(default)
|
||||
|
||||
|
||||
+16
-7
@@ -28,23 +28,32 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlin.collections.associateWith
|
||||
import kotlin.collections.isNotEmpty
|
||||
|
||||
@Immutable
|
||||
class GlobalTopNavFilter(
|
||||
val relays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val outboxRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val proxyRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
) : IFeedTopNavFilter {
|
||||
override fun matchAuthor(pubkey: HexKey): Boolean = true
|
||||
|
||||
override fun match(noteEvent: Event) = true
|
||||
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<GlobalTopNavPerRelayFilterSet> =
|
||||
relays.map {
|
||||
GlobalTopNavPerRelayFilterSet(it.associateWith { GlobalTopNavPerRelayFilter })
|
||||
combine(outboxRelays, proxyRelays) { outboxRelays, proxyRelays ->
|
||||
if (proxyRelays.isNotEmpty()) {
|
||||
GlobalTopNavPerRelayFilterSet(proxyRelays.associateWith { GlobalTopNavPerRelayFilter })
|
||||
} else {
|
||||
GlobalTopNavPerRelayFilterSet(outboxRelays.associateWith { GlobalTopNavPerRelayFilter })
|
||||
}
|
||||
}
|
||||
|
||||
override fun startValue(cache: LocalCache): GlobalTopNavPerRelayFilterSet =
|
||||
GlobalTopNavPerRelayFilterSet(
|
||||
relays.value.associateWith { GlobalTopNavPerRelayFilter },
|
||||
)
|
||||
if (proxyRelays.value.isNotEmpty()) {
|
||||
GlobalTopNavPerRelayFilterSet(proxyRelays.value.associateWith { GlobalTopNavPerRelayFilter })
|
||||
} else {
|
||||
GlobalTopNavPerRelayFilterSet(outboxRelays.value.associateWith { GlobalTopNavPerRelayFilter })
|
||||
}
|
||||
}
|
||||
|
||||
+6
-9
@@ -30,13 +30,12 @@ import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHashes
|
||||
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
|
||||
import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
@Immutable
|
||||
class HashtagTopNavFilter(
|
||||
val hashtags: Set<String>,
|
||||
val relays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val relayList: Set<NormalizedRelayUrl>,
|
||||
) : IFeedTopNavFilter {
|
||||
val hashtagScopes: Set<String> = hashtags.mapTo(mutableSetOf()) { HashtagId.toScope(it) }
|
||||
|
||||
@@ -50,16 +49,14 @@ class HashtagTopNavFilter(
|
||||
}
|
||||
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<HashtagTopNavPerRelayFilterSet> =
|
||||
relays.map {
|
||||
MutableStateFlow(
|
||||
HashtagTopNavPerRelayFilterSet(
|
||||
it.associateWith { HashtagTopNavPerRelayFilter(hashtags) },
|
||||
relayList.associateWith { HashtagTopNavPerRelayFilter(hashtags) },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override fun startValue(cache: LocalCache): HashtagTopNavPerRelayFilterSet =
|
||||
HashtagTopNavPerRelayFilterSet(
|
||||
relays.value.associateWith {
|
||||
HashtagTopNavPerRelayFilter(hashtags)
|
||||
},
|
||||
relayList.associateWith { HashtagTopNavPerRelayFilter(hashtags) },
|
||||
)
|
||||
}
|
||||
|
||||
+116
-13
@@ -28,8 +28,10 @@ import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.LocationTopNavFilte
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.hashtag.HashtagTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
@@ -43,16 +45,20 @@ import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListEvent
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.FlowCollector
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
import kotlinx.coroutines.flow.combineTransform
|
||||
|
||||
class NoteFeedFlow(
|
||||
val metadataFlow: StateFlow<NoteState?>,
|
||||
val signer: NostrSigner,
|
||||
val allFollowRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val outboxRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val blockedRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val proxyRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val caches: FeedDecryptionCaches,
|
||||
) : IFeedFlowsType {
|
||||
fun process(noteEvent: Event): IFeedTopNavFilter =
|
||||
fun processByOutbox(
|
||||
noteEvent: Event,
|
||||
outboxRelays: Set<NormalizedRelayUrl>,
|
||||
): IFeedTopNavFilter =
|
||||
when (noteEvent) {
|
||||
is PeopleListEvent -> {
|
||||
if (noteEvent.dTag() == PeopleListEvent.Companion.BLOCK_LIST_D_TAG) {
|
||||
@@ -71,10 +77,10 @@ class NoteFeedFlow(
|
||||
AllCommunitiesTopNavFilter(caches.communityListCache.cachedCommunityIdSet(noteEvent), blockedRelays)
|
||||
}
|
||||
is HashtagListEvent -> {
|
||||
HashtagTopNavFilter(caches.hashtagCache.cachedHashtags(noteEvent), allFollowRelays)
|
||||
HashtagTopNavFilter(caches.hashtagCache.cachedHashtags(noteEvent), outboxRelays)
|
||||
}
|
||||
is GeohashListEvent -> {
|
||||
LocationTopNavFilter(caches.geohashCache.cachedGeohashes(noteEvent), allFollowRelays)
|
||||
LocationTopNavFilter(caches.geohashCache.cachedGeohashes(noteEvent), outboxRelays)
|
||||
}
|
||||
is CommunityDefinitionEvent -> {
|
||||
SingleCommunityTopNavFilter(
|
||||
@@ -87,7 +93,10 @@ class NoteFeedFlow(
|
||||
else -> AuthorsByOutboxTopNavFilter(emptySet(), blockedRelays)
|
||||
}
|
||||
|
||||
suspend fun FlowCollector<IFeedTopNavFilter>.process(noteEvent: Event) {
|
||||
suspend fun FlowCollector<IFeedTopNavFilter>.processByOutbox(
|
||||
noteEvent: Event,
|
||||
outboxRelays: Set<NormalizedRelayUrl>,
|
||||
) {
|
||||
when (noteEvent) {
|
||||
is PeopleListEvent -> {
|
||||
if (noteEvent.dTag() == PeopleListEvent.Companion.BLOCK_LIST_D_TAG) {
|
||||
@@ -106,10 +115,10 @@ class NoteFeedFlow(
|
||||
emit(AllCommunitiesTopNavFilter(caches.communityListCache.communityIdSet(noteEvent), blockedRelays))
|
||||
}
|
||||
is HashtagListEvent -> {
|
||||
emit(HashtagTopNavFilter(caches.hashtagCache.hashtags(noteEvent), allFollowRelays))
|
||||
emit(HashtagTopNavFilter(caches.hashtagCache.hashtags(noteEvent), outboxRelays))
|
||||
}
|
||||
is GeohashListEvent -> {
|
||||
emit(LocationTopNavFilter(caches.geohashCache.geohashes(noteEvent), allFollowRelays))
|
||||
emit(LocationTopNavFilter(caches.geohashCache.geohashes(noteEvent), outboxRelays))
|
||||
}
|
||||
is CommunityDefinitionEvent -> {
|
||||
emit(
|
||||
@@ -128,23 +137,113 @@ class NoteFeedFlow(
|
||||
}
|
||||
}
|
||||
|
||||
fun processByProxy(
|
||||
noteEvent: Event,
|
||||
proxyRelays: Set<NormalizedRelayUrl>,
|
||||
): IFeedTopNavFilter =
|
||||
when (noteEvent) {
|
||||
is PeopleListEvent -> {
|
||||
if (noteEvent.dTag() == PeopleListEvent.Companion.BLOCK_LIST_D_TAG) {
|
||||
MutedAuthorsByProxyTopNavFilter(caches.peopleListCache.cachedUserIdSet(noteEvent), proxyRelays)
|
||||
} else {
|
||||
AuthorsByProxyTopNavFilter(caches.peopleListCache.cachedUserIdSet(noteEvent), proxyRelays)
|
||||
}
|
||||
}
|
||||
is MuteListEvent -> {
|
||||
MutedAuthorsByProxyTopNavFilter(caches.muteListCache.cachedUserIdSet(noteEvent), proxyRelays)
|
||||
}
|
||||
is FollowListEvent -> {
|
||||
AuthorsByProxyTopNavFilter(noteEvent.followIdSet(), proxyRelays)
|
||||
}
|
||||
is CommunityListEvent -> {
|
||||
AllCommunitiesTopNavFilter(caches.communityListCache.cachedCommunityIdSet(noteEvent), blockedRelays)
|
||||
}
|
||||
is HashtagListEvent -> {
|
||||
HashtagTopNavFilter(caches.hashtagCache.cachedHashtags(noteEvent), proxyRelays)
|
||||
}
|
||||
is GeohashListEvent -> {
|
||||
LocationTopNavFilter(caches.geohashCache.cachedGeohashes(noteEvent), proxyRelays)
|
||||
}
|
||||
is CommunityDefinitionEvent -> {
|
||||
SingleCommunityTopNavFilter(
|
||||
community = noteEvent.addressTag(),
|
||||
authors = noteEvent.moderatorKeys().toSet().ifEmpty { null },
|
||||
relays = noteEvent.relayUrls().toSet(),
|
||||
blockedRelays = blockedRelays,
|
||||
)
|
||||
}
|
||||
else -> AuthorsByProxyTopNavFilter(emptySet(), proxyRelays)
|
||||
}
|
||||
|
||||
suspend fun FlowCollector<IFeedTopNavFilter>.processByProxy(
|
||||
noteEvent: Event,
|
||||
proxyRelays: Set<NormalizedRelayUrl>,
|
||||
) {
|
||||
when (noteEvent) {
|
||||
is PeopleListEvent -> {
|
||||
if (noteEvent.dTag() == PeopleListEvent.Companion.BLOCK_LIST_D_TAG) {
|
||||
emit(MutedAuthorsByProxyTopNavFilter(caches.peopleListCache.userIdSet(noteEvent), proxyRelays))
|
||||
} else {
|
||||
emit(AuthorsByProxyTopNavFilter(caches.peopleListCache.userIdSet(noteEvent), proxyRelays))
|
||||
}
|
||||
}
|
||||
is MuteListEvent -> {
|
||||
emit(MutedAuthorsByProxyTopNavFilter(caches.muteListCache.mutedUserIdSet(noteEvent), proxyRelays))
|
||||
}
|
||||
is FollowListEvent -> {
|
||||
emit(AuthorsByProxyTopNavFilter(noteEvent.followIdSet(), proxyRelays))
|
||||
}
|
||||
is CommunityListEvent -> {
|
||||
emit(AllCommunitiesTopNavFilter(caches.communityListCache.communityIdSet(noteEvent), blockedRelays))
|
||||
}
|
||||
is HashtagListEvent -> {
|
||||
emit(HashtagTopNavFilter(caches.hashtagCache.hashtags(noteEvent), proxyRelays))
|
||||
}
|
||||
is GeohashListEvent -> {
|
||||
emit(LocationTopNavFilter(caches.geohashCache.geohashes(noteEvent), proxyRelays))
|
||||
}
|
||||
is CommunityDefinitionEvent -> {
|
||||
emit(
|
||||
SingleCommunityTopNavFilter(
|
||||
community = noteEvent.addressTag(),
|
||||
authors = noteEvent.moderatorKeys().toSet().ifEmpty { null },
|
||||
relays = noteEvent.relayUrls().toSet(),
|
||||
blockedRelays = blockedRelays,
|
||||
),
|
||||
)
|
||||
}
|
||||
else ->
|
||||
emit(
|
||||
AuthorsByProxyTopNavFilter(emptySet(), proxyRelays),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun flow() =
|
||||
metadataFlow.transformLatest { noteState ->
|
||||
combineTransform(metadataFlow, outboxRelays, proxyRelays) { noteState, outboxRelays, proxyRelays ->
|
||||
val noteEvent = noteState?.note?.event
|
||||
if (noteEvent == null) {
|
||||
AuthorsByOutboxTopNavFilter(emptySet(), blockedRelays)
|
||||
} else {
|
||||
process(noteEvent)
|
||||
if (proxyRelays.isEmpty()) {
|
||||
processByOutbox(noteEvent, outboxRelays)
|
||||
} else {
|
||||
processByProxy(noteEvent, proxyRelays)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun startValue(): IFeedTopNavFilter {
|
||||
val noteEvent = metadataFlow.value?.note?.event
|
||||
if (noteEvent == null) {
|
||||
return if (noteEvent == null) {
|
||||
return AuthorsByOutboxTopNavFilter(emptySet(), blockedRelays)
|
||||
} else {
|
||||
return process(noteEvent)
|
||||
if (proxyRelays.value.isEmpty()) {
|
||||
processByOutbox(noteEvent, outboxRelays.value)
|
||||
} else {
|
||||
processByProxy(noteEvent, proxyRelays.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +252,11 @@ class NoteFeedFlow(
|
||||
if (noteEvent == null) {
|
||||
collector.emit(AuthorsByOutboxTopNavFilter(emptySet(), blockedRelays))
|
||||
} else {
|
||||
collector.process(noteEvent)
|
||||
if (proxyRelays.value.isEmpty()) {
|
||||
collector.processByOutbox(noteEvent, outboxRelays.value)
|
||||
} else {
|
||||
collector.processByProxy(noteEvent, proxyRelays.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -47,11 +47,11 @@ class AuthorsByOutboxTopNavFilter(
|
||||
}
|
||||
|
||||
fun convert(map: Map<NormalizedRelayUrl, Set<HexKey>>) =
|
||||
AuthorsByOutboxTopNavPerRelayFilterSet(
|
||||
map.mapValues { AuthorsByOutboxTopNavPerRelayFilter(it.value) },
|
||||
AuthorsTopNavPerRelayFilterSet(
|
||||
map.mapValues { AuthorsTopNavPerRelayFilter(it.value) },
|
||||
)
|
||||
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<AuthorsByOutboxTopNavPerRelayFilterSet> {
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<AuthorsTopNavPerRelayFilterSet> {
|
||||
val authorsPerRelay = OutboxRelayLoader.toAuthorsPerRelayFlow(authors, cache) { it }
|
||||
|
||||
return combine(authorsPerRelay, blockedRelays) { authors, blocked ->
|
||||
@@ -59,7 +59,7 @@ class AuthorsByOutboxTopNavFilter(
|
||||
}
|
||||
}
|
||||
|
||||
override fun startValue(cache: LocalCache): AuthorsByOutboxTopNavPerRelayFilterSet {
|
||||
override fun startValue(cache: LocalCache): AuthorsTopNavPerRelayFilterSet {
|
||||
val authorsPerRelay = OutboxRelayLoader.authorsPerRelaySnapshot(authors, cache) { it }
|
||||
|
||||
return convert(authorsPerRelay.minus(blockedRelays.value))
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
@Immutable
|
||||
class AuthorsByProxyTopNavFilter(
|
||||
val authors: Set<String>,
|
||||
val proxyRelays: Set<NormalizedRelayUrl>,
|
||||
) : IFeedTopNavFilter {
|
||||
override fun matchAuthor(pubkey: HexKey) = pubkey in authors
|
||||
|
||||
override fun match(noteEvent: Event): Boolean =
|
||||
if (noteEvent is LiveActivitiesEvent) {
|
||||
noteEvent.participantsIntersect(authors)
|
||||
} else {
|
||||
noteEvent.pubKey in authors
|
||||
}
|
||||
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<AuthorsTopNavPerRelayFilterSet> =
|
||||
MutableStateFlow(
|
||||
AuthorsTopNavPerRelayFilterSet(
|
||||
proxyRelays.associateWith { AuthorsTopNavPerRelayFilter(authors) },
|
||||
),
|
||||
)
|
||||
|
||||
override fun startValue(cache: LocalCache): AuthorsTopNavPerRelayFilterSet =
|
||||
AuthorsTopNavPerRelayFilterSet(
|
||||
proxyRelays.associateWith { AuthorsTopNavPerRelayFilter(authors) },
|
||||
)
|
||||
}
|
||||
+1
-1
@@ -24,6 +24,6 @@ import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilter
|
||||
|
||||
@Immutable
|
||||
class AuthorsByOutboxTopNavPerRelayFilter(
|
||||
class AuthorsTopNavPerRelayFilter(
|
||||
val authors: Set<String>,
|
||||
) : IFeedTopNavPerRelayFilter
|
||||
+2
-2
@@ -23,6 +23,6 @@ package com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
|
||||
class AuthorsByOutboxTopNavPerRelayFilterSet(
|
||||
val set: Map<NormalizedRelayUrl, AuthorsByOutboxTopNavPerRelayFilter>,
|
||||
class AuthorsTopNavPerRelayFilterSet(
|
||||
val set: Map<NormalizedRelayUrl, AuthorsTopNavPerRelayFilter>,
|
||||
) : IFeedTopNavPerRelayFilterSet
|
||||
+4
-4
@@ -47,11 +47,11 @@ class MutedAuthorsByOutboxTopNavFilter(
|
||||
}
|
||||
|
||||
fun convert(map: Map<NormalizedRelayUrl, Set<HexKey>>) =
|
||||
MutedAuthorsByOutboxTopNavPerRelayFilterSet(
|
||||
map.mapValues { MutedAuthorsByOutboxTopNavPerRelayFilter(it.value) },
|
||||
MutedAuthorsTopNavPerRelayFilterSet(
|
||||
map.mapValues { MutedAuthorsTopNavPerRelayFilter(it.value) },
|
||||
)
|
||||
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<MutedAuthorsByOutboxTopNavPerRelayFilterSet> {
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<MutedAuthorsTopNavPerRelayFilterSet> {
|
||||
val authorsPerRelay = OutboxRelayLoader.toAuthorsPerRelayFlow(authors, cache) { it }
|
||||
|
||||
return combine(authorsPerRelay, blockedRelays) { authors, blocked ->
|
||||
@@ -59,7 +59,7 @@ class MutedAuthorsByOutboxTopNavFilter(
|
||||
}
|
||||
}
|
||||
|
||||
override fun startValue(cache: LocalCache): MutedAuthorsByOutboxTopNavPerRelayFilterSet {
|
||||
override fun startValue(cache: LocalCache): MutedAuthorsTopNavPerRelayFilterSet {
|
||||
val authorsPerRelay = OutboxRelayLoader.authorsPerRelaySnapshot(authors, cache) { it }
|
||||
|
||||
return convert(authorsPerRelay.minus(blockedRelays.value))
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
@Immutable
|
||||
class MutedAuthorsByProxyTopNavFilter(
|
||||
val authors: Set<String>,
|
||||
val proxyRelays: Set<NormalizedRelayUrl>,
|
||||
) : IFeedTopNavFilter {
|
||||
override fun matchAuthor(pubkey: HexKey) = pubkey in authors
|
||||
|
||||
override fun match(noteEvent: Event): Boolean =
|
||||
if (noteEvent is LiveActivitiesEvent) {
|
||||
noteEvent.participantsIntersect(authors)
|
||||
} else {
|
||||
noteEvent.pubKey in authors
|
||||
}
|
||||
|
||||
override fun toPerRelayFlow(cache: LocalCache): Flow<MutedAuthorsTopNavPerRelayFilterSet> =
|
||||
MutableStateFlow(
|
||||
MutedAuthorsTopNavPerRelayFilterSet(
|
||||
proxyRelays.associateWith { MutedAuthorsTopNavPerRelayFilter(authors) },
|
||||
),
|
||||
)
|
||||
|
||||
override fun startValue(cache: LocalCache): MutedAuthorsTopNavPerRelayFilterSet =
|
||||
MutedAuthorsTopNavPerRelayFilterSet(
|
||||
proxyRelays.associateWith { MutedAuthorsTopNavPerRelayFilter(authors) },
|
||||
)
|
||||
}
|
||||
+1
-1
@@ -24,6 +24,6 @@ import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilter
|
||||
|
||||
@Immutable
|
||||
class MutedAuthorsByOutboxTopNavPerRelayFilter(
|
||||
class MutedAuthorsTopNavPerRelayFilter(
|
||||
val authors: Set<String>,
|
||||
) : IFeedTopNavPerRelayFilter
|
||||
+2
-2
@@ -23,6 +23,6 @@ package com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
|
||||
class MutedAuthorsByOutboxTopNavPerRelayFilterSet(
|
||||
val set: Map<NormalizedRelayUrl, MutedAuthorsByOutboxTopNavPerRelayFilter>,
|
||||
class MutedAuthorsTopNavPerRelayFilterSet(
|
||||
val set: Map<NormalizedRelayUrl, MutedAuthorsTopNavPerRelayFilter>,
|
||||
) : IFeedTopNavPerRelayFilterSet
|
||||
+6
@@ -31,9 +31,12 @@ import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.privateOutbox.PrivateOutboxRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip38UserStatus.StatusEvent
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.geohashList.GeohashListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.hashtagList.HashtagListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BroadcastRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.IndexerRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent
|
||||
@@ -59,6 +62,9 @@ val AccountInfoAndListsFromKeyKinds2 =
|
||||
TrustedRelayListEvent.KIND,
|
||||
BroadcastRelayListEvent.KIND,
|
||||
IndexerRelayListEvent.KIND,
|
||||
ProxyRelayListEvent.KIND,
|
||||
HashtagListEvent.KIND,
|
||||
GeohashListEvent.KIND,
|
||||
)
|
||||
|
||||
val AmethystMetadataKinds = listOf(AppSpecificDataEvent.KIND)
|
||||
|
||||
+6
@@ -28,9 +28,12 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.geohashList.GeohashListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.hashtagList.HashtagListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BroadcastRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.IndexerRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip96FileStorage.config.FileServersEvent
|
||||
@@ -53,6 +56,9 @@ val BasicAccountInfoKinds2 =
|
||||
TrustedRelayListEvent.KIND,
|
||||
BroadcastRelayListEvent.KIND,
|
||||
IndexerRelayListEvent.KIND,
|
||||
ProxyRelayListEvent.KIND,
|
||||
HashtagListEvent.KIND,
|
||||
GeohashListEvent.KIND,
|
||||
)
|
||||
|
||||
fun filterBasicAccountInfoFromKeys(
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.vitorpamplona.amethyst.model.nip51Lists.HiddenUsersState
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -62,7 +63,7 @@ class FilterByListParams(
|
||||
|
||||
fun isGlobal(comingFrom: List<NormalizedRelayUrl>) =
|
||||
followLists is GlobalTopNavFilter &&
|
||||
comingFrom.any { followLists.relays.value.contains(it) }
|
||||
comingFrom.any { followLists.outboxRelays.value.contains(it) }
|
||||
|
||||
fun match(
|
||||
noteEvent: Event,
|
||||
@@ -89,7 +90,7 @@ class FilterByListParams(
|
||||
hiddenUsers: HiddenUsersState.LiveHiddenUsers,
|
||||
): FilterByListParams =
|
||||
FilterByListParams(
|
||||
isHiddenList = followLists is MutedAuthorsByOutboxTopNavFilter,
|
||||
isHiddenList = followLists is MutedAuthorsByOutboxTopNavFilter || followLists is MutedAuthorsByProxyTopNavFilter,
|
||||
followLists = followLists,
|
||||
hiddenLists = hiddenUsers,
|
||||
)
|
||||
|
||||
@@ -85,6 +85,7 @@ import com.vitorpamplona.amethyst.ui.note.types.DisplayFollowList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayIndexerRelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayNIP65RelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayProxyRelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayRelaySet
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplaySearchRelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayTrustedRelayList
|
||||
@@ -191,6 +192,7 @@ import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BroadcastRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.IndexerRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relaySets.RelaySetEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent
|
||||
@@ -659,6 +661,7 @@ private fun RenderNoteRow(
|
||||
is BlockedRelayListEvent -> DisplayBlockedRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is TrustedRelayListEvent -> DisplayTrustedRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is IndexerRelayListEvent -> DisplayIndexerRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is ProxyRelayListEvent -> DisplayProxyRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is BroadcastRelayListEvent -> DisplayBroadcastRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is PinListEvent -> RenderPinListEvent(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is EmojiPackEvent -> RenderEmojiPack(baseNote, true, backgroundColor, accountViewModel)
|
||||
|
||||
@@ -234,6 +234,27 @@ fun DisplayTrustedRelayList(
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DisplayProxyRelayList(
|
||||
baseNote: Note,
|
||||
backgroundColor: MutableState<Color>,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
val relays by accountViewModel.account.proxyRelayListDecryptionCache.observeDecryptedRelayList(baseNote).collectAsStateWithLifecycle(
|
||||
accountViewModel.account.proxyRelayListDecryptionCache.fastStartValueForRelayList(baseNote),
|
||||
)
|
||||
|
||||
DisplayRelaySet(
|
||||
relays,
|
||||
stringRes(id = R.string.proxy_relays_title),
|
||||
null,
|
||||
backgroundColor,
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DisplayIndexerRelayList(
|
||||
baseNote: Note,
|
||||
|
||||
+6
-6
@@ -21,14 +21,14 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip23LongForm
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.LocationTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip23LongForm.subassemblies.filterLongFormByAllCommunities
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip23LongForm.subassemblies.filterLongFormByAuthors
|
||||
@@ -46,12 +46,12 @@ fun makeLongFormFilter(
|
||||
): List<RelayBasedFilter> =
|
||||
when (feedSettings) {
|
||||
is AllCommunitiesTopNavPerRelayFilterSet -> filterLongFormByAllCommunities(feedSettings, since, defaultSince)
|
||||
is AllFollowsByOutboxTopNavPerRelayFilterSet -> filterLongFormByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsByOutboxTopNavPerRelayFilterSet -> filterLongFormByAuthors(feedSettings, since, defaultSince)
|
||||
is AllFollowsTopNavPerRelayFilterSet -> filterLongFormByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsTopNavPerRelayFilterSet -> filterLongFormByAuthors(feedSettings, since, defaultSince)
|
||||
is GlobalTopNavPerRelayFilterSet -> filterLongFormGlobal(feedSettings, since, defaultSince)
|
||||
is HashtagTopNavPerRelayFilterSet -> filterLongFormByHashtag(feedSettings, since, defaultSince)
|
||||
is LocationTopNavPerRelayFilterSet -> filterLongFormByGeohash(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsByOutboxTopNavPerRelayFilterSet -> filterLongFormByAuthors(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsTopNavPerRelayFilterSet -> filterLongFormByAuthors(feedSettings, since, defaultSince)
|
||||
is SingleCommunityTopNavPerRelayFilterSet -> filterLongFormByCommunity(feedSettings, since, defaultSince)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip23LongForm.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
@@ -50,7 +50,7 @@ fun filterLongFormAuthors(
|
||||
}
|
||||
|
||||
fun filterLongFormByAuthors(
|
||||
authorSet: AuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: AuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
@@ -71,7 +71,7 @@ fun filterLongFormByAuthors(
|
||||
}
|
||||
|
||||
fun filterLongFormByAuthors(
|
||||
authorSet: MutedAuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: MutedAuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+2
-2
@@ -20,12 +20,12 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip23LongForm.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
|
||||
fun filterLongFormByFollows(
|
||||
followsSet: AllFollowsByOutboxTopNavPerRelayFilterSet,
|
||||
followsSet: AllFollowsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+6
@@ -46,9 +46,12 @@ import com.vitorpamplona.amethyst.model.ParticipantListBuilder
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.model.nip28PublicChats.PublicChatChannel
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel.observeChannel
|
||||
import com.vitorpamplona.amethyst.ui.layouts.LeftPictureLayout
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
@@ -115,6 +118,9 @@ fun RenderPublicChatChannelThumb(
|
||||
is MutedAuthorsByOutboxTopNavFilter -> topFilter.authors
|
||||
is AllFollowsByOutboxTopNavFilter -> topFilter.authors
|
||||
is SingleCommunityTopNavFilter -> topFilter.authors
|
||||
is AuthorsByProxyTopNavFilter -> topFilter.authors
|
||||
is MutedAuthorsByProxyTopNavFilter -> topFilter.authors
|
||||
is AllFollowsByProxyTopNavFilter -> topFilter.authors
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -21,14 +21,14 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip28Chats
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.LocationTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip28Chats.subassemblies.filterPublicChatsByAllCommunities
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip28Chats.subassemblies.filterPublicChatsByAuthors
|
||||
@@ -46,12 +46,12 @@ fun makePublicChatsFilter(
|
||||
): List<RelayBasedFilter> =
|
||||
when (feedSettings) {
|
||||
is AllCommunitiesTopNavPerRelayFilterSet -> filterPublicChatsByAllCommunities(feedSettings, since, defaultSince)
|
||||
is AllFollowsByOutboxTopNavPerRelayFilterSet -> filterPublicChatsByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsByOutboxTopNavPerRelayFilterSet -> filterPublicChatsByAuthors(feedSettings, since, defaultSince)
|
||||
is AllFollowsTopNavPerRelayFilterSet -> filterPublicChatsByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsTopNavPerRelayFilterSet -> filterPublicChatsByAuthors(feedSettings, since, defaultSince)
|
||||
is GlobalTopNavPerRelayFilterSet -> filterPublicChatsGlobal(feedSettings, since, defaultSince)
|
||||
is HashtagTopNavPerRelayFilterSet -> filterPublicChatsByHashtag(feedSettings, since, defaultSince)
|
||||
is LocationTopNavPerRelayFilterSet -> filterPublicChatsByGeohash(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsByOutboxTopNavPerRelayFilterSet -> filterPublicChatsByAuthors(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsTopNavPerRelayFilterSet -> filterPublicChatsByAuthors(feedSettings, since, defaultSince)
|
||||
is SingleCommunityTopNavPerRelayFilterSet -> filterPublicChatsByCommunity(feedSettings, since, defaultSince)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip28Chats.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
@@ -57,7 +57,7 @@ fun filterPublicChatsAuthors(
|
||||
}
|
||||
|
||||
fun filterPublicChatsByAuthors(
|
||||
authorSet: AuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: AuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
@@ -78,7 +78,7 @@ fun filterPublicChatsByAuthors(
|
||||
}
|
||||
|
||||
fun filterPublicChatsByAuthors(
|
||||
authorSet: MutedAuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: MutedAuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+2
-2
@@ -20,12 +20,12 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip28Chats.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
|
||||
fun filterPublicChatsByFollows(
|
||||
followsSet: AllFollowsByOutboxTopNavPerRelayFilterSet,
|
||||
followsSet: AllFollowsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+6
-6
@@ -21,14 +21,14 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip51FollowSets
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.LocationTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip51FollowSets.subassemblies.filterFollowSetsByAllCommunities
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip51FollowSets.subassemblies.filterFollowSetsByAuthors
|
||||
@@ -46,12 +46,12 @@ fun makeFollowSetsFilter(
|
||||
): List<RelayBasedFilter> =
|
||||
when (feedSettings) {
|
||||
is AllCommunitiesTopNavPerRelayFilterSet -> filterFollowSetsByAllCommunities(feedSettings, since, defaultSince)
|
||||
is AllFollowsByOutboxTopNavPerRelayFilterSet -> filterFollowSetsByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsByOutboxTopNavPerRelayFilterSet -> filterFollowSetsByAuthors(feedSettings, since, defaultSince)
|
||||
is AllFollowsTopNavPerRelayFilterSet -> filterFollowSetsByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsTopNavPerRelayFilterSet -> filterFollowSetsByAuthors(feedSettings, since, defaultSince)
|
||||
is GlobalTopNavPerRelayFilterSet -> filterFollowSetsGlobal(feedSettings, since, defaultSince)
|
||||
is HashtagTopNavPerRelayFilterSet -> filterFollowSetsByHashtag(feedSettings, since, defaultSince)
|
||||
is LocationTopNavPerRelayFilterSet -> filterFollowSetsByGeohash(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsByOutboxTopNavPerRelayFilterSet -> filterFollowSetsByAuthors(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsTopNavPerRelayFilterSet -> filterFollowSetsByAuthors(feedSettings, since, defaultSince)
|
||||
is SingleCommunityTopNavPerRelayFilterSet -> filterFollowSetsByCommunity(feedSettings, since, defaultSince)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip51FollowSets.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
@@ -50,7 +50,7 @@ fun filterFollowSetsAuthors(
|
||||
}
|
||||
|
||||
fun filterFollowSetsByAuthors(
|
||||
authorSet: AuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: AuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
@@ -71,7 +71,7 @@ fun filterFollowSetsByAuthors(
|
||||
}
|
||||
|
||||
fun filterFollowSetsByAuthors(
|
||||
authorSet: MutedAuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: MutedAuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+2
-2
@@ -20,12 +20,12 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip51FollowSets.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
|
||||
fun filterFollowSetsByFollows(
|
||||
followsSet: AllFollowsByOutboxTopNavPerRelayFilterSet,
|
||||
followsSet: AllFollowsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+6
@@ -25,9 +25,12 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.ParticipantListBuilder
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
||||
import com.vitorpamplona.quartz.nip51Lists.muteList.MuteListEvent
|
||||
@@ -80,6 +83,9 @@ open class DiscoverLiveFeedFilter(
|
||||
is MutedAuthorsByOutboxTopNavFilter -> topFilter.authors
|
||||
is AllFollowsByOutboxTopNavFilter -> topFilter.authors
|
||||
is SingleCommunityTopNavFilter -> topFilter.authors
|
||||
is AuthorsByProxyTopNavFilter -> topFilter.authors
|
||||
is MutedAuthorsByProxyTopNavFilter -> topFilter.authors
|
||||
is AllFollowsByProxyTopNavFilter -> topFilter.authors
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -46,9 +46,12 @@ import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.ParticipantListBuilder
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteAndMap
|
||||
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
@@ -242,6 +245,9 @@ fun LoadParticipants(
|
||||
is MutedAuthorsByOutboxTopNavFilter -> topFilter.authors
|
||||
is AllFollowsByOutboxTopNavFilter -> topFilter.authors
|
||||
is SingleCommunityTopNavFilter -> topFilter.authors
|
||||
is AuthorsByProxyTopNavFilter -> topFilter.authors
|
||||
is MutedAuthorsByProxyTopNavFilter -> topFilter.authors
|
||||
is AllFollowsByProxyTopNavFilter -> topFilter.authors
|
||||
else -> emptySet()
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -21,14 +21,14 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip53LiveActivities
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.LocationTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip53LiveActivities.subassemblies.filterLiveActivitiesByAllCommunities
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip53LiveActivities.subassemblies.filterLiveActivitiesByAuthors
|
||||
@@ -46,12 +46,12 @@ fun makeLiveActivitiesFilter(
|
||||
): List<RelayBasedFilter> =
|
||||
when (feedSettings) {
|
||||
is AllCommunitiesTopNavPerRelayFilterSet -> filterLiveActivitiesByAllCommunities(feedSettings, since, defaultSince)
|
||||
is AllFollowsByOutboxTopNavPerRelayFilterSet -> filterLiveActivitiesByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsByOutboxTopNavPerRelayFilterSet -> filterLiveActivitiesByAuthors(feedSettings, since, defaultSince)
|
||||
is AllFollowsTopNavPerRelayFilterSet -> filterLiveActivitiesByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsTopNavPerRelayFilterSet -> filterLiveActivitiesByAuthors(feedSettings, since, defaultSince)
|
||||
is GlobalTopNavPerRelayFilterSet -> filterLiveActivitiesGlobal(feedSettings, since, defaultSince)
|
||||
is HashtagTopNavPerRelayFilterSet -> filterLiveActivitiesByHashtag(feedSettings, since, defaultSince)
|
||||
is LocationTopNavPerRelayFilterSet -> filterLiveActivitiesByGeohash(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsByOutboxTopNavPerRelayFilterSet -> filterLiveActivitiesByAuthors(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsTopNavPerRelayFilterSet -> filterLiveActivitiesByAuthors(feedSettings, since, defaultSince)
|
||||
is SingleCommunityTopNavPerRelayFilterSet -> filterLiveActivitiesByCommunity(feedSettings, since, defaultSince)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip53LiveActivities.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
@@ -62,7 +62,7 @@ fun filterLiveActivitiesAuthors(
|
||||
}
|
||||
|
||||
fun filterLiveActivitiesByAuthors(
|
||||
authorSet: AuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: AuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
@@ -83,7 +83,7 @@ fun filterLiveActivitiesByAuthors(
|
||||
}
|
||||
|
||||
fun filterLiveActivitiesByAuthors(
|
||||
authorSet: MutedAuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: MutedAuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+2
-2
@@ -20,12 +20,12 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip53LiveActivities.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
|
||||
fun filterLiveActivitiesByFollows(
|
||||
followsSet: AllFollowsByOutboxTopNavPerRelayFilterSet,
|
||||
followsSet: AllFollowsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+6
@@ -48,9 +48,12 @@ import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.ParticipantListBuilder
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote
|
||||
import com.vitorpamplona.amethyst.ui.layouts.LeftPictureLayout
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
@@ -208,6 +211,9 @@ fun LoadModerators(
|
||||
is MutedAuthorsByOutboxTopNavFilter -> topFilter.authors
|
||||
is AllFollowsByOutboxTopNavFilter -> topFilter.authors
|
||||
is SingleCommunityTopNavFilter -> topFilter.authors
|
||||
is AuthorsByProxyTopNavFilter -> topFilter.authors
|
||||
is MutedAuthorsByProxyTopNavFilter -> topFilter.authors
|
||||
is AllFollowsByProxyTopNavFilter -> topFilter.authors
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -21,14 +21,14 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip72Communities
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.LocationTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip72Communities.subassemblies.filterCommunitiesByAllCommunities
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip72Communities.subassemblies.filterCommunitiesByAuthors
|
||||
@@ -46,12 +46,12 @@ fun makeCommunitiesFilter(
|
||||
): List<RelayBasedFilter> =
|
||||
when (feedSettings) {
|
||||
is AllCommunitiesTopNavPerRelayFilterSet -> filterCommunitiesByAllCommunities(feedSettings, since, defaultSince)
|
||||
is AllFollowsByOutboxTopNavPerRelayFilterSet -> filterCommunitiesByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsByOutboxTopNavPerRelayFilterSet -> filterCommunitiesByAuthors(feedSettings, since, defaultSince)
|
||||
is AllFollowsTopNavPerRelayFilterSet -> filterCommunitiesByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsTopNavPerRelayFilterSet -> filterCommunitiesByAuthors(feedSettings, since, defaultSince)
|
||||
is GlobalTopNavPerRelayFilterSet -> filterCommunitiesGlobal(feedSettings, since, defaultSince)
|
||||
is HashtagTopNavPerRelayFilterSet -> filterCommunitiesByHashtag(feedSettings, since, defaultSince)
|
||||
is LocationTopNavPerRelayFilterSet -> filterCommunitiesByGeohash(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsByOutboxTopNavPerRelayFilterSet -> filterCommunitiesByAuthors(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsTopNavPerRelayFilterSet -> filterCommunitiesByAuthors(feedSettings, since, defaultSince)
|
||||
is SingleCommunityTopNavPerRelayFilterSet -> filterCommunitiesByCommunity(feedSettings, since, defaultSince)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip72Communities.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
@@ -51,7 +51,7 @@ fun filterCommunitiesAuthors(
|
||||
}
|
||||
|
||||
fun filterCommunitiesByAuthors(
|
||||
authorSet: AuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: AuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
@@ -72,7 +72,7 @@ fun filterCommunitiesByAuthors(
|
||||
}
|
||||
|
||||
fun filterCommunitiesByAuthors(
|
||||
authorSet: MutedAuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: MutedAuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+2
-2
@@ -20,12 +20,12 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip72Communities.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
|
||||
fun filterCommunitiesByFollows(
|
||||
followsSet: AllFollowsByOutboxTopNavPerRelayFilterSet,
|
||||
followsSet: AllFollowsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+6
-6
@@ -21,14 +21,14 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip90DVMs
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.LocationTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip90DVMs.subassemblies.filterContentDVMsByAllCommunities
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip90DVMs.subassemblies.filterContentDVMsByAuthors
|
||||
@@ -46,12 +46,12 @@ fun makeContentDVMsFilter(
|
||||
): List<RelayBasedFilter> =
|
||||
when (feedSettings) {
|
||||
is AllCommunitiesTopNavPerRelayFilterSet -> filterContentDVMsByAllCommunities(feedSettings, since, defaultSince)
|
||||
is AllFollowsByOutboxTopNavPerRelayFilterSet -> filterContentDVMsByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsByOutboxTopNavPerRelayFilterSet -> filterContentDVMsByAuthors(feedSettings, since, defaultSince)
|
||||
is AllFollowsTopNavPerRelayFilterSet -> filterContentDVMsByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsTopNavPerRelayFilterSet -> filterContentDVMsByAuthors(feedSettings, since, defaultSince)
|
||||
is GlobalTopNavPerRelayFilterSet -> filterContentDVMsGlobal(feedSettings, since, defaultSince)
|
||||
is HashtagTopNavPerRelayFilterSet -> filterContentDVMsByHashtag(feedSettings, since, defaultSince)
|
||||
is LocationTopNavPerRelayFilterSet -> filterContentDVMsByGeohash(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsByOutboxTopNavPerRelayFilterSet -> filterContentDVMsByAuthors(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsTopNavPerRelayFilterSet -> filterContentDVMsByAuthors(feedSettings, since, defaultSince)
|
||||
is SingleCommunityTopNavPerRelayFilterSet -> filterContentDVMsByCommunity(feedSettings, since, defaultSince)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip90DVMs.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
@@ -52,7 +52,7 @@ fun filterContentDVMsAuthors(
|
||||
}
|
||||
|
||||
fun filterContentDVMsByAuthors(
|
||||
authorSet: AuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: AuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
@@ -73,7 +73,7 @@ fun filterContentDVMsByAuthors(
|
||||
}
|
||||
|
||||
fun filterContentDVMsByAuthors(
|
||||
authorSet: MutedAuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: MutedAuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+2
-2
@@ -20,12 +20,12 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip90DVMs.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
|
||||
fun filterContentDVMsByFollows(
|
||||
followsSet: AllFollowsByOutboxTopNavPerRelayFilterSet,
|
||||
followsSet: AllFollowsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+6
-6
@@ -21,14 +21,14 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.LocationTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds.subassemblies.filterClassifiedsByAllCommunities
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds.subassemblies.filterClassifiedsByAuthors
|
||||
@@ -46,12 +46,12 @@ fun makeClassifiedsFilter(
|
||||
): List<RelayBasedFilter> =
|
||||
when (feedSettings) {
|
||||
is AllCommunitiesTopNavPerRelayFilterSet -> filterClassifiedsByAllCommunities(feedSettings, since, defaultSince)
|
||||
is AllFollowsByOutboxTopNavPerRelayFilterSet -> filterClassifiedsByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsByOutboxTopNavPerRelayFilterSet -> filterClassifiedsByAuthors(feedSettings, since, defaultSince)
|
||||
is AllFollowsTopNavPerRelayFilterSet -> filterClassifiedsByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsTopNavPerRelayFilterSet -> filterClassifiedsByAuthors(feedSettings, since, defaultSince)
|
||||
is GlobalTopNavPerRelayFilterSet -> filterClassifiedsGlobal(feedSettings, since, defaultSince)
|
||||
is HashtagTopNavPerRelayFilterSet -> filterClassifiedsByHashtag(feedSettings, since, defaultSince)
|
||||
is LocationTopNavPerRelayFilterSet -> filterClassifiedsByGeohash(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsByOutboxTopNavPerRelayFilterSet -> filterClassifiedsByAuthors(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsTopNavPerRelayFilterSet -> filterClassifiedsByAuthors(feedSettings, since, defaultSince)
|
||||
is SingleCommunityTopNavPerRelayFilterSet -> filterClassifiedsByCommunity(feedSettings, since, defaultSince)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
@@ -50,7 +50,7 @@ fun filterClassifiedsAuthors(
|
||||
}
|
||||
|
||||
fun filterClassifiedsByAuthors(
|
||||
authorSet: AuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: AuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
@@ -71,7 +71,7 @@ fun filterClassifiedsByAuthors(
|
||||
}
|
||||
|
||||
fun filterClassifiedsByAuthors(
|
||||
authorSet: MutedAuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: MutedAuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+2
-2
@@ -20,12 +20,12 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
|
||||
fun filterClassifiedsByFollows(
|
||||
followsSet: AllFollowsByOutboxTopNavPerRelayFilterSet,
|
||||
followsSet: AllFollowsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ fun PrepareViewModelsGeoHashScreen(
|
||||
factory =
|
||||
GeoHashFeedViewModel.Factory(
|
||||
tag.geohash,
|
||||
accountViewModel.account.followOutboxes.flow.value,
|
||||
accountViewModel.account.followOutboxesOrProxy.flow.value,
|
||||
accountViewModel.account,
|
||||
),
|
||||
)
|
||||
|
||||
+2
-2
@@ -68,7 +68,7 @@ fun filterPostsByGeohash(
|
||||
Filter(
|
||||
tags = geohashesToFollowMap,
|
||||
kinds = PostsByGeohashKinds,
|
||||
limit = 200,
|
||||
limit = 100,
|
||||
since = since,
|
||||
),
|
||||
),
|
||||
@@ -78,7 +78,7 @@ fun filterPostsByGeohash(
|
||||
Filter(
|
||||
tags = geohashesScoreMap,
|
||||
kinds = CommentKinds,
|
||||
limit = 200,
|
||||
limit = 100,
|
||||
since = since,
|
||||
),
|
||||
),
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ fun GeoHashFilterAssemblerSubscription(
|
||||
// even if they are tracking the same tag.
|
||||
val state =
|
||||
remember(tag) {
|
||||
GeohashQueryState(tag.geohash, accountViewModel.account.followOutboxes.flow.value)
|
||||
GeohashQueryState(tag.geohash, accountViewModel.account.followOutboxesOrProxy.flow.value)
|
||||
}
|
||||
|
||||
KeyDataSourceSubscription(state, accountViewModel.dataSources().geohashes)
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ fun PrepareViewModelsHashtagScreen(
|
||||
factory =
|
||||
HashtagFeedViewModel.Factory(
|
||||
tag.hashtag,
|
||||
accountViewModel.account.followOutboxes.flow.value,
|
||||
accountViewModel.account.followOutboxesOrProxy.flow.value,
|
||||
accountViewModel.account,
|
||||
),
|
||||
)
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ fun HashtagFilterAssemblerSubscription(
|
||||
// even if they are tracking the same tag.
|
||||
val state =
|
||||
remember(tag) {
|
||||
HashtagQueryState(tag.hashtag, accountViewModel.account.followOutboxes.flow.value)
|
||||
HashtagQueryState(tag.hashtag, accountViewModel.account.followOutboxesOrProxy.flow.value)
|
||||
}
|
||||
|
||||
KeyDataSourceSubscription(state, accountViewModel.dataSources().hashtags)
|
||||
|
||||
+4
-1
@@ -24,6 +24,7 @@ import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
||||
@@ -39,7 +40,9 @@ class HomeConversationsFeedFilter(
|
||||
) : AdditiveFeedFilter<Note>() {
|
||||
override fun feedKey(): String = account.userProfile().pubkeyHex + "-" + account.settings.defaultHomeFollowList.value
|
||||
|
||||
override fun showHiddenKey(): Boolean = account.liveHomeFollowLists.value is MutedAuthorsByOutboxTopNavFilter
|
||||
override fun showHiddenKey(): Boolean =
|
||||
account.liveHomeFollowLists.value is MutedAuthorsByOutboxTopNavFilter ||
|
||||
account.liveHomeFollowLists.value is MutedAuthorsByProxyTopNavFilter
|
||||
|
||||
override fun feed(): List<Note> {
|
||||
val filterParams = buildFilterParams(account)
|
||||
|
||||
+6
@@ -25,9 +25,12 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.emphChat.EphemeralChatChannel
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveComplexFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
||||
import com.vitorpamplona.quartz.experimental.ephemChat.chat.EphemeralChatEvent
|
||||
@@ -130,6 +133,9 @@ class HomeLiveFilter(
|
||||
is MutedAuthorsByOutboxTopNavFilter -> topFilter.authors
|
||||
is AllFollowsByOutboxTopNavFilter -> topFilter.authors
|
||||
is SingleCommunityTopNavFilter -> topFilter.authors
|
||||
is AuthorsByProxyTopNavFilter -> topFilter.authors
|
||||
is MutedAuthorsByProxyTopNavFilter -> topFilter.authors
|
||||
is AllFollowsByProxyTopNavFilter -> topFilter.authors
|
||||
else -> null
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -24,6 +24,7 @@ import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavFilter
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByProxyTopNavFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
||||
@@ -45,7 +46,9 @@ class HomeNewThreadFeedFilter(
|
||||
) : AdditiveFeedFilter<Note>() {
|
||||
override fun feedKey(): String = account.userProfile().pubkeyHex + "-" + account.settings.defaultHomeFollowList.value
|
||||
|
||||
override fun showHiddenKey(): Boolean = account.liveHomeFollowLists.value is MutedAuthorsByOutboxTopNavFilter
|
||||
override fun showHiddenKey(): Boolean =
|
||||
account.liveHomeFollowLists.value is MutedAuthorsByOutboxTopNavFilter ||
|
||||
account.liveHomeFollowLists.value is MutedAuthorsByProxyTopNavFilter
|
||||
|
||||
fun buildFilterParams(account: Account): FilterByListParams =
|
||||
FilterByListParams.create(
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.nip65Follows
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.nip01Core.filterHomePostsByGeohashes
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.nip01Core.filterHomePostsByHashtags
|
||||
@@ -29,7 +29,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.nip72Commun
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
|
||||
fun filterHomePostsByAllFollows(
|
||||
followsSet: AllFollowsByOutboxTopNavPerRelayFilterSet,
|
||||
followsSet: AllFollowsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
sinceBoundaryNew: Long?,
|
||||
sinceBoundaryReply: Long?,
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.nip65Follows
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.experimental.ephemChat.chat.EphemeralChatEvent
|
||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
||||
@@ -106,7 +106,7 @@ fun filterReplyHomePostsByAuthors(
|
||||
}
|
||||
|
||||
fun filterHomePostsByAuthors(
|
||||
authorSet: AuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: AuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
sinceBoundaryNew: Long?,
|
||||
sinceBoundaryReply: Long?,
|
||||
@@ -133,7 +133,7 @@ fun filterHomePostsByAuthors(
|
||||
}
|
||||
|
||||
fun filterHomePostsByAuthors(
|
||||
authorSet: MutedAuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: MutedAuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
sinceBoundaryNew: Long?,
|
||||
sinceBoundaryReply: Long?,
|
||||
|
||||
+6
-6
@@ -21,14 +21,14 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.nip65Follows
|
||||
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.LocationTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relayClient.eoseManagers.PerUserAndFollowListEoseManager
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.HomeQueryState
|
||||
@@ -60,12 +60,12 @@ class HomeOutboxEventsEoseManager(
|
||||
val repliesSince = key.feedState.homeReplies.lastNoteCreatedAtIfFilled()
|
||||
return when (feedSettings) {
|
||||
is AllCommunitiesTopNavPerRelayFilterSet -> filterHomePostsByAllCommunities(feedSettings, since, newThreadSince)
|
||||
is AllFollowsByOutboxTopNavPerRelayFilterSet -> filterHomePostsByAllFollows(feedSettings, since, newThreadSince, repliesSince)
|
||||
is AuthorsByOutboxTopNavPerRelayFilterSet -> filterHomePostsByAuthors(feedSettings, since, newThreadSince, repliesSince)
|
||||
is AllFollowsTopNavPerRelayFilterSet -> filterHomePostsByAllFollows(feedSettings, since, newThreadSince, repliesSince)
|
||||
is AuthorsTopNavPerRelayFilterSet -> filterHomePostsByAuthors(feedSettings, since, newThreadSince, repliesSince)
|
||||
is GlobalTopNavPerRelayFilterSet -> filterHomePostsByGlobal(feedSettings, since, newThreadSince, repliesSince)
|
||||
is HashtagTopNavPerRelayFilterSet -> filterHomePostsByHashtags(feedSettings, since, newThreadSince)
|
||||
is LocationTopNavPerRelayFilterSet -> filterHomePostsByGeohashes(feedSettings, since, newThreadSince)
|
||||
is MutedAuthorsByOutboxTopNavPerRelayFilterSet -> filterHomePostsByAuthors(feedSettings, since, newThreadSince, repliesSince)
|
||||
is MutedAuthorsTopNavPerRelayFilterSet -> filterHomePostsByAuthors(feedSettings, since, newThreadSince, repliesSince)
|
||||
is SingleCommunityTopNavPerRelayFilterSet -> filterHomePostsByCommunity(feedSettings, since, newThreadSince)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
+19
@@ -64,6 +64,8 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.nip37.renderPrivateO
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.nip65.Nip65RelayListViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.nip65.renderNip65HomeItems
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.nip65.renderNip65NotifItems
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.proxy.ProxyRelayListViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.proxy.renderProxyItems
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.search.SearchRelayListViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.search.renderSearchItems
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.trusted.TrustedRelayListViewModel
|
||||
@@ -90,6 +92,7 @@ fun AllRelayListScreen(
|
||||
val connectedViewModel: ConnectedRelayListViewModel = viewModel()
|
||||
val broadcastViewModel: BroadcastRelayListViewModel = viewModel()
|
||||
val indexerViewModel: IndexerRelayListViewModel = viewModel()
|
||||
val proxyViewModel: ProxyRelayListViewModel = viewModel()
|
||||
|
||||
dmViewModel.init(accountViewModel)
|
||||
nip65ViewModel.init(accountViewModel)
|
||||
@@ -101,6 +104,7 @@ fun AllRelayListScreen(
|
||||
trustedViewModel.init(accountViewModel)
|
||||
broadcastViewModel.init(accountViewModel)
|
||||
indexerViewModel.init(accountViewModel)
|
||||
proxyViewModel.init(accountViewModel)
|
||||
|
||||
LaunchedEffect(accountViewModel) {
|
||||
dmViewModel.load()
|
||||
@@ -113,6 +117,7 @@ fun AllRelayListScreen(
|
||||
trustedViewModel.load()
|
||||
broadcastViewModel.load()
|
||||
indexerViewModel.load()
|
||||
proxyViewModel.load()
|
||||
}
|
||||
|
||||
MappedAllRelayListView(
|
||||
@@ -126,6 +131,7 @@ fun AllRelayListScreen(
|
||||
trustedViewModel,
|
||||
broadcastViewModel,
|
||||
indexerViewModel,
|
||||
proxyViewModel,
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
@@ -144,6 +150,7 @@ fun MappedAllRelayListView(
|
||||
trustedViewModel: TrustedRelayListViewModel,
|
||||
broadcastViewModel: BroadcastRelayListViewModel,
|
||||
indexerViewModel: IndexerRelayListViewModel,
|
||||
proxyViewModel: ProxyRelayListViewModel,
|
||||
accountViewModel: AccountViewModel,
|
||||
newNav: INav,
|
||||
) {
|
||||
@@ -158,6 +165,7 @@ fun MappedAllRelayListView(
|
||||
val connectedRelays by connectedViewModel.relays.collectAsStateWithLifecycle()
|
||||
val broadcastRelays by broadcastViewModel.relays.collectAsStateWithLifecycle()
|
||||
val indexerRelays by indexerViewModel.relays.collectAsStateWithLifecycle()
|
||||
val proxyRelays by proxyViewModel.relays.collectAsStateWithLifecycle()
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
@@ -173,6 +181,7 @@ fun MappedAllRelayListView(
|
||||
blockedViewModel.clear()
|
||||
broadcastViewModel.clear()
|
||||
indexerViewModel.clear()
|
||||
proxyViewModel.clear()
|
||||
newNav.popBack()
|
||||
},
|
||||
onPost = {
|
||||
@@ -185,6 +194,7 @@ fun MappedAllRelayListView(
|
||||
blockedViewModel.create()
|
||||
broadcastViewModel.create()
|
||||
indexerViewModel.create()
|
||||
proxyViewModel.create()
|
||||
newNav.popBack()
|
||||
},
|
||||
)
|
||||
@@ -242,6 +252,15 @@ fun MappedAllRelayListView(
|
||||
}
|
||||
renderPrivateOutboxItems(privateOutboxFeedState, privateOutboxViewModel, accountViewModel, newNav)
|
||||
|
||||
item {
|
||||
SettingsCategory(
|
||||
stringRes(R.string.proxy_section),
|
||||
stringRes(R.string.proxy_section_explainer),
|
||||
SettingsCategorySpacingModifier,
|
||||
)
|
||||
}
|
||||
renderProxyItems(proxyRelays, proxyViewModel, accountViewModel, newNav)
|
||||
|
||||
item {
|
||||
SettingsCategory(
|
||||
stringRes(R.string.broadcast_section),
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.proxy
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.rememberExtendedNav
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.common.BasicRelaySetupInfo
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.common.BasicRelaySetupInfoDialog
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.common.RelayUrlEditField
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.common.relaySetupInfoBuilder
|
||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||
|
||||
@Composable
|
||||
fun ProxyRelayList(
|
||||
postViewModel: ProxyRelayListViewModel,
|
||||
accountViewModel: AccountViewModel,
|
||||
onClose: () -> Unit,
|
||||
nav: INav,
|
||||
) {
|
||||
val feedState by postViewModel.relays.collectAsStateWithLifecycle()
|
||||
|
||||
val newNav = rememberExtendedNav(nav, onClose)
|
||||
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
LazyColumn(
|
||||
contentPadding = FeedPadding,
|
||||
) {
|
||||
renderProxyItems(feedState, postViewModel, accountViewModel, newNav)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun LazyListScope.renderProxyItems(
|
||||
feedState: List<BasicRelaySetupInfo>,
|
||||
postViewModel: ProxyRelayListViewModel,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
itemsIndexed(feedState, key = { _, item -> "Proxy" + item.relay }) { index, item ->
|
||||
BasicRelaySetupInfoDialog(
|
||||
item,
|
||||
onDelete = { postViewModel.deleteRelay(item) },
|
||||
accountViewModel = accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = StdVertSpacer)
|
||||
RelayUrlEditField { postViewModel.addRelay(relaySetupInfoBuilder(it)) }
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.proxy
|
||||
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.common.BasicRelaySetupInfoModel
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
|
||||
class ProxyRelayListViewModel : BasicRelaySetupInfoModel() {
|
||||
override fun getRelayList(): List<NormalizedRelayUrl>? =
|
||||
account.proxyRelayList.flow.value
|
||||
.toList()
|
||||
|
||||
override suspend fun saveRelayList(urlList: List<NormalizedRelayUrl>) {
|
||||
account.saveProxyRelayList(urlList)
|
||||
}
|
||||
}
|
||||
+4
@@ -125,6 +125,7 @@ import com.vitorpamplona.amethyst.ui.note.types.DisplayFollowList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayIndexerRelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayNIP65RelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayProxyRelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayRelaySet
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplaySearchRelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayTrustedRelayList
|
||||
@@ -212,6 +213,7 @@ import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BroadcastRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.IndexerRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relaySets.RelaySetEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent
|
||||
@@ -605,6 +607,8 @@ private fun FullBleedNoteCompose(
|
||||
DisplaySearchRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
} else if (noteEvent is BlockedRelayListEvent) {
|
||||
DisplayBlockedRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
} else if (noteEvent is ProxyRelayListEvent) {
|
||||
DisplayProxyRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
} else if (noteEvent is TrustedRelayListEvent) {
|
||||
DisplayTrustedRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
} else if (noteEvent is IndexerRelayListEvent) {
|
||||
|
||||
+6
-6
@@ -21,14 +21,14 @@
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.video.datasource.subassemblies
|
||||
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.LocationTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relayClient.eoseManagers.PerUserAndFollowListEoseManager
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.video.datasource.VideoQueryState
|
||||
@@ -61,12 +61,12 @@ class VideoOutboxEventsFilterSubAssembler(
|
||||
val defaultSince = key.feedState.videoFeed.lastNoteCreatedAtWhenFullyLoaded.value
|
||||
return when (feedSettings) {
|
||||
is AllCommunitiesTopNavPerRelayFilterSet -> filterPictureAndVideoByAllCommunities(feedSettings, since, defaultSince)
|
||||
is AllFollowsByOutboxTopNavPerRelayFilterSet -> filterPictureAndVideoByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsByOutboxTopNavPerRelayFilterSet -> filterPictureAndVideoByAuthors(feedSettings, since, defaultSince)
|
||||
is AllFollowsTopNavPerRelayFilterSet -> filterPictureAndVideoByFollows(feedSettings, since, defaultSince)
|
||||
is AuthorsTopNavPerRelayFilterSet -> filterPictureAndVideoByAuthors(feedSettings, since, defaultSince)
|
||||
is GlobalTopNavPerRelayFilterSet -> filterPictureAndVideoGlobal(feedSettings, since, defaultSince)
|
||||
is HashtagTopNavPerRelayFilterSet -> filterPictureAndVideoByHashtag(feedSettings, since, defaultSince)
|
||||
is LocationTopNavPerRelayFilterSet -> filterPictureAndVideoByGeohash(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsByOutboxTopNavPerRelayFilterSet -> filterPictureAndVideoByAuthors(feedSettings, since, defaultSince)
|
||||
is MutedAuthorsTopNavPerRelayFilterSet -> filterPictureAndVideoByAuthors(feedSettings, since, defaultSince)
|
||||
is SingleCommunityTopNavPerRelayFilterSet -> filterPictureAndVideoByCommunity(feedSettings, since, defaultSince)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.video.datasource.subassemblies.nip65Follows
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.video.datasource.LegacyMimeTypeMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.video.datasource.PictureAndVideoKinds
|
||||
@@ -64,7 +64,7 @@ fun filterPictureAndVideoAuthors(
|
||||
}
|
||||
|
||||
fun filterPictureAndVideoByAuthors(
|
||||
authorSet: AuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: AuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
@@ -85,7 +85,7 @@ fun filterPictureAndVideoByAuthors(
|
||||
}
|
||||
|
||||
fun filterPictureAndVideoByAuthors(
|
||||
authorSet: MutedAuthorsByOutboxTopNavPerRelayFilterSet,
|
||||
authorSet: MutedAuthorsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.video.datasource.subassemblies.nip65Follows
|
||||
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsByOutboxTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet
|
||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.video.datasource.subassemblies.nip01Core.filterPictureAndVideoGeohash
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.video.datasource.subassemblies.nip01Core.filterPictureAndVideoHashtag
|
||||
@@ -28,7 +28,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.video.datasource.subassembl
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
|
||||
fun filterPictureAndVideoByFollows(
|
||||
followsSet: AllFollowsByOutboxTopNavPerRelayFilterSet,
|
||||
followsSet: AllFollowsTopNavPerRelayFilterSet,
|
||||
since: SincePerRelayMap?,
|
||||
defaultSince: Long? = null,
|
||||
): List<RelayBasedFilter> {
|
||||
|
||||
@@ -494,6 +494,7 @@
|
||||
|
||||
<string name="follow_list_selection">Follow List</string>
|
||||
<string name="follow_list_kind3follows">All Follows</string>
|
||||
<string name="follow_list_kind3follows_proxy">Follows via Proxy</string>
|
||||
<string name="follow_list_aroundme">Around Me</string>
|
||||
<string name="follow_list_global">Global</string>
|
||||
<string name="follow_list_mute_list">Mute List</string>
|
||||
@@ -1092,6 +1093,10 @@
|
||||
<string name="trusted_section">Trusted Relays</string>
|
||||
<string name="trusted_section_explainer">Relays you trust to not need a Tor connection for</string>
|
||||
|
||||
<string name="proxy_relays_title">Proxy Relays</string>
|
||||
<string name="proxy_section">Proxy Relays</string>
|
||||
<string name="proxy_section_explainer">Aggregator relays the app must use to download your feeds from, like filter.nostr.wine. This replaces the outbox model and will make the app connect to only the relays in your lists.</string>
|
||||
|
||||
<string name="broadcast_relays_title">Broadcast Relays</string>
|
||||
<string name="broadcast_section">Broadcast Relays</string>
|
||||
<string name="broadcast_section_explainer">Relays that specialize in pushing your notes to all of the other relays, like sendit.nosflare.com. Amethyst will add this relay to all new events made by you</string>
|
||||
|
||||
@@ -84,6 +84,7 @@ import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BroadcastRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.IndexerRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relaySets.RelaySetEvent
|
||||
import com.vitorpamplona.quartz.nip52Calendar.CalendarDateSlotEvent
|
||||
@@ -262,6 +263,7 @@ class EventFactory {
|
||||
PollNoteEvent.KIND -> PollNoteEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
PrivateDmEvent.KIND -> PrivateDmEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
PrivateOutboxRelayListEvent.KIND -> PrivateOutboxRelayListEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
ProxyRelayListEvent.KIND -> ProxyRelayListEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
ReactionEvent.KIND -> ReactionEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
RelationshipStatusEvent.KIND -> RelationshipStatusEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
RelayAuthEvent.KIND -> RelayAuthEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ class BlockedRelayListEvent(
|
||||
|
||||
companion object {
|
||||
const val KIND = 10006
|
||||
val ALT = "Blocked relays from this author"
|
||||
const val ALT = "Blocked relays from this author"
|
||||
val ALT_TAG = arrayOf(AltTag.Companion.assemble(ALT))
|
||||
|
||||
fun createAddress(pubKey: HexKey): Address = Address(KIND, pubKey, "")
|
||||
|
||||
+1
-3
@@ -59,7 +59,7 @@ class BroadcastRelayListEvent(
|
||||
|
||||
companion object {
|
||||
const val KIND = 10088
|
||||
const val ALT = "Broadcasting relays from this author"
|
||||
const val ALT = "Broadcast relays from this author"
|
||||
val TAGS = arrayOf(AltTag.assemble(ALT))
|
||||
|
||||
fun createAddress(pubKey: HexKey): Address = Address(KIND, pubKey, "")
|
||||
@@ -75,9 +75,7 @@ class BroadcastRelayListEvent(
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
): BroadcastRelayListEvent {
|
||||
val newRelayList = relays.map { RelayTag.assemble(it) }
|
||||
println("AABBCC 1 ${earlierVersion.content}")
|
||||
val privateTags = earlierVersion.privateTags(signer) ?: throw SignerExceptions.UnauthorizedDecryptionException()
|
||||
println("AABBCC 2 ${privateTags.size}")
|
||||
val publicTags = earlierVersion.tags.remove(RelayTag::match)
|
||||
val newPrivateTags = privateTags.remove(RelayTag::notMatch).plus(newRelayList)
|
||||
|
||||
|
||||
+2
-2
@@ -58,8 +58,8 @@ class IndexerRelayListEvent(
|
||||
suspend fun decryptRelays(signer: NostrSigner): List<NormalizedRelayUrl> = publicRelays() + (decryptPrivateRelays(signer) ?: emptyList())
|
||||
|
||||
companion object {
|
||||
const val KIND = 10087
|
||||
const val ALT = "Broadcasting relays from this author"
|
||||
const val KIND = 10086
|
||||
const val ALT = "Indexer relays from this author"
|
||||
val TAGS = arrayOf(AltTag.assemble(ALT))
|
||||
|
||||
fun createAddress(pubKey: HexKey): Address = Address(KIND, pubKey, "")
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip51Lists.relayLists
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerSync
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.SignerExceptions
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
|
||||
import com.vitorpamplona.quartz.nip31Alts.AltTag
|
||||
import com.vitorpamplona.quartz.nip31Alts.alt
|
||||
import com.vitorpamplona.quartz.nip51Lists.PrivateTagArrayEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.encryption.PrivateTagsInContent
|
||||
import com.vitorpamplona.quartz.nip51Lists.encryption.signNip51List
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.RelayTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.proxyRelays
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.tags.relays
|
||||
import com.vitorpamplona.quartz.nip51Lists.remove
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import kotlin.collections.plus
|
||||
|
||||
@Immutable
|
||||
class ProxyRelayListEvent(
|
||||
id: HexKey,
|
||||
pubKey: HexKey,
|
||||
createdAt: Long,
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : PrivateTagArrayEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||
fun publicRelays() = tags.relays()
|
||||
|
||||
suspend fun decryptPrivateRelays(signer: NostrSigner) = privateTags(signer)?.relays()
|
||||
|
||||
suspend fun decryptRelays(signer: NostrSigner): List<NormalizedRelayUrl> = publicRelays() + (decryptPrivateRelays(signer) ?: emptyList())
|
||||
|
||||
companion object {
|
||||
const val KIND = 10087
|
||||
const val ALT = "Proxy relays from this author"
|
||||
val TAGS = arrayOf(AltTag.assemble(ALT))
|
||||
|
||||
fun createAddress(pubKey: HexKey): Address = Address(KIND, pubKey, "")
|
||||
|
||||
fun createAddressATag(pubKey: HexKey): ATag = ATag(KIND, pubKey, "", null)
|
||||
|
||||
fun createAddressTag(pubKey: HexKey): String = Address.Companion.assemble(KIND, pubKey, "")
|
||||
|
||||
suspend fun updateRelayList(
|
||||
earlierVersion: ProxyRelayListEvent,
|
||||
relays: List<NormalizedRelayUrl>,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
): ProxyRelayListEvent {
|
||||
val newRelayList = relays.map { RelayTag.assemble(it) }
|
||||
val privateTags = earlierVersion.privateTags(signer) ?: throw SignerExceptions.UnauthorizedDecryptionException()
|
||||
|
||||
val publicTags = earlierVersion.tags.remove(RelayTag::match)
|
||||
val newPrivateTags = privateTags.remove(RelayTag::notMatch).plus(newRelayList)
|
||||
|
||||
return signer.signNip51List(createdAt, KIND, publicTags, newPrivateTags)
|
||||
}
|
||||
|
||||
suspend fun create(
|
||||
relays: List<NormalizedRelayUrl>,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
): ProxyRelayListEvent {
|
||||
val privateTagArray = relays.map { RelayTag.assemble(it) }.toTypedArray()
|
||||
return signer.signNip51List(createdAt, KIND, TAGS, privateTagArray)
|
||||
}
|
||||
|
||||
suspend fun create(
|
||||
relays: List<NormalizedRelayUrl>,
|
||||
signer: NostrSignerSync,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
): ProxyRelayListEvent {
|
||||
val privateTagArray = relays.map { RelayTag.assemble(it) }.toTypedArray()
|
||||
return signer.signNip51List(createdAt, KIND, TAGS, privateTagArray)
|
||||
}
|
||||
|
||||
suspend fun build(
|
||||
publicRelays: List<NormalizedRelayUrl> = emptyList(),
|
||||
privateRelays: List<NormalizedRelayUrl> = emptyList(),
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
initializer: TagArrayBuilder<ProxyRelayListEvent>.() -> Unit = {},
|
||||
) = eventTemplate<ProxyRelayListEvent>(
|
||||
kind = KIND,
|
||||
description = PrivateTagsInContent.encryptNip44(privateRelays.map { RelayTag.assemble(it) }.toTypedArray(), signer),
|
||||
createdAt = createdAt,
|
||||
) {
|
||||
alt(ALT)
|
||||
proxyRelays(publicRelays)
|
||||
|
||||
initializer()
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -28,6 +28,7 @@ import com.vitorpamplona.quartz.nip51Lists.PrivateTagArrayEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.BroadcastRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.IndexerRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.ProxyRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relaySets.RelaySetEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.NameTag
|
||||
@@ -45,6 +46,8 @@ fun TagArrayBuilder<BroadcastRelayListEvent>.broadcastRelays(relays: List<Normal
|
||||
|
||||
fun TagArrayBuilder<IndexerRelayListEvent>.indexerRelays(relays: List<NormalizedRelayUrl>) = addAll(relays.map { RelayTag.assemble(it) })
|
||||
|
||||
fun TagArrayBuilder<ProxyRelayListEvent>.proxyRelays(relays: List<NormalizedRelayUrl>) = addAll(relays.map { RelayTag.assemble(it) })
|
||||
|
||||
fun TagArrayBuilder<PrivateOutboxRelayListEvent>.privateRelays(relays: List<NormalizedRelayUrl>) = addAll(relays.map { RelayTag.assemble(it) })
|
||||
|
||||
fun TagArrayBuilder<RelaySetEvent>.relaySet(relays: List<NormalizedRelayUrl>) = addAll(relays.map { RelayTag.assemble(it) })
|
||||
|
||||
Reference in New Issue
Block a user