From 02f0260dfcc551c161e10fec9411fa675a078673 Mon Sep 17 00:00:00 2001 From: Mavis Date: Wed, 10 Jun 2026 14:11:43 +0800 Subject: [PATCH] =?UTF-8?q?docs(android):=20=E5=AE=8C=E6=95=B4=E6=96=B9?= =?UTF-8?q?=E6=A1=88=20+=20logo=20=E8=B5=84=E6=BA=90=20+=20=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 docs/android/ 目录: - README.md 总入口(快速上手 + 决策摘要 + 数据流) - 01-architecture.md 模块划分 + 数据流 + 选型理由 - 02-api-contract.md 每个接口的请求/响应 + DTO 字段映射 - 03-build-run.md Gradle/SDK/网络安全白名单/真机调试 - 04-milestones.md 7 天里程碑 + DoD + E2E 测试场景 新增 assets/: - logo/: 主图标 master + adaptive icon + 5 DPI launcher (方/圆) - splash/: 启动屏 logo + 完整背景预览 + 5 DPI 资源 - android_resources/: 集成所需的 XML(adaptive icon/主题/颜色/字符串/drawable/layout) - INTEGRATION.md 集成指南 - logo.svg + _make_logo.py 设计源 设计风格:参考用户提供的木质方块字母积木图,米色木纹底 + 深棕色字母 D,代表 'Diary',温暖私人日记感。 服务器体检:所有容器/API/DB/翻译主链路正常,TMT 本月已用 0.37%。 MaaS 备用通道上次已验证可用。 --- docs/android/01-architecture.md | 371 +++++++++++ docs/android/02-api-contract.md | 585 +++++++++++++++++ docs/android/03-build-run.md | 602 ++++++++++++++++++ docs/android/04-milestones.md | 273 ++++++++ docs/android/README.md | 179 ++++++ docs/android/assets/INTEGRATION.md | 230 +++++++ docs/android/assets/_make_logo.py | 289 +++++++++ .../drawable/splash_screen.xml | 28 + .../layout/activity_splash.xml | 43 ++ .../mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../values/colors_splash.xml | 7 + .../values/dimens_splash.xml | 5 + .../values/strings_splash.xml | 6 + .../values/themes_splash.xml | 23 + docs/android/assets/logo.svg | 99 +++ .../assets/logo/ic_launcher_background.png | Bin 0 -> 2185 bytes .../assets/logo/ic_launcher_foreground.png | Bin 0 -> 7259 bytes .../assets/logo/icon_foreground_1024.png | Bin 0 -> 17113 bytes docs/android/assets/logo/icon_master_1024.png | Bin 0 -> 18447 bytes .../assets/logo/mipmap-hdpi/ic_launcher.png | Bin 0 -> 4313 bytes .../logo/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 1532 bytes .../assets/logo/mipmap-mdpi/ic_launcher.png | Bin 0 -> 3001 bytes .../logo/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 966 bytes .../assets/logo/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 5748 bytes .../logo/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 2021 bytes .../assets/logo/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 8600 bytes .../logo/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 2930 bytes .../logo/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 11643 bytes .../logo/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 3585 bytes .../splash/drawable-hdpi/ic_splash_logo.png | Bin 0 -> 5460 bytes .../splash/drawable-mdpi/ic_splash_logo.png | Bin 0 -> 3822 bytes .../splash/drawable-xhdpi/ic_splash_logo.png | Bin 0 -> 7275 bytes .../splash/drawable-xxhdpi/ic_splash_logo.png | Bin 0 -> 10536 bytes .../drawable-xxxhdpi/ic_splash_logo.png | Bin 0 -> 13701 bytes docs/android/assets/splash/splash_bg_full.png | Bin 0 -> 46649 bytes docs/android/assets/splash/splash_logo.png | Bin 0 -> 9544 bytes 37 files changed, 2750 insertions(+) create mode 100644 docs/android/01-architecture.md create mode 100644 docs/android/02-api-contract.md create mode 100644 docs/android/03-build-run.md create mode 100644 docs/android/04-milestones.md create mode 100644 docs/android/README.md create mode 100644 docs/android/assets/INTEGRATION.md create mode 100644 docs/android/assets/_make_logo.py create mode 100644 docs/android/assets/android_resources/drawable/splash_screen.xml create mode 100644 docs/android/assets/android_resources/layout/activity_splash.xml create mode 100644 docs/android/assets/android_resources/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 docs/android/assets/android_resources/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 docs/android/assets/android_resources/values/colors_splash.xml create mode 100644 docs/android/assets/android_resources/values/dimens_splash.xml create mode 100644 docs/android/assets/android_resources/values/strings_splash.xml create mode 100644 docs/android/assets/android_resources/values/themes_splash.xml create mode 100644 docs/android/assets/logo.svg create mode 100644 docs/android/assets/logo/ic_launcher_background.png create mode 100644 docs/android/assets/logo/ic_launcher_foreground.png create mode 100644 docs/android/assets/logo/icon_foreground_1024.png create mode 100644 docs/android/assets/logo/icon_master_1024.png create mode 100644 docs/android/assets/logo/mipmap-hdpi/ic_launcher.png create mode 100644 docs/android/assets/logo/mipmap-hdpi/ic_launcher_round.png create mode 100644 docs/android/assets/logo/mipmap-mdpi/ic_launcher.png create mode 100644 docs/android/assets/logo/mipmap-mdpi/ic_launcher_round.png create mode 100644 docs/android/assets/logo/mipmap-xhdpi/ic_launcher.png create mode 100644 docs/android/assets/logo/mipmap-xhdpi/ic_launcher_round.png create mode 100644 docs/android/assets/logo/mipmap-xxhdpi/ic_launcher.png create mode 100644 docs/android/assets/logo/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 docs/android/assets/logo/mipmap-xxxhdpi/ic_launcher.png create mode 100644 docs/android/assets/logo/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 docs/android/assets/splash/drawable-hdpi/ic_splash_logo.png create mode 100644 docs/android/assets/splash/drawable-mdpi/ic_splash_logo.png create mode 100644 docs/android/assets/splash/drawable-xhdpi/ic_splash_logo.png create mode 100644 docs/android/assets/splash/drawable-xxhdpi/ic_splash_logo.png create mode 100644 docs/android/assets/splash/drawable-xxxhdpi/ic_splash_logo.png create mode 100644 docs/android/assets/splash/splash_bg_full.png create mode 100644 docs/android/assets/splash/splash_logo.png diff --git a/docs/android/01-architecture.md b/docs/android/01-architecture.md new file mode 100644 index 0000000..c259cca --- /dev/null +++ b/docs/android/01-architecture.md @@ -0,0 +1,371 @@ +# 01 · 架构 + +> 回答 3 个问题:**模块怎么分?数据怎么流?为啥这样选?** + +--- + +## 1. 模块划分 + +原则:**单 module + 按包分层**。MVP 不上多 module,等过 80 个 Kotlin 文件再拆 `:data` `:domain` `:ui` 三个 Gradle module。 + +### 1.1 顶层包结构 + +``` +com.diary.news +├── DiaryNewsApp.kt # @HiltAndroidApp +├── MainActivity.kt # @AndroidEntryPoint,Compose host +│ +├── data/ # ─── 数据层(对外接口 + 缓存)─── +│ ├── api/ +│ │ ├── ApiService.kt # Retrofit interface +│ │ ├── dto/ # 12 个文件,与后端 schema 一一对应 +│ │ ├── AuthInterceptor.kt # 加 Bearer +│ │ └── TokenAuthenticator.kt # 401 自动 refresh +│ ├── auth/ +│ │ ├── TokenStore.kt # EncryptedSharedPreferences 封装 +│ │ └── AuthRepository.kt +│ ├── db/ +│ │ ├── AppDatabase.kt +│ │ ├── dao/ +│ │ └── entity/ +│ └── repository/ # ─── 业务仓储 ─── +│ ├── ArticleRepository.kt +│ ├── BookmarkRepository.kt +│ └── SourceRepository.kt +│ +├── domain/ # ─── 纯 Kotlin 业务模型(无 Android 依赖)─── +│ └── model/ +│ ├── Article.kt +│ ├── Source.kt +│ ├── Bookmark.kt +│ └── ... +│ +├── di/ # ─── Hilt 模块 ─── +│ ├── NetworkModule.kt # Retrofit + OkHttp + Interceptor +│ ├── DatabaseModule.kt # Room +│ └── RepositoryModule.kt # @Binds 绑定 interface → impl +│ +└── ui/ # ─── 表现层(Compose)─── + ├── theme/ + │ ├── Theme.kt # Material3 + 蓝主题 + │ ├── Color.kt + │ └── Type.kt + ├── nav/ + │ └── AppNav.kt # Navigation Compose + ├── login/ + │ ├── LoginScreen.kt + │ └── LoginViewModel.kt + ├── feed/ + │ ├── FeedScreen.kt + │ ├── FeedViewModel.kt + │ └── ArticlePagingSource.kt + ├── article/ + │ ├── ArticleScreen.kt + │ ├── ArticleViewModel.kt + │ └── ArticleTabs.kt # 评论/译文/原文 三段 Tab + ├── bookmarks/ + │ ├── BookmarksScreen.kt + │ └── BookmarksViewModel.kt + ├── sources/ + │ ├── SourcesScreen.kt + │ └── SourcesViewModel.kt + └── common/ # 通用组件 + ├── ArticleCard.kt + ├── CommentaryBox.kt + ├── EmptyState.kt + ├── ErrorState.kt + └── LoadingState.kt +``` + +### 1.2 分层依赖关系(单向) + +``` +ui ──→ domain ──→ data ──→ (Retrofit / Room) + ↑ + └─ TokenStore(被 ApiService 和 AuthRepository 共用) +``` + +**关键约束**: +- `domain` **不依赖 Android SDK**(纯 Kotlin,为了以后能抽出来 JVM 跑单元测试) +- `data` 可以依赖 Android SDK(`Context` for EncryptedSharedPreferences / Room) +- `ui` 唯一允许持有 `Context` 的层,通过 Hilt `@ApplicationContext` 注入 + +### 1.3 为什么不现在分 Gradle module + +| 拆 module 的好处 | 不拆的好处(现阶段)| +|---|---| +| 强制分层 | 编译快(单 module 增量编译 5s,多 module 30s+)| +| 增量 build 更快 | 心智负担低,新功能加上去就完了 | +| 团队人多时并行开发 | 适合 1-2 人小项目 | + +**触发拆 module 的信号**:Kotlin 文件 > 80,或 build 时间 > 60s。 + +--- + +## 2. 数据流 + +### 2.1 三种典型场景 + +#### 场景 A:列表(分页 + 缓存无关) + +``` +FeedScreen + └─ FeedViewModel.pager: Flow> + └─ Pager(config = PagingConfig(pageSize =50)) + └─ ArticlePagingSource + └─ load(page): ApiService.listArticles(page, page_size =50) + └─ 返回 ArticleListResponseDto + └─ DTO → domain.Article mapper + └─ PagingData → LazyColumn +``` + +**为什么用 Paging 3 而不是 LazyColumn + 自己管 offset**: +- 预取(滑到底前 3 个就开始加载下一页) +- 失败重试只重试那一页 +- 内存上限自动管(滑走的会被回收) +- 后续要换成 Room-backed `RemoteMediator` 也是几行代码 + +#### 场景 B:详情(单次拉取 + Room 缓存) + +``` +ArticleScreen(articleId) + └─ ArticleViewModel.uiState: StateFlow + └─ load(id): + ├─ Room.bookmarkDao.findById(id) → 看是否已收藏(乐观更新用) + ├─ ApiService.getArticle(id) + └─ 合并 → UiState.Success(article, isBookmarked) +``` + +**Room 这里只缓存 bookmark 表**(不是 article 表)。原因见 §3。 + +#### 场景 C:登录 + +``` +LoginScreen + └─ LoginViewModel.login(username, password) + └─ AuthRepository.login() + ├─ ApiService.login(LoginRequest) + └─ TokenStore.save(access, refresh, expiresAt) + └─ 触发 SharedFlow + └─ MainActivity 监听 → 导航到 Feed +``` + +### 2.2 异常 / 401 处理 + +``` +ApiService 任意调用 → OkHttp chain + ├─ AuthInterceptor: 加 Authorization: Bearer + └─ server 返回 401 + ↓ +OkHttp 调 TokenAuthenticator.authenticate(route, response) + ├─ 检查:是不是 /auth/refresh 自己 401? 是 → 清 token,返回 null(放弃) + ├─ synchronized(this) { ... } ← 单飞锁,防并发 refresh + ├─ 当前 in-memory token ≠ request 里用的? 是 → 说明别的线程刚刷过,直接用新 token 重试 + ├─ POST /auth/refresh { refresh_token } → 新 token pair + ├─ TokenStore.save(新 token pair) + └─ 重发原 request(自动) +``` + +### 2.3 线程模型 + +| 操作 | 调度器 | 备注 | +|---|---|---| +| UI 渲染 | Main(自动)| `LaunchedEffect` / `collectAsState` | +| Retrofit `suspend fun` | IO(Retrofit 自动切)| 别用 `withContext(Dispatchers.IO)` 包 | +| Room 查询 | IO(Room 自动切)| 同上 | +| Token 读写 SP | IO(用 `flow` API)| 别在主线程 read/write | +| 图片解码 | Coil 自动 | 别手切线程 | + +**铁律**:**不要在 `Main` 干 IO**。Compose 的 `LaunchedEffect` 是 Main,默认别在里面跑阻塞调用。 + +--- + +## 3. 本地存储策略 + +### 3.1 三种数据,三种归宿 + +| 数据 | 存储位置 | 加密 | 生命周期 | +|---|---|---|---| +| `access_token` / `refresh_token` | EncryptedSharedPreferences | ✅ Keystore | 用户清 app 数据才消失 | +| 收藏列表(`bookmarks`)| Room | ❌(本机隐私)| 卸载即清 | +| 文章列表当前可见页 | 不缓存(每次拉)| — | — | +| 已读标记(可选, MVP 不做)| Room | ❌ | 卸载即清 | + +### 3.2 为什么 article 列表不缓存 + +- 后端每次返回最新翻译(LLM 增强是异步的,可能上次拉时是 pending,这次拉变 ok) +- 缓存旧版会让用户疑惑"为啥我刷了半天内容没变" +- Room 全文索引占空间,翻译正文动辄几 KB +- 列表失败时显示 Snackbar 提示 + 空状态,够了 + +### 3.3 Room schema(MVP 只要一张表) + +```kotlin@Entity(tableName = "bookmarks_cache", primaryKeys = ["userId", "articleId"]) +data class BookmarkCacheEntity( + val userId: Long, + val articleId: Long, + val title: String, + val titleZh: String?, + val bodyZhText: String?, // 离线展示用 + val publishedAt: String?, // ISO 8601 + val sourceName: String, + @ColumnInfo(name = "synced_at") val syncedAt: Long = System.currentTimeMillis(), +) + +@Dao +interface BookmarkDao { + @Query("SELECT * FROM bookmarks_cache WHERE userId = :userId ORDER BY synced_at DESC") + fun observe(userId: Long): Flow> + + @Query("SELECT articleId FROM bookmarks_cache WHERE userId = :userId") + suspend fun ids(userId: Long): List + + @Insert(onConflict = REPLACE) + suspend fun upsertAll(items: List) + + @Query("DELETE FROM bookmarks_cache WHERE userId = :userId") + suspend fun clear(userId: Long) +} +``` + +**用途**: +- 离线可看收藏列表(标题 + 译文正文) +- 详情页打开时秒判 `isBookmarked`(不用每次都 GET /bookmarks) + +--- + +## 4. 关键依赖选型理由 + +### 4.1 Retrofit vs Ktor Client + +| 维度 | Retrofit | Ktor Client | +|---|---|---| +| Android 生态 | ✅ 10 年沉淀,Coil/Paging 都有 adapter | ❌ KMP 偏多,Android 教程少 | +| 拦截器 | ✅ 完善(Authenticator / Interceptor)| ✅ 也有但 API 不一样 | +| 团队熟悉度 | ✅ 大多数 Android 团队都会 | ❌ 新 | +| 大小 | ~150KB | ~300KB | + +**结论**:Retrofit,成熟压倒一切。 + +### 4.2 kotlinx.serialization vs Moshi + +| 维度 | kotlinx.serialization | Moshi | +|---|---|---| +| 编译期生成 | ✅ KSP(快)| ❌ KAPT(慢)| +| 与 Kotlin 特性 | ✅ Sealed class / value class 一流 | ⚠️ 需要额外 adapter | +| 学习曲线 | ✅ `@Serializable` 一行 | ⚠️ 需要手动 adapter | + +**结论**:kotlinx.serialization,我们后端 Pydantic 是声明式,客户端也用声明式,心智一致。 + +### 4.3 Hilt vs Koin + +| 维度 | Hilt | Koin | +|---|---|---| +| 编译期 | ✅(编译时检查依赖图) | ❌ 运行时崩 | +| 启动速度 | ✅ 零反射 | ⚠️ 启动慢 | +| 与 Jetpack 集成 | ✅ ViewModel / Worker 原生 | ⚠️ 手动 `viewModel { }` | +| 学习曲线 | ⚠️ 注解多 | ✅ DSL 友好 | + +**结论**:Hilt,Jetpack 集成 + 编译期校验。 + +### 4.4 Coil vs Glide vs Fresco + +| 维度 | Coil | Glide | Fresco | +|---|---|---|---| +| Compose 支持 | ✅ 一等公民 | ⚠️ 用 GlideImage 包一层 | ❌ 没 Compose | +| 包大小 | ~250KB | ~500KB | ~2MB | +| 性能 | 高 | 高 | 极高(过度工程)| + +**结论**:Coil,Compose 原生。 + +### 4.5 Paging 3 vs 手写 + +**结论**:Paging 3,理由见 §2.1。 + +### 4.6 不用的东西 + +| 东西 | 为啥不用 | +|---|---| +| RxJava | 现在 Coroutines + Flow 完全够用 | +| Dagger 2(纯)| Hilt 是 Dagger 的 Android 简化版 | +| LiveData | StateFlow 完全替代 | +| MMKV | EncryptedSharedPreferences 已够,MMKV 是 Tencent 的另选 | +| Volley | 过时 | + +--- + +## 5. 安全架构 + +### 5.1 Token 流转 + +``` +LoginScreen 输入 + ↓ HTTPS? ❌(我们 HTTP,见 network_security_config) + ↓ 走明文 HTTP POST /auth/login + ↓ server 返回 { access_token, refresh_token } + ↓ TokenStore.save: + ├─ MasterKey(AES256_GCM) 由 Android Keystore 保护 + ├─ prefs.put("access", access_token) // AES256_SIV 加密 key + ├─ prefs.put("refresh", refresh_token) // AES256_GCM 加密 value + └─ 写盘 + ↓ 后续每次请求 + ↓ AuthInterceptor 读 SP → in-memory cache → 加 Bearer header +``` + +### 5.2 Network Security Config(精准白名单) + +```xml + + + + + + + + 207.57.129.228 + + +``` + +**为什么是白名单而不是全开 `cleartextTrafficPermitted="true"`**: +- 万一以后引入了第三方 SDK(广告 / 统计),不会偷偷走 HTTP +- 出问题时,review 更容易 +- 业界 best practice + +### 5.3 不做的事 + +- ❌ 不存用户密码(只存服务端返回的 token) +- ❌ 不在 logcat 输出 token(debug build 用 Timber 自动 redact) +- ❌ 不让 WebView 跑 JS(`body_zh_formatted` 是 HTML 片段,不是完整文档) +- ❌ 不 root 检测(私人 app,没必要恶心自己) + +--- + +## 6. 测试策略(MVP 阶段) + +| 层级 | 工具 | 覆盖率目标 | +|---|---|---| +| 单元测试(domain 层)| JUnit 5 + MockK | domain 逻辑 80%+ | +| ViewModel 测试 | Turbine + MockK | 关键 ViewModel | +| Repository 测试 | MockWebServer + Room in-memory | 网络 + DB 集成 | +| UI 测试 | Compose Test | 登录 + 列表各 1 个 happy path | +| 手工 | 真机刷一遍 | 7 天里程碑 DoD(见 04)| + +**先不写 UI 测试**,等主流程跑通再补。 + +--- + +## 7. 未来扩展点 + +下面这些**不影响当前架构**,需要时再加: + +| 扩展 | 改动量 | 备注 | +|---|---|---| +| 多账号切换 | TokenStore 改成 `Map` | 1 天 | +| 推送通知 | 加 Firebase 依赖 + Service | 半天,但要选 FCM 还是国内通道 | +| Wear OS | 新 module,共用 `:data` `:domain` | 2-3 天 | +| 深色主题 | `Theme.kt` 加 dark colorScheme | 2 小时 | +| Tablet adaptive UI | WindowSizeClass + 列表/详情双栏 | 1 天 | +| 平板分屏 | 同上 | 同上 | +| 阅读历史 | Room 加 `history` 表 | 半天 | +| 离线下载 | `DownloadManager` + Room | 1-2 天 | \ No newline at end of file diff --git a/docs/android/02-api-contract.md b/docs/android/02-api-contract.md new file mode 100644 index 0000000..7887ee8 --- /dev/null +++ b/docs/android/02-api-contract.md @@ -0,0 +1,585 @@ +# 02 · API 契约 + +> 后端:`http://207.57.129.228:3000/api/v1` +> +> 所有接口**走 Bearer JWT**(除 `auth/*` 外)。401 自动由 OkHttp `TokenAuthenticator` 处理。 +> +> 本文档是**对后端 OpenAPI 的客户端镜像**,任何 schema 改动两边必须同步更新。 + +--- + +## 1. 鉴权(2 个) + +### 1.1 `POST /auth/login` + +**用途**:用户名密码登录,拿 token。 + +**Request**: +```json +{ + "username": "owner", + "password": "test1234" +} +``` + +**Response 200**: +```json +{ + "access_token": "eyJhbGciOiJIUzI1NiIs...", + "refresh_token": "eyJhbGciOiJIUzI1NiIs...", + "token_type": "bearer", + "expires_in": 3600 +} +``` + +**DTO**: +```kotlin +@Serializable +data class LoginRequest( + val username: String, + val password: String, +) + +@Serializable +data class TokenPairDto( + val access_token: String, + val refresh_token: String, + @SerialName("token_type") val tokenType: String = "bearer", + @SerialName("expires_in") val expiresIn: Int, +) +``` + +### 1.2 `POST /auth/refresh` + +**用途**:access 过期时换新的。 + +**Request**: +```json +{ + "refresh_token": "eyJhbGciOiJIUzI1NiIs..." +} +``` + +**Response 200**:同 `login`。 + +**DTO**: +```kotlin +@Serializable +data class RefreshRequest( + @SerialName("refresh_token") val refreshToken: String, +) +``` + +--- + +## 2. 我(2 个) + +### 2.1 `GET /me` + +**Response 200**: +```json +{ + "id": 1, + "username": "owner", + "email": null, + "role": "owner", + "created_at": "2026-01-15T08:00:00Z", + "last_login_at": "2026-06-10T03:42:11Z" +} +``` + +**DTO**: +```kotlin +@Serializable +data class MeDto( + val id: Long, + val username: String, + val email: String? = null, + val role: String, // "owner" | "member" + @SerialName("created_at") val createdAt: String, + @SerialName("last_login_at") val lastLoginAt: String? = null, +) +``` + +### 2.2 `GET /me/usage` + +**用途**:TMT 翻译配额使用情况。 + +**Response 200**: +```json +{ + "month_used": 128000, + "month_quota": 5000000, + "month_remaining": 4872000 +} +``` + +**DTO**: +```kotlin +@Serializable +data class UsageDto( + @SerialName("month_used") val monthUsed: Long, + @SerialName("month_quota") val monthQuota: Long, + @SerialName("month_remaining") val monthRemaining: Long, +) +``` + +--- + +## 3. 文章(2 个) + +### 3.1 `GET /articles` — 列表(分页) + +**Query 参数**: + +| 参数 | 类型 | 必填 | 默认 | 说明 | +|---|---|---|---|---| +| `page` | int | 否 | 1 | 页码(从 1 开始)| +| `page_size` | int | 否 | 50 | 每页条数(1-200)| +| `source` | string | 否 | - | 逗号分隔 source slug,如 `dw,nhk` | +| `q` | string | 否 | - | 标题 / 正文模糊搜索 | +| `lang` | enum | 否 | "both" | `src` / `zh` / `both` | +| `since` | datetime | 否 | 24h 前 | 起始时间(UTC)| +| `until` | datetime | 否 | - | 结束时间(UTC)| +| `category` | string | 否 | - | LLM 分类 | +| `starred_only` | bool | 否 | false | 只看收藏 | + +**Response 200**: +```json +{ + "items": [ + { + "id": 510006, + "source": { + "id": 4, + "name": "BBC 中文", + "slug": "bbc-zh", + "region": "UK" + }, + "title": "Iran attacks Bahrain and Jordan...", + "title_zh": "伊朗袭击巴林和约旦以报复美国对霍尔木兹的袭击", + "body_zh_text": "...", + "summary_zh": "...", + "lang_src": "en", + "translation_status": "ok", + "category": "国际,军事", + "published_at": "2026-06-10T03:30:00Z", + "fetched_at": "2026-06-10T03:35:21Z", + "image_url": "https://...", + "image_ai_url": "https://...", + "commentary": "中东局势进一步升级...", + "commentary_status": "ok", + "is_starred": false + } + ], + "page": 1, + "page_size": 50, + "total": 228, + "total_pages": 5 +} +``` + +**DTO**: +```kotlin +@Serializable +data class ArticleListResponseDto( + val items: List, + val page: Int, + @SerialName("page_size") val pageSize: Int, + val total: Int, + @SerialName("total_pages") val totalPages: Int, +) + +@Serializable +data class ArticleListItemDto( + val id: Long, + val source: SourceBriefDto, + val title: String, + @SerialName("title_zh") val titleZh: String? = null, + @SerialName("body_zh_text") val bodyZhText: String? = null, + @SerialName("summary_zh") val summaryZh: String? = null, + @SerialName("lang_src") val langSrc: String? = null, + @SerialName("translation_status") val translationStatus: String, // "pending" | "ok" | "failed" + val category: String? = null, + @SerialName("published_at") val publishedAt: String? = null, + @SerialName("fetched_at") val fetchedAt: String, + @SerialName("image_url") val imageUrl: String? = null, + @SerialName("image_ai_url") val imageAiUrl: String? = null, + val commentary: String? = null, + @SerialName("commentary_status") val commentaryStatus: String? = null, + @SerialName("is_starred") val isStarred: Boolean = false, +) + +@Serializable +data class SourceBriefDto( + val id: Long, + val name: String, + val slug: String, + val region: String? = null, +) +``` + +### 3.2 `GET /articles/{id}` — 详情 + +**Response 200**(字段是 ListItem 的超集,再加正文): +```json +{ + "id": 510006, + "source": { ... }, + "url": "https://www.bbc.com/...", + "title": "Iran attacks...", + "body_html": "

...

", + "body_text": "Iran attacked Bahrain...", + "title_zh": "伊朗袭击巴林...", + "body_zh_html": "

...

", + "body_zh_text": "伊朗袭击巴林和约旦...", + "body_zh_formatted": "
...
", + "summary_zh": "...", + "lang_src": "en", + "author": "Jane Doe", + "image_url": "...", + "image_ai_url": "...", + "translation_status": "ok", + "translation_engine": "tencent", + "translated_at": "2026-06-10T03:36:02Z", + "category": "国际,军事", + "format_status": "ok", + "classify_status": "ok", + "image_ai_status": "ok", + "commentary_status": "ok", + "commentary": "中东局势进一步升级...", + "entities": { + "PERSON": ["Trump", "Khamenei"], + "ORG": ["UN", "EU"] + }, + "sentiment": -0.42, + "duplicate_of": null, + "published_at": "2026-06-10T03:30:00Z", + "fetched_at": "2026-06-10T03:35:21Z", + "is_starred": true +} +``` + +**DTO**: +```kotlin +@Serializable +data class ArticleDetailDto( + // 继承列表项所有字段 + val id: Long, + val source: SourceBriefDto, + val title: String, + @SerialName("title_zh") val titleZh: String? = null, + @SerialName("body_zh_text") val bodyZhText: String? = null, + @SerialName("summary_zh") val summaryZh: String? = null, + @SerialName("lang_src") val langSrc: String? = null, + @SerialName("translation_status") val translationStatus: String, + val category: String? = null, + @SerialName("published_at") val publishedAt: String? = null, + @SerialName("fetched_at") val fetchedAt: String, + @SerialName("image_url") val imageUrl: String? = null, + @SerialName("image_ai_url") val imageAiUrl: String? = null, + val commentary: String? = null, + @SerialName("commentary_status") val commentaryStatus: String? = null, + @SerialName("is_starred") val isStarred: Boolean = false, + // 详情独有 + val url: String, + @SerialName("body_html") val bodyHtml: String? = null, + @SerialName("body_text") val bodyText: String, + @SerialName("body_zh_html") val bodyZhHtml: String? = null, + @SerialName("body_zh_formatted") val bodyZhFormatted: String? = null, + val author: String? = null, + @SerialName("translation_engine") val translationEngine: String? = null, + @SerialName("translated_at") val translatedAt: String? = null, + @SerialName("format_status") val formatStatus: String? = null, + @SerialName("classify_status") val classifyStatus: String? = null, + @SerialName("image_ai_status") val imageAiStatus: String? = null, + val entities: JsonObject? = null, + val sentiment: Double? = null, + @SerialName("duplicate_of") val duplicateOf: Long? = null, +) +``` + +--- + +## 4. 源(1 个) + +### 4.1 `GET /sources` + +**Response 200**: +```json +[ + { + "id": 1, + "name": "DW 中文", + "slug": "dw", + "kind": "rss", + "url": "https://rss.dw.com/...", + "enabled": true, + "region": "DE", + "language_src": "de", + "priority": 10, + "fetch_interval_min": 30, + "translate_to": "zh", + "last_fetched_at": "2026-06-10T03:35:21Z", + "last_status": "ok", + "consecutive_failures": 0, + "blocklist_tags": ["体育", "娱乐"] + } +] +``` + +**DTO**: +```kotlin +@Serializable +data class SourceDto( + val id: Long, + val name: String, + val slug: String, + val kind: String, + val url: String, + val enabled: Boolean, + val region: String? = null, + @SerialName("language_src") val languageSrc: String? = null, + val priority: Int, + @SerialName("fetch_interval_min") val fetchIntervalMin: Int, + @SerialName("translate_to") val translateTo: String, + @SerialName("last_fetched_at") val lastFetchedAt: String? = null, + @SerialName("last_status") val lastStatus: String? = null, + @SerialName("consecutive_failures") val consecutiveFailures: Int = 0, + @SerialName("blocklist_tags") val blocklistTags: List? = null, +) +``` + +--- + +## 5. 收藏(3 个) + +### 5.1 `GET /bookmarks` — 我的收藏 + +**Response 200**: +```json +[ + { + "id": 88, + "article_id": 510006, + "note": "中东局势长期观察", + "created_at": "2026-06-10T05:12:30Z" + } +] +``` + +**DTO**: +```kotlin +@Serializable +data class BookmarkDto( + val id: Long, + @SerialName("article_id") val articleId: Long, + val note: String? = null, + @SerialName("created_at") val createdAt: String, +) +``` + +### 5.2 `POST /bookmarks` — 收藏 + +**Request**: +```json +{ + "article_id": 510006, + "note": "可选备注" +} +``` + +**Response 201**:同 5.1。 + +**DTO**: +```kotlin +@Serializable +data class BookmarkCreateRequest( + @SerialName("article_id") val articleId: Long, + val note: String? = null, +) +``` + +### 5.3 `DELETE /bookmarks/{article_id}` — 取消收藏 + +**Response 204**(无 body)。 + +--- + +## 6. 订阅(3 个) + +### 6.1 `POST /subscriptions` — 订阅源 + +**Request**: +```json +{ + "source_id": 1, + "category_filter": ["国际", "科技"] +} +``` + +**Response 201**: +```json +{ + "id": 12, + "source_id": 1, + "category_filter": ["国际", "科技"], + "created_at": "2026-06-10T05:00:00Z" +} +``` + +**DTO**: +```kotlin +@Serializable +data class SubscriptionCreateRequest( + @SerialName("source_id") val sourceId: Long, + @SerialName("category_filter") val categoryFilter: List? = null, +) + +@Serializable +data class SubscriptionDto( + val id: Long, + @SerialName("source_id") val sourceId: Long, + @SerialName("category_filter") val categoryFilter: List? = null, + @SerialName("created_at") val createdAt: String, +) +``` + +### 6.2 `GET /subscriptions` — 我的订阅列表 + +**Response 200**:`SubscriptionDto[]` + +### 6.3 `DELETE /subscriptions/{id}` — 取消订阅 + +**Response 204**。 + +--- + +## 7. 错误响应 + +### 7.1 4xx / 5xx 统一格式(RFC 7807) + +```json +{ + "type": "about:blank", + "title": "Article not found", + "status": 404, + "instance": "http://207.57.129.228:3000/api/v1/articles/999999" +} +``` + +### 7.2 422 Validation Error + +```json +{ + "type": "about:blank", + "title": "Validation Error", + "status": 422, + "errors": [ + { + "loc": ["body", "username"], + "msg": "field required", + "type": "value_error.missing" + } + ], + "instance": "..." +} +``` + +### 7.3 客户端处理策略 + +```kotlin +sealed class ApiError(message: String) : Exception(message) { + object Unauthorized : ApiError("请重新登录") + object NotFound : ApiError("资源不存在") + data class Validation(val errors: List) : ApiError("请求参数错误: $errors") + data class Server(val status: Int, val title: String) : ApiError("服务器错误: $title") + data class Network(cause: Throwable) : ApiError("网络错误: ${cause.message}") +} + +// 在 Repository 里捕获 HttpException: +val response = try { + api.listArticles(...) +} catch (e: HttpException) { + when (e.code()) { + 401 -> throw ApiError.Unauthorized + 404 -> throw ApiError.NotFound + 422 -> { + val body = e.response()?.errorBody()?.string() + throw ApiError.Validation(parseValidationErrors(body)) + } + else -> throw ApiError.Server(e.code(), e.message()) + } +} catch (e: IOException) { + throw ApiError.Network(e) +} +``` + +--- + +## 8. DTO ↔ Domain 映射表 + +DTO 是网络层的事,domain model 是 UI 层的事。**永远不要让 DTO 漏到 UI**。 + +| DTO | Domain | 转换点 | +|---|---|---| +| `ArticleListItemDto` | `domain.model.Article` | `ArticlePagingSource.map()` | +| `ArticleDetailDto` | `domain.model.ArticleDetail` | `ArticleRepository.getArticle()` | +| `SourceDto` | `domain.model.Source` | `SourceRepository.list()` | +| `BookmarkDto` | `domain.model.Bookmark` | `BookmarkRepository.list()` | +| `MeDto` | `domain.model.User` | `AuthRepository.me()` | + +**Domain model 示例**(UI 用): + +```kotlin +data class Article( + val id: Long, + val sourceName: String, + val sourceSlug: String, + val title: String, + val titleZh: String?, + val bodyZhText: String?, + val summaryZh: String?, + val langSrc: String?, + val translationStatus: String, + val categories: List, // 已拆分逗号分隔 + val publishedAt: Instant?, + val imageUrl: String?, + val imageAiUrl: String?, + val commentary: String?, + val commentaryStatus: String?, + val isStarred: Boolean, +) + +data class ArticleDetail( + val article: Article, + val url: String, + val bodyText: String, + val bodyHtml: String?, + val bodyZhHtml: String?, + val bodyZhFormatted: String?, // 优先用这个做正文渲染 + val author: String?, + val translationEngine: String?, + val formatStatus: String?, + val classifyStatus: String?, + val imageAiStatus: String?, + val entities: Map>?, + val sentiment: Double?, +) +``` + +--- + +## 9. 不在 MVP 的接口(列出来,以后再用) + +下面这些是 `admin` 系列,客户端不需要: + +- `GET /admin/sources` `POST /admin/sources` `PATCH /admin/sources/{id}` `DELETE /admin/sources/{id}` +- `POST /admin/refresh/{source_id}` +- `POST /admin/translation/rerun/{article_id}` +- `POST /admin/translation/quota/reset` +- `GET /admin/health` +- `GET /admin/llm/settings` `PUT /admin/llm/settings` `POST /admin/llm/settings/reset` `POST /admin/llm/settings/test` +- `POST /admin/llm/enrich/{article_id}` + +这些都是 **owner 自己后台用**,你会在 web 后台管,app 不碰。 \ No newline at end of file diff --git a/docs/android/03-build-run.md b/docs/android/03-build-run.md new file mode 100644 index 0000000..fdba285 --- /dev/null +++ b/docs/android/03-build-run.md @@ -0,0 +1,602 @@ +# 03 · 构建与运行 + +> 从 0 到能装到真机跑的 APK,每一步都给具体命令。 +> +> 假设你本地已经有:**Android Studio Hedgehog(2023.1.1)+** + **JDK 17** + **Android SDK 35** + **Kotlin 2.0.21**。 + +--- + +## 0. 环境清单 + +| 工具 | 版本 | 验证命令 | +|---|---|---| +| Android Studio | Hedgehog (2023.1.1) 或更新 | Help → About | +| JDK | 17 | `java -version` | +| Android SDK | 35 | SDK Manager 看 "Android 15.0" | +| Gradle | 8.10+(Studio 自带) | `gradle --version` | +| Kotlin | 2.0.21(项目自带)| 无所谓 | + +**JDK 注意**:**JDK 17**,不是 11、不是 21。AGP 8.7 要求 JDK 17。 + +--- + +## 1. 新建工程 + +1. **File → New → New Project** +2. 选 **Empty Activity (Compose)** +3. 配置: + +| 项 | 值 | +|---|---| +| Name | `Diary News` | +| Package name | `com.diary.news` | +| Save location | `~/projects/diary-news-android/` | +| Language | **Kotlin** | +| Minimum SDK | **API 24 ("Nougat")** | +| Build configuration language | **Kotlin DSL** | +| ☑️ Use Version Catalog | **勾上**(用 `libs.versions.toml`)| + +4. **Finish** + +--- + +## 2. 改版本目录 + +打开 `gradle/libs.versions.toml`,**整体替换**为: + +```toml +[versions] +agp = "8.7.2" +kotlin = "2.0.21" +ksp = "2.0.21-1.0.27" + +# AndroidX & Compose +compose-bom = "2024.10.01" +activity-compose = "1.9.3" +lifecycle = "2.8.7" +navigation-compose = "2.8.4" + +# Network +retrofit = "2.11.0" +retrofit-kotlinx-converter = "1.0.0" +okhttp = "4.12.0" +kotlinx-serialization = "1.7.3" +kotlinx-coroutines = "1.9.0" + +# DI +hilt = "2.52" +hilt-navigation-compose = "1.2.0" + +# Persistence +room = "2.6.1" +security-crypto = "1.1.0-alpha06" + +# Paging +paging = "3.3.4" +paging-compose = "3.3.4" + +# Image +coil = "2.7.0" + +# Test +junit = "4.13.2" +mockk = "1.13.13" +turbine = "1.2.0" + +[libraries] +# Core +kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" } +kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" } + +# Compose +androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity-compose" } +androidx-compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose-bom" } +androidx-compose-ui = { module = "androidx.compose.ui:ui" } +androidx-compose-ui-graphics = { module = "androidx.compose.ui:ui-graphics" } +androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } +androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" } +androidx-compose-material3 = { module = "androidx.compose.material3:material3" } +androidx-compose-material-icons = { module = "androidx.compose.material:material-icons-extended" } +androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycle" } +androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle" } +androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation-compose" } + +# Network +retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } +retrofit-kotlinx-serialization = { module = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter", version.ref = "retrofit-kotlinx-converter" } +okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } +okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" } + +# DI +hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" } +hilt-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" } +hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hilt-navigation-compose" } + +# Persistence +room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } +room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" } +room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } +room-paging = { module = "androidx.room:room-paging", version.ref = "room" } +security-crypto = { module = "androidx.security:security-crypto-ktx", version.ref = "security-crypto" } + +# Paging +paging-runtime = { module = "androidx.paging:paging-runtime-ktx", version.ref = "paging" } +paging-compose = { module = "androidx.paging:paging-compose", version.ref = "paging-compose" } + +# Image +coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" } + +# Test +junit = { module = "junit:junit", version.ref = "junit" } +mockk = { module = "io.mockk:mockk", version.ref = "mockk" } +turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } +``` + +--- + +## 3. 改 `app/build.gradle.kts` + +整体替换为: + +```kotlin +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.kotlin.compose) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.ksp) + alias(libs.plugins.hilt) +} + +android { + namespace = "com.diary.news" + compileSdk = 35 + + defaultConfig { + applicationId = "com.diary.news" + minSdk = 24 + targetSdk = 35 + versionCode = 1 + versionName = "0.1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + debug { + isMinifyEnabled = false + } + release { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro", + ) + // debug 阶段先不上签名,直接装 debug APK + // 真要 release,见 §6 + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = "17" + } + + buildFeatures { + compose = true + } + + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} + +dependencies { + // Compose BOM 统一管 + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.activity.compose) + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.ui.graphics) + implementation(libs.androidx.compose.ui.tooling.preview) + implementation(libs.androidx.compose.material3) + implementation(libs.androidx.compose.material.icons) + implementation(libs.androidx.lifecycle.viewmodel.compose) + implementation(libs.androidx.lifecycle.runtime.compose) + implementation(libs.androidx.navigation.compose) + debugImplementation(libs.androidx.compose.ui.tooling) + + // Coroutines + implementation(libs.kotlinx.coroutines.android) + + // Network + implementation(libs.retrofit) + implementation(libs.retrofit.kotlinx.serialization) + implementation(libs.okhttp) + implementation(libs.okhttp.logging) + + // Serialization + implementation(libs.kotlinx.serialization.json) + + // DI + implementation(libs.hilt.android) + ksp(libs.hilt.compiler) + implementation(libs.hilt.navigation.compose) + + // Persistence + implementation(libs.room.runtime) + implementation(libs.room.ktx) + implementation(libs.room.paging) + ksp(libs.room.compiler) + implementation(libs.security.crypto) + + // Paging + implementation(libs.paging.runtime) + implementation(libs.paging.compose) + + // Image + implementation(libs.coil.compose) + + // Test + testImplementation(libs.junit) + testImplementation(libs.mockk) + testImplementation(libs.turbine) + testImplementation(libs.kotlinx.coroutines.test) +} +``` + +--- + +## 4. 网络安全白名单(关键!) + +### 4.1 `app/src/main/AndroidManifest.xml` + +整体替换: + +```xml + + + + + + + + + + + + + + + + +``` + +### 4.2 `app/src/main/res/xml/network_security_config.xml` + +新建文件: + +```xml + + + + + + + + + + + + 207.57.129.228 + + +``` + +### 4.3 `app/src/main/res/xml/backup_rules.xml`(禁止备份 token) + +```xml + + + + +``` + +### 4.4 `app/src/main/res/xml/data_extraction_rules.xml`(Android 12+) + +```xml + + + + + + + + + +``` + +--- + +## 5. ProGuard / R8 规则(发布包必加) + +`app/proguard-rules.pro`: + +```proguard +# Retrofit +-keepattributes Signature, InnerClasses, EnclosingMethod +-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations +-keepattributes AnnotationDefault +-keep,allowobfuscation,allowshrinking interface retrofit2.Call +-keep,allowobfuscation,allowshrinking class retrofit2.Response +-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation + +# kotlinx.serialization +-keepattributes *Annotation*, InnerClasses +-dontnote kotlinx.serialization.AnnotationsKt + +-keep,includedescriptorclasses class com.diary.news.**$$serializer { *; } +-keepclassmembers class com.diary.news.** { + *** Companion; + } +-keepclasseswithmembers class com.diary.news.** { + kotlinx.serialization.KSerializer serializer(...); + } + +# OkHttp +-dontwarn org.conscrypt.** +-dontwarn org.bouncycastle.** +-dontwarn org.openjsse.** + +# Hilt +-keep class dagger.hilt.** { *; } +-keep class * extends dagger.hilt.android.HiltAndroidApp +``` + +--- + +## 6. 第一次 Sync & Build + +### 6.1 Sync Gradle + +- Android Studio 顶部会弹"Gradle files have changed..." → **Sync Now** +- 或菜单 **File → Sync Project with Gradle Files** +- 等 5-15 分钟(下载依赖) + +### 6.2 第一次 build + +```bash +# 命令行 +./gradlew assembleDebug + +# 或 Studio 右上角 ▶️ 直接 Run +``` + +预期: +- `BUILD SUCCESSFUL` +- 产物在 `app/build/outputs/apk/debug/app-debug.apk` + +### 6.3 跑在模拟器 + +1. 工具栏 AVD Manager → Create Virtual Device → Pixel 7 + API 35 +2. 启动模拟器(等 30s-1min) +3. Run ▶️ + +**模拟器坑**: +- 模拟器自己的 IP 是 `10.0.2.2`,不是 `127.0.0.1` +- 但我们的目标是 `207.57.129.228`(真实服务器),**模拟器直连外网就行,无需特殊配置** +- 如果你只是想测本地后端,临时把 `network_security_config.xml` 改成 `10.0.2.2` 白名单 + +### 6.4 跑在真机 + +1. **设置 → 关于手机 → 连续点 7 次"版本号"** → 开启开发者模式 +2. **设置 → 系统 → 开发者选项 → 打开 USB 调试** +3. USB 连电脑 → 手机弹"允许 USB 调试" → 确定 +4. Studio 右上角设备列表选你的真机 → Run ▶️ + +--- + +## 7. 配置服务器地址(可切换 debug / release) + +**MVP 写死在 `BuildConfig`**。 + +在 `app/build.gradle.kts` 的 `defaultConfig` 加: + +```kotlin +defaultConfig { + // ... + buildConfigField("String", "API_BASE_URL", "\"http://207.57.129.228:3000/api/v1/\"") +} + +buildTypes { + debug { + buildConfigField("String", "API_BASE_URL", "\"http://207.57.129.228:3000/api/v1/\"") + } + release { + buildConfigField("String", "API_BASE_URL", "\"http://207.57.129.228:3000/api/v1/\"") + // 后续要换 https,改这里 + 加证书 + } +} +``` + +代码里用: + +```kotlin +@Provides @Singleton +fun provideRetrofit(okHttp: OkHttpClient): Retrofit = + Retrofit.Builder() + .baseUrl(BuildConfig.API_BASE_URL) + .client(okHttp) + .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) + .build() +``` + +--- + +## 8. 调试技巧 + +### 8.1 OkHttp 日志 + +```kotlin +@Provides @Singleton +fun provideOkHttp( + tokenStore: TokenStore, +): OkHttpClient = + OkHttpClient.Builder() + .addInterceptor(AuthInterceptor(tokenStore)) + .addInterceptor(HttpLoggingInterceptor().apply { + level = if (BuildConfig.DEBUG) Level.BODY else Level.NONE + }) + .authenticator(TokenAuthenticator(tokenStore, ...)) + .connectTimeout(15, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .build() +``` + +`Level.BODY` 会在 Logcat 打印所有请求和响应体(包含 token!小心)。 + +**生产包务必改回 `Level.NONE`**。 + +### 8.2 Compose Preview + +```kotlin +@Preview(showBackground = true) +@Composable +fun ArticleCardPreview() { + DiaryNewsTheme { + ArticleCard( + a = Article( + id = 1, + sourceName = "DW", + sourceSlug = "dw", + title = "Sample title", + titleZh = "示例标题", + bodyZhText = "示例正文...", + ... + ), + onClick = {}, + ) + } +} +``` + +### 8.3 Layout Inspector + +Studio → **Tools → Layout Inspector** → 选进程 → 实时看 Compose 树。 + +### 8.4 抓包 + +推荐 **Charles** 或 **mitmproxy**: +- 模拟器:WiFi → 长按 → 修改网络 → 手动代理 → 127.0.0.1:8888 +- 真机:Charles Proxy + 安装证书 +- 注意:**mitmproxy 会让 HTTPS 失效**(因为加了第三方 CA),我们的 HTTP 不受影响 + +--- + +## 9. CI(可选,MVP 不强求) + +如果你想每次 push 自动出 debug APK: + +`.github/workflows/build.yml`: + +```yaml +name: Build APK +on: + push: + branches: [main] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build + run: ./gradlew assembleDebug + - name: Upload APK + uses: actions/upload-artifact@v4 + with: + name: app-debug + path: app/build/outputs/apk/debug/app-debug.apk +``` + +--- + +## 10. 常见报错速查 + +| 报错 | 原因 | 解决 | +|---|---|---| +| `Cleartext HTTP traffic to 207.57.129.228 not permitted` | 没配 network_security_config | 装 §4 | +| `Cannot resolve symbol 'hiltViewModel'` | 没加 `hilt-navigation-compose` | 装 §2 依赖 | +| `Hilt: @AndroidEntryPoint ... missing binding` | Application 没 `@HiltAndroidApp` | 检查 `DiaryNewsApp.kt` | +| `KSP not found` | KSP 版本与 Kotlin 不匹配 | 检查 `ksp` 版本号 | +| `Plugin [id: 'com.google.devtools.ksp'] was not found` | settings.gradle.kts 没声明 | 在 `pluginManagement` 块加 | +| `Composable invocations can only happen from the context of a @Composable function` | 在 `LaunchedEffect` 里调非 suspend 阻塞 | 加 `withContext(Dispatchers.IO)` | +| `JSON decode error: Polymorphic serializer was not found` | 后端返回了 polymorphic 类型,DTO 没声明 | DTO 加 `@JsonClassDiscriminator` 或 sealed class | +| `401 Unauthorized` 一片 | Token 过期 / 错 | 启动 app 看 logcat 的 OkHttp 日志,确认 refresh 接口通不通 | + +--- + +## 11. 发布签名(真要上架时再弄) + +```bash +# 生成 keystore +keytool -genkey -v -keystore diary-news.jks -keyalg RSA -keysize 2048 \ + -validity 10000 -alias diary-news + +# 在 ~/.gradle/gradle.properties 加 +DIARY_NEWS_STORE_FILE=diary-news.jks +DIARY_NEWS_STORE_PASSWORD=... +DIARY_NEWS_KEY_ALIAS=diary-news +DIARY_NEWS_KEY_PASSWORD=... + +# app/build.gradle.kts +signingConfigs { + create("release") { + storeFile = file(providers.gradleProperty("DIARY_NEWS_STORE_FILE").get()) + storePassword = providers.gradleProperty("DIARY_NEWS_STORE_PASSWORD").get() + keyAlias = providers.gradleProperty("DIARY_NEWS_KEY_ALIAS").get() + keyPassword = providers.gradleProperty("DIARY_NEWS_KEY_PASSWORD").get() + } +} +buildTypes { + release { + signingConfig = signingConfigs.getByName("release") + } +} +``` + +**MVP 阶段不弄**,直接 debug APK 装手机上跑就够了。 \ No newline at end of file diff --git a/docs/android/04-milestones.md b/docs/android/04-milestones.md new file mode 100644 index 0000000..25e63ed --- /dev/null +++ b/docs/android/04-milestones.md @@ -0,0 +1,273 @@ +# 04 · 7 天里程碑 + +> 目标:第 7 天能装一个 APK 到真机,跑通 **登录 → 列表 → 详情 → 收藏 → 离线缓存** 完整链路。 +> +> 工作量估计基于:**全栈老哥**(你已经会 Kotlin/Compose 基础),按一天 3-4 小时有效开发时间算。 +> +> **每个里程碑有明确 DoD**(Definition of Done)。不达 DoD 不算完成。 + +--- + +## 全局 DoD(贯穿 7 天) + +- [ ] `./gradlew assembleDebug` 每次都 BUILD SUCCESSFUL +- [ ] 真机/模拟器能装能跑,不闪退 +- [ ] `git commit` 节奏:每个里程碑一个 commit,信息写清楚 +- [ ] logcat 无 ERROR 级别的 crash +- [ ] 没有 hardcoded 颜色 / 字体大小(全部走 `MaterialTheme`) + +--- + +## Day 1 — 工程骨架 + 鉴权三件套 + +**目标**:能登录、能持久化 token、401 自动 refresh、空 UI 能跳转。 + +### 任务清单 + +| # | 任务 | 文件 | 估时 | +|---|---|---|---| +| 1 | 新建 Android Studio 工程,改 `libs.versions.toml` + `app/build.gradle.kts` | 见 03 | 30min | +| 2 | 配 `network_security_config.xml` + 4 个 res 文件 | 见 03 §4 | 15min | +| 3 | `DiaryNewsApp.kt`(`@HiltAndroidApp`)| `app/` | 5min | +| 4 | `MainActivity.kt`(`@AndroidEntryPoint`,装 `AppNav`)| `app/` | 15min | +| 5 | DTO 文件 12 个 | `data/api/dto/` | 1h | +| 6 | `ApiService.kt` | `data/api/` | 30min | +| 7 | `TokenStore.kt`(EncryptedSharedPreferences)| `data/auth/` | 30min | +| 8 | `AuthInterceptor.kt` + `TokenAuthenticator.kt` | `data/api/` | 1h | +| 9 | `NetworkModule.kt`(Hilt)| `di/` | 30min | +| 10 | `LoginScreen.kt` + `LoginViewModel.kt` | `ui/login/` | 1h | +| 11 | `AppNav.kt` 骨架(Login ↔ Feed)| `ui/nav/` | 15min | +| 12 | `Theme.kt` + `Color.kt` + `Type.kt`(复用 web 的蓝 #2080f0)| `ui/theme/` | 30min | + +### Day 1 DoD + +- [ ] `./gradlew assembleDebug` BUILD SUCCESSFUL +- [ ] 装到真机,启动能看到登录页 +- [ ] 输入 `owner / test1234`,点登录 → 跳到一个空白 Feed 页 +- [ ] 杀掉 app 再开 → 直接进 Feed 页(token 持久化生效) +- [ ] 等 60min 后,任意接口请求 → 自动 refresh → 用户无感 +- [ ] logcat 里能看到 `OkHttp` 打印的请求日志(debug build) +- [ ] 进 `设置 → 应用 → Diary News → 存储`,看不到明文 token(只在加密 SP 里) + +### 验证方法 + +```bash +# Day 1 验证清单(贴在 issue / PR 描述里): +- [x] 登录成功,TokenStore 保存到 EncryptedSP +- [x] 重启 app 自动进 Feed(读 SP 成功) +- [x] 改密码 → 旧 token 在 server 失效 → app 收到 401 → 跳登录 +- [x] 等 access 过期(60min)→ 任意请求 → 自动 refresh → 200 +``` + +--- + +## Day 2 — Feed 列表(分页 + 卡片) + +**目标**:能滚能动,看到真实的新闻列表,卡片视觉对齐 web。 + +### 任务清单 + +| # | 任务 | 文件 | 估时 | +|---|---|---|---| +| 1 | `ArticlePagingSource.kt` | `ui/feed/` | 30min | +| 2 | `FeedViewModel.kt`(Paging 流)| `ui/feed/` | 30min | +| 3 | `ArticleCard.kt`(对齐 web 视觉)| `ui/common/` | 1h | +| 4 | `FeedScreen.kt`(LazyColumn + 加载状态)| `ui/feed/` | 1h | +| 5 | 源筛选 + 关键词搜索(下拉 + 输入)| `ui/feed/` | 1h | +| 6 | 空状态 / 错误状态 / 加载状态组件 | `ui/common/` | 30min | + +### Day 2 DoD + +- [ ] 列表能加载第一页(50 条) +- [ ] 滑到底自动加载下一页(Paging 3 自动) +- [ ] 卡片展示:源 / 语言 / 分类 tag / 时间 / 原标题(灰)/ 中标题 / 插图 / 译文正文摘要 / 评论钩子 +- [ ] 源筛选:选一个源,列表只剩该源 +- [ ] 关键词搜索:输入 "AI" → 列表过滤 +- [ ] 无网络时显示空状态 + 重试按钮 +- [ ] 滚得快时图片不卡(Coil 默认就 OK) + +### 视觉对齐清单 + +对照 web `frontend/src/views/Feed.vue`: +- 卡片圆角、间距、字号 1:1 +- 中文标题字号 18sp,原标题 13sp 灰 +- 评论钩子块背景 `#f6f8ff`,左边框 `#2080f0` 3dp + +--- + +## Day 3 — 详情页(三段 Tab) + +**目标**:点卡片进详情,看到完整译文 + 评论 + 原文。 + +### 任务清单 + +| # | 任务 | 文件 | 估时 | +|---|---|---|---| +| 1 | `ArticleDetailDto` → `domain.ArticleDetail` mapper | `data/` | 30min | +| 2 | `ArticleViewModel.kt`(`StateFlow`)| `ui/article/` | 30min | +| 3 | `ArticleScreen.kt` 骨架 + TabRow | `ui/article/` | 30min | +| 4 | `ArticleTabs.kt`:`CommentaryTab` / `TranslationTab` / `OriginalTab` | `ui/article/` | 1h | +| 5 | `TranslationTab`:WebView 渲染 `body_zh_formatted`(无 JS)| `ui/article/` | 1h | +| 6 | `OriginalTab`:WebView 渲染 `body_html`(无 JS)| `ui/article/` | 15min | +| 7 | 详情页顶部卡片(标题 / 分类 / 时间 / 插图)| `ui/article/` | 30min | +| 8 | 收藏按钮 ☆(Day 4 接 API,Day 3 先显示静态)| `ui/article/` | 15min | + +### Day 3 DoD + +- [ ] 点列表卡片 → 进详情页 +- [ ] 顶部展示:原标题(灰)/ 中标题(主)/ 插图 / 分类 tag / 发布时间 / 作者 +- [ ] 三个 Tab 可切换:评论 / 译文 / 原文 +- [ ] 译文 Tab 用 `body_zh_formatted`,如果没有就 fallback 到 `body_zh_text` +- [ ] WebView 不开 JS(验证方式:`runJavaScript` 调用失败) +- [ ] 详情页旋转屏幕 / 切换深色模式不崩 + +--- + +## Day 4 — 收藏(乐观更新 + Room 缓存) + +**目标**:能收藏 / 取消,UI 秒响应,失败可回滚。 + +### 任务清单 + +| # | 任务 | 文件 | 估时 | +|---|---|---|---| +| 1 | Room:`AppDatabase.kt` + `BookmarkDao.kt` + `BookmarkCacheEntity` | `data/db/` | 1h | +| 2 | `BookmarkRepository.kt`(乐观更新)| `data/repository/` | 1h | +| 3 | `DatabaseModule.kt`(Hilt)| `di/` | 15min | +| 4 | 详情页收藏按钮接 `ArticleViewModel.toggleBookmark()` | `ui/article/` | 30min | +| 5 | `BookmarksScreen.kt` + `BookmarksViewModel.kt` | `ui/bookmarks/` | 1h | +| 6 | 离线显示:无网络时用 Room 缓存渲染 | `ui/bookmarks/` | 30min | + +### Day 4 DoD + +- [ ] 详情页点 ☆ → 立刻变实心(乐观更新) +- [ ] 后台调 `POST /bookmarks`,失败时 → 回滚 ☆ + Snackbar "收藏失败,已撤销" +- [ ] 收藏列表页能看到所有收藏 +- [ ] 离线时收藏列表仍可看(读 Room 缓存) +- [ ] 滑动列表时无卡顿(用 `LazyColumn` + `key`) + +--- + +## Day 5 — 源 + 订阅 + +**目标**:能看所有源、订阅 / 取消订阅。 + +### 任务清单 + +| # | 任务 | 文件 | 估时 | +|---|---|---|---| +| 1 | `SourceRepository.kt` | `data/repository/` | 30min | +| 2 | `SourcesScreen.kt` + `SourcesViewModel.kt` | `ui/sources/` | 1h | +| 3 | 订阅按钮 + `POST/DELETE /subscriptions` | `ui/sources/` | 1h | +| 4 | 底部导航栏:Feed / Sources / Bookmarks | `ui/nav/` | 1h | + +### Day 5 DoD + +- [ ] 底部三 Tab:Feed / Sources / Bookmarks +- [ ] Sources 页能看到所有 enabled 源,带订阅状态 +- [ ] 点订阅按钮 → 立刻变化 + 后台请求 +- [ ] 失败 Snackbar 提示 + 回滚 +- [ ] Feed 页源筛选多选能跨 Tab 状态保留(navigation 状态管理) + +--- + +## Day 6 — 主题 + 通用打磨 + +**目标**:视觉统一、空状态友好、加载体验好。 + +### 任务清单 + +| # | 任务 | 文件 | 估时 | +|---|---|---|---| +| 1 | Material3 主题:浅色 + 深色(Dynamic Color,Android 12+)| `ui/theme/` | 1h | +| 2 | 自定义启动屏 + 应用图标 | `res/` | 30min | +| 3 | 通用加载 / 空 / 错误组件统一风格 | `ui/common/` | 30min | +| 4 | 下拉刷新(`SwipeRefreshLayout` / `PullToRefreshContainer`)| `ui/feed/` | 30min | +| 5 | 网络状态监听(ConnectivityManager)| `data/` | 30min | +| 6 | 离线条 / Snackbar 提示 | `ui/common/` | 30min | +| 7 | 长按卡片 → 分享 / 复制 URL 菜单 | `ui/common/` | 30min | + +### Day 6 DoD + +- [ ] 切深色模式 → 全 app 颜色自动切(阅读体验好) +- [ ] 启动屏不闪白(用 SplashScreen API) +- [ ] 列表支持下拉刷新 +- [ ] 飞行模式下进入 app → 各页有合理提示 +- [ ] 长按文章卡片弹出菜单:复制链接 / 在浏览器打开 / 分享 + +--- + +## Day 7 — 收尾 + 真机端到端测试 + APK 打包 + +**目标**:出第一个 release-ready APK,完整跑一遍所有功能。 + +### 任务清单 + +| # | 任务 | 文件 | 估时 | +|---|---|---|---| +| 1 | `README.md`(装 app 说明 + 调试指南)| 根目录 | 30min | +| 2 | ProGuard / R8 配置 + release build 验证 | `proguard-rules.pro` | 1h | +| 3 | 真机端到端测试(用 [e2e-checklist.md](#) 列表)| — | 2h | +| 4 | crash 报告接入(可选:Sentry / Firebase Crashlytics)| — | 1h | +| 5 | 修最后发现的 bug | — | 1h | + +### Day 7 DoD + +- [ ] `./gradlew assembleRelease` 出 `app-release-unsigned.apk` +- [ ] debug APK 跑完下面所有场景,全过 + +### E2E 测试场景清单 + +- [ ] 第一次启动 → 登录页 +- [ ] 登录成功 → 进 Feed +- [ ] 列表能加载,滑到底加载更多 +- [ ] 源筛选 / 关键词搜索生效 +- [ ] 点卡片进详情,三段 Tab 都能切 +- [ ] 收藏 / 取消收藏 UI 秒响应,后台请求成功 +- [ ] 收藏页能看到刚收藏的 +- [ ] 杀进程,重启,直接进 Feed(token 持久化) +- [ ] 飞行模式启动,各页空状态 + 离线缓存(收藏)仍可用 +- [ ] access 过期后任意请求,自动 refresh,UI 无感 +- [ ] 改密码,旧 token → app 跳登录 + +--- + +## 风险 & 应对 + +| 风险 | 概率 | 影响 | 应对 | +|---|---|---|---| +| Compose / Kotlin 版本不兼容,build 失败 | 中 | 高 | 严格用本文档指定版本;失败先查 [Compose-Kotlin Compatibility Map](https://developer.android.com/jetpack/androidx/releases/compose-kotlin) | +| 后端 schema 改了,app 跑不起来 | 中 | 中 | 启动时 catch `SerializationException`,跳错误页 + 重启按钮 | +| 真机 7.0 / 7.1 系统太老,某些 API 没有 | 低 | 中 | 用 AndroidX 兼容层;遇到问题查 [API 24 compat matrix](https://developer.android.com/training/backward-compatible-support) | +| 网络安全白名单加错,全 app 报错 | 低 | 高 | 第 1 次 build 一定先跑清单 Day 1 DoD | +| 11 章(ProGuard)没做就 release,接口全找不到 | 中 | 高 | Day 7 必须先跑 `./gradlew assembleRelease` 再装机 | +| EncryptedSharedPreferences 在某些定制 ROM 上崩 | 极低 | 中 | catch `GeneralSecurityException`,fallback 引导用户重新登录 | + +--- + +## 后续迭代方向(7 天后看) + +| 优先级 | 功能 | 估时 | +|---|---|---| +| P1 | FCM 推送(新文章到时通知)| 2-3 天 | +| P1 | 阅读历史(本地)| 半天 | +| P2 | 平板 adaptive(WindowSizeClass + 双栏)| 1-2 天 | +| P2 | 离线下载包(整周报导出)| 2-3 天 | +| P3 | Wear OS 端 | 1 周 | +| P3 | 主屏 widget | 2-3 天 | +| P3 | 多账号切换 | 1 天 | + +--- + +## 任务量快速核算 + +| Day | 估时 | 主要内容 | +|---|---|---| +| 1 | 7h | 工程 + 鉴权 | +| 2 | 4.5h | Feed + 分页 + 卡片 | +| 3 | 4.5h | 详情 + WebView | +| 4 | 4h | 收藏 + Room | +| 5 | 3.5h | 源 + 订阅 + 底导 | +| 6 | 4h | 主题 + 通用 | +| 7 | 5.5h | 测试 + APK | +| **总计** | **~33h** | 7 个有效工作日 | \ No newline at end of file diff --git a/docs/android/README.md b/docs/android/README.md new file mode 100644 index 0000000..3534509 --- /dev/null +++ b/docs/android/README.md @@ -0,0 +1,179 @@ +# Diary News — Android App + +> 私人新闻聚合器的 Android 客户端,读 FastAPI 后端。 +> +> **状态**:方案阶段(未开工)。本文档是开工前的最终蓝图,任何代码改动必须先对齐这里的约定。 + +--- + +## 0. 一句话总览 + +- **后端**:`http://207.57.129.228:3000/api/v1`(私有 IP 直连,明文 HTTP) +- **客户端**:Kotlin + Jetpack Compose,单 module +- **认证**:Bearer JWT,access 60min,自动 refresh +- **离线**:列表分页缓存 + 收藏本地库 + Token 加密存储 +- **目标**:7 天出第一个能跑通登录 → 列表 → 详情 → 收藏的 APK + +--- + +## 1. 文档索引(按开工顺序读) + +| 序 | 文档 | 作用 | 何时读 | +|---|---|---|---| +| 1 | [01-architecture.md](01-architecture.md) | 模块划分 + 数据流 + 依赖选型理由 | 开工前 30min | +| 2 | [02-api-contract.md](02-api-contract.md) | 每个接口的请求/响应 + DTO 字段映射表 | 写 DTO 时对照 | +| 3 | [03-build-run.md](03-build-run.md) | Gradle / SDK / network security / 真机调试 | 第一次 build 前 | +| 4 | [04-milestones.md](04-milestones.md) | 7 天里程碑拆分 + DoD | 每天开工前看当天任务 | + +--- + +## 2. 5 分钟决策摘要(免读细节直接用) + +| 维度 | 选择 | 替代方案(及为啥不选)| +|---|---|---| +| 语言 | Kotlin 2.0.21 | — | +| UI | Jetpack Compose (Material3) | ❌ XML View(老)| ❌ RN/Flutter(项目太轻)| +| 网络 | Retrofit 2.11 + OkHttp 4.12 | ❌ Ktor Client(生态薄)| +| 序列化 | kotlinx.serialization 1.7.3 | ❌ Moshi(更重)| +| DI | Hilt 2.52 | ❌ Koin(运行时,启动慢)| +| 分页 | Paging 3.3.4 | ❌ 手写 LazyColumn + offset | +| 图片 | Coil 2.7 | ❌ Glide(Compose 集成弱)| +| 路由 | Navigation Compose 2.8.4 | — | +| 加密 | security-crypto 1.1.0-alpha06(EncryptedSharedPreferences)| — | +| 本地 DB | Room 2.6.1 | — | +| minSdk | 24 (Android 7.0) | ❌ 26(放弃 7.0/7.1 ~3% 用户)| +| targetSdk | 35 (Android 15) | — | +| compileSdk | 35 | — | +| AGP | 8.7.2 | — | +| API base | `http://207.57.129.228:3000/api/v1` | ❌ HTTPS(当前 server 无证书)| + +--- + +## 3. 顶层目录(最终落地的样子) + +``` +diary-news-android/ # ← 独立 Git 仓库(不要混进 diary-news) +├── settings.gradle.kts├── build.gradle.kts # root +├── gradle/ +│ ├── libs.versions.toml # 集中版本 +│ └── wrapper/ +├── app/ +│ ├── build.gradle.kts│ ├── proguard-rules.pro│ └── src/main/ +│ ├── AndroidManifest.xml +│ ├── res/ # xml + values + mipmap +│ └── java/com/diary/news/ +│ ├── DiaryNewsApp.kt # @HiltAndroidApp +│ ├── MainActivity.kt│ ├── data/ # api/auth/db/repository +│ ├── domain/ # 业务 model +│ ├── di/ # Hilt modules +│ └── ui/ # theme/nav/login/feed/article/bookmarks/sources/common +└── README.md +``` + +> **仓库策略**:Android app 单独建 Git 仓库 `diary-news-android`,不要和 `diary-news`(后端 + web)混。原因是 release 节奏 / CI / 依赖管理天然不同。 + +--- + +## 4. 端到端数据流(登录 → 刷列表 → 打开详情 → 收藏) + +``` +1. 启动 + DiaryNewsApp.onCreate + → Hilt 初始化 + → MainActivity 检查 TokenStore:有 access 且未过期 → 直接进 Feed + → 无 / 过期 → 进 LoginScreen + +2. 登录 + LoginScreen → LoginViewModel.login() + → POST /auth/login { username, password } + → 拿到 { access_token, refresh_token, expires_in } + → TokenStore.save() (EncryptedSharedPreferences) + → 跳 FeedScreen + +3. 列表 + FeedScreen → FeedViewModel + → Pager + ArticlePagingSource(api::listArticles) + → ApiService.listArticles(page, page_size, ...) + → AuthInterceptor 加 Authorization: Bearer + → 返回 ArticleListResponseDto + → Paging 流到 LazyColumn + → 每一项 ArticleCard 渲染 + +4. 详情 + 点 ArticleCard → ArticleScreen(articleId) + → ArticleViewModel.load(id) + → ApiService.getArticle(id) + → 三段 Tab:评论(commentary)/译文(body_zh_formatted)/原文(body_html) + +5. 收藏 + 详情页点 ☆ 按钮 → ArticleViewModel.toggleBookmark() + → POST /bookmarks { article_id } 或 DELETE /bookmarks/{id} + → 乐观更新 UI(立刻变实心★,失败再回滚 + Snackbar) + +6. 401 自动 refresh + 任意接口返回 401 + → OkHttp TokenAuthenticator 拦截 + → 拿 refresh_token 调 /auth/refresh + → 拿到新 access → 重发原请求 + → 用户完全无感 +``` + +--- + +## 5. 不要做的事(踩坑清单) + +| 坑 | 说明 | 正确做法 | +|---|---|---| +| ❌ 把 access_token 存普通 SharedPreferences | root 手机秒读 | `EncryptedSharedPreferences` + Keystore | +| ❌ 在主线程调 Retrofit | ANR | `suspend fun` + ViewModelScope(自动主线程安全)| +| ❌ 在每次请求前同步读 token | 阻塞 UI | TokenStore 缓存到内存,只在 save/load 时动 SP | +| ❌ refresh 接口并发触发 N 次 | 触发限流 / 死锁 | `synchronized(this)` 单飞锁 | +| ❌ 全量缓存所有文章 | DB 撑爆,启动慢 | 只缓存当前可见页 | +| ❌ WebView 开 JS | XSS 风险 | `settings.javaScriptEnabled = false` | +| ❌ 信任 HTTPS 证书所有 CA | 中间人 | 默认 `system` trust anchor,不动 | +| ❌ 让 HTTP 走全网 | 不安全 | `network_security_config.xml` 白名单单一 IP | +| ❌ 在 ViewModel 里持有 Context | 内存泄漏 | 用 `@HiltAndroidApp` / `AndroidEntryPoint`,Context 通过 Hilt 注入 | +| ❌ ProGuard 不留 keep 规则就 release | retrofit 接口全找不到 | 详见 03-build-run.md §5 | + +--- + +## 6. 启动指令(开工第一步) + +1. **Android Studio Hedgehog**(2023.1.1)+ → `File → New → New Project → Empty Activity (Compose)` +2. **包名**:`com.diary.news` +3. **Application name**:`Diary News` +4. **Min SDK**:24 / **Target SDK**:35 +5. **Kotlin DSL** + **Version Catalog**(`gradle/libs.versions.toml`) +6. 改完 `gradle/libs.versions.toml` 后第一次 Sync —— 视网络,5-15 分钟 +7. 跑 `gradlew assembleDebug` 出第一个 debug APK +8. 真机或模拟器装上,网络选 **宿主机的桥接**(模拟器用 `10.0.2.2:3000` 临时绕开,真机直接走 server IP) + +完整步骤见 [03-build-run.md](03-build-run.md)。 + +--- + +## 7. 与 web 端的关系 + +| 项 | web (Vue) | Android (Kotlin) | +|---|---|---| +| 主题色 | `#2080f0` | 同 | +| 字体 | 系统字体 + 14px/13px | Material3 Typography scale | +| 卡片布局 | 标题 → 译标 → 摘要 → 评论钩子 | 同(插图在中间)| +| 列表分页 | 12345 页码 (NPagination)| 滚动加载(Paging 3)| +| 详情页布局 | 评论 / 译文 / 原文 三段 | 同(改用 Tab) | +| 鉴权 | localStorage 存 token | EncryptedSharedPreferences | + +视觉与交互**保持一致**,不要做出两个产品的分裂感。 + +--- + +## 8. 后续可能加的东西(不在 MVP) + +- 推送通知(FCM / 极光) +- 离线下载包(整本周报导出 PDF) +- 阅读历史(本地,不上服务端) +- 暗色主题(Material3 Dynamic Color) +- 主屏幕 widget(显示今日头条) +- Wear OS 端(以后再说) + +> 原则:**MVP 先能跑,再加料**。每加一项功能,先回到 [01-architecture.md](01-architecture.md) 看会不会破坏现有分层。 \ No newline at end of file diff --git a/docs/android/assets/INTEGRATION.md b/docs/android/assets/INTEGRATION.md new file mode 100644 index 0000000..02f6af7 --- /dev/null +++ b/docs/android/assets/INTEGRATION.md @@ -0,0 +1,230 @@ +# Logo + 启动屏集成指南 + +> 把 `assets/` 下所有产物拷到你的 Android Studio 工程目录里。 +> +> 主要文件清单 + 拷贝目标位置。 + +--- + +## 1. 文件清单 + +### 1.1 应用图标 + +| 源文件 | 目标位置(Android Studio 项目)| +|---|---| +| `assets/logo/ic_launcher_foreground.png` | `app/src/main/res/mipmap-anydpi-v26/ic_launcher_foreground.png`(覆盖)| +| `assets/logo/ic_launcher_background.png` | `app/src/main/res/mipmap-anydpi-v26/ic_launcher_background.png`(覆盖)| +| `assets/logo/mipmap-mdpi/ic_launcher.png` | `app/src/main/res/mipmap-mdpi/ic_launcher.png`(覆盖)| +| `assets/logo/mipmap-mdpi/ic_launcher_round.png` | `app/src/main/res/mipmap-mdpi/ic_launcher_round.png`(覆盖)| +| `assets/logo/mipmap-hdpi/ic_launcher.png` | `app/src/main/res/mipmap-hdpi/ic_launcher.png`(覆盖)| +| `assets/logo/mipmap-hdpi/ic_launcher_round.png` | `app/src/main/res/mipmap-hdpi/ic_launcher_round.png`(覆盖)| +| `assets/logo/mipmap-xhdpi/ic_launcher.png` | `app/src/main/res/mipmap-xhdpi/ic_launcher.png`(覆盖)| +| `assets/logo/mipmap-xhdpi/ic_launcher_round.png` | `app/src/main/res/mipmap-xhdpi/ic_launcher_round.png`(覆盖)| +| `assets/logo/mipmap-xxhdpi/ic_launcher.png` | `app/src/main/res/mipmap-xxhdpi/ic_launcher.png`(覆盖)| +| `assets/logo/mipmap-xxhdpi/ic_launcher_round.png` | `app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png`(覆盖)| +| `assets/logo/mipmap-xxxhdpi/ic_launcher.png` | `app/src/main/res/mipmap-xxxhdpi/ic_launcher.png`(覆盖)| +| `assets/logo/mipmap-xxxhdpi/ic_launcher_round.png` | `app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png`(覆盖)| + +### 1.2 Adaptive icon XML + +把 `assets/android_resources/mipmap-anydpi-v26/` 下的两个 XML 也拷到对应目录: + +| 源文件 | 目标 | +|---|---| +| `ic_launcher.xml` | `app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml` | +| `ic_launcher_round.xml` | `app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml` | + +> Android 8.0+ 会优先用 `` XML。如果项目里已经有同名 XML,**整体覆盖**即可。 + +### 1.3 启动屏资源 + +| 源文件 | 目标 | +|---|---| +| `splash/drawable-mdpi/ic_splash_logo.png` | `app/src/main/res/drawable-mdpi/ic_splash_logo.png` | +| `splash/drawable-hdpi/ic_splash_logo.png` | `app/src/main/res/drawable-hdpi/ic_splash_logo.png` | +| `splash/drawable-xhdpi/ic_splash_logo.png` | `app/src/main/res/drawable-xhdpi/ic_splash_logo.png` | +| `splash/drawable-xxhdpi/ic_splash_logo.png` | `app/src/main/res/drawable-xxhdpi/ic_splash_logo.png` | +| `splash/drawable-xxxhdpi/ic_splash_logo.png` | `app/src/main/res/drawable-xxxhdpi/ic_splash_logo.png` | + +### 1.4 XML 主题 / 颜色 / 字符串 + +| 源文件 | 目标 | +|---|---| +| `android_resources/values/colors_splash.xml` | `app/src/main/res/values/colors_splash.xml` | +| `android_resources/values/strings_splash.xml` | `app/src/main/res/values/strings_splash.xml` | +| `android_resources/values/themes_splash.xml` | `app/src/main/res/values/themes_splash.xml` | +| `android_resources/values/dimens_splash.xml` | `app/src/main/res/values/dimens_splash.xml` | +| `android_resources/drawable/splash_screen.xml` | `app/src/main/res/drawable/splash_screen.xml` | +| `android_resources/layout/activity_splash.xml` | `app/src/main/res/layout/activity_splash.xml` | + +--- + +## 2. 集成步骤 + +### 2.1 加 SplashScreen 依赖 + +`gradle/libs.versions.toml`: + +```toml +[versions] +core-splashscreen = "1.0.1" + +[libraries] +androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "core-splashscreen" } +``` + +`app/build.gradle.kts`: + +```kotlin +dependencies { + // ... + implementation(libs.androidx.core.splashscreen) +} +``` + +### 2.2 `AndroidManifest.xml` 改启动主题 + +```xml + + + + android:exported="true"> + ... + + +``` + +或者用 v31 区分: + +```xml + + + + + + + + +``` + +**最简单做法**:在 `MainActivity` 里 **不** 用 `android:theme`,改在 `onCreate` 里用 SplashScreen API 处理。 + +### 2.3 `MainActivity.kt`(SplashScreen API 用法) + +```kotlin +package com.diary.news + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Surface +import androidx.compose.ui.Modifier +import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen +import com.diary.news.ui.theme.DiaryNewsTheme +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class MainActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + // 1. 安装 SplashScreen(必须在 super.onCreate 之前) + val splashScreen = installSplashScreen() + // 可选:保持启动屏直到数据加载完成 + // splashScreen.setKeepOnScreenCondition { !viewModel.isReady.value } + + super.onCreate(savedInstanceState) + enableEdgeToEdge() + + setContent { + DiaryNewsTheme { + Surface(modifier = Modifier.fillMaxSize()) { + AppNav() + } + } + } + } +} +``` + +### 2.4 应用名(`strings.xml`) + +确保 `app/src/main/res/values/strings.xml` 有: + +```xml + + Diary News + +``` + +--- + +## 3. 验证清单 + +装到真机后,逐项过: + +- [ ] **桌面图标**:长按图标 → 看 launcher 上的视觉,是不是米色木质方块 D +- [ ] **不同 launcher 风格**:长按图标 → 改 "Edit" / "Themes",确认 adaptive icon 正常(Pixel Launcher / Nova / 系统自带都试一下) +- [ ] **启动屏**:点图标,启动时先看到木色启动屏 + Diary News 文字,然后进登录页 / Feed +- [ ] **启动屏过渡**:启动屏消失时是否平滑(无白闪 / 黑闪) +- [ ] **暗色模式**:系统切深色 → 启动屏颜色是否仍然温暖(用了固定木色,深色模式不变) +- [ ] **横竖屏切换**:旋转屏幕时启动屏不崩(虽然启动时不会切,但要看 activity 不因配置变更崩) +- [ ] **低版本兼容**:Android 7.0 / 8.0 真机测试启动屏是否正常显示 +- [ ] **多 DPI**:在 Pixel 2 (xhdpi) / Pixel 7 Pro (xxxhdpi) 上看图标清晰度 + +--- + +## 4. 关于"以后用域名访问" + +Android 这边改 IP 为域名,只需要两处: + +1. `app/build.gradle.kts` 里 `buildConfigField` 的 `API_BASE_URL` 改成 `https://你的域名/api/v1/` +2. `app/src/main/res/xml/network_security_config.xml` 删掉 IP 白名单,改成默认 HTTPS 即可(或者保留 +加域名白名单) + +代码不动,业务逻辑零变更。 + +--- + +## 5. 设计说明 + +### 颜色 + +| 角色 | HEX | 来源 | +|---|---|---| +| 木色底 | `#F5E9D0` | 参考图取色 | +| 中木色 | `#E8D4A8` | 渐变中间色 | +| 暗木色 | `#C9A876` | 阴影 / 渐变底部 | +| 字母深棕 | `#3E2A1E` | 字母主体 | +| 木纹线 | `#A8825A` | 半透明纹理 | + +整套配色都是低饱和度暖色,**跟"私人日报 / 日记"的氛围匹配**,和 web 端 `#2080f0` 的蓝色主调形成"冷暖对比",反而有"早晚看新闻"的感觉。 + +### 字体 + +- 当前使用 Arial(Pillow 默认 fallback) +- 真机运行时,SplashScreen 的文字是 SVG/drawable 渲染的,字体以系统为准 +- Compose 里的 `Text()` 可以用 `FontFamily.Serif`(衬线感更接近参考图) + +### 安全区(Adaptive Icon) + +- Android adaptive icon 要求 foreground 主体放中心 **66%**(108x108 中的 72x72 中心区) +- 我们的 `safe_zone=True` 参数自动留了 22% padding,符合规范 +- **不要**给 foreground PNG 加背景色 —— 必须是透明 PNG +- **不要**让主体元素贴边 + +### 启动屏时长 + +- SplashScreen API 的默认时长 ≈ 200ms(很短,基本看不到) +- 我们做了 `setKeepOnScreenCondition` 注释,如果以后想"等数据加载完再消失",取消注释就行 +- **不要**手动 sleep 假装启动屏,Google Play 政策明文禁止 \ No newline at end of file diff --git a/docs/android/assets/_make_logo.py b/docs/android/assets/_make_logo.py new file mode 100644 index 0000000..eb5f2b9 --- /dev/null +++ b/docs/android/assets/_make_logo.py @@ -0,0 +1,289 @@ +"""重做字母 D — 用更干净的 polygon path。""" +from PIL import Image, ImageDraw, ImageFont, ImageChops, ImageFilter +from pathlib import Path + +OUT = Path(r'D:\selftools\diary-news\docs\android\assets') +LOGO = OUT / 'logo' +SPLASH = OUT / 'splash' + +WOOD_LIGHT = (245, 233, 208) +WOOD_MID = (232, 212, 168) +WOOD_DARK = (201, 168, 118) +GRAIN_LINE = (168, 130, 90) +LETTER_DARK = (62, 42, 30) +LETTER_DARKER = (42, 27, 16) + + +def lerp(a, b, t): + return tuple(int(a[i] + (b[i] - a[i]) * t) for i in range(3)) + + +def make_wood_gradient(w, h, top, mid, bot): + img = Image.new('RGB', (w, h), top) + px = img.load() + for y in range(h): + t = y / max(1, h - 1) + c = lerp(top, mid, min(1.0, t * 2)) if t < 0.5 else lerp(mid, bot, (t - 0.5) * 2) + for x in range(w): + px[x, y] = c + return img + + +def add_wood_grain(img, spacing=10, opacity=40): + w, h = img.size + overlay = Image.new('RGBA', (w, h), (0, 0, 0, 0)) + draw = ImageDraw.Draw(overlay) + for y in range(0, h, spacing): + op = max(15, opacity - (y % spacing) * 2) + draw.line([(0, y), (w, y)], fill=(*GRAIN_LINE, op), width=1) + return Image.alpha_composite(img.convert('RGBA'), overlay) + + +def draw_letter_D_simple(canvas_size, box): + """画一个干净的 D — 用 polygon 直接画出 D 的外形。 + D 的几何:左竖条 + 上下凸出半圆(右半)+ 中间挖空。 + """ + img = Image.new('RGBA', canvas_size, (0, 0, 0, 0)) + draw = ImageDraw.Draw(img) + x0, y0, x1, y1 = box + bw, bh = x1 - x0, y1 - y0 + cx = (x0 + x1) // 2 + cy = (y0 + y1) // 2 + + # D 的外轮廓尺寸 + dw = bw * 0.52 + dh = bh * 0.68 + L = int(cx - dw / 2) # 左 + R = int(cx + dw / 2) # 右 + T = int(cy - dh / 2) # 顶 + B = int(cy + dh / 2) # 底 + # 笔画粗细 + bar_w = dw * 0.32 + # 凸出(让 D 顶/底圆润) + bulge = bar_w * 0.35 + + # 1) 画 D 的整体外形:左竖条 + 上下半圆 + 右半椭圆 + # 用 polygon 拼一个 D + D_path = [ + # 左竖条顶 + (L, T + bulge), + # 左竖条底 + (L, B - bulge), + # 底弧起点 + (L + bar_w * 0.4, B), + # 右半圆底部 + (R - bar_w * 0.3, B), + # 右半圆弧最高点(顶部) + (R, cy), + # 右半圆底部 → 已经在 (R - bar_w*0.3, B) + # 顶弧起点 + (L + bar_w * 0.4, T), + ] + # 实际上我们直接用 pieslice 拼 + # 顶半圆:从 (L, T+bulge) 到 (R-bar_w*0.3, T),画 pieslice 180°~360° + # 实际更简单:画三个形状叠起来 + + # a) 左竖条(矩形) + draw.rectangle( + [L, T + bulge * 0.5, L + bar_w, B - bulge * 0.5], + fill=LETTER_DARK, + ) + + # b) 顶半圆(右半,从 180° 到 360°,中心点) + # pieslice 接受 bbox + start/end angle(角度,3 点钟方向=0,逆时针为正) + # Pillow 中 pieslice 是顺时针 0=3 点,90=6 点,180=9 点,270=12 点 + # 我们要画右上 1/4 圆:从 270° 到 360°(即 12 点 → 3 点)不对 + # 重新想:画 D 的右半外轮廓,是一个完整的椭圆右半 + # 顶弧:从 (L+bar_w, T) 弧形向右下到 (R, cy) + # 用 arc 描边粗一些,然后用 chord 实心填充 + + # 直接用 pieslice 实心填充 + ellipse 配合 + # 简化方案: + # - 画一个完整 ellipse fill DARK + # - 再画一个稍小的 ellipse fill 木色(挖空内部) + # - 用矩形覆盖椭圆左半,挖出左边的"竖条" + # 这样视觉上就是 D + + # 整个 D 占的区域 + full_ell = [L, T, R + int(bulge * 0.5), B] + # 让椭圆稍微超出矩形一点,确保右半圆足够圆 + inner_ell = [L + bar_w, T + bar_w * 1.05, R + int(bulge * 0.5) - bar_w * 0.55, B - bar_w * 1.05] + + # 1) 整个外轮廓 fill DARK + draw.ellipse(full_ell, fill=LETTER_DARK) + # 2) 内部挖空(fill 木色,让字母透出底) + draw.ellipse(inner_ell, fill=WOOD_LIGHT) + # 3) 用矩形盖住椭圆左半,形成 D 的竖条 + # 矩形左边到 L+bar_w*0.9,右边到 inner_ell 的左侧+一点 + rect_left = L + rect_right = L + bar_w + (inner_ell[0] - (L + bar_w)) // 2 + 2 + # 让矩形比椭圆略矮,保持椭圆上下凸出 + rect_top = T + bar_w * 0.85 + rect_bot = B - bar_w * 0.85 + # 矩形 fill DARK(竖条) + draw.rectangle([rect_left, rect_top, rect_right, rect_bot], fill=LETTER_DARK) + # 4) 在矩形右侧挖一个米色矩形,让 D 中间真的空出来 + # 计算 D 中间的"肚子"位置 + mid_left = L + bar_w + 4 + mid_right = R - bar_w * 0.4 + mid_top = T + bar_w * 1.1 + mid_bot = B - bar_w * 1.1 + # 用椭圆 fill 米色 覆盖中间的"空腔" + # 但这样会把竖条也覆盖,改成用 polygon + # 实际上 inner_ell 已经挖空了椭圆内部,现在要把"竖条"也挖掉中间一部分 + # 方法:用 ellipse 在竖条右侧挖一个椭圆洞 + draw.ellipse( + [mid_left, mid_top, mid_right, mid_bot], + fill=WOOD_LIGHT, + ) + # 5) 用矩形 cover 椭圆左半(只留右边空腔) + cover_left = mid_left - 5 + cover_right = mid_left + (mid_right - mid_left) * 0.30 + draw.rectangle( + [cover_left, mid_top + (mid_bot - mid_top) * 0.05, + cover_right, mid_bot - (mid_bot - mid_top) * 0.05], + fill=WOOD_LIGHT, + ) + + # 6) 描深色边 + # 左竖条外缘 + draw.line([(L, T + bulge * 0.5), (L, B - bulge * 0.5)], fill=LETTER_DARKER, width=3) + # 顶弧右端 + 右半圆 + 底弧右端 + draw.arc(full_ell, start=270, end=90, fill=LETTER_DARKER, width=3) + + return img + + +def make_block_icon(size, safe_zone=False): + canvas_size = (size, size) + if safe_zone: + pad = int(size * 0.22) + else: + pad = int(size * 0.08) + box = (pad, pad, size - pad, size - pad) + + bw, bh = box[2] - box[0], box[3] - box[1] + wood = make_wood_gradient(bw, bh, WOOD_LIGHT, WOOD_MID, WOOD_DARK) + wood = add_wood_grain(wood, spacing=int(size * 0.025), opacity=50) + + wood_rgba = Image.new('RGBA', canvas_size, (0, 0, 0, 0)) + mask = Image.new('L', (bw, bh), 0) + ImageDraw.Draw(mask).rounded_rectangle([0, 0, bw - 1, bh - 1], radius=int(size * 0.18), fill=255) + wood_rgba.paste(wood, (box[0], box[1]), mask) + + edge = Image.new('RGBA', canvas_size, (0, 0, 0, 0)) + ed = ImageDraw.Draw(edge) + ed.rounded_rectangle([box[0], box[1], box[2] - 1, box[3] - 1], + radius=int(size * 0.18), outline=(107, 79, 48, 200), width=2) + wood_rgba = Image.alpha_composite(wood_rgba, edge) + + shadow = Image.new('RGBA', canvas_size, (0, 0, 0, 0)) + sd = ImageDraw.Draw(shadow) + sd.ellipse([int(size * 0.28), int(size * 0.93), int(size * 0.72), int(size * 1.02)], fill=(0, 0, 0, 50)) + shadow = shadow.filter(ImageFilter.GaussianBlur(4)) + + hl = Image.new('RGBA', canvas_size, (0, 0, 0, 0)) + hd = ImageDraw.Draw(hl) + hd.rounded_rectangle( + [box[0], box[1], box[2] - 1, box[1] + bh // 2], + radius=int(size * 0.18), fill=(255, 255, 255, 35), + ) + + letter = draw_letter_D_simple(canvas_size, box) + + final = Image.new('RGBA', canvas_size, (0, 0, 0, 0)) + final = Image.alpha_composite(final, shadow) + final = Image.alpha_composite(final, wood_rgba) + final = Image.alpha_composite(final, hl) + final = Image.alpha_composite(final, letter) + return final + + +def make_round_icon(size): + canvas = Image.new('RGBA', (size, size), (0, 0, 0, 0)) + wood = make_wood_gradient(size, size, WOOD_LIGHT, WOOD_MID, WOOD_DARK) + wood = add_wood_grain(wood, spacing=int(size * 0.04), opacity=50) + + mask = Image.new('L', (size, size), 0) + ImageDraw.Draw(mask).ellipse([0, 0, size - 1, size - 1], fill=255) + canvas.paste(wood, (0, 0), mask) + + letter = draw_letter_D_simple( + (size, size), + (int(size * 0.20), int(size * 0.20), int(size * 0.80), int(size * 0.80)), + ) + canvas = Image.alpha_composite(canvas, letter) + + hl = Image.new('RGBA', (size, size), (0, 0, 0, 0)) + hd = ImageDraw.Draw(hl) + hd.ellipse([int(size * 0.1), int(size * 0.05), int(size * 0.9), int(size * 0.55)], + fill=(255, 255, 255, 35)) + hl_mask = Image.new('L', (size, size), 0) + ImageDraw.Draw(hl_mask).ellipse([0, 0, size - 1, size - 1], fill=255) + hl.putalpha(ImageChops.multiply(hl.split()[3], hl_mask)) + canvas = Image.alpha_composite(canvas, hl) + return canvas + + +# === 重新生成 === +print('[1] master 1024') +make_block_icon(1024, safe_zone=False).save(LOGO / 'icon_master_1024.png') + +print('[2] adaptive icon 432') +make_block_icon(432, safe_zone=True).save(LOGO / 'ic_launcher_foreground.png') +bg = make_wood_gradient(432, 432, WOOD_LIGHT, WOOD_MID, WOOD_DARK) +bg = add_wood_grain(bg, spacing=12, opacity=30) +bg.save(LOGO / 'ic_launcher_background.png') + +print('[3] launcher icons 5 DPI') +SIZES = {'mdpi': 48, 'hdpi': 72, 'xhdpi': 96, 'xxhdpi': 144, 'xxxhdpi': 192} +icon_master = make_block_icon(1024, safe_zone=False) +for dpi, sz in SIZES.items(): + d = LOGO / f'mipmap-{dpi}' + d.mkdir(exist_ok=True) + icon_master.resize((sz, sz), Image.LANCZOS).save(d / 'ic_launcher.png') + make_round_icon(sz).save(d / 'ic_launcher_round.png') + print(f' {dpi}: {sz}x{sz}') + +print('[4] 启动屏 logo 512') +make_block_icon(512, safe_zone=False).save(SPLASH / 'splash_logo.png') + +print('[5] 启动屏背景 1080x1920') +bg_w, bg_h = 1080, 1920 +bg_full = make_wood_gradient(bg_w, bg_h, WOOD_LIGHT, WOOD_MID, WOOD_DARK) +bg_full = add_wood_grain(bg_full, spacing=20, opacity=35).convert('RGBA') +logo_big = make_block_icon(512, safe_zone=False) +logo_x = (bg_w - 512) // 2 +logo_y = (bg_h - 512) // 2 - 100 +bg_full.alpha_composite(logo_big, (logo_x, logo_y)) + +draw = ImageDraw.Draw(bg_full) +try: + font_big = ImageFont.truetype('arial.ttf', 110) + font_sm = ImageFont.truetype('arial.ttf', 38) +except Exception: + font_big = ImageFont.load_default() + font_sm = ImageFont.load_default() + +name = 'Diary News' +bb = draw.textbbox((0, 0), name, font=font_big) +tw = bb[2] - bb[0] +draw.text(((bg_w - tw) // 2, logo_y + 512 + 80), name, fill=LETTER_DARK, font=font_big) + +sub = 'Your Private News Diary' +bb2 = draw.textbbox((0, 0), sub, font=font_sm) +tw2 = bb2[2] - bb2[0] +draw.text(((bg_w - tw2) // 2, logo_y + 512 + 230), sub, fill=(90, 65, 40), font=font_sm) + +bg_full.save(SPLASH / 'splash_bg_full.png') +print(' OK') + +print('[6] 启动屏各 DPI logo') +SPLASH_SIZES = {'mdpi': 192, 'hdpi': 288, 'xhdpi': 384, 'xxhdpi': 576, 'xxxhdpi': 768} +for dpi, sz in SPLASH_SIZES.items(): + d = SPLASH / f'drawable-{dpi}' + d.mkdir(exist_ok=True, parents=True) + make_block_icon(sz, safe_zone=False).save(d / 'ic_splash_logo.png') + print(f' {dpi}: {sz}x{sz}') + +print('\n=== 完成 ===') \ No newline at end of file diff --git a/docs/android/assets/android_resources/drawable/splash_screen.xml b/docs/android/assets/android_resources/drawable/splash_screen.xml new file mode 100644 index 0000000..ff6e0ea --- /dev/null +++ b/docs/android/assets/android_resources/drawable/splash_screen.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/android/assets/android_resources/layout/activity_splash.xml b/docs/android/assets/android_resources/layout/activity_splash.xml new file mode 100644 index 0000000..666e792 --- /dev/null +++ b/docs/android/assets/android_resources/layout/activity_splash.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/android/assets/android_resources/mipmap-anydpi-v26/ic_launcher.xml b/docs/android/assets/android_resources/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..4ae7d12 --- /dev/null +++ b/docs/android/assets/android_resources/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/docs/android/assets/android_resources/mipmap-anydpi-v26/ic_launcher_round.xml b/docs/android/assets/android_resources/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..4ae7d12 --- /dev/null +++ b/docs/android/assets/android_resources/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/docs/android/assets/android_resources/values/colors_splash.xml b/docs/android/assets/android_resources/values/colors_splash.xml new file mode 100644 index 0000000..a89a51f --- /dev/null +++ b/docs/android/assets/android_resources/values/colors_splash.xml @@ -0,0 +1,7 @@ + + + + #F5E9D0 + #3E2A1E + #5A4128 + \ No newline at end of file diff --git a/docs/android/assets/android_resources/values/dimens_splash.xml b/docs/android/assets/android_resources/values/dimens_splash.xml new file mode 100644 index 0000000..869109a --- /dev/null +++ b/docs/android/assets/android_resources/values/dimens_splash.xml @@ -0,0 +1,5 @@ + + + + 160dp + \ No newline at end of file diff --git a/docs/android/assets/android_resources/values/strings_splash.xml b/docs/android/assets/android_resources/values/strings_splash.xml new file mode 100644 index 0000000..0057caa --- /dev/null +++ b/docs/android/assets/android_resources/values/strings_splash.xml @@ -0,0 +1,6 @@ + + + + Your Private News Diary + 你的私人新闻日报 + \ No newline at end of file diff --git a/docs/android/assets/android_resources/values/themes_splash.xml b/docs/android/assets/android_resources/values/themes_splash.xml new file mode 100644 index 0000000..8eb82f1 --- /dev/null +++ b/docs/android/assets/android_resources/values/themes_splash.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/android/assets/logo.svg b/docs/android/assets/logo.svg new file mode 100644 index 0000000..f579fd9 --- /dev/null +++ b/docs/android/assets/logo.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D + + + D + + \ No newline at end of file diff --git a/docs/android/assets/logo/ic_launcher_background.png b/docs/android/assets/logo/ic_launcher_background.png new file mode 100644 index 0000000000000000000000000000000000000000..376ea19b4720975659e1cd2214bf323c01f6579d GIT binary patch literal 2185 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

N?IjnHuj#cj-Ys&p;1+OOx#P92ge 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 HFt7d}_D{MW literal 0 HcmV?d00001 diff --git a/docs/android/assets/logo/icon_master_1024.png b/docs/android/assets/logo/icon_master_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..0faa07937bfae71b2d02170ee4d1ff437f91c2a0 GIT binary patch literal 18447 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 TCs9G*A2u#tz37pRAo%|Qgx#V1 literal 0 HcmV?d00001 diff --git a/docs/android/assets/logo/mipmap-hdpi/ic_launcher.png b/docs/android/assets/logo/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..0de65c90623655fb307ad28b46502fc6e43604d0 GIT binary patch literal 4313 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 Hu0mjf{|Q<@ literal 0 HcmV?d00001 diff --git a/docs/android/assets/logo/mipmap-hdpi/ic_launcher_round.png b/docs/android/assets/logo/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..f9e4cca435d8a7cdf6226d5e15ffd45513e05d7c GIT binary patch literal 1532 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 DsPEOx literal 0 HcmV?d00001 diff --git a/docs/android/assets/logo/mipmap-xxhdpi/ic_launcher.png b/docs/android/assets/logo/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..ddd5ebf5abe641ccf89474b6df3eb4c80c978aca GIT binary patch literal 8600 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 literal 0 HcmV?d00001 diff --git a/docs/android/assets/logo/mipmap-xxxhdpi/ic_launcher.png b/docs/android/assets/logo/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..27c735dc4b3ebb1946e11aa1ed7170b8afffecf2 GIT binary patch literal 11643 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 literal 0 HcmV?d00001 diff --git a/docs/android/assets/logo/mipmap-xxxhdpi/ic_launcher_round.png b/docs/android/assets/logo/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..628da44b4c2f68e1724afdf38e248f2843b7df1d GIT binary patch literal 3585 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 Hu0mjf5cjvn literal 0 HcmV?d00001 diff --git a/docs/android/assets/splash/drawable-hdpi/ic_splash_logo.png b/docs/android/assets/splash/drawable-hdpi/ic_splash_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bd5b971edd686e986374b2539a512468b2357b45 GIT binary patch literal 5460 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 literal 0 HcmV?d00001 diff --git a/docs/android/assets/splash/drawable-mdpi/ic_splash_logo.png b/docs/android/assets/splash/drawable-mdpi/ic_splash_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..deab548f7473f3dd0b66aa0884849f4572b26244 GIT binary patch literal 3822 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 literal 0 HcmV?d00001 diff --git a/docs/android/assets/splash/drawable-xhdpi/ic_splash_logo.png b/docs/android/assets/splash/drawable-xhdpi/ic_splash_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..add29f79951d82354f39ef6aa0d45f9ca745c753 GIT binary patch literal 7275 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 literal 0 HcmV?d00001 diff --git a/docs/android/assets/splash/drawable-xxhdpi/ic_splash_logo.png b/docs/android/assets/splash/drawable-xxhdpi/ic_splash_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e5fdf9e980bb11c3bd80c134e8326879568bcf56 GIT binary patch literal 10536 zcmcI~i93{0|NfZ;W1legGPH;am3^DB6fKrwB(g>Jt?cWJT@)%3VJv0evX-n#XkjFY z?2&!n#xne#-uM0f3BS26*K>K!^O@)VEa!9X`p7KibmH_8u*yW|)C*!1Xp%{OuL=`dp|}_<5Oy6dVJ6v&a-#nbPQMMpFqF920owOKq-SF1`(^%=ivJA@MEMcMhyo}5(l%Y z(B6-{R%v?d{q3Qx>Rt&0OiVK15^iC@3aXuEh3lVyo*h3DIdKxOri~$_0z>r!k(nVJ zfnee|s!ap%`>yQ#59f!u7k6LckW83my zZ7R$X6?09pnAuU6&VFjeW06Tu4phx&D7mU^R?4Vt7JxnouassRu7eOd$4PQT2Ls*< z!ublYd|0nJU`aY($Op53XxijEY$Lt;366b=mL3pzZ>$YWEVt-)p{)4QW7#UtUqhLE zyGWgfS!=u~d>`56SAbPZQo9Ht=w6yxZW~-~x=z5zS z`OxiyEIm*xe^c${`1SqICsw)5F<+D53F6j6Y6E4kiX{fp9b@(?$$0=dmmnZ)pDcqn z@V*Ws72BA?6bZCzqr0E>~t*;H%P6M$$4`jXBn2t_0(0iOcI>k z>~Shp@X|DvV7ph{yBDR(TPFsjjM<6XAryU1pnM2a{U{iu3lj16s?Cs zyr{c5U04(}D-6zhET>mWYSqikK1%o|Vh>1X;gsTC1mM-EG(~v!_4Ug`X?KiE*&gxJ zTI(i!$6x`e7*08un0DA?0QvKU4R0<^y*|-N|DXE_P>_qK3qKa&ul(mm99-#z;WL&J zK-v4{?{e4T(FU7piIOz1HhAc0p zSrB{EJ0~Mw{RA$~iw8bkiruBlfU-qRw4Gq^0&jCr$K8T7_j*4~+{}?N zMgH&_HS<|a%PVI){Z32@8%OGW&TPJ26VcDCjsF0%uUTtn!p`(!+-SWmxN!n(cE>{H z=&N(+rq0uthe#~8x_RBLTP3frpdy>u+-D$Uluo2WZ^Og4c4S{{o|t+3R=o=qlOX~B zzJ6G&j=a_n8+JGS!KY4#(w5jbTXf zZ&=0w#COHJ&itVndsFO)YNoYv3{7H1bOFx(Q7BxOU2U0{HZ!{yR?T>G6cc=A*KDl2 znpru)R%XT}ImmbVj!d-hV07RuUndfvZ<3uksx}B0<0OG>`I`$zL(x^*0M2{54?Ck< zH}TkONM4`3IRZ!WNwH3e=At*fJpKXdWoPw1NRc(zO_ ziDoK5V7I)~)X~zX0PK}};tMqLG33h=j!^8EOO(pKZX-3sj-t!`4Z7a8p7zk1hj*@D zK5qbnYnO6tbXmHD7()*;qC>II#L5RGsw6Yyk3o|ck`EB35dz*}43-_eR&G_NP~TJF*Y05y@j^+N4k-Vv9Z}_h@^%q> zlC!wlGSg3PUVaFsl{(rG@|;5y*)og7l2}k`?g;>yz$lFR=Qwsgr*%XIGHnm5VN}pu_>d$$`Kn4CN! z^{C$IYXhvRRM(a1NJlt6RjH%tPfm^4?Mv@f4=x_uy#Y0bL2uwHmr&per+Uy|fz4PO*8gB1kfC6tXv=^Zz@Lld(9YGjWWV z!;1fH4Pgm?FfLFgsN%Ko+nn^sW%+UIn;2QB{VXlg6G!}@-jpy^t2s|xuX!WK*8Z6v z3yhS+7arg8{~P@rAe%pjWAB~>FiLdJ2W_=~_0!hCbQBvQPPy2v%3sGviDp8B#|7{s zN|1Zp+?q}8mD+|7WD{ZJ5l-k<5(Lqxhd%R9(*beMDKmW{n2l6bh|k*N${X2T`cwHv zUOf(u$n0~A-b!XYA6)}SHcOfLjt6MS!Jc!Ffbq*}{Kr#+V&$vU$u8Y0$@Kq}j-g>l zhT@h^_q7i-?SInW$p3r6w{Ios>Gs`<{jMt@Z0MZ%VOrJWZ{Pk6<~Dp_91q%cbclI@b!p!eA)9sdv=0+9GT!w}x={C)sa-l@zv zgJVo?+PSJ{>E;w-X`IcD|AVW)FsS^eI_o8jMSe!QL9Znr5qIm#XKLTA%Wq;;0nA}e zWTklb7rbYekjX6RKRT0Qp*-}V2$3^{pe%GVn#O2|t4C(kEpkNu%wkE5yRuPc_YsED zZqe81R{lUyBxG*KXY90Tq}NL%+ykjymrNLt_aC04p54XeGd+2BA3jff3iVXwn<&+L zq546Ec$Q05F#Es<^&STw+z#$d?>{2a9LKm}@94-E)bdA!SE0c5{B}~`GpEsF89t30 zUlJh6*2?;Hb*mo6dlP+5E3@2WYstHgHd$DCH@&rSl@hU9WGBcQWsPwGgSGFOg7)XW zsH0i5 z=aP^G{om|Z9J=bNCbLT{zGdtwmZ`zZI1}Cp=C*G1wVrpFmDS)T(w$y!rIG?)LEVYU z(QBz8)n)VbQ4Rcua@eN~0_^)8hK+enNiK<=TTya+Q`lH0ecgxL+NN^^><4~3X(L-s z(t`l25Kl%mPph;6-V_3WYhSu5obM~Y-FW#j?R`RwFnZFxxG=98Nk z)GqgZU_uip`c&39DNshg`Pibl@H>lI*50dn-9OdsALTCzl72q3e#efD^THF4Rh?7d zvs322yr+WyE!qyn@!*S_QDgkYu15i)rX<6rle<%#qUv&1iF>ZgUhV%aI$1fVMf#>k z!xON`_NA3^pMWwYws!H~V&y4mUx;|c?{}CrZ+-ft3Uym?<+8aEmS zqADx7AHatSNn@NL(fb~bPWBHg>=pL4IC}Bo&qYoWQ~i0MopgQ)3t68p#FwW5LlI#F zOKV$lu#_j~Q!D3dQow7qZA{c6$PZZPW^^;!TND#AC*;)Q=_$C^?sJaUW7Bh*|GL}o zHltrj{fNw2d*)7;e{Dn_eEiJ&+#k%n^_D*fbBm#$;F_1_o&U}EzAnQw_Rc;G1+WlJ z{hv^Lqb6WdO_$lo|Dn{hvvl?IGf*O)~sd?(Cl!^}Cq{;w(R zjF}bY;%r`(czFlQXy;3!7{aYG{3e2Un-ZI#z|utF-yCJqPAgzUNR+ z8X`x1rhUv6JV&2!nJ7tRc_xEL+zaNNiBW0U%@Pu-p`O7%tW-r|CB#+lqe&wB_>^M^ zUhXVWRk(h*VFZX&TX}d34m+d-Y^#;cQqKw4E{ zM1i>KdrS%0Uwat%E9jVZ=NHKZqlP`M-lc^s$n}%u0{ic>UUIM++{1rmBYSu+6EZG# zOMm)mE$5qk2)0t6-Eh)X)F-LQ!b(4vJ$2+C61@_3m@iLPC21G?kK@ zkVdSi!~_ht%jF+*-a^YU7=S1kX+cwo?z!#}Hqz9_X4N%12p9xE;h`}P zUV~?X3^%~gX_Ff>o?j9o1)c)m^UCsEAP%tjECAw=@<$+c8OF1>k=z*k_K$mUHY;Ah zv~qZ?8`2s;aftrUZ2Mu?y3!alySUX5VBld5ysC-k@|ZWEoTKeaL81FcUGFSF8i#q+ zh?EG$;D}#=@a<>{UocA5S^X~}37IEyn=&;Z_7-*ru$skqvqDj=71+No#7*KV!m$VM z*#_;CzWr}H$ocqWsRS+!Kr9Wc2{fhj7#!%tf!Utg-t&;Yd~&U17ZHU1=Y(^c`BB12x(Cm%ZsxrO zyPaB%g>Lc9He9v#2z^CK7=C1Y+H=>djt6o;0j3=roPNw0fkbCPZc*5w_IjZpf{d6a z9y_@DZ!xjYYp&V$&I;Oz;L(ty%anr#F9i7q{x9|~-?tUDPN!j@tW;@|kB!O;7QHoP zPj~`(yLBj%Sn?~L7>l5~?Dhc?;AVCk^f^S2{~f)rGs1o9@_`OqCQTgH&r zYe6ZSIfFm2hZebORI%Q8PW25~hZcjjTIsl5GD`FCdI${p+>|P&OH^4MJ7gQ=UV{iP zGSQS8k`+yqqjEybf8scG;d@lO({I-mD`#idr8FVc=>_~bV64+MKHa?0&wicQ=4|cu zZ#rNygSfk&)C#la>K!cD&zxczNiZ*4*%%Ff29f(n*|*H<>*SYdm?8)>1Y?w4>T8QR zN|74qPWgkQTI{-o#;AfFWQ$Y*J)>BEN*J8;{+qjJZv6M&I+-~6NpB)Cr$T(HRljdGlnv4cV5P+{qNhTI^ zK0>A+6yoA_if~d`Xr`@hZFTLOk!*x^VeokM>w+77vwZ(2EL@!z(wepwD%IuaNGGEj z=ZktP-$BX(TJJn#E>S?()-MDxr_9!UBF+u4#7U~2pob>Iuo2Oc^iMbB>}s6NHbdA* z`jV`acAH13OXP5!%lBht!RvJn@XCbNgS&WVl>tkZB(*5)4j+~hZ7Idj6m6hQXno4L_sxenHaD+-LscxU@>X)FU?7iBht3x7vIFz zz-=zFkgR++4kS&eX|Fp^+d_h0I(t`xNu(52$Bo<8J!AAkDR&q6%D4EY>R#8BhvULt)N+-D`P>Ka3tO( ze#mJqR{EnU?CQx-_{R&IUduYWcb;ZJLnkeKwLfQ<02ep6<+P@?r^92gI`2^zVoB5M z2mfu-*4DMYo2iux^z4*-o73az1(Ny4{^O@&8wZwTq%apN_)&;-0!!-p(A_%v?gsAK z(}_|GNF5EYARHiRBp);k;hKPQB)F#QJz;^cfzZ954_p zV#AF#s^P9ahg$aUKf`AB#J%rlpw@@JM}4>byn9aLcEJC9@u(5lcY^YQ?fT4KB?T4N z(oaNr;tGP1Kni3P!LP5ZkJY-ZnBl5KwlHs@dNnv3N}taY+_*^>bZX%|)IqONVY(0y zj^q2y45LS@HZW1l$J^B`@k^h_rx`}~>l>de z=}ZJaB|yf^xc?Zxf{gDoolW8wY));ln}Z&5+tuh0hH?Rw7jds*cr2v8wOhqv?@W+z z%l{g?EF``x)=eOFo}%j)WNoq;QVz9CsF0&cD~QDyNCzh@`U@oqbtr&EiQo)lB&!Wq zaO2_Q!@^N(?5Ug=5EBP$Ose<*$b=U?&ais~(hN&Xg3bG59^2-9S~!N1e@*ZK6{ZM{ zbdWFO)gfqmK1AJ7`lHvd&^FG^%@lf}Om@imc%%?-m@Qo%-c+FRBGHQ? zGXk!MomsOx8tf`Zq3+EbrbnQr(358w?`}{=eklpWT61~P*$31&c(`g&-v-SuA6)R{ z%-%|o3_R}1X|KPU(lEMd`bz5H)7d#_C-0qUv;Vj8{%}_&q{o+AWkP0$WY<+D7G>)7 zpykrT?@p$f^Q&^UHyE&%IHV4v`Z!7z%>zSmh@dw0Rzl?4j*@J(ND3S*Y;UK|1Yokd zU+~W>Z9t}74FwWGoCT?mvUz;K)!8Hx+t6Clye=(}X4kl+uv9VVF-?@%&(#afirreN zPI+1C_eEE4{b0LE#?t`HMCJ}RDcMqX$5QdT$NXm?6{EEjy^W@Zi{tTT7Qc&_7}bmD zGWc2;CQbphziRg4+fpYs@WJ01@mn8BNkNNW`ZIQSddUqkJ9ZVWV=4Y)aZMwKmvD$q zZK%9Uw9m1~Fe)WwF=*d}wkdT@QMATd$o~^A(INIpB!g2ccolY){bwh*@&7g=&Jd#N z*fd>`Fa40mptZt;SyQ8!gHZ`z0kaPXaJxml6)aFEme3$My1&e$%0O-yH!V@s8r}bW z_;$sg2Cu@6LCwzo~3)?mjlYY@PJYiC6rQfxZ}VvAbdbufB}AJDnrZvE0b&l zcvNylGBo4cm9C$#froscj?YQ!q4p_ow45glfC@(Z8aqh%#-DlHVd;q$ksqpngmA5` zPd^fKo1XsL&mYhY`NlCHFuMMi@(qyeRn}&@FBe=bg(sRkWCQ9-Pse_xI@8%l^-%zx z4U>t8&5F-8twWF`R4U{mbB$?N>flu>Bg1dDe9HDE{v9C<-j^m^$*oHnkke?I{wx;( zkxb1$JvlhNy4`0BT)Y7P+`zK!5+z=B*Moos_WHCdX5TTH$9?|$tw*l}vgjy6{L%1= z;_$a2&&`+TBI!wWvE=3b+iN@ce-u)e8)pC9#^d%cI_TIZ^~Rmf-NzjESf8Z)_|87nv}!0Ew+8=%8NCku!K zaWt4Tqjfs6>i2AIE#1r3VLN-@gKx;+Nx858?-mh!tsY zB^Pn$WmW**$*1~JJH45lZH=g3Y5@u#cPdLj3Je&La$ODS;Mm@|?#Fz$h?n0nWQqx+ zNOw@Uy^0KYk-znwozhqhIRr5A*?34?E9SPbfTezJU_s$kANjpUX092&2xr0HwY7e^ zQmF^T(V;;5@rr>CNYyxrBK_j~^0yLIm(Aq)N7TFNr2mCg9Y&z(?8f_kRl>>aiy=w; z>&WSNmDSk7BADfht@VrlTB6`sqYvE=*bdDnI@%?N#juUEb7f_#o^ZUe9&IvNXr3J^(V4n&y1(_q9Q?HXOTOtP32qQE*FC zIC=90-07a;!Uq`(dXT@oYTdmMuk~}kSQ9v&L7GV*VU&h;GFR{*7F6?whhxDm3RkE) zUrC=&S1EV*d=dixGMwxUohizm-1;QD%ul+maxht$7i_fS5D$J>q5PB4$Y%Zwbg-f| zQ}MkvPxHV(a6IP+J?KPI(X-WJVd(_UYk*u|`XvgEJ)(EGaVsylaYw-0b2$e5m`?nq zRLl&wY!nT)Z_u+qW{zl31a^J3fynwtcCylDWn0%UC&~W=3Z{RG8g6yOGoS8z#4C1u zMmX8skQAxU>i^#1JSk0iHF36-g3Khvaj8=hvB(6ym6W>9%egHmd>D&5Pq-5cC<&M- zm}cLXph6^%RT>2acs4?)#ZDeN1HQou*A6S}E@#9)L1u{&gh_AJyAun$r5N!DpUFR= zXnbPJ^b)O1)ylVC{)znBDlMqZ)-W7I@&+!9Vi2&?>L1W}d38O0WM=g63QuyH5yt=b z%LB6)pTLPFE!<&Ko|*T$+(C~#znJ8mY)n>)&#ta8DM_&C#YpP;Zx|fxbe@!Fili~p zc=A`Tx}F3w^Li`ghmvGK5b-gLH`7}0@WJ?|xXLUC=|aU>v<~AXe5sY))v?YfkoZP1 zBwt$|eiNl|39i?O#QtQu1m2*%Pjis+b>!iZx*b^(FjVA@f>PCAm*=!SLYa_1`FvUE zyW)y>U7KEoxkZLX1nVpfjpeV{w(jrZEw4MLiXxLWoQAgbuRGqUar{-_Fd@*r7hzM4#SUzh zS8ir1GPSP%9J7c^c(UU5`3+U;3R_@uQu7@1g;-b9?K;2s%9*v?+K^(FhKpgU#TCbF zhxH9aXA<3hOP`ftl+;;r%BOv@`9`_0T$j5ob9;PL$As{VcM4|zU0vRh<7XjC^MuPxI$!bK zq-q5n#FgHJ%B3c9{|LeL)@uhZhmJu(YJWjTF^B8iNN#77+xM-)(PT5W8!@jn!erIE zE8GnZ8U%HpM=UQj-McfWUe zhOVADlwbBE*?;_=rS`0)&H-bWGay2Ny-xbP_409}qg5{> z^Xrll33-jr=~Dd0?QWbNEcH8_`u)RC)pF(T@=%9Xx{iIqRKFyww8{BN=j76tv=M2RKGsmF z(;D+1EeFOdL{|*yQWg7UN&ta&r?GgSSipoY+Be^>lXWG>%4+2`paNf~`Z_s>gJ=@Zd#gGthHtk0mnK|)LnEHcN zd1|Hd>WagK*L|-(UtIPsQr2P_ebq`b^x1VDNgOCt%l9>xLo=$gJl9R46pEiA^kw*s z=L!ZIvEm5v7S0x?ed+hQVLSHxPmKyVz7;V&{)tkH4W-mu8g5dHlo=?gC0k2O{4Z}g z+%_5>Fm}KF%%N<;+Nj!YY`VLbbxYA!J%tBfsNQWmyY@|?C9iPTz$d0?uD-Cr>p+k4x-+#e`_iwK!O*P$Lo9D`LiuIjS0?sBNSJY_dLX5cznv891pA0a-AbfTovXFWa% zv(H)Cd#g{E8nji|=;y!n{wlhGlf-L66=O*MrjUG#5R*zze(;jJnkRCJ5|cGU;aAHS zXZfbCcOHeoMg8^|6hro$fkh{LcJlmeWmjnn9Qpl`#~$3bZ^Ik1omda0Q~=L>bm-^B z(?;Q$K5%qa5pKOurLDJKto#8GAMsgT{fv{WV|h@*an8g>MM;t&TLaT;F$JWV)!N!m z2g9u2z+W?Ix*@T)kfbqzqZar@q7x6BF~Aa`T?OMiUOc z7Si_!z@i%y!>%aoCl;x$i{oQ+-+zW$+6BvMDZ}DlTzZw=>&0~j#ruiNmDJ@gP6>t~ zGZ8?O{JAf+@OVQ^UdeZ_FF$t@g_w<(*G)uO2y|I%(+$43b=@f}GM$4oW7;>E?uW@- z8zkRr(V7WaQmu{sps#?!l#QOH{hrun`lfo=$R0hyh~Kd4d2)NbaXZhk#iK9r*6IN% zShd^hC$q~}g$KpH;=0M0B7ECklr9SI>0&-Dzic?IzkO+&HJn|&(%pbfEmn1puq}z~ z;e)(M>SvHv!7L+qjnJt+4?)y*1ixwC?i>g6F-JC82%!qFNNWjO7Z-SS~pOphA- zhW+XS`3Z@gG#SQmLQrkDIN5DH+ME&ZSyC@y={-*7zTb?jn|mpy);pmHJf z)6s@9Qzwx<%&=%-!Sgrw75AUL*1c~8{rsl!Xq{kqOfq3n?*y`Cj@;)r?-3J{SO3?} zoO-(k%kO_2^yJ;<6}v^U#qo4&VTA2HmbWU?$L+H0z0D0r475?9w&cFG<=D8j)RH~1 z(nCH;>bv@_yt#FDDC4}}Lub~!rsnke{Lb%xEmXS{%3i$9XT}v+sQX7@x{XW-Lg@k# zPfUKkF{}73VoXaO@1vMnas;^$`b`sZ6PGj9ZAF+VP#knJA1k=H`FdBQ42g~82rYzP zRX~1|IAbm+UQ8$MlMii*c1?Sk^O|sxV)`=fX$3LjHgv&V`=rdZ?3sxv!t~V9iP*l3 zH3j{{_1miCVyP*D`DrtZf4ER6nuID4yl#7R>QkDR8o?^>t=Z*wOonV~Q+qJB;Df*E na%K!r=m^CJi9(#0gZ2(Hi=DHipKxpf=yTlx%aWP?7X%p;RUnm5Q-+th@@B3Wmx~_9w&uclS^A2`fWu;W4006Sv zY_>Q8fQLgoAd16ZS7Jdj0ERoaZL!!Lervdmm%765l-gMPjmvuX7rRFBv)>ib*HM_K4XaWJ?b{E3tR>A9*nUY3bzk&T zi-VHji54GWL=cb*L{KyGdiZ*xwSf6+nBBh*LC?R$$|Ln7utw97J(yUp5`}tC2uKMn zppk&GUR1Kpnc$o<;fd_IZGdRqB@c8ZamOTqh5rl!{uGE+t^fo^y&7nK7f9E|ao)9s z?aIY?Uq@sBb?;2n{FUC0m{Ez*-5PdjY9m{;`3UMx#CFa-Dqvl5`nzwO1)5dE!>ID=b>MLLa2!JQj<#e3G! zcoXefi>FdAz!_4F_#3{s_^p6U60N?{l0%gQ_`7g^mJN}tiZH+;3~;VWB5#+26rj*Kgb+s^4jcXB*9M4qTdT}UpLy! zHa`)P+Pxvd5S@8HCi?9kv|r@zC+fzA{S-WP9+wBCTBS>yIgzx6?e0J1} zvRlUiBcQ6bGNHp~ zQQ=EDdV{GjbLGO4glOMewKdSu>R@EAH$QZWeb2w!O5eOlLI^n&^(gS zF)y5Gl3VhZG9wRIMJnq8fXN@X;@5sgZlO~R z2*~o>5j}on5Gi4Zvl1IKd?5RDjlrAS6Rb)J5Wa}-=A7Ns1k96eo(lom5;$F1N-K*{ zZRg#!f9&oC=ZJ~e9(f|Mw-8sj8BRdy1T;QLhzFsyy7Wi_D!y|w0w(Qc8jP~pR}n;~l&mi?Hjn=$F70S@Jv?9tSSB25EGlyvT0 zL3bY(T=G*N&>d%PiZy?Db0kBtsq59;;mF^wm^;gK0J!^faNWRKeBP%%tTcJeR#`xI zor$S(MN6I_|FU&K#Fk8LiGjC!&hy)lEQsBUcLNnyM2EL?IaGa{?jFVGBJOWrZ!esr{9$gFB0=Vbm4259~fSpOo=nMG8VGIG} zoG`s?**-^Ka9pnTwp&o`En)TPY-xZ#ZwTAJ6TELRHICSBcW3@QKLG%;mwR=kT~E9G zuqCh7ROBl_@8wK>hI>#4?`~;*S@nP7!^Md2cH2A?^bUWA_NV#FJczEeRunH|iSP&M zT!;ojIR0%(%!5WjMzk=_b%yy{t=uEz66i}e1oK!dt1?;%VM(bYHg8N&=^F4v_qZF{ zRnjlZHd&G%5HoNwu9!9v%YXzJUNx zM48toEaEt<)lFPQv_uy0GM-6xB^Qg58`6MB3i<#n5&^32tt zvVr1&A?Vm;8r9BzAb zGFIHHGdE-YMX&tnM&{)>IS?tq%NhRQM7tc}f-YG5opzf#7QaC-KUZ8xw0JVF|AGs5 zRxS=Jc*}{{LnnbOI{=z3yJ&4x3K1-bGm}m+07$DAzq>h9QQZJXHJcHmDWoU^bZH!O zQ~LKa1>%U41^`Q)X7eAJ*}(ahAWhE^lSz9R5HlbDRVNMSM8w%^w&rajeeubg zIVV38IV?Tj=QrR-*PA3>e-8vyhB}_JiuUJ@^H?O$v>gfw()>w#@3kt z(mV(qY0cHo;zS%L1sV-^d5{H%8|O}lTG8`F9+-*6@|Sl_?c|(f&luA16lLf}TwWkY zKm1GVLC9WT8VSg3d#}iP8#2)_T{BVppnWmGd73iJ6vn2q%dZBqDUaWFM^H0U5XLBj zS!i}@D#sDp^P5FaWy8DEW8Rhko89u(_r-`n{8$?p#Gx^ei4>b%L=pjg2Hi3xMXZ9} zVfhSs$q9pwF@ozFjTz06oRLa<+>Fo#@*Gr&$e#B*aw~d9SsnPNDpCOXPYD`uWWN9p z^9KODjd!GwK*1I$X6!;7x(1S`GAset2)e4c9T9wA0RV?cMCfjE2Qsj4r|1ZI{E%ht zzB`(e=kN0f-GymZJ}~vPj*4fwcuxF=ihm5{PTL})x?7<@Ol$s~JopwU88I<*NY8?! z=nDYD(g4X_s{jJkA?f#$2z{Bl8!A`(*`?K>Hp33$8h4v1_qb-~qgA65LlxKmKiYXz zUy1{_g8u=oYL(# zM+63t zoIJ}`O|7x$onmZ(mfHSCcsTM;{a+27naWzijGUf4sb*WYgnP)0eA$Wv=yO&T9)dl! zayxgvS4Is3P=vvY0M$Fv6rojes&1eGpK+Y~aDzE}EWu8QqhPnIJcYnn4>qf+-t8bTL2;eOstA7c1BgOBfZeRmx~aNzJaDMI&3 zNcMBB)a1={vqUP~8^D!P2UY4lD(Ks}s6w-l`A`T?=m%Y*$MHa)!2k3h{J(m*a{O&N z_Dbwc(qq*m8)*{Yo)ddRT_d8C1_!FpuGXB36uN-E2#c|kcVe2a$lwn`YxR%YLm^8* z3-5bZm^)`xt1IIGw_v^nOOH?jjDKoyRL$%&jc3*2o^zW{GxA}g2WbMrLY^+&4o3jD zJ=McEN{`(hHP#@>#EHrt;)-b*R2vfXQ|$cyOP90xP7oPDwbS*Vl})E^`bGsJrj)bA z;<_MuqwQ&8=wyXB`cNqbpyfBj80YLHo{7DMtWjk1LCSSVG4zWrklFhF8~UZUchCPk zgLFc%^TVq0l!y()z?l8=){EAGp;5Ky)>XOXBFmw_AH?ZylruORL0zs#2lRza9=uO? zPT5dGK^mJcs4s;!yjPk-syWky-i5+}EgJC02VbNBvA}*livcVrPeGN&MRwK2rj8#U z%fV5LA&{5$`8RD|7>K>laU7MTH!o*4jW`pPNe3p{Ql_mB;!zJx}m&rc252379 z!r_U#$5so?Hk@Hoo5O;4l<1Qz`jpY3@1r4&2vB&?my7K`B)?r}V1^vVd4gG_j32`9!uad~KfhI@`HrC1;@x`qNQD zl{L^}JSL(h1>RvNeL4qY_ADWlI(=I#tqK&E2obuOFP`CFA7OPG;+uaej7_(J!vW!+ zmKf$jurr>-y=6qX>Gm{Vn&CrTf zi3rDm2;9;vaV$Mc5NbbMZkduE3=`VXF@JnKYQD%%#K zMv@3u*3iumdc+C}0X!mt#oMle0$XD91KBB$U=r z?nKT#Ap!c}S#)?1+<|G~#ONR{^Ux@^e9Vcw4y?!OwhFHyEFDYwvgFEH_vUN)V3@Ny z1eE-&p*!5Z8Mpz;MJ@RjD;x@7>h+g%(j|&!=jMLtm(BcN2G2+` zpe)29PwTtdQTLk6bcaGWgMFAp9vHOSJ(TCiGUS-_{oXNK;$qR-}g0F7A&j5 z{RkI)zT;Be9$p{#bRC|%PI582=8)KOl|pA80hODz5<^v+kk?;K&_|9=VVgnUInTYI zm|>cf8J8aKe;eOZx}e4`u(986`;11?@2=2}}krH_tV zb~3Mrdip2ae5Cdlc$b68Etz60={i3oO|H<93G2+cN^#(z@j&s9F5TV3IU+qoKO@YS z0$hJ3(fgAJ*ZZLbOkc2YEKv>&>l0$0#&Pc5)7-8xDMSDM9M`=F6jbY?-Gj!D5*(@c zlymQ-!Imt=?W?9`=s&p|vAUKP;iXrOR6zRlLVWo$18{y04_JD3k{`(rqrWNuaSmjQ z6noQ;Oh9ADBoO+N-pVyyR0AYy7+uAYhoNf2Hic?tu9_qL*;r`i4uQg}x4sD-p zJXu>l^;!Qx`va~9mg*UEcs<-7SJaxbNCi;E4_`k<0@f93ivacD;cMe?{7y{~P`4bu zdTar(u2LfdXRFt%sRF0;B>Nu?@*3v$V}DGL9X#5Jb)v3@#nZtBRjW<_vY&w2&QJIx z9WRLhYN0out1YaymFB*m!xI<^LG*`a?-hV1oe0pxvgs*ym-em@2bk$Qz#JBw3p}-! zT5|VGnj*qDa2CePpf{R04gnHEZ=POvw-&elmjdBd$YTevPC7RDwea`R+Ul#9Cfp6u zjDsxjoaHq;-txEVn>cF$3tP;%BhI)IJD_+?kp+J8Vf40rsCDP$Z+^Sq9D3V_U{Ya+JX6`mL8P?-$J0m9Y-rD zW&D47SGxThaMgx#i(GD-T#IlK_r|L2vf9Off5Wxh^&IE*1I)Q!0~vvTvr^83C$a$T z|2ndH&ln)h@N?6jEy+7*4bZjoA96f5Mo!P&Q%r3t6AtGG3){-_-!Bp_I=>9mV-J4Q zHks(46u@~XX4a^~Z&`5yFm#?;0II4K^DzlL+(H6qm*cEc!XR+qiB%=aaExCmawd(} zD7nu0XCDH- zs`NhhsIyOnF`*>OiUk&EUSVkkfot6evZOoMC!9!o|N~I-}Po zmHjnDj`Y5z*Yja0JJs{?30juR|C7tuyTdO5DkqrzwQ6;{y)CIwHOXIpN)Dzf0+>7j z3JF3e!2KPjuyWKCU+Dp=ZSvG?+k0shkbKG(poc=9B<%2qStjhwz;B5wLZwsoS%5U7 z>WG(DVXP$ntQriqE0g8`nEL{fO`jq~;S8XL-9#z1GVlpuVWc>R1*?N}Z?pXs@CjA9 z)*P#tE5_!}+plO-BCq~`SV#!~zb8apnYnL|PKtqu1>=y5iQSJRG^CWl^vsM)>lGKz zzak|Ye{p)Cn$$=6BZ=H11CaIUm?~SX(o!6qc)bpALN|Wdte%J>|4OL2<|mFJD(+!D z@y-L!+DHPLHOqn40hlHJl^)#|K0ODm6PIK;q)0J119tAO7vp#`hnSF#BuqXxRIQ!lF`4t+|IXSwa~+0~p7ZkjQ~L zT3C`_snw5F+6RI0ty);6JtGsrmF`))+y5pt!Pvuz{+EYw zl!WqEQIajV0>$uQ381jJOyKune3_A`p4$0ahHh^@PrEWAodlCMu$cgMp08t8pLn?Z z1W18};(_(xjgc$*-L!&_~osbz6l-zn+A-sd;i@?h_4%W!C&@4a!41|?^^dTw|PvB-|fLvr7jlD zOZlnRcL6Sgzc(vUvf{4{7D`CzA~JY;aFTr(!_@X6J2xlh)v}=NlZllyZo--OvB3*A z%p$O{j72Pcdnjx@Ulf7Je77ws|Zgyi?wE?i76mWOWiY zi|<1Y>6aE^^uy{+;Fi)XKNogO$2;-_y+T^(P`qLq)SRl8F!nCd49|crY_272?RqIY zOk4(DUj`YfwiuZMm-3ZDXOLOl!iz<`?dY63CwlTo4K~UdC*s@}b-@pue9e*7r`k-5{vwZ&IR>x7x zaBo2yasWDywMUc`uK!MC$ufaNNtZ4iXk?S8qU;-XLHb2p1F#1GCodxwyEjc}Y`1v> zG={k-Sj$Iu?S!?f|1}ENJdSyDIwLn~WOMSjNyqK`8gWoT#XeC6@J^{bv|@m8$bOnZ>VE4s5jI@S&&e0pcrhF)dKf_?UgAL z`TS&69GhYWLBZx{T`qrB?WPqJXs>0|dHJ`bRY_F09Seo}5nRC!zVDy-j z;Z&SDhp@iYVF~QXwbgE9GK5!pz^!S8czgJT$@8TG33x06fUDP}T9taA3K}-Swt@y3 z2fyD{y-)ne+Qg4AjBx){binfl84-%DhsPFGEB&Rpy7M*iAoOP!&wOB33a_*dEd3(y z(mI;4F&&0MhT}af`DxPAf6=FvHV{?vv*(&f2U&*m@)|jRgG{4h1PWN!Aa^6YbKR?x zw*2VBgQ1!VPqIGLwEw}4^YTfsYzFHO3y`Xnzg2(|P8>bq%Dm;6{@k^uLR3Bs_1ulT zD11wXmO>Xas#VgG_S7h{CUCU^K);tSG>)&>3tOk)@TtCb(@oyg18~nB?oDkSm-k); z2|w6BCY`lvQU$an0*A6$=2*MwQd2LSB}A?Rz~S>5&)08{DQNzO>Vth4e9*R5LGvB# z0(35)7kYgcZO!XZCKPGsc}Q=OBmeFCxc&H};l`dpZ07GkQ5(o2S=bTTG`i7lVdj6@ zXoXm8e9GtV%Oat%^+Fh2AxIn7#zDGY%dyBKCzH-fnx1o?+X3Nhs?)4^qxr&j2Na#T zfF!7v1F6YE+R@senmM|O^SeSn4lk0wW(=J8wZz{V{MT?;N?@*966y_IrcfC;iZ_*hHA(or-~6tT3G zFtAbG56JZ<fp*ssMR%TO`+BVXF|Zv1*<&$f)*WOf57JUnJV`EAXVQC~+gc(~$#qJ{ZF)j&%h)E*aSOF1q4?IO-kC z91$InVmbOz+~+b6ZDDsUsbE&38LAfGvu7p#Hil7cVQf*H2cEGQLg#8BcE($YyLSwJ z@m8O&56>b$LxJq@1P*trfX3WEYwC;WJ%>7r_u%6Tw5FjRWD0*l8wz~~hb!*SO3W*U zig!M|eEja+g($KZW6sUd_69A>V96)u*@tjNbXBH2p+4Nd!7iMcBOm_=c14UgZQ38i zJUT7$Hv+|B8BD%sZc*~qlxP2$iRsPR@XE!xHn6q4W!V&V>$)1*@^9<{;E@!zvXYka z4Xu0!? zgsJ=M2SeDovk9>!*h}&KO=s&w0nF}uG>F%Z0(MQBwjZP8dz2( zRssp)5zY-1_^%(pMsK%CkQXDspBQ@9PXR z1)djOp6|XSOl+9OtIb;uxZgcc$DZ_K&gbrN%f(2=!bIIrVEnwe_`63;C2T87QIGqI z#d}WrZRN$jv|HK)PoLZcuTNCZ86aiq(B2j9nQ2AWvG0#bG(rh-U0Pdl8Hm4PG%Qhe z_=&)nK!m(GDD7ie%kY~?q*}19Z!mi#YQnt=q=RFme}WU zr?bRjt{+fiEx`c}=Ru(I;e1wy^&5GvJVJT9j=_*I_n_{`n>5w9p*?$i+h}CkNdt8m^uO8ICfF~5VB+9QDj zbW_!+zF-%(VVY8idfqxa9|-`9YOpaO0bu+`P^ekrCFI_nFSmIU>GL}n|gKW zh45$=fUl0J4L;(m_*U}?*hh!m=p_Q$TQ6$07^=hs>H%2frbW5 zC?3IX+GiD1`<8lNRnvV~V^hvmm(Ncg&go#jCZLjfaxsY%SOfKpcUREZMwiFyaO;n^ z&^SYCnt<-M2>Z6Y%oa+kR6sz$a5z7}T9|DO(#RGtFFaGhEGYoCuU2YZX-2?fN4`B2 z)dGr|r&Ebd9zvuV7ETTnn8F(*joqHSk-6gAzx=+}fU`GcUydcn0*BoiTEgsF89EGN zE1_KUn4=EkYG>e4>U9cWe0a#*kE1&%iN!7v^})1MnU1CQp*T9D_*d&`$P01TtbW_& zeXDGAW5yN{Vgokm0P2EEw7D9qQ62sQuy<~Z9W`vF-g&VJQ-D30q#sS}apsx`Od|uk z{#_nH6K_DO;|2q@nvRq>NRO-*M{_2Ez!gNm8Pn!J+6-9#w6=TQr2?7qG3=HBFYh+Y zWGQ()Pb@&nvp!Ez0}bA>Iucnu2xr@P%rc$ywg$x<@)xz&j%f1_r2~4lSLf$7tHnW~ znO8vuEVd>W60V;`z(bcw{X-LXgWyT@LKuN=Wo9fQfUgO$8{E6I0iA5W$>)AX0Rf0F z7Qf!k&&ueBcLiCS?Ke%8eZ6#OR2|;=vq*?t3C;7--?-(d0LV+>Uu$=b85rTfJ$XWa zuN1J^*O#l@<<|!<7A_%PAWDMu+9Qctv&u{0aj5@78NgT)XAUp1kuIbF`hrTc%S1pA zT_r9I_l~~(%v7UkM&^$4X3CT2s(ZnFM38A+clRCg_~3MALT2RUha4qEber-(EP<8S z^i;u2>1WW{gy-dU`Vp&tw#um5N=2(9E7R(hsR_t&#XVz8p2DWA!y^VDM zfris(q`4Q}6&s42dtBz4pUpht89p8fY3aS%V%U?k?aI%WBTY|D@Ok~hFg)FD=8(qH z(C7ZjX?Y^%ycY3FldlHznu{{cvALkQgv`-L15H}IAM1Q-+ZJ8G_ElPz_6bTnbNd2< zb^dA9`Z*XilKJ4MgOBFDq4F@A+|K4^`8D)X=8SWqKw+8EoHLHzmf|pFJ_lv#*fZWy z)wDDKXq7(w(DbDBZO6e-$awV4_%lX#{9*x4nfFG_zqm8kX=sDq*W$L|)C080j-U?v zYnM{n8m*su^d75vd~y0(k?-Q01%i6*$;6S;Pt}8)em}cQr=YB=n4`#J%-!Ws(<4Yg z`)7KLM~h%Xw7hfqD8DuANPq?y`V&@_`J_2;A^2#{ehSa_%AJpN7!v9QuS@Q-h9dPM zn61McqU{tNU$V z_4+{G=of#XxFMsDo)5?!Is1l+-T6%|d!pfnm=q5m&(NI7#vGnEj~A`3Jk}b^vLilJ zk$RCY=jZ7%Ekq4Kw#^jR`CXYMm+S-}uOp4^3swOu)B# z&nrs!m>LrUN#~AS1=0ygG3N^ccbsK|@`V?p>>(otB`YQ`R$EDsZaueQ@nGbuOQVJ| z5@Cr#{;*X?aNA{pZLy0W+}(qg;8i!#lw=C`)=ta9Vxp_~I+Hdm{dqc$U`ZGV? zQS$=gRftTykDK~_zq3rIarPiPvs&kS#*64@^U+5lJs!tAk;*-@)=+QzU=6t^IA@{a zN2$TpadXeGkCvP@287mfdy2Y*IXV8t>6b^|uwBNd!#bEP0>8zmIX*y@O)p zuI>w6O8R)=_v1GVH)wg$WpbT)2T09|q(3~D^>3dKzd|B9DUxsX_&LdAeu=YX%gjAa z-lwsdbFH7s*$R4Pa;Mr3oKw_mV}B$@>;h?pRD+{0A2fGNk3WuOH1*2(pT}$8e}3rT z>yPZr%LN=D=?@Pg6woWg5 z_~DJ}_pr>Whs+|bek2oCVMTR9TV}6N82h54x51oW9o ztf+zstFDecd_Oe}Z01RyM2Q^UDwg3!+^Zy6;q?eZz}NW>EsojqfLo1!-Vm ztx-m8;tta#*9x2ee1EZqo7moNy5{H1_C{pL=QQVhjS=r<%Lxk03ii|JjQAee#wpihY7#dFi{#g(GYm|zCt|k`yRu+O3y{?In_EWdttFmc(9Ic=x3@}d4 z>FoL~AGqqc#EZFcfn5(S-29v$JIjCpoPuUPu+6{doCN_7Sz^$ZR(bMs@toHc8=rjo z5_X&2Da%Q@R@fJK_|h#UzK%3Phs9bSEO?jU8t)17PglgyLaF(Yh9Z9MI*t zoA0-o^XfFo!AB1`oPo!s#rUW4M^Cj>MAIftSwRnpPNsmQM`NDB@;U{=tAf_h>Gh1Q zaAme)=h#cMwg~4lnyx>e=!^RkoW1~5LGyV!o8c0OePCY9tQJ4K5L#`^8Al^R53MMM z)+%1m{)`r^?=0Ct=hDl0s+v2jHK^F`8Uxh@O}nU^KGw9K!=(>eNjC4t4SH&Sot0m^ogB8 z%dy{;W8dtSMYk-Ng{$ywV(Q+k_nh^sUASI{i1Tq-s3?vadDOnhHMR1a+{ZomZr`{j55?nSZAZ0xgNXXr&NeQ99jH~r{% ztbQCVbPGV&=Oc4guUq!T4n_aD=e0_z$SOeoEW-NS^qhafErYp>&8%DAm1&VY1u-*^`=IWTz(O%cvF^S}*pE#3Oe;GpC O2ivUdwmh?Boc=$r-a)|t literal 0 HcmV?d00001 diff --git a/docs/android/assets/splash/splash_bg_full.png b/docs/android/assets/splash/splash_bg_full.png new file mode 100644 index 0000000000000000000000000000000000000000..90479761fee4b09002b67b0d53c1f5ab622a706d GIT binary patch literal 46649 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�RYC9Pt?* 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