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