Add support for modifying follow set descriptions.

This commit is contained in:
KotlinGeekDev
2025-10-09 16:56:40 +01:00
parent 192a257780
commit 9aa5f1bd9f
4 changed files with 148 additions and 18 deletions

View File

@@ -137,6 +137,13 @@ fun ListsAndSetsScreen(
account = accountViewModel.account, account = accountViewModel.account,
) )
}, },
changeItemDescription = { followSet, newDescription ->
followSetsViewModel.modifyFollowSetDescription(
newDescription = newDescription,
followSet = followSet,
account = accountViewModel.account,
)
},
cloneItem = { followSet, customName, customDescription -> cloneItem = { followSet, customName, customDescription ->
followSetsViewModel.cloneFollowSet( followSetsViewModel.cloneFollowSet(
currentFollowSet = followSet, currentFollowSet = followSet,
@@ -163,6 +170,7 @@ fun CustomListsScreen(
addItem: (title: String, description: String?) -> Unit, addItem: (title: String, description: String?) -> Unit,
openItem: (identifier: String) -> Unit, openItem: (identifier: String) -> Unit,
renameItem: (followSet: FollowSet, newName: String) -> Unit, renameItem: (followSet: FollowSet, newName: String) -> Unit,
changeItemDescription: (followSet: FollowSet, newDescription: String?) -> Unit,
cloneItem: (followSet: FollowSet, customName: String?, customDesc: String?) -> Unit, cloneItem: (followSet: FollowSet, customName: String?, customDesc: String?) -> Unit,
deleteItem: (followSet: FollowSet) -> Unit, deleteItem: (followSet: FollowSet) -> Unit,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
@@ -222,6 +230,7 @@ fun CustomListsScreen(
onRefresh = refresh, onRefresh = refresh,
onOpenItem = openItem, onOpenItem = openItem,
onRenameItem = renameItem, onRenameItem = renameItem,
onItemDescriptionChange = changeItemDescription,
onItemClone = cloneItem, onItemClone = cloneItem,
onDeleteItem = deleteItem, onDeleteItem = deleteItem,
) )
@@ -382,6 +391,9 @@ private fun SetItemPreview() {
onFollowSetRename = { onFollowSetRename = {
println("Follow set new name: $it") println("Follow set new name: $it")
}, },
onFollowSetDescriptionChange = { description ->
println("The follow set's description has been changed to $description")
},
onFollowSetClone = { newName, newDesc -> onFollowSetClone = { newName, newDesc ->
println("The follow set has been cloned, and has custom name: $newName, Desc: $newDesc") println("The follow set has been cloned, and has custom name: $newName, Desc: $newDesc")
}, },

View File

@@ -68,6 +68,7 @@ fun CustomSetItem(
followSet: FollowSet, followSet: FollowSet,
onFollowSetClick: () -> Unit, onFollowSetClick: () -> Unit,
onFollowSetRename: (String) -> Unit, onFollowSetRename: (String) -> Unit,
onFollowSetDescriptionChange: (String?) -> Unit,
onFollowSetClone: (customName: String?, customDescription: String?) -> Unit, onFollowSetClone: (customName: String?, customDescription: String?) -> Unit,
onFollowSetDelete: () -> Unit, onFollowSetDelete: () -> Unit,
) { ) {
@@ -183,7 +184,9 @@ fun CustomSetItem(
) { ) {
SetOptionsButton( SetOptionsButton(
followSetName = followSet.title, followSetName = followSet.title,
onListRename = onFollowSetRename, followSetDescription = followSet.description,
onSetRename = onFollowSetRename,
onSetDescriptionChange = onFollowSetDescriptionChange,
onSetCloneCreate = onFollowSetClone, onSetCloneCreate = onFollowSetClone,
onListDelete = onFollowSetDelete, onListDelete = onFollowSetDelete,
) )
@@ -195,7 +198,9 @@ fun CustomSetItem(
private fun SetOptionsButton( private fun SetOptionsButton(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
followSetName: String, followSetName: String,
onListRename: (String) -> Unit, followSetDescription: String?,
onSetRename: (String) -> Unit,
onSetDescriptionChange: (String?) -> Unit,
onSetCloneCreate: (optionalName: String?, optionalDec: String?) -> Unit, onSetCloneCreate: (optionalName: String?, optionalDec: String?) -> Unit,
onListDelete: () -> Unit, onListDelete: () -> Unit,
) { ) {
@@ -207,10 +212,12 @@ private fun SetOptionsButton(
VerticalDotsIcon() VerticalDotsIcon()
SetOptionsMenu( SetOptionsMenu(
listName = followSetName, setName = followSetName,
setDescription = followSetDescription,
isExpanded = isMenuOpen.value, isExpanded = isMenuOpen.value,
onDismiss = { isMenuOpen.value = false }, onDismiss = { isMenuOpen.value = false },
onListRename = onListRename, onSetRename = onSetRename,
onSetDescriptionChange = onSetDescriptionChange,
onSetClone = onSetCloneCreate, onSetClone = onSetCloneCreate,
onDelete = onListDelete, onDelete = onListDelete,
) )
@@ -221,8 +228,10 @@ private fun SetOptionsButton(
private fun SetOptionsMenu( private fun SetOptionsMenu(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
isExpanded: Boolean, isExpanded: Boolean,
listName: String, setName: String,
onListRename: (String) -> Unit, setDescription: String?,
onSetRename: (String) -> Unit,
onSetDescriptionChange: (String?) -> Unit,
onSetClone: (optionalNewName: String?, optionalNewDesc: String?) -> Unit, onSetClone: (optionalNewName: String?, optionalNewDesc: String?) -> Unit,
onDelete: () -> Unit, onDelete: () -> Unit,
onDismiss: () -> Unit, onDismiss: () -> Unit,
@@ -230,6 +239,8 @@ private fun SetOptionsMenu(
val isRenameDialogOpen = remember { mutableStateOf(false) } val isRenameDialogOpen = remember { mutableStateOf(false) }
val renameString = remember { mutableStateOf("") } val renameString = remember { mutableStateOf("") }
val isDescriptionModDialogOpen = remember { mutableStateOf(false) }
val isCopyDialogOpen = remember { mutableStateOf(false) } val isCopyDialogOpen = remember { mutableStateOf(false) }
val optionalCloneName = remember { mutableStateOf<String?>(null) } val optionalCloneName = remember { mutableStateOf<String?>(null) }
val optionalCloneDescription = remember { mutableStateOf<String?>(null) } val optionalCloneDescription = remember { mutableStateOf<String?>(null) }
@@ -238,14 +249,6 @@ private fun SetOptionsMenu(
expanded = isExpanded, expanded = isExpanded,
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
) { ) {
DropdownMenuItem(
text = {
Text(text = stringRes(R.string.quick_action_delete))
},
onClick = {
onDelete()
},
)
DropdownMenuItem( DropdownMenuItem(
text = { text = {
Text(text = stringRes(R.string.follow_set_rename_btn_label)) Text(text = stringRes(R.string.follow_set_rename_btn_label))
@@ -255,6 +258,15 @@ private fun SetOptionsMenu(
onDismiss() onDismiss()
}, },
) )
DropdownMenuItem(
text = {
Text(text = "Modify description")
},
onClick = {
isDescriptionModDialogOpen.value = true
onDismiss()
},
)
DropdownMenuItem( DropdownMenuItem(
text = { text = {
Text(text = stringRes(R.string.follow_set_copy_action_btn_label)) Text(text = stringRes(R.string.follow_set_copy_action_btn_label))
@@ -264,22 +276,38 @@ private fun SetOptionsMenu(
onDismiss() onDismiss()
}, },
) )
DropdownMenuItem(
text = {
Text(text = stringRes(R.string.quick_action_delete))
},
onClick = {
onDelete()
},
)
} }
if (isRenameDialogOpen.value) { if (isRenameDialogOpen.value) {
RenameDialog( SetRenameDialog(
currentName = listName, currentName = setName,
newName = renameString.value, newName = renameString.value,
onStringRenameChange = { onStringRenameChange = {
renameString.value = it renameString.value = it
}, },
onDismissDialog = { isRenameDialogOpen.value = false }, onDismissDialog = { isRenameDialogOpen.value = false },
onListRename = { onListRename = {
onListRename(renameString.value) onSetRename(renameString.value)
}, },
) )
} }
if (isDescriptionModDialogOpen.value) {
SetModifyDescriptionDialog(
currentDescription = setDescription,
onDismissDialog = { isDescriptionModDialogOpen.value = false },
onModifyDescription = onSetDescriptionChange,
)
}
if (isCopyDialogOpen.value) { if (isCopyDialogOpen.value) {
SetCloneDialog( SetCloneDialog(
optionalNewName = optionalCloneName.value, optionalNewName = optionalCloneName.value,
@@ -299,7 +327,7 @@ private fun SetOptionsMenu(
} }
@Composable @Composable
private fun RenameDialog( private fun SetRenameDialog(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
currentName: String, currentName: String,
newName: String, newName: String,
@@ -358,6 +386,69 @@ private fun RenameDialog(
) )
} }
@Composable
private fun SetModifyDescriptionDialog(
modifier: Modifier = Modifier,
currentDescription: String?,
onDismissDialog: () -> Unit,
onModifyDescription: (String?) -> Unit,
) {
val updatedDescription = remember { mutableStateOf<String?>(null) }
val modifyIndicatorLabel =
if (currentDescription == null) {
"This list doesn't have a description"
} else {
buildAnnotatedString {
append("Current description: ")
withStyle(
SpanStyle(
fontWeight = FontWeight.Bold,
fontStyle = FontStyle.Normal,
fontSize = 15.sp,
),
) {
append("\"" + currentDescription + "\"")
}
}.text
}
AlertDialog(
onDismissRequest = onDismissDialog,
title = {
Text(text = "Modify description")
},
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 = "Modify") }
},
dismissButton = {
Button(onClick = onDismissDialog) { Text(text = stringRes(R.string.cancel)) }
},
)
}
@Composable @Composable
private fun SetCloneDialog( private fun SetCloneDialog(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,

View File

@@ -51,6 +51,7 @@ fun FollowSetFeedView(
onRefresh: () -> Unit = {}, onRefresh: () -> Unit = {},
onOpenItem: (String) -> Unit = {}, onOpenItem: (String) -> Unit = {},
onRenameItem: (targetSet: FollowSet, newName: String) -> Unit, onRenameItem: (targetSet: FollowSet, newName: String) -> Unit,
onItemDescriptionChange: (followSet: FollowSet, newDescription: String?) -> Unit,
onItemClone: (followSet: FollowSet, customName: String?, customDesc: String?) -> Unit, onItemClone: (followSet: FollowSet, customName: String?, customDesc: String?) -> Unit,
onDeleteItem: (followSet: FollowSet) -> Unit, onDeleteItem: (followSet: FollowSet) -> Unit,
) { ) {
@@ -64,6 +65,7 @@ fun FollowSetFeedView(
onRefresh = onRefresh, onRefresh = onRefresh,
onItemClick = onOpenItem, onItemClick = onOpenItem,
onItemRename = onRenameItem, onItemRename = onRenameItem,
onItemDescriptionChange = onItemDescriptionChange,
onItemClone = onItemClone, onItemClone = onItemClone,
onItemDelete = onDeleteItem, onItemDelete = onDeleteItem,
) )
@@ -93,6 +95,7 @@ fun FollowSetLoaded(
onRefresh: () -> Unit = {}, onRefresh: () -> Unit = {},
onItemClick: (itemIdentifier: String) -> Unit = {}, onItemClick: (itemIdentifier: String) -> Unit = {},
onItemRename: (followSet: FollowSet, newName: String) -> Unit, onItemRename: (followSet: FollowSet, newName: String) -> Unit,
onItemDescriptionChange: (followSet: FollowSet, newDescription: String?) -> Unit,
onItemClone: (followSet: FollowSet, customName: String?, customDesc: String?) -> Unit, onItemClone: (followSet: FollowSet, customName: String?, customDesc: String?) -> Unit,
onItemDelete: (followSet: FollowSet) -> Unit, onItemDelete: (followSet: FollowSet) -> Unit,
) { ) {
@@ -116,6 +119,9 @@ fun FollowSetLoaded(
onFollowSetRename = { onFollowSetRename = {
onItemRename(set, it) onItemRename(set, it)
}, },
onFollowSetDescriptionChange = { newDescription ->
onItemDescriptionChange(set, newDescription)
},
onFollowSetClone = { cloneName, cloneDescription -> onFollowSetClone = { cloneName, cloneDescription ->
onItemClone(set, cloneName, cloneDescription) onItemClone(set, cloneName, cloneDescription)
}, },

View File

@@ -160,6 +160,27 @@ class FollowSetFeedViewModel(
} }
} }
fun modifyFollowSetDescription(
newDescription: String?,
followSet: FollowSet,
account: Account,
) {
if (!account.settings.isWriteable()) {
println("You are in read-only mode. Please login to make modifications.")
} else {
viewModelScope.launch(Dispatchers.IO) {
val setEvent = getFollowSetNote(followSet.identifierTag, account)?.event as PeopleListEvent
PeopleListEvent.modifyDescription(
earlierVersion = setEvent,
newDescription = newDescription,
signer = account.signer,
) {
account.sendMyPublicAndPrivateOutbox(it)
}
}
}
}
fun cloneFollowSet( fun cloneFollowSet(
currentFollowSet: FollowSet, currentFollowSet: FollowSet,
customCloneName: String?, customCloneName: String?,