diff --git a/shared/src/commonMain/composeResources/drawable/compose-multiplatform.xml b/shared/src/commonMain/composeResources/drawable/compose-multiplatform.xml index 1ffc948..944802b 100644 --- a/shared/src/commonMain/composeResources/drawable/compose-multiplatform.xml +++ b/shared/src/commonMain/composeResources/drawable/compose-multiplatform.xml @@ -1,44 +1,49 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/plus/rua/project/CalendarViewModel.kt b/shared/src/commonMain/kotlin/plus/rua/project/CalendarViewModel.kt index feea61e..d328ac2 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/CalendarViewModel.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/CalendarViewModel.kt @@ -15,9 +15,9 @@ import kotlinx.datetime.minus import kotlinx.datetime.number import kotlinx.datetime.plus import kotlinx.datetime.todayIn -import kotlin.time.Clock import plus.rua.project.ui.COLLAPSE_THRESHOLD import plus.rua.project.ui.FLING_VELOCITY_THRESHOLD_DP +import kotlin.time.Clock /** * 日历日期数据,用于网格单元格渲染。 @@ -198,7 +198,8 @@ class CalendarViewModel( val firstOfMonth = LocalDate(year, month, 1) val dayOfWeekOffset = firstOfMonth.dayOfWeek.ordinal val startDate = firstOfMonth.minus(DatePeriod(days = dayOfWeekOffset)) - val nextMonth = if (month == 12) LocalDate(year + 1, 1, 1) else LocalDate(year, month + 1, 1) + val nextMonth = + if (month == 12) LocalDate(year + 1, 1, 1) else LocalDate(year, month + 1, 1) val daysInMonth = nextMonth.minus(DatePeriod(days = 1)).day val rows = ((dayOfWeekOffset + daysInMonth - 1) / 7) + 1 val totalDays = rows * 7 diff --git a/shared/src/commonMain/kotlin/plus/rua/project/ui/BottomCard.kt b/shared/src/commonMain/kotlin/plus/rua/project/ui/BottomCard.kt index 848ff9e..56a7ebf 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/BottomCard.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/BottomCard.kt @@ -11,7 +11,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip diff --git a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthPage.kt b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthPage.kt index 544dc6a..51da8c4 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthPage.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthPage.kt @@ -73,10 +73,12 @@ fun CalendarMonthPage( null } - Box(modifier = modifier.clipToBounds().then( - if (totalHeightDp != null) Modifier.height(totalHeightDp) - else Modifier - )) { + Box( + modifier = modifier.clipToBounds().then( + if (totalHeightDp != null) Modifier.height(totalHeightDp) + else Modifier + ) + ) { weeks.forEachIndexed { weekIndex, week -> val isSelected = hasSelectedWeek && weekIndex == selectedWeekIndex val isAbove = hasSelectedWeek && weekIndex < selectedWeekIndex @@ -135,7 +137,9 @@ fun CalendarMonthPage( ) .padding(vertical = ROW_PADDING_DP.dp) .then( - if (isAbove || isBelow) Modifier.graphicsLayer { alpha = 1f - collapseProgress } + if (isAbove || isBelow) Modifier.graphicsLayer { + alpha = 1f - collapseProgress + } else Modifier ) ) { diff --git a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthView.kt b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthView.kt index ceffd4e..c24ae65 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthView.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarMonthView.kt @@ -27,9 +27,9 @@ import kotlinx.datetime.TimeZone import kotlinx.datetime.number import kotlinx.datetime.plus import kotlinx.datetime.todayIn +import plus.rua.project.CalendarViewModel import kotlin.math.abs import kotlin.time.Clock -import plus.rua.project.CalendarViewModel /** * 日历主界面,包含月/周视图切换和折叠动画。 @@ -47,6 +47,7 @@ fun CalendarMonthView( val viewModel = remember { CalendarViewModel(coroutineScope) } val today = remember { Clock.System.todayIn(TimeZone.currentSystemDefault()) } val currentYear by remember { derivedStateOf { viewModel.selectedDate.year } } + @Suppress("DEPRECATION") // monthNumber 无替代 API,kotlinx-datetime 尚未提供新接口 val currentMonth by remember { derivedStateOf { viewModel.selectedDate.month.number } } val density = LocalDensity.current @@ -62,7 +63,13 @@ fun CalendarMonthView( val collapseProgress = viewModel.collapseProgress val headerHeightPx = monthHeaderHeightPx + weekdayHeaderHeightPx val rowPaddingPx = with(density) { ROW_PADDING_DP.dp.toPx() }.toInt() - val cardGapPx = with(density) { lerp(CARD_GAP_EXPANDED_DP.toFloat(), CARD_GAP_COLLAPSED_DP.toFloat(), collapseProgress).dp.toPx() }.toInt() + val cardGapPx = with(density) { + lerp( + CARD_GAP_EXPANDED_DP.toFloat(), + CARD_GAP_COLLAPSED_DP.toFloat(), + collapseProgress + ).dp.toPx() + }.toInt() // 翻页时在相邻月份行数之间插值,使 BottomCard 高度平滑过渡 // abs(fraction) > 阈值时启用插值,避免静止时的浮点抖动 @@ -85,7 +92,8 @@ fun CalendarMonthView( // 加上 Row 的 vertical padding (6dp × 2) // 用于 rowHeightPx 尚未测量时的 fallback,避免首次布局高度为 0 val estimatedRowHeightPx = if (screenWidthPx > 0) { - val cellWidth = (screenWidthPx - with(density) { (HORIZONTAL_PADDING_DP * 2).dp.toPx() }) / 7 + val cellWidth = + (screenWidthPx - with(density) { (HORIZONTAL_PADDING_DP * 2).dp.toPx() }) / 7 val rowPadding = with(density) { (ROW_PADDING_DP * 2).dp.toPx() } (cellWidth + rowPadding).toInt() } else 0 @@ -110,7 +118,8 @@ fun CalendarMonthView( // BottomCard 高度 = 屏幕剩余空间(屏幕高度 - 日历区域高度) val calendarAreaHeightPx = headerHeightPx + gridHeightPx + rowPaddingPx + cardGapPx - val cardHeightPx = if (screenHeightPx > 0 && calendarAreaHeightPx > 0) screenHeightPx - calendarAreaHeightPx else 0 + val cardHeightPx = + if (screenHeightPx > 0 && calendarAreaHeightPx > 0) screenHeightPx - calendarAreaHeightPx else 0 // 行高已知时约束 pager 高度防止内容溢出;否则让 pager 自由扩展以触发首次行高测量 val pagerModifier = if (rowHeightPx > 0 && gridHeightPx > 0) { @@ -140,9 +149,10 @@ fun CalendarMonthView( } ) WeekdayHeader( - modifier = Modifier.fillMaxWidth().padding(bottom = ROW_PADDING_DP.dp).onSizeChanged { size -> - weekdayHeaderHeightPx = size.height - } + modifier = Modifier.fillMaxWidth().padding(bottom = ROW_PADDING_DP.dp) + .onSizeChanged { size -> + weekdayHeaderHeightPx = size.height + } ) // 完全折叠且无动画时切换到 WeekPager(单行高效渲染), // 否则使用 CalendarPager(含折叠动画和下拉恢复过程) @@ -168,7 +178,7 @@ fun CalendarMonthView( // 优先选中当月内的今天,否则选中该月1号 @Suppress("DEPRECATION") // monthNumber 无替代 API,kotlinx-datetime 尚未提供新接口 val date = if (year == today.year && today.month.number == month) today - else LocalDate(year, month, 1) + else LocalDate(year, month, 1) viewModel.selectDate(date) }, collapseProgress = viewModel.collapseProgress, @@ -184,14 +194,14 @@ fun CalendarMonthView( } // 拖拽范围 = 折叠时日历实际高度变化量 (weeks-1)×rowHeight,使手指移动与视觉变化 1:1 对应 - val dragRangeMinPx = with(density) { DRAG_RANGE_MIN_DP.dp.toPx() } - val dragRangePx = if (effectiveRowHeightPx > 0) { - maxOf((effectiveWeeks - 1) * effectiveRowHeightPx.toFloat(), dragRangeMinPx) - } else { - dragRangeMinPx - } + val dragRangeMinPx = with(density) { DRAG_RANGE_MIN_DP.dp.toPx() } + val dragRangePx = if (effectiveRowHeightPx > 0) { + maxOf((effectiveWeeks - 1) * effectiveRowHeightPx.toFloat(), dragRangeMinPx) + } else { + dragRangeMinPx + } - if (cardHeightPx > 0) { + if (cardHeightPx > 0) { BottomCard( viewModel = viewModel, dragRangePx = dragRangePx, diff --git a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarPager.kt b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarPager.kt index c7f2eab..1d29e21 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarPager.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarPager.kt @@ -47,6 +47,7 @@ fun CalendarPager( modifier: Modifier = Modifier ) { val initialYear = remember { today.year } + @Suppress("DEPRECATION") // monthNumber 无替代 API,kotlinx-datetime 尚未提供新接口 val initialMonth = remember { today.month.number } val coroutineScope = rememberCoroutineScope() @@ -74,13 +75,15 @@ fun CalendarPager( selectedDate = selectedDate, today = today, onDateClick = { date -> - onDateClick(date) - // 点击跨月日期时,滚动到该月对应的页 - val clickedYear = date.year + onDateClick(date) + // 点击跨月日期时,滚动到该月对应的页 + val clickedYear = date.year + @Suppress("DEPRECATION") // monthNumber 无替代 API,kotlinx-datetime 尚未提供新接口 val clickedMonth = date.month.number if (clickedYear != year || clickedMonth != month) { - val targetPage = yearMonthToPage(clickedYear, clickedMonth, initialYear, initialMonth) + val targetPage = + yearMonthToPage(clickedYear, clickedMonth, initialYear, initialMonth) if (targetPage != pagerState.currentPage) { coroutineScope.launch { pagerState.animateScrollToPage(targetPage) diff --git a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarUtils.kt b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarUtils.kt index 0ab15e4..7afce9d 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarUtils.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/CalendarUtils.kt @@ -60,6 +60,7 @@ fun calculateWeeksCount(year: Int, month: Int): Int { */ fun calculateWeeksCountForPage(page: Int, today: LocalDate): Int { val initialYear = today.year + @Suppress("DEPRECATION") // monthNumber 无替代 API,kotlinx-datetime 尚未提供新接口 val initialMonth = today.month.number val offset = page - START_PAGE diff --git a/shared/src/commonMain/kotlin/plus/rua/project/ui/MonthHeader.kt b/shared/src/commonMain/kotlin/plus/rua/project/ui/MonthHeader.kt index 54f0dd2..e8d3ca1 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/MonthHeader.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/MonthHeader.kt @@ -1,12 +1,12 @@ package plus.rua.project.ui import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically import androidx.compose.animation.togetherWith -import androidx.compose.animation.core.tween import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -45,10 +45,10 @@ fun MonthHeader( transitionSpec = { if (targetState.second > initialState.second) { slideInVertically(tween(250)) { -it } + fadeIn(tween(250)) togetherWith - slideOutVertically(tween(250)) { it } + fadeOut(tween(250)) + slideOutVertically(tween(250)) { it } + fadeOut(tween(250)) } else { slideInVertically(tween(250)) { it } + fadeIn(tween(250)) togetherWith - slideOutVertically(tween(250)) { -it } + fadeOut(tween(250)) + slideOutVertically(tween(250)) { -it } + fadeOut(tween(250)) } } ) { (y, m) -> @@ -63,10 +63,10 @@ fun MonthHeader( transitionSpec = { if (targetState > initialState) { slideInVertically(tween(250)) { -it } + fadeIn(tween(250)) togetherWith - slideOutVertically(tween(250)) { it } + fadeOut(tween(250)) + slideOutVertically(tween(250)) { it } + fadeOut(tween(250)) } else { slideInVertically(tween(250)) { it } + fadeIn(tween(250)) togetherWith - slideOutVertically(tween(250)) { -it } + fadeOut(tween(250)) + slideOutVertically(tween(250)) { -it } + fadeOut(tween(250)) } } ) { week -> diff --git a/shared/src/commonMain/kotlin/plus/rua/project/ui/WeekPager.kt b/shared/src/commonMain/kotlin/plus/rua/project/ui/WeekPager.kt index 010a968..6173edb 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/WeekPager.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/WeekPager.kt @@ -13,11 +13,11 @@ import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.unit.dp -import kotlin.math.abs import kotlinx.coroutines.flow.drop import kotlinx.datetime.DatePeriod import kotlinx.datetime.LocalDate import kotlinx.datetime.plus +import kotlin.math.abs /** * 周视图分页器,折叠状态下显示选中日期所在周,支持左右滑动切换周。 diff --git a/shared/src/commonTest/kotlin/plus/rua/project/CalendarViewModelTest.kt b/shared/src/commonTest/kotlin/plus/rua/project/CalendarViewModelTest.kt index 08d8cb2..0361dec 100644 --- a/shared/src/commonTest/kotlin/plus/rua/project/CalendarViewModelTest.kt +++ b/shared/src/commonTest/kotlin/plus/rua/project/CalendarViewModelTest.kt @@ -5,7 +5,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.datetime.Clock import kotlinx.datetime.Instant import kotlinx.datetime.LocalDate -import kotlinx.datetime.TimeZone import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse diff --git a/shared/src/commonTest/kotlin/plus/rua/project/ui/CalendarUtilsTest.kt b/shared/src/commonTest/kotlin/plus/rua/project/ui/CalendarUtilsTest.kt index 77c2e4d..292f53f 100644 --- a/shared/src/commonTest/kotlin/plus/rua/project/ui/CalendarUtilsTest.kt +++ b/shared/src/commonTest/kotlin/plus/rua/project/ui/CalendarUtilsTest.kt @@ -1,9 +1,6 @@ package plus.rua.project.ui -import kotlinx.datetime.DatePeriod import kotlinx.datetime.LocalDate -import kotlinx.datetime.minus -import kotlinx.datetime.plus import kotlin.test.Test import kotlin.test.assertEquals diff --git a/shared/src/iosMain/kotlin/plus/rua/project/Platform.ios.kt b/shared/src/iosMain/kotlin/plus/rua/project/Platform.ios.kt index 90195d9..b8abfdb 100644 --- a/shared/src/iosMain/kotlin/plus/rua/project/Platform.ios.kt +++ b/shared/src/iosMain/kotlin/plus/rua/project/Platform.ios.kt @@ -2,8 +2,9 @@ package plus.rua.project import platform.UIKit.UIDevice -class IOSPlatform: Platform { - override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion +class IOSPlatform : Platform { + override val name: String = + UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion } actual fun getPlatform(): Platform = IOSPlatform() \ No newline at end of file