ffafee550e
Merge branch 'feat/record-detail-image-lightbox'
2026-07-22 15:23:53 +08:00
70c97ed9d5
revert(photo-editor): 恢复点击裁剪 icon 进入裁剪的交互
...
撤销"切到裁剪 tab 自动进入裁剪"的改动,保留原来的两步操作:
点击下方裁剪 icon 进入裁剪模式,再次点击 ✓ 确认裁剪。
ViewModel 恢复 toggleCrop,删除无用的 enterCrop/exitCrop;
保留裁剪框拖动的 bug 修复(本地累积值 + rememberUpdatedState)。
2026-07-22 15:20:13 +08:00
d3ebd6829b
fix(photo-editor): 修复裁剪框拖动的闭包快照陷阱
...
pointerInput(Unit) 的手势 lambda 只在首次组合捕获一次 state,
后续 onDragStart 读的是过期快照,导致再次拖动从中心开始。
改用本地累积值绕开 StateFlow 往返:onDragStart 把 state 快照到
mutableFloatStateOf,onDrag 每帧在累积值上叠加增量,onDragEnd
一次性提交。onDragStart 通过 rememberUpdatedState 读最新 state。
enterCrop 改为幂等(已启用则保留当前框),避免 LaunchedEffect
因 editorState 变化重触时冲掉用户拖动结果。
2026-07-22 15:18:19 +08:00
b8509381d9
fix(photo-editor): 修复裁剪 tab 流程与裁剪框拖动
...
两个问题:
1. 切到裁剪 tab 后还要再点裁剪 icon 才进入裁剪——改为切 tab 即自动进入,
底部按钮由"开关裁剪"改为"✓ 确认裁剪",点击烘焙裁剪并保留在 tab。
2. 裁剪框无法移动——重写 CropOverlay 拖动逻辑:
- 加 BODY 整体平移(拖框内区域平移整框)
- onDrag 每帧从 state 读实时裁剪值叠加增量,修复闭包快照导致的抖动
- dragHandle 内聚到组件内部,消除跨重组延迟
- 抽出 hitHandle/moveCrop,四角与整体均带边界约束防交叉越界
ViewModel 新增 enterCrop/exitCrop/applyCrop,删除 toggleCrop。
2026-07-22 14:34:42 +08:00
cec8debff0
feat(date-recorder): 详情页图片灯箱,支持缩放/旋转手势
...
点击详情页大图弹出全屏深色遮罩,集成 panpf/zoomimage 的
SketchZoomAsyncImage,支持双指缩放、平移、捻合旋转(松手吸附
0/90/180/270°)与双击复位,点空白或返回键关闭。
新增 zoomimage-compose-sketch4 1.6.0 依赖(与项目 sketch 同作者,
SketchZoomAsyncImage 是 AsyncImage 超集,额外提供缩放/旋转/大图分片)。
2026-07-22 14:26:27 +08:00
d47a38bc19
feat(date-recorder): 美化记录器界面,卡片图上叠加文字、排序菜单精简
...
- 网格卡片:照片铺满整卡,底部渐变蒙层叠加标题与拍摄日期
- 网格改为自适应约 3 列,间距 8dp→4dp,卡片圆角 12dp→8dp
- 排序菜单 6 项精简为 3 个字段项,点击已选字段切换升降序
- 新增 RecordSortOrder.nextAfter 纯函数及单元测试
2026-07-20 18:28:39 +08:00
b589800eda
refactor: 记录编辑页复用共享 formatLocalDate
2026-07-20 17:25:08 +08:00
0d83fef3a9
feat: 新建记录标题预填拍摄日期并支持联动
2026-07-20 17:23:33 +08:00
94e81bffb1
docs: 新建记录标题预填默认值设计规格
2026-07-20 15:54:59 +08:00
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
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
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
b2942a3ca9
chre: lint CLAUDE.md to AGENTS.md
2026-07-17 13:25:13 +08:00
2e61fea21b
chore: add .zcode to git ginore
2026-07-17 13:24:46 +08:00
a1c71c2b93
chore: remove useless docs
2026-07-17 13:24:18 +08:00
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
c665adfeff
release: v1.3.0
v1.3.0
2026-07-09 17:21:57 +08:00
afea8bf109
feat: refactor shift pattern with atomic rephase and swipeable calendar
...
班次设置页重构与体验增强:
数据模型重构:
- phaseBreaks + override 两独立字段 → 原子 RephaseFlip(date, flippedTo, rephaseFrom)
- 解决幽灵重排/撤销误删/断点链不级联三大问题
体验改进:
- 角标颜色按类别配对(onPrimary/onError/onTertiary)
- 迷你月历动态行数(复用 getMonthGridInfo)
- 恢复默认改 Snackbar 撤销(首次引入 SnackbarHost)
- 锚点日期与周期行右侧对齐修复
- 点击年月标题弹 DatePicker 选月份跳转
- HorizontalPager 滑动翻月 + 高度插值平滑过渡
2026-07-09 17:16:45 +08:00
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
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
1cf950817e
feat(shift): tap year-month title to pick date in mini calendar
...
点击迷你月历顶部"年 月"标题弹出 DatePicker,
选定日期后跳转到对应月份,比连点箭头快。
2026-07-09 16:55:22 +08:00
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
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
14a3239b39
feat: shift pattern settings page
...
个人轮班设置页:独立 Activity + SharedPreferences 持久化 + onResume 立即生效。
数据模型支持:
- 基础周期(锚点 + 班次序列)
- 单日翻转 overrides(调班)
- 相位断点 phaseBreaks(从某天起重排周期相位)
UI:
- FAB 菜单"班次设置"入口
- 基础周期预设(1班1休/2班2休/3班3休/4班4休)+ 锚点 DatePicker
- 迷你月历(点=翻转班休,长按=设/清断点)
- 恢复默认
实现:TDD,6 任务逐个 spec + 代码质量审查。
2026-07-07 09:36:44 +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
5afac5dd04
docs: add shift pattern settings design spec
...
个人轮班设置页设计:独立 Activity + SharedPreferences + onResume 重读。
数据模型支持单日 override + 相位断点重排,完整覆盖调班场景。
2026-07-06 16:43:03 +08:00
08a6016479
chore(deps): bump stable dependencies
...
- composeBom 2026.05.01 -> 2026.06.01
- androidx-lifecycle 2.10.0 -> 2.11.0
- androidx-uiautomator 2.3.0 -> 2.4.0
- tyme4kt 1.4.5 -> 1.5.0
- spotless 8.5.1 -> 8.8.0
Verified via :app:assembleDebug and :core:testDebugUnitTest.
2026-07-06 14:26:48 +08:00
db31b9eaed
chore: add project-level yayacal-release skill
2026-06-18 15:21:48 +08:00
fae7654452
release: v1.2.0
v1.2.0
2026-06-18 15:07:09 +08:00
4be8cada86
调整应用图标小黄鸭占比
2026-06-18 13:43:50 +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
283a474eb1
docs: add rose day icon design spec
2026-06-16 17:38:55 +08:00
e07ccd8b4e
docs: update ui AGENTS.md for DogParkScreen
2026-06-16 16:38:20 +08:00
3fcdeab702
feat: navigate to DogParkActivity from AboutActivity
2026-06-16 16:31:01 +08:00
ac48a56465
feat: add DogParkActivity with fade-in entry transition
2026-06-16 16:24:10 +08:00