Files
anroid-CheckShot/docs/superpowers/plans/2026-05-13-theme-mode-plan.md

520 lines
14 KiB
Markdown
Raw Normal View History

# 主题模式切换 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Add theme mode toggle (follow-system/light/dark) and fix dark mode font visibility
**Architecture:** Add ThemeMode enum + PreferencesManager storage, thread themeMode through InspectionCameraTheme, replace all hardcoded Color values with MaterialTheme.colorScheme.* across all screens
**Tech Stack:** Jetpack Compose, Material3, DataStore Preferences
---
### Task 1: Add ThemeMode enum
**Files:**
- Modify: `app/src/main/java/com/inspection/camera/data/models/WatermarkModels.kt`
- [ ] **Step 1: Add ThemeMode enum**
Add after the existing enums at end of file:
```kotlin
enum class ThemeMode {
FOLLOW_SYSTEM,
LIGHT,
DARK
}
```
- [ ] **Step 2: Verify compilation**
Run: `cd android-CheckShot && ./gradlew :app:compileDebugKotlin`
Expected: BUILD SUCCESSFUL
- [ ] **Step 3: Commit**
```bash
git add app/src/main/java/com/inspection/camera/data/models/WatermarkModels.kt
git commit -m "feat: add ThemeMode enum (follow-system/light/dark)"
```
---
### Task 2: Add themeMode to PreferencesManager
**Files:**
- Modify: `app/src/main/java/com/inspection/camera/data/PreferencesManager.kt`
- [ ] **Step 1: Add KEY_THEME_MODE + themeMode Flow + setter**
After `KEY_FILE_NAME_TEMPLATE` line, add:
```kotlin
private val KEY_THEME_MODE = stringPreferencesKey("theme_mode")
```
After `fileNameTemplate` Flow, add:
```kotlin
val themeMode: Flow<ThemeMode> = context.dataStore.data.map { prefs ->
val mode = prefs[KEY_THEME_MODE] ?: ThemeMode.FOLLOW_SYSTEM.name
try {
ThemeMode.valueOf(mode)
} catch (e: Exception) {
ThemeMode.FOLLOW_SYSTEM
}
}
```
After `setFileNameTemplate`, add:
```kotlin
suspend fun setThemeMode(mode: ThemeMode) {
context.dataStore.edit { prefs ->
prefs[KEY_THEME_MODE] = mode.name
}
}
```
Add import for ThemeMode above existing imports:
```kotlin
import com.inspection.camera.data.models.ThemeMode
```
- [ ] **Step 2: Verify compilation**
Run: `cd android-CheckShot && ./gradlew :app:compileDebugKotlin`
Expected: BUILD SUCCESSFUL
- [ ] **Step 3: Commit**
```bash
git add app/src/main/java/com/inspection/camera/data/PreferencesManager.kt
git commit -m "feat: add themeMode preference to DataStore"
```
---
### Task 3: Update InspectionCameraTheme to accept themeMode
**Files:**
- Modify: `app/src/main/java/com/inspection/camera/ui/theme/Theme.kt`
- [ ] **Step 1: Replace darkTheme param with themeMode**
Change the function signature from:
```kotlin
fun InspectionCameraTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
)
```
to:
```kotlin
fun InspectionCameraTheme(
themeMode: ThemeMode = ThemeMode.FOLLOW_SYSTEM,
content: @Composable () -> Unit
) {
val isDark = when (themeMode) {
ThemeMode.FOLLOW_SYSTEM -> isSystemInDarkTheme()
ThemeMode.LIGHT -> false
ThemeMode.DARK -> true
}
val colorScheme = if (isDark) DarkColorScheme else LightColorScheme
// ... rest stays the same
}
```
Also remove the old `darkTheme: Boolean = isSystemInDarkTheme()` parameter and the `val colorScheme = if (darkTheme) DarkColorScheme else LightColorScheme` line since it's now inside the function.
Add import:
```kotlin
import com.inspection.camera.data.models.ThemeMode
```
The final function should look like:
```kotlin
@Composable
fun InspectionCameraTheme(
themeMode: ThemeMode = ThemeMode.FOLLOW_SYSTEM,
content: @Composable () -> Unit
) {
val isDark = when (themeMode) {
ThemeMode.FOLLOW_SYSTEM -> isSystemInDarkTheme()
ThemeMode.LIGHT -> false
ThemeMode.DARK -> true
}
val colorScheme = if (isDark) DarkColorScheme else LightColorScheme
// ... rest unchanged
}
```
- [ ] **Step 2: Verify compilation**
Run: `cd android-CheckShot && ./gradlew :app:compileDebugKotlin`
Expected: BUILD SUCCESSFUL
- [ ] **Step 3: Commit**
```bash
git add app/src/main/java/com/inspection/camera/ui/theme/Theme.kt
git commit -m "refactor: replace darkTheme param with themeMode in InspectionCameraTheme"
```
---
### Task 4: Update MainActivity to pass themeMode
**Files:**
- Modify: `app/src/main/java/com/inspection/camera/ui/MainActivity.kt`
- [ ] **Step 1: Read themeMode from PreferencesManager and pass to theme**
Add `var themeMode` state variable and collect the Flow. Pass to `InspectionCameraTheme`:
```kotlin
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import com.inspection.camera.data.models.ThemeMode
class MainActivity : ComponentActivity() {
private lateinit var preferencesManager: PreferencesManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
preferencesManager = PreferencesManager(this)
setContent {
var themeMode by remember { mutableStateOf(ThemeMode.FOLLOW_SYSTEM) }
LaunchedEffect(Unit) {
preferencesManager.themeMode.collect { themeMode = it }
}
InspectionCameraTheme(themeMode = themeMode) {
MainApp(preferencesManager = preferencesManager)
}
}
}
}
```
Remove `import androidx.compose.foundation.isSystemInDarkTheme` if it was previously used only through `InspectionCameraTheme`'s default.
- [ ] **Step 2: Verify compilation**
Run: `cd android-CheckShot && ./gradlew :app:compileDebugKotlin`
Expected: BUILD SUCCESSFUL
- [ ] **Step 3: Commit**
```bash
git add app/src/main/java/com/inspection/camera/ui/MainActivity.kt
git commit -m "feat: read themeMode preference and pass to InspectionCameraTheme"
```
---
### Task 5: Add theme selector to SettingsScreen
**Files:**
- Modify: `app/src/main/java/com/inspection/camera/ui/settings/SettingsScreen.kt`
- [ ] **Step 1: Add themeMode state and collect from preferences**
Add state variable alongside existing ones:
```kotlin
var themeMode by remember { mutableStateOf(ThemeMode.FOLLOW_SYSTEM) }
```
Add collection logic:
```kotlin
scope.launch {
preferencesManager.themeMode.collect { themeMode = it }
}
```
- [ ] **Step 2: Add theme section UI before "通用设置" section**
Add before the "通用设置" section (before `Spacer(modifier = Modifier.height(16.dp))` that precedes `SettingsSection(title = "通用设置")`):
```kotlin
Spacer(modifier = Modifier.height(16.dp))
// 主题设置
SettingsSection(title = "主题设置") {
SettingsItem(title = "界面主题") {
listOf(
ThemeMode.FOLLOW_SYSTEM to "跟随系统",
ThemeMode.LIGHT to "浅色模式",
ThemeMode.DARK to "暗色模式"
).forEach { (mode, label) ->
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { scope.launch { preferencesManager.setThemeMode(mode) } }
.padding(vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(
selected = themeMode == mode,
onClick = { scope.launch { preferencesManager.setThemeMode(mode) } }
)
Spacer(modifier = Modifier.width(8.dp))
Text(label)
}
}
}
}
```
Replace hardcoded settings colors. Change `CardDefaults.cardColors(containerColor = Color.White)` (line 352):
```kotlin
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface)
```
Change section title `Primary` (line 358) to `MaterialTheme.colorScheme.primary`.
Note: TopAppBar colors, description text colors, etc. will be fixed in Task 7 (global pass).
Add import:
```kotlin
import com.inspection.camera.data.models.ThemeMode
import androidx.compose.material3.MaterialTheme
```
- [ ] **Step 3: Verify compilation**
Run: `cd android-CheckShot && ./gradlew :app:compileDebugKotlin`
Expected: BUILD SUCCESSFUL
- [ ] **Step 4: Commit**
```bash
git add app/src/main/java/com/inspection/camera/ui/settings/SettingsScreen.kt
git commit -m "feat: add theme selector UI to settings screen"
```
---
### Task 6: Replace hardcoded colors in GalleryScreen
**Files:**
- Modify: `app/src/main/java/com/inspection/camera/ui/gallery/GalleryScreen.kt`
- [ ] **Step 1: Replace color values**
Replace TopAppBar colors (lines 132-137):
```kotlin
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary,
navigationIconContentColor = MaterialTheme.colorScheme.onPrimary,
actionIconContentColor = MaterialTheme.colorScheme.onPrimary
)
```
Replace `Color.LightGray` placeholder background (line 171):
```kotlin
.background(MaterialTheme.colorScheme.surfaceVariant)
```
Replace `Color.Red` delete icon tint (line 239):
```kotlin
Icon(Icons.Default.Delete, contentDescription = "删除", tint = MaterialTheme.colorScheme.error)
```
Replace `Color.Red` delete button text (line 274):
```kotlin
Text("确定删除", color = MaterialTheme.colorScheme.error)
```
Replace `Color.Black.copy(alpha = 0.05f)` zoomable background (line 296):
```kotlin
.background(MaterialTheme.colorScheme.surfaceVariant)
```
Remove unused imports: `import com.inspection.camera.ui.theme.Primary`
- [ ] **Step 2: Verify compilation**
Run: `cd android-CheckShot && ./gradlew :app:compileDebugKotlin`
Expected: BUILD SUCCESSFUL
- [ ] **Step 3: Commit**
```bash
git add app/src/main/java/com/inspection/camera/ui/gallery/GalleryScreen.kt
git commit -m "fix: replace hardcoded colors with MaterialTheme.colorScheme in GalleryScreen"
```
---
### Task 7: Replace hardcoded colors in MergeScreen
**Files:**
- Modify: `app/src/main/java/com/inspection/camera/ui/merge/MergeScreen.kt`
- [ ] **Step 1: Replace color values**
TopAppBar colors (lines 294-298):
```kotlin
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary,
navigationIconContentColor = MaterialTheme.colorScheme.onPrimary
)
```
Auto-import text color (line 344):
```kotlin
color = MaterialTheme.colorScheme.primary
```
Quality/layout button backgrounds (lines 368, 636):
```kotlin
.background(if (imageQuality == quality) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surfaceVariant)
```
Quality button text (line 374):
```kotlin
color = if (imageQuality == quality) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface
```
Placeholder background (line 406):
```kotlin
.background(MaterialTheme.colorScheme.surfaceVariant)
```
Selection overlay (line 438):
```kotlin
.background(MaterialTheme.colorScheme.scrim.copy(alpha = 0.5f), CircleShape)
```
Check icon tint (lines 443, 649):
```kotlin
tint = MaterialTheme.colorScheme.onPrimary
```
Add icon tint (line 451):
```kotlin
tint = MaterialTheme.colorScheme.onSurfaceVariant
```
Layout option backgrounds (line 636):
```kotlin
.background(if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surfaceVariant)
```
Layout option text (line 643):
```kotlin
color = if (isSelected) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface
```
Remove unused import: `import com.inspection.camera.ui.theme.Primary`
- [ ] **Step 2: Verify compilation**
Run: `cd android-CheckShot && ./gradlew :app:compileDebugKotlin`
Expected: BUILD SUCCESSFUL
- [ ] **Step 3: Commit**
```bash
git add app/src/main/java/com/inspection/camera/ui/merge/MergeScreen.kt
git commit -m "fix: replace hardcoded colors with MaterialTheme.colorScheme in MergeScreen"
```
---
### Task 8: Replace hardcoded colors in SettingsScreen (remaining)
**Files:**
- Modify: `app/src/main/java/com/inspection/camera/ui/settings/SettingsScreen.kt`
- [ ] **Step 1: Replace remaining hardcoded colors**
Save button text (line 117):
```kotlin
Text("保存", color = MaterialTheme.colorScheme.onPrimary)
```
TopAppBar colors (lines 120-124):
```kotlin
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary,
navigationIconContentColor = MaterialTheme.colorScheme.onPrimary
)
```
Description text colors (lines 160, 274, 324):
```kotlin
color = MaterialTheme.colorScheme.onSurfaceVariant
```
```kotlin
color = MaterialTheme.colorScheme.onSurfaceVariant
```
```kotlin
color = MaterialTheme.colorScheme.onSurfaceVariant
```
Section title color (line 358) — already changed in Task 5 to `MaterialTheme.colorScheme.primary`.
- [ ] **Step 2: Verify compilation**
Run: `cd android-CheckShot && ./gradlew :app:compileDebugKotlin`
Expected: BUILD SUCCESSFUL
- [ ] **Step 3: Commit**
```bash
git add app/src/main/java/com/inspection/camera/ui/settings/SettingsScreen.kt
git commit -m "fix: replace hardcoded TopAppBar/card/description colors with MaterialTheme.colorScheme in SettingsScreen"
```
---
### Task 9: Verify CameraScreen overlay colors unchanged
**Files:**
- Inspect: `app/src/main/java/com/inspection/camera/ui/camera/CameraScreen.kt`
- [ ] **Step 1: Confirm camera overlay colors are preserved**
CameraScreen uses semi-transparent overlays over the live camera preview:
- `Color.Black.copy(alpha = 0.3f)` for top/bottom control bars
- `Color.White` for FAB and icons
- `Color.Black.copy(alpha = 0.6f)` for location card
- `Color.Black.copy(alpha = 0.9f)` for flash effect
These should remain as-is since they overlay live camera preview, not app background.
- [ ] **Step 2: Optional — replace non-overlay colors if any are missed**
The PermissionRequest composable uses no hardcoded colors that need changing (text with default style inherits from MaterialTheme).
- [ ] **Step 3: Commit**
```bash
git add app/src/main/java/com/inspection/camera/ui/camera/CameraScreen.kt
git commit -m "chore: confirm CameraScreen overlay colors are correct for dark mode"
```
---
### Verification: Full build
- [ ] **Step 1: Full build**
```bash
cd android-CheckShot && ./gradlew :app:assembleDebug
```
Expected: BUILD SUCCESSFUL
- [ ] **Step 2: Remove unused imports across all modified files**
Ensure no unused imports remain (e.g., `import com.inspection.camera.ui.theme.Primary` removed from GalleryScreen, MergeScreen).