Merge branch 'vitorpamplona:main' into labeled-bookmarks

This commit is contained in:
KotlinGeekDev
2025-11-05 20:25:46 +00:00
committed by GitHub
11 changed files with 248 additions and 185 deletions
@@ -286,8 +286,8 @@ class Account(
val peopleListDecryptionCache = PeopleListDecryptionCache(signer)
val blockPeopleList = BlockPeopleListState(signer, cache, peopleListDecryptionCache, scope)
val peopleListsState = PeopleListsState(signer, cache, peopleListDecryptionCache, scope)
val followListsState = FollowListsState(signer, cache, scope)
val peopleLists = PeopleListsState(signer, cache, peopleListDecryptionCache, scope)
val followLists = FollowListsState(signer, cache, scope)
val hiddenUsers = HiddenUsersState(muteList.flow, blockPeopleList.flow, scope, settings)
@@ -325,7 +325,7 @@ class Account(
val followsPerRelay = FollowsPerOutboxRelay(kind3FollowList, blockedRelayList, proxyRelayList, cache, scope).flow
// Merges all follow lists to create a single All Follows feed.
val allFollows = MergedFollowListsState(kind3FollowList, peopleListsState, hashtagList, geohashList, communityList, scope)
val allFollows = MergedFollowListsState(kind3FollowList, peopleLists, followLists, hashtagList, geohashList, communityList, scope)
val privateDMDecryptionCache = PrivateDMCache(signer)
val privateZapsDecryptionCache = PrivateZapCache(signer)
@@ -1780,8 +1780,8 @@ class Account(
logTime("Account ${userProfile().toBestDisplayName()} newEventBundle Update with ${newNotes.size} new notes") {
upgradeAttestations()
newNotesPreProcessor.runNew(newNotes)
peopleListsState.newNotes(newNotes)
followListsState.newNotes(newNotes)
peopleLists.newNotes(newNotes)
followLists.newNotes(newNotes)
}
}
}
@@ -1790,8 +1790,8 @@ class Account(
cache.live.deletedEventBundles.collect { deletedNotes ->
logTime("Account ${userProfile().toBestDisplayName()} deletedEventBundle Update with ${deletedNotes.size} new notes") {
newNotesPreProcessor.runDeleted(deletedNotes)
peopleListsState.deletedNotes(deletedNotes)
followListsState.deletedNotes(deletedNotes)
peopleLists.deletedNotes(deletedNotes)
followLists.deletedNotes(deletedNotes)
}
}
}
@@ -94,10 +94,20 @@ class PeopleListsState(
suspend fun List<PeopleListEvent>.mapToUserIdSet() = this.map { it.userIdSet() }.flattenToSet()
val allPeopleListProfiles: StateFlow<Set<HexKey>> =
suspend fun List<PeopleListEvent>.mapGoodUsersToIdSet() =
this
.mapNotNull {
if (it.dTag() != PeopleListEvent.BLOCK_LIST_D_TAG) {
it.userIdSet()
} else {
null
}
}.flattenToSet()
val allGoodPeopleListProfiles: StateFlow<Set<HexKey>> =
latestLists
.map { it.mapToUserIdSet() }
.onStart { emit(latestLists.value.mapToUserIdSet()) }
.map { it.mapGoodUsersToIdSet() }
.onStart { emit(latestLists.value.mapGoodUsersToIdSet()) }
.flowOn(Dispatchers.IO)
.stateIn(scope, SharingStarted.Eagerly, emptySet())
@@ -131,8 +141,6 @@ class PeopleListsState(
)
}
fun isUserInFollowSets(user: User): Boolean = allPeopleListProfiles.value.contains(user.pubkeyHex)
fun DeletionEvent.hasDeletedAnyPeopleList() = deleteAddressesWithKind(PeopleListEvent.KIND) || deletesAnyEventIn(peopleListsEventIds.value)
fun hasItemInNoteList(notes: Set<Note>): Boolean =
@@ -24,8 +24,10 @@ import androidx.compose.runtime.Immutable
import com.vitorpamplona.amethyst.model.nip02FollowLists.Kind3FollowListState
import com.vitorpamplona.amethyst.model.nip51Lists.geohashLists.GeohashListState
import com.vitorpamplona.amethyst.model.nip51Lists.hashtagLists.HashtagListState
import com.vitorpamplona.amethyst.model.nip51Lists.peopleList.FollowListsState
import com.vitorpamplona.amethyst.model.nip51Lists.peopleList.PeopleListsState
import com.vitorpamplona.amethyst.model.nip72Communities.CommunityListState
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip72ModCommunities.follow.tags.CommunityTag
import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId
import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId
@@ -41,7 +43,8 @@ import kotlinx.coroutines.flow.stateIn
class MergedFollowListsState(
val kind3List: Kind3FollowListState,
val followSetList: PeopleListsState,
val peopleList: PeopleListsState,
val followList: FollowListsState,
val hashtagList: HashtagListState,
val geohashList: GeohashListState,
val communityList: CommunityListState,
@@ -63,13 +66,14 @@ class MergedFollowListsState(
fun mergeLists(
kind3: Kind3FollowListState.Kind3Follows,
followSetProfiles: Set<String>,
peopleListProfiles: Set<String>,
followListProfiles: Set<String>,
hashtags: Set<String>,
geohashes: Set<String>,
community: Set<CommunityTag>,
): AllFollows =
AllFollows(
authors = kind3.authors + followSetProfiles,
authors = kind3.authors + peopleListProfiles + followListProfiles,
hashtags = hashtags,
geotags = geohashes,
communities = community.mapTo(mutableSetOf()) { it.address.toValue() },
@@ -77,17 +81,29 @@ class MergedFollowListsState(
val flow: StateFlow<AllFollows> =
combine(
kind3List.flow,
followSetList.allPeopleListProfiles,
hashtagList.flow,
geohashList.flow,
communityList.flow,
::mergeLists,
).onStart {
listOf(
kind3List.flow,
peopleList.allGoodPeopleListProfiles,
followList.allPeopleListProfiles,
hashtagList.flow,
geohashList.flow,
communityList.flow,
),
) { args ->
mergeLists(
args[0] as Kind3FollowListState.Kind3Follows,
args[1] as Set<HexKey>,
args[2] as Set<HexKey>,
args[3] as Set<String>,
args[4] as Set<String>,
args[5] as Set<CommunityTag>,
)
}.onStart {
emit(
mergeLists(
kind3List.flow.value,
followSetList.allPeopleListProfiles.value,
peopleList.allGoodPeopleListProfiles.value,
followList.allPeopleListProfiles.value,
hashtagList.flow.value,
geohashList.flow.value,
communityList.flow.value,
@@ -100,7 +116,8 @@ class MergedFollowListsState(
SharingStarted.Eagerly,
mergeLists(
kind3List.flow.value,
followSetList.allPeopleListProfiles.value,
peopleList.allGoodPeopleListProfiles.value,
followList.allPeopleListProfiles.value,
hashtagList.flow.value,
geohashList.flow.value,
communityList.flow.value,
@@ -148,14 +148,14 @@ class TopNavFilterState(
val livePeopleListsFlow: Flow<List<FeedDefinition>> =
combine(
account.peopleListsState.peopleListNotes,
account.followListsState.followListNotes,
account.peopleLists.peopleListNotes,
account.followLists.followListNotes,
::mergePeopleLists,
).onStart {
emit(
mergePeopleLists(
account.peopleListsState.peopleListNotes.value,
account.followListsState.followListNotes.value,
account.peopleLists.peopleListNotes.value,
account.followLists.followListNotes.value,
),
)
}
@@ -55,7 +55,7 @@ class PeopleListViewModel : ViewModel() {
selectedDTag
.transformLatest {
emitAll(
account.peopleListsState.selectListFlow(it).flowOn(Dispatchers.IO),
account.peopleLists.selectListFlow(it).flowOn(Dispatchers.IO),
)
}.flowOn(Dispatchers.IO)
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), null)
@@ -73,23 +73,23 @@ class PeopleListViewModel : ViewModel() {
}
suspend fun deleteFollowSet() {
account.peopleListsState.deleteFollowSet(selectedDTag.value, account)
account.peopleLists.deleteFollowSet(selectedDTag.value, account)
}
fun loadNote(): AddressableNote? = account.peopleListsState.getPeopleListNote(selectedDTag.value)
fun loadNote(): AddressableNote? = account.peopleLists.getPeopleListNote(selectedDTag.value)
suspend fun removeUserFromSet(
user: User,
isPrivate: Boolean,
) {
account.peopleListsState.removeUserFromSet(user, isPrivate, selectedDTag.value, account)
account.peopleLists.removeUserFromSet(user, isPrivate, selectedDTag.value, account)
}
suspend fun addUserToSet(
user: User,
isPrivate: Boolean,
) {
account.peopleListsState.addUserToSet(user, selectedDTag.value, isPrivate, account)
account.peopleLists.addUserToSet(user, selectedDTag.value, isPrivate, account)
}
fun hasUserFlow(
@@ -40,7 +40,7 @@ import com.vitorpamplona.amethyst.model.nip51Lists.peopleList.PeopleList
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
import com.vitorpamplona.amethyst.ui.theme.Size30dp
import com.vitorpamplona.amethyst.ui.theme.Size40dp
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import kotlinx.coroutines.flow.StateFlow
@@ -83,7 +83,7 @@ fun AllPeopleListFeedView(
@Composable
fun AllPeopleListFeedEmpty(message: String = stringRes(R.string.feed_is_empty)) {
Column(
Modifier.fillMaxSize().padding(horizontal = Size30dp),
Modifier.fillMaxSize().padding(horizontal = Size40dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
@@ -42,7 +42,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.nip51Lists.peopleList.PeopleList
@@ -52,7 +51,6 @@ import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
import kotlinx.coroutines.flow.StateFlow
@Composable
@@ -61,10 +59,10 @@ fun ListOfPeopleListsScreen(
nav: INav,
) {
ListOfPeopleListsScreen(
listFlow = accountViewModel.account.peopleListsState.uiListFlow,
listFlow = accountViewModel.account.peopleLists.uiListFlow,
addItem = { title: String, description: String? ->
accountViewModel.runIOCatching {
accountViewModel.account.peopleListsState.addFollowList(
accountViewModel.account.peopleLists.addFollowList(
listName = title,
listDescription = description,
account = accountViewModel.account,
@@ -76,7 +74,7 @@ fun ListOfPeopleListsScreen(
},
renameItem = { followSet, newValue ->
accountViewModel.runIOCatching {
accountViewModel.account.peopleListsState.renameFollowList(
accountViewModel.account.peopleLists.renameFollowList(
newName = newValue,
peopleList = followSet,
account = accountViewModel.account,
@@ -85,7 +83,7 @@ fun ListOfPeopleListsScreen(
},
changeItemDescription = { followSet, newDescription ->
accountViewModel.runIOCatching {
accountViewModel.account.peopleListsState.modifyFollowSetDescription(
accountViewModel.account.peopleLists.modifyFollowSetDescription(
newDescription = newDescription,
peopleList = followSet,
account = accountViewModel.account,
@@ -94,7 +92,7 @@ fun ListOfPeopleListsScreen(
},
cloneItem = { followSet, customName, customDescription ->
accountViewModel.runIOCatching {
accountViewModel.account.peopleListsState.cloneFollowSet(
accountViewModel.account.peopleLists.cloneFollowSet(
currentPeopleList = followSet,
customCloneName = customName,
customCloneDescription = customDescription,
@@ -104,7 +102,7 @@ fun ListOfPeopleListsScreen(
},
deleteItem = { followSet ->
accountViewModel.runIOCatching {
accountViewModel.account.peopleListsState.deleteFollowSet(
accountViewModel.account.peopleLists.deleteFollowSet(
identifierTag = followSet.identifierTag,
account = accountViewModel.account,
)
@@ -131,9 +129,7 @@ fun ListOfPeopleListsScreen(
},
floatingActionButton = {
PeopleListFabsAndMenu(
onAddSet = { name: String, description: String? ->
addItem(name, description)
},
onAddSet = addItem,
)
},
) { paddingValues ->
@@ -142,8 +138,6 @@ fun ListOfPeopleListsScreen(
.padding(
top = paddingValues.calculateTopPadding(),
bottom = paddingValues.calculateBottomPadding(),
start = 10.dp,
end = 10.dp,
).fillMaxHeight(),
) {
AllPeopleListFeedView(
@@ -257,37 +251,3 @@ fun NewPeopleListCreationDialog(
},
)
}
@Preview(showSystemUi = true)
@Composable
private fun PeopleListItemPreview() {
val samplePeopleList =
PeopleList(
identifierTag = "00001-2222",
title = "Sample List Title",
description = "Sample List Description",
emptySet(),
emptySet(),
)
ThemeComparisonColumn {
PeopleListItem(
modifier = Modifier,
samplePeopleList,
onClick = {
println("follow set: ${samplePeopleList.identifierTag}")
},
onRename = {
println("Follow set new name: $it")
},
onDescriptionChange = { description ->
println("The follow set's description has been changed to $description")
},
onClone = { newName, newDesc ->
println("The follow set has been cloned, and has custom name: $newName, Desc: $newDesc")
},
onDelete = {
println(" The follow set ${samplePeopleList.title} has been deleted.")
},
)
}
}
@@ -22,18 +22,21 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.list
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.People
import androidx.compose.material.icons.outlined.Groups
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.FilterChip
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
@@ -41,7 +44,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
@@ -49,19 +51,110 @@ import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.model.nip51Lists.peopleList.PeopleList
import com.vitorpamplona.amethyst.ui.components.ClickableBox
import com.vitorpamplona.amethyst.ui.note.VerticalDotsIcon
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
import com.vitorpamplona.amethyst.ui.theme.Font10SP
import com.vitorpamplona.amethyst.ui.theme.NoSoTinyBorders
import com.vitorpamplona.amethyst.ui.theme.Size10Modifier
import com.vitorpamplona.amethyst.ui.theme.Size50ModifierOffset10
import com.vitorpamplona.amethyst.ui.theme.Size5dp
import com.vitorpamplona.amethyst.ui.theme.SpacedBy2dp
import com.vitorpamplona.amethyst.ui.theme.SpacedBy5dp
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
@Preview()
@Composable
private fun PeopleListItemPreview() {
val user1: User = LocalCache.getOrCreateUser("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c")
val user2: User = LocalCache.getOrCreateUser("ca89cb11f1c75d5b6622268ff43d2288ea8b2cb5b9aa996ff9ff704fc904b78b")
val user3: User = LocalCache.getOrCreateUser("7eb29c126b3628077e2e3d863b917a56b74293aa9d8a9abc26a40ba3f2866baf")
val samplePeopleList1 =
PeopleList(
identifierTag = "00001-2222",
title = "Sample List Title",
description = "Sample List Description",
emptySet(),
emptySet(),
)
val samplePeopleList2 =
PeopleList(
identifierTag = "00001-2222",
title = "Sample List Title",
description = "Sample List Description",
setOf(user1, user3),
emptySet(),
)
val samplePeopleList3 =
PeopleList(
identifierTag = "00001-2222",
title = "Sample List Title",
description = "Sample List Description",
emptySet(),
setOf(user1, user3),
)
val samplePeopleList4 =
PeopleList(
identifierTag = "00001-2222",
title = "Sample List Title",
description = "Sample List Description",
setOf(user3),
setOf(user1, user2, user3),
)
ThemeComparisonColumn {
Column {
PeopleListItem(
modifier = Modifier,
peopleList = samplePeopleList1,
onClick = {},
onRename = {},
onDescriptionChange = { },
onClone = { newName, newDesc -> },
onDelete = {},
)
PeopleListItem(
modifier = Modifier,
peopleList = samplePeopleList2,
onClick = {},
onRename = {},
onDescriptionChange = { },
onClone = { newName, newDesc -> },
onDelete = {},
)
PeopleListItem(
modifier = Modifier,
peopleList = samplePeopleList3,
onClick = {},
onRename = {},
onDescriptionChange = { },
onClone = { newName, newDesc -> },
onDelete = {},
)
PeopleListItem(
modifier = Modifier,
peopleList = samplePeopleList4,
onClick = {},
onRename = {},
onDescriptionChange = { },
onClone = { newName, newDesc -> },
onDelete = {},
)
}
}
}
@Composable
fun PeopleListItem(
@@ -73,112 +166,93 @@ fun PeopleListItem(
onClone: (customName: String?, customDescription: String?) -> Unit,
onDelete: () -> Unit,
) {
val context = LocalContext.current
Row(
modifier =
modifier
.clickable(onClick = onClick),
) {
Row(
modifier =
Modifier
.padding(bottom = 12.dp)
.weight(1f),
verticalAlignment = Alignment.CenterVertically,
) {
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.Center,
ListItem(
modifier = modifier.clickable(onClick = onClick),
headlineContent = {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(peopleList.title)
Column(
modifier = NoSoTinyBorders,
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.End,
) {
PeopleListOptionsButton(
peopleListName = peopleList.title,
peopleListDescription = peopleList.description,
onListRename = onRename,
onListDescriptionChange = onDescriptionChange,
onListCloneCreate = onClone,
onListDelete = onDelete,
)
}
}
},
supportingContent = {
Text(
peopleList.description ?: "",
overflow = TextOverflow.Ellipsis,
maxLines = 2,
)
},
leadingContent = {
Box(contentAlignment = Alignment.Center) {
Icon(
imageVector = Icons.Outlined.Groups,
contentDescription = stringRes(R.string.follow_set_icon_description),
modifier = Size50ModifierOffset10,
)
Row(
modifier = Modifier.align(Alignment.BottomCenter).offset(y = (-5).dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = SpacedBy5dp,
) {
Icon(
painter = painterResource(R.drawable.format_list_bulleted_type),
contentDescription = stringRes(R.string.follow_set_icon_description),
)
Text(peopleList.title, fontWeight = FontWeight.Bold)
if (peopleList.publicMembers.isEmpty() && peopleList.privateMembers.isEmpty()) {
FilterChip(
selected = true,
onClick = {},
label = {
Text(text = stringRes(R.string.follow_set_empty_label))
},
leadingIcon = {
Icon(
imageVector = Icons.Default.People,
contentDescription = null,
)
},
shape = ButtonBorder,
Text(
text = stringRes(R.string.follow_set_empty_label2),
fontSize = Font10SP,
)
}
if (peopleList.publicMembers.isNotEmpty()) {
val publicMemberSize = peopleList.publicMembers.size
FilterChip(
selected = true,
onClick = {},
label = {
Text(text = "$publicMemberSize")
},
leadingIcon = {
Icon(
painterResource(R.drawable.ic_public),
contentDescription = null,
)
},
shape = ButtonBorder,
)
Spacer(modifier = StdHorzSpacer)
}
if (peopleList.privateMembers.isNotEmpty()) {
val privateMemberSize = peopleList.privateMembers.size
FilterChip(
selected = true,
onClick = {},
label = {
Text(text = "$privateMemberSize")
},
leadingIcon = {
} else {
if (peopleList.privateMembers.isNotEmpty()) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = SpacedBy2dp,
) {
Icon(
painterResource(R.drawable.lock),
modifier = Size10Modifier,
contentDescription = null,
)
},
shape = ButtonBorder,
)
Text(
text = peopleList.privateMembers.size.toString(),
fontSize = Font10SP,
)
}
}
if (peopleList.publicMembers.isNotEmpty()) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = SpacedBy2dp,
) {
Icon(
painterResource(R.drawable.ic_public),
modifier = Size10Modifier,
contentDescription = null,
)
Text(
text = peopleList.publicMembers.size.toString(),
fontSize = Font10SP,
)
}
}
}
}
Spacer(modifier = StdVertSpacer)
Text(
peopleList.description ?: "",
fontWeight = FontWeight.Light,
overflow = TextOverflow.Ellipsis,
maxLines = 2,
)
}
}
Column(
modifier =
Modifier
.padding(start = 5.dp)
.padding(vertical = 7.dp),
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.End,
) {
PeopleListOptionsButton(
peopleListName = peopleList.title,
peopleListDescription = peopleList.description,
onListRename = onRename,
onListDescriptionChange = onDescriptionChange,
onListCloneCreate = onClone,
onListDelete = onDelete,
)
}
}
},
)
}
@Composable
@@ -150,7 +150,7 @@ private fun FollowSetManagementScreenBody(
accountViewModel: AccountViewModel,
nav: INav,
) {
val followSetsState by accountViewModel.account.peopleListsState.uiListFlow
val followSetsState by accountViewModel.account.peopleLists.uiListFlow
.collectAsStateWithLifecycle()
if (followSetsState.isEmpty()) {
@@ -168,7 +168,7 @@ private fun FollowSetManagementScreenBody(
userIsPublicMember = list.publicMembers.contains(userToAddOrRemove),
onRemoveUser = {
accountViewModel.runIOCatching {
accountViewModel.account.peopleListsState.removeUserFromSet(
accountViewModel.account.peopleLists.removeUserFromSet(
userToAddOrRemove,
isPrivate = list.privateMembers.contains(userToAddOrRemove),
list.identifierTag,
@@ -178,7 +178,7 @@ private fun FollowSetManagementScreenBody(
},
onAddUserToList = { userShouldBePrivate ->
accountViewModel.runIOCatching {
accountViewModel.account.peopleListsState.addUserToSet(
accountViewModel.account.peopleLists.addUserToSet(
userToAddOrRemove,
list.identifierTag,
userShouldBePrivate,
@@ -196,7 +196,7 @@ private fun FollowSetManagementScreenBody(
userName = userToAddOrRemove.toBestDisplayName(),
onSetCreate = { setName, memberShouldBePrivate, description ->
accountViewModel.runIOCatching {
accountViewModel.account.peopleListsState.addFollowList(
accountViewModel.account.peopleLists.addFollowList(
listName = setName,
listDescription = description,
isPrivate = memberShouldBePrivate,
@@ -30,6 +30,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
@@ -371,3 +372,5 @@ val SpacedBy5dp = Arrangement.spacedBy(Size5dp)
val SpacedBy10dp = Arrangement.spacedBy(Size10dp)
val PopupUpEffect = RoundedCornerShape(0.dp, 0.dp, 15.dp, 15.dp)
val Size50ModifierOffset10 = Modifier.size(50.dp).offset(y = (-10).dp)
+1
View File
@@ -536,6 +536,7 @@
<string name="follow_set_single_member_label">member</string>
<string name="follow_set_multiple_member_label">members</string>
<string name="follow_set_empty_label">No members</string>
<string name="follow_set_empty_label2">Empty</string>
<string name="follow_set_absence_indicator">%1$s is not in this list</string>
<string name="follow_set_man_dialog_title">Your Lists</string>
<string name="follow_set_empty_dialog_msg">No follow lists were found, or you don\'t have any follow lists. Tap below to refresh, or use the menu to create one.</string>