diff --git a/AGENTS.md b/AGENTS.md index 54113b1..8150a76 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -24,7 +24,10 @@ YaYa 是一款基于纯 Android + Jetpack Compose 构建的日历应用。应用 |-----------|---------| | `app/` | Android 应用壳层模块(见 `app/AGENTS.md`) | | `core/` | Android Library 核心模块:所有 Compose UI、ViewModel 和业务逻辑(见 `core/AGENTS.md`) | -| `gradle/` | Gradle Wrapper 文件 | +| `macrobenchmark/` | 宏基准测试模块,Baseline Profile 生成(见 `macrobenchmark/AGENTS.md`) | +| `gradle/` | Gradle Wrapper 文件(见 `gradle/wrapper/AGENTS.md`) | +| `scripts/` | 性能追踪脚本(见 `scripts/AGENTS.md`) | +| `logs/` | 性能追踪日志输出目录(见 `logs/AGENTS.md`) | ## For AI Agents diff --git a/app/AGENTS-anim.md b/app/AGENTS-anim.md new file mode 100644 index 0000000..29acbb3 --- /dev/null +++ b/app/AGENTS-anim.md @@ -0,0 +1,33 @@ + + + +# anim + +## Purpose +Activity 转场动画资源目录。定义 Activity 进入和退出的滑入/滑出动画效果,配合 `overridePendingTransition()` 使用。 + +## Key Files + +| File | Description | +|------|-------------| +| `slide_in_right.xml` | 从右侧滑入(duration: 350ms,fast_out_slow_in 插值器) | +| `slide_in_left.xml` | 从左侧滑入 | +| `slide_out_left.xml` | 向左侧滑出 | +| `slide_out_right.xml` | 向右侧滑出 | + +## Subdirectories +无 + +## For AI Agents + +### Working In This Directory +- 新增转场动画需同步更新对应 Activity 的 `overridePendingTransition()` 调用 +- 动画时长建议 300-400ms,使用 `fast_out_slow_in` 插值器保持 Material Design 一致性 + +## Dependencies + +### Internal +- `app/src/main/kotlin/plus/rua/project/AboutActivity.kt` — 使用 slide_in_right / slide_out_left +- `app/src/main/kotlin/plus/rua/project/LicensesActivity.kt` — 使用 slide_in_right / slide_out_left + + diff --git a/app/AGENTS-values.md b/app/AGENTS-values.md new file mode 100644 index 0000000..84725cd --- /dev/null +++ b/app/AGENTS-values.md @@ -0,0 +1,31 @@ + + + +# values + +## Purpose +Android 值资源目录,包含应用字符串和 Material 3 主题定义。 + +## Key Files + +| File | Description | +|------|-------------| +| `strings.xml` | 应用名称字符串(`app_name: YaYa`) | +| `themes.xml` | 日间主题:`Theme.Material.Light.NoActionBar` | + +## Subdirectories +无 + +## For AI Agents + +### Working In This Directory +- 新增字符串资源在此文件中定义 +- 主题继承自 `Theme.Material.Light.NoActionBar`,支持 `enableEdgeToEdge()` 全屏显示 +- 夜间模式主题在 `../values-night/themes.xml` 中定义 + +## Dependencies + +### Internal +- `app/src/main/AndroidManifest.xml` — 引用主题 + + diff --git a/app/src/main/AGENTS.md b/app/src/main/AGENTS.md index 419bfc6..a883ac0 100644 --- a/app/src/main/AGENTS.md +++ b/app/src/main/AGENTS.md @@ -27,7 +27,9 @@ Android 应用主 source set,包含入口 Activities、应用清单、主题 |-----------|---------| | `kotlin/plus/rua/project/` | Kotlin 源码(见 `kotlin/plus/rua/project/AGENTS.md`) | | `res/` | Android 资源文件(图标、主题、字符串、动画) | -| `assets/` | 原始资产文件(GIF 等) | +| `res/anim/` | Activity 转场动画 XML(见 `res/anim/AGENTS.md`) | +| `res/values/` | 字符串和主题定义(见 `res/values/AGENTS.md`) | +| `assets/` | 原始资产文件(GIF 等)(见 `assets/AGENTS.md`) | ## For AI Agents diff --git a/app/src/main/assets/AGENTS.md b/app/src/main/assets/AGENTS.md new file mode 100644 index 0000000..d23a126 --- /dev/null +++ b/app/src/main/assets/AGENTS.md @@ -0,0 +1,25 @@ + + + +# assets + +## Purpose +原始资产文件目录,存放不需要 Android 资源系统处理的二进制文件。当前包含 GIF 动画资源。 + +## Key Files + +无顶层文件 + +## Subdirectories + +| Directory | Purpose | +|-----------|---------| +| `gifs/` | GIF 动画资源(见 `gifs/AGENTS.md`) | + +## For AI Agents + +### Working In This Directory +- 新增原始资源文件直接放入此目录或其子目录 +- 通过 `AssetManager` 在运行时访问 + + diff --git a/app/src/main/assets/gifs/AGENTS.md b/app/src/main/assets/gifs/AGENTS.md new file mode 100644 index 0000000..8659a6f --- /dev/null +++ b/app/src/main/assets/gifs/AGENTS.md @@ -0,0 +1,33 @@ + + + +# gifs + +## Purpose +GIF 动画资源目录,存放应用使用的动画 GIF 文件(001.gif ~ 152.gif),由 `AnimatedGif` Composable 组件通过 `sketch` 库加载显示。 + +## Key Files + +| File | Description | +|------|-------------| +| `001.gif` ~ `152.gif` | 应用动画 GIF 资源 | + +## Subdirectories +无 + +## For AI Agents + +### Working In This Directory +- 替换或新增 GIF 时保持连续编号 +- GIF 文件较大,注意 APK 体积影响 +- `AnimatedGif` 组件使用 `sketch` 库异步加载和播放 + +## Dependencies + +### Internal +- `core/src/main/kotlin/plus/rua/project/ui/AnimatedGif.kt` — GIF 显示组件 + +### External +- `sketch` 4.4.0(GIF 解码和播放) + + diff --git a/core/src/main/assets/AGENTS.md b/core/src/main/assets/AGENTS.md new file mode 100644 index 0000000..df256ae --- /dev/null +++ b/core/src/main/assets/AGENTS.md @@ -0,0 +1,25 @@ + + + +# assets + +## Purpose +核心模块原始资产文件目录,与 `app/src/main/assets/` 镜像,包含 GIF 动画资源供 `AnimatedGif` Composable 组件加载。 + +## Key Files + +无顶层文件 + +## Subdirectories + +| Directory | Purpose | +|-----------|---------| +| `gifs/` | GIF 动画资源(见 `gifs/AGENTS.md`) | + +## For AI Agents + +### Working In This Directory +- 此目录与 `app/src/main/assets/` 内容同步 +- 通过 `AssetManager` 在运行时访问 + + diff --git a/core/src/main/assets/gifs/AGENTS.md b/core/src/main/assets/gifs/AGENTS.md new file mode 100644 index 0000000..8659a6f --- /dev/null +++ b/core/src/main/assets/gifs/AGENTS.md @@ -0,0 +1,33 @@ + + + +# gifs + +## Purpose +GIF 动画资源目录,存放应用使用的动画 GIF 文件(001.gif ~ 152.gif),由 `AnimatedGif` Composable 组件通过 `sketch` 库加载显示。 + +## Key Files + +| File | Description | +|------|-------------| +| `001.gif` ~ `152.gif` | 应用动画 GIF 资源 | + +## Subdirectories +无 + +## For AI Agents + +### Working In This Directory +- 替换或新增 GIF 时保持连续编号 +- GIF 文件较大,注意 APK 体积影响 +- `AnimatedGif` 组件使用 `sketch` 库异步加载和播放 + +## Dependencies + +### Internal +- `core/src/main/kotlin/plus/rua/project/ui/AnimatedGif.kt` — GIF 显示组件 + +### External +- `sketch` 4.4.0(GIF 解码和播放) + + diff --git a/core/src/main/kotlin/plus/rua/project/ui/CalendarMonthView.kt b/core/src/main/kotlin/plus/rua/project/ui/CalendarMonthView.kt index 91ee412..4982e39 100644 --- a/core/src/main/kotlin/plus/rua/project/ui/CalendarMonthView.kt +++ b/core/src/main/kotlin/plus/rua/project/ui/CalendarMonthView.kt @@ -143,8 +143,7 @@ fun CalendarMonthView( snapshotFlow { yearPagerState.settledPage }.collect { page -> if (page != lastSettledPage) { val diff = page - lastSettledPage - val newYear = viewModel.yearViewYear.value + diff - viewModel.setYearViewYear(newYear) + viewModel.setYearViewYear(viewModel.yearViewYear.value + diff) lastSettledPage = page } } @@ -289,7 +288,7 @@ fun CalendarMonthView( } else { pageOffset } - val pageYear = yearViewYear + (page - yearPagerState.currentPage) + val pageYear = yearViewYear + (page - yearPagerState.settledPage) YearGridView( year = pageYear, selectedMonth = if (pageYear == currentYear) currentMonth else 0, diff --git a/gradle/wrapper/AGENTS.md b/gradle/wrapper/AGENTS.md new file mode 100644 index 0000000..87e899b --- /dev/null +++ b/gradle/wrapper/AGENTS.md @@ -0,0 +1,31 @@ + + + +# wrapper + +## Purpose +Gradle Wrapper 目录,包含 `gradle-wrapper.jar` 和 `gradle-wrapper.properties`。Wrapper 允许项目在没有预装 Gradle 的环境中使用固定版本的 Gradle 构建。 + +## Key Files + +| File | Description | +|------|-------------| +| `gradle-wrapper.jar` | Gradle Wrapper 可执行 JAR | +| `gradle-wrapper.properties` | Wrapper 配置:Gradle 发行版 URL(当前 9.5.1) | + +## Subdirectories +无 + +## For AI Agents + +### Working In This Directory +- 通常不需要手动修改此目录内容 +- 升级 Gradle 版本时使用 `./gradlew wrapper --gradle-version=X.Y.Z` +- `gradle-wrapper.properties` 中的 `distributionUrl` 指向 Gradle 官方发行版 + +## Dependencies + +### External +- Gradle 9.5.1 + + diff --git a/macrobenchmark/AGENTS.md b/macrobenchmark/AGENTS.md new file mode 100644 index 0000000..ba3d058 --- /dev/null +++ b/macrobenchmark/AGENTS.md @@ -0,0 +1,44 @@ + + + +# macrobenchmark + +## Purpose +宏基准测试模块,使用 Android Baseline Profile 技术自动生成启动优化配置文件。通过 UI Automator 模拟真实用户交互路径,收集 AOT 编译所需的 profile 数据。 + +## Key Files + +| File | Description | +|------|-------------| +| `build.gradle.kts` | 模块构建配置(`com.android.test` 插件、benchmark 构建类型、Baseline Profile 自动复制任务) | + +## Subdirectories + +| Directory | Purpose | +|-----------|---------| +| `src/main/java/plus/rua/project/baseline/` | Baseline Profile 生成器(见 `src/main/java/plus/rua/project/baseline/AGENTS.md`) | + +## For AI Agents + +### Working In This Directory +- 修改此模块需连接 Android 设备/模拟器运行 +- Baseline Profile 一键生成:`./gradlew :macrobenchmark:updateBaselineProfile` +- 仅运行基准测试:`./gradlew :macrobenchmark:connectedBenchmarkAndroidTest` +- 生成的 profile 自动复制到 `core/src/main/baseline-prof.txt` + +### Testing Requirements +- 需要已安装应用的 benchmark 构建类型 +- 模拟器需启用 GPU 加速(software renderer 不支持 gfxinfo framestats) + +## Dependencies + +### Internal +- `:app` 模块 — 目标测试应用 +- `:core` 模块 — profile 自动复制到 `core/src/main/baseline-prof.txt` + +### External +- `androidx.benchmark:benchmark-macro-junit4` +- `androidx.test.uiautomator` +- `androidx.test.ext:junit` + + diff --git a/macrobenchmark/src/main/java/plus/rua/project/baseline/AGENTS.md b/macrobenchmark/src/main/java/plus/rua/project/baseline/AGENTS.md new file mode 100644 index 0000000..aaa39cd --- /dev/null +++ b/macrobenchmark/src/main/java/plus/rua/project/baseline/AGENTS.md @@ -0,0 +1,35 @@ + + + +# baseline + +## Purpose +Baseline Profile 自动生成器。通过 UI Automator 模拟完整用户交互路径(冷启动、FAB 展开、年/月视图切换、日期选择、折叠/展开、关于页、开源许可页),生成 AOT 编译优化所需的 startup profile。 + +## Key Files + +| File | Description | +|------|-------------| +| `BaselineProfileGenerator.kt` | Profile 生成测试类,覆盖全部用户交互路径 | + +## Subdirectories +无 + +## For AI Agents + +### Working In This Directory +- 新增交互路径需在 `BaselineProfileGenerator.kt` 的 `profileBlock` 中添加对应步骤 +- 使用 `device.findObject(By.res(...))` 或 `device.findObject(By.text(...))` 定位 UI 元素 +- 每个操作后调用 `device.waitForIdle()` 等待动画完成 + +### Testing Requirements +- 运行:`./gradlew :macrobenchmark:updateBaselineProfile` +- 需要设备/模拟器连接,应用已安装在 benchmark 构建类型下 + +## Dependencies + +### External +- `androidx.benchmark.macro.junit4.BaselineProfileRule` +- `androidx.test.uiautomator` + + diff --git a/scripts/AGENTS.md b/scripts/AGENTS.md new file mode 100644 index 0000000..ab4f45a --- /dev/null +++ b/scripts/AGENTS.md @@ -0,0 +1,37 @@ + + + +# scripts + +## Purpose +开发辅助脚本目录,包含性能追踪工具。使用 Perfetto 在设备上抓取应用 trace,并生成结构化报告。 + +## Key Files + +| File | Description | +|------|-------------| +| `profile.sh` | Perfetto 性能追踪脚本:抓取 trace、帧统计、内存快照,生成 Markdown 报告 | + +## Subdirectories +无 + +## For AI Agents + +### Working In This Directory +- 修改脚本后确保 `adb` 可用性检查和设备连接检测逻辑保持完整 +- 脚本输出到 `logs/` 目录(trace、framestats、meminfo、report) + +### Testing Requirements +- 需要已安装 `adb` 和连接的设备 +- 应用需已安装:`./gradlew :app:installDebug` + +## Dependencies + +### Internal +- `logs/` — 脚本输出目录 + +### External +- Android SDK `adb` +- 设备上的 `perfetto` 工具 + +