- Removes the deprecated hacks from Contact Lists
- Removes the use of kind 3 to show hashtags which fixes issues when people unfollowing the hashtag and it would just affect the InterestListEvent
This commit is contained in:
@@ -38,8 +38,8 @@ import com.vitorpamplona.amethyst.model.nip01UserMetadata.UserMetadataState
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.DeclaredFollowsPerOutboxRelay
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListOutboxOrProxyRelays
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListReusedOutboxOrProxyRelays
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListState
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowsPerOutboxRelay
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.Kind3FollowListState
|
||||
import com.vitorpamplona.amethyst.model.nip03Timestamp.OtsState
|
||||
import com.vitorpamplona.amethyst.model.nip17Dms.DmInboxRelayState
|
||||
import com.vitorpamplona.amethyst.model.nip17Dms.DmRelayListState
|
||||
@@ -266,7 +266,7 @@ class Account(
|
||||
val blockedRelayListDecryptionCache = BlockedRelayListDecryptionCache(signer)
|
||||
val blockedRelayList = BlockedRelayListState(signer, cache, blockedRelayListDecryptionCache, scope, settings)
|
||||
|
||||
val kind3FollowList = FollowListState(signer, cache, scope, settings)
|
||||
val kind3FollowList = Kind3FollowListState(signer, cache, scope, settings)
|
||||
val followSetsState = FollowSetState(signer, cache, scope)
|
||||
|
||||
val ephemeralChatListDecryptionCache = EphemeralChatListDecryptionCache(signer)
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
|
||||
class DeclaredFollowsPerOutboxRelay(
|
||||
kind3Follows: FollowListState,
|
||||
kind3Follows: Kind3FollowListState,
|
||||
val cache: LocalCache,
|
||||
scope: CoroutineScope,
|
||||
) {
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
|
||||
class FollowListOutboxOrProxyRelays(
|
||||
kind3Follows: FollowListState,
|
||||
kind3Follows: Kind3FollowListState,
|
||||
blockedRelayList: BlockedRelayListState,
|
||||
proxyRelayList: ProxyRelayListState,
|
||||
val cache: LocalCache,
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
|
||||
class FollowListReusedOutboxOrProxyRelays(
|
||||
kind3Follows: FollowListState,
|
||||
kind3Follows: Kind3FollowListState,
|
||||
blockedRelayList: BlockedRelayListState,
|
||||
proxyRelayList: ProxyRelayListState,
|
||||
val cache: LocalCache,
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
|
||||
class FollowsPerOutboxRelay(
|
||||
kind3Follows: FollowListState,
|
||||
kind3Follows: Kind3FollowListState,
|
||||
blockedRelayList: BlockedRelayListState,
|
||||
proxyRelayList: ProxyRelayListState,
|
||||
val cache: LocalCache,
|
||||
|
||||
+7
-28
@@ -25,12 +25,10 @@ import com.vitorpamplona.amethyst.model.AccountSettings
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.model.UserState
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohashes
|
||||
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||
import com.vitorpamplona.quartz.nip02FollowList.tags.ContactTag
|
||||
import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId
|
||||
import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
@@ -45,7 +43,7 @@ import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class FollowListState(
|
||||
class Kind3FollowListState(
|
||||
val signer: NostrSigner,
|
||||
val cache: LocalCache,
|
||||
val scope: CoroutineScope,
|
||||
@@ -77,8 +75,8 @@ class FollowListState(
|
||||
// Creates a long-term reference for all follows of a user
|
||||
val userList =
|
||||
flow
|
||||
.map {
|
||||
it.authors.mapNotNull {
|
||||
.map { kind3Follows ->
|
||||
kind3Follows.authors.mapNotNull {
|
||||
cache.checkGetOrCreateUser(it)
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
@@ -96,15 +94,9 @@ class FollowListState(
|
||||
*/
|
||||
@Immutable
|
||||
class Kind3Follows(
|
||||
val authors: Set<String> = emptySet(),
|
||||
val authorsPlusMe: Set<String>,
|
||||
val hashtags: Set<String> = emptySet(),
|
||||
val geotags: Set<String> = emptySet(),
|
||||
val communities: Set<String> = emptySet(),
|
||||
) {
|
||||
val geotagScopes: Set<String> = geotags.mapTo(mutableSetOf<String>()) { GeohashId.toScope(it) }
|
||||
val hashtagScopes: Set<String> = hashtags.mapTo(mutableSetOf<String>()) { HashtagId.toScope(it) }
|
||||
}
|
||||
val authors: Set<HexKey> = emptySet(),
|
||||
val authorsPlusMe: Set<HexKey>,
|
||||
)
|
||||
|
||||
fun buildKind3Follows(latestContactList: ContactListEvent?): Kind3Follows {
|
||||
// makes sure the output include only valid p tags
|
||||
@@ -113,19 +105,6 @@ class FollowListState(
|
||||
return Kind3Follows(
|
||||
authors = verifiedFollowingUsers,
|
||||
authorsPlusMe = verifiedFollowingUsers + signer.pubKey,
|
||||
hashtags =
|
||||
latestContactList
|
||||
?.unverifiedFollowTagSet()
|
||||
?.map { it.lowercase() }
|
||||
?.toSet() ?: emptySet(),
|
||||
geotags =
|
||||
latestContactList
|
||||
?.geohashes()
|
||||
?.toSet() ?: emptySet(),
|
||||
communities =
|
||||
latestContactList
|
||||
?.verifiedFollowAddressSet()
|
||||
?.toSet() ?: emptySet(),
|
||||
)
|
||||
}
|
||||
|
||||
+36
-15
@@ -20,12 +20,15 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.model.serverList
|
||||
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListState
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.Kind3FollowListState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.followSets.FollowSetState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.geohashLists.GeohashListState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.hashtagLists.HashtagListState
|
||||
import com.vitorpamplona.amethyst.model.nip72Communities.CommunityListState
|
||||
import com.vitorpamplona.quartz.nip72ModCommunities.follow.tags.CommunityTag
|
||||
import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId
|
||||
import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
@@ -37,38 +40,50 @@ import kotlinx.coroutines.flow.sample
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class MergedFollowListsState(
|
||||
val kind3List: FollowListState,
|
||||
val kind3List: Kind3FollowListState,
|
||||
val followSetList: FollowSetState,
|
||||
val hashtagList: HashtagListState,
|
||||
val geohashList: GeohashListState,
|
||||
val communityList: CommunityListState,
|
||||
val scope: CoroutineScope,
|
||||
) {
|
||||
/**
|
||||
This contains a big OR of everything the user wants to see in the a single feed.
|
||||
*/
|
||||
@Immutable
|
||||
class AllFollows(
|
||||
val authors: Set<String> = emptySet(),
|
||||
val hashtags: Set<String> = emptySet(),
|
||||
val geotags: Set<String> = emptySet(),
|
||||
val communities: Set<String> = emptySet(),
|
||||
) {
|
||||
val geotagScopes: Set<String> = geotags.mapTo(mutableSetOf<String>()) { GeohashId.toScope(it) }
|
||||
val hashtagScopes: Set<String> = hashtags.mapTo(mutableSetOf<String>()) { HashtagId.toScope(it) }
|
||||
}
|
||||
|
||||
fun mergeLists(
|
||||
kind3: FollowListState.Kind3Follows,
|
||||
kind3: Kind3FollowListState.Kind3Follows,
|
||||
followSetProfiles: Set<String>,
|
||||
hashtags: Set<String>,
|
||||
geohashes: Set<String>,
|
||||
community: Set<CommunityTag>,
|
||||
): FollowListState.Kind3Follows =
|
||||
FollowListState.Kind3Follows(
|
||||
kind3.authors + followSetProfiles,
|
||||
kind3.authorsPlusMe,
|
||||
kind3.hashtags + hashtags,
|
||||
kind3.geotags + geohashes,
|
||||
kind3.communities + community.map { it.address.toValue() },
|
||||
): AllFollows =
|
||||
AllFollows(
|
||||
authors = kind3.authors + followSetProfiles,
|
||||
hashtags = hashtags,
|
||||
geotags = geohashes,
|
||||
communities = community.mapTo(mutableSetOf()) { it.address.toValue() },
|
||||
)
|
||||
|
||||
val flow: StateFlow<FollowListState.Kind3Follows> =
|
||||
val flow: StateFlow<AllFollows> =
|
||||
combine(
|
||||
kind3List.flow,
|
||||
followSetList.profilesFlow,
|
||||
hashtagList.flow,
|
||||
geohashList.flow,
|
||||
communityList.flow,
|
||||
) { kind3, followSet, hashtag, geohash, community ->
|
||||
mergeLists(kind3, followSet, hashtag, geohash, community)
|
||||
}.onStart {
|
||||
::mergeLists,
|
||||
).onStart {
|
||||
emit(
|
||||
mergeLists(
|
||||
kind3List.flow.value,
|
||||
@@ -83,6 +98,12 @@ class MergedFollowListsState(
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.Eagerly,
|
||||
kind3List.flow.value,
|
||||
mergeLists(
|
||||
kind3List.flow.value,
|
||||
followSetList.profilesFlow.value,
|
||||
hashtagList.flow.value,
|
||||
geohashList.flow.value,
|
||||
communityList.flow.value,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@ import com.vitorpamplona.amethyst.model.ALL_USER_FOLLOWS
|
||||
import com.vitorpamplona.amethyst.model.AROUND_ME
|
||||
import com.vitorpamplona.amethyst.model.GLOBAL_FOLLOWS
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListState
|
||||
import com.vitorpamplona.amethyst.model.serverList.MergedFollowListsState
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allFollows.AllFollowsFeedFlow
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.allUserFollows.AllUserFollowsFeedFlow
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.aroundMe.AroundMeFeedFlow
|
||||
@@ -49,7 +49,7 @@ import kotlinx.coroutines.flow.transformLatest
|
||||
|
||||
class FeedTopNavFilterState(
|
||||
val feedFilterListName: MutableStateFlow<String>,
|
||||
val allFollows: StateFlow<FollowListState.Kind3Follows>,
|
||||
val allFollows: StateFlow<MergedFollowListsState.AllFollows>,
|
||||
val locationFlow: StateFlow<LocationState.LocationResult>,
|
||||
val followsRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val blockedRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
|
||||
+12
-12
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.model.topNavFeeds.allFollows
|
||||
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListState
|
||||
import com.vitorpamplona.amethyst.model.serverList.MergedFollowListsState
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedFlowsType
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -29,31 +29,31 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
||||
class AllFollowsFeedFlow(
|
||||
val allFollows: StateFlow<FollowListState.Kind3Follows?>,
|
||||
val allFollows: StateFlow<MergedFollowListsState.AllFollows?>,
|
||||
val followsRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val blockedRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val proxyRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
) : IFeedFlowsType {
|
||||
fun convert(
|
||||
kind3: FollowListState.Kind3Follows?,
|
||||
allFollows: MergedFollowListsState.AllFollows?,
|
||||
proxyRelays: Set<NormalizedRelayUrl>,
|
||||
): IFeedTopNavFilter =
|
||||
if (kind3 != null) {
|
||||
if (allFollows != null) {
|
||||
if (proxyRelays.isEmpty()) {
|
||||
AllFollowsByOutboxTopNavFilter(
|
||||
authors = kind3.authors,
|
||||
hashtags = kind3.hashtags,
|
||||
geotags = kind3.geotags,
|
||||
communities = kind3.communities,
|
||||
authors = allFollows.authors,
|
||||
hashtags = allFollows.hashtags,
|
||||
geotags = allFollows.geotags,
|
||||
communities = allFollows.communities,
|
||||
defaultRelays = followsRelays,
|
||||
blockedRelays = blockedRelays,
|
||||
)
|
||||
} else {
|
||||
AllFollowsByProxyTopNavFilter(
|
||||
authors = kind3.authors,
|
||||
hashtags = kind3.hashtags,
|
||||
geotags = kind3.geotags,
|
||||
communities = kind3.communities,
|
||||
authors = allFollows.authors,
|
||||
hashtags = allFollows.hashtags,
|
||||
geotags = allFollows.geotags,
|
||||
communities = allFollows.communities,
|
||||
proxyRelays = proxyRelays,
|
||||
)
|
||||
}
|
||||
|
||||
+6
-6
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.model.topNavFeeds.allUserFollows
|
||||
|
||||
import com.vitorpamplona.amethyst.model.nip02FollowLists.FollowListState
|
||||
import com.vitorpamplona.amethyst.model.serverList.MergedFollowListsState
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedFlowsType
|
||||
import com.vitorpamplona.amethyst.model.topNavFeeds.IFeedTopNavFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -29,25 +29,25 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
||||
class AllUserFollowsFeedFlow(
|
||||
val allFollows: StateFlow<FollowListState.Kind3Follows?>,
|
||||
val allFollows: StateFlow<MergedFollowListsState.AllFollows?>,
|
||||
val followsRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val blockedRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
val proxyRelays: StateFlow<Set<NormalizedRelayUrl>>,
|
||||
) : IFeedFlowsType {
|
||||
fun convert(
|
||||
kind3: FollowListState.Kind3Follows?,
|
||||
allFollows: MergedFollowListsState.AllFollows?,
|
||||
proxyRelays: Set<NormalizedRelayUrl>,
|
||||
): IFeedTopNavFilter =
|
||||
if (kind3 != null) {
|
||||
if (allFollows != null) {
|
||||
if (proxyRelays.isEmpty()) {
|
||||
AllUserFollowsByOutboxTopNavFilter(
|
||||
authors = kind3.authors,
|
||||
authors = allFollows.authors,
|
||||
defaultRelays = followsRelays,
|
||||
blockedRelays = blockedRelays,
|
||||
)
|
||||
} else {
|
||||
AllUserFollowsByProxyTopNavFilter(
|
||||
authors = kind3.authors,
|
||||
authors = allFollows.authors,
|
||||
proxyRelays = proxyRelays,
|
||||
)
|
||||
}
|
||||
|
||||
-17
@@ -23,14 +23,11 @@ package com.vitorpamplona.quartz.nip02FollowList
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.PubKeyHintProvider
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerSync
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser
|
||||
import com.vitorpamplona.quartz.nip02FollowList.tags.ContactTag
|
||||
import com.vitorpamplona.quartz.nip31Alts.AltTag
|
||||
@@ -45,12 +42,7 @@ class ContactListEvent(
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
AddressHintProvider,
|
||||
PubKeyHintProvider {
|
||||
override fun addressHints() = tags.mapNotNull(ATag::parseAsHint)
|
||||
|
||||
override fun linkedAddressIds() = tags.mapNotNull(ATag::parseAddressId)
|
||||
|
||||
override fun pubKeyHints() = tags.mapNotNull(ContactTag::parseAsHint)
|
||||
|
||||
override fun linkedPubKeys() = tags.mapNotNull(ContactTag::parseKey)
|
||||
@@ -60,17 +52,8 @@ class ContactListEvent(
|
||||
*/
|
||||
fun verifiedFollowKeySet(): Set<HexKey> = tags.mapNotNullTo(mutableSetOf(), ContactTag::parseValidKey)
|
||||
|
||||
/**
|
||||
* Returns a list of a-tags that are verified as correct.
|
||||
*/
|
||||
@Deprecated("Use CommunityListEvent instead.")
|
||||
fun verifiedFollowAddressSet(): Set<HexKey> = tags.mapNotNullTo(mutableSetOf(), ATag::parseValidAddress)
|
||||
|
||||
fun unverifiedFollowKeySet() = tags.mapNotNull(ContactTag::parseKey)
|
||||
|
||||
@Deprecated("Use HashtagListEvent instead.")
|
||||
fun unverifiedFollowTagSet() = tags.hashtags()
|
||||
|
||||
fun follows() = tags.mapNotNull(ContactTag::parseValid)
|
||||
|
||||
fun relays(): Map<NormalizedRelayUrl, ReadWrite>? {
|
||||
|
||||
Reference in New Issue
Block a user