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