diff --git a/app/src/main/java/me/zobrist/tichucounter/BaseActivity.kt b/app/src/main/java/me/zobrist/tichucounter/BaseActivity.kt deleted file mode 100644 index e9a040b..0000000 --- a/app/src/main/java/me/zobrist/tichucounter/BaseActivity.kt +++ /dev/null @@ -1,83 +0,0 @@ -package me.zobrist.tichucounter - -import android.content.SharedPreferences -import android.os.Bundle -import android.view.WindowManager -import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.app.AppCompatDelegate -import androidx.core.os.LocaleListCompat -import androidx.preference.PreferenceManager -import dagger.hilt.android.AndroidEntryPoint -import me.zobrist.tichucounter.domain.Language -import me.zobrist.tichucounter.domain.SettingsAdapter -import me.zobrist.tichucounter.domain.Theme -import javax.inject.Inject - -@AndroidEntryPoint -abstract class BaseActivity : AppCompatActivity(), - SharedPreferences.OnSharedPreferenceChangeListener { - - @Inject - lateinit var settingsAdapter: SettingsAdapter - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - keepScreenOn(settingsAdapter.keepScreenOn) - updateTheme(settingsAdapter.theme) - - PreferenceManager.getDefaultSharedPreferences(this) - .registerOnSharedPreferenceChangeListener(this) - } - - override fun onResume() { - super.onResume() - PreferenceManager.getDefaultSharedPreferences(this) - .registerOnSharedPreferenceChangeListener(this) - } - - override fun onPause() { - super.onPause() - PreferenceManager.getDefaultSharedPreferences(this) - .unregisterOnSharedPreferenceChangeListener(this) - } - - override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) { - when (key) { - settingsAdapter.language::class.simpleName -> setLanguage(settingsAdapter.language) - settingsAdapter.keepScreenOn::class.simpleName -> keepScreenOn(settingsAdapter.keepScreenOn) - settingsAdapter.theme::class.simpleName -> updateTheme(settingsAdapter.theme) - } - } - - - private fun updateTheme(theme: Theme) { - - val themeValue = when (theme) { - Theme.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO - Theme.DARK -> AppCompatDelegate.MODE_NIGHT_YES - Theme.DEFAULT -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM - } - - if (themeValue != AppCompatDelegate.getDefaultNightMode()) { - AppCompatDelegate.setDefaultNightMode(themeValue) - delegate.applyDayNight() - } - } - - private fun keepScreenOn(keepOn: Boolean) { - if (keepOn) { - window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) - } else { - window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) - } - } - - private fun setLanguage(language: Language) { - val currentLocale = AppCompatDelegate.getApplicationLocales()[0].toString() - - if (language.value != currentLocale) { - val newLocale = LocaleListCompat.forLanguageTags(language.value) - AppCompatDelegate.setApplicationLocales(newLocale) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt b/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt index 09344dc..8dac229 100644 --- a/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt +++ b/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt @@ -1,9 +1,12 @@ package me.zobrist.tichucounter import android.os.Bundle +import android.view.WindowManager import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.annotation.StringRes +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.app.AppCompatDelegate import androidx.compose.foundation.layout.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* @@ -15,6 +18,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.core.os.LocaleListCompat import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController @@ -26,8 +30,7 @@ import com.google.accompanist.systemuicontroller.rememberSystemUiController import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch -import me.zobrist.tichucounter.domain.NavigationAction -import me.zobrist.tichucounter.domain.TopBarAction +import me.zobrist.tichucounter.domain.* import me.zobrist.tichucounter.repository.GameRepository import me.zobrist.tichucounter.ui.AppTheme import me.zobrist.tichucounter.ui.MainViewModel @@ -39,11 +42,14 @@ import me.zobrist.tichucounter.ui.settings.SettingsViewModel import javax.inject.Inject @AndroidEntryPoint -class MainActivity : BaseActivity() { +class MainActivity : AppCompatActivity(), ISettingsChangeListener { @Inject lateinit var gameRepository: GameRepository + @Inject + lateinit var settingsAdapter: SettingsAdapter + private val counterViewModel: CounterViewModel by viewModels() private val historyViewModel: HistoryViewModel by viewModels() private val settingsViewModel: SettingsViewModel by viewModels() @@ -53,6 +59,8 @@ class MainActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + settingsAdapter.registerOnChangeListener(this) + setContent { AppTheme { val systemUiController = rememberSystemUiController() @@ -62,6 +70,41 @@ class MainActivity : BaseActivity() { } } + override fun onDestroy() { + super.onDestroy() + settingsAdapter.unregisterOnChangeListener(this) + } + + override fun onLanguageChanged(language: Language) { + val currentLocale = AppCompatDelegate.getApplicationLocales()[0].toString() + + if (language.value != currentLocale) { + val newLocale = LocaleListCompat.forLanguageTags(language.value) + AppCompatDelegate.setApplicationLocales(newLocale) + } + } + + override fun onThemeChanged(theme: Theme) { + val themeValue = when (theme) { + Theme.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO + Theme.DARK -> AppCompatDelegate.MODE_NIGHT_YES + Theme.DEFAULT -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM + } + + if (themeValue != AppCompatDelegate.getDefaultNightMode()) { + AppCompatDelegate.setDefaultNightMode(themeValue) + delegate.applyDayNight() + } + } + + override fun onScreenOnChanged(keepOn: KeepScreenOn) { + if (keepOn.value) { + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } else { + window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + } + } + @OptIn(ExperimentalMaterial3Api::class) @Composable fun MyScaffoldLayout( diff --git a/app/src/main/java/me/zobrist/tichucounter/domain/SettingsAdapter.kt b/app/src/main/java/me/zobrist/tichucounter/domain/SettingsAdapter.kt index 65bfb82..ca83692 100644 --- a/app/src/main/java/me/zobrist/tichucounter/domain/SettingsAdapter.kt +++ b/app/src/main/java/me/zobrist/tichucounter/domain/SettingsAdapter.kt @@ -5,37 +5,90 @@ import androidx.appcompat.app.AppCompatDelegate.getApplicationLocales import androidx.preference.PreferenceManager import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject +import javax.inject.Singleton enum class Theme { DEFAULT, DARK, LIGHT } enum class Language(val value: String) { ENGLISH("en"), GERMAN("de") } +enum class KeepScreenOn(val value: Boolean) { ON(true), OFF(false) } +interface ISettingsChangeListener { + fun onLanguageChanged(language: Language) + fun onThemeChanged(theme: Theme) + fun onScreenOnChanged(keepOn: KeepScreenOn) +} +@Singleton class SettingsAdapter @Inject constructor(@ApplicationContext private val context: Context) { private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + private var listenerList = mutableListOf() - val language: Language - get() { - return try { - var setting = sharedPreferences.getString(Language::class.simpleName, null) - enumValueOf(setting!!) - } catch (_: NullPointerException) { - val current = getCurrentAppLanguage() - setLanguage(current) - current - } + var language: Language + private set + + var theme: Theme + private set + + var keepScreenOn: KeepScreenOn + private set + + init { + language = try { + enumValueOf(sharedPreferences.getString(Language::class.simpleName, null)!!) + } catch (_: NullPointerException) { + getCurrentAppLanguage() } - val theme: Theme - get() { - val setting = sharedPreferences.getString(Theme::class.simpleName, Theme.DEFAULT.name) - return enumValueOf(setting!!) + theme = try { + enumValueOf(sharedPreferences.getString(Theme::class.simpleName, null)!!) + } catch (_: java.lang.Exception) { + Theme.DEFAULT } - val keepScreenOn: Boolean - get() { - return sharedPreferences.getBoolean("keep_screen_on", false) + keepScreenOn = try { + enumValueOf(sharedPreferences.getString(KeepScreenOn::class.simpleName, null)!!) + } catch (_: java.lang.Exception) { + KeepScreenOn.OFF } + } + + fun registerOnChangeListener(listener: ISettingsChangeListener) { + listenerList.add(listener) + + listener.onThemeChanged(theme) + listener.onLanguageChanged(language) + listener.onScreenOnChanged(keepScreenOn) + } + + fun unregisterOnChangeListener(listener: ISettingsChangeListener?) { + if (listener != null) { + listenerList.remove(listener) + } + } + + fun setLanguage(language: Language) { + this.language = language + updatePreference(Language::class.simpleName, language.name) + notifyListeners(language) + } + + fun setTheme(theme: Theme) { + this.theme = theme + updatePreference(Theme::class.simpleName, theme.name) + notifyListeners(theme) + } + + fun setKeepScreenOn(setting: KeepScreenOn) { + this.keepScreenOn = setting + updatePreference(KeepScreenOn::class.simpleName, setting.name) + notifyListeners(setting) + } + + private fun updatePreference(name: String?, value: String) { + val editor = sharedPreferences.edit() + editor.putString(name, value) + editor.apply() + } private fun getCurrentAppLanguage(): Language { return when (getApplicationLocales()[0].toString()) { @@ -44,22 +97,22 @@ class SettingsAdapter @Inject constructor(@ApplicationContext private val contex } } - fun setLanguage(language: Language) { - val editor = sharedPreferences.edit() - editor.putString(Language::class.simpleName, language.name) - editor.apply() + private fun notifyListeners(language: Language) { + listenerList.forEach { + it.onLanguageChanged(language) + } } - fun setTheme(theme: Theme) { - val editor = sharedPreferences.edit() - editor.putString(Theme::class.simpleName, theme.name) - editor.apply() + private fun notifyListeners(theme: Theme) { + listenerList.forEach { + it.onThemeChanged(theme) + } } - fun setKeepScreenOn(setting: Boolean) { - val editor = sharedPreferences.edit() - editor.putBoolean("keep_screen_on", setting) - editor.apply() + private fun notifyListeners(keepScreenOn: KeepScreenOn) { + listenerList.forEach { + it.onScreenOnChanged(keepScreenOn) + } } } \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/settings/SettingsView.kt b/app/src/main/java/me/zobrist/tichucounter/ui/settings/SettingsView.kt index d6a05e9..bb02db3 100644 --- a/app/src/main/java/me/zobrist/tichucounter/ui/settings/SettingsView.kt +++ b/app/src/main/java/me/zobrist/tichucounter/ui/settings/SettingsView.kt @@ -18,6 +18,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import me.zobrist.tichucounter.R +import me.zobrist.tichucounter.domain.KeepScreenOn import me.zobrist.tichucounter.domain.Language import me.zobrist.tichucounter.domain.Theme import me.zobrist.tichucounter.ui.AppTheme @@ -38,7 +39,7 @@ val themeMap = mapOf( @Composable fun SettingsView(viewModel: SettingsViewModel) { SettingsView( - viewModel.screenOn, + viewModel.screenOn.value, viewModel.language, viewModel.theme, { viewModel.updateScreenOn(it) }, @@ -51,7 +52,7 @@ fun SettingsView( valueScreenOn: Boolean = true, valueLanguage: Language = Language.ENGLISH, valueTheme: Theme = Theme.DARK, - updateScreenOn: (Boolean) -> Unit = {}, + updateScreenOn: (KeepScreenOn) -> Unit = {}, updateLanguage: (Language) -> Unit = {}, updateTheme: (Theme) -> Unit = {} ) { @@ -59,7 +60,7 @@ fun SettingsView( BooleanSetting( stringResource(R.string.keep_screen_on), valueScreenOn - ) { updateScreenOn(it) } + ) { updateScreenOn(if (it) KeepScreenOn.ON else KeepScreenOn.OFF) } StringSetting( stringResource(R.string.choose_language_text), diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/settings/SettingsViewModel.kt b/app/src/main/java/me/zobrist/tichucounter/ui/settings/SettingsViewModel.kt index 3db0b89..b37e1bd 100644 --- a/app/src/main/java/me/zobrist/tichucounter/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/me/zobrist/tichucounter/ui/settings/SettingsViewModel.kt @@ -5,6 +5,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import me.zobrist.tichucounter.domain.KeepScreenOn import me.zobrist.tichucounter.domain.Language import me.zobrist.tichucounter.domain.SettingsAdapter import me.zobrist.tichucounter.domain.Theme @@ -20,7 +21,7 @@ class SettingsViewModel @Inject constructor(private val settings: SettingsAdapte var theme by mutableStateOf(settings.theme) private set - var screenOn by mutableStateOf(false) + var screenOn by mutableStateOf(settings.keepScreenOn) private set fun updateLanguage(language: Language) { @@ -33,7 +34,7 @@ class SettingsViewModel @Inject constructor(private val settings: SettingsAdapte this.theme = settings.theme } - fun updateScreenOn(value: Boolean) { + fun updateScreenOn(value: KeepScreenOn) { settings.setKeepScreenOn(value) screenOn = settings.keepScreenOn }