195 Commits

Author SHA1 Message Date
xfy
b1064f95b7 feat(date-recorder): use camera and crop icons for record/crop buttons
- DateRecorder FAB: Icons.Filled.Add -> Icons.Filled.PhotoCamera
  (与 onOpenCamera / '拍照记录' 语义一致)
- PhotoEditor crop toggle: 纯文字 -> Icons.Filled.Crop / CropFree 图标
  (Crop 关闭态, CropFree 开启态, contentDescription 保留无障碍语义)
2026-07-17 16:31:39 +08:00
xfy
81aeb8e894 fix(date-recorder): split handwriting strokes on finger lift
endStroke() was a no-op, so addStrokePoint() kept appending every new
pointer-down to the previous stroke (its only segmentation cue was
points.isEmpty()). A second drag after lift got joined into the first,
and toPath() drew them as a single polyline.

Add isFinished flag to HandStroke and implement real endStroke() that
marks the current stroke finished. withAddedPoint() now starts a new
segment when the previous stroke is null, empty, or finished.
2026-07-17 16:01:44 +08:00
xfy
50da18460f fix(date-recorder): correct photo EXIF orientation and fix capture crash
- PhotoProcessor: read EXIF orientation and rotate bitmap on load so
  camera JPEGs display upright
- CameraScreen: set target rotation so CameraX writes correct EXIF
- CameraScreen: fix RejectedExecutionException by not shutting down the
  capture executor on dispose (CameraX may still post to it after)
- CameraScreen: route capture callback through main handler for thread
  safety before triggering Activity navigation
- CameraScreen: defer camera binding until PreviewView is attached to
  avoid repeated Surface abandon/recreate and camera rebind loops
- CameraScreen: use an overlay (not component swap) for the capturing
  state so the bound ImageCapture is not torn down mid-capture
- deps: add androidx.exifinterface for EXIF reading
2026-07-17 15:36:36 +08:00
xfy
8963b6162b feat(date-recorder): photo journal tool with camera, editor, and album grid
新增"日期记录器"工具:相册式记录管理,支持拍照→编辑→记录信息的完整流程。

数据层:
- Room 2.8.4 首个数据库(KSP 2.3.10),DateRecord 实体含标题/备注/拍摄日期/关联日期
- DateRecordConverters 处理 kotlinx-datetime ↔ ISO 字符串
- DateRecorderRepository 封装 DAO + filesDir 照片文件管理

UI 层:
- CameraScreen: CameraX 1.5.3 应用内预览,运行时权限请求,前后摄切换
- PhotoEditorScreen: 纯 Compose 自实现旋转/裁剪/手写三 Tab 编辑器
- DateRecorderScreen: LazyVerticalGrid 相册网格 + 多选 + 6 种排序 + 批量删除
- RecordEditScreen / RecordDetailScreen: 记录信息编辑与详情查看

基础设施:
- CAMERA 权限 + FileProvider(filesDir 存储,免存储权限)
- 5 个 Activity 延续项目 Activity+Intent 滑动转场模式
- 2 个单测:排序逻辑 6 种组合 + 降采样计算
2026-07-17 13:21:45 +08:00
xfy
2a3089bf47 feat(shift): smooth height interpolation for mini calendar swipe
滑动翻月时高度平滑过渡,不再跳变:
- 复用主日历的 interpolatedWeeks 行数插值逻辑
  (currentPageOffsetFraction 在当前页与目标页行数间 lerp)
- 行高由 BoxWithConstraints 宽度推算(格宽=宽/7,aspectRatio(1f) 使行高=格宽)
- HorizontalPager 套 Modifier.height(px).clipToBounds(),跟随手指实时变高
- 迷你月历简化版:无折叠动画,只保留展开态 gridHeightPx = rowH * weeks
2026-07-09 17:14:54 +08:00
xfy
7b1290dd66 feat(shift): swipeable mini calendar via HorizontalPager
迷你月历接入 HorizontalPager,支持左右滑动翻月:
- 复用主日历 START_PAGE/pageToYearMonth/yearMonthToPage 工具
- viewYear/viewMonth 由 pagerState.currentPage 派生
- 箭头按钮改为 animateScrollToPage
- DatePicker 选月后 animateScrollToPage 跳转
- 网格提取为 MonthGrid 单页组件
2026-07-09 17:07:38 +08:00
xfy
1cf950817e feat(shift): tap year-month title to pick date in mini calendar
点击迷你月历顶部"年 月"标题弹出 DatePicker,
选定日期后跳转到对应月份,比连点箭头快。
2026-07-09 16:55:22 +08:00
xfy
62ed8bd09a fix(shift): align anchor date with cycle row and trim top padding
- 顶部内边距过高:Scaffold padding 已含 TopAppBar 间距,
  Column 去掉多余 vertical=8.dp,避免叠加
- 锚点日期右侧不齐:TextButton 自带内边距导致右边缘内缩,
  改为 Text+clickable 与"周期"行纯 Text 结构一致,右侧对齐
2026-07-09 16:46:38 +08:00
xfy
c68944bd55 feat(shift): undoable reset-to-default via Snackbar
恢复默认改为 Snackbar 撤销模式:
- 点恢复默认立即生效 + 显示 5 秒"撤销"Snackbar
- 点撤销恢复之前的 pattern
- 删除 AlertDialog 确认框(更现代,防误操作)
- 首次在项目引入 SnackbarHost
2026-07-09 16:38:57 +08:00
xfy
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
xfy
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
xfy
d8014b5154 test(shift): add safety-net tests for long-press rephase scenarios
锁定重构前行为:单次长按重排、连续两次长按、撤销。
作为 RephaseFlip 重构的回归基线。
2026-07-09 16:25:23 +08:00
xfy
66a054f2d8 feat(shift): long-press flips and rephases subsequent days
长按语义从"设相位断点"改为"翻转该天并从次日起重排":
- 翻转当天 override + 次日插入 PhaseBreak(重排起点)
- 后续按 cycle 自动顺延,匹配用户直觉
- 再次长按同一天可撤销(移除 override + 关联断点)
- 角标"断"改为"起",文案同步更新
2026-07-09 16:14:41 +08:00
xfy
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
xfy
32d66f0a42 fix(shift): subscribe shiftPattern to trigger recomposition on refresh 2026-07-06 19:09:26 +08:00
xfy
a5795b16dc feat(shift): add ShiftPatternActivity, Screen, and mini calendar grid 2026-07-06 18:52:16 +08:00
xfy
d528b98cde feat(shift): wire VM factory, onResume reload, settings menu entry 2026-07-06 18:41:07 +08:00
xfy
e08243d0fa test(shift): cover refreshShiftPattern reload after storage change 2026-07-06 18:37:47 +08:00
xfy
ef55ffcf64 feat(shift): inject ShiftPatternStorage into CalendarViewModel 2026-07-06 18:34:12 +08:00
xfy
1f1db17384 fix(shift): persist name field, guard empty cycle, test corrupt-data path 2026-07-06 18:30:40 +08:00
xfy
e4834a52c9 feat(shift): add ShiftPatternStorage for persistence 2026-07-06 18:24:28 +08:00
xfy
eca6c61058 test(shift): cover non-zero cycleOffset and multiple phase breaks; add kindAt KDoc 2026-07-06 18:20:48 +08:00
xfy
778d5dc8be feat(shift): support overrides and phase breaks in ShiftPattern 2026-07-06 18:14:24 +08:00
xfy
0fbbdfa444 feat: show rose day icon with priority over birthday crown 2026-06-16 18:06:50 +08:00
xfy
25885d84b3 feat: compute rose day flag in LunarCache 2026-06-16 17:59:00 +08:00
xfy
a8c2637a0c feat: add rose day vector drawable 2026-06-16 17:56:49 +08:00
xfy
e07ccd8b4e docs: update ui AGENTS.md for DogParkScreen 2026-06-16 16:38:20 +08:00
xfy
6532363cdb feat: add DogParkScreen for full-screen easter egg video 2026-06-16 16:15:09 +08:00
xfy
9d2f67b9fb feat: wire up version click easter egg in AboutScreen 2026-06-16 16:03:51 +08:00
xfy
6830c1e510 feat: add easter egg toast message logic with tests 2026-06-16 15:50:46 +08:00
xfy
3ab50ec900 assets: add dog park easter egg background video 2026-06-16 15:41:28 +08:00
xfy
bd4dad4794 chore(profile): 重新生成 Baseline/Startup Profile
benchmark buildType 已关闭 R8 混淆,重新生成 profile 后
plus.rua.project 下类名保持原始可读签名,避免 release
打包时 profile 匹配风险。
2026-06-16 14:41:25 +08:00
xfy
a731507b3b feat: 月视图年月支持日期选择器跳转
- MonthHeader 新增 onYearMonthClick 回调,点击年月文字打开日期选择器
- CalendarMonthView 集成 DatePickerDialog,选择日期后调用 selectDate
- 复用现有 CalendarPager 动画,跨月跳转时自动平滑翻页

同时包含之前的改动:
- 临时隐藏 SplashActivity 入口,改由 MainActivity 作为 LAUNCHER
- benchmark build type 关闭 R8 混淆与资源压缩,保证 profile 可读性
2026-06-16 14:19:41 +08:00
xfy
21327d572b feat(splash): add custom SplashActivity with background image 2026-06-16 13:11:43 +08:00
xfy
de329c2020 feat(splash): add dimmed dark-mode splash background 2026-06-16 12:36:49 +08:00
xfy
8204ae15cf feat(splash): use SplashScreen API with custom background 2026-06-16 12:27:12 +08:00
xfy
1f2fc8644f feat(splash): add reusable SplashScreen composable 2026-06-16 11:51:00 +08:00
xfy
d98579c2bf feat(splash): add launch background webp asset 2026-06-16 11:43:56 +08:00
xfy
f6b1ed7368 chore(baseline): 重新生成 Baseline Profile 与 Startup Profile 2026-06-16 10:51:38 +08:00
xfy
91068ded1c chore(baseline): regenerate baseline profile after startup optimizations 2026-06-15 19:17:16 +08:00
xfy
5bf8a85f7a Merge branch 'feature-birthday-crown' 2026-06-15 16:48:24 +08:00
xfy
3ca0d334e7 refactor: remove redundant icon content description and reorder DayCellImpl params 2026-06-15 16:45:58 +08:00
xfy
94861dc2f7 style: apply spotless formatting 2026-06-15 16:41:07 +08:00
xfy
de47509a32 feat: show tilted birthday crown with click bounce animation 2026-06-15 16:36:13 +08:00
xfy
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
xfy
f33e68d1db feat: compute birthday flag in LunarCache 2026-06-15 16:22:47 +08:00
xfy
06ac30e6d2 feat: compute birthday flag in LunarCache 2026-06-15 16:10:22 +08:00
xfy
7404bdfc28 feat: add birthday crown vector drawable 2026-06-15 16:03:41 +08:00
xfy
825eb526de feat(about): 将关于页面背景图优化为 WebP 2026-06-15 15:40:34 +08:00
xfy
9a09be56ef feat(about): 将 xiaogou_bg1.jpg 设为关于页面背景 2026-06-15 15:04:58 +08:00