diff --git a/app/build.gradle b/app/build.gradle index a4cc544..c10a5fc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,7 +30,7 @@ android { targetSdkVersion 33 versionCode versionProperties["versionCode"].toInteger() versionName "1.1.0Beta1" - resConfigs("de", "en") + resConfigs 'de', 'en' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true vectorDrawables { diff --git a/app/src/main/java/me/zobrist/tichucounter/BaseActivity.kt b/app/src/main/java/me/zobrist/tichucounter/BaseActivity.kt index a8343a7..a83c63f 100644 --- a/app/src/main/java/me/zobrist/tichucounter/BaseActivity.kt +++ b/app/src/main/java/me/zobrist/tichucounter/BaseActivity.kt @@ -7,17 +7,23 @@ 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) - val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) - keepScreenOn(sharedPreferences.getBoolean("screen_on", false)) - updateTheme(sharedPreferences.getString("theme", null)) + keepScreenOn(settingsAdapter.keepScreenOn) + updateTheme(settingsAdapter.theme) PreferenceManager.getDefaultSharedPreferences(this) .registerOnSharedPreferenceChangeListener(this) @@ -37,20 +43,19 @@ abstract class BaseActivity : AppCompatActivity(), override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) { when (key) { - "language" -> setLanguage(sharedPreferences.getString(key, null)) - "screen_on" -> keepScreenOn(sharedPreferences.getBoolean(key, false)) - "theme" -> updateTheme(sharedPreferences.getString(key, null)) + 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: String?) { + private fun updateTheme(theme: Theme) { val themeValue = when (theme) { - "light" -> AppCompatDelegate.MODE_NIGHT_NO - "dark" -> AppCompatDelegate.MODE_NIGHT_YES - "default" -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM - else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM + Theme.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO + Theme.DARK -> AppCompatDelegate.MODE_NIGHT_YES + Theme.DEFAULT -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM } if (themeValue != AppCompatDelegate.getDefaultNightMode()) { @@ -67,7 +72,13 @@ abstract class BaseActivity : AppCompatActivity(), } } - private fun setLanguage(locale: String?) { + private fun setLanguage(language: Language) { + + val locale = when (language) { + Language.ENGLISH -> "en" + Language.GERMAN -> "de" + else -> null + } val currentLocale = AppCompatDelegate.getApplicationLocales()[0].toString() diff --git a/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt b/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt index 7bfe64b..ff0f02b 100644 --- a/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt +++ b/app/src/main/java/me/zobrist/tichucounter/MainActivity.kt @@ -31,6 +31,8 @@ import me.zobrist.tichucounter.ui.MainViewModel import me.zobrist.tichucounter.ui.counter.* import me.zobrist.tichucounter.ui.history.HistoryList import me.zobrist.tichucounter.ui.history.HistoryViewModel +import me.zobrist.tichucounter.ui.settings.SettingsView +import me.zobrist.tichucounter.ui.settings.SettingsViewModel import javax.inject.Inject @AndroidEntryPoint @@ -41,6 +43,7 @@ class MainActivity : BaseActivity() { private val counterViewModel: CounterViewModel by viewModels() private val historyViewModel: HistoryViewModel by viewModels() + private val settingsViewModel: SettingsViewModel by viewModels() private val mainViewModel: MainViewModel by viewModels() @@ -79,9 +82,7 @@ class MainActivity : BaseActivity() { } composable("settings") { - Column() { - Text("Settings") - } + SettingsView(settingsViewModel) mainViewModel.setActions(emptyList()) } } diff --git a/app/src/main/java/me/zobrist/tichucounter/domain/SettingsAdapter.kt b/app/src/main/java/me/zobrist/tichucounter/domain/SettingsAdapter.kt new file mode 100644 index 0000000..9d3d636 --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/domain/SettingsAdapter.kt @@ -0,0 +1,50 @@ +package me.zobrist.tichucounter.domain + +import android.content.Context +import androidx.preference.PreferenceManager +import dagger.hilt.android.qualifiers.ApplicationContext +import javax.inject.Inject + +enum class Theme { DEFAULT, DARK, LIGHT } +enum class Language { DEFAULT, GERMAN, ENGLISH } + + +class SettingsAdapter @Inject constructor(@ApplicationContext private val context: Context) { + + private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + + val language: Language + get() { + return Language.values()[sharedPreferences.getInt(Language::class.simpleName, 0)] + } + + val theme: Theme + get() { + return Theme.values()[sharedPreferences.getInt(Theme::class.simpleName, 0)] + } + + val keepScreenOn: Boolean + get() { + return sharedPreferences.getBoolean("keep_screen_on", false) + } + + + fun setLanguage(language: Language) { + val editor = sharedPreferences.edit() + editor.putInt(Language::class.simpleName, language.ordinal) + editor.commit() + } + + fun setTheme(theme: Theme) { + val editor = sharedPreferences.edit() + editor.putInt(Theme::class.simpleName, theme.ordinal) + editor.commit() + } + + fun setKeepScreenOn(setting: Boolean) { + val editor = sharedPreferences.edit() + editor.putBoolean("keep_screen_on", setting) + editor.commit() + } + +} \ 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 new file mode 100644 index 0000000..75f7d08 --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/ui/settings/SettingsView.kt @@ -0,0 +1,122 @@ +package me.zobrist.tichucounter.ui.settings + +import androidx.compose.foundation.layout.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Check +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import me.zobrist.tichucounter.R +import me.zobrist.tichucounter.domain.Language +import me.zobrist.tichucounter.domain.Theme + + +val languageMap = mapOf( + Language.DEFAULT to R.string.android_default_text, + Language.ENGLISH to R.string.english, + Language.GERMAN to R.string.german +) + +val themeMap = mapOf( + Theme.DEFAULT to R.string.android_default_text, + Theme.DARK to R.string.dark, + Theme.LIGHT to R.string.light +) + + +@Composable +fun SettingsView(viewModel: SettingsViewModel) { + SettingsView( + viewModel.screenOn, + viewModel.language, + viewModel.theme, + { viewModel.updateScreenOn(it) }, + { viewModel.updateLanguage(it) }, + { viewModel.updateTheme(it) }) +} + +@Preview +@Composable +fun SettingsView( + valueScreenOn: Boolean = true, + valueLanguage: Language = Language.ENGLISH, + valueTheme: Theme = Theme.DARK, + updateScreenOn: (Boolean) -> Unit = {}, + updateLanguage: (Language) -> Unit = {}, + updateTheme: (Theme) -> Unit = {} +) { + Column() { + BooleanSetting( + stringResource(R.string.keep_screen_on), + valueScreenOn + ) { updateScreenOn(it) } + + StringSetting( + stringResource(R.string.choose_language_text), + languageMap, + valueLanguage, + ) { updateLanguage(it) } + + StringSetting( + stringResource(R.string.choose_theme_text), + themeMap, + valueTheme, + ) { updateTheme(it) } + } +} + +@Composable +fun BooleanSetting(name: String, value: Boolean, updateValue: (Boolean) -> Unit) { + Row { + Column() { + Text(text = name) + } + Column() { + Checkbox(checked = value, onCheckedChange = { updateValue(it) }) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun StringSetting(name: String, map: Map, selected: T, onSelected: (T) -> Unit) { + + var expanded by remember { mutableStateOf(false) } + + Row() { + TextField( + value = stringResource(map[selected]!!), + onValueChange = { }, + singleLine = true, + label = { Text(name) }, + readOnly = true, + modifier = Modifier + .onFocusChanged { + if (it.isFocused) { + expanded = true + } + } + ) + DropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false } + ) { + map.forEach { + DropdownMenuItem( + onClick = { + onSelected(it.key) + expanded = false + }, + text = { Text(stringResource(it.value)) }, + trailingIcon = { + if (it.key == selected) { + Icon(Icons.Outlined.Check, contentDescription = null) + } + }) + } + } + } +} 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 new file mode 100644 index 0000000..3db0b89 --- /dev/null +++ b/app/src/main/java/me/zobrist/tichucounter/ui/settings/SettingsViewModel.kt @@ -0,0 +1,41 @@ +package me.zobrist.tichucounter.ui.settings + +import androidx.compose.runtime.getValue +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.Language +import me.zobrist.tichucounter.domain.SettingsAdapter +import me.zobrist.tichucounter.domain.Theme +import javax.inject.Inject + +@HiltViewModel +class SettingsViewModel @Inject constructor(private val settings: SettingsAdapter) : ViewModel() { + + + var language by mutableStateOf(settings.language) + private set + + var theme by mutableStateOf(settings.theme) + private set + + var screenOn by mutableStateOf(false) + private set + + fun updateLanguage(language: Language) { + settings.setLanguage(language) + this.language = settings.language + } + + fun updateTheme(theme: Theme) { + settings.setTheme(theme) + this.theme = settings.theme + } + + fun updateScreenOn(value: Boolean) { + settings.setKeepScreenOn(value) + screenOn = settings.keepScreenOn + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable-mdpi/back.png b/app/src/main/res/drawable-mdpi/back.png deleted file mode 100644 index 72b8bd7..0000000 Binary files a/app/src/main/res/drawable-mdpi/back.png and /dev/null differ diff --git a/app/src/main/res/drawable-mdpi/checkmark.png b/app/src/main/res/drawable-mdpi/checkmark.png deleted file mode 100644 index 75d2263..0000000 Binary files a/app/src/main/res/drawable-mdpi/checkmark.png and /dev/null differ diff --git a/app/src/main/res/drawable-night/back.png b/app/src/main/res/drawable-night/back.png deleted file mode 100644 index 770c83c..0000000 Binary files a/app/src/main/res/drawable-night/back.png and /dev/null differ diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml deleted file mode 100644 index 0bff127..0000000 --- a/app/src/main/res/menu/activity_main_drawer.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/menu/menu_counter.xml b/app/src/main/res/menu/menu_counter.xml deleted file mode 100644 index b3832dc..0000000 --- a/app/src/main/res/menu/menu_counter.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml deleted file mode 100644 index 6f638ab..0000000 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml deleted file mode 100644 index e93c628..0000000 --- a/app/src/main/res/values/arrays.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - @string/dark - @string/light - @string/android_default_text - - - - dark - light - default - - - - - @string/english - @string/german - - - - en - de - - \ No newline at end of file diff --git a/build.gradle b/build.gradle index f1a53dd..b2dbe00 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.3.1' + classpath 'com.android.tools.build:gradle:7.4.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle.properties b/gradle.properties index 4d15d01..30dbeb4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,6 +16,6 @@ org.gradle.jvmargs=-Xmx2048m # https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX -android.enableJetifier=true +android.enableJetifier=false # Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7e135b5..f9d4a26 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip