diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/SettingsDataCategory.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/SettingsDataCategory.kt index 8accccb..87dd959 100644 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/SettingsDataCategory.kt +++ b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/SettingsDataCategory.kt @@ -47,13 +47,14 @@ fun SettingsDataCategory( modifier: Modifier = Modifier ) { // TODO: 本页及其相关组件重组性能检查优化 - // TODO: 优化内部项目样式 val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() val snackbarHostState = remember { SnackbarHostState() } val scope = rememberCoroutineScope() val listState = rememberLazyListState() + var initialCategory by rememberSaveable { mutableStateOf("") } var showDialog by rememberSaveable { mutableStateOf(false) } + val categories by DataStoreManager.categoriesFlow.collectAsState(initial = emptyList()) val isExpanded by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } } @@ -68,7 +69,10 @@ fun SettingsDataCategory( icon = Icons.Outlined.Add, text = stringResource(R.string.action_add_category), expanded = isExpanded, - onClick = { showDialog = true } + onClick = { + initialCategory = "" + showDialog = true + } ) }, modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection), @@ -92,8 +96,12 @@ fun SettingsDataCategory( items(items = categories, key = { it }) { CategoryItem( name = it, - onDelete = { it -> - scope.launch { DataStoreManager.setCategories(categories - it) } + onClick = { category -> + initialCategory = category + showDialog = true + }, + onDelete = { category -> + scope.launch { DataStoreManager.setCategories(categories - category) } }, modifier = Modifier.animateItem( fadeInSpec = tween(100), @@ -110,20 +118,29 @@ fun SettingsDataCategory( CategoryPromptDialog( visible = showDialog, - text = stringResource(R.string.tip_enter_category), - onSave = { - if (!categories.contains(it)) { - scope.launch { - DataStoreManager.setCategories(categories + it) - } - } else { - scope.launch { - /*snackbarHostState.showSnackbar( + initialCategory = initialCategory, + onSave = { oldCategory, newCategory -> + if (oldCategory.isEmpty()) { + if (!categories.contains(newCategory)) { + scope.launch { + DataStoreManager.setCategories(categories + newCategory) + } + } else { + scope.launch { + /*snackbarHostState.showSnackbar( message = context.getString(R.string.error_category_duplicate) )*/ - // 调换分类位置 - val tempList = categories - it - DataStoreManager.setCategories(tempList + it) + // 调换分类位置 + val tempList = categories - newCategory + DataStoreManager.setCategories(tempList + newCategory) + } + } + } else { + if (oldCategory != newCategory) { + scope.launch { + val tempList = categories - oldCategory + DataStoreManager.setCategories(tempList + newCategory) + } } } }, diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/category/CategoryDialog.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/category/CategoryDialog.kt index 671f28d..d4ae27f 100644 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/category/CategoryDialog.kt +++ b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/category/CategoryDialog.kt @@ -6,18 +6,19 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.text.input.TextFieldLineLimits import androidx.compose.foundation.text.input.clearText import androidx.compose.foundation.text.input.rememberTextFieldState +import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Info import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties @@ -28,19 +29,20 @@ import cn.super12138.todo.ui.components.BasicDialog fun CategoryPromptDialog( modifier: Modifier = Modifier, visible: Boolean, - icon: ImageVector = Icons.Outlined.Info, - title: String = stringResource(R.string.tip_tips), - text: String, - confirmButtonText: String = stringResource(R.string.action_save), - showDismissButton: Boolean = true, - dismissButtonText: String = stringResource(R.string.action_cancel), - properties: DialogProperties = DialogProperties(), - onSave: (String) -> Unit, + initialCategory: String = "", + onSave: (oldValue: String, newValue: String) -> Unit, onDismiss: () -> Unit ) { - val textFieldState = rememberTextFieldState() + val textFieldState = rememberTextFieldState(initialText = initialCategory) var isError by rememberSaveable { mutableStateOf(false) } + LaunchedEffect(visible) { + if (visible) { + textFieldState.setTextAndPlaceCursorAtEnd(initialCategory) + isError = false + } + } + val supportingText = listOf( stringResource(R.string.tip_max_length_5), stringResource(R.string.error_no_content_entered), @@ -51,11 +53,11 @@ fun CategoryPromptDialog( BasicDialog( visible = visible, - icon = icon, - title = title, + icon = Icons.Outlined.Info, + title = stringResource(R.string.tip_tips), text = { // 已经是实现好滚动的Column布局 - Text(text) + Text(stringResource(R.string.tip_enter_category)) Spacer(Modifier.size(3.dp)) OutlinedTextField( state = textFieldState, @@ -65,8 +67,8 @@ fun CategoryPromptDialog( isError = isError ) }, - confirmButton = confirmButtonText, - dismissButton = if (showDismissButton) dismissButtonText else null, + confirmButton = stringResource(R.string.action_save), + dismissButton = stringResource(R.string.action_cancel), onConfirm = { val trimmedText = textFieldState.text.trim() when { @@ -83,7 +85,7 @@ fun CategoryPromptDialog( } else -> { - onSave(trimmedText.toString()) + onSave(initialCategory, trimmedText.toString()) isError = false currentSupportingText = supportingText[0] textFieldState.clearText() @@ -92,7 +94,7 @@ fun CategoryPromptDialog( } }, onDismiss = onDismiss, - properties = properties, + properties = DialogProperties(), modifier = modifier ) } \ No newline at end of file diff --git a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/category/CategoryItem.kt b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/category/CategoryItem.kt index e300df6..0ca8269 100644 --- a/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/category/CategoryItem.kt +++ b/app/src/main/kotlin/cn/super12138/todo/ui/pages/settings/components/category/CategoryItem.kt @@ -18,7 +18,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.sp import cn.super12138.todo.R import cn.super12138.todo.ui.TodoDefaults import cn.super12138.todo.utils.VibrationUtils @@ -27,6 +26,7 @@ import cn.super12138.todo.utils.VibrationUtils fun CategoryItem( modifier: Modifier = Modifier, name: String, + onClick: (String) -> Unit = {}, onDelete: (String) -> Unit = {} ) { val view = LocalView.current @@ -35,6 +35,12 @@ fun CategoryItem( .fillMaxWidth() .wrapContentHeight() .clip(MaterialTheme.shapes.large) + .clickable( + onClick = { + VibrationUtils.performHapticFeedback(view) + onClick(name) + } + ) .padding( horizontal = TodoDefaults.settingsItemHorizontalPadding, vertical = TodoDefaults.settingsItemVerticalPadding / 2