|
|
c68944bd55
|
feat(shift): undoable reset-to-default via Snackbar
恢复默认改为 Snackbar 撤销模式:
- 点恢复默认立即生效 + 显示 5 秒"撤销"Snackbar
- 点撤销恢复之前的 pattern
- 删除 AlertDialog 确认框(更现代,防误操作)
- 首次在项目引入 SnackbarHost
|
2026-07-09 16:38:57 +08:00 |
|
|
|
4b098442c4
|
fix(shift): badge color contrast and dynamic calendar rows
- 角标文字色按背景类别配对:班=onPrimary,休=onError,起=onTertiary
- 迷你月历复用 getMonthGridInfo 动态算行数(4/5/6),不再固定 6 行
|
2026-07-09 16:36:36 +08:00 |
|
|
|
f8df108bf3
|
refactor(shift): replace phaseBreaks with atomic RephaseFlip
数据模型重构:把"翻转+重排"从两个独立字段(override+phaseBreak)
改为单一原子结构 RephaseFlip(date, flippedTo, rephaseFrom)。
- 删除 PhaseBreak / phaseBreaks / cycleOffset(UI 未使用 offset!=0)
- kindAt:overrides → rephaseFlip 当天 → 活跃锚点(从 rephaseFrom 取)
- Storage:KEY_BREAKS → KEY_REPHASE,编码 翻转日:值:重排起点
- ShiftCalendarGrid:toggleFlipAndRephase 产出原子记录,撤销按 date 精确匹配
- toggleOverride 加保护:rephaseFlip 翻转日被点时整体移除,防幽灵重排
解决问题:撤销误删独立断点、单独点翻转留幽灵、连续长按断点链不级联。
|
2026-07-09 16:33:29 +08:00 |
|
|
|
d8014b5154
|
test(shift): add safety-net tests for long-press rephase scenarios
锁定重构前行为:单次长按重排、连续两次长按、撤销。
作为 RephaseFlip 重构的回归基线。
|
2026-07-09 16:25:23 +08:00 |
|
|
|
66a054f2d8
|
feat(shift): long-press flips and rephases subsequent days
长按语义从"设相位断点"改为"翻转该天并从次日起重排":
- 翻转当天 override + 次日插入 PhaseBreak(重排起点)
- 后续按 cycle 自动顺延,匹配用户直觉
- 再次长按同一天可撤销(移除 override + 关联断点)
- 角标"断"改为"起",文案同步更新
|
2026-07-09 16:14:41 +08:00 |
|
|
|
7f080f2d90
|
fix(shift): add color legend and restore manifest trailing newline
- Add legend text (班/休/断点 color meanings) below mini calendar
- Restore trailing newline in AndroidManifest.xml
|
2026-07-06 19:10:27 +08:00 |
|
|
|
32d66f0a42
|
fix(shift): subscribe shiftPattern to trigger recomposition on refresh
|
2026-07-06 19:09:26 +08:00 |
|
|
|
a5795b16dc
|
feat(shift): add ShiftPatternActivity, Screen, and mini calendar grid
|
2026-07-06 18:52:16 +08:00 |
|
|
|
d528b98cde
|
feat(shift): wire VM factory, onResume reload, settings menu entry
|
2026-07-06 18:41:07 +08:00 |
|
|
|
e08243d0fa
|
test(shift): cover refreshShiftPattern reload after storage change
|
2026-07-06 18:37:47 +08:00 |
|
|
|
ef55ffcf64
|
feat(shift): inject ShiftPatternStorage into CalendarViewModel
|
2026-07-06 18:34:12 +08:00 |
|
|
|
1f1db17384
|
fix(shift): persist name field, guard empty cycle, test corrupt-data path
|
2026-07-06 18:30:40 +08:00 |
|
|
|
e4834a52c9
|
feat(shift): add ShiftPatternStorage for persistence
|
2026-07-06 18:24:28 +08:00 |
|
|
|
eca6c61058
|
test(shift): cover non-zero cycleOffset and multiple phase breaks; add kindAt KDoc
|
2026-07-06 18:20:48 +08:00 |
|
|
|
778d5dc8be
|
feat(shift): support overrides and phase breaks in ShiftPattern
|
2026-07-06 18:14:24 +08:00 |
|
|
|
0fbbdfa444
|
feat: show rose day icon with priority over birthday crown
|
2026-06-16 18:06:50 +08:00 |
|
|
|
25885d84b3
|
feat: compute rose day flag in LunarCache
|
2026-06-16 17:59:00 +08:00 |
|
|
|
a8c2637a0c
|
feat: add rose day vector drawable
|
2026-06-16 17:56:49 +08:00 |
|
|
|
e07ccd8b4e
|
docs: update ui AGENTS.md for DogParkScreen
|
2026-06-16 16:38:20 +08:00 |
|
|
|
6532363cdb
|
feat: add DogParkScreen for full-screen easter egg video
|
2026-06-16 16:15:09 +08:00 |
|
|
|
9d2f67b9fb
|
feat: wire up version click easter egg in AboutScreen
|
2026-06-16 16:03:51 +08:00 |
|
|
|
6830c1e510
|
feat: add easter egg toast message logic with tests
|
2026-06-16 15:50:46 +08:00 |
|
|
|
3ab50ec900
|
assets: add dog park easter egg background video
|
2026-06-16 15:41:28 +08:00 |
|
|
|
bd4dad4794
|
chore(profile): 重新生成 Baseline/Startup Profile
benchmark buildType 已关闭 R8 混淆,重新生成 profile 后
plus.rua.project 下类名保持原始可读签名,避免 release
打包时 profile 匹配风险。
|
2026-06-16 14:41:25 +08:00 |
|
|
|
a731507b3b
|
feat: 月视图年月支持日期选择器跳转
- MonthHeader 新增 onYearMonthClick 回调,点击年月文字打开日期选择器
- CalendarMonthView 集成 DatePickerDialog,选择日期后调用 selectDate
- 复用现有 CalendarPager 动画,跨月跳转时自动平滑翻页
同时包含之前的改动:
- 临时隐藏 SplashActivity 入口,改由 MainActivity 作为 LAUNCHER
- benchmark build type 关闭 R8 混淆与资源压缩,保证 profile 可读性
|
2026-06-16 14:19:41 +08:00 |
|
|
|
21327d572b
|
feat(splash): add custom SplashActivity with background image
|
2026-06-16 13:11:43 +08:00 |
|
|
|
de329c2020
|
feat(splash): add dimmed dark-mode splash background
|
2026-06-16 12:36:49 +08:00 |
|
|
|
8204ae15cf
|
feat(splash): use SplashScreen API with custom background
|
2026-06-16 12:27:12 +08:00 |
|
|
|
1f2fc8644f
|
feat(splash): add reusable SplashScreen composable
|
2026-06-16 11:51:00 +08:00 |
|
|
|
d98579c2bf
|
feat(splash): add launch background webp asset
|
2026-06-16 11:43:56 +08:00 |
|
|
|
f6b1ed7368
|
chore(baseline): 重新生成 Baseline Profile 与 Startup Profile
|
2026-06-16 10:51:38 +08:00 |
|
|
|
91068ded1c
|
chore(baseline): regenerate baseline profile after startup optimizations
|
2026-06-15 19:17:16 +08:00 |
|
|
|
5bf8a85f7a
|
Merge branch 'feature-birthday-crown'
|
2026-06-15 16:48:24 +08:00 |
|
|
|
3ca0d334e7
|
refactor: remove redundant icon content description and reorder DayCellImpl params
|
2026-06-15 16:45:58 +08:00 |
|
|
|
94861dc2f7
|
style: apply spotless formatting
|
2026-06-15 16:41:07 +08:00 |
|
|
|
de47509a32
|
feat: show tilted birthday crown with click bounce animation
|
2026-06-15 16:36:13 +08:00 |
|
|
|
564e4e3960
|
refactor: 清理无效 ProGuard 规则、调试日志,trace 解耦 VM
P0 正确性与工程卫生修复:
- 删除 core/proguard-rules.pro 中全部无效的 -keepclassmembers 规则
(LunarCache.getOrCompute 实为实例 suspend 方法,generateMonthDays 实为
private,签名均不匹配,属 placebo);同时移除 core/build.gradle.kts
release block 内重复的 consumerProguardFiles 声明
- 将 7 处 composeTrace 调用从 CalendarViewModel 移至 Compose 层
(MenuItem.onClick / onMonthClick / BottomCard 回调),VM 不再依赖
android.os.Trace,可在纯 JVM 环境测试无需兜底
- 删除 CalendarViewModel 与 4 个 UI 文件中约 30 处 logd 调用及其辅助
变量/ SideEffect/ DisposableEffect (AnimLog.kt 工具函数保留)
- 删除 CalendarViewModel.getIsoWeekNumber 不可达的 weekNumber < 1 递归分支
- 修正 MainActivity.kt setContent 块缩进错位
- 同步 README: sketch 渲染 GIF→动画 WebP,补提 :macrobenchmark 模块;
删除 AGENTS.md 顶部过时的「README 与实际不符」注释
验证: spotlessApply UP-TO-DATE, testDebugUnitTest 全过,
assembleDebug + assembleRelease (R8) 均成功
|
2026-06-15 16:24:38 +08:00 |
|
|
|
f33e68d1db
|
feat: compute birthday flag in LunarCache
|
2026-06-15 16:22:47 +08:00 |
|
|
|
06ac30e6d2
|
feat: compute birthday flag in LunarCache
|
2026-06-15 16:10:22 +08:00 |
|
|
|
7404bdfc28
|
feat: add birthday crown vector drawable
|
2026-06-15 16:03:41 +08:00 |
|
|
|
825eb526de
|
feat(about): 将关于页面背景图优化为 WebP
|
2026-06-15 15:40:34 +08:00 |
|
|
|
9a09be56ef
|
feat(about): 将 xiaogou_bg1.jpg 设为关于页面背景
|
2026-06-15 15:04:58 +08:00 |
|
|
|
6e1c2a39ae
|
docs: 校正 assets AGENTS.md,消除 GIF/镜像等错误描述
问题
- 4 份 assets/AGENTS.md 与 Task 1-5 后的实际状态全部相反:
- 声称 core/app "内容同步/镜像" → 实际职责不同 (core 管 UI/WebP, app 管启动器)
- 声称文件是 .gif → 实际是 .webp 动画
- 声称由 AnimatedGif 加载 → 实际是 AnimatedWebp
- app/assets/gifs/ 只剩过时 AGENTS.md (PNG 已被 Task 1 删)
改动
- core/assets/AGENTS.md: 移除"与 app 镜像"错误说法, 说明职责划分, 列 app_icon.webp
- core/assets/animations/AGENTS.md: GIF→WebP 正名, 说明构建期扫描机制 + 测试守卫,
保留"历史命名曾为 gifs/"历史说明
- app/assets/AGENTS.md: 反映清理后为空, 警告勿再放图标源 PNG
- 删除 app/assets/gifs/ 过时空目录 (仅剩 1 个过时 AGENTS.md)
验证
- grep 全 assets 无真正错误描述 (剩余命中均为有意的纠正/历史说明)
- ./gradlew :app:assembleDebug → BUILD SUCCESSFUL
|
2026-06-15 14:08:18 +08:00 |
|
|
|
58a97d1725
|
refactor: WebP 文件列表改由构建期 BuildConfig 注入,消除 (1..152) 硬编码
问题
- AnimatedWebp.kt 原写死 WEBP_FILES = (1..152).map{...}, 与磁盘文件耦合却无校验
- 加 153.webp → 永远不会被随机到; 删某个 → random() 偶发命中不存在的资源
- 这是静默失败, 运行期无报错, 难排查
改动
- core/build.gradle.kts defaultConfig: 构建期扫描 assets/animations/ 生成
buildConfigField("String[]", "WEBP_FILES", "new String[]{...}")
含 require(webpFiles.isNotEmpty()) 防空目录构建
- AnimatedWebp.kt: WEBP_FILES 从 private 硬编码改为 internal val = BuildConfig.WEBP_FILES.toList()
(internal 让同模块测试可访问)
- 新增 AnimatedWebpFilesTest: 2 个守卫测试
1. webpFilesMatchDirectoryContents: WEBP_FILES 必须与 assets/animations/ 一一对应
2. webpFilesUseZeroPaddedThreeDigitNames: 锁定 NNN.webp 命名约定
TDD 流程
- 先写测试 → 编译失败(WEBP_FILES 是 private) → 红灯成立
- 改实现 → 测试 PASS → 绿灯
- 突变验证: 临时改 WEBP_FILES = (1..150) 漏掉 151/152
→ webpFilesMatchDirectoryContents 立即 FAIL, 守卫有效
- 恢复后全量 146 个测试 0 失败
设计说明
- 当前实现里 WEBP_FILES 与目录都来自同一次构建期扫描, 二者天然一致
- 测试的核心价值是锁定「两者一致」不变量, 防止有人回退成硬编码
(突变验证已证明: 回退后测试立即失败)
- BuildConfig 生成结果验证: String[] 含 152 个元素 001~152.webp
验证
- ./gradlew :core:testDebugUnitTest → 146 tests, 0 failures, 0 errors
- ./gradlew :app:assembleDebug → BUILD SUCCESSFUL
- BuildConfig.java: public static final String[] WEBP_FILES = new String[]{"001.webp",...,"152.webp"}
|
2026-06-15 14:02:21 +08:00 |
|
|
|
87d51b253a
|
refactor: gifs/→animations/、AnimatedGif→AnimatedWebp, 名实相符
问题
- 目录名 gifs/ 与类名 AnimatedGif 长期描述 GIF, 但实际格式是 WebP 动画
(依赖 sketch-animated-webp, 文件后缀也是 .webp)
- 名实不符持续误导阅读者, 也让 GIF 相关搜索返回错误结果
改动(仅重命名, 不改运行时行为)
- core/src/main/assets/gifs/ → animations/ (git mv, 152 个 webp + AGENTS.md)
- core/.../ui/AnimatedGif.kt → AnimatedWebp.kt, 函数 AnimatedGif() → AnimatedWebp()
- Platform.kt:13 getWebpUri 路径 gifs/ → animations/
- BottomCard.kt:175 调用点 AnimatedGif( → AnimatedWebp(
- CalendarMonthView.kt:583 注释同步
- scripts/profile.sh:228,1103 两处场景描述/trace 文档同步
- baseline-prof.txt: 19 处 AnimatedGifKt → AnimatedWebpKt (R8 类名)
注: lambda hash 可能需下次 updateBaselineProfile 重新生成校准, 当前不影响构建
验证
- grep 全仓库 (排除 build/AGENTS.md/baseline-prof) 无 AnimatedGif/ 残留
- ./gradlew :app:assembleDebug → BUILD SUCCESSFUL
备注
- WEBP_FILES = (1..152) 硬编码暂保留, 下一个提交替换为构建期 BuildConfig
- AGENTS.md 文档校正留待 Task 6 统一处理
|
2026-06-15 13:57:09 +08:00 |
|
|
|
7d6ed1428e
|
refactor: 日期检查器 Canvas 手绘图标替换为 Material Icons
CalendarIcon/ArrowRightIcon 改用 Icons.Filled.DateRange 和
Icons.AutoMirrored.Filled.ArrowForward,统一图标风格并支持
RTL 自动镜像;删除冗余 Canvas 绘制代码及关联 import(Offset/
StrokeCap/Stroke)。
|
2026-06-15 13:26:34 +08:00 |
|
|
|
7628f299c2
|
fix: 加载保质期列表时钳制旧数据,清理历史持久化的负数天数
|
2026-06-15 11:40:26 +08:00 |
|
|
|
1438b405a9
|
feat: 日期检查器 Row 日期选择器禁选早于生产日期
|
2026-06-15 11:30:43 +08:00 |
|
|
|
2085c22987
|
fix: 日期检查器写入保质期天数前钳制为非负,防止负数落库
|
2026-06-15 11:27:35 +08:00 |
|
|
|
55d50c3e1d
|
feat: 添加 clampExpiryDays 纯函数钳制保质期天数为非负
|
2026-06-15 11:24:38 +08:00 |
|