Add Bookmark group metadata edit to routes/nav. Make refactors to make use of it.

This commit is contained in:
KotlinGeekDev
2025-11-27 07:19:04 +01:00
parent 0f21c72936
commit cd0a0405a9
7 changed files with 31 additions and 215 deletions
@@ -60,6 +60,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountSwitcherAndLeftDrawe
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.bookmarkgroups.display.BookmarkGroupScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.bookmarkgroups.list.ListOfBookmarkGroupsScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.bookmarkgroups.list.metadata.BookmarkGroupMetadataScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.bookmarkgroups.membershipManagement.ArticleBookmarkListManagementScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.bookmarkgroups.membershipManagement.PostBookmarkListManagementScreen
import com.vitorpamplona.amethyst.ui.screen.loggedIn.bookmarks.BookmarkListScreen
@@ -145,6 +146,7 @@ fun AppNavigation(
composableFromEnd<Route.BookmarkGroups> { ListOfBookmarkGroupsScreen(accountViewModel, nav) }
composableFromEndArgs<Route.BookmarkGroupView> { BookmarkGroupScreen(it.dTag, it.bookmarkType, accountViewModel, nav) }
composableFromBottomArgs<Route.BookmarkGroupMetadataEdit> { BookmarkGroupMetadataScreen(it.dTag, accountViewModel, nav) }
composableFromBottomArgs<Route.PostBookmarkManagement> { PostBookmarkListManagementScreen(it.postId, accountViewModel, nav) }
composableFromBottomArgs<Route.ArticleBookmarkManagement> { ArticleBookmarkListManagementScreen(Address(it.kind, it.pubKeyHex, it.dTag), accountViewModel, nav) }
@@ -56,6 +56,10 @@ sealed class Route {
val bookmarkType: BookmarkType,
) : Route()
@Serializable data class BookmarkGroupMetadataEdit(
val dTag: String? = null,
) : Route()
@Serializable data class PostBookmarkManagement(
val postId: String,
) : Route()
@@ -51,12 +51,9 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
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.unit.dp
import androidx.compose.ui.unit.sp
import com.vitorpamplona.amethyst.R
@@ -79,8 +76,8 @@ fun BookmarkGroupItem(
modifier: Modifier = Modifier,
bookmarkList: LabeledBookmarkList,
onClick: (bookmarkItemType: BookmarkType) -> Unit,
onRename: (String) -> Unit,
onDescriptionChange: (String?) -> Unit,
onRename: () -> Unit,
onDescriptionChange: () -> Unit,
onClone: (customName: String?, customDescription: String?) -> Unit,
onDelete: () -> Unit,
) {
@@ -252,8 +249,8 @@ private fun BookmarkGroupOptionsButton(
modifier: Modifier = Modifier,
bookmarkGroupName: String,
bookmarkGroupDescription: String?,
onGroupRename: (String) -> Unit,
onGroupDescriptionChange: (String?) -> Unit,
onGroupRename: () -> Unit,
onGroupDescriptionChange: () -> Unit,
onGroupCloneCreate: (optionalName: String?, optionalDec: String?) -> Unit,
onGroupDelete: () -> Unit,
) {
@@ -283,17 +280,12 @@ private fun GroupOptionsMenu(
isExpanded: Boolean,
groupName: String,
groupDescription: String?,
onGroupRename: (String) -> Unit,
onGroupDescriptionChange: (String?) -> Unit,
onGroupRename: () -> Unit,
onGroupDescriptionChange: () -> Unit,
onGroupClone: (optionalNewName: String?, optionalNewDesc: String?) -> Unit,
onDelete: () -> Unit,
onDismiss: () -> Unit,
) {
val isRenameDialogOpen = remember { mutableStateOf(false) }
val renameString = remember { mutableStateOf("") }
val isDescriptionModDialogOpen = remember { mutableStateOf(false) }
val isCopyDialogOpen = remember { mutableStateOf(false) }
val optionalCloneName = remember { mutableStateOf<String?>(null) }
val optionalCloneDescription = remember { mutableStateOf<String?>(null) }
@@ -307,7 +299,7 @@ private fun GroupOptionsMenu(
Text(text = stringRes(R.string.follow_set_rename_btn_label))
},
onClick = {
isRenameDialogOpen.value = true
onGroupRename()
onDismiss()
},
)
@@ -316,7 +308,7 @@ private fun GroupOptionsMenu(
Text(text = stringRes(R.string.follow_set_desc_modify_label))
},
onClick = {
isDescriptionModDialogOpen.value = true
onGroupDescriptionChange()
onDismiss()
},
)
@@ -339,28 +331,6 @@ private fun GroupOptionsMenu(
)
}
if (isRenameDialogOpen.value) {
GroupRenameDialog(
currentName = groupName,
newName = renameString.value,
onStringRenameChange = {
renameString.value = it
},
onDismissDialog = { isRenameDialogOpen.value = false },
onGroupRename = {
onGroupRename(renameString.value)
},
)
}
if (isDescriptionModDialogOpen.value) {
GroupModifyDescriptionDialog(
currentDescription = groupDescription,
onDismissDialog = { isDescriptionModDialogOpen.value = false },
onModifyDescription = onGroupDescriptionChange,
)
}
if (isCopyDialogOpen.value) {
GroupCloneDialog(
optionalNewName = optionalCloneName.value,
@@ -379,129 +349,6 @@ private fun GroupOptionsMenu(
}
}
@Composable
private fun GroupRenameDialog(
modifier: Modifier = Modifier,
currentName: String,
newName: String,
onStringRenameChange: (String) -> Unit,
onDismissDialog: () -> Unit,
onGroupRename: (String) -> Unit,
) {
val renameIndicator =
buildAnnotatedString {
append(stringRes(R.string.follow_set_rename_dialog_indicator_first_part) + " ")
withStyle(
SpanStyle(
fontWeight = FontWeight.Bold,
fontStyle = FontStyle.Normal,
fontSize = 15.sp,
),
) {
append("\"" + currentName + "\"")
}
append(" " + stringRes(R.string.follow_set_rename_dialog_indicator_second_part))
}
AlertDialog(
onDismissRequest = onDismissDialog,
title = {
Text(text = stringRes(R.string.follow_set_rename_btn_label))
},
text = {
Column(
verticalArrangement = Arrangement.spacedBy(Size5dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = renameIndicator,
fontSize = 15.sp,
fontWeight = FontWeight.Light,
fontStyle = FontStyle.Italic,
)
TextField(
value = newName,
onValueChange = onStringRenameChange,
)
}
},
confirmButton = {
Button(
onClick = {
onGroupRename(newName)
onDismissDialog()
},
) { Text(text = stringRes(R.string.rename)) }
},
dismissButton = {
Button(onClick = onDismissDialog) { Text(text = stringRes(R.string.cancel)) }
},
)
}
@Composable
private fun GroupModifyDescriptionDialog(
modifier: Modifier = Modifier,
currentDescription: String?,
onDismissDialog: () -> Unit,
onModifyDescription: (String?) -> Unit,
) {
val updatedDescription = remember { mutableStateOf<String?>(null) }
val modifyIndicatorLabel =
if (currentDescription == null) {
stringRes(R.string.follow_set_empty_desc_label)
} else {
buildAnnotatedString {
append(stringRes(R.string.follow_set_current_desc_label) + " ")
withStyle(
SpanStyle(
fontWeight = FontWeight.Bold,
fontStyle = FontStyle.Normal,
fontSize = 15.sp,
),
) {
append("\"" + currentDescription + "\"")
}
}.text
}
AlertDialog(
onDismissRequest = onDismissDialog,
title = {
Text(text = stringRes(R.string.follow_set_desc_modify_label))
},
text = {
Column(
verticalArrangement = Arrangement.spacedBy(Size5dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = modifyIndicatorLabel,
fontSize = 15.sp,
fontWeight = FontWeight.Light,
fontStyle = FontStyle.Italic,
)
TextField(
value = updatedDescription.value ?: "",
onValueChange = { updatedDescription.value = it },
)
}
},
confirmButton = {
Button(
onClick = {
onModifyDescription(updatedDescription.value)
onDismissDialog()
},
) { Text(text = stringRes(R.string.follow_set_desc_modify_btn_label)) }
},
dismissButton = {
Button(onClick = onDismissDialog) { Text(text = stringRes(R.string.cancel)) }
},
)
}
@Composable
private fun GroupCloneDialog(
modifier: Modifier = Modifier,
@@ -49,8 +49,8 @@ import kotlinx.coroutines.flow.StateFlow
fun ListOfBookmarkGroupsFeedView(
groupListFeedSource: StateFlow<List<LabeledBookmarkList>>,
onOpenItem: (String, BookmarkType) -> Unit,
onRenameItem: (targetBookmarkGroup: LabeledBookmarkList, newName: String) -> Unit,
onItemDescriptionChange: (bookmarkGroup: LabeledBookmarkList, newDescription: String?) -> Unit,
onRenameItem: (targetBookmarkGroup: LabeledBookmarkList) -> Unit,
onItemDescriptionChange: (bookmarkGroup: LabeledBookmarkList) -> Unit,
onItemClone: (bookmarkGroup: LabeledBookmarkList, customName: String?, customDesc: String?) -> Unit,
onDeleteItem: (bookmarkGroup: LabeledBookmarkList) -> Unit,
) {
@@ -71,8 +71,8 @@ fun ListOfBookmarkGroupsFeedView(
modifier = Modifier.fillMaxSize().animateItem(),
bookmarkList = groupItem,
onClick = { bookmarkType -> onOpenItem(groupItem.identifier, bookmarkType) },
onRename = { onRenameItem(groupItem, it) },
onDescriptionChange = { onItemDescriptionChange(groupItem, it) },
onRename = { onRenameItem(groupItem) },
onDescriptionChange = { onItemDescriptionChange(groupItem) },
onClone = { cloneName, cloneDescription -> onItemClone(groupItem, cloneName, cloneDescription) },
onDelete = { onDeleteItem(groupItem) },
)
@@ -32,8 +32,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.nip51Lists.labeledBookmarkLists.LabeledBookmarkList
@@ -52,35 +50,15 @@ fun ListOfBookmarkGroupsScreen(
) {
ListOfBookmarkGroupsFeed(
listSource = accountViewModel.account.labeledBookmarkLists.listFeedFlow,
addBookmarkGroup = { title, description ->
accountViewModel.launchSigner {
accountViewModel.account.labeledBookmarkLists.addLabeledBookmarkList(
listName = title,
listDescription = description,
account = accountViewModel.account,
)
}
},
addBookmarkGroup = { nav.nav(Route.BookmarkGroupMetadataEdit()) },
openBookmarkGroup = { identifier, bookmarkType ->
nav.nav(Route.BookmarkGroupView(identifier, bookmarkType))
},
renameBookmarkGroup = { bookmarkGroup, newName ->
accountViewModel.launchSigner {
accountViewModel.account.labeledBookmarkLists.renameBookmarkList(
newName = newName,
bookmarkList = bookmarkGroup,
account = accountViewModel.account,
)
}
renameBookmarkGroup = { bookmarkGroup ->
nav.nav(Route.BookmarkGroupMetadataEdit(bookmarkGroup.identifier))
},
changeBookmarkGroupDescription = { bookmarkGroup, newDescription ->
accountViewModel.launchSigner {
accountViewModel.account.labeledBookmarkLists.modifyListDescription(
newDescription = newDescription,
bookmarkList = bookmarkGroup,
account = accountViewModel.account,
)
}
changeBookmarkGroupDescription = { bookmarkGroup ->
nav.nav(Route.BookmarkGroupMetadataEdit(bookmarkGroup.identifier))
},
cloneBookmarkGroup = { bookmarkGroup, customName, customDesc ->
accountViewModel.launchSigner {
@@ -107,10 +85,10 @@ fun ListOfBookmarkGroupsScreen(
@Composable
fun ListOfBookmarkGroupsFeed(
listSource: StateFlow<List<LabeledBookmarkList>>,
addBookmarkGroup: (title: String, description: String?) -> Unit,
addBookmarkGroup: () -> Unit,
openBookmarkGroup: (identifier: String, bookmarkType: BookmarkType) -> Unit,
renameBookmarkGroup: (bookmarkGroup: LabeledBookmarkList, newName: String) -> Unit,
changeBookmarkGroupDescription: (bookmarkGroup: LabeledBookmarkList, newDescription: String?) -> Unit,
renameBookmarkGroup: (bookmarkGroup: LabeledBookmarkList) -> Unit,
changeBookmarkGroupDescription: (bookmarkGroup: LabeledBookmarkList) -> Unit,
cloneBookmarkGroup: (bookmarkGroup: LabeledBookmarkList, customName: String?, customDesc: String?) -> Unit,
deleteBookmarkGroup: (bookmarkGroup: LabeledBookmarkList) -> Unit,
nav: INav,
@@ -120,7 +98,7 @@ fun ListOfBookmarkGroupsFeed(
TopBarWithBackButton(caption = stringRes(R.string.bookmark_lists), nav::popBack)
},
floatingActionButton = {
BookmarkGroupFabAndMenu(onAddGroup = addBookmarkGroup)
BookmarkGroupFab(onAddGroup = addBookmarkGroup)
},
) { paddingValues ->
Column(
@@ -143,9 +121,7 @@ fun ListOfBookmarkGroupsFeed(
}
@Composable
fun BookmarkGroupFabAndMenu(onAddGroup: (name: String, description: String?) -> Unit) {
val isSetAdditionDialogOpen = remember { mutableStateOf(false) }
fun BookmarkGroupFab(onAddGroup: () -> Unit) {
ExtendedFloatingActionButton(
text = {
Text(text = stringRes(R.string.follow_set_create_btn_label))
@@ -156,21 +132,8 @@ fun BookmarkGroupFabAndMenu(onAddGroup: (name: String, description: String?) ->
contentDescription = null,
)
},
onClick = {
isSetAdditionDialogOpen.value = true
},
onClick = onAddGroup,
shape = CircleShape,
containerColor = MaterialTheme.colorScheme.primary,
)
if (isSetAdditionDialogOpen.value) {
NewBookmarkGroupCreationDialog(
onDismiss = {
isSetAdditionDialogOpen.value = false
},
onCreateGroup = { name, description ->
onAddGroup(name, description)
},
)
}
}
@@ -83,7 +83,7 @@ private fun ListManagementView(
TopBarWithBackButton(caption = stringRes(R.string.article_bookmark_management_title), nav::popBack)
},
floatingActionButton = {
NewListButton { }
NewListButton { nav.nav(Route.BookmarkGroupMetadataEdit()) }
},
) { contentPadding ->
Column(
@@ -82,7 +82,7 @@ private fun ListManagementView(
TopBarWithBackButton(caption = stringRes(R.string.post_bookmark_management_title), nav::popBack)
},
floatingActionButton = {
NewListButton { }
NewListButton { nav.nav(Route.BookmarkGroupMetadataEdit()) }
},
) { contentPadding ->
Column(