refactor: 删除 P0 冗余代码(自定义combine/死StateFlow/网格重复算法/runBlocking)
- 删除自定义 6 参数 combine + Quintuple,改用标准库嵌套 combine + Triple - 删除 yearViewProgress 死 StateFlow 及关联测试 - generateMonthDays/generateMiniMonthDays 复用 getMonthGridInfo - WeekPager 移除 runBlocking,交由 DayCell 自行异步计算 - 修复 AnimLog 在 JVM 单元测试中因 android.util.Log 不可用而崩溃
This commit is contained in:
parent
e249700ee5
commit
829f89eb7c
@ -56,37 +56,6 @@ data class CalendarUiState(
|
||||
val showLegalHoliday: Boolean
|
||||
)
|
||||
|
||||
/**
|
||||
* 将六个 [Flow] 合并为一个 [Flow],使用 [transform] 处理最新值。
|
||||
*
|
||||
* kotlinx-coroutines 1.11 仅内置到 5 参数的 [combine] 重载,
|
||||
* 此扩展用于扁平化 6 个 StateFlow 的合并,避免多层嵌套产生的中间流。
|
||||
*/
|
||||
private inline fun <T1, T2, T3, T4, T5, T6, R> combine(
|
||||
flow: Flow<T1>,
|
||||
flow2: Flow<T2>,
|
||||
flow3: Flow<T3>,
|
||||
flow4: Flow<T4>,
|
||||
flow5: Flow<T5>,
|
||||
flow6: Flow<T6>,
|
||||
crossinline transform: suspend (T1, T2, T3, T4, T5, T6) -> R
|
||||
): Flow<R> = combine(
|
||||
combine(flow, flow2, flow3, flow4, flow5) { t1, t2, t3, t4, t5 ->
|
||||
Quintuple(t1, t2, t3, t4, t5)
|
||||
},
|
||||
flow6
|
||||
) { quintuple, t6 ->
|
||||
transform(quintuple.first, quintuple.second, quintuple.third, quintuple.fourth, quintuple.fifth, t6)
|
||||
}
|
||||
|
||||
private data class Quintuple<T1, T2, T3, T4, T5>(
|
||||
val first: T1,
|
||||
val second: T2,
|
||||
val third: T3,
|
||||
val fourth: T4,
|
||||
val fifth: T5
|
||||
)
|
||||
|
||||
/**
|
||||
* 日历状态管理,持有选中日期、折叠状态和 ISO 周号计算逻辑。
|
||||
*
|
||||
@ -141,9 +110,6 @@ class CalendarViewModel(
|
||||
private val _isYearView = MutableStateFlow(false)
|
||||
val isYearView: StateFlow<Boolean> = _isYearView.asStateFlow()
|
||||
|
||||
private val _yearViewProgress = MutableStateFlow(0f)
|
||||
val yearViewProgress: StateFlow<Float> = _yearViewProgress.asStateFlow()
|
||||
|
||||
private val _yearViewYear = MutableStateFlow(today.year)
|
||||
val yearViewYear: StateFlow<Int> = _yearViewYear.asStateFlow()
|
||||
|
||||
@ -170,13 +136,9 @@ class CalendarViewModel(
|
||||
|
||||
/** 聚合 UI 状态,减少 Compose 层分散订阅导致的重组。 */
|
||||
val uiState: StateFlow<CalendarUiState> = combine(
|
||||
_selectedDate,
|
||||
_isCollapsed,
|
||||
_isYearView,
|
||||
_yearViewYear,
|
||||
_collapseProgress,
|
||||
_showLegalHoliday
|
||||
) { selectedDate, isCollapsed, isYearView, yearViewYear, collapseProgress, showLegalHoliday ->
|
||||
combine(_selectedDate, _isCollapsed, _isYearView) { s, c, y -> Triple(s, c, y) },
|
||||
combine(_yearViewYear, _collapseProgress, _showLegalHoliday) { y, p, h -> Triple(y, p, h) }
|
||||
) { (selectedDate, isCollapsed, isYearView), (yearViewYear, collapseProgress, showLegalHoliday) ->
|
||||
CalendarUiState(
|
||||
selectedDate = selectedDate,
|
||||
isCollapsed = isCollapsed,
|
||||
@ -212,8 +174,6 @@ class CalendarViewModel(
|
||||
if (_isYearView.value) {
|
||||
logd(TAG_VM, "[toggleYearView] ===== START Year→Month t=$t0 =====")
|
||||
composeTraceBeginSection("YearView→MonthView")
|
||||
_yearViewProgress.value = 0f
|
||||
logd(TAG_VM, "[toggleYearView] yearViewProgress=0 dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
_isYearView.value = false
|
||||
logd(TAG_VM, "[toggleYearView] isYearView=false dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
composeTraceEndSection()
|
||||
@ -223,8 +183,6 @@ class CalendarViewModel(
|
||||
composeTraceBeginSection("MonthView→YearView")
|
||||
_yearViewYear.value = _selectedDate.value.year
|
||||
logd(TAG_VM, "[toggleYearView] yearViewYear=${_yearViewYear.value} dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
_yearViewProgress.value = 1f
|
||||
logd(TAG_VM, "[toggleYearView] yearViewProgress=1 dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
_isYearView.value = true
|
||||
logd(TAG_VM, "[toggleYearView] isYearView=true dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
composeTraceEndSection()
|
||||
@ -253,8 +211,6 @@ class CalendarViewModel(
|
||||
logd(TAG_VM, "[selectMonthFromYearView] selectedDate set dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
_isYearView.value = false
|
||||
logd(TAG_VM, "[selectMonthFromYearView] isYearView=false dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
_yearViewProgress.value = 0f
|
||||
logd(TAG_VM, "[selectMonthFromYearView] yearViewProgress=0 dt=${(System.nanoTime() - t0) / 1_000_000}ms")
|
||||
composeTraceEndSection()
|
||||
logd(TAG_VM, "[selectMonthFromYearView] ===== END total=${(System.nanoTime() - t0) / 1_000_000}ms =====")
|
||||
}
|
||||
|
||||
@ -292,16 +292,9 @@ data class HolidayEdgeInfo(
|
||||
)
|
||||
|
||||
private fun generateMonthDays(year: Int, month: Int): List<DayData> {
|
||||
val firstOfMonth = LocalDate(year, Month(month), 1)
|
||||
val offset = firstOfMonth.dayOfWeek.ordinal
|
||||
val startDate = firstOfMonth.minus(DatePeriod(days = offset))
|
||||
val nextMonth = if (month == 12) LocalDate(year + 1, 1, 1) else LocalDate(year, Month(month + 1), 1)
|
||||
val daysInMonth = nextMonth.minus(DatePeriod(days = 1)).day
|
||||
val rows = ((offset + daysInMonth - 1) / 7) + 1
|
||||
val totalDays = rows * 7
|
||||
|
||||
return (0 until totalDays).map { i ->
|
||||
val date = startDate.plus(DatePeriod(days = i))
|
||||
val info = getMonthGridInfo(year, month)
|
||||
return (0 until info.totalDays).map { i ->
|
||||
val date = info.startDate.plus(DatePeriod(days = i))
|
||||
DayData(
|
||||
date = date,
|
||||
isCurrentMonth = date.month.number == month && date.year == year
|
||||
|
||||
@ -18,13 +18,10 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.datetime.DatePeriod
|
||||
import kotlinx.datetime.LocalDate
|
||||
import kotlinx.datetime.daysUntil
|
||||
import kotlinx.datetime.plus
|
||||
import plus.rua.project.DayCellInfo
|
||||
import plus.rua.project.LunarCache
|
||||
import plus.rua.project.ShiftKind
|
||||
import plus.rua.project.composeTraceBeginSection
|
||||
import plus.rua.project.composeTraceEndSection
|
||||
@ -99,11 +96,6 @@ fun WeekPager(
|
||||
) {
|
||||
(0 until 7).forEach { dayOffset ->
|
||||
val date = weekMonday.plus(DatePeriod(days = dayOffset))
|
||||
val lunarData = remember(date) {
|
||||
runBlocking {
|
||||
LunarCache.default.getOrCompute(date)
|
||||
}
|
||||
}
|
||||
DayCell(
|
||||
date = date,
|
||||
isCurrentMonth = date.month == selectedDate.month
|
||||
@ -115,8 +107,7 @@ fun WeekPager(
|
||||
cellIndex = dayOffset,
|
||||
onClick = { onDateClick(date) },
|
||||
modifier = Modifier.weight(1f),
|
||||
interactionSource = interactionSource,
|
||||
lunarData = lunarData
|
||||
interactionSource = interactionSource
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,16 +307,9 @@ private data class MiniDayData(
|
||||
|
||||
private fun generateMiniMonthDays(year: Int, month: Int): List<MiniDayData> {
|
||||
composeTraceBeginSection("generateMiniMonthDays:$year-$month")
|
||||
val firstOfMonth = LocalDate(year, Month(month), 1)
|
||||
val offset = firstOfMonth.dayOfWeek.ordinal
|
||||
val startDate = firstOfMonth.minus(DatePeriod(days = offset))
|
||||
val nextMonth = if (month == 12) LocalDate(year + 1, 1, 1) else LocalDate(year, Month(month + 1), 1)
|
||||
val daysInMonth = nextMonth.minus(DatePeriod(days = 1)).day
|
||||
val rows = ((offset + daysInMonth - 1) / 7) + 1
|
||||
val totalDays = rows * 7
|
||||
|
||||
val result = (0 until totalDays).map { i ->
|
||||
val date = startDate.plus(DatePeriod(days = i))
|
||||
val info = getMonthGridInfo(year, month)
|
||||
val result = (0 until info.totalDays).map { i ->
|
||||
val date = info.startDate.plus(DatePeriod(days = i))
|
||||
MiniDayData(
|
||||
date = date,
|
||||
isCurrentMonth = date.month.number == month && date.year == year
|
||||
|
||||
@ -6,13 +6,22 @@ import plus.rua.project.shared.BuildConfig
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun logd(tag: String, message: () -> String) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(tag, message())
|
||||
try {
|
||||
Log.d(tag, message())
|
||||
} catch (_: RuntimeException) {
|
||||
// Android Log not available in JVM unit tests; fallback to stdout
|
||||
println("D/$tag: ${message()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun logd(tag: String, message: String) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(tag, message)
|
||||
try {
|
||||
Log.d(tag, message)
|
||||
} catch (_: RuntimeException) {
|
||||
println("D/$tag: $message")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,11 +52,6 @@ class CalendarViewModelStateTest {
|
||||
assertFalse(createViewModel().isYearView.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun init_yearViewProgressDefaultsZero() {
|
||||
assertEquals(0f, createViewModel().yearViewProgress.value, 0.001f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun init_yearViewYearDefaultsToTodayYear() {
|
||||
assertEquals(2026, createViewModel().yearViewYear.value)
|
||||
@ -375,7 +370,6 @@ class CalendarViewModelStateTest {
|
||||
assertFalse(vm.isYearView.value)
|
||||
vm.toggleYearView()
|
||||
assertTrue(vm.isYearView.value)
|
||||
assertEquals(1f, vm.yearViewProgress.value, 0.001f)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -385,7 +379,6 @@ class CalendarViewModelStateTest {
|
||||
assertTrue(vm.isYearView.value)
|
||||
vm.toggleYearView()
|
||||
assertFalse(vm.isYearView.value)
|
||||
assertEquals(0f, vm.yearViewProgress.value, 0.001f)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user