yayacal/CLAUDE.md
xfy bf28008d17 refactor: Wave 1 — 构建清理、测试修复、文档修正、a11y 改进
- build: 清理版本目录死依赖(appcompat、core、material3)
- build: 精简 ProGuard keep 规则,仅保留热点路径和第三方库
- refactor: 重命名 PredictiveBackHandler → AppPredictiveBackHandler
- test: formatLunarDate 精确断言 + 闰月测试
- test: 统一测试命名风格(下划线),Unconfined → StandardTestDispatcher
- docs: 修正文档为纯 Android + Jetpack Compose 描述
- feat(a11y): 添加可访问性语义标注(WeekdayHeader heading、BottomCard 拖拽描述)
- feat: 为 DayCell、MonthHeader、WeekdayHeader、BottomCard 添加 @Preview

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 17:51:12 +08:00

4.7 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

YaYa is a calendar app built with pure Android + Jetpack Compose, targeting Android only. The UI is written entirely in Jetpack Compose with Material 3.

Build Commands

# Build Android debug APK
./gradlew :app:assembleDebug

# Install Android debug APK to connected device
./gradlew :app:installDebug

# Run core module tests
./gradlew :core:testDebugUnitTest

# Run a single test class
./gradlew :core:testDebugUnitTest --tests "plus.rua.project.ui.CalendarUtilsTest"

Gradle configuration cache and build cache are enabled by default (gradle.properties).

Architecture

Three-module structure:

  • :core — all Compose UI, ViewModel, and business logic (com.android.library)
  • :app — thin Android shell (MainActivityApp())
  • :macrobenchmark — Macrobenchmark module for Baseline Profile generation

Calendar UI composition (all in plus.rua.project.ui):

CalendarMonthView          ← top-level screen (MonthHeader + WeekdayHeader + pager + BottomCard)
  ├── MonthHeader          ← year/month label + ISO week number
  ├── WeekdayHeader        ← fixed "一二三四五六日" row
  ├── CalendarPager        ← HorizontalPager with Int.MAX_VALUE pages (month view)
  │     └── CalendarMonthPage  ← 6×7 grid of DayCell with collapse animation
  │           └── DayCell      ← single day circle with selection/today states
  ├── WeekPager            ← HorizontalPager for single-week view (collapsed state)
  │     └── DayCell
  ├── YearGridView         ← 4×3 mini-month grid with year navigation (year view)
  │     └── MiniMonth      ← compact month: title + weekday row + day numbers
  └── BottomCard           ← drag handle card, drives collapse/expand gestures

ShiftPattern (in plus.rua.project) defines personal shift cycles (WORK/OFF) independent of public holidays. Uses modular arithmetic: (date - anchorDate) mod cycle.size.

CalendarUtils (in plus.rua.project.ui) holds pager constants (START_PAGE = Int.MAX_VALUE/2, COLLAPSE_THRESHOLD = 0.25f) and page↔date arithmetic (pageToYearMonth, yearMonthToPage, pageToWeekMonday).

Collapse/expand animation: CalendarMonthView supports month↔week transition via CalendarViewModel.collapseProgress (0f=month, 1f=week). BottomCard captures vertical drag gestures and calls viewModel.onDrag()/onExpandDrag(). When progress crosses 50% on release, a spring animation snaps to the nearest state. CalendarMonthPage compresses non-selected weeks toward zero height during collapse. When fully collapsed, WeekPager replaces CalendarPager for efficient single-week paging.

Pager page mapping: Both CalendarPager and WeekPager use Int.MAX_VALUE pages centered at Int.MAX_VALUE / 2. Page-to-date conversion is arithmetic — no index-based list. CalendarPager maps pages to yearMonth; WeekPager maps pages to week-Monday dates. Both skip the initial snapshotFlow emission (.drop(1)) to preserve the "today" selection on first render.

CalendarViewModel holds selectedDate and isCollapsed state, computes month day grids (6×7=42 cells) and ISO week numbers. Week starts on Monday (ISO 8601).

Performance tracing: ComposeTrace.kt provides composeTraceBeginSection/composeTraceEndSection wrapping android.os.Trace. Custom markers are inserted at key points (e.g., MonthView:Compose, YearView:Compose, VM:collapseProgress) for Perfetto/Systrace analysis. See DEVELOPMENT.md for trace recording and Python parsing scripts.

Key Dependencies

  • Kotlin 2.3.21, Compose Multiplatform 1.11.0, Material 3 1.10.0-alpha05
  • kotlinx-datetime 0.8.0 for all date logic (no java.util.Calendar)
  • tyme4kt for Chinese traditional calendar (lunar dates, solar terms, festivals)
  • sketch 4.4.0 for animated GIF display (AsyncImage with sketch-animated-gif)
  • AGP 9.2.1, compileSdk/targetSdk 37, minSdk 24
  • JVM target: 17
  • R8 full mode enabled (android.enableR8.fullMode=true)

Conventions

  • Package: plus.rua.project (core), plus.rua.project.ui (UI composables)
  • Version catalog at gradle/libs.versions.toml — all dependency versions declared there
  • @Suppress("DEPRECATION") used for monthNumber access on kotlinx.datetime.LocalDate — must include inline comment explaining reason
  • UI text is in Chinese (weekday labels, month header format "2026年5月")
  • Public @Composable functions require KDoc per COMMENTS.md
  • Modifier parameter always last in composable signatures
  • Callback parameters use on prefix (onDateClick, onMonthChanged)