diff --git a/core/src/main/kotlin/plus/rua/project/ui/DayCell.kt b/core/src/main/kotlin/plus/rua/project/ui/DayCell.kt index c11ca24..792e2aa 100644 --- a/core/src/main/kotlin/plus/rua/project/ui/DayCell.kt +++ b/core/src/main/kotlin/plus/rua/project/ui/DayCell.kt @@ -1,9 +1,12 @@ package plus.rua.project.ui import androidx.compose.animation.animateColor +import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.FastOutSlowInEasing +import androidx.compose.animation.core.Spring import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.spring import androidx.compose.animation.core.tween import androidx.compose.animation.core.updateTransition import androidx.compose.ui.graphics.TransformOrigin @@ -16,14 +19,19 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -31,6 +39,7 @@ import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.drawscope.Stroke +import androidx.compose.ui.res.painterResource import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.font.FontWeight @@ -44,6 +53,7 @@ import kotlinx.datetime.number import plus.rua.project.DayCellInfo import plus.rua.project.LunarCache import plus.rua.project.ShiftKind +import plus.rua.project.shared.R enum class DayCellState { NORMAL, OTHER_MONTH, TODAY, SELECTED, SELECTED_TODAY @@ -63,6 +73,9 @@ enum class DayCellState { * @param holidayEdgeInfo 假日在连续序列中的边缘状态,决定背景圆角。null 表示无假日。 * @param cellIndex 单元格在月网格中的线性索引(weekIndex*7+dayIndex),用于法定假日波浪动画延迟。 * @param onClick 点击回调 + * @param interactionSource 点击交互源 + * @param lunarCache 农历缓存实例 + * @param lunarData 预计算的日期信息;null 时内部自动获取 * @param modifier 外部布局修饰符 */ @Composable @@ -76,10 +89,10 @@ fun DayCell( holidayEdgeInfo: HolidayEdgeInfo? = null, cellIndex: Int = 0, onClick: () -> Unit, - modifier: Modifier = Modifier, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, lunarCache: LunarCache = LunarCache.default, lunarData: DayCellInfo? = null, + modifier: Modifier = Modifier, ) { if (lunarData != null) { DayCellImpl( @@ -136,6 +149,16 @@ private fun DayCellImpl( interactionSource: MutableInteractionSource, lunarData: DayCellInfo, ) { + val isBirthday = lunarData.isBirthday + var birthdayClickTick by remember(date) { mutableIntStateOf(0) } + val crownScale = remember(date) { Animatable(1f) } + LaunchedEffect(birthdayClickTick) { + if (birthdayClickTick > 0) { + crownScale.animateTo(1.4f, spring(dampingRatio = Spring.DampingRatioMediumBouncy)) + crownScale.animateTo(1f, spring(dampingRatio = Spring.DampingRatioMediumBouncy)) + } + } + val annotationText = lunarData.annotationText val isAnnotationHighlight = lunarData.isAnnotationHighlight val holidayBadge = lunarData.holidayBadge @@ -296,7 +319,10 @@ private fun DayCellImpl( .clickable( interactionSource = interactionSource, indication = null, - onClick = onClick + onClick = { + if (isBirthday) birthdayClickTick += 1 + onClick() + } ), contentAlignment = Alignment.Center ) { @@ -346,5 +372,23 @@ private fun DayCellImpl( ) } } + if (isBirthday) { + Icon( + painter = painterResource(R.drawable.ic_birthday_crown), + contentDescription = "生日", + tint = Color.Unspecified, + modifier = Modifier + .align(Alignment.TopStart) + .zIndex(1f) + .padding(start = 2.dp, top = 2.dp) + .size(14.dp) + .graphicsLayer { + rotationZ = -45f + transformOrigin = TransformOrigin.Center + scaleX = crownScale.value + scaleY = crownScale.value + } + ) + } } }