Moves the ContactList cache lists to AccountViewModel, where it can be disposed more efficiently.
This commit is contained in:
@@ -225,6 +225,7 @@ class Account(
|
|||||||
@Immutable
|
@Immutable
|
||||||
class LiveFollowLists(
|
class LiveFollowLists(
|
||||||
val users: Set<String> = emptySet(),
|
val users: Set<String> = emptySet(),
|
||||||
|
val usersPlusMe: Set<String>,
|
||||||
val hashtags: Set<String> = emptySet(),
|
val hashtags: Set<String> = emptySet(),
|
||||||
val geotags: Set<String> = emptySet(),
|
val geotags: Set<String> = emptySet(),
|
||||||
val communities: Set<String> = emptySet(),
|
val communities: Set<String> = emptySet(),
|
||||||
@@ -423,17 +424,29 @@ class Account(
|
|||||||
val liveKind3FollowsFlow: Flow<LiveFollowLists> =
|
val liveKind3FollowsFlow: Flow<LiveFollowLists> =
|
||||||
userProfile().flow().follows.stateFlow.transformLatest {
|
userProfile().flow().follows.stateFlow.transformLatest {
|
||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
|
|
||||||
|
// makes sure the output include only valid p tags
|
||||||
|
val verifiedFollowingUsers = it.user.latestContactList?.verifiedFollowKeySet() ?: emptySet()
|
||||||
|
|
||||||
emit(
|
emit(
|
||||||
LiveFollowLists(
|
LiveFollowLists(
|
||||||
it.user.cachedFollowingKeySet(),
|
verifiedFollowingUsers,
|
||||||
it.user.cachedFollowingTagSet(),
|
verifiedFollowingUsers + keyPair.pubKeyHex,
|
||||||
it.user.cachedFollowingGeohashSet(),
|
it.user.latestContactList
|
||||||
it.user.cachedFollowingCommunitiesSet(),
|
?.unverifiedFollowTagSet()
|
||||||
|
?.map { it.lowercase() }
|
||||||
|
?.toSet() ?: emptySet(),
|
||||||
|
it.user.latestContactList
|
||||||
|
?.unverifiedFollowGeohashSet()
|
||||||
|
?.toSet() ?: emptySet(),
|
||||||
|
it.user.latestContactList
|
||||||
|
?.verifiedFollowAddressSet()
|
||||||
|
?.toSet() ?: emptySet(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val liveKind3Follows = liveKind3FollowsFlow.stateIn(scope, SharingStarted.Eagerly, LiveFollowLists())
|
val liveKind3Follows = liveKind3FollowsFlow.stateIn(scope, SharingStarted.Eagerly, LiveFollowLists(usersPlusMe = setOf(keyPair.pubKeyHex)))
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
private val liveHomeList: Flow<ListNameNotePair> by lazy {
|
private val liveHomeList: Flow<ListNameNotePair> by lazy {
|
||||||
@@ -465,11 +478,11 @@ class Account(
|
|||||||
} else if (peopleListFollows.listName == KIND3_FOLLOWS) {
|
} else if (peopleListFollows.listName == KIND3_FOLLOWS) {
|
||||||
emit(kind3Follows)
|
emit(kind3Follows)
|
||||||
} else if (peopleListFollows.event == null) {
|
} else if (peopleListFollows.event == null) {
|
||||||
emit(LiveFollowLists())
|
emit(LiveFollowLists(usersPlusMe = setOf(keyPair.pubKeyHex)))
|
||||||
} else {
|
} else {
|
||||||
val result = waitToDecrypt(peopleListFollows.event)
|
val result = waitToDecrypt(peopleListFollows.event)
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
emit(LiveFollowLists())
|
emit(LiveFollowLists(usersPlusMe = setOf(keyPair.pubKeyHex)))
|
||||||
} else {
|
} else {
|
||||||
emit(result)
|
emit(result)
|
||||||
}
|
}
|
||||||
@@ -481,7 +494,7 @@ class Account(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val liveHomeFollowLists: StateFlow<LiveFollowLists?> by lazy {
|
val liveHomeFollowLists: StateFlow<LiveFollowLists?> by lazy {
|
||||||
liveHomeFollowListFlow.stateIn(scope, SharingStarted.Eagerly, LiveFollowLists())
|
liveHomeFollowListFlow.stateIn(scope, SharingStarted.Eagerly, LiveFollowLists(usersPlusMe = setOf(keyPair.pubKeyHex)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun relaysFromPeopleListFlows(
|
fun relaysFromPeopleListFlows(
|
||||||
@@ -540,7 +553,7 @@ class Account(
|
|||||||
|
|
||||||
val liveNotificationFollowLists: StateFlow<LiveFollowLists?> by lazy {
|
val liveNotificationFollowLists: StateFlow<LiveFollowLists?> by lazy {
|
||||||
combinePeopleListFlows(liveKind3FollowsFlow, liveNotificationList)
|
combinePeopleListFlows(liveKind3FollowsFlow, liveNotificationList)
|
||||||
.stateIn(scope, SharingStarted.Eagerly, LiveFollowLists())
|
.stateIn(scope, SharingStarted.Eagerly, LiveFollowLists(usersPlusMe = setOf(keyPair.pubKeyHex)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@@ -552,7 +565,7 @@ class Account(
|
|||||||
|
|
||||||
val liveStoriesFollowLists: StateFlow<LiveFollowLists?> by lazy {
|
val liveStoriesFollowLists: StateFlow<LiveFollowLists?> by lazy {
|
||||||
combinePeopleListFlows(liveKind3FollowsFlow, liveStoriesList)
|
combinePeopleListFlows(liveKind3FollowsFlow, liveStoriesList)
|
||||||
.stateIn(scope, SharingStarted.Eagerly, LiveFollowLists())
|
.stateIn(scope, SharingStarted.Eagerly, LiveFollowLists(usersPlusMe = setOf(keyPair.pubKeyHex)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@@ -564,7 +577,7 @@ class Account(
|
|||||||
|
|
||||||
val liveDiscoveryFollowLists: StateFlow<LiveFollowLists?> by lazy {
|
val liveDiscoveryFollowLists: StateFlow<LiveFollowLists?> by lazy {
|
||||||
combinePeopleListFlows(liveKind3FollowsFlow, liveDiscoveryList)
|
combinePeopleListFlows(liveKind3FollowsFlow, liveDiscoveryList)
|
||||||
.stateIn(scope, SharingStarted.Eagerly, LiveFollowLists())
|
.stateIn(scope, SharingStarted.Eagerly, LiveFollowLists(usersPlusMe = setOf(keyPair.pubKeyHex)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun decryptLiveFollows(
|
private fun decryptLiveFollows(
|
||||||
@@ -572,10 +585,11 @@ class Account(
|
|||||||
onReady: (LiveFollowLists) -> Unit,
|
onReady: (LiveFollowLists) -> Unit,
|
||||||
) {
|
) {
|
||||||
listEvent.privateTags(signer) { privateTagList ->
|
listEvent.privateTags(signer) { privateTagList ->
|
||||||
|
val users = (listEvent.bookmarkedPeople() + listEvent.filterUsers(privateTagList)).toSet()
|
||||||
onReady(
|
onReady(
|
||||||
LiveFollowLists(
|
LiveFollowLists(
|
||||||
users =
|
users = users,
|
||||||
(listEvent.bookmarkedPeople() + listEvent.filterUsers(privateTagList)).toSet(),
|
usersPlusMe = users + userProfile().pubkeyHex,
|
||||||
hashtags =
|
hashtags =
|
||||||
(listEvent.hashtags() + listEvent.filterHashtags(privateTagList)).toSet(),
|
(listEvent.hashtags() + listEvent.filterHashtags(privateTagList)).toSet(),
|
||||||
geotags =
|
geotags =
|
||||||
@@ -759,6 +773,10 @@ class Account(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun countFollowersOf(pubkey: HexKey): Int = LocalCache.users.count { _, it -> it.latestContactList?.isTaggedUser(pubkey) ?: false }
|
||||||
|
|
||||||
|
suspend fun followerCount(): Int = countFollowersOf(keyPair.pubKeyHex)
|
||||||
|
|
||||||
fun sendNewUserMetadata(
|
fun sendNewUserMetadata(
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
picture: String? = null,
|
picture: String? = null,
|
||||||
@@ -2813,9 +2831,7 @@ class Account(
|
|||||||
flowHiddenUsers.value.hiddenUsers.contains(userHex) ||
|
flowHiddenUsers.value.hiddenUsers.contains(userHex) ||
|
||||||
flowHiddenUsers.value.spammers.contains(userHex)
|
flowHiddenUsers.value.spammers.contains(userHex)
|
||||||
|
|
||||||
fun followingKeySet(): Set<HexKey> = userProfile().cachedFollowingKeySet()
|
fun followingKeySet(): Set<HexKey> = liveKind3Follows.value.users
|
||||||
|
|
||||||
fun followingTagSet(): Set<HexKey> = userProfile().cachedFollowingTagSet()
|
|
||||||
|
|
||||||
fun isAcceptable(user: User): Boolean {
|
fun isAcceptable(user: User): Boolean {
|
||||||
if (userProfile().pubkeyHex == user.pubkeyHex) {
|
if (userProfile().pubkeyHex == user.pubkeyHex) {
|
||||||
@@ -2865,8 +2881,6 @@ class Account(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getRelevantReports(note: Note): Set<Note> {
|
fun getRelevantReports(note: Note): Set<Note> {
|
||||||
val followsPlusMe = userProfile().latestContactList?.verifiedFollowKeySetAndMe ?: emptySet()
|
|
||||||
|
|
||||||
val innerReports =
|
val innerReports =
|
||||||
if (note.event is RepostEvent || note.event is GenericRepostEvent) {
|
if (note.event is RepostEvent || note.event is GenericRepostEvent) {
|
||||||
note.replyTo?.map { getRelevantReports(it) }?.flatten() ?: emptyList()
|
note.replyTo?.map { getRelevantReports(it) }?.flatten() ?: emptyList()
|
||||||
@@ -2875,8 +2889,8 @@ class Account(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
note.reportsBy(followsPlusMe) +
|
note.reportsBy(liveKind3Follows.value.usersPlusMe) +
|
||||||
(note.author?.reportsBy(followsPlusMe) ?: emptyList()) +
|
(note.author?.reportsBy(liveKind3Follows.value.usersPlusMe) ?: emptyList()) +
|
||||||
innerReports
|
innerReports
|
||||||
).toSet()
|
).toSet()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -336,52 +336,24 @@ class User(
|
|||||||
|
|
||||||
fun isFollowing(user: User): Boolean = latestContactList?.isTaggedUser(user.pubkeyHex) ?: false
|
fun isFollowing(user: User): Boolean = latestContactList?.isTaggedUser(user.pubkeyHex) ?: false
|
||||||
|
|
||||||
fun isFollowingHashtag(tag: String): Boolean = latestContactList?.isTaggedHash(tag) ?: false
|
fun isFollowingHashtag(tag: String): Boolean {
|
||||||
|
return latestContactList?.unverifiedFollowTagSet()?.map { it.lowercase() }?.toSet()?.let {
|
||||||
fun isFollowingHashtagCached(tag: String): Boolean {
|
|
||||||
return latestContactList?.verifiedFollowTagSet?.let {
|
|
||||||
return tag.lowercase() in it
|
return tag.lowercase() in it
|
||||||
}
|
}
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isFollowingGeohashCached(geoTag: String): Boolean {
|
fun isFollowingGeohash(geoTag: String): Boolean {
|
||||||
return latestContactList?.verifiedFollowGeohashSet?.let {
|
return latestContactList?.unverifiedFollowAddressSet()?.toSet()?.let {
|
||||||
return geoTag.lowercase() in it
|
return geoTag.lowercase() in it
|
||||||
}
|
}
|
||||||
?: false
|
?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isFollowingCached(user: User): Boolean {
|
|
||||||
return latestContactList?.verifiedFollowKeySet?.let {
|
|
||||||
return user.pubkeyHex in it
|
|
||||||
}
|
|
||||||
?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isFollowingCached(userHex: String): Boolean {
|
|
||||||
return latestContactList?.verifiedFollowKeySet?.let {
|
|
||||||
return userHex in it
|
|
||||||
}
|
|
||||||
?: false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun transientFollowCount(): Int? = latestContactList?.unverifiedFollowKeySet()?.size
|
fun transientFollowCount(): Int? = latestContactList?.unverifiedFollowKeySet()?.size
|
||||||
|
|
||||||
suspend fun transientFollowerCount(): Int = LocalCache.users.count { _, it -> it.latestContactList?.isTaggedUser(pubkeyHex) ?: false }
|
suspend fun transientFollowerCount(): Int = LocalCache.users.count { _, it -> it.latestContactList?.isTaggedUser(pubkeyHex) ?: false }
|
||||||
|
|
||||||
fun cachedFollowingKeySet(): Set<HexKey> = latestContactList?.verifiedFollowKeySet ?: emptySet()
|
|
||||||
|
|
||||||
fun cachedFollowingTagSet(): Set<String> = latestContactList?.verifiedFollowTagSet ?: emptySet()
|
|
||||||
|
|
||||||
fun cachedFollowingGeohashSet(): Set<HexKey> = latestContactList?.verifiedFollowGeohashSet ?: emptySet()
|
|
||||||
|
|
||||||
fun cachedFollowingCommunitiesSet(): Set<HexKey> = latestContactList?.verifiedFollowCommunitySet ?: emptySet()
|
|
||||||
|
|
||||||
fun cachedFollowCount(): Int? = latestContactList?.verifiedFollowKeySet?.size
|
|
||||||
|
|
||||||
suspend fun cachedFollowerCount(): Int = LocalCache.users.count { _, it -> it.latestContactList?.isTaggedUser(pubkeyHex) ?: false }
|
|
||||||
|
|
||||||
fun hasSentMessagesTo(key: ChatroomKey?): Boolean {
|
fun hasSentMessagesTo(key: ChatroomKey?): Boolean {
|
||||||
val messagesToUser = privateChatrooms[key] ?: return false
|
val messagesToUser = privateChatrooms[key] ?: return false
|
||||||
|
|
||||||
|
|||||||
@@ -763,9 +763,11 @@ class FollowListViewModel(
|
|||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
val liveKind3FollowsFlow: Flow<List<CodeName>> =
|
val liveKind3FollowsFlow: Flow<List<CodeName>> =
|
||||||
account.userProfile().flow().follows.stateFlow.transformLatest {
|
account.liveKind3FollowsFlow.transformLatest {
|
||||||
|
checkNotInMainThread()
|
||||||
|
|
||||||
val communities =
|
val communities =
|
||||||
it.user.cachedFollowingCommunitiesSet().mapNotNull {
|
it.communities.mapNotNull {
|
||||||
LocalCache.checkGetOrCreateAddressableNote(it)?.let { communityNote ->
|
LocalCache.checkGetOrCreateAddressableNote(it)?.let { communityNote ->
|
||||||
CodeName(
|
CodeName(
|
||||||
"Community/${communityNote.idHex}",
|
"Community/${communityNote.idHex}",
|
||||||
@@ -776,12 +778,12 @@ class FollowListViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val hashtags =
|
val hashtags =
|
||||||
it.user.cachedFollowingTagSet().map {
|
it.hashtags.map {
|
||||||
CodeName("Hashtag/$it", HashtagName(it), CodeNameType.ROUTE)
|
CodeName("Hashtag/$it", HashtagName(it), CodeNameType.ROUTE)
|
||||||
}
|
}
|
||||||
|
|
||||||
val geotags =
|
val geotags =
|
||||||
it.user.cachedFollowingGeohashSet().map {
|
it.geotags.map {
|
||||||
CodeName("Geohash/$it", GeoHashName(it), CodeNameType.ROUTE)
|
CodeName("Geohash/$it", GeoHashName(it), CodeNameType.ROUTE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.vitorpamplona.amethyst.BuildConfig
|
import com.vitorpamplona.amethyst.BuildConfig
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import com.vitorpamplona.amethyst.model.Account
|
||||||
import com.vitorpamplona.amethyst.model.FeatureSetType
|
import com.vitorpamplona.amethyst.model.FeatureSetType
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.MediaServersListView
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.MediaServersListView
|
||||||
@@ -114,7 +115,6 @@ import com.vitorpamplona.ammolite.relays.RelayPoolStatus
|
|||||||
import com.vitorpamplona.quartz.encoders.ATag
|
import com.vitorpamplona.quartz.encoders.ATag
|
||||||
import com.vitorpamplona.quartz.encoders.HexKey
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
import com.vitorpamplona.quartz.events.ImmutableListOfLists
|
import com.vitorpamplona.quartz.events.ImmutableListOfLists
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -151,7 +151,7 @@ fun DrawerContent(
|
|||||||
EditStatusBoxes(accountViewModel.account.userProfile(), accountViewModel, drawerState)
|
EditStatusBoxes(accountViewModel.account.userProfile(), accountViewModel, drawerState)
|
||||||
}
|
}
|
||||||
|
|
||||||
FollowingAndFollowerCounts(accountViewModel.account.userProfile(), onClickUser)
|
FollowingAndFollowerCounts(accountViewModel.account, onClickUser)
|
||||||
|
|
||||||
HorizontalDivider(
|
HorizontalDivider(
|
||||||
thickness = DividerThickness,
|
thickness = DividerThickness,
|
||||||
@@ -380,18 +380,12 @@ fun UserStatusDeleteButton(onClick: () -> Unit) {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun FollowingAndFollowerCounts(
|
private fun FollowingAndFollowerCounts(
|
||||||
baseAccountUser: User,
|
baseAccountUser: Account,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
var followingCount by remember { mutableStateOf("--") }
|
val followingCount = baseAccountUser.liveKind3Follows.collectAsStateWithLifecycle()
|
||||||
var followerCount by remember { mutableStateOf("--") }
|
var followerCount by remember { mutableStateOf("--") }
|
||||||
|
|
||||||
WatchFollow(baseAccountUser = baseAccountUser) { newFollowing ->
|
|
||||||
if (followingCount != newFollowing) {
|
|
||||||
followingCount = newFollowing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WatchFollower(baseAccountUser = baseAccountUser) { newFollower ->
|
WatchFollower(baseAccountUser = baseAccountUser) { newFollower ->
|
||||||
if (followerCount != newFollower) {
|
if (followerCount != newFollower) {
|
||||||
followerCount = newFollower
|
followerCount = newFollower
|
||||||
@@ -402,7 +396,9 @@ private fun FollowingAndFollowerCounts(
|
|||||||
modifier = drawerSpacing.clickable(onClick = onClick),
|
modifier = drawerSpacing.clickable(onClick = onClick),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = followingCount,
|
text =
|
||||||
|
followingCount.value.users.size
|
||||||
|
.toString(),
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -419,31 +415,19 @@ private fun FollowingAndFollowerCounts(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun WatchFollow(
|
|
||||||
baseAccountUser: User,
|
|
||||||
onReady: (String) -> Unit,
|
|
||||||
) {
|
|
||||||
val accountUserFollowsState by baseAccountUser.live().follows.observeAsState()
|
|
||||||
|
|
||||||
LaunchedEffect(key1 = accountUserFollowsState) {
|
|
||||||
launch(Dispatchers.IO) {
|
|
||||||
onReady(accountUserFollowsState?.user?.cachedFollowCount()?.toString() ?: "--")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun WatchFollower(
|
fun WatchFollower(
|
||||||
baseAccountUser: User,
|
baseAccountUser: Account,
|
||||||
onReady: (String) -> Unit,
|
onReady: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
val accountUserFollowersState by baseAccountUser.live().followers.observeAsState()
|
val accountUserFollowersState by baseAccountUser
|
||||||
|
.userProfile()
|
||||||
|
.live()
|
||||||
|
.followers
|
||||||
|
.observeAsState()
|
||||||
|
|
||||||
LaunchedEffect(key1 = accountUserFollowersState) {
|
LaunchedEffect(key1 = accountUserFollowersState) {
|
||||||
launch(Dispatchers.IO) {
|
onReady(baseAccountUser.followerCount().toString() ?: "--")
|
||||||
onReady(accountUserFollowersState?.user?.cachedFollowerCount()?.toString() ?: "--")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -676,7 +676,7 @@ fun LoadModerators(
|
|||||||
|
|
||||||
val newParticipantUsers =
|
val newParticipantUsers =
|
||||||
if (followingKeySet == null) {
|
if (followingKeySet == null) {
|
||||||
val allFollows = accountViewModel.account.userProfile().cachedFollowingKeySet()
|
val allFollows = accountViewModel.account.liveKind3Follows.value.users
|
||||||
val followingParticipants =
|
val followingParticipants =
|
||||||
ParticipantListBuilder().followsThatParticipateOn(baseNote, allFollows).minus(hosts)
|
ParticipantListBuilder().followsThatParticipateOn(baseNote, allFollows).minus(hosts)
|
||||||
|
|
||||||
@@ -732,7 +732,7 @@ private fun LoadParticipants(
|
|||||||
|
|
||||||
val newParticipantUsers =
|
val newParticipantUsers =
|
||||||
if (followingKeySet == null) {
|
if (followingKeySet == null) {
|
||||||
val allFollows = accountViewModel.account.userProfile().cachedFollowingKeySet()
|
val allFollows = accountViewModel.account.liveKind3Follows.value.users
|
||||||
val followingParticipants =
|
val followingParticipants =
|
||||||
ParticipantListBuilder()
|
ParticipantListBuilder()
|
||||||
.followsThatParticipateOn(baseNote, allFollows)
|
.followsThatParticipateOn(baseNote, allFollows)
|
||||||
@@ -889,7 +889,7 @@ fun RenderChannelThumb(
|
|||||||
|
|
||||||
val newParticipantUsers =
|
val newParticipantUsers =
|
||||||
if (followingKeySet == null) {
|
if (followingKeySet == null) {
|
||||||
val allFollows = accountViewModel.account.userProfile().cachedFollowingKeySet()
|
val allFollows = accountViewModel.account.liveKind3Follows.value.users
|
||||||
val followingParticipants =
|
val followingParticipants =
|
||||||
ParticipantListBuilder().followsThatParticipateOn(baseNote, allFollows).toList()
|
ParticipantListBuilder().followsThatParticipateOn(baseNote, allFollows).toList()
|
||||||
|
|
||||||
|
|||||||
@@ -367,11 +367,10 @@ fun WatchUserFollows(
|
|||||||
remember {
|
remember {
|
||||||
accountViewModel.userFollows
|
accountViewModel.userFollows
|
||||||
.map {
|
.map {
|
||||||
it.user.isFollowingCached(userHex) ||
|
accountViewModel.isFollowing(userHex) || (userHex == accountViewModel.account.userProfile().pubkeyHex)
|
||||||
(userHex == accountViewModel.account.userProfile().pubkeyHex)
|
|
||||||
}.distinctUntilChanged()
|
}.distinctUntilChanged()
|
||||||
}.observeAsState(
|
}.observeAsState(
|
||||||
accountViewModel.account.userProfile().isFollowingCached(userHex) ||
|
accountViewModel.isFollowing(userHex) ||
|
||||||
(userHex == accountViewModel.account.userProfile().pubkeyHex),
|
(userHex == accountViewModel.account.userProfile().pubkeyHex),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+3
-4
@@ -29,12 +29,12 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
|
||||||
@@ -44,12 +44,11 @@ fun DisplayFollowingHashtagsInPost(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
val userFollowState by accountViewModel.userFollows.observeAsState()
|
val userFollowState by accountViewModel.account.liveKind3Follows.collectAsStateWithLifecycle()
|
||||||
var firstTag by remember(baseNote) { mutableStateOf<String?>(null) }
|
var firstTag by remember(baseNote) { mutableStateOf<String?>(null) }
|
||||||
|
|
||||||
LaunchedEffect(key1 = userFollowState) {
|
LaunchedEffect(key1 = userFollowState) {
|
||||||
val followingTags = userFollowState?.user?.cachedFollowingTagSet() ?: emptySet()
|
val newFirstTag = baseNote.event?.firstIsTaggedHashes(userFollowState.hashtags)
|
||||||
val newFirstTag = baseNote.event?.firstIsTaggedHashes(followingTags)
|
|
||||||
|
|
||||||
if (firstTag != newFirstTag) {
|
if (firstTag != newFirstTag) {
|
||||||
firstTag = newFirstTag
|
firstTag = newFirstTag
|
||||||
|
|||||||
+2
-2
@@ -807,10 +807,10 @@ class AccountViewModel(
|
|||||||
|
|
||||||
fun isFollowing(user: User?): Boolean {
|
fun isFollowing(user: User?): Boolean {
|
||||||
if (user == null) return false
|
if (user == null) return false
|
||||||
return account.userProfile().isFollowingCached(user)
|
return account.isFollowing(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isFollowing(user: HexKey): Boolean = account.userProfile().isFollowingCached(user)
|
fun isFollowing(user: HexKey): Boolean = account.isFollowing(user)
|
||||||
|
|
||||||
val hideDeleteRequestDialog: Boolean
|
val hideDeleteRequestDialog: Boolean
|
||||||
get() = account.hideDeleteRequestDialog
|
get() = account.hideDeleteRequestDialog
|
||||||
|
|||||||
+1
-1
@@ -188,7 +188,7 @@ fun GeoHashActionOptions(
|
|||||||
.observeAsState()
|
.observeAsState()
|
||||||
val isFollowingTag by
|
val isFollowingTag by
|
||||||
remember(userState) {
|
remember(userState) {
|
||||||
derivedStateOf { userState?.user?.isFollowingGeohashCached(tag) ?: false }
|
derivedStateOf { userState?.user?.isFollowingGeohash(tag) ?: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFollowingTag) {
|
if (isFollowingTag) {
|
||||||
|
|||||||
+1
-1
@@ -167,7 +167,7 @@ fun HashtagActionOptions(
|
|||||||
.observeAsState()
|
.observeAsState()
|
||||||
val isFollowingTag by
|
val isFollowingTag by
|
||||||
remember(userState) {
|
remember(userState) {
|
||||||
derivedStateOf { userState?.user?.isFollowingHashtagCached(tag) ?: false }
|
derivedStateOf { userState?.user?.isFollowingHashtag(tag) ?: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFollowingTag) {
|
if (isFollowingTag) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.crypto
|
package com.vitorpamplona.quartz.crypto
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||||
|
|
||||||
class KeyPair(
|
class KeyPair(
|
||||||
@@ -29,6 +30,7 @@ class KeyPair(
|
|||||||
) {
|
) {
|
||||||
val privKey: ByteArray?
|
val privKey: ByteArray?
|
||||||
val pubKey: ByteArray
|
val pubKey: ByteArray
|
||||||
|
val pubKeyHex: HexKey
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (privKey == null) {
|
if (privKey == null) {
|
||||||
@@ -52,6 +54,8 @@ class KeyPair(
|
|||||||
this.pubKey = pubKey
|
this.pubKey = pubKey
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.pubKeyHex = this.pubKey.toHexKey().intern()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String = "KeyPair(privateKey=${privKey?.toHexKey()}, publicKey=${pubKey.toHexKey()}"
|
override fun toString(): String = "KeyPair(privateKey=${privKey?.toHexKey()}, publicKey=${pubKey.toHexKey()}"
|
||||||
|
|||||||
Reference in New Issue
Block a user