diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/FollowSetFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/FollowSetFeedFilter.kt index b0b3e2fec..bba8dd44d 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/FollowSetFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/FollowSetFeedFilter.kt @@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.ui.dal import android.util.Log import com.vitorpamplona.amethyst.model.Account -import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.FollowSet import kotlinx.coroutines.launch import kotlin.coroutines.cancellation.CancellationException @@ -30,12 +29,10 @@ import kotlin.coroutines.cancellation.CancellationException class FollowSetFeedFilter( val account: Account, ) : FeedFilter() { - private val followSetEventPairs: MutableMap = mutableMapOf() - override fun feedKey(): String = account.userProfile().pubkeyHex override fun feed(): List { - val userFollowSets = account.userProfile().followSets + val userFollowSets = account.userProfile().followSetNotes if (userFollowSets.isEmpty()) { account.scope.launch { try { @@ -47,14 +44,7 @@ class FollowSetFeedFilter( } } } - updateFollowSetEventPairs(userFollowSets) - return followSetEventPairs.values.toList() - } - - private fun updateFollowSetEventPairs(notes: Set) { - notes.forEach { note -> - val noteAndSetPair = note to account.mapNoteToFollowSet(note) - followSetEventPairs.putIfAbsent(noteAndSetPair.first, noteAndSetPair.second) - } + val followSets = userFollowSets.map { account.mapNoteToFollowSet(it) } + return followSets } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/lists/CustomListsScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/lists/CustomListsScreen.kt index 8d379f295..0c9b8a608 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/lists/CustomListsScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/lists/CustomListsScreen.kt @@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.lists import android.util.Log import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -42,6 +43,7 @@ import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -60,6 +62,7 @@ import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.ui.feeds.FeedEmpty import com.vitorpamplona.amethyst.ui.feeds.FeedError import com.vitorpamplona.amethyst.ui.feeds.LoadingFeed +import com.vitorpamplona.amethyst.ui.feeds.RefresheableBox import com.vitorpamplona.amethyst.ui.navigation.INav import com.vitorpamplona.amethyst.ui.navigation.TopBarWithBackButton import com.vitorpamplona.amethyst.ui.screen.NostrUserFollowSetFeedViewModel @@ -71,6 +74,9 @@ import com.vitorpamplona.amethyst.ui.theme.FeedPadding import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn +import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch @Composable fun ListsScreen( @@ -83,6 +89,7 @@ fun ListsScreen( factory = NostrUserFollowSetFeedViewModel.Factory(accountViewModel.account), ) + val currentCoroutineScope = rememberCoroutineScope() val lifeCycleOwner = LocalLifecycleOwner.current DisposableEffect(lifeCycleOwner) { @@ -109,6 +116,17 @@ fun ListsScreen( refresh = { followSetsViewModel.invalidateData() }, + openItem = { + currentCoroutineScope.launch(Dispatchers.IO) { + val note = followSetsViewModel.getFollowSetAddressable(it, accountViewModel.account) + if (note != null) { + val event = note.event as PeopleListEvent + println("Found list, with title: ${event.nameOrTitle()}") + } else { + println("No corresponding note found for this list.") + } + } + }, accountViewModel, nav, ) @@ -118,6 +136,7 @@ fun ListsScreen( fun CustomListsScreen( followSetState: FollowSetState, refresh: () -> Unit, + openItem: (identifier: String) -> Unit, accountViewModel: AccountViewModel, nav: INav, ) { @@ -130,7 +149,11 @@ fun CustomListsScreen( TopBarWithBackButton(stringRes(R.string.my_lists), nav::popBack) }, ) { - Column(Modifier.padding(it).fillMaxHeight()) { + Column( + Modifier + .padding(it) + .fillMaxHeight(), + ) { when (followSetState) { FollowSetState.Loading -> LoadingFeed() @@ -139,6 +162,7 @@ fun CustomListsScreen( FollowListLoaded( loadedFeedState = followSetFeed, onRefresh = refresh, + onItemClick = openItem, ) } @@ -164,16 +188,26 @@ fun FollowListLoaded( modifier: Modifier = Modifier, loadedFeedState: List, onRefresh: () -> Unit = {}, + onItemClick: (String) -> Unit = {}, ) { Log.d("FollowSetComposable", "FollowListLoaded: Follow Set size: ${loadedFeedState.size}") val listState = rememberLazyListState() - LazyColumn( - state = listState, - contentPadding = FeedPadding, + RefresheableBox( + onRefresh = onRefresh, ) { - itemsIndexed(loadedFeedState, key = { _, item -> item.title }) { index, set -> - CustomListItem(followSet = set) + LazyColumn( + state = listState, + contentPadding = FeedPadding, + ) { + itemsIndexed(loadedFeedState, key = { _, item -> item.identifierTag }) { index, set -> + CustomListItem( + followSet = set, + onFollowSetClick = { + onItemClick(set.identifierTag) + }, + ) + } } } } @@ -182,10 +216,12 @@ fun FollowListLoaded( fun CustomListItem( modifier: Modifier = Modifier, followSet: FollowSet, + onFollowSetClick: () -> Unit, ) { Row( modifier = modifier + .clickable(onClick = onFollowSetClick) .border( width = Dp.Hairline, color = Color.Gray, @@ -261,15 +297,19 @@ fun CustomListItem( private fun ListItemPreview() { val sampleFollowSet = FollowSet( - visibility = ListVisibility.Mixed, + identifierTag = "00001-2222", title = "Sample List Title", description = "Sample List Description", + visibility = ListVisibility.Mixed, emptySet(), ) ThemeComparisonColumn { CustomListItem( modifier = Modifier, sampleFollowSet, + onFollowSetClick = { + println("follow set: ${sampleFollowSet.identifierTag}") + }, ) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/lists/FollowSet.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/lists/FollowSet.kt index 253424109..ce37ba19d 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/lists/FollowSet.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/lists/FollowSet.kt @@ -26,9 +26,10 @@ import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent @Stable data class FollowSet( - val visibility: ListVisibility, + val identifierTag: String, val title: String, val description: String?, + val visibility: ListVisibility, val profileList: Set, ) : NostrList(listVisibility = visibility, content = profileList) { companion object { @@ -36,6 +37,7 @@ data class FollowSet( event: PeopleListEvent, signer: NostrSigner, ): FollowSet { + val address = event.address() val dTag = event.dTag() val listTitle = event.nameOrTitle() ?: dTag val listDescription = event.description() ?: "" @@ -44,16 +46,18 @@ data class FollowSet( event.privateTaggedUsers(signer) { userList -> privateFollows.addAll(userList) } return if (publicFollows.isEmpty() && privateFollows.isNotEmpty()) { FollowSet( - visibility = ListVisibility.Private, + identifierTag = address.toValue(), title = listTitle, description = listDescription, + visibility = ListVisibility.Private, profileList = privateFollows.toSet(), ) } else if (publicFollows.isNotEmpty() && privateFollows.isEmpty()) { FollowSet( - visibility = ListVisibility.Public, + identifierTag = address.toValue(), title = listTitle, description = listDescription, + visibility = ListVisibility.Public, profileList = publicFollows.toSet(), ) } else {