diff --git a/app/src/main/kotlin/net/metacircular/engpad/ui/notebooks/NotebookListScreen.kt b/app/src/main/kotlin/net/metacircular/engpad/ui/notebooks/NotebookListScreen.kt index a94974b..07891c8 100644 --- a/app/src/main/kotlin/net/metacircular/engpad/ui/notebooks/NotebookListScreen.kt +++ b/app/src/main/kotlin/net/metacircular/engpad/ui/notebooks/NotebookListScreen.kt @@ -1,7 +1,6 @@ package net.metacircular.engpad.ui.notebooks -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -69,6 +68,7 @@ fun NotebookListScreen( val notebooks by viewModel.notebooks.collectAsState() var showCreateDialog by remember { mutableStateOf(false) } var notebookToDelete by remember { mutableStateOf(null) } + var notebookToRename by remember { mutableStateOf(null) } var filterText by remember { mutableStateOf("") } var sortField by remember { mutableStateOf(SortField.LAST_EDITED) } @@ -169,7 +169,8 @@ fun NotebookListScreen( NotebookItem( notebook = notebook, onClick = { onNotebookClick(notebook.id) }, - onLongClick = { notebookToDelete = notebook }, + onRename = { notebookToRename = notebook }, + onDelete = { notebookToDelete = notebook }, ) } } @@ -197,43 +198,75 @@ fun NotebookListScreen( }, ) } + + notebookToRename?.let { notebook -> + RenameNotebookDialog( + notebook = notebook, + onDismiss = { notebookToRename = null }, + onRename = { newTitle -> + viewModel.renameNotebook(notebook.id, newTitle) + notebookToRename = null + }, + ) + } } -@OptIn(ExperimentalFoundationApi::class) @Composable private fun NotebookItem( notebook: Notebook, onClick: () -> Unit, - onLongClick: () -> Unit, + onRename: () -> Unit, + onDelete: () -> Unit, ) { val dateFormat = remember { SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US) } + var showMenu by remember { mutableStateOf(false) } Card( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 4.dp) - .combinedClickable( - onClick = onClick, - onLongClick = onLongClick, - ), + .clickable(onClick = onClick), ) { - Column(modifier = Modifier.padding(16.dp)) { - Text( - text = notebook.title, - style = MaterialTheme.typography.titleMedium, - ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - ) { + Row( + modifier = Modifier.padding(start = 16.dp, top = 16.dp, bottom = 16.dp, end = 4.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Column(modifier = Modifier.weight(1f)) { Text( - text = notebook.pageSize.lowercase().replaceFirstChar { it.uppercase() }, - style = MaterialTheme.typography.bodySmall, - ) - Text( - text = dateFormat.format(Date(notebook.updatedAt)), - style = MaterialTheme.typography.bodySmall, + text = notebook.title, + style = MaterialTheme.typography.titleMedium, ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Text( + text = notebook.pageSize.lowercase().replaceFirstChar { it.uppercase() }, + style = MaterialTheme.typography.bodySmall, + ) + Text( + text = dateFormat.format(Date(notebook.updatedAt)), + style = MaterialTheme.typography.bodySmall, + ) + } + } + Box { + androidx.compose.material3.IconButton(onClick = { showMenu = true }) { + Text("\u22EE", style = MaterialTheme.typography.bodyLarge) + } + DropdownMenu( + expanded = showMenu, + onDismissRequest = { showMenu = false }, + ) { + DropdownMenuItem( + text = { Text("Rename") }, + onClick = { showMenu = false; onRename() }, + ) + DropdownMenuItem( + text = { Text("Delete") }, + onClick = { showMenu = false; onDelete() }, + ) + } } } } @@ -312,14 +345,44 @@ private fun DeleteNotebookDialog( title = { Text("Delete Notebook") }, text = { Text("Delete \"${notebook.title}\"? This cannot be undone.") }, confirmButton = { - TextButton(onClick = onConfirm) { - Text("Delete") - } + TextButton(onClick = onConfirm) { Text("Delete") } }, dismissButton = { - TextButton(onClick = onDismiss) { - Text("Cancel") - } + TextButton(onClick = onDismiss) { Text("Cancel") } + }, + ) +} + +@Composable +private fun RenameNotebookDialog( + notebook: Notebook, + onDismiss: () -> Unit, + onRename: (String) -> Unit, +) { + var title by remember { mutableStateOf(notebook.title) } + + AlertDialog( + onDismissRequest = onDismiss, + title = { Text("Rename Notebook") }, + text = { + OutlinedTextField( + value = title, + onValueChange = { title = it }, + label = { Text("Title") }, + singleLine = true, + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.Words, + ), + modifier = Modifier.fillMaxWidth(), + ) + }, + confirmButton = { + TextButton( + onClick = { onRename(title.ifBlank { notebook.title }) }, + ) { Text("Rename") } + }, + dismissButton = { + TextButton(onClick = onDismiss) { Text("Cancel") } }, ) } diff --git a/app/src/main/kotlin/net/metacircular/engpad/ui/notebooks/NotebookListViewModel.kt b/app/src/main/kotlin/net/metacircular/engpad/ui/notebooks/NotebookListViewModel.kt index a786ff3..764df64 100644 --- a/app/src/main/kotlin/net/metacircular/engpad/ui/notebooks/NotebookListViewModel.kt +++ b/app/src/main/kotlin/net/metacircular/engpad/ui/notebooks/NotebookListViewModel.kt @@ -29,6 +29,12 @@ class NotebookListViewModel( } } + fun renameNotebook(id: Long, title: String) { + viewModelScope.launch { + repository.updateTitle(id, title) + } + } + class Factory(private val repository: NotebookRepository) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T {