14 KiB
主题模式切换 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:
enum class ThemeMode {
FOLLOW_SYSTEM,
LIGHT,
DARK
}
- Step 2: Verify compilation
Run: cd android-CheckShot && ./gradlew :app:compileDebugKotlin
Expected: BUILD SUCCESSFUL
- Step 3: Commit
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:
private val KEY_THEME_MODE = stringPreferencesKey("theme_mode")
After fileNameTemplate Flow, add:
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:
suspend fun setThemeMode(mode: ThemeMode) {
context.dataStore.edit { prefs ->
prefs[KEY_THEME_MODE] = mode.name
}
}
Add import for ThemeMode above existing imports:
import com.inspection.camera.data.models.ThemeMode
- Step 2: Verify compilation
Run: cd android-CheckShot && ./gradlew :app:compileDebugKotlin
Expected: BUILD SUCCESSFUL
- Step 3: Commit
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:
fun InspectionCameraTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
)
to:
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:
import com.inspection.camera.data.models.ThemeMode
The final function should look like:
@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
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:
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
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:
var themeMode by remember { mutableStateOf(ThemeMode.FOLLOW_SYSTEM) }
Add collection logic:
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 = "通用设置")):
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):
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:
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
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):
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):
.background(MaterialTheme.colorScheme.surfaceVariant)
Replace Color.Red delete icon tint (line 239):
Icon(Icons.Default.Delete, contentDescription = "删除", tint = MaterialTheme.colorScheme.error)
Replace Color.Red delete button text (line 274):
Text("确定删除", color = MaterialTheme.colorScheme.error)
Replace Color.Black.copy(alpha = 0.05f) zoomable background (line 296):
.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
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):
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary,
navigationIconContentColor = MaterialTheme.colorScheme.onPrimary
)
Auto-import text color (line 344):
color = MaterialTheme.colorScheme.primary
Quality/layout button backgrounds (lines 368, 636):
.background(if (imageQuality == quality) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surfaceVariant)
Quality button text (line 374):
color = if (imageQuality == quality) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface
Placeholder background (line 406):
.background(MaterialTheme.colorScheme.surfaceVariant)
Selection overlay (line 438):
.background(MaterialTheme.colorScheme.scrim.copy(alpha = 0.5f), CircleShape)
Check icon tint (lines 443, 649):
tint = MaterialTheme.colorScheme.onPrimary
Add icon tint (line 451):
tint = MaterialTheme.colorScheme.onSurfaceVariant
Layout option backgrounds (line 636):
.background(if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surfaceVariant)
Layout option text (line 643):
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
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):
Text("保存", color = MaterialTheme.colorScheme.onPrimary)
TopAppBar colors (lines 120-124):
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary,
navigationIconContentColor = MaterialTheme.colorScheme.onPrimary
)
Description text colors (lines 160, 274, 324):
color = MaterialTheme.colorScheme.onSurfaceVariant
color = MaterialTheme.colorScheme.onSurfaceVariant
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
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 barsColor.Whitefor FAB and iconsColor.Black.copy(alpha = 0.6f)for location cardColor.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
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
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).