feat: 优化设置页页面样式,简化布局
This commit is contained in:
parent
12285e5be7
commit
667cb152ea
26 changed files with 510 additions and 418 deletions
|
|
@ -38,7 +38,7 @@ android {
|
||||||
applicationId = "cn.super12138.todo"
|
applicationId = "cn.super12138.todo"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 923
|
versionCode = 940
|
||||||
versionName = "2.3.3"
|
versionName = "2.3.3"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
package cn.super12138.todo.ui
|
package cn.super12138.todo.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.shape.CornerBasedShape
|
||||||
|
import androidx.compose.foundation.shape.ZeroCornerSize
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.Shape
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
object TodoDefaults {
|
object TodoDefaults {
|
||||||
|
|
@ -26,7 +32,9 @@ object TodoDefaults {
|
||||||
/**
|
/**
|
||||||
* 设置项垂直边距
|
* 设置项垂直边距
|
||||||
*/
|
*/
|
||||||
val settingsItemVerticalPadding = 20.dp
|
val settingsItemVerticalPadding = 16.dp
|
||||||
|
|
||||||
|
val settingsItemPadding = 2.dp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 待办进度条粗度
|
* 待办进度条粗度
|
||||||
|
|
@ -47,4 +55,29 @@ object TodoDefaults {
|
||||||
* 待办进度条波幅
|
* 待办进度条波幅
|
||||||
*/
|
*/
|
||||||
const val waveAmplitude = 0.6f
|
const val waveAmplitude = 0.6f
|
||||||
|
|
||||||
|
val ScreenContainerShape: Shape
|
||||||
|
@Composable
|
||||||
|
get() = MaterialTheme.shapes.large.copy(
|
||||||
|
bottomStart = ZeroCornerSize,
|
||||||
|
bottomEnd = ZeroCornerSize
|
||||||
|
)
|
||||||
|
|
||||||
|
val ContainerColor: Color
|
||||||
|
@Composable
|
||||||
|
get() = MaterialTheme.colorScheme.surfaceBright
|
||||||
|
|
||||||
|
val BackgroundColor: Color
|
||||||
|
@Composable
|
||||||
|
get() = MaterialTheme.colorScheme.surfaceContainer
|
||||||
|
|
||||||
|
val SettingsItemDefaultShape: CornerBasedShape
|
||||||
|
@Composable
|
||||||
|
get() = MaterialTheme.shapes.small
|
||||||
|
|
||||||
|
val SettingsItemRoundedShape: CornerBasedShape
|
||||||
|
@Composable
|
||||||
|
get() = MaterialTheme.shapes.large
|
||||||
|
|
||||||
|
val fadedEdgeWidth = 8.dp
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +73,7 @@ class CrashActivity : ComponentActivity() {
|
||||||
) {
|
) {
|
||||||
CrashPage(
|
CrashPage(
|
||||||
crashLog = crashLogs ?: stringResource(R.string.tip_no_crash_logs),
|
crashLog = crashLogs ?: stringResource(R.string.tip_no_crash_logs),
|
||||||
exitApp = { finishAffinity() },
|
exitApp = ::finishAffinity,
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
|
|
@ -19,6 +18,7 @@ import androidx.core.view.WindowCompat
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import cn.super12138.todo.constants.Constants
|
import cn.super12138.todo.constants.Constants
|
||||||
import cn.super12138.todo.logic.datastore.DataStoreManager
|
import cn.super12138.todo.logic.datastore.DataStoreManager
|
||||||
|
import cn.super12138.todo.ui.TodoDefaults
|
||||||
import cn.super12138.todo.ui.components.Konfetti
|
import cn.super12138.todo.ui.components.Konfetti
|
||||||
import cn.super12138.todo.ui.navigation.TodoNavigation
|
import cn.super12138.todo.ui.navigation.TodoNavigation
|
||||||
import cn.super12138.todo.ui.theme.DarkMode
|
import cn.super12138.todo.ui.theme.DarkMode
|
||||||
|
|
@ -83,7 +83,7 @@ class MainActivity : ComponentActivity() {
|
||||||
contrastLevel = contrastLevel.toDouble(),
|
contrastLevel = contrastLevel.toDouble(),
|
||||||
dynamicColor = dynamicColor
|
dynamicColor = dynamicColor
|
||||||
) {
|
) {
|
||||||
Surface(color = MaterialTheme.colorScheme.background) {
|
Surface(color = TodoDefaults.BackgroundColor) {
|
||||||
TodoNavigation(
|
TodoNavigation(
|
||||||
viewModel = mainViewModel,
|
viewModel = mainViewModel,
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
|
|
|
||||||
|
|
@ -4,26 +4,28 @@ import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.FabPosition
|
import androidx.compose.material3.FabPosition
|
||||||
import androidx.compose.material3.FilledIconButton
|
import androidx.compose.material3.FilledIconButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButtonDefaults
|
import androidx.compose.material3.IconButtonDefaults
|
||||||
import androidx.compose.material3.LargeTopAppBar
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.ScaffoldDefaults
|
import androidx.compose.material3.ScaffoldDefaults
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
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 cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
|
import cn.super12138.todo.ui.TodoDefaults
|
||||||
import cn.super12138.todo.utils.VibrationUtils
|
import cn.super12138.todo.utils.VibrationUtils
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -31,16 +33,14 @@ import cn.super12138.todo.utils.VibrationUtils
|
||||||
* * 内容默认由 Box 容器包裹;实际使用时推荐配合 Column 或 Row
|
* * 内容默认由 Box 容器包裹;实际使用时推荐配合 Column 或 Row
|
||||||
*
|
*
|
||||||
* @param title 标题文本
|
* @param title 标题文本
|
||||||
* @param scrollBehavior 滚动行为,用于支持页面内容滚动时标题栏的压缩效果
|
|
||||||
* @param onBack 当返回按钮被按下时的操作
|
* @param onBack 当返回按钮被按下时的操作
|
||||||
* @param contentWindowInsets 内容边距,通常用于将内容和系统状态栏等隔开;可以使用 `WindowInsets.safeContent`
|
* @param contentWindowInsets 内容边距,通常用于将内容和系统状态栏等隔开;可以使用 `WindowInsets.safeContent`
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun LargeTopAppBarScaffold(
|
fun TopAppBarScaffold(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
title: String,
|
title: String,
|
||||||
scrollBehavior: TopAppBarScrollBehavior,
|
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
snackbarHost: @Composable () -> Unit = {},
|
snackbarHost: @Composable () -> Unit = {},
|
||||||
floatingActionButton: @Composable () -> Unit = {},
|
floatingActionButton: @Composable () -> Unit = {},
|
||||||
|
|
@ -49,7 +49,7 @@ fun LargeTopAppBarScaffold(
|
||||||
content: @Composable (PaddingValues) -> Unit
|
content: @Composable (PaddingValues) -> Unit
|
||||||
) {
|
) {
|
||||||
val view = LocalView.current
|
val view = LocalView.current
|
||||||
LargeTopAppBarScaffold(
|
TopAppBarScaffold(
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
|
|
@ -59,7 +59,7 @@ fun LargeTopAppBarScaffold(
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
FilledIconButton(
|
FilledIconButton(
|
||||||
colors = IconButtonDefaults.filledIconButtonColors(containerColor = MaterialTheme.colorScheme.surfaceContainerHigh),
|
colors = IconButtonDefaults.filledIconButtonColors(containerColor = MaterialTheme.colorScheme.surfaceContainerHighest),
|
||||||
shapes = IconButtonDefaults.shapes(),
|
shapes = IconButtonDefaults.shapes(),
|
||||||
onClick = {
|
onClick = {
|
||||||
VibrationUtils.performHapticFeedback(view)
|
VibrationUtils.performHapticFeedback(view)
|
||||||
|
|
@ -72,25 +72,24 @@ fun LargeTopAppBarScaffold(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollBehavior = scrollBehavior,
|
|
||||||
snackbarHost = snackbarHost,
|
snackbarHost = snackbarHost,
|
||||||
floatingActionButton = floatingActionButton,
|
floatingActionButton = floatingActionButton,
|
||||||
floatingActionButtonPosition = floatingActionButtonPosition,
|
floatingActionButtonPosition = floatingActionButtonPosition,
|
||||||
contentWindowInsets = contentWindowInsets,
|
contentWindowInsets = contentWindowInsets,
|
||||||
modifier = modifier
|
modifier = modifier,
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
|
//TODO: 应用圆角效果
|
||||||
Box { content(innerPadding) }
|
Box { content(innerPadding) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun LargeTopAppBarScaffold(
|
fun TopAppBarScaffold(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
title: @Composable () -> Unit = {},
|
title: @Composable () -> Unit = {},
|
||||||
navigationIcon: @Composable () -> Unit = {},
|
navigationIcon: @Composable () -> Unit = {},
|
||||||
actions: @Composable RowScope.() -> Unit = {},
|
actions: @Composable RowScope.() -> Unit = {},
|
||||||
scrollBehavior: TopAppBarScrollBehavior,
|
|
||||||
snackbarHost: @Composable () -> Unit = {},
|
snackbarHost: @Composable () -> Unit = {},
|
||||||
floatingActionButton: @Composable () -> Unit = {},
|
floatingActionButton: @Composable () -> Unit = {},
|
||||||
floatingActionButtonPosition: FabPosition = FabPosition.End,
|
floatingActionButtonPosition: FabPosition = FabPosition.End,
|
||||||
|
|
@ -98,20 +97,22 @@ fun LargeTopAppBarScaffold(
|
||||||
content: @Composable (PaddingValues) -> Unit
|
content: @Composable (PaddingValues) -> Unit
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = modifier
|
modifier = modifier,
|
||||||
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
|
||||||
topBar = {
|
topBar = {
|
||||||
LargeTopAppBar(
|
TopAppBar(
|
||||||
title = title,
|
title = title,
|
||||||
navigationIcon = navigationIcon,
|
navigationIcon = navigationIcon,
|
||||||
actions = actions,
|
actions = actions,
|
||||||
scrollBehavior = scrollBehavior
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
|
containerColor = TodoDefaults.BackgroundColor,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
snackbarHost = snackbarHost,
|
snackbarHost = snackbarHost,
|
||||||
floatingActionButton = floatingActionButton,
|
floatingActionButton = floatingActionButton,
|
||||||
floatingActionButtonPosition = floatingActionButtonPosition,
|
floatingActionButtonPosition = floatingActionButtonPosition,
|
||||||
contentWindowInsets = contentWindowInsets
|
contentWindowInsets = contentWindowInsets,
|
||||||
|
containerColor = TodoDefaults.BackgroundColor,
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
Box { content(innerPadding) }
|
Box { content(innerPadding) }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package cn.super12138.todo.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import cn.super12138.todo.ui.TodoDefaults
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
|
@Composable
|
||||||
|
fun RoundedScreenContainer(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
content: @Composable () -> Unit,
|
||||||
|
) {
|
||||||
|
Surface(
|
||||||
|
modifier = modifier.padding(horizontal = TodoDefaults.screenHorizontalPadding),
|
||||||
|
color = TodoDefaults.BackgroundColor,
|
||||||
|
shape = TodoDefaults.ScreenContainerShape,
|
||||||
|
content = content
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -44,7 +44,7 @@ import cn.super12138.todo.logic.datastore.DataStoreManager
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
import cn.super12138.todo.ui.TodoDefaults
|
||||||
import cn.super12138.todo.ui.components.ChipItem
|
import cn.super12138.todo.ui.components.ChipItem
|
||||||
import cn.super12138.todo.ui.components.ConfirmDialog
|
import cn.super12138.todo.ui.components.ConfirmDialog
|
||||||
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.TopAppBarScaffold
|
||||||
import cn.super12138.todo.ui.components.TodoFloatingActionButton
|
import cn.super12138.todo.ui.components.TodoFloatingActionButton
|
||||||
import cn.super12138.todo.ui.pages.editor.components.TodoCategoryChip
|
import cn.super12138.todo.ui.pages.editor.components.TodoCategoryChip
|
||||||
import cn.super12138.todo.ui.pages.editor.components.TodoCategoryTextField
|
import cn.super12138.todo.ui.pages.editor.components.TodoCategoryTextField
|
||||||
|
|
@ -69,7 +69,7 @@ fun TodoEditorPage(
|
||||||
// TODO: 本页及其相关组件重组性能检查优化
|
// TODO: 本页及其相关组件重组性能检查优化
|
||||||
val view = LocalView.current
|
val view = LocalView.current
|
||||||
val animatedVisibilityScope = LocalNavAnimatedContentScope.current
|
val animatedVisibilityScope = LocalNavAnimatedContentScope.current
|
||||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||||
|
|
||||||
val uiState = rememberEditorState(initialTodo = toDo)
|
val uiState = rememberEditorState(initialTodo = toDo)
|
||||||
|
|
||||||
|
|
@ -112,9 +112,8 @@ fun TodoEditorPage(
|
||||||
|
|
||||||
BackHandler(onBack = ::checkModifiedBeforeBack)
|
BackHandler(onBack = ::checkModifiedBeforeBack)
|
||||||
|
|
||||||
LargeTopAppBarScaffold(
|
TopAppBarScaffold(
|
||||||
title = stringResource(if (toDo != null) R.string.title_edit_task else R.string.action_add_task),
|
title = stringResource(if (toDo != null) R.string.title_edit_task else R.string.action_add_task),
|
||||||
scrollBehavior = scrollBehavior,
|
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
with(sharedTransitionScope) {
|
with(sharedTransitionScope) {
|
||||||
Row(
|
Row(
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,10 @@
|
||||||
package cn.super12138.todo.ui.pages.settings
|
package cn.super12138.todo.ui.pages.settings
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
|
@ -18,17 +13,15 @@ import androidx.compose.runtime.mutableLongStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalUriHandler
|
import androidx.compose.ui.platform.LocalUriHandler
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
import cn.super12138.todo.constants.Constants
|
import cn.super12138.todo.constants.Constants
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
import cn.super12138.todo.ui.components.TopAppBarScaffold
|
||||||
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.RoundedScreenContainer
|
||||||
import cn.super12138.todo.ui.icons.GitHubIcon
|
import cn.super12138.todo.ui.icons.GitHubIcon
|
||||||
import cn.super12138.todo.ui.pages.settings.components.Settings
|
import cn.super12138.todo.ui.pages.settings.components.SettingsContainer
|
||||||
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
|
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
|
||||||
import cn.super12138.todo.utils.SystemUtils
|
import cn.super12138.todo.utils.SystemUtils
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
@ -42,80 +35,82 @@ fun SettingsAbout(
|
||||||
onNavigateUp: () -> Unit,
|
onNavigateUp: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
TopAppBarScaffold(
|
||||||
LargeTopAppBarScaffold(
|
|
||||||
title = stringResource(R.string.pref_about),
|
title = stringResource(R.string.pref_about),
|
||||||
onBack = onNavigateUp,
|
onBack = onNavigateUp,
|
||||||
scrollBehavior = scrollBehavior,
|
modifier = modifier,
|
||||||
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val uriHandler = LocalUriHandler.current
|
val uriHandler = LocalUriHandler.current
|
||||||
|
var clickCount by remember { mutableIntStateOf(0) }
|
||||||
|
var lastClickTime by remember { mutableLongStateOf(0L) }
|
||||||
|
|
||||||
Column(
|
LaunchedEffect(clickCount) {
|
||||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
if (clickCount > 0) {
|
||||||
modifier = Modifier
|
lastClickTime = System.currentTimeMillis()
|
||||||
.fillMaxSize()
|
val currentClickTime = lastClickTime
|
||||||
.padding(innerPadding)
|
delay(300L)
|
||||||
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
|
|
||||||
.verticalScroll(rememberScrollState())
|
|
||||||
) {
|
|
||||||
Settings {
|
|
||||||
var clickCount by remember { mutableIntStateOf(0) }
|
|
||||||
var lastClickTime by remember { mutableLongStateOf(0L) }
|
|
||||||
|
|
||||||
LaunchedEffect(clickCount) {
|
if (currentClickTime == lastClickTime) {
|
||||||
if (clickCount > 0) {
|
clickCount = 0
|
||||||
lastClickTime = System.currentTimeMillis()
|
|
||||||
val currentClickTime = lastClickTime
|
|
||||||
delay(300L)
|
|
||||||
|
|
||||||
if (currentClickTime == lastClickTime) {
|
|
||||||
clickCount = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SettingsItem(
|
RoundedScreenContainer(Modifier.padding(innerPadding)) {
|
||||||
leadingIconRes = R.drawable.ic_numbers,
|
SettingsContainer(Modifier.fillMaxSize()) {
|
||||||
title = stringResource(R.string.pref_app_version),
|
item {
|
||||||
description = SystemUtils.getAppVersion(context),
|
SettingsItem(
|
||||||
onClick = {
|
leadingIconRes = R.drawable.ic_numbers,
|
||||||
clickCount++
|
title = stringResource(R.string.pref_app_version),
|
||||||
if (clickCount == 5) {
|
description = SystemUtils.getAppVersion(context),
|
||||||
if ((System.currentTimeMillis() % 2) == 0.toLong()) {
|
onClick = {
|
||||||
Toast.makeText(context, "🍨", Toast.LENGTH_SHORT).show()
|
clickCount++
|
||||||
} else {
|
if (clickCount == 5) {
|
||||||
Toast.makeText(context, "✈️", Toast.LENGTH_SHORT).show()
|
if ((System.currentTimeMillis() % 2) == 0.toLong()) {
|
||||||
|
Toast.makeText(context, "🍨", Toast.LENGTH_SHORT).show()
|
||||||
|
} else {
|
||||||
|
Toast.makeText(context, "✈️", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
clickCount = 0
|
||||||
}
|
}
|
||||||
clickCount = 0
|
},
|
||||||
}
|
topRounded = true
|
||||||
}
|
)
|
||||||
)
|
}
|
||||||
SettingsItem(
|
item {
|
||||||
leadingIconRes = R.drawable.ic_person_4,
|
SettingsItem(
|
||||||
title = stringResource(R.string.pref_developer),
|
leadingIconRes = R.drawable.ic_person_4,
|
||||||
description = stringResource(R.string.developer_name),
|
title = stringResource(R.string.pref_developer),
|
||||||
onClick = { uriHandler.openUri(Constants.DEVELOPER_GITHUB) }
|
description = stringResource(R.string.developer_name),
|
||||||
)
|
onClick = { uriHandler.openUri(Constants.DEVELOPER_GITHUB) },
|
||||||
SettingsItem(
|
)
|
||||||
leadingIcon = GitHubIcon,
|
}
|
||||||
title = stringResource(R.string.pref_view_on_github),
|
item {
|
||||||
description = stringResource(R.string.pref_view_on_github_desc),
|
SettingsItem(
|
||||||
onClick = { uriHandler.openUri(Constants.GITHUB_REPO) }
|
leadingIcon = GitHubIcon,
|
||||||
)
|
title = stringResource(R.string.pref_view_on_github),
|
||||||
SettingsItem(
|
description = stringResource(R.string.pref_view_on_github_desc),
|
||||||
leadingIconRes = R.drawable.ic_balance,
|
onClick = { uriHandler.openUri(Constants.GITHUB_REPO) }
|
||||||
title = stringResource(R.string.pref_licence),
|
)
|
||||||
description = stringResource(R.string.pref_licence_desc),
|
}
|
||||||
onClick = toLicencePage
|
item {
|
||||||
)
|
SettingsItem(
|
||||||
SettingsItem(
|
leadingIconRes = R.drawable.ic_balance,
|
||||||
leadingIconRes = R.drawable.ic_code_blocks,
|
title = stringResource(R.string.pref_licence),
|
||||||
title = stringResource(R.string.pref_developer_options),
|
description = stringResource(R.string.pref_licence_desc),
|
||||||
description = stringResource(R.string.pref_developer_options_desc),
|
onClick = toLicencePage
|
||||||
onClick = toDevPage
|
)
|
||||||
)
|
}
|
||||||
|
item {
|
||||||
|
SettingsItem(
|
||||||
|
leadingIconRes = R.drawable.ic_code_blocks,
|
||||||
|
title = stringResource(R.string.pref_developer_options),
|
||||||
|
description = stringResource(R.string.pref_developer_options_desc),
|
||||||
|
onClick = toDevPage,
|
||||||
|
bottomRounded = true
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
@ -14,7 +13,7 @@ import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.TopAppBarScaffold
|
||||||
import cn.super12138.todo.ui.pages.settings.components.licence.LicenceList
|
import cn.super12138.todo.ui.pages.settings.components.licence.LicenceList
|
||||||
import com.mikepenz.aboutlibraries.ui.compose.android.produceLibraries
|
import com.mikepenz.aboutlibraries.ui.compose.android.produceLibraries
|
||||||
|
|
||||||
|
|
@ -24,10 +23,8 @@ fun SettingsAboutLicence(
|
||||||
onNavigateUp: () -> Unit,
|
onNavigateUp: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
TopAppBarScaffold(
|
||||||
LargeTopAppBarScaffold(
|
|
||||||
title = stringResource(R.string.pref_licence),
|
title = stringResource(R.string.pref_licence),
|
||||||
scrollBehavior = scrollBehavior,
|
|
||||||
onBack = onNavigateUp,
|
onBack = onNavigateUp,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,20 @@
|
||||||
package cn.super12138.todo.ui.pages.settings
|
package cn.super12138.todo.ui.pages.settings
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
import cn.super12138.todo.constants.Constants
|
import cn.super12138.todo.constants.Constants
|
||||||
import cn.super12138.todo.logic.datastore.DataStoreManager
|
import cn.super12138.todo.logic.datastore.DataStoreManager
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
import cn.super12138.todo.ui.components.TopAppBarScaffold
|
||||||
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.RoundedScreenContainer
|
||||||
import cn.super12138.todo.ui.pages.settings.components.Settings
|
import cn.super12138.todo.ui.pages.settings.components.SettingsContainer
|
||||||
import cn.super12138.todo.ui.pages.settings.components.SwitchSettingsItem
|
import cn.super12138.todo.ui.pages.settings.components.SwitchSettingsItem
|
||||||
import cn.super12138.todo.ui.pages.settings.components.appearance.contrast.ContrastPicker
|
import cn.super12138.todo.ui.pages.settings.components.appearance.contrast.ContrastPicker
|
||||||
import cn.super12138.todo.ui.pages.settings.components.appearance.darkmode.DarkModePicker
|
import cn.super12138.todo.ui.pages.settings.components.appearance.darkmode.DarkModePicker
|
||||||
|
|
@ -41,46 +36,48 @@ fun SettingsAppearance(
|
||||||
val contrastLevel by DataStoreManager.contrastLevelFlow.collectAsState(initial = Constants.PREF_CONTRAST_LEVEL_DEFAULT)
|
val contrastLevel by DataStoreManager.contrastLevelFlow.collectAsState(initial = Constants.PREF_CONTRAST_LEVEL_DEFAULT)
|
||||||
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
TopAppBarScaffold(
|
||||||
LargeTopAppBarScaffold(
|
|
||||||
title = stringResource(R.string.pref_appearance),
|
title = stringResource(R.string.pref_appearance),
|
||||||
onBack = onNavigateUp,
|
onBack = onNavigateUp,
|
||||||
scrollBehavior = scrollBehavior,
|
modifier = modifier,
|
||||||
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
Column(
|
RoundedScreenContainer(Modifier.padding(innerPadding)) {
|
||||||
modifier = Modifier
|
SettingsContainer(Modifier.fillMaxSize()) {
|
||||||
.fillMaxSize()
|
item(key = 1) {
|
||||||
.padding(innerPadding)
|
SwitchSettingsItem(
|
||||||
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
|
checked = dynamicColor,
|
||||||
.verticalScroll(rememberScrollState())
|
leadingIconRes = R.drawable.ic_wand_stars,
|
||||||
) {
|
title = stringResource(R.string.pref_appearance_dynamic_color),
|
||||||
Settings {
|
description = stringResource(R.string.pref_appearance_dynamic_color_desc),
|
||||||
SwitchSettingsItem(
|
onCheckedChange = { scope.launch { DataStoreManager.setDynamicColor(it) } },
|
||||||
checked = dynamicColor,
|
topRounded = true
|
||||||
leadingIconRes = R.drawable.ic_wand_stars,
|
)
|
||||||
title = stringResource(R.string.pref_appearance_dynamic_color),
|
}
|
||||||
description = stringResource(R.string.pref_appearance_dynamic_color_desc),
|
|
||||||
onCheckedChange = { scope.launch { DataStoreManager.setDynamicColor(it) } },
|
|
||||||
)
|
|
||||||
|
|
||||||
DarkModePicker(
|
item(key = 2) {
|
||||||
currentDarkMode = { DarkMode.fromId(darkMode) },
|
DarkModePicker(
|
||||||
onDarkModeChange = { scope.launch { DataStoreManager.setDarkMode(it.id) } }
|
currentDarkMode = { DarkMode.fromId(darkMode) },
|
||||||
)
|
onDarkModeChange = { scope.launch { DataStoreManager.setDarkMode(it.id) } }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
PalettePicker(
|
item(key = 3) {
|
||||||
currentPalette = { PaletteStyle.fromId(paletteStyle) },
|
PalettePicker(
|
||||||
onPaletteChange = { scope.launch { DataStoreManager.setPaletteStyle(it.id) } },
|
currentPalette = { PaletteStyle.fromId(paletteStyle) },
|
||||||
isDynamicColor = dynamicColor,
|
onPaletteChange = { scope.launch { DataStoreManager.setPaletteStyle(it.id) } },
|
||||||
isDarkMode = DarkMode.fromId(darkMode),
|
isDynamicColor = dynamicColor,
|
||||||
contrastLevel = ContrastLevel.fromFloat(contrastLevel)
|
isDarkMode = DarkMode.fromId(darkMode),
|
||||||
)
|
contrastLevel = ContrastLevel.fromFloat(contrastLevel)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
ContrastPicker(
|
item(key = 4) {
|
||||||
currentContrast = ContrastLevel.fromFloat(contrastLevel),
|
ContrastPicker(
|
||||||
onContrastChange = { scope.launch { DataStoreManager.setContrastLevel(it.value) } }
|
currentContrast = ContrastLevel.fromFloat(contrastLevel),
|
||||||
)
|
onContrastChange = { scope.launch { DataStoreManager.setContrastLevel(it.value) } },
|
||||||
|
bottomRounded = true
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,12 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
|
@ -22,17 +18,16 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||||
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.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
|
||||||
import cn.super12138.todo.ui.activities.MainActivity
|
import cn.super12138.todo.ui.activities.MainActivity
|
||||||
import cn.super12138.todo.ui.components.ConfirmDialog
|
import cn.super12138.todo.ui.components.ConfirmDialog
|
||||||
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.TopAppBarScaffold
|
||||||
import cn.super12138.todo.ui.pages.settings.components.Settings
|
import cn.super12138.todo.ui.components.RoundedScreenContainer
|
||||||
import cn.super12138.todo.ui.pages.settings.components.SettingsCategory
|
import cn.super12138.todo.ui.pages.settings.components.SettingsCategory
|
||||||
|
import cn.super12138.todo.ui.pages.settings.components.SettingsContainer
|
||||||
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
|
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
|
||||||
import cn.super12138.todo.ui.viewmodels.MainViewModel
|
import cn.super12138.todo.ui.viewmodels.MainViewModel
|
||||||
import cn.super12138.todo.utils.SystemUtils
|
import cn.super12138.todo.utils.SystemUtils
|
||||||
|
|
@ -48,9 +43,7 @@ fun SettingsData(
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
var showRestoreDialog by rememberSaveable { mutableStateOf(false) }
|
var showRestoreDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
|
@ -104,47 +97,49 @@ fun SettingsData(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
LargeTopAppBarScaffold(
|
TopAppBarScaffold(
|
||||||
title = stringResource(R.string.pref_data),
|
title = stringResource(R.string.pref_data),
|
||||||
onBack = onNavigateUp,
|
onBack = onNavigateUp,
|
||||||
scrollBehavior = scrollBehavior,
|
|
||||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||||
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = modifier,
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
Column(
|
RoundedScreenContainer(Modifier.padding(innerPadding)) {
|
||||||
Modifier
|
SettingsContainer(Modifier.fillMaxSize()) {
|
||||||
.fillMaxSize()
|
item {
|
||||||
.padding(innerPadding)
|
SettingsCategory(title = stringResource(R.string.pref_category_data_management), first = true)
|
||||||
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
|
SettingsItem(
|
||||||
.verticalScroll(rememberScrollState())
|
leadingIconRes = R.drawable.ic_download,
|
||||||
) {
|
title = stringResource(R.string.pref_backup),
|
||||||
SettingsCategory(stringResource(R.string.pref_category_data_management))
|
description = stringResource(R.string.pref_backup_desc),
|
||||||
Settings {
|
onClick = {
|
||||||
SettingsItem(
|
backupLauncher.launch("Todo-backup-${SystemUtils.getTime()}.zip")
|
||||||
leadingIconRes = R.drawable.ic_download,
|
},
|
||||||
title = stringResource(R.string.pref_backup),
|
topRounded = true
|
||||||
description = stringResource(R.string.pref_backup_desc),
|
)
|
||||||
onClick = {
|
}
|
||||||
backupLauncher.launch("Todo-backup-${SystemUtils.getTime()}.zip")
|
item {
|
||||||
}
|
SettingsItem(
|
||||||
)
|
leadingIconRes = R.drawable.ic_upload,
|
||||||
SettingsItem(
|
title = stringResource(R.string.pref_restore),
|
||||||
leadingIconRes = R.drawable.ic_upload,
|
description = stringResource(R.string.pref_restore_desc),
|
||||||
title = stringResource(R.string.pref_restore),
|
onClick = {
|
||||||
description = stringResource(R.string.pref_restore_desc),
|
restoreLauncher.launch(arrayOf("application/zip"))
|
||||||
onClick = {
|
},
|
||||||
restoreLauncher.launch(arrayOf("application/zip"))
|
bottomRounded = true
|
||||||
}
|
)
|
||||||
)
|
}
|
||||||
}
|
|
||||||
SettingsCategory(stringResource(R.string.pref_category_category_management))
|
item {
|
||||||
Settings {
|
SettingsCategory(stringResource(R.string.pref_category_category_management))
|
||||||
SettingsItem(
|
SettingsItem(
|
||||||
leadingIconRes = R.drawable.ic_category,
|
leadingIconRes = R.drawable.ic_category,
|
||||||
title = stringResource(R.string.pref_category_category_management),
|
title = stringResource(R.string.pref_category_category_management),
|
||||||
description = stringResource(R.string.pref_category_management_desc),
|
description = stringResource(R.string.pref_category_management_desc),
|
||||||
onClick = toCategoryManager
|
onClick = toCategoryManager,
|
||||||
)
|
topRounded = true,
|
||||||
|
bottomRounded = true
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
|
@ -26,13 +25,12 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||||
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.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.IntOffset
|
import androidx.compose.ui.unit.IntOffset
|
||||||
import cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
import cn.super12138.todo.logic.datastore.DataStoreManager
|
import cn.super12138.todo.logic.datastore.DataStoreManager
|
||||||
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.TopAppBarScaffold
|
||||||
import cn.super12138.todo.ui.components.TodoFloatingActionButton
|
import cn.super12138.todo.ui.components.TodoFloatingActionButton
|
||||||
import cn.super12138.todo.ui.pages.settings.components.category.CategoryItem
|
import cn.super12138.todo.ui.pages.settings.components.category.CategoryItem
|
||||||
import cn.super12138.todo.ui.pages.settings.components.category.CategoryPromptDialog
|
import cn.super12138.todo.ui.pages.settings.components.category.CategoryPromptDialog
|
||||||
|
|
@ -45,7 +43,6 @@ fun SettingsDataCategory(
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
// TODO: 本页及其相关组件重组性能检查优化
|
// TODO: 本页及其相关组件重组性能检查优化
|
||||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
|
|
@ -57,10 +54,9 @@ fun SettingsDataCategory(
|
||||||
|
|
||||||
val isExpanded by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }
|
val isExpanded by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }
|
||||||
|
|
||||||
LargeTopAppBarScaffold(
|
TopAppBarScaffold(
|
||||||
title = stringResource(R.string.pref_category_category_management),
|
title = stringResource(R.string.pref_category_category_management),
|
||||||
onBack = onNavigateUp,
|
onBack = onNavigateUp,
|
||||||
scrollBehavior = scrollBehavior,
|
|
||||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
TodoFloatingActionButton(
|
TodoFloatingActionButton(
|
||||||
|
|
@ -73,7 +69,7 @@ fun SettingsDataCategory(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = modifier,
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = listState,
|
state = listState,
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,15 @@
|
||||||
package cn.super12138.todo.ui.pages.settings
|
package cn.super12138.todo.ui.pages.settings
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
import cn.super12138.todo.ui.components.TopAppBarScaffold
|
||||||
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.RoundedScreenContainer
|
||||||
import cn.super12138.todo.ui.pages.settings.components.Settings
|
import cn.super12138.todo.ui.pages.settings.components.SettingsContainer
|
||||||
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
|
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
|
@ -24,26 +19,22 @@ fun SettingsDeveloperOptions(
|
||||||
onNavigateUp: () -> Unit,
|
onNavigateUp: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
TopAppBarScaffold(
|
||||||
LargeTopAppBarScaffold(
|
|
||||||
title = stringResource(R.string.pref_developer_options),
|
title = stringResource(R.string.pref_developer_options),
|
||||||
onBack = onNavigateUp,
|
onBack = onNavigateUp,
|
||||||
scrollBehavior = scrollBehavior,
|
modifier = modifier,
|
||||||
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
Column(
|
RoundedScreenContainer(Modifier.padding(innerPadding)) {
|
||||||
modifier = Modifier
|
SettingsContainer(Modifier.fillMaxSize()) {
|
||||||
.fillMaxSize()
|
item {
|
||||||
.padding(innerPadding)
|
SettingsItem(
|
||||||
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
|
leadingIconRes = R.drawable.ic_padding,
|
||||||
.verticalScroll(rememberScrollState())
|
title = stringResource(R.string.pref_padding),
|
||||||
) {
|
onClick = toPaddingPage,
|
||||||
Settings {
|
topRounded = true,
|
||||||
SettingsItem(
|
bottomRounded = true
|
||||||
leadingIconRes = R.drawable.ic_padding,
|
)
|
||||||
title = stringResource(R.string.pref_padding),
|
}
|
||||||
onClick = toPaddingPage
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,9 @@
|
||||||
package cn.super12138.todo.ui.pages.settings
|
package cn.super12138.todo.ui.pages.settings
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
|
@ -17,17 +13,16 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||||
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.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
import cn.super12138.todo.constants.Constants
|
import cn.super12138.todo.constants.Constants
|
||||||
import cn.super12138.todo.logic.datastore.DataStoreManager
|
import cn.super12138.todo.logic.datastore.DataStoreManager
|
||||||
import cn.super12138.todo.logic.model.SortingMethod
|
import cn.super12138.todo.logic.model.SortingMethod
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
import cn.super12138.todo.ui.components.RoundedScreenContainer
|
||||||
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.TopAppBarScaffold
|
||||||
import cn.super12138.todo.ui.pages.settings.components.Settings
|
|
||||||
import cn.super12138.todo.ui.pages.settings.components.SettingsCategory
|
import cn.super12138.todo.ui.pages.settings.components.SettingsCategory
|
||||||
|
import cn.super12138.todo.ui.pages.settings.components.SettingsContainer
|
||||||
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
|
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
|
||||||
import cn.super12138.todo.ui.pages.settings.components.SettingsPlainBox
|
import cn.super12138.todo.ui.pages.settings.components.SettingsPlainBox
|
||||||
import cn.super12138.todo.ui.pages.settings.components.SettingsRadioDialog
|
import cn.super12138.todo.ui.pages.settings.components.SettingsRadioDialog
|
||||||
|
|
@ -48,76 +43,79 @@ fun SettingsInterface(
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
|
||||||
var showSortingMethodDialog by rememberSaveable { mutableStateOf(false) }
|
var showSortingMethodDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
LargeTopAppBarScaffold(
|
TopAppBarScaffold(
|
||||||
title = stringResource(R.string.pref_interface_interaction),
|
title = stringResource(R.string.pref_interface_interaction),
|
||||||
onBack = onNavigateUp,
|
onBack = onNavigateUp,
|
||||||
scrollBehavior = scrollBehavior,
|
modifier = modifier,
|
||||||
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
Column(
|
RoundedScreenContainer(Modifier.padding(innerPadding)) {
|
||||||
Modifier
|
SettingsContainer(Modifier.fillMaxSize()) {
|
||||||
.fillMaxSize()
|
item {
|
||||||
.padding(innerPadding)
|
SettingsCategory(title = stringResource(R.string.pref_category_todo_list), first = true)
|
||||||
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
|
SwitchSettingsItem(
|
||||||
.verticalScroll(rememberScrollState())
|
leadingIconRes = R.drawable.ic_checklist,
|
||||||
) {
|
title = stringResource(R.string.pref_show_completed),
|
||||||
SettingsCategory(stringResource(R.string.pref_category_todo_list))
|
description = stringResource(R.string.pref_show_completed_desc),
|
||||||
Settings {
|
checked = showCompleted,
|
||||||
SwitchSettingsItem(
|
onCheckedChange = { scope.launch { DataStoreManager.setShowCompleted(it) } },
|
||||||
leadingIconRes = R.drawable.ic_checklist,
|
topRounded = true
|
||||||
title = stringResource(R.string.pref_show_completed),
|
)
|
||||||
description = stringResource(R.string.pref_show_completed_desc),
|
}
|
||||||
checked = showCompleted,
|
item {
|
||||||
onCheckedChange = { scope.launch { DataStoreManager.setShowCompleted(it) } },
|
SettingsItem(
|
||||||
)
|
leadingIconRes = R.drawable.ic_sort,
|
||||||
SettingsItem(
|
title = stringResource(R.string.pref_sorting_method),
|
||||||
leadingIconRes = R.drawable.ic_sort,
|
description = SortingMethod.fromId(sortingMethod).getDisplayName(context),
|
||||||
title = stringResource(R.string.pref_sorting_method),
|
onClick = { showSortingMethodDialog = true },
|
||||||
description = SortingMethod.fromId(sortingMethod).getDisplayName(context),
|
bottomRounded = true
|
||||||
onClick = { showSortingMethodDialog = true }
|
)
|
||||||
)
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
SettingsCategory(stringResource(R.string.pref_category_global))
|
||||||
|
SwitchSettingsItem(
|
||||||
|
checked = secureMode,
|
||||||
|
leadingIconRes = R.drawable.ic_shield,
|
||||||
|
title = stringResource(R.string.pref_secure_mode),
|
||||||
|
description = stringResource(R.string.pref_secure_mode_desc),
|
||||||
|
onCheckedChange = { scope.launch { DataStoreManager.setSecureMode(it) } },
|
||||||
|
topRounded = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
SwitchSettingsItem(
|
||||||
|
checked = hapticFeedback,
|
||||||
|
leadingIconRes = R.drawable.ic_touch_long,
|
||||||
|
title = stringResource(R.string.pref_haptic_feedback),
|
||||||
|
description = stringResource(R.string.pref_haptic_feedback_desc),
|
||||||
|
onCheckedChange = { scope.launch { DataStoreManager.setHapticFeedback(it) } },
|
||||||
|
bottomRounded = true
|
||||||
|
)
|
||||||
|
SettingsPlainBox(stringResource(R.string.pref_haptic_feedback_more_info))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SettingsCategory(stringResource(R.string.pref_category_global))
|
|
||||||
Settings {
|
|
||||||
SwitchSettingsItem(
|
|
||||||
checked = secureMode,
|
|
||||||
leadingIconRes = R.drawable.ic_shield,
|
|
||||||
title = stringResource(R.string.pref_secure_mode),
|
|
||||||
description = stringResource(R.string.pref_secure_mode_desc),
|
|
||||||
onCheckedChange = { scope.launch { DataStoreManager.setSecureMode(it) } }
|
|
||||||
)
|
|
||||||
SwitchSettingsItem(
|
|
||||||
checked = hapticFeedback,
|
|
||||||
leadingIconRes = R.drawable.ic_touch_long,
|
|
||||||
title = stringResource(R.string.pref_haptic_feedback),
|
|
||||||
description = stringResource(R.string.pref_haptic_feedback_desc),
|
|
||||||
onCheckedChange = { scope.launch { DataStoreManager.setHapticFeedback(it) } }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
SettingsPlainBox(stringResource(R.string.pref_haptic_feedback_more_info))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
val sortingList = remember {
|
||||||
|
SortingMethod.entries.map {
|
||||||
val sortingList = remember {
|
SettingsRadioOptions(
|
||||||
SortingMethod.entries.map {
|
id = it.id,
|
||||||
SettingsRadioOptions(
|
text = it.getDisplayName(context)
|
||||||
id = it.id,
|
)
|
||||||
text = it.getDisplayName(context)
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
SettingsRadioDialog(
|
||||||
|
visible = showSortingMethodDialog,
|
||||||
|
title = stringResource(R.string.pref_sorting_method),
|
||||||
|
currentOptions = SettingsRadioOptions(
|
||||||
|
id = sortingMethod,
|
||||||
|
text = SortingMethod.fromId(sortingMethod).getDisplayName(context)
|
||||||
|
),
|
||||||
|
options = sortingList,
|
||||||
|
onSelect = { scope.launch { DataStoreManager.setSortingMethod(it) } },
|
||||||
|
onDismiss = { showSortingMethodDialog = false }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
SettingsRadioDialog(
|
|
||||||
visible = showSortingMethodDialog,
|
|
||||||
title = stringResource(R.string.pref_sorting_method),
|
|
||||||
currentOptions = SettingsRadioOptions(
|
|
||||||
id = sortingMethod,
|
|
||||||
text = SortingMethod.fromId(sortingMethod).getDisplayName(context)
|
|
||||||
),
|
|
||||||
options = sortingList,
|
|
||||||
onSelect = { scope.launch { DataStoreManager.setSortingMethod(it) } },
|
|
||||||
onDismiss = { showSortingMethodDialog = false }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,21 +1,16 @@
|
||||||
package cn.super12138.todo.ui.pages.settings
|
package cn.super12138.todo.ui.pages.settings
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
import cn.super12138.todo.ui.components.TopAppBarScaffold
|
||||||
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
|
import cn.super12138.todo.ui.components.RoundedScreenContainer
|
||||||
import cn.super12138.todo.ui.pages.settings.components.Settings
|
import cn.super12138.todo.ui.pages.settings.components.SettingsContainer
|
||||||
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
|
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
|
|
@ -28,46 +23,50 @@ fun SettingsMain(
|
||||||
onNavigateUp: () -> Unit,
|
onNavigateUp: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
TopAppBarScaffold(
|
||||||
LargeTopAppBarScaffold(
|
|
||||||
title = stringResource(R.string.page_settings),
|
title = stringResource(R.string.page_settings),
|
||||||
scrollBehavior = scrollBehavior,
|
|
||||||
onBack = onNavigateUp,
|
onBack = onNavigateUp,
|
||||||
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection)
|
modifier = modifier
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
Column(
|
RoundedScreenContainer(Modifier.padding(innerPadding)) {
|
||||||
Modifier
|
SettingsContainer(Modifier.fillMaxSize()) {
|
||||||
.fillMaxSize()
|
item {
|
||||||
.padding(innerPadding)
|
SettingsItem(
|
||||||
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
|
leadingIconRes = R.drawable.ic_palette,
|
||||||
.verticalScroll(rememberScrollState())
|
title = stringResource(R.string.pref_appearance),
|
||||||
) {
|
description = stringResource(R.string.pref_appearance_desc),
|
||||||
Settings {
|
onClick = toAppearancePage,
|
||||||
SettingsItem(
|
topRounded = true
|
||||||
leadingIconRes = R.drawable.ic_palette,
|
)
|
||||||
title = stringResource(R.string.pref_appearance),
|
}
|
||||||
description = stringResource(R.string.pref_appearance_desc),
|
|
||||||
onClick = toAppearancePage
|
|
||||||
)
|
|
||||||
SettingsItem(
|
|
||||||
leadingIconRes = R.drawable.ic_view_comfy,
|
|
||||||
title = stringResource(R.string.pref_interface_interaction),
|
|
||||||
description = stringResource(R.string.pref_interface_interaction_desc),
|
|
||||||
onClick = toInterfacePage
|
|
||||||
)
|
|
||||||
SettingsItem(
|
|
||||||
leadingIconRes = R.drawable.ic_dns,
|
|
||||||
title = stringResource(R.string.pref_data),
|
|
||||||
description = stringResource(R.string.pref_data_desc),
|
|
||||||
onClick = toDataPage
|
|
||||||
)
|
|
||||||
SettingsItem(
|
|
||||||
leadingIconRes = R.drawable.ic_info,
|
|
||||||
title = stringResource(R.string.pref_about),
|
|
||||||
description = stringResource(R.string.pref_about_desc),
|
|
||||||
onClick = toAboutPage
|
|
||||||
)
|
|
||||||
|
|
||||||
|
item {
|
||||||
|
SettingsItem(
|
||||||
|
leadingIconRes = R.drawable.ic_view_comfy,
|
||||||
|
title = stringResource(R.string.pref_interface_interaction),
|
||||||
|
description = stringResource(R.string.pref_interface_interaction_desc),
|
||||||
|
onClick = toInterfacePage
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
SettingsItem(
|
||||||
|
leadingIconRes = R.drawable.ic_dns,
|
||||||
|
title = stringResource(R.string.pref_data),
|
||||||
|
description = stringResource(R.string.pref_data_desc),
|
||||||
|
onClick = toDataPage
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
item {
|
||||||
|
SettingsItem(
|
||||||
|
leadingIconRes = R.drawable.ic_info,
|
||||||
|
title = stringResource(R.string.pref_about),
|
||||||
|
description = stringResource(R.string.pref_about_desc),
|
||||||
|
onClick = toAboutPage,
|
||||||
|
bottomRounded = true
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.CornerBasedShape
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|
@ -20,19 +21,15 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.drawWithContent
|
import androidx.compose.ui.draw.drawWithContent
|
||||||
import androidx.compose.ui.geometry.Offset
|
|
||||||
import androidx.compose.ui.geometry.Size
|
|
||||||
import androidx.compose.ui.graphics.BlendMode
|
|
||||||
import androidx.compose.ui.graphics.Brush
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.CompositingStrategy
|
import androidx.compose.ui.graphics.CompositingStrategy
|
||||||
import androidx.compose.ui.graphics.Shape
|
|
||||||
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
|
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
import cn.super12138.todo.ui.TodoDefaults
|
||||||
|
import cn.super12138.todo.utils.drawFadedEdge
|
||||||
|
import cn.super12138.todo.utils.getPartialRoundedShape
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RowSettingsItem(
|
fun RowSettingsItem(
|
||||||
|
|
@ -41,13 +38,14 @@ fun RowSettingsItem(
|
||||||
title: String,
|
title: String,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
trailingContent: (@Composable () -> Unit)? = null,
|
trailingContent: (@Composable () -> Unit)? = null,
|
||||||
shape: Shape = MaterialTheme.shapes.small,
|
background: Color = TodoDefaults.ContainerColor,
|
||||||
background: Color = MaterialTheme.colorScheme.surfaceContainerHigh,
|
|
||||||
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
|
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
|
||||||
verticalAlignment: Alignment.Vertical = Alignment.Top,
|
verticalAlignment: Alignment.Vertical = Alignment.Top,
|
||||||
scrollState: ScrollState = rememberScrollState(),
|
scrollState: ScrollState = rememberScrollState(),
|
||||||
fadedEdgeWidth: Dp,
|
fadedEdgeWidth: Dp,
|
||||||
maskColor: Color = MaterialTheme.colorScheme.background,
|
maskColor: Color = TodoDefaults.ContainerColor,
|
||||||
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false,
|
||||||
content: @Composable RowScope.() -> Unit
|
content: @Composable RowScope.() -> Unit
|
||||||
) {
|
) {
|
||||||
MoreContentSettingsItem(
|
MoreContentSettingsItem(
|
||||||
|
|
@ -55,8 +53,9 @@ fun RowSettingsItem(
|
||||||
title = title,
|
title = title,
|
||||||
description = description,
|
description = description,
|
||||||
trailingContent = trailingContent,
|
trailingContent = trailingContent,
|
||||||
shape = shape,
|
|
||||||
background = background,
|
background = background,
|
||||||
|
topRounded = topRounded,
|
||||||
|
bottomRounded = bottomRounded,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
|
|
@ -94,12 +93,13 @@ fun LazyRowSettingsItem(
|
||||||
title: String,
|
title: String,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
trailingContent: (@Composable () -> Unit)? = null,
|
trailingContent: (@Composable () -> Unit)? = null,
|
||||||
shape: Shape = MaterialTheme.shapes.small,
|
background: Color = TodoDefaults.ContainerColor,
|
||||||
background: Color = MaterialTheme.colorScheme.surfaceContainerHigh,
|
|
||||||
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
|
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
|
||||||
verticalAlignment: Alignment.Vertical = Alignment.Top,
|
verticalAlignment: Alignment.Vertical = Alignment.Top,
|
||||||
fadedEdgeWidth: Dp,
|
fadedEdgeWidth: Dp,
|
||||||
maskColor: Color = MaterialTheme.colorScheme.background,
|
maskColor: Color = TodoDefaults.ContainerColor,
|
||||||
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false,
|
||||||
content: LazyListScope.() -> Unit
|
content: LazyListScope.() -> Unit
|
||||||
) {
|
) {
|
||||||
MoreContentSettingsItem(
|
MoreContentSettingsItem(
|
||||||
|
|
@ -107,7 +107,8 @@ fun LazyRowSettingsItem(
|
||||||
title = title,
|
title = title,
|
||||||
description = description,
|
description = description,
|
||||||
trailingContent = trailingContent,
|
trailingContent = trailingContent,
|
||||||
shape = shape,
|
topRounded = topRounded,
|
||||||
|
bottomRounded = bottomRounded,
|
||||||
background = background,
|
background = background,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) {
|
) {
|
||||||
|
|
@ -145,15 +146,18 @@ fun MoreContentSettingsItem(
|
||||||
title: String,
|
title: String,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
trailingContent: (@Composable () -> Unit)? = null,
|
trailingContent: (@Composable () -> Unit)? = null,
|
||||||
shape: Shape = MaterialTheme.shapes.small,
|
background: Color = TodoDefaults.ContainerColor,
|
||||||
background: Color = MaterialTheme.colorScheme.surfaceContainerHigh,
|
shape: CornerBasedShape = TodoDefaults.SettingsItemDefaultShape,
|
||||||
|
roundedShape: CornerBasedShape = TodoDefaults.SettingsItemRoundedShape,
|
||||||
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false,
|
||||||
content: @Composable () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.wrapContentHeight()
|
.wrapContentHeight()
|
||||||
.clip(shape)
|
.clip(shape.getPartialRoundedShape(topRounded, bottomRounded, roundedShape))
|
||||||
.background(background)
|
.background(background)
|
||||||
.padding(
|
.padding(
|
||||||
horizontal = TodoDefaults.settingsItemHorizontalPadding,
|
horizontal = TodoDefaults.settingsItemHorizontalPadding,
|
||||||
|
|
@ -195,22 +199,3 @@ fun MoreContentSettingsItem(
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ContentDrawScope.drawFadedEdge(
|
|
||||||
edgeWidth: Dp,
|
|
||||||
maskColor: Color,
|
|
||||||
leftEdge: Boolean
|
|
||||||
) {
|
|
||||||
val edgeWidthPx = edgeWidth.toPx()
|
|
||||||
drawRect(
|
|
||||||
topLeft = Offset(if (leftEdge) 0f else size.width - edgeWidthPx, 0f),
|
|
||||||
size = Size(edgeWidthPx, size.height),
|
|
||||||
brush =
|
|
||||||
Brush.horizontalGradient(
|
|
||||||
colors = listOf(Color.Transparent, maskColor),
|
|
||||||
startX = if (leftEdge) 0f else size.width,
|
|
||||||
endX = if (leftEdge) edgeWidthPx else size.width - edgeWidthPx
|
|
||||||
),
|
|
||||||
blendMode = BlendMode.DstIn
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -8,20 +8,23 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
import cn.super12138.todo.ui.TodoDefaults
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsCategory(
|
fun SettingsCategory(
|
||||||
title: String,
|
title: String,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier,
|
||||||
|
first: Boolean = false,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(
|
.padding(
|
||||||
top = TodoDefaults.settingsItemVerticalPadding / 2,
|
top = if (first) 0.dp else TodoDefaults.settingsItemVerticalPadding,
|
||||||
start = TodoDefaults.settingsItemHorizontalPadding,
|
start = TodoDefaults.settingsItemHorizontalPadding / 2,
|
||||||
end = TodoDefaults.settingsItemHorizontalPadding,
|
end = TodoDefaults.settingsItemHorizontalPadding / 2,
|
||||||
|
bottom = TodoDefaults.settingsItemVerticalPadding / 2
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,35 @@
|
||||||
package cn.super12138.todo.ui.pages.settings.components
|
package cn.super12138.todo.ui.pages.settings.components
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
import cn.super12138.todo.ui.TodoDefaults
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Settings(
|
fun SettingsContainer(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
content: @Composable ColumnScope.() -> Unit,
|
state: LazyListState = rememberLazyListState(),
|
||||||
|
content: LazyListScope.() -> Unit,
|
||||||
) {
|
) {
|
||||||
Column(
|
LazyColumn(
|
||||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
verticalArrangement = Arrangement.spacedBy(TodoDefaults.settingsItemPadding),
|
||||||
|
state = state,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.padding(vertical = TodoDefaults.screenVerticalPadding)
|
) {
|
||||||
.clip(MaterialTheme.shapes.extraLarge),
|
item {
|
||||||
content = content
|
Spacer(modifier = Modifier.size(TodoDefaults.settingsItemVerticalPadding))
|
||||||
)
|
}
|
||||||
|
|
||||||
|
content()
|
||||||
|
|
||||||
|
item {
|
||||||
|
Spacer(modifier = Modifier.size(TodoDefaults.settingsItemVerticalPadding))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -76,7 +76,7 @@ fun RadioItem(
|
||||||
modifier
|
modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(56.dp)
|
.height(56.dp)
|
||||||
.clip(MaterialTheme.shapes.small)
|
.clip(TodoDefaults.SettingsItemDefaultShape)
|
||||||
.background(MaterialTheme.colorScheme.surfaceContainerHighest)
|
.background(MaterialTheme.colorScheme.surfaceContainerHighest)
|
||||||
.selectable(
|
.selectable(
|
||||||
selected = selected,
|
selected = selected,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.wrapContentHeight
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
|
import androidx.compose.foundation.shape.CornerBasedShape
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
|
@ -17,7 +18,6 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.Shape
|
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
|
|
@ -26,6 +26,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import cn.super12138.todo.ui.TodoDefaults
|
import cn.super12138.todo.ui.TodoDefaults
|
||||||
import cn.super12138.todo.utils.VibrationUtils
|
import cn.super12138.todo.utils.VibrationUtils
|
||||||
|
import cn.super12138.todo.utils.getPartialRoundedShape
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsItem(
|
fun SettingsItem(
|
||||||
|
|
@ -33,6 +34,8 @@ fun SettingsItem(
|
||||||
@DrawableRes leadingIconRes: Int,
|
@DrawableRes leadingIconRes: Int,
|
||||||
title: String,
|
title: String,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false,
|
||||||
enableClick: Boolean = true,
|
enableClick: Boolean = true,
|
||||||
onClick: () -> Unit = {}
|
onClick: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
|
|
@ -41,6 +44,8 @@ fun SettingsItem(
|
||||||
title = title,
|
title = title,
|
||||||
description = description,
|
description = description,
|
||||||
trailingContent = null,
|
trailingContent = null,
|
||||||
|
topRounded = topRounded,
|
||||||
|
bottomRounded = bottomRounded,
|
||||||
enableClick = enableClick,
|
enableClick = enableClick,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
|
|
@ -53,6 +58,8 @@ fun SettingsItem(
|
||||||
leadingIcon: ImageVector? = null,
|
leadingIcon: ImageVector? = null,
|
||||||
title: String,
|
title: String,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false,
|
||||||
enableClick: Boolean = true,
|
enableClick: Boolean = true,
|
||||||
onClick: () -> Unit = {}
|
onClick: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
|
|
@ -61,6 +68,8 @@ fun SettingsItem(
|
||||||
title = title,
|
title = title,
|
||||||
description = description,
|
description = description,
|
||||||
trailingContent = null,
|
trailingContent = null,
|
||||||
|
topRounded = topRounded,
|
||||||
|
bottomRounded = bottomRounded,
|
||||||
enableClick = enableClick,
|
enableClick = enableClick,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
|
|
@ -74,7 +83,9 @@ fun SettingsItem(
|
||||||
title: String,
|
title: String,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
trailingContent: (@Composable () -> Unit)? = null,
|
trailingContent: (@Composable () -> Unit)? = null,
|
||||||
background: Color = MaterialTheme.colorScheme.surfaceContainerHigh,
|
background: Color = TodoDefaults.ContainerColor,
|
||||||
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false,
|
||||||
enableClick: Boolean = true,
|
enableClick: Boolean = true,
|
||||||
onClick: () -> Unit = {}
|
onClick: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
|
|
@ -93,6 +104,8 @@ fun SettingsItem(
|
||||||
description = description,
|
description = description,
|
||||||
trailingContent = trailingContent,
|
trailingContent = trailingContent,
|
||||||
background = background,
|
background = background,
|
||||||
|
topRounded = topRounded,
|
||||||
|
bottomRounded = bottomRounded,
|
||||||
enableClick = enableClick,
|
enableClick = enableClick,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
|
|
@ -106,7 +119,9 @@ fun SettingsItem(
|
||||||
title: String,
|
title: String,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
trailingContent: (@Composable () -> Unit)? = null,
|
trailingContent: (@Composable () -> Unit)? = null,
|
||||||
background: Color = MaterialTheme.colorScheme.surfaceContainerHigh,
|
background: Color = TodoDefaults.ContainerColor,
|
||||||
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false,
|
||||||
enableClick: Boolean = true,
|
enableClick: Boolean = true,
|
||||||
onClick: () -> Unit = {}
|
onClick: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
|
|
@ -125,6 +140,8 @@ fun SettingsItem(
|
||||||
description = description,
|
description = description,
|
||||||
trailingContent = trailingContent,
|
trailingContent = trailingContent,
|
||||||
background = background,
|
background = background,
|
||||||
|
topRounded = topRounded,
|
||||||
|
bottomRounded = bottomRounded,
|
||||||
enableClick = enableClick,
|
enableClick = enableClick,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
|
|
@ -139,8 +156,11 @@ fun SettingsItem(
|
||||||
title: String,
|
title: String,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
trailingContent: (@Composable () -> Unit)? = null,
|
trailingContent: (@Composable () -> Unit)? = null,
|
||||||
shape: Shape = MaterialTheme.shapes.small,
|
background: Color = TodoDefaults.ContainerColor,
|
||||||
background: Color = MaterialTheme.colorScheme.surfaceContainerHigh,
|
shape: CornerBasedShape = TodoDefaults.SettingsItemDefaultShape,
|
||||||
|
roundedShape: CornerBasedShape = TodoDefaults.SettingsItemRoundedShape,
|
||||||
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false,
|
||||||
enableClick: Boolean = true,
|
enableClick: Boolean = true,
|
||||||
onClick: () -> Unit = {},
|
onClick: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
|
|
@ -149,7 +169,7 @@ fun SettingsItem(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.wrapContentHeight()
|
.wrapContentHeight()
|
||||||
.clip(shape)
|
.clip(shape.getPartialRoundedShape(topRounded, bottomRounded, roundedShape))
|
||||||
.clickable(
|
.clickable(
|
||||||
enabled = enableClick,
|
enabled = enableClick,
|
||||||
onClick = {
|
onClick = {
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,8 @@ fun SettingsPlainBox(
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.wrapContentHeight()
|
.wrapContentHeight()
|
||||||
.padding(
|
.padding(
|
||||||
start = TodoDefaults.settingsItemHorizontalPadding,
|
vertical = TodoDefaults.settingsItemVerticalPadding,
|
||||||
end = TodoDefaults.settingsItemHorizontalPadding,
|
horizontal = TodoDefaults.settingsItemHorizontalPadding / 2
|
||||||
bottom = TodoDefaults.settingsItemVerticalPadding
|
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,11 @@ fun SwitchSettingsItem(
|
||||||
@DrawableRes leadingIconRes: Int,
|
@DrawableRes leadingIconRes: Int,
|
||||||
title: String,
|
title: String,
|
||||||
description: String? = null,
|
description: String? = null,
|
||||||
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false,
|
||||||
checked: Boolean,
|
checked: Boolean,
|
||||||
onCheckedChange: (Boolean) -> Unit
|
onCheckedChange: (Boolean) -> Unit
|
||||||
) {
|
) {
|
||||||
val view = LocalView.current
|
|
||||||
SettingsItem(
|
SettingsItem(
|
||||||
leadingIcon = painterResource(leadingIconRes),
|
leadingIcon = painterResource(leadingIconRes),
|
||||||
title = title,
|
title = title,
|
||||||
|
|
@ -28,14 +29,13 @@ fun SwitchSettingsItem(
|
||||||
trailingContent = {
|
trailingContent = {
|
||||||
Switch(
|
Switch(
|
||||||
checked = checked,
|
checked = checked,
|
||||||
onCheckedChange = {
|
onCheckedChange = null,
|
||||||
VibrationUtils.performHapticFeedback(view)
|
|
||||||
onCheckedChange(it)
|
|
||||||
},
|
|
||||||
modifier = Modifier.padding(start = TodoDefaults.settingsItemHorizontalPadding / 2)
|
modifier = Modifier.padding(start = TodoDefaults.settingsItemHorizontalPadding / 2)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick = { onCheckedChange(!checked) },
|
onClick = { onCheckedChange(!checked) },
|
||||||
|
topRounded = topRounded,
|
||||||
|
bottomRounded = bottomRounded,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,15 +35,19 @@ import cn.super12138.todo.utils.VibrationUtils
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ContrastPicker(
|
fun ContrastPicker(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
currentContrast: ContrastLevel,
|
currentContrast: ContrastLevel,
|
||||||
onContrastChange: (ContrastLevel) -> Unit,
|
onContrastChange: (ContrastLevel) -> Unit,
|
||||||
modifier: Modifier = Modifier
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false
|
||||||
) {
|
) {
|
||||||
val view = LocalView.current
|
val view = LocalView.current
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
MoreContentSettingsItem(
|
MoreContentSettingsItem(
|
||||||
title = stringResource(R.string.pref_contrast_level),
|
title = stringResource(R.string.pref_contrast_level),
|
||||||
description = stringResource(R.string.pref_contrast_level_desc),
|
description = stringResource(R.string.pref_contrast_level_desc),
|
||||||
|
topRounded = topRounded,
|
||||||
|
bottomRounded = bottomRounded,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) {
|
) {
|
||||||
val contrastLevelName =
|
val contrastLevelName =
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,17 @@ import androidx.compose.ui.platform.LocalContext
|
||||||
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 cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
|
import cn.super12138.todo.ui.TodoDefaults
|
||||||
import cn.super12138.todo.ui.pages.settings.components.LazyRowSettingsItem
|
import cn.super12138.todo.ui.pages.settings.components.LazyRowSettingsItem
|
||||||
import cn.super12138.todo.ui.theme.DarkMode
|
import cn.super12138.todo.ui.theme.DarkMode
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DarkModePicker(
|
fun DarkModePicker(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
currentDarkMode: () -> DarkMode,
|
currentDarkMode: () -> DarkMode,
|
||||||
onDarkModeChange: (darkMode: DarkMode) -> Unit,
|
onDarkModeChange: (darkMode: DarkMode) -> Unit,
|
||||||
modifier: Modifier = Modifier
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val isInDarkTheme = isSystemInDarkTheme()
|
val isInDarkTheme = isSystemInDarkTheme()
|
||||||
|
|
@ -31,7 +34,9 @@ fun DarkModePicker(
|
||||||
title = stringResource(R.string.pref_dark_mode),
|
title = stringResource(R.string.pref_dark_mode),
|
||||||
description = stringResource(R.string.pref_dark_mode_desc),
|
description = stringResource(R.string.pref_dark_mode_desc),
|
||||||
horizontalArrangement = Arrangement.spacedBy(5.dp),
|
horizontalArrangement = Arrangement.spacedBy(5.dp),
|
||||||
fadedEdgeWidth = 8.dp,
|
fadedEdgeWidth = TodoDefaults.fadedEdgeWidth,
|
||||||
|
topRounded = topRounded,
|
||||||
|
bottomRounded = bottomRounded,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) {
|
) {
|
||||||
items(items = darkModeList, key = { it.id }) {
|
items(items = darkModeList, key = { it.id }) {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import androidx.compose.ui.Modifier
|
||||||
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 cn.super12138.todo.R
|
import cn.super12138.todo.R
|
||||||
|
import cn.super12138.todo.ui.TodoDefaults
|
||||||
import cn.super12138.todo.ui.pages.settings.components.LazyRowSettingsItem
|
import cn.super12138.todo.ui.pages.settings.components.LazyRowSettingsItem
|
||||||
import cn.super12138.todo.ui.theme.ContrastLevel
|
import cn.super12138.todo.ui.theme.ContrastLevel
|
||||||
import cn.super12138.todo.ui.theme.DarkMode
|
import cn.super12138.todo.ui.theme.DarkMode
|
||||||
|
|
@ -18,12 +19,14 @@ import cn.super12138.todo.ui.theme.PaletteStyle
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun PalettePicker(
|
fun PalettePicker(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
currentPalette: () -> PaletteStyle,
|
currentPalette: () -> PaletteStyle,
|
||||||
onPaletteChange: (paletteStyle: PaletteStyle) -> Unit,
|
onPaletteChange: (paletteStyle: PaletteStyle) -> Unit,
|
||||||
isDynamicColor: Boolean,
|
isDynamicColor: Boolean,
|
||||||
isDarkMode: DarkMode,
|
isDarkMode: DarkMode,
|
||||||
contrastLevel: ContrastLevel,
|
contrastLevel: ContrastLevel,
|
||||||
modifier: Modifier = Modifier
|
topRounded: Boolean = false,
|
||||||
|
bottomRounded: Boolean = false
|
||||||
) {
|
) {
|
||||||
val paletteOptions = remember { PaletteStyle.entries.toList() }
|
val paletteOptions = remember { PaletteStyle.entries.toList() }
|
||||||
|
|
||||||
|
|
@ -31,7 +34,9 @@ fun PalettePicker(
|
||||||
title = stringResource(R.string.pref_palette_style),
|
title = stringResource(R.string.pref_palette_style),
|
||||||
description = stringResource(R.string.pref_palette_style_desc),
|
description = stringResource(R.string.pref_palette_style_desc),
|
||||||
horizontalArrangement = Arrangement.spacedBy(5.dp),
|
horizontalArrangement = Arrangement.spacedBy(5.dp),
|
||||||
fadedEdgeWidth = 8.dp,
|
fadedEdgeWidth = TodoDefaults.fadedEdgeWidth,
|
||||||
|
topRounded = topRounded,
|
||||||
|
bottomRounded = bottomRounded,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) {
|
) {
|
||||||
items(items = paletteOptions, key = { it.id }) {
|
items(items = paletteOptions, key = { it.id }) {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,16 @@
|
||||||
package cn.super12138.todo.utils
|
package cn.super12138.todo.utils
|
||||||
|
|
||||||
|
import androidx.compose.foundation.shape.CornerBasedShape
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.geometry.Size
|
||||||
|
import androidx.compose.ui.graphics.BlendMode
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
import cn.super12138.todo.logic.model.Priority
|
import cn.super12138.todo.logic.model.Priority
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -15,4 +22,37 @@ fun Priority.containerColor(): Color =
|
||||||
Priority.Default -> MaterialTheme.colorScheme.secondary
|
Priority.Default -> MaterialTheme.colorScheme.secondary
|
||||||
Priority.Important -> MaterialTheme.colorScheme.tertiary
|
Priority.Important -> MaterialTheme.colorScheme.tertiary
|
||||||
Priority.Urgent -> MaterialTheme.colorScheme.error
|
Priority.Urgent -> MaterialTheme.colorScheme.error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CornerBasedShape.getPartialRoundedShape(
|
||||||
|
topRounded: Boolean,
|
||||||
|
bottomRounded: Boolean,
|
||||||
|
roundedShape: CornerBasedShape
|
||||||
|
): CornerBasedShape =
|
||||||
|
this.copy(
|
||||||
|
topStart = if (topRounded) roundedShape.topStart else this.topStart,
|
||||||
|
topEnd = if (topRounded) roundedShape.topEnd else this.topEnd,
|
||||||
|
bottomEnd = if (bottomRounded) roundedShape.bottomEnd else this.bottomEnd,
|
||||||
|
bottomStart = if (bottomRounded) roundedShape.bottomStart else this.bottomStart,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
fun ContentDrawScope.drawFadedEdge(
|
||||||
|
edgeWidth: Dp,
|
||||||
|
maskColor: Color,
|
||||||
|
leftEdge: Boolean
|
||||||
|
) {
|
||||||
|
val edgeWidthPx = edgeWidth.toPx()
|
||||||
|
drawRect(
|
||||||
|
topLeft = Offset(if (leftEdge) 0f else size.width - edgeWidthPx, 0f),
|
||||||
|
size = Size(edgeWidthPx, size.height),
|
||||||
|
brush =
|
||||||
|
Brush.horizontalGradient(
|
||||||
|
colors = listOf(Color.Transparent, maskColor),
|
||||||
|
startX = if (leftEdge) 0f else size.width,
|
||||||
|
endX = if (leftEdge) edgeWidthPx else size.width - edgeWidthPx
|
||||||
|
),
|
||||||
|
blendMode = BlendMode.DstIn
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue