Skip to content

Commit

Permalink
Merge pull request feelfreelinux#163 from otwarty-wykop-mobilny/theme…
Browse files Browse the repository at this point in the history
…_updates
  • Loading branch information
mateuszkwiecinski authored Dec 23, 2021
2 parents 6b251e2 + c32382c commit c4bb3cd
Show file tree
Hide file tree
Showing 19 changed files with 165 additions and 132 deletions.
26 changes: 12 additions & 14 deletions app/src/main/kotlin/io/github/wykopmobilny/base/BaseActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import io.github.wykopmobilny.R
import io.github.wykopmobilny.storage.api.SettingsPreferencesApi
import io.github.wykopmobilny.styles.AppThemeUi
import io.github.wykopmobilny.styles.ApplicableStyleUi
import io.github.wykopmobilny.styles.StylesDependencies
import io.github.wykopmobilny.ui.dialogs.showExceptionDialog
import io.github.wykopmobilny.utils.requireDependency
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.dropWhile
import kotlinx.coroutines.flow.first
Expand All @@ -38,15 +37,14 @@ abstract class BaseActivity : AppCompatActivity(), HasAndroidInjector {
@Inject
lateinit var themeSettingsPreferences: SettingsPreferencesApi

private val getAppStyle by lazy { application.requireDependency<StylesDependencies>().getAppStyle() }

@Inject
lateinit var androidInjector: DispatchingAndroidInjector<Any>

override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
val initialTheme = runBlocking { getAppStyle().first() }.theme
initTheme(initialTheme)
val getAppStyle = application.requireDependency<StylesDependencies>().getAppStyle()
val initialStyle = runBlocking { getAppStyle().first() }.style
initTheme(initialStyle)
super.onCreate(savedInstanceState)

val slidr = if (enableSwipeBackLayout) {
Expand All @@ -58,9 +56,9 @@ abstract class BaseActivity : AppCompatActivity(), HasAndroidInjector {
val shared = getAppStyle().stateIn(this)
launch {
shared
.map { it.theme }
.map { it.style }
.distinctUntilChanged()
.dropWhile { it == initialTheme }
.dropWhile { it == initialStyle }
.collect {
updateTheme(it)
recreate()
Expand Down Expand Up @@ -92,8 +90,8 @@ abstract class BaseActivity : AppCompatActivity(), HasAndroidInjector {
}

// This function initializes activity theme based on settings
private fun initTheme(initialTheme: AppThemeUi) {
updateTheme(initialTheme)
private fun initTheme(style: ApplicableStyleUi) {
updateTheme(style)
if (isActivityTransfluent || enableSwipeBackLayout) {
theme.applyStyle(R.style.TransparentActivityTheme, true)
window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
Expand All @@ -110,11 +108,11 @@ abstract class BaseActivity : AppCompatActivity(), HasAndroidInjector {
}
}

private fun updateTheme(newTheme: AppThemeUi) {
private fun updateTheme(newTheme: ApplicableStyleUi) {
val appTheme = when (newTheme) {
AppThemeUi.Light -> R.style.WykopAppTheme
AppThemeUi.Dark -> R.style.WykopAppTheme_Dark
AppThemeUi.DarkAmoled -> R.style.WykopAppTheme_Amoled
ApplicableStyleUi.Light -> R.style.WykopAppTheme
ApplicableStyleUi.Dark -> R.style.WykopAppTheme_Dark
ApplicableStyleUi.DarkAmoled -> R.style.WykopAppTheme_Amoled
}
setTheme(appTheme)
}
Expand Down
21 changes: 10 additions & 11 deletions app/src/main/kotlin/io/github/wykopmobilny/base/ThemableActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ import androidx.lifecycle.lifecycleScope
import com.r0adkll.slidr.attachSlidr
import com.r0adkll.slidr.model.SlidrConfig
import io.github.wykopmobilny.R
import io.github.wykopmobilny.styles.AppThemeUi
import io.github.wykopmobilny.styles.ApplicableStyleUi
import io.github.wykopmobilny.styles.StylesDependencies
import io.github.wykopmobilny.utils.requireDependency
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.dropWhile
import kotlinx.coroutines.flow.first
Expand All @@ -22,11 +21,11 @@ import kotlinx.coroutines.runBlocking

internal abstract class ThemableActivity : AppCompatActivity() {

private val getAppStyle by lazy { requireDependency<StylesDependencies>().getAppStyle() }

override fun onCreate(savedInstanceState: Bundle?) {
val initialTheme = runBlocking { getAppStyle().first() }.theme
updateTheme(initialTheme)
val getAppStyle = requireDependency<StylesDependencies>().getAppStyle()
val initialStyle = runBlocking { getAppStyle().first() }.style
updateTheme(initialStyle)
super.onCreate(savedInstanceState ?: intent.getBundleExtra("saved_State"))

window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
Expand All @@ -36,9 +35,9 @@ internal abstract class ThemableActivity : AppCompatActivity() {
val shared = getAppStyle().stateIn(this)
launch {
shared
.map { it.theme }
.map { it.style }
.distinctUntilChanged()
.dropWhile { it == initialTheme }
.dropWhile { it == initialStyle }
.collect {
updateTheme(it)
recreate()
Expand All @@ -59,11 +58,11 @@ internal abstract class ThemableActivity : AppCompatActivity() {
}
}

private fun updateTheme(theme: AppThemeUi) {
private fun updateTheme(theme: ApplicableStyleUi) {
val themeRes = when (theme) {
AppThemeUi.Light -> R.style.Theme_App_Light
AppThemeUi.Dark -> R.style.Theme_App_Dark
AppThemeUi.DarkAmoled -> R.style.Theme_App_Amoled
ApplicableStyleUi.Light -> R.style.Theme_App_Light
ApplicableStyleUi.Dark -> R.style.Theme_App_Dark
ApplicableStyleUi.DarkAmoled -> R.style.Theme_App_Amoled
}
setTheme(themeRes)
}
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
INSERT OR IGNORE INTO preferenceEntity (key, value)
VALUES (
"settings.appearance.app_theme",
(
SELECT "dark"
FROM preferenceEntity
WHERE key = "settings.appearance.dark_theme" AND value = "true"
)
);

INSERT OR IGNORE INTO preferenceEntity (key, value)
VALUES (
"settings.appearance.app_theme",
(
SELECT "light"
FROM preferenceEntity
WHERE key = "settings.appearance.dark_theme" AND value = "false"
)
);

DELETE FROM preferenceEntity WHERE key = "settings.appearance.dark_theme";
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import io.github.wykopmobilny.domain.settings.prefs.GetMediaPreferences
import io.github.wykopmobilny.domain.settings.prefs.GetMikroblogPreferences
import io.github.wykopmobilny.domain.settings.prefs.MainScreen
import io.github.wykopmobilny.domain.settings.prefs.MikroblogScreen
import io.github.wykopmobilny.domain.styles.AppThemePreference
import io.github.wykopmobilny.domain.utils.safe
import io.github.wykopmobilny.ui.base.AppScopes
import io.github.wykopmobilny.ui.settings.AppThemeUi
import io.github.wykopmobilny.ui.settings.AppearancePreferencesUi
import io.github.wykopmobilny.ui.settings.AppearancePreferencesUi.AppearanceSectionUi
import io.github.wykopmobilny.ui.settings.AppearancePreferencesUi.ImagesSectionUi
Expand Down Expand Up @@ -62,13 +64,19 @@ class GetAppearancePreferencesQuery @Inject internal constructor(
private fun appearanceFlow(): Flow<AppearanceSectionUi> =
getAppearanceSectionPreferences().map { appearance ->
AppearanceSectionUi(
useDarkTheme = Setting(
currentValue = appearance.isDarkTheme,
onClicked = { updateUserSetting(UserSettings.darkTheme, !appearance.isDarkTheme) },
userThemeSetting = ListSetting(
values = AppThemeUi.values().toList(),
currentValue = appearance.appThemePreference.toUi(),
onSelected = { updateUserSetting(UserSettings.appTheme, it.toDomain()) },
),
useAmoledTheme = Setting(
currentValue = appearance.isAmoledTheme,
isEnabled = appearance.isDarkTheme,
isEnabled = when (appearance.appThemePreference) {
AppThemePreference.Auto,
AppThemePreference.Dark,
-> true
AppThemePreference.Light -> false
},
onClicked = { updateUserSetting(UserSettings.useAmoledTheme, !appearance.isAmoledTheme) },
),
fontSize = ListSetting(
Expand Down Expand Up @@ -172,6 +180,20 @@ class GetAppearancePreferencesQuery @Inject internal constructor(
}
}

private fun AppThemePreference.toUi() =
when (this) {
AppThemePreference.Auto -> AppThemeUi.Automatic
AppThemePreference.Light -> AppThemeUi.Light
AppThemePreference.Dark -> AppThemeUi.Dark
}

private fun AppThemeUi.toDomain() =
when (this) {
AppThemeUi.Automatic -> AppThemePreference.Auto
AppThemeUi.Light -> AppThemePreference.Light
AppThemeUi.Dark -> AppThemePreference.Dark
}

private fun MainScreen.toUi() =
when (this) {
MainScreen.Promoted -> MainScreenUi.Promoted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@ package io.github.wykopmobilny.domain.settings

import io.github.wykopmobilny.domain.settings.prefs.MainScreen
import io.github.wykopmobilny.domain.settings.prefs.MikroblogScreen
import io.github.wykopmobilny.domain.styles.AppThemePreference

internal object UserSettings {

val darkTheme = booleanMapping(preferencesKey = "settings.appearance.dark_theme")
val appTheme = enumMapping(
preferencesKey = "settings.appearance.app_theme",
mapOf(
AppThemePreference.Auto to "auto",
AppThemePreference.Light to "light",
AppThemePreference.Dark to "dark",
),
)
val useAmoledTheme = booleanMapping(preferencesKey = "settings.appearance.amoled_theme")
val defaultScreen = enumMapping(
preferencesKey = "settings.appearance.default_screen",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import io.github.wykopmobilny.domain.navigation.SystemSettingsDetector
import io.github.wykopmobilny.domain.settings.FontSize
import io.github.wykopmobilny.domain.settings.UserSettings
import io.github.wykopmobilny.domain.settings.get
import io.github.wykopmobilny.domain.styles.AppTheme
import io.github.wykopmobilny.domain.styles.GetAppTheme
import io.github.wykopmobilny.domain.styles.AppThemePreference
import io.github.wykopmobilny.ui.base.AppScopes
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
Expand All @@ -17,20 +17,20 @@ import javax.inject.Inject

internal class GetAppearanceSectionPreferences @Inject constructor(
private val appStorage: AppStorage,
private val getAppTheme: GetAppTheme,
private val systemSettingsDetector: SystemSettingsDetector,
private val appScopes: AppScopes,
) {

operator fun invoke() = combine(
darkThemeFlow(),
operator fun invoke(): SharedFlow<AppearanceSection> = combine(
appStorage.get(UserSettings.appTheme).map { it ?: AppThemePreference.Auto },
appStorage.get(UserSettings.useAmoledTheme).map { it ?: false },
appStorage.get(UserSettings.font).map { it ?: FontSize.Normal },
appStorage.get(UserSettings.defaultScreen).map { it ?: MainScreen.Promoted },
appStorage.get(UserSettings.disableEdgeSlide).map { it ?: findDefaultEdgeSlide() },
) { (isDarkTheme, isAmoledTheme), fontSize, defaultScreen, disableEdgeSlide ->
) { appTheme, useAmoledTheme, fontSize, defaultScreen, disableEdgeSlide ->
AppearanceSection(
isDarkTheme = isDarkTheme,
isAmoledTheme = isAmoledTheme,
appThemePreference = appTheme,
isAmoledTheme = useAmoledTheme,
defaultScreen = defaultScreen,
defaultFont = fontSize,
disableEdgeSlide = disableEdgeSlide,
Expand All @@ -42,20 +42,6 @@ internal class GetAppearanceSectionPreferences @Inject constructor(
replay = 0,
)

private fun darkThemeFlow() = combine(
getAppTheme(),
appStorage.get(UserSettings.useAmoledTheme),
) { currentAppTheme, amoledTheme ->
val isDarkTheme = when (currentAppTheme) {
AppTheme.Light -> false
AppTheme.Dark -> true
AppTheme.DarkAmoled -> true
}
val isAmoledTheme = amoledTheme == true

isDarkTheme to isAmoledTheme
}

private suspend fun findDefaultEdgeSlide() =
when (systemSettingsDetector.getNavigationMode()) {
NavigationMode.ThreeButtons,
Expand All @@ -68,7 +54,7 @@ internal class GetAppearanceSectionPreferences @Inject constructor(
}

internal data class AppearanceSection(
val isDarkTheme: Boolean,
val appThemePreference: AppThemePreference,
val isAmoledTheme: Boolean,
val defaultScreen: MainScreen,
val defaultFont: FontSize,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.github.wykopmobilny.domain.styles

enum class AppTheme {
internal enum class AppThemePreference {
Auto,
Light,
Dark,
DarkAmoled,
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,54 @@
package io.github.wykopmobilny.domain.styles

import io.github.wykopmobilny.domain.navigation.NightModeState
import io.github.wykopmobilny.domain.navigation.SystemSettingsDetector
import io.github.wykopmobilny.domain.settings.prefs.GetAppearanceSectionPreferences
import io.github.wykopmobilny.styles.AppThemeUi
import io.github.wykopmobilny.styles.ApplicableStyleUi
import io.github.wykopmobilny.styles.GetAppStyle
import io.github.wykopmobilny.styles.StyleUi
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import javax.inject.Inject

internal class GetAppStyleQuery @Inject constructor(
private val getAppTheme: GetAppTheme,
private val getAppearanceSectionPreferences: GetAppearanceSectionPreferences,
private val systemSettingsDetector: SystemSettingsDetector,
) : GetAppStyle {

override fun invoke() =
combine(
getAppTheme(),
getAppearanceSectionPreferences(),
) { theme, appearance ->
StyleUi(
theme = theme.toUi(),
edgeSlidingBehaviorEnabled = !appearance.disableEdgeSlide,
)
}
getAppearanceSectionPreferences()
.map { appearance ->
StyleUi(
style = findAppStyle(appearance.appThemePreference, appearance.isAmoledTheme),
edgeSlidingBehaviorEnabled = !appearance.disableEdgeSlide,
)
}
.distinctUntilChanged()
}

private fun AppTheme.toUi() = when (this) {
AppTheme.Light -> AppThemeUi.Light
AppTheme.Dark -> AppThemeUi.Dark
AppTheme.DarkAmoled -> AppThemeUi.DarkAmoled
private suspend fun findAppStyle(appThemePreference: AppThemePreference, isAmoledTheme: Boolean) =
when (appThemePreference) {
AppThemePreference.Auto ->
if (isSystemDark()) {
findDarkMode(isAmoledTheme)
} else {
ApplicableStyleUi.Light
}
AppThemePreference.Light -> ApplicableStyleUi.Light
AppThemePreference.Dark -> findDarkMode(isAmoledTheme)
}

private fun findDarkMode(isAmoledTheme: Boolean) =
if (isAmoledTheme) {
ApplicableStyleUi.DarkAmoled
} else {
ApplicableStyleUi.Dark
}

private suspend fun isSystemDark() =
when (systemSettingsDetector.getNightModeState()) {
NightModeState.Enabled -> true
NightModeState.Disabled,
NightModeState.Unknown,
-> false
}
}
Loading

0 comments on commit c4bb3cd

Please sign in to comment.