chore: 字符串国际化 & 代码格式化和优化

This commit is contained in:
Super12138 2026-02-08 13:16:26 +08:00
parent b585565459
commit 9617f8d0aa
16 changed files with 94 additions and 47 deletions

View file

@ -38,7 +38,7 @@ android {
applicationId = "cn.super12138.todo" applicationId = "cn.super12138.todo"
minSdk = 24 minSdk = 24
targetSdk = 36 targetSdk = 36
versionCode = 976 versionCode = 978
versionName = "2.3.3" versionName = "2.3.3"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

View file

@ -52,7 +52,7 @@ fun TodoDueDateChooser(
TextField( TextField(
value = value.toLocalDateString(), value = value.toLocalDateString(),
onValueChange = {}, onValueChange = {},
label = { Text("截止日期(可选)") }, label = { Text(stringResource(R.string.label_due_date)) },
readOnly = true, readOnly = true,
interactionSource = interactionSource, interactionSource = interactionSource,
modifier = modifier modifier = modifier

View file

@ -20,7 +20,7 @@ import cn.super12138.todo.ui.components.TopAppBarScaffold
import cn.super12138.todo.ui.pages.overview.components.RoundedCornerCardLarge import cn.super12138.todo.ui.pages.overview.components.RoundedCornerCardLarge
import cn.super12138.todo.ui.pages.overview.components.UpcomingTaskCard import cn.super12138.todo.ui.pages.overview.components.UpcomingTaskCard
import cn.super12138.todo.ui.viewmodels.MainViewModel import cn.super12138.todo.ui.viewmodels.MainViewModel
import java.util.Calendar import cn.super12138.todo.utils.SystemUtils
@OptIn(ExperimentalMaterial3ExpressiveApi::class) @OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable @Composable
@ -28,25 +28,16 @@ fun OverviewPage(
viewModel: MainViewModel, viewModel: MainViewModel,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val today = Calendar.getInstance().apply {
// 将时间设置为当天的开始00:00:00.000
// 兼容API24
set(Calendar.HOUR_OF_DAY, 0)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}
val toDos by viewModel.sortedTodos.collectAsState(initial = emptyList()) val toDos by viewModel.sortedTodos.collectAsState(initial = emptyList())
val totalTasks by remember { derivedStateOf { toDos.size } } val totalTasks by remember { derivedStateOf { toDos.size } }
val completedTasks by remember { derivedStateOf { toDos.count { it.isCompleted } } } val completedTasks by remember { derivedStateOf { toDos.count { it.isCompleted } } }
val nextWeekTodo by remember { val nextWeekTodo by remember {
derivedStateOf { derivedStateOf {
val now = System.currentTimeMillis() val today = SystemUtils.getToday()
val weekFromNow = now + 7L * 24 * 60 * 60 * 1000 val weekFromToday = today + 7L * 24 * 60 * 60 * 1000
toDos.filter { todo -> toDos.filter { todo ->
val due = todo.dueDate ?: return@filter false val due = todo.dueDate ?: return@filter false
due >= today.timeInMillis && due < weekFromNow due in today..<weekFromToday
} }
} }
} }
@ -66,14 +57,14 @@ fun OverviewPage(
item { item {
RoundedCornerCardLarge( RoundedCornerCardLarge(
iconRes = R.drawable.ic_apps, iconRes = R.drawable.ic_apps,
title = "总任务", title = stringResource(R.string.title_all_task),
count = totalTasks count = totalTasks
) )
} }
item { item {
RoundedCornerCardLarge( RoundedCornerCardLarge(
iconRes = R.drawable.ic_check_circle, iconRes = R.drawable.ic_check_circle,
title = "已完成", title = stringResource(R.string.title_completed_task),
count = completedTasks, count = completedTasks,
containerColor = MaterialTheme.colorScheme.secondaryContainer containerColor = MaterialTheme.colorScheme.secondaryContainer
) )
@ -81,7 +72,7 @@ fun OverviewPage(
item { item {
RoundedCornerCardLarge( RoundedCornerCardLarge(
iconRes = R.drawable.ic_pending, iconRes = R.drawable.ic_pending,
title = "未完成", title = stringResource(R.string.title_pending_task),
count = totalTasks - completedTasks, count = totalTasks - completedTasks,
containerColor = MaterialTheme.colorScheme.errorContainer // tertiaryContainer containerColor = MaterialTheme.colorScheme.errorContainer // tertiaryContainer
) )

View file

@ -81,7 +81,7 @@ fun RoundedCornerCardLarge(
) { ) {
Text( Text(
text = title, text = title,
style = MaterialTheme.typography.bodyMedium style = MaterialTheme.typography.titleMedium
) )
BasicText( BasicText(

View file

@ -18,6 +18,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
@ -79,6 +80,8 @@ fun UpcomingTaskItem(
dueDate: Long?, dueDate: Long?,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val context = LocalContext.current
Column( Column(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
@ -100,7 +103,7 @@ fun UpcomingTaskItem(
) )
Text( Text(
text = dueDate.toRelativeTimeString(), text = dueDate.toRelativeTimeString(context),
style = MaterialTheme.typography.labelMedium.copy( style = MaterialTheme.typography.labelMedium.copy(
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold

View file

@ -41,6 +41,19 @@ object SystemUtils {
return sdf.format(currentTime) return sdf.format(currentTime)
} }
/**
* 获取当天的时间戳
*/
fun getToday(): Long = Calendar.getInstance().apply {
// 将时间设置为当天的开始00:00:00.000
// 兼容API24
set(Calendar.HOUR_OF_DAY, 0)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}.timeInMillis
} }
fun ComponentActivity.configureEdgeToEdge() { fun ComponentActivity.configureEdgeToEdge() {

View file

@ -1,5 +1,6 @@
package cn.super12138.todo.utils package cn.super12138.todo.utils
import android.content.Context
import androidx.compose.foundation.shape.CornerBasedShape 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
@ -11,6 +12,7 @@ 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.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import cn.super12138.todo.R
import cn.super12138.todo.logic.model.Priority import cn.super12138.todo.logic.model.Priority
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
@ -88,8 +90,14 @@ fun Long?.toLocalDateString(): String {
return format.format(date) return format.format(date)
} }
// 未来相对时间如“3天后”的实现最小层级为天 /**
fun Long?.toRelativeTimeString(): String { * 将时间戳转换为相对时间字符串
*
* @receiver Long? 时间戳单位为毫秒 null
* @param context 上下文用于获取字符串资源
* @return String 格式化后的相对时间字符串如果为传入参数为null则返回空字符串反之根据时间差返回相应的字符串今天明天3天后2周后1个月后1年后
*/
fun Long?.toRelativeTimeString(context: Context): String {
if (this == null) return "" if (this == null) return ""
val today = Calendar.getInstance().apply { val today = Calendar.getInstance().apply {
// 将时间设置为当天的开始00:00:00.000 // 将时间设置为当天的开始00:00:00.000
@ -103,12 +111,24 @@ fun Long?.toRelativeTimeString(): String {
return diff.toComponents { days, _, _, _, _ -> return diff.toComponents { days, _, _, _, _ ->
when { when {
days.days == 1.days -> "明天" days.days == 1.days -> context.getString(R.string.time_tomorrow)
days.days > 1.days && days.days < 7.days -> "${days}天后" days.days > 1.days && days.days < 7.days -> context.getString(
days.days in 7.days..<30.days -> "${days / 7}周后" R.string.time_in_days,
days.days in 30.days..<365.days -> "${days / 30}个月后" days.toInt()
days.days >= 365.days -> "${days / 365}年后" )
else -> "今天"
days.days in 7.days..<30.days -> context.getString(
R.string.time_in_weeks,
(days / 7).toInt()
)
days.days in 30.days..<365.days -> context.getString(
R.string.time_in_months,
(days / 30).toInt()
)
days.days >= 365.days -> context.getString(R.string.time_in_years, (days / 365).toInt())
else -> context.getString(R.string.time_today)
} }
} }
} }

View file

@ -119,4 +119,14 @@
<string name="tip_short_category">尽量使用简短的分类名称</string> <string name="tip_short_category">尽量使用简短的分类名称</string>
<string name="action_clear">清除</string> <string name="action_clear">清除</string>
<string name="title_upcoming_task">临近的任务</string> <string name="title_upcoming_task">临近的任务</string>
<string name="time_today">今天</string>
<string name="time_tomorrow">明天</string>
<string name="time_in_days">%d 天后</string>
<string name="time_in_weeks">%d 周后</string>
<string name="time_in_months">%d 个月后</string>
<string name="time_in_years">%d 年后</string>
<string name="label_due_date">截止日期(可选)</string>
<string name="title_all_task">总任务</string>
<string name="title_completed_task">已完成</string>
<string name="title_pending_task">未完成</string>
</resources> </resources>

View file

@ -119,5 +119,15 @@
<string name="page_overview">Overview</string> <string name="page_overview">Overview</string>
<string name="tip_short_category">Keep category names concise</string> <string name="tip_short_category">Keep category names concise</string>
<string name="action_clear">Clear</string> <string name="action_clear">Clear</string>
<string name="title_upcoming_task">Upcoming Task</string> <string name="title_upcoming_task">Upcoming</string>
<string name="time_today">Today</string>
<string name="time_tomorrow">Tomorrow</string>
<string name="time_in_days">in %d d</string>
<string name="time_in_weeks">in %d w</string>
<string name="time_in_months">in %d mo</string>
<string name="time_in_years">in %d y</string>
<string name="label_due_date">Due Date (Optional)</string>
<string name="title_all_task">All</string>
<string name="title_completed_task">Completed</string>
<string name="title_pending_task">Pending</string>
</resources> </resources>