forked from melod1n/fast-messenger
clean up settings and some other things
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
package com.meloda.app.fast.common
|
||||
|
||||
import com.meloda.app.fast.common.model.LongPollState
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
interface LongPollController {
|
||||
val currentState: StateFlow<LongPollState>
|
||||
val stateToApply: StateFlow<LongPollState>
|
||||
|
||||
fun updateCurrentState(newState: LongPollState)
|
||||
fun setStateToApply(newState: LongPollState)
|
||||
}
|
||||
|
||||
class LongPollControllerImpl : LongPollController {
|
||||
|
||||
override val currentState = MutableStateFlow<LongPollState>(LongPollState.Stopped)
|
||||
override val stateToApply = MutableStateFlow<LongPollState>(LongPollState.Stopped)
|
||||
|
||||
override fun updateCurrentState(newState: LongPollState) {
|
||||
currentState.value = newState
|
||||
}
|
||||
|
||||
override fun setStateToApply(newState: LongPollState) {
|
||||
currentState.value = newState
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
package com.meloda.app.fast.common.di
|
||||
|
||||
import coil.ImageLoader
|
||||
import com.meloda.app.fast.common.LongPollController
|
||||
import com.meloda.app.fast.common.LongPollControllerImpl
|
||||
import com.meloda.app.fast.common.provider.ResourceProvider
|
||||
import com.meloda.app.fast.common.provider.ResourceProviderImpl
|
||||
import org.koin.core.module.dsl.singleOf
|
||||
import org.koin.dsl.bind
|
||||
import org.koin.dsl.module
|
||||
|
||||
val commonModule = module {
|
||||
@@ -9,4 +15,7 @@ val commonModule = module {
|
||||
.crossfade(true)
|
||||
.build()
|
||||
}
|
||||
|
||||
singleOf(::LongPollControllerImpl) bind LongPollController::class
|
||||
singleOf(::ResourceProviderImpl) bind ResourceProvider::class
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.meloda.app.fast.common
|
||||
package com.meloda.app.fast.common.extensions
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
package com.meloda.app.fast.common
|
||||
package com.meloda.app.fast.common.model
|
||||
|
||||
data class ApiLanguage(val value: String)
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.meloda.app.fast.common.model
|
||||
|
||||
private const val MODE_NIGHT_NO = 1
|
||||
private const val MODE_NIGHT_YES = 2
|
||||
private const val MODE_NIGHT_FOLLOW_SYSTEM = -1
|
||||
private const val MODE_NIGHT_AUTO_BATTERY = 3
|
||||
|
||||
enum class DarkMode(val value: Int) {
|
||||
DISABLED(MODE_NIGHT_NO),
|
||||
FOLLOW_SYSTEM(MODE_NIGHT_FOLLOW_SYSTEM),
|
||||
AUTO_BATTERY(MODE_NIGHT_AUTO_BATTERY),
|
||||
ENABLED(MODE_NIGHT_YES);
|
||||
|
||||
companion object {
|
||||
|
||||
fun parse(value: Int): DarkMode = entries.firstOrNull { it.value == value }
|
||||
?: throw IllegalArgumentException("Unknown dark mode with value: $value")
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,5 +1,4 @@
|
||||
package com.meloda.app.fast.datastore.model
|
||||
|
||||
package com.meloda.app.fast.common.model
|
||||
sealed class LongPollState {
|
||||
data object Stopped : LongPollState()
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.meloda.app.fast.common
|
||||
package com.meloda.app.fast.common.model
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.annotation.ColorInt
|
||||
+3
-1
@@ -1,4 +1,4 @@
|
||||
package com.meloda.app.fast.common
|
||||
package com.meloda.app.fast.common.model
|
||||
|
||||
import android.content.res.Resources
|
||||
import androidx.annotation.PluralsRes
|
||||
@@ -18,6 +18,8 @@ sealed class UiText {
|
||||
data class Simple(val text: String) : UiText()
|
||||
|
||||
data class QuantityResource(@PluralsRes val resId: Int, val quantity: Int) : UiText()
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun UiText?.parseString(resources: Resources): String? {
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.meloda.app.fast.common.provider
|
||||
|
||||
import android.content.res.Resources
|
||||
|
||||
interface ResourceProvider {
|
||||
|
||||
fun getString(resId: Int): String
|
||||
}
|
||||
|
||||
class ResourceProviderImpl(private val resources: Resources) : ResourceProvider {
|
||||
|
||||
override fun getString(resId: Int): String {
|
||||
return resources.getString(resId)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package com.meloda.app.fast.datastore
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import com.meloda.app.fast.common.model.DarkMode
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
object AppSettings {
|
||||
|
||||
private var preferences: SharedPreferences by Delegates.notNull()
|
||||
|
||||
fun init(preferences: SharedPreferences) {
|
||||
this.preferences = preferences
|
||||
}
|
||||
|
||||
fun edit(
|
||||
commit: Boolean = false,
|
||||
action: SharedPreferences.Editor.() -> Unit
|
||||
) {
|
||||
preferences.edit(commit, action)
|
||||
}
|
||||
|
||||
fun getString(key: String, defaultValue: String?): String? {
|
||||
return preferences.getString(key, defaultValue)
|
||||
}
|
||||
|
||||
fun getBoolean(key: String, defaultValue: Boolean): Boolean {
|
||||
return preferences.getBoolean(key, defaultValue)
|
||||
}
|
||||
|
||||
fun getInt(key: String, defaultValue: Int): Int {
|
||||
return preferences.getInt(key, defaultValue)
|
||||
}
|
||||
|
||||
fun getLong(key: String, defaultValue: Long): Long {
|
||||
return preferences.getLong(key, defaultValue)
|
||||
}
|
||||
|
||||
fun getFloat(key: String, defaultValue: Float): Float {
|
||||
return preferences.getFloat(key, defaultValue)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : Any> get(clazz: KClass<T>, key: String, defaultValue: T): T {
|
||||
return when (clazz) {
|
||||
String::class -> getString(key, defaultValue as String)
|
||||
Boolean::class -> getBoolean(key, defaultValue as Boolean)
|
||||
Int::class -> getInt(key, defaultValue as Int)
|
||||
Long::class -> getLong(key, defaultValue as Long)
|
||||
Float::class -> getFloat(key, defaultValue as Float)
|
||||
else -> throw IllegalStateException("Unsupported class: $clazz")
|
||||
} as T
|
||||
}
|
||||
|
||||
inline fun <reified T> get(key: String, defaultValue: T): T {
|
||||
return when (T::class) {
|
||||
String::class -> getString(key, defaultValue as String)
|
||||
Boolean::class -> getBoolean(key, defaultValue as Boolean)
|
||||
Int::class -> getInt(key, defaultValue as Int)
|
||||
Long::class -> getLong(key, defaultValue as Long)
|
||||
Float::class -> getFloat(key, defaultValue as Float)
|
||||
else -> throw IllegalStateException("Unsupported class: ${T::class}")
|
||||
} as T
|
||||
}
|
||||
|
||||
fun <T> put(key: String, newValue: T?) {
|
||||
preferences.edit {
|
||||
when (newValue) {
|
||||
is String -> putString(key, newValue)
|
||||
is Boolean -> putBoolean(key, newValue)
|
||||
is Int -> putInt(key, newValue)
|
||||
is Long -> putLong(key, newValue)
|
||||
is Float -> putFloat(key, newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var deviceId: String
|
||||
get() = get("device_id", "")
|
||||
set(value) = put("device_id", value)
|
||||
|
||||
object General {
|
||||
var useContactNames: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_USE_CONTACT_NAMES,
|
||||
SettingsKeys.DEFAULT_VALUE_USE_CONTACT_NAMES
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_USE_CONTACT_NAMES, value)
|
||||
|
||||
var enablePullToRefresh: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH,
|
||||
SettingsKeys.DEFAULT_VALUE_ENABLE_PULL_TO_REFRESH
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH, value)
|
||||
}
|
||||
|
||||
object Appearance {
|
||||
var enableMultiline: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_APPEARANCE_MULTILINE,
|
||||
SettingsKeys.DEFAULT_VALUE_MULTILINE
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_APPEARANCE_MULTILINE, value)
|
||||
|
||||
var darkMode: DarkMode
|
||||
get() = get(
|
||||
SettingsKeys.KEY_APPEARANCE_DARK_MODE,
|
||||
SettingsKeys.DEFAULT_VALUE_APPEARANCE_DARK_MODE
|
||||
).let(DarkMode.Companion::parse)
|
||||
set(mode) = put(SettingsKeys.KEY_APPEARANCE_DARK_MODE, mode.value)
|
||||
|
||||
var enableAmoledDark: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_APPEARANCE_AMOLED_THEME,
|
||||
SettingsKeys.DEFAULT_VALUE_APPEARANCE_AMOLED_THEME
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_APPEARANCE_AMOLED_THEME, value)
|
||||
|
||||
var enableDynamicColors: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_USE_DYNAMIC_COLORS,
|
||||
SettingsKeys.DEFAULT_VALUE_USE_DYNAMIC_COLORS
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_USE_DYNAMIC_COLORS, value)
|
||||
|
||||
var appLanguage: String
|
||||
get() = get(
|
||||
SettingsKeys.KEY_APPEARANCE_LANGUAGE,
|
||||
SettingsKeys.DEFAULT_APPEARANCE_LANGUAGE
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_APPEARANCE_LANGUAGE, value)
|
||||
}
|
||||
|
||||
object Features {
|
||||
var fastText: String
|
||||
get() = get(
|
||||
SettingsKeys.KEY_FEATURES_FAST_TEXT,
|
||||
SettingsKeys.DEFAULT_VALUE_FEATURES_FAST_TEXT
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_FEATURES_FAST_TEXT, value)
|
||||
}
|
||||
|
||||
object Activity {
|
||||
var sendOnlineStatus: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_ACTIVITY_SEND_ONLINE_STATUS,
|
||||
SettingsKeys.DEFAULT_VALUE_KEY_ACTIVITY_SEND_ONLINE_STATUS
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_ACTIVITY_SEND_ONLINE_STATUS, value)
|
||||
}
|
||||
|
||||
object Debug {
|
||||
var showAlertAfterCrash: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_DEBUG_SHOW_CRASH_ALERT,
|
||||
true
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_DEBUG_SHOW_CRASH_ALERT, value)
|
||||
|
||||
var longPollInBackground: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_FEATURES_LONG_POLL_IN_BACKGROUND,
|
||||
SettingsKeys.DEFAULT_VALUE_FEATURES_LONG_POLL_IN_BACKGROUND
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_FEATURES_LONG_POLL_IN_BACKGROUND, value)
|
||||
|
||||
var useBlur: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_APPEARANCE_USE_BLUR,
|
||||
SettingsKeys.DEFAULT_VALUE_KEY_APPEARANCE_USE_BLUR
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_APPEARANCE_USE_BLUR, value)
|
||||
|
||||
var showEmojiButton: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_SHOW_EMOJI_BUTTON,
|
||||
SettingsKeys.DEFAULT_VALUE_KEY_SHOW_EMOJI_BUTTON
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_SHOW_EMOJI_BUTTON, value)
|
||||
|
||||
var showDebugCategory: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_SHOW_DEBUG_CATEGORY,
|
||||
false
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_SHOW_DEBUG_CATEGORY, value)
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package com.meloda.app.fast.datastore
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.os.PowerManager
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
|
||||
fun isUsingDarkMode(
|
||||
resources: Resources,
|
||||
powerManager: PowerManager,
|
||||
): Boolean {
|
||||
val nightThemeMode: Int = SettingsController.getInt(
|
||||
SettingsKeys.KEY_APPEARANCE_DARK_THEME,
|
||||
SettingsKeys.DEFAULT_VALUE_APPEARANCE_DARK_THEME
|
||||
)
|
||||
|
||||
val appForceDarkMode = nightThemeMode == AppCompatDelegate.MODE_NIGHT_YES
|
||||
val appBatterySaver = nightThemeMode == AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY
|
||||
|
||||
val systemUiNightMode = resources.configuration.uiMode
|
||||
|
||||
val isSystemBatterySaver = powerManager.isPowerSaveMode
|
||||
val isSystemUsingDarkTheme =
|
||||
systemUiNightMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
||||
|
||||
return appForceDarkMode || (appBatterySaver && isSystemBatterySaver) || (!appBatterySaver && isSystemUsingDarkTheme && nightThemeMode == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
}
|
||||
|
||||
fun isUsingDynamicColors(): Boolean = SettingsController.getBoolean(
|
||||
SettingsKeys.KEY_USE_DYNAMIC_COLORS,
|
||||
SettingsKeys.DEFAULT_VALUE_USE_DYNAMIC_COLORS
|
||||
)
|
||||
|
||||
fun isUsingAmoledBackground(): Boolean = SettingsController.getBoolean(
|
||||
SettingsKeys.KEY_APPEARANCE_AMOLED_THEME,
|
||||
SettingsKeys.DEFAULT_VALUE_APPEARANCE_AMOLED_THEME
|
||||
)
|
||||
|
||||
fun selectedColorScheme(): Int = SettingsController.getInt(
|
||||
SettingsKeys.KEY_APPEARANCE_COLOR_SCHEME,
|
||||
SettingsKeys.DEFAULT_VALUE_APPEARANCE_COLOR_SCHEME
|
||||
)
|
||||
|
||||
fun isUsingBlur(): Boolean = SettingsController.getBoolean(
|
||||
SettingsKeys.KEY_APPEARANCE_BLUR,
|
||||
SettingsKeys.DEFAULT_VALUE_KEY_APPEARANCE_BLUR
|
||||
)
|
||||
|
||||
fun isDebugSettingsShown(): Boolean = SettingsController.getBoolean(
|
||||
SettingsKeys.KEY_SHOW_DEBUG_CATEGORY,
|
||||
false
|
||||
)
|
||||
|
||||
fun isMultiline(): Boolean = SettingsController.getBoolean(
|
||||
SettingsKeys.KEY_APPEARANCE_MULTILINE,
|
||||
SettingsKeys.DEFAULT_VALUE_MULTILINE
|
||||
)
|
||||
@@ -1,95 +0,0 @@
|
||||
package com.meloda.app.fast.datastore
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
object SettingsController {
|
||||
|
||||
private var preferences: SharedPreferences by Delegates.notNull()
|
||||
|
||||
fun init(preferences: SharedPreferences) {
|
||||
this.preferences = preferences
|
||||
}
|
||||
|
||||
fun edit(
|
||||
commit: Boolean = false,
|
||||
action: SharedPreferences.Editor.() -> Unit
|
||||
) {
|
||||
preferences.edit(commit, action)
|
||||
}
|
||||
|
||||
fun getString(key: String, defaultValue: String?): String? {
|
||||
return preferences.getString(key, defaultValue)
|
||||
}
|
||||
|
||||
fun getBoolean(key: String, defaultValue: Boolean): Boolean {
|
||||
return preferences.getBoolean(key, defaultValue)
|
||||
}
|
||||
|
||||
fun getInt(key: String, defaultValue: Int): Int {
|
||||
return preferences.getInt(key, defaultValue)
|
||||
}
|
||||
|
||||
fun getLong(key: String, defaultValue: Long): Long {
|
||||
return preferences.getLong(key, defaultValue)
|
||||
}
|
||||
|
||||
fun getFloat(key: String, defaultValue: Float): Float {
|
||||
return preferences.getFloat(key, defaultValue)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : Any> get(clazz: KClass<T>, key: String, defaultValue: T): T {
|
||||
return when (clazz) {
|
||||
String::class -> getString(key, defaultValue as String)
|
||||
Boolean::class -> getBoolean(key, defaultValue as Boolean)
|
||||
Int::class -> getInt(key, defaultValue as Int)
|
||||
Long::class -> getLong(key, defaultValue as Long)
|
||||
Float::class -> getFloat(key, defaultValue as Float)
|
||||
else -> throw IllegalStateException("Unsupported class: $clazz")
|
||||
} as T
|
||||
}
|
||||
|
||||
inline fun <reified T> get(key: String, defaultValue: T): T {
|
||||
return when (T::class) {
|
||||
String::class -> getString(key, defaultValue as String)
|
||||
Boolean::class -> getBoolean(key, defaultValue as Boolean)
|
||||
Int::class -> getInt(key, defaultValue as Int)
|
||||
Long::class -> getLong(key, defaultValue as Long)
|
||||
Float::class -> getFloat(key, defaultValue as Float)
|
||||
else -> throw IllegalStateException("Unsupported class: ${T::class}")
|
||||
} as T
|
||||
}
|
||||
|
||||
fun <T> put(key: String, newValue: T?) {
|
||||
preferences.edit {
|
||||
when (newValue) {
|
||||
is String -> putString(key, newValue)
|
||||
is Boolean -> putBoolean(key, newValue)
|
||||
is Int -> putInt(key, newValue)
|
||||
is Long -> putLong(key, newValue)
|
||||
is Float -> putFloat(key, newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isLongPollInBackgroundEnabled: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_FEATURES_LONG_POLL_IN_BACKGROUND,
|
||||
SettingsKeys.DEFAULT_VALUE_FEATURES_LONG_POLL_IN_BACKGROUND
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_FEATURES_LONG_POLL_IN_BACKGROUND, value)
|
||||
|
||||
var deviceId: String
|
||||
get() = get("device_id", "")
|
||||
set(value) = put("device_id", value)
|
||||
|
||||
var enablePullToRefresh: Boolean
|
||||
get() = get(
|
||||
SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH,
|
||||
SettingsKeys.DEFAULT_VALUE_ENABLE_PULL_TO_REFRESH
|
||||
)
|
||||
set(value) = put(SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH, value)
|
||||
}
|
||||
@@ -17,8 +17,8 @@ object SettingsKeys {
|
||||
const val KEY_APPEARANCE = "appearance"
|
||||
const val KEY_APPEARANCE_MULTILINE = "appearance_multiline"
|
||||
const val DEFAULT_VALUE_MULTILINE = true
|
||||
const val KEY_APPEARANCE_DARK_THEME = "appearance_appearance_dark_theme"
|
||||
const val DEFAULT_VALUE_APPEARANCE_DARK_THEME = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
const val KEY_APPEARANCE_DARK_MODE = "appearance_appearance_dark_mode"
|
||||
const val DEFAULT_VALUE_APPEARANCE_DARK_MODE = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
const val KEY_APPEARANCE_AMOLED_THEME = "appearance_amoled_theme"
|
||||
const val DEFAULT_VALUE_APPEARANCE_AMOLED_THEME = false
|
||||
const val KEY_USE_DYNAMIC_COLORS = "appearance_use_dynamic_colors"
|
||||
@@ -26,8 +26,9 @@ object SettingsKeys {
|
||||
const val KEY_APPEARANCE_COLOR_SCHEME = "appearance_color_scheme"
|
||||
const val DEFAULT_VALUE_APPEARANCE_COLOR_SCHEME = 0
|
||||
const val KEY_APPEARANCE_LANGUAGE = "appearance_language"
|
||||
const val KEY_APPEARANCE_BLUR = "appearance_blur"
|
||||
const val DEFAULT_VALUE_KEY_APPEARANCE_BLUR = false
|
||||
const val DEFAULT_APPEARANCE_LANGUAGE = ""
|
||||
const val KEY_APPEARANCE_USE_BLUR = "appearance_use_blur"
|
||||
const val DEFAULT_VALUE_KEY_APPEARANCE_USE_BLUR = false
|
||||
|
||||
const val KEY_FEATURES_FAST_TEXT = "features_fast_text"
|
||||
const val DEFAULT_VALUE_FEATURES_FAST_TEXT = "¯\\_(ツ)_/¯"
|
||||
|
||||
@@ -1,144 +1,124 @@
|
||||
package com.meloda.app.fast.datastore
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.os.PowerManager
|
||||
import android.util.Log
|
||||
import com.meloda.app.fast.datastore.model.LongPollState
|
||||
import com.meloda.app.fast.ui.model.ThemeConfig
|
||||
import com.meloda.app.fast.common.model.DarkMode
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
||||
interface UserSettings {
|
||||
val theme: StateFlow<ThemeConfig>
|
||||
val longPollStateToApply: StateFlow<LongPollState>
|
||||
val longPollCurrentState: StateFlow<LongPollState>
|
||||
val online: StateFlow<Boolean>
|
||||
val debugSettingsEnabled: StateFlow<Boolean>
|
||||
|
||||
val useContactNames: StateFlow<Boolean>
|
||||
val language: StateFlow<String>
|
||||
val enablePullToRefresh: StateFlow<Boolean>
|
||||
|
||||
fun updateUsingDarkTheme()
|
||||
fun useDarkThemeChanged(use: Boolean)
|
||||
fun useAmoledThemeChanged(use: Boolean)
|
||||
fun useDynamicColorsChanged(use: Boolean)
|
||||
fun useBlurChanged(use: Boolean)
|
||||
fun useMultiline(use: Boolean)
|
||||
fun setLongPollStateToApply(newState: LongPollState)
|
||||
fun updateLongPollCurrentState(currentState: LongPollState)
|
||||
fun setOnline(use: Boolean)
|
||||
fun enableDebugSettings(enable: Boolean)
|
||||
val enableMultiline: StateFlow<Boolean>
|
||||
val darkMode: StateFlow<DarkMode>
|
||||
val enableAmoledDark: StateFlow<Boolean>
|
||||
val enableDynamicColors: StateFlow<Boolean>
|
||||
val appLanguage: StateFlow<String>
|
||||
|
||||
val fastText: StateFlow<String>
|
||||
|
||||
val sendOnlineStatus: StateFlow<Boolean>
|
||||
|
||||
val showAlertAfterCrash: StateFlow<Boolean>
|
||||
val longPollInBackground: StateFlow<Boolean>
|
||||
val useBlur: StateFlow<Boolean>
|
||||
val showEmojiButton: StateFlow<Boolean>
|
||||
val showDebugCategory: StateFlow<Boolean>
|
||||
|
||||
fun onUseContactNamesChanged(use: Boolean)
|
||||
fun onLanguageChanged(newLanguage: String)
|
||||
fun onEnablePullToRefreshChanged(enable: Boolean)
|
||||
|
||||
fun onEnableMultilineChanged(enable: Boolean)
|
||||
fun onDarkModeChanged(mode: DarkMode)
|
||||
fun onEnableAmoledDarkChanged(enable: Boolean)
|
||||
fun onEnableDynamicColorsChanged(enable: Boolean)
|
||||
fun onAppLanguageChanged(language: String)
|
||||
|
||||
fun onFastTextChanged(text: String)
|
||||
|
||||
fun onSendOnlineStatusChanged(send: Boolean)
|
||||
|
||||
fun onShowAlertAfterCrashChanged(show: Boolean)
|
||||
fun onLongPollInBackgroundChanged(inBackground: Boolean)
|
||||
fun onUseBlurChanged(use: Boolean)
|
||||
fun onShowEmojiButtonChanged(show: Boolean)
|
||||
fun onShowDebugCategoryChanged(show: Boolean)
|
||||
}
|
||||
|
||||
class UserSettingsImpl(
|
||||
private val resources: Resources,
|
||||
private val powerManager: PowerManager
|
||||
) : UserSettings {
|
||||
class UserSettingsImpl : UserSettings {
|
||||
|
||||
override val theme = MutableStateFlow(
|
||||
ThemeConfig(
|
||||
usingDarkStyle = isUsingDarkMode(resources, powerManager),
|
||||
usingDynamicColors = isUsingDynamicColors(),
|
||||
selectedColorScheme = selectedColorScheme(),
|
||||
usingAmoledBackground = isUsingAmoledBackground(),
|
||||
usingBlur = isUsingBlur(),
|
||||
isMultiline = isMultiline(),
|
||||
isDeviceCompact = false
|
||||
)
|
||||
)
|
||||
override val useContactNames = MutableStateFlow(AppSettings.General.useContactNames)
|
||||
override val enablePullToRefresh = MutableStateFlow(AppSettings.General.enablePullToRefresh)
|
||||
|
||||
override val longPollStateToApply = MutableStateFlow<LongPollState>(LongPollState.Stopped)
|
||||
override val longPollCurrentState = MutableStateFlow<LongPollState>(LongPollState.Stopped)
|
||||
override val enableMultiline = MutableStateFlow(AppSettings.Appearance.enableMultiline)
|
||||
override val darkMode = MutableStateFlow(AppSettings.Appearance.darkMode)
|
||||
override val enableAmoledDark = MutableStateFlow(AppSettings.Appearance.enableAmoledDark)
|
||||
override val enableDynamicColors = MutableStateFlow(AppSettings.Appearance.enableDynamicColors)
|
||||
override val appLanguage = MutableStateFlow(AppSettings.Appearance.appLanguage)
|
||||
|
||||
override val online = MutableStateFlow(
|
||||
SettingsController.getBoolean(
|
||||
SettingsKeys.KEY_ACTIVITY_SEND_ONLINE_STATUS,
|
||||
SettingsKeys.DEFAULT_VALUE_KEY_ACTIVITY_SEND_ONLINE_STATUS
|
||||
)
|
||||
)
|
||||
override val fastText = MutableStateFlow(AppSettings.Features.fastText)
|
||||
|
||||
override val debugSettingsEnabled = MutableStateFlow(
|
||||
SettingsController.getBoolean(
|
||||
SettingsKeys.KEY_SHOW_DEBUG_CATEGORY,
|
||||
false
|
||||
)
|
||||
)
|
||||
override val sendOnlineStatus = MutableStateFlow(AppSettings.Activity.sendOnlineStatus)
|
||||
|
||||
override val useContactNames = MutableStateFlow(
|
||||
SettingsController.getBoolean(
|
||||
SettingsKeys.KEY_USE_CONTACT_NAMES,
|
||||
SettingsKeys.DEFAULT_VALUE_USE_CONTACT_NAMES
|
||||
)
|
||||
)
|
||||
|
||||
override val language = MutableStateFlow("")
|
||||
|
||||
override val enablePullToRefresh = MutableStateFlow(SettingsController.enablePullToRefresh)
|
||||
|
||||
override fun updateUsingDarkTheme() {
|
||||
useDarkThemeChanged(
|
||||
isUsingDarkMode(
|
||||
resources = resources,
|
||||
powerManager = powerManager,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun useDarkThemeChanged(use: Boolean) {
|
||||
theme.value = theme.value.copy(
|
||||
usingDarkStyle = use
|
||||
)
|
||||
}
|
||||
|
||||
override fun useAmoledThemeChanged(use: Boolean) {
|
||||
theme.value = theme.value.copy(
|
||||
usingAmoledBackground = use
|
||||
)
|
||||
}
|
||||
|
||||
override fun useDynamicColorsChanged(use: Boolean) {
|
||||
theme.value = theme.value.copy(usingDynamicColors = use)
|
||||
}
|
||||
|
||||
override fun useBlurChanged(use: Boolean) {
|
||||
theme.value = theme.value.copy(usingBlur = use)
|
||||
}
|
||||
|
||||
override fun useMultiline(use: Boolean) {
|
||||
theme.value = theme.value.copy(isMultiline = use)
|
||||
}
|
||||
|
||||
override fun setLongPollStateToApply(newState: LongPollState) {
|
||||
longPollStateToApply.update { newState }
|
||||
Log.d("UserSettings", "setLongPollState: $newState")
|
||||
}
|
||||
|
||||
override fun updateLongPollCurrentState(currentState: LongPollState) {
|
||||
longPollCurrentState.update { currentState }
|
||||
Log.d("UserSettings", "updateLongPollCurrentState: $currentState")
|
||||
}
|
||||
|
||||
override fun setOnline(use: Boolean) {
|
||||
online.value = use
|
||||
}
|
||||
|
||||
override fun enableDebugSettings(enable: Boolean) {
|
||||
debugSettingsEnabled.update { enable }
|
||||
}
|
||||
override val showAlertAfterCrash = MutableStateFlow(AppSettings.Debug.showAlertAfterCrash)
|
||||
override val longPollInBackground = MutableStateFlow(AppSettings.Debug.longPollInBackground)
|
||||
override val useBlur = MutableStateFlow(AppSettings.Debug.useBlur)
|
||||
override val showEmojiButton = MutableStateFlow(AppSettings.Debug.showEmojiButton)
|
||||
override val showDebugCategory = MutableStateFlow(AppSettings.Debug.showDebugCategory)
|
||||
|
||||
override fun onUseContactNamesChanged(use: Boolean) {
|
||||
useContactNames.update { use }
|
||||
}
|
||||
|
||||
override fun onLanguageChanged(newLanguage: String) {
|
||||
language.update { newLanguage }
|
||||
useContactNames.value = use
|
||||
}
|
||||
|
||||
override fun onEnablePullToRefreshChanged(enable: Boolean) {
|
||||
enablePullToRefresh.update { enable }
|
||||
enablePullToRefresh.value = enable
|
||||
}
|
||||
|
||||
override fun onEnableMultilineChanged(enable: Boolean) {
|
||||
enableMultiline.value = enable
|
||||
}
|
||||
|
||||
override fun onDarkModeChanged(mode: DarkMode) {
|
||||
darkMode.value = mode
|
||||
}
|
||||
|
||||
override fun onEnableAmoledDarkChanged(enable: Boolean) {
|
||||
enableAmoledDark.value = enable
|
||||
}
|
||||
|
||||
override fun onEnableDynamicColorsChanged(enable: Boolean) {
|
||||
enableDynamicColors.value = enable
|
||||
}
|
||||
|
||||
override fun onAppLanguageChanged(language: String) {
|
||||
appLanguage.value = language
|
||||
}
|
||||
|
||||
override fun onFastTextChanged(text: String) {
|
||||
fastText.value = text
|
||||
}
|
||||
|
||||
override fun onSendOnlineStatusChanged(send: Boolean) {
|
||||
sendOnlineStatus.value = send
|
||||
}
|
||||
|
||||
override fun onShowAlertAfterCrashChanged(show: Boolean) {
|
||||
showAlertAfterCrash.value = show
|
||||
}
|
||||
|
||||
override fun onLongPollInBackgroundChanged(inBackground: Boolean) {
|
||||
longPollInBackground.value = inBackground
|
||||
}
|
||||
|
||||
override fun onUseBlurChanged(use: Boolean) {
|
||||
useBlur.value = use
|
||||
}
|
||||
|
||||
override fun onShowEmojiButtonChanged(show: Boolean) {
|
||||
showEmojiButton.value = show
|
||||
}
|
||||
|
||||
override fun onShowDebugCategoryChanged(show: Boolean) {
|
||||
showDebugCategory.value = show
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package com.meloda.app.fast.network.interceptor
|
||||
|
||||
import androidx.core.net.toUri
|
||||
import com.meloda.app.fast.common.ApiLanguage
|
||||
import com.meloda.app.fast.common.model.ApiLanguage
|
||||
import com.meloda.app.fast.common.provider.Provider
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
|
||||
@@ -22,7 +22,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
import com.meloda.app.fast.ui.theme.LocalIsDarkTheme
|
||||
import com.meloda.app.fast.ui.theme.LocalThemeConfig
|
||||
|
||||
/**
|
||||
* Default alpha levels used by Material components.
|
||||
@@ -79,7 +79,7 @@ object ContentAlpha {
|
||||
lowContrastAlpha: Float
|
||||
): Float {
|
||||
val contentColor = LocalContentColor.current
|
||||
return if (!LocalIsDarkTheme.current) {
|
||||
return if (!LocalThemeConfig.current.darkMode) {
|
||||
if (contentColor.luminance() > 0.5) highContrastAlpha else lowContrastAlpha
|
||||
} else {
|
||||
if (contentColor.luminance() < 0.5) highContrastAlpha else lowContrastAlpha
|
||||
|
||||
@@ -33,8 +33,8 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import com.meloda.app.fast.common.UiText
|
||||
import com.meloda.app.fast.common.parseString
|
||||
import com.meloda.app.fast.common.model.UiText
|
||||
import com.meloda.app.fast.common.model.parseString
|
||||
import com.meloda.app.fast.ui.util.ImmutableList
|
||||
import com.meloda.app.fast.ui.util.ImmutableList.Companion.toImmutableList
|
||||
import com.meloda.app.fast.ui.util.getString
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.meloda.app.fast.ui.model
|
||||
|
||||
data class ThemeConfig(
|
||||
val usingDarkStyle: Boolean,
|
||||
val usingDynamicColors: Boolean,
|
||||
val darkMode: Boolean,
|
||||
val dynamicColors: Boolean,
|
||||
val selectedColorScheme: Int,
|
||||
val usingAmoledBackground: Boolean,
|
||||
val usingBlur: Boolean,
|
||||
val isMultiline: Boolean,
|
||||
val amoledDark: Boolean,
|
||||
val enableBlur: Boolean,
|
||||
val enableMultiline: Boolean,
|
||||
val isDeviceCompact: Boolean
|
||||
)
|
||||
|
||||
@@ -9,7 +9,6 @@ import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -104,20 +103,18 @@ private val robotoFonts = FontFamily(
|
||||
)
|
||||
)
|
||||
|
||||
val LocalTheme = compositionLocalOf {
|
||||
val LocalThemeConfig = compositionLocalOf {
|
||||
ThemeConfig(
|
||||
usingDarkStyle = false,
|
||||
usingDynamicColors = false,
|
||||
darkMode = false,
|
||||
dynamicColors = false,
|
||||
selectedColorScheme = 0,
|
||||
usingAmoledBackground = false,
|
||||
usingBlur = false,
|
||||
isMultiline = false,
|
||||
amoledDark = false,
|
||||
enableBlur = false,
|
||||
enableMultiline = false,
|
||||
isDeviceCompact = false
|
||||
)
|
||||
}
|
||||
|
||||
val LocalIsDarkTheme = compositionLocalOf { false }
|
||||
|
||||
val LocalHazeState = compositionLocalOf {
|
||||
HazeState()
|
||||
}
|
||||
@@ -181,11 +178,9 @@ fun AppTheme(
|
||||
}
|
||||
}
|
||||
|
||||
CompositionLocalProvider(LocalIsDarkTheme provides useDarkTheme) {
|
||||
MaterialTheme(
|
||||
colorScheme = predefinedColorScheme ?: colorScheme,
|
||||
typography = typography,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
MaterialTheme(
|
||||
colorScheme = predefinedColorScheme ?: colorScheme,
|
||||
typography = typography,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.meloda.app.fast.ui.util
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.os.PowerManager
|
||||
import android.view.KeyEvent
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -10,9 +12,12 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.key.onKeyEvent
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.meloda.app.fast.common.UiText
|
||||
import androidx.core.content.getSystemService
|
||||
import com.meloda.app.fast.common.model.DarkMode
|
||||
import com.meloda.app.fast.common.model.UiText
|
||||
|
||||
@Composable
|
||||
fun UiText?.getString(): String? {
|
||||
@@ -75,3 +80,19 @@ fun LazyListState.isScrollingUp(): Boolean {
|
||||
}
|
||||
}.value
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun isNeedToEnableDarkMode(darkMode: DarkMode): Boolean {
|
||||
val context = LocalContext.current
|
||||
|
||||
val appForceDarkMode = darkMode == DarkMode.ENABLED
|
||||
val appBatterySaver = darkMode == DarkMode.AUTO_BATTERY
|
||||
|
||||
val systemUiNightMode = context.resources.configuration.uiMode
|
||||
|
||||
val isSystemBatterySaver = context.getSystemService<PowerManager>()?.isPowerSaveMode == true
|
||||
val isSystemUsingDarkTheme =
|
||||
systemUiNightMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
||||
|
||||
return appForceDarkMode || (appBatterySaver && isSystemBatterySaver) || (!appBatterySaver && isSystemUsingDarkTheme && darkMode == DarkMode.FOLLOW_SYSTEM)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user