Skip to content

Commit 15df32c

Browse files
authored
Dark Theme background color (#151)
1 parent de60f47 commit 15df32c

File tree

20 files changed

+220
-53
lines changed

20 files changed

+220
-53
lines changed

app/build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ android {
5454

5555
flavorDimensions = ["type"]
5656
productFlavors {
57+
dev {
58+
dimension "type"
59+
applicationIdSuffix = ".dev"
60+
resValue "string", "app_name", "SDAI Dev"
61+
buildConfigField "String", "BUILD_FLAVOR_TYPE", "\"FOSS\""
62+
}
5763
foss {
5864
dimension "type"
5965
applicationIdSuffix = ".foss"

data/src/main/java/com/shifthackz/aisdv1/data/preference/PreferenceManagerImpl.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.content.SharedPreferences
44
import com.shifthackz.aisdv1.core.common.extensions.fixUrlSlashes
55
import com.shifthackz.aisdv1.core.common.extensions.shouldUseNewMediaStore
66
import com.shifthackz.aisdv1.domain.entity.ColorToken
7+
import com.shifthackz.aisdv1.domain.entity.DarkThemeToken
78
import com.shifthackz.aisdv1.domain.entity.HuggingFaceModel
89
import com.shifthackz.aisdv1.domain.entity.ServerSource
910
import com.shifthackz.aisdv1.domain.entity.Settings
@@ -150,13 +151,21 @@ class PreferenceManagerImpl(
150151
.putBoolean(KEY_DESIGN_DARK_THEME, value)
151152
.apply()
152153
.also { onPreferencesChanged() }
154+
153155
override var designColorToken: String
154156
get() = preferences.getString(KEY_DESIGN_COLOR_TOKEN, "${ColorToken.MAUVE}") ?: "${ColorToken.MAUVE}"
155157
set(value) = preferences.edit()
156158
.putString(KEY_DESIGN_COLOR_TOKEN, value)
157159
.apply()
158160
.also { onPreferencesChanged() }
159161

162+
override var designDarkThemeToken: String
163+
get() = preferences.getString(KEY_DESIGN_DARK_TOKEN, "${DarkThemeToken.FRAPPE}") ?: "${DarkThemeToken.FRAPPE}"
164+
set(value) = preferences.edit()
165+
.putString(KEY_DESIGN_DARK_TOKEN, value)
166+
.apply()
167+
.also { onPreferencesChanged() }
168+
160169
override fun observe(): Flowable<Settings> = preferencesChangedSubject
161170
.toFlowable(BackpressureStrategy.LATEST)
162171
.map {
@@ -175,6 +184,7 @@ class PreferenceManagerImpl(
175184
designUseSystemDarkTheme = designUseSystemDarkTheme,
176185
designDarkTheme = designDarkTheme,
177186
designColorToken = designColorToken,
187+
designDarkThemeToken = designDarkThemeToken,
178188
)
179189
}
180190

@@ -199,6 +209,7 @@ class PreferenceManagerImpl(
199209
private const val KEY_DESIGN_SYSTEM_DARK_THEME = "key_design_system_dark_theme"
200210
private const val KEY_DESIGN_DARK_THEME = "key_design_dark_theme"
201211
private const val KEY_DESIGN_COLOR_TOKEN = "key_design_color_token_theme"
212+
private const val KEY_DESIGN_DARK_TOKEN = "key_design_dark_color_token_theme"
202213
private const val KEY_FORCE_SETUP_AFTER_UPDATE = "force_upd_setup_v0.x.x-v0.5.8"
203214
}
204215
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.shifthackz.aisdv1.domain.entity
2+
3+
enum class DarkThemeToken {
4+
FRAPPE, MACCHIATO, MOCHA;
5+
6+
companion object {
7+
fun parse(value: String) = entries.find { "$it" == value } ?: FRAPPE
8+
}
9+
}

domain/src/main/java/com/shifthackz/aisdv1/domain/entity/Settings.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ data class Settings(
1515
val designUseSystemDarkTheme: Boolean,
1616
val designDarkTheme: Boolean,
1717
val designColorToken: String,
18+
val designDarkThemeToken: String,
1819
)

domain/src/main/java/com/shifthackz/aisdv1/domain/preference/PreferenceManager.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ interface PreferenceManager {
2424
var designUseSystemDarkTheme: Boolean
2525
var designDarkTheme: Boolean
2626
var designColorToken: String
27+
var designDarkThemeToken: String
2728

2829
fun observe(): Flowable<Settings>
2930
}

presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/settings/SettingsIntent.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.shifthackz.aisdv1.presentation.screen.settings
22

33
import com.shifthackz.aisdv1.core.common.links.LinksProvider
44
import com.shifthackz.aisdv1.domain.entity.ColorToken
5+
import com.shifthackz.aisdv1.domain.entity.DarkThemeToken
56
import com.shifthackz.android.core.mvi.MviIntent
67
import org.koin.core.component.KoinComponent
78
import org.koin.core.component.inject
@@ -79,6 +80,8 @@ sealed interface SettingsIntent : MviIntent {
7980

8081
data class NewColorToken(val token: ColorToken) : SettingsIntent
8182

83+
data class NewDarkThemeToken(val token: DarkThemeToken) : SettingsIntent
84+
8285
data object StoragePermissionGranted : SettingsIntent
8386

8487
data object DismissDialog : SettingsIntent

presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/settings/SettingsScreen.kt

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import androidx.compose.material.icons.filled.DarkMode
2828
import androidx.compose.material.icons.filled.DeleteForever
2929
import androidx.compose.material.icons.filled.DynamicForm
3030
import androidx.compose.material.icons.filled.Folder
31+
import androidx.compose.material.icons.filled.FormatColorFill
3132
import androidx.compose.material.icons.filled.Gavel
3233
import androidx.compose.material.icons.filled.InvertColors
3334
import androidx.compose.material.icons.filled.MonetizationOn
@@ -64,6 +65,7 @@ import com.shifthackz.aisdv1.presentation.theme.isSdAppInDarkTheme
6465
import com.shifthackz.aisdv1.presentation.utils.PermissionUtil
6566
import com.shifthackz.aisdv1.presentation.utils.ReportProblemEmailComposer
6667
import com.shifthackz.aisdv1.presentation.widget.color.AccentColorSelector
68+
import com.shifthackz.aisdv1.presentation.widget.color.DarkThemeColorSelector
6769
import com.shifthackz.aisdv1.presentation.widget.item.SettingsHeader
6870
import com.shifthackz.aisdv1.presentation.widget.item.SettingsItem
6971
import com.shifthackz.aisdv1.presentation.widget.item.SettingsItemContent
@@ -144,11 +146,17 @@ private fun ContentSettingsState(
144146
state: SettingsState,
145147
processIntent: (SettingsIntent) -> Unit = {},
146148
) {
149+
val isDark = isSdAppInDarkTheme()
150+
val palette = colorTokenPalette(
151+
isDark = isDark,
152+
darkThemeToken = state.darkThemeToken,
153+
)
147154
val systemUiController = rememberSystemUiController()
148155
val navBarColor = MaterialTheme.colorScheme.surface
149156
LaunchedEffect(
150-
state.useSystemDarkTheme,
157+
isDark,
151158
state.darkTheme,
159+
state.darkThemeToken,
152160
) {
153161
systemUiController.setNavigationBarColor(navBarColor)
154162
}
@@ -389,9 +397,31 @@ private fun ContentSettingsState(
389397
},
390398
)
391399
}
400+
AnimatedVisibility(visible = !state.loading && isDark) {
401+
Column(
402+
modifier = itemModifier
403+
.clip(RoundedCornerShape(16.dp))
404+
.background(MaterialTheme.colorScheme.surfaceTint.copy(alpha = 0.8f))
405+
.defaultMinSize(minHeight = 50.dp),
406+
) {
407+
Spacer(modifier = Modifier.height(16.dp))
408+
SettingsItemContent(
409+
text = R.string.settings_item_lf_dark_theme_color.asUiText(),
410+
icon = Icons.Default.FormatColorFill,
411+
)
412+
Spacer(modifier = Modifier.height(16.dp))
413+
DarkThemeColorSelector(
414+
modifier = Modifier.padding(horizontal = 10.dp),
415+
selectedToken = state.darkThemeToken,
416+
colorToken = state.colorToken,
417+
onSelected = { _, token ->
418+
processIntent(SettingsIntent.NewDarkThemeToken(token))
419+
}
420+
)
421+
Spacer(modifier = Modifier.height(14.dp))
422+
}
423+
}
392424
AnimatedVisibility(visible = !state.loading) {
393-
val isDark = isSdAppInDarkTheme()
394-
val palette = colorTokenPalette(isDark = isDark)
395425
Column(
396426
modifier = itemModifier
397427
.clip(RoundedCornerShape(16.dp))

presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/settings/SettingsState.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.shifthackz.aisdv1.presentation.screen.settings
22

33
import androidx.compose.runtime.Immutable
44
import com.shifthackz.aisdv1.domain.entity.ColorToken
5+
import com.shifthackz.aisdv1.domain.entity.DarkThemeToken
56
import com.shifthackz.aisdv1.domain.entity.ServerSource
67
import com.shifthackz.aisdv1.presentation.model.Modal
78
import com.shifthackz.android.core.mvi.MviState
@@ -23,6 +24,7 @@ data class SettingsState(
2324
val useSystemDarkTheme: Boolean = false,
2425
val darkTheme: Boolean = false,
2526
val colorToken: ColorToken = ColorToken.MAUVE,
27+
val darkThemeToken: DarkThemeToken = DarkThemeToken.FRAPPE,
2628
val appVersion: String = "",
2729
val showLocalUseNNAPI: Boolean = false,
2830
val showSdModelSelector: Boolean = false,

presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/settings/SettingsViewModel.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import com.shifthackz.aisdv1.core.common.schedulers.SchedulersProvider
88
import com.shifthackz.aisdv1.core.common.schedulers.subscribeOnMainThread
99
import com.shifthackz.aisdv1.core.viewmodel.MviRxViewModel
1010
import com.shifthackz.aisdv1.domain.entity.ColorToken
11+
import com.shifthackz.aisdv1.domain.entity.DarkThemeToken
1112
import com.shifthackz.aisdv1.domain.entity.ServerSource
1213
import com.shifthackz.aisdv1.domain.preference.PreferenceManager
1314
import com.shifthackz.aisdv1.domain.usecase.caching.ClearAppCacheUseCase
@@ -62,6 +63,7 @@ class SettingsViewModel(
6263
useSystemDarkTheme = settings.designUseSystemDarkTheme,
6364
darkTheme = settings.designDarkTheme,
6465
colorToken = ColorToken.parse(settings.designColorToken),
66+
darkThemeToken = DarkThemeToken.parse(settings.designDarkThemeToken),
6567
appVersion = version,
6668
showLocalUseNNAPI = settings.source == ServerSource.LOCAL,
6769
showSdModelSelector = settings.source == ServerSource.AUTOMATIC1111,
@@ -148,6 +150,10 @@ class SettingsViewModel(
148150
preferenceManager.designColorToken = "${intent.token}"
149151
}
150152

153+
is SettingsIntent.NewDarkThemeToken -> {
154+
preferenceManager.designDarkThemeToken = "${intent.token}"
155+
}
156+
151157
SettingsIntent.Action.PickLanguage -> updateState {
152158
it.copy(screenModal = Modal.Language)
153159
}

presentation/src/main/java/com/shifthackz/aisdv1/presentation/theme/ColorTheme.kt

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import androidx.compose.foundation.isSystemInDarkTheme
44
import androidx.compose.runtime.Composable
55
import androidx.compose.ui.graphics.Color
66
import com.shifthackz.aisdv1.domain.entity.ColorToken
7+
import com.shifthackz.aisdv1.domain.entity.DarkThemeToken
78
import com.shifthackz.aisdv1.domain.preference.PreferenceManager
89
import com.shifthackz.catppuccin.compose.CatppuccinMaterial
910
import com.shifthackz.catppuccin.palette.Catppuccin
@@ -31,14 +32,27 @@ fun isSdAppInDarkTheme(): Boolean {
3132
@Composable
3233
fun colorTokenPalette(
3334
token: ColorToken = ColorToken.MAUVE,
35+
darkThemeToken: DarkThemeToken = DarkThemeToken.FRAPPE,
3436
isDark: Boolean,
3537
): CatppuccinPalette {
3638
return if (isDark) {
37-
CatppuccinMaterial.Frappe(
38-
primary = token.toColor(Catppuccin.Frappe),
39-
secondary = token.toColor(Catppuccin.Frappe).copy(alpha = 0.5f),
40-
tertiary = token.toColor(Catppuccin.Frappe).copy(alpha = 0.5f),
41-
)
39+
when (darkThemeToken) {
40+
DarkThemeToken.FRAPPE -> CatppuccinMaterial.Frappe(
41+
primary = token.toColor(Catppuccin.Frappe),
42+
secondary = token.toColor(Catppuccin.Frappe).copy(alpha = 0.5f),
43+
tertiary = token.toColor(Catppuccin.Frappe).copy(alpha = 0.5f),
44+
)
45+
DarkThemeToken.MACCHIATO -> CatppuccinMaterial.Macchiato(
46+
primary = token.toColor(Catppuccin.Macchiato),
47+
secondary = token.toColor(Catppuccin.Macchiato).copy(alpha = 0.5f),
48+
tertiary = token.toColor(Catppuccin.Macchiato).copy(alpha = 0.5f),
49+
)
50+
DarkThemeToken.MOCHA -> CatppuccinMaterial.Mocha(
51+
primary = token.toColor(Catppuccin.Mocha),
52+
secondary = token.toColor(Catppuccin.Mocha).copy(alpha = 0.5f),
53+
tertiary = token.toColor(Catppuccin.Mocha).copy(alpha = 0.5f),
54+
)
55+
}
4256
} else {
4357
CatppuccinMaterial.Latte(
4458
primary = token.toColor(Catppuccin.Latte),

0 commit comments

Comments
 (0)