支持显示节气的倒计时信息

This commit is contained in:
amos wong
2026-01-02 16:15:16 +08:00
parent 44c1824269
commit 85e441d5cc
3 changed files with 121 additions and 4 deletions

View File

@@ -13,11 +13,11 @@ android {
applicationId = "com.memory.app"
minSdk = 26
targetSdk = 35
versionCode = 41
versionName = "1.5.7"
versionCode = 42
versionName = "1.5.8"
buildConfigField("String", "API_BASE_URL", "\"https://x.amos.us.kg/api/\"")
buildConfigField("int", "VERSION_CODE", "41")
buildConfigField("int", "VERSION_CODE", "42")
}
signingConfigs {

View File

@@ -350,6 +350,9 @@ fun ProfileScreen(
// Holiday Countdown
HolidayCountdown()
// 底部留白,避免被导航栏遮挡
Spacer(modifier = Modifier.height(100.dp))
}
}
}
@@ -358,11 +361,13 @@ fun ProfileScreen(
private fun HolidayCountdown() {
var showAll by remember { mutableStateOf(false) }
val allHolidays = remember { HolidayUtils.getUpcomingHolidays(20) }
val allSolarTerms = remember { HolidayUtils.getUpcomingSolarTerms(20) }
if (allHolidays.isEmpty()) return
val mainHoliday = allHolidays.first()
val upcomingHolidays = if (showAll) allHolidays.drop(1) else allHolidays.drop(1).take(2)
val upcomingSolarTerms = if (showAll) allSolarTerms.take(6) else allSolarTerms.take(2)
Column(
modifier = Modifier.fillMaxWidth(),
@@ -461,6 +466,47 @@ private fun HolidayCountdown() {
}
}
}
// Solar Terms Section
if (upcomingSolarTerms.isNotEmpty()) {
Spacer(modifier = Modifier.height(20.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "🌿 节气",
fontSize = 13.sp,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Spacer(modifier = Modifier.height(10.dp))
if (showAll) {
// Vertical list when expanded
upcomingSolarTerms.forEach { termWithDays ->
UpcomingHolidayItem(termWithDays)
Spacer(modifier = Modifier.height(8.dp))
}
} else {
// Horizontal layout for first 2 items
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(10.dp)
) {
upcomingSolarTerms.take(2).forEach { termWithDays ->
CompactHolidayItem(
holidayWithDays = termWithDays,
modifier = Modifier.weight(1f)
)
}
}
}
}
}
}

View File

@@ -7,7 +7,8 @@ data class Holiday(
val name: String,
val emoji: String,
val date: LocalDate,
val isLunar: Boolean = false
val isLunar: Boolean = false,
val isSolarTerm: Boolean = false // 是否为节气
)
object HolidayUtils {
@@ -56,6 +57,63 @@ object HolidayUtils {
)
}
// 获取24节气2025-2026年
private fun getSolarTerms(): List<Holiday> {
return listOf(
// 2025年24节气
Holiday("小寒", "❄️", LocalDate.of(2025, 1, 5), isSolarTerm = true),
Holiday("大寒", "🥶", LocalDate.of(2025, 1, 20), isSolarTerm = true),
Holiday("立春", "🌱", LocalDate.of(2025, 2, 3), isSolarTerm = true),
Holiday("雨水", "🌧️", LocalDate.of(2025, 2, 18), isSolarTerm = true),
Holiday("惊蛰", "🐛", LocalDate.of(2025, 3, 5), isSolarTerm = true),
Holiday("春分", "🌸", LocalDate.of(2025, 3, 20), isSolarTerm = true),
Holiday("清明", "🍃", LocalDate.of(2025, 4, 4), isSolarTerm = true),
Holiday("谷雨", "🌾", LocalDate.of(2025, 4, 20), isSolarTerm = true),
Holiday("立夏", "☀️", LocalDate.of(2025, 5, 5), isSolarTerm = true),
Holiday("小满", "🌿", LocalDate.of(2025, 5, 21), isSolarTerm = true),
Holiday("芒种", "🌾", LocalDate.of(2025, 6, 5), isSolarTerm = true),
Holiday("夏至", "🌞", LocalDate.of(2025, 6, 21), isSolarTerm = true),
Holiday("小暑", "🌡️", LocalDate.of(2025, 7, 7), isSolarTerm = true),
Holiday("大暑", "🔥", LocalDate.of(2025, 7, 22), isSolarTerm = true),
Holiday("立秋", "🍂", LocalDate.of(2025, 8, 7), isSolarTerm = true),
Holiday("处暑", "🌤️", LocalDate.of(2025, 8, 23), isSolarTerm = true),
Holiday("白露", "💧", LocalDate.of(2025, 9, 7), isSolarTerm = true),
Holiday("秋分", "🍁", LocalDate.of(2025, 9, 23), isSolarTerm = true),
Holiday("寒露", "🌫️", LocalDate.of(2025, 10, 8), isSolarTerm = true),
Holiday("霜降", "🥀", LocalDate.of(2025, 10, 23), isSolarTerm = true),
Holiday("立冬", "🌨️", LocalDate.of(2025, 11, 7), isSolarTerm = true),
Holiday("小雪", "🌨️", LocalDate.of(2025, 11, 22), isSolarTerm = true),
Holiday("大雪", "❄️", LocalDate.of(2025, 12, 7), isSolarTerm = true),
Holiday("冬至", "🧊", LocalDate.of(2025, 12, 21), isSolarTerm = true),
// 2026年24节气
Holiday("小寒", "❄️", LocalDate.of(2026, 1, 5), isSolarTerm = true),
Holiday("大寒", "🥶", LocalDate.of(2026, 1, 20), isSolarTerm = true),
Holiday("立春", "🌱", LocalDate.of(2026, 2, 4), isSolarTerm = true),
Holiday("雨水", "🌧️", LocalDate.of(2026, 2, 19), isSolarTerm = true),
Holiday("惊蛰", "🐛", LocalDate.of(2026, 3, 5), isSolarTerm = true),
Holiday("春分", "🌸", LocalDate.of(2026, 3, 20), isSolarTerm = true),
Holiday("清明", "🍃", LocalDate.of(2026, 4, 5), isSolarTerm = true),
Holiday("谷雨", "🌾", LocalDate.of(2026, 4, 20), isSolarTerm = true),
Holiday("立夏", "☀️", LocalDate.of(2026, 5, 5), isSolarTerm = true),
Holiday("小满", "🌿", LocalDate.of(2026, 5, 21), isSolarTerm = true),
Holiday("芒种", "🌾", LocalDate.of(2026, 6, 5), isSolarTerm = true),
Holiday("夏至", "🌞", LocalDate.of(2026, 6, 21), isSolarTerm = true),
Holiday("小暑", "🌡️", LocalDate.of(2026, 7, 7), isSolarTerm = true),
Holiday("大暑", "🔥", LocalDate.of(2026, 7, 23), isSolarTerm = true),
Holiday("立秋", "🍂", LocalDate.of(2026, 8, 7), isSolarTerm = true),
Holiday("处暑", "🌤️", LocalDate.of(2026, 8, 23), isSolarTerm = true),
Holiday("白露", "💧", LocalDate.of(2026, 9, 7), isSolarTerm = true),
Holiday("秋分", "🍁", LocalDate.of(2026, 9, 23), isSolarTerm = true),
Holiday("寒露", "🌫️", LocalDate.of(2026, 10, 8), isSolarTerm = true),
Holiday("霜降", "🥀", LocalDate.of(2026, 10, 23), isSolarTerm = true),
Holiday("立冬", "🌨️", LocalDate.of(2026, 11, 7), isSolarTerm = true),
Holiday("小雪", "🌨️", LocalDate.of(2026, 11, 22), isSolarTerm = true),
Holiday("大雪", "❄️", LocalDate.of(2026, 12, 7), isSolarTerm = true),
Holiday("冬至", "🧊", LocalDate.of(2026, 12, 22), isSolarTerm = true)
)
}
// 获取即将到来的节日(包括今天)
fun getUpcomingHolidays(count: Int = 3): List<HolidayWithDays> {
val today = LocalDate.now()
@@ -68,6 +126,19 @@ object HolidayUtils {
HolidayWithDays(holiday, daysUntil)
}
}
// 获取即将到来的节气
fun getUpcomingSolarTerms(count: Int = 3): List<HolidayWithDays> {
val today = LocalDate.now()
return getSolarTerms()
.filter { !it.date.isBefore(today) }
.sortedBy { it.date }
.take(count)
.map { term ->
val daysUntil = ChronoUnit.DAYS.between(today, term.date).toInt()
HolidayWithDays(term, daysUntil)
}
}
}
data class HolidayWithDays(