465 lines
16 KiB
Markdown
465 lines
16 KiB
Markdown
|
|
# Android Large Typography Implementation Plan
|
|||
|
|
|
|||
|
|
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|||
|
|
|
|||
|
|
**Goal:** 在 `app-android` 中完成全局大字模式排版与触达重构,让大字模式下文本“稳、清晰、易读”,并保证聊天/阅读/设置等高频页面一致体验。
|
|||
|
|
|
|||
|
|
**Architecture:** 基于 `LifeechoTheme` 的双层 token(Typography + TouchTarget)注入,将 UI 从硬编码 `sp/dp` 迁移到语义化 token。先改主题与公共组件,再改聊天/阅读/设置高频模块,最后做全局扫尾与验收。
|
|||
|
|
|
|||
|
|
**Tech Stack:** Kotlin, Jetpack Compose Material3, Compose UI Test, JUnit4, Gradle
|
|||
|
|
|
|||
|
|
**Related Skills:** @superpowers:executing-plans, @superpowers:verification-before-completion
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Task 1: 建立双层令牌与主题切换入口
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Create: `app-android/app/src/main/java/com/huaga/life_echo/ui/theme/TypographyTokens.kt`
|
|||
|
|
- Create: `app-android/app/src/main/java/com/huaga/life_echo/ui/theme/TouchTargetTokens.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/theme/Theme.kt`
|
|||
|
|
- Test: `app-android/app/src/test/java/com/huaga/life_echo/ui/theme/TypographyTokensTest.kt`
|
|||
|
|
- Test: `app-android/app/src/test/java/com/huaga/life_echo/ui/theme/TouchTargetTokensTest.kt`
|
|||
|
|
|
|||
|
|
**Step 1: Write the failing test**
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
@Test
|
|||
|
|
fun largeTypography_bodyWeightAndLineHeightRatio_areAccessible() {
|
|||
|
|
val large = largeTypographyTokens()
|
|||
|
|
val body = large.bodyPrimary
|
|||
|
|
val ratio = body.lineHeight.value / body.fontSize.value
|
|||
|
|
|
|||
|
|
assertTrue(body.fontWeight.weight >= FontWeight.Medium.weight)
|
|||
|
|
assertTrue(ratio in 1.45f..1.65f)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
@Test
|
|||
|
|
fun largeTouchTarget_minimumHeights_areAtLeast52dp() {
|
|||
|
|
val large = largeTouchTargetTokens()
|
|||
|
|
assertTrue(large.buttonMinHeight.value >= 52f)
|
|||
|
|
assertTrue(large.listItemMinHeight.value >= 52f)
|
|||
|
|
assertTrue(large.iconTapMinSize.value >= 52f)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: Run test to verify it fails**
|
|||
|
|
|
|||
|
|
Run: `cd app-android && ./gradlew :app:testDebugUnitTest --tests "com.huaga.life_echo.ui.theme.*TokensTest" -i`
|
|||
|
|
Expected: FAIL(token API 尚不存在)
|
|||
|
|
|
|||
|
|
**Step 3: Write minimal implementation**
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
data class TextToken(
|
|||
|
|
val fontSize: TextUnit,
|
|||
|
|
val lineHeight: TextUnit,
|
|||
|
|
val fontWeight: FontWeight,
|
|||
|
|
val letterSpacing: TextUnit,
|
|||
|
|
val fontFamily: FontFamily = FontFamily.SansSerif,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
data class TypographyTokens(
|
|||
|
|
val headingPrimary: TextToken,
|
|||
|
|
val bodyPrimary: TextToken,
|
|||
|
|
val bodySecondary: TextToken,
|
|||
|
|
val caption: TextToken,
|
|||
|
|
val button: TextToken,
|
|||
|
|
val bubble: TextToken,
|
|||
|
|
val readingTitle: TextToken,
|
|||
|
|
val readingBody: TextToken,
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
data class TouchTargetTokens(
|
|||
|
|
val buttonMinHeight: Dp,
|
|||
|
|
val listItemMinHeight: Dp,
|
|||
|
|
val iconTapMinSize: Dp,
|
|||
|
|
val inputMinHeight: Dp,
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
@Composable
|
|||
|
|
fun rememberTypographyTokens(): TypographyTokens {
|
|||
|
|
val large = AppSettings.rememberLargeFontMode()
|
|||
|
|
return remember(large) { if (large) largeTypographyTokens() else normalTypographyTokens() }
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 4: Run test to verify it passes**
|
|||
|
|
|
|||
|
|
Run: `cd app-android && ./gradlew :app:testDebugUnitTest --tests "com.huaga.life_echo.ui.theme.*TokensTest" -i`
|
|||
|
|
Expected: PASS
|
|||
|
|
|
|||
|
|
**Step 5: Commit**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd app-android
|
|||
|
|
git add app/src/main/java/com/huaga/life_echo/ui/theme/Theme.kt \
|
|||
|
|
app/src/main/java/com/huaga/life_echo/ui/theme/TypographyTokens.kt \
|
|||
|
|
app/src/main/java/com/huaga/life_echo/ui/theme/TouchTargetTokens.kt \
|
|||
|
|
app/src/test/java/com/huaga/life_echo/ui/theme/TypographyTokensTest.kt \
|
|||
|
|
app/src/test/java/com/huaga/life_echo/ui/theme/TouchTargetTokensTest.kt
|
|||
|
|
git commit -m "feat(android): add typography and touch target token system"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Task 2: 提供统一文本/触达 helper,阻断页面硬编码继续扩散
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Create: `app-android/app/src/main/java/com/huaga/life_echo/ui/theme/TextTokenExtensions.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/theme/Dimensions.kt`
|
|||
|
|
- Test: `app-android/app/src/test/java/com/huaga/life_echo/ui/theme/TextTokenExtensionsTest.kt`
|
|||
|
|
|
|||
|
|
**Step 1: Write the failing test**
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
@Test
|
|||
|
|
fun toTextStyle_mapsTokenFieldsExactly() {
|
|||
|
|
val token = TextToken(
|
|||
|
|
fontSize = 18.sp,
|
|||
|
|
lineHeight = 28.sp,
|
|||
|
|
fontWeight = FontWeight.Medium,
|
|||
|
|
letterSpacing = 0.2.sp,
|
|||
|
|
fontFamily = FontFamily.SansSerif
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
val style = token.toTextStyle()
|
|||
|
|
assertEquals(18.sp, style.fontSize)
|
|||
|
|
assertEquals(28.sp, style.lineHeight)
|
|||
|
|
assertEquals(FontWeight.Medium, style.fontWeight)
|
|||
|
|
assertEquals(0.2.sp, style.letterSpacing)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: Run test to verify it fails**
|
|||
|
|
|
|||
|
|
Run: `cd app-android && ./gradlew :app:testDebugUnitTest --tests "com.huaga.life_echo.ui.theme.TextTokenExtensionsTest" -i`
|
|||
|
|
Expected: FAIL(`toTextStyle()` 不存在)
|
|||
|
|
|
|||
|
|
**Step 3: Write minimal implementation**
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
fun TextToken.toTextStyle(): TextStyle = TextStyle(
|
|||
|
|
fontSize = fontSize,
|
|||
|
|
lineHeight = lineHeight,
|
|||
|
|
fontWeight = fontWeight,
|
|||
|
|
letterSpacing = letterSpacing,
|
|||
|
|
fontFamily = fontFamily
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
并在 `Dimensions.kt` 中把原有 `AppTypographyData` 标记为过渡层,内部改为委托新 token(避免双源)。
|
|||
|
|
|
|||
|
|
**Step 4: Run test to verify it passes**
|
|||
|
|
|
|||
|
|
Run: `cd app-android && ./gradlew :app:testDebugUnitTest --tests "com.huaga.life_echo.ui.theme.TextTokenExtensionsTest" -i`
|
|||
|
|
Expected: PASS
|
|||
|
|
|
|||
|
|
**Step 5: Commit**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd app-android
|
|||
|
|
git add app/src/main/java/com/huaga/life_echo/ui/theme/TextTokenExtensions.kt \
|
|||
|
|
app/src/main/java/com/huaga/life_echo/ui/theme/Dimensions.kt \
|
|||
|
|
app/src/test/java/com/huaga/life_echo/ui/theme/TextTokenExtensionsTest.kt
|
|||
|
|
git commit -m "refactor(android): add text token style helpers"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Task 3: 改造公共组件(设置页基石)
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/components/common/SettingItem.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/components/common/SectionCard.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/components/common/AppScaffold.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/components/common/MarkdownText.kt`
|
|||
|
|
- Test: `app-android/app/src/androidTest/java/com/huaga/life_echo/ui/components/common/SettingItemLargeModeTest.kt`
|
|||
|
|
|
|||
|
|
**Step 1: Write the failing test**
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
@Test
|
|||
|
|
fun settingItem_largeMode_hasMinTouchHeightAndReadableTypography() {
|
|||
|
|
composeRule.setContent {
|
|||
|
|
AppSettings.largeFontMode = true
|
|||
|
|
LifeechoTheme {
|
|||
|
|
SettingItem(icon = AppIcons.FormatSize, label = "大字模式", type = SettingItemType.TOGGLE, value = true)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
composeRule.onNodeWithText("大字模式").assertExists()
|
|||
|
|
composeRule.onNodeWithText("大字模式").assertIsDisplayed()
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: Run test to verify it fails**
|
|||
|
|
|
|||
|
|
Run:
|
|||
|
|
`cd app-android && ./gradlew :app:connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.huaga.life_echo.ui.components.common.SettingItemLargeModeTest`
|
|||
|
|
Expected: FAIL(触达最小高度/排版尚未统一)
|
|||
|
|
|
|||
|
|
**Step 3: Write minimal implementation**
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
val typography = LocalTypographyTokens.current
|
|||
|
|
val touch = LocalTouchTargetTokens.current
|
|||
|
|
|
|||
|
|
Row(
|
|||
|
|
modifier = Modifier
|
|||
|
|
.fillMaxWidth()
|
|||
|
|
.heightIn(min = touch.listItemMinHeight)
|
|||
|
|
.clickable(...)
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`SectionCard`/`AppScaffold` 的标题与间距统一改为 token;`MarkdownText` 的 paragraph/quote/code 同步走 token(阅读页会复用)。
|
|||
|
|
|
|||
|
|
**Step 4: Run test to verify it passes**
|
|||
|
|
|
|||
|
|
Run: same command as Step 2
|
|||
|
|
Expected: PASS
|
|||
|
|
|
|||
|
|
**Step 5: Commit**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd app-android
|
|||
|
|
git add app/src/main/java/com/huaga/life_echo/ui/components/common/SettingItem.kt \
|
|||
|
|
app/src/main/java/com/huaga/life_echo/ui/components/common/SectionCard.kt \
|
|||
|
|
app/src/main/java/com/huaga/life_echo/ui/components/common/AppScaffold.kt \
|
|||
|
|
app/src/main/java/com/huaga/life_echo/ui/components/common/MarkdownText.kt \
|
|||
|
|
app/src/androidTest/java/com/huaga/life_echo/ui/components/common/SettingItemLargeModeTest.kt
|
|||
|
|
git commit -m "refactor(android): unify common component typography and touch targets"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Task 4: 改造聊天组件(气泡 + 输入 + 语音)
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/MessageBubble.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/ChatInputField.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/VoiceRecordButton.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/components/chat/MessageList.kt`
|
|||
|
|
- Test: `app-android/app/src/androidTest/java/com/huaga/life_echo/ui/components/chat/LargeModeChatTypographyTest.kt`
|
|||
|
|
|
|||
|
|
**Step 1: Write the failing test**
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
@Test
|
|||
|
|
fun chatInput_largeMode_respectsMinHeightAndReadableText() {
|
|||
|
|
composeRule.setContent {
|
|||
|
|
AppSettings.largeFontMode = true
|
|||
|
|
LifeechoTheme {
|
|||
|
|
ChatInputField(value = "", onValueChange = {}, onSend = {})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
composeRule.onNodeWithText("输入消息...").assertExists()
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: Run test to verify it fails**
|
|||
|
|
|
|||
|
|
Run:
|
|||
|
|
`cd app-android && ./gradlew :app:connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.huaga.life_echo.ui.components.chat.LargeModeChatTypographyTest`
|
|||
|
|
Expected: FAIL(输入框/语音按钮仍有硬编码高度与字体)
|
|||
|
|
|
|||
|
|
**Step 3: Write minimal implementation**
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
val typography = LocalTypographyTokens.current
|
|||
|
|
val touch = LocalTouchTargetTokens.current
|
|||
|
|
|
|||
|
|
OutlinedTextField(
|
|||
|
|
textStyle = typography.bodyPrimary.toTextStyle(),
|
|||
|
|
modifier = Modifier.heightIn(min = touch.inputMinHeight)
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
并将聊天气泡正文、流式文本、时间分隔、语音按钮文案全部迁移到 token。
|
|||
|
|
|
|||
|
|
**Step 4: Run test to verify it passes**
|
|||
|
|
|
|||
|
|
Run: same command as Step 2
|
|||
|
|
Expected: PASS
|
|||
|
|
|
|||
|
|
**Step 5: Commit**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd app-android
|
|||
|
|
git add app/src/main/java/com/huaga/life_echo/ui/components/chat/MessageBubble.kt \
|
|||
|
|
app/src/main/java/com/huaga/life_echo/ui/components/chat/ChatInputField.kt \
|
|||
|
|
app/src/main/java/com/huaga/life_echo/ui/components/chat/VoiceRecordButton.kt \
|
|||
|
|
app/src/main/java/com/huaga/life_echo/ui/components/chat/MessageList.kt \
|
|||
|
|
app/src/androidTest/java/com/huaga/life_echo/ui/components/chat/LargeModeChatTypographyTest.kt
|
|||
|
|
git commit -m "refactor(android): migrate chat typography and touch areas to tokens"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Task 5: 改造阅读组件(章节正文/标题/目录)
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterReadingView.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/FullTextReadingView.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterCard.kt`
|
|||
|
|
- Test: `app-android/app/src/androidTest/java/com/huaga/life_echo/ui/components/memoir/LargeModeReadingTypographyTest.kt`
|
|||
|
|
|
|||
|
|
**Step 1: Write the failing test**
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
@Test
|
|||
|
|
fun readingView_largeMode_usesReadableHeadingAndBody() {
|
|||
|
|
composeRule.setContent {
|
|||
|
|
AppSettings.largeFontMode = true
|
|||
|
|
LifeechoTheme {
|
|||
|
|
ChapterReadingView(chapter = sampleChapter())
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
composeRule.onNodeWithText("第1章").assertExists()
|
|||
|
|
composeRule.onNodeWithText(sampleChapter().title).assertExists()
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: Run test to verify it fails**
|
|||
|
|
|
|||
|
|
Run:
|
|||
|
|
`cd app-android && ./gradlew :app:connectedDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.huaga.life_echo.ui.components.memoir.LargeModeReadingTypographyTest`
|
|||
|
|
Expected: FAIL(阅读页仍存在硬编码 `sp` 与固定行高)
|
|||
|
|
|
|||
|
|
**Step 3: Write minimal implementation**
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
Text(
|
|||
|
|
text = chapter.title,
|
|||
|
|
style = LocalTypographyTokens.current.readingTitle.toTextStyle()
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
MarkdownText(
|
|||
|
|
content = processedContent,
|
|||
|
|
fontSize = LocalTypographyTokens.current.readingBody.fontSize.value.toInt(),
|
|||
|
|
lineHeight = LocalTypographyTokens.current.readingBody.lineHeight.value.toInt()
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
并将目录卡片/章号/提示文案统一迁移到 token。
|
|||
|
|
|
|||
|
|
**Step 4: Run test to verify it passes**
|
|||
|
|
|
|||
|
|
Run: same command as Step 2
|
|||
|
|
Expected: PASS
|
|||
|
|
|
|||
|
|
**Step 5: Commit**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd app-android
|
|||
|
|
git add app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterReadingView.kt \
|
|||
|
|
app/src/main/java/com/huaga/life_echo/ui/components/memoir/FullTextReadingView.kt \
|
|||
|
|
app/src/main/java/com/huaga/life_echo/ui/components/memoir/ChapterCard.kt \
|
|||
|
|
app/src/androidTest/java/com/huaga/life_echo/ui/components/memoir/LargeModeReadingTypographyTest.kt
|
|||
|
|
git commit -m "refactor(android): migrate memoir reading typography to tokens"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Task 6: 改造高频页面与全局扫尾(screen 层)
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/screens/ProfileScreen.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/screens/CreateMemoryScreen.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/screens/MyMemoirScreen.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/screens/ConversationListScreen.kt`
|
|||
|
|
- Modify: `app-android/app/src/main/java/com/huaga/life_echo/ui/screens/*.kt`(其余硬编码清理)
|
|||
|
|
- Test: `app-android/app/src/test/java/com/huaga/life_echo/ui/theme/HardcodedTypographyGuardTest.kt`
|
|||
|
|
|
|||
|
|
**Step 1: Write the failing test**
|
|||
|
|
|
|||
|
|
```kotlin
|
|||
|
|
@Test
|
|||
|
|
fun uiDirectory_shouldNotIntroduceNewHardcodedSpValues() {
|
|||
|
|
val offenders = scanUiFilesForPattern("""\b\d+(\.\d+)?\.sp\b""")
|
|||
|
|
.filterNot { allowedLegacyPattern(it) }
|
|||
|
|
assertTrue("Found hardcoded sp: $offenders", offenders.isEmpty())
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: Run test to verify it fails**
|
|||
|
|
|
|||
|
|
Run: `cd app-android && ./gradlew :app:testDebugUnitTest --tests "com.huaga.life_echo.ui.theme.HardcodedTypographyGuardTest" -i`
|
|||
|
|
Expected: FAIL(现有硬编码命中)
|
|||
|
|
|
|||
|
|
**Step 3: Write minimal implementation**
|
|||
|
|
|
|||
|
|
- 优先处理高频页面(聊天、阅读、设置)
|
|||
|
|
- 然后按文件批次替换其余 screen 层硬编码
|
|||
|
|
- 必要保留项加白名单注释并记录原因
|
|||
|
|
|
|||
|
|
**Step 4: Run test to verify it passes**
|
|||
|
|
|
|||
|
|
Run: same command as Step 2
|
|||
|
|
Expected: PASS(或仅剩明确白名单)
|
|||
|
|
|
|||
|
|
**Step 5: Commit**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd app-android
|
|||
|
|
git add app/src/main/java/com/huaga/life_echo/ui/screens \
|
|||
|
|
app/src/test/java/com/huaga/life_echo/ui/theme/HardcodedTypographyGuardTest.kt
|
|||
|
|
git commit -m "refactor(android): migrate screens to typography and touch tokens"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Task 7: 完整验证与文档更新
|
|||
|
|
|
|||
|
|
**Files:**
|
|||
|
|
- Modify: `app-android/README.md`
|
|||
|
|
- Modify: `docs/plans/2026-03-06-android-large-typography-design.md`(补实现状态)
|
|||
|
|
- Create: `docs/plans/2026-03-06-android-large-typography-test-report.md`
|
|||
|
|
|
|||
|
|
**Step 1: Write the failing verification checklist**
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
- [ ] 聊天页大字模式无气泡截断
|
|||
|
|
- [ ] 阅读页正文行高稳定
|
|||
|
|
- [ ] 设置页列表项可触达 >= 52dp
|
|||
|
|
- [ ] 3 分钟任务可完成
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: Run full test suites**
|
|||
|
|
|
|||
|
|
Run:
|
|||
|
|
- `cd app-android && ./gradlew :app:testDebugUnitTest`
|
|||
|
|
- `cd app-android && ./gradlew :app:connectedDebugAndroidTest`
|
|||
|
|
|
|||
|
|
Expected:
|
|||
|
|
- Unit tests: BUILD SUCCESSFUL
|
|||
|
|
- Android tests: all passed
|
|||
|
|
|
|||
|
|
**Step 3: Run manual DoD scenario**
|
|||
|
|
|
|||
|
|
Run 手工流程并记录:
|
|||
|
|
- 打开大字模式
|
|||
|
|
- 阅读章节
|
|||
|
|
- 返回目录
|
|||
|
|
- 发送消息
|
|||
|
|
- 记录耗时和阅读反馈
|
|||
|
|
|
|||
|
|
**Step 4: Update docs with evidence**
|
|||
|
|
|
|||
|
|
- 在测试报告中写入命令、结果、设备、截图路径、失败重试记录(如有)。
|
|||
|
|
|
|||
|
|
**Step 5: Commit**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add app-android/README.md \
|
|||
|
|
docs/plans/2026-03-06-android-large-typography-design.md \
|
|||
|
|
docs/plans/2026-03-06-android-large-typography-test-report.md
|
|||
|
|
git commit -m "docs(android): add large typography migration verification report"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Execution Notes
|
|||
|
|
|
|||
|
|
- 每个 Task 完成后先做局部 code review,再进入下一 Task。
|
|||
|
|
- 严格保持“测试先行(红)-> 最小实现(绿)-> 重构(保持绿)”。
|
|||
|
|
- 若出现 UI 回归,优先回滚当前 Task 的改动,不跨 Task 修补。
|
|||
|
|
- 完成前必须执行 @superpowers:verification-before-completion。
|