chore: 字符串国际化 & 代码格式化和优化
This commit is contained in:
parent
b585565459
commit
9617f8d0aa
16 changed files with 94 additions and 47 deletions
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ fun RoundedCornerCardLarge(
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.titleMedium
|
||||||
)
|
)
|
||||||
|
|
||||||
BasicText(
|
BasicText(
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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>
|
||||||
Loading…
Reference in a new issue