Update android studio. Add compose settings screen.
Some checks are pending
continuous-integration/drone/push Build is pending
Some checks are pending
continuous-integration/drone/push Build is pending
This commit is contained in:
@@ -30,7 +30,7 @@ android {
|
|||||||
targetSdkVersion 33
|
targetSdkVersion 33
|
||||||
versionCode versionProperties["versionCode"].toInteger()
|
versionCode versionProperties["versionCode"].toInteger()
|
||||||
versionName "1.1.0Beta1"
|
versionName "1.1.0Beta1"
|
||||||
resConfigs("de", "en")
|
resConfigs 'de', 'en'
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
|
|||||||
@@ -7,17 +7,23 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.core.os.LocaleListCompat
|
import androidx.core.os.LocaleListCompat
|
||||||
import androidx.preference.PreferenceManager
|
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(),
|
abstract class BaseActivity : AppCompatActivity(),
|
||||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var settingsAdapter: SettingsAdapter
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
keepScreenOn(settingsAdapter.keepScreenOn)
|
||||||
keepScreenOn(sharedPreferences.getBoolean("screen_on", false))
|
updateTheme(settingsAdapter.theme)
|
||||||
updateTheme(sharedPreferences.getString("theme", null))
|
|
||||||
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(this)
|
PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
.registerOnSharedPreferenceChangeListener(this)
|
.registerOnSharedPreferenceChangeListener(this)
|
||||||
@@ -37,20 +43,19 @@ abstract class BaseActivity : AppCompatActivity(),
|
|||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) {
|
||||||
when (key) {
|
when (key) {
|
||||||
"language" -> setLanguage(sharedPreferences.getString(key, null))
|
settingsAdapter.language::class.simpleName -> setLanguage(settingsAdapter.language)
|
||||||
"screen_on" -> keepScreenOn(sharedPreferences.getBoolean(key, false))
|
settingsAdapter.keepScreenOn::class.simpleName -> keepScreenOn(settingsAdapter.keepScreenOn)
|
||||||
"theme" -> updateTheme(sharedPreferences.getString(key, null))
|
settingsAdapter.theme::class.simpleName -> updateTheme(settingsAdapter.theme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun updateTheme(theme: String?) {
|
private fun updateTheme(theme: Theme) {
|
||||||
|
|
||||||
val themeValue = when (theme) {
|
val themeValue = when (theme) {
|
||||||
"light" -> AppCompatDelegate.MODE_NIGHT_NO
|
Theme.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO
|
||||||
"dark" -> AppCompatDelegate.MODE_NIGHT_YES
|
Theme.DARK -> AppCompatDelegate.MODE_NIGHT_YES
|
||||||
"default" -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
Theme.DEFAULT -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||||
else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (themeValue != AppCompatDelegate.getDefaultNightMode()) {
|
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()
|
val currentLocale = AppCompatDelegate.getApplicationLocales()[0].toString()
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ import me.zobrist.tichucounter.ui.MainViewModel
|
|||||||
import me.zobrist.tichucounter.ui.counter.*
|
import me.zobrist.tichucounter.ui.counter.*
|
||||||
import me.zobrist.tichucounter.ui.history.HistoryList
|
import me.zobrist.tichucounter.ui.history.HistoryList
|
||||||
import me.zobrist.tichucounter.ui.history.HistoryViewModel
|
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
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@@ -41,6 +43,7 @@ class MainActivity : BaseActivity() {
|
|||||||
|
|
||||||
private val counterViewModel: CounterViewModel by viewModels()
|
private val counterViewModel: CounterViewModel by viewModels()
|
||||||
private val historyViewModel: HistoryViewModel by viewModels()
|
private val historyViewModel: HistoryViewModel by viewModels()
|
||||||
|
private val settingsViewModel: SettingsViewModel by viewModels()
|
||||||
private val mainViewModel: MainViewModel by viewModels()
|
private val mainViewModel: MainViewModel by viewModels()
|
||||||
|
|
||||||
|
|
||||||
@@ -79,9 +82,7 @@ class MainActivity : BaseActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
composable("settings") {
|
composable("settings") {
|
||||||
Column() {
|
SettingsView(settingsViewModel)
|
||||||
Text("Settings")
|
|
||||||
}
|
|
||||||
mainViewModel.setActions(emptyList())
|
mainViewModel.setActions(emptyList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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 <T> StringSetting(name: String, map: Map<T, Int>, 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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB |
@@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
tools:showIn="navigation_view">
|
|
||||||
|
|
||||||
<group android:checkableBehavior="single">
|
|
||||||
<item
|
|
||||||
android:id="@+id/nav_counter"
|
|
||||||
android:icon="@drawable/ic_menu_camera"
|
|
||||||
android:title="@string/menu_counter" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/nav_history"
|
|
||||||
android:icon="@drawable/ic_menu_gallery"
|
|
||||||
android:title="@string/menu_history" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/nav_settings"
|
|
||||||
android:icon="@drawable/ic_menu_slideshow"
|
|
||||||
android:title="@string/menu_settings" />
|
|
||||||
</group>
|
|
||||||
</menu>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
tools:context="me.zobrist.tichucounter.MainActivity">
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_undo"
|
|
||||||
android:icon="@drawable/ic_baseline_undo_24"
|
|
||||||
android:orderInCategory="5"
|
|
||||||
android:title="@string/undo"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_new"
|
|
||||||
android:checkable="false"
|
|
||||||
android:icon="@drawable/ic_baseline_add_24"
|
|
||||||
android:orderInCategory="10"
|
|
||||||
android:title="@string/clear"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
</menu>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/mobile_navigation"
|
|
||||||
app:startDestination="@+id/nav_counter">
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/nav_counter"
|
|
||||||
android:name="me.zobrist.tichucounter.ui.counter.CounterFragment"
|
|
||||||
android:label="@string/menu_counter"
|
|
||||||
tools:layout="@layout/fragment_counter" />
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/nav_history"
|
|
||||||
android:name="me.zobrist.tichucounter.ui.history.HistoryFragment"
|
|
||||||
android:label="@string/menu_history"
|
|
||||||
tools:layout="@layout/fragment_slideshow" />
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/nav_settings"
|
|
||||||
android:name="me.zobrist.tichucounter.ui.settings.SettingsFragment"
|
|
||||||
android:label="@string/menu_settings" />
|
|
||||||
</navigation>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<!-- Theme Preference -->
|
|
||||||
<string-array name="theme_entries">
|
|
||||||
<item>@string/dark</item>
|
|
||||||
<item>@string/light</item>
|
|
||||||
<item>@string/android_default_text</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="theme_values">
|
|
||||||
<item>dark</item>
|
|
||||||
<item>light</item>
|
|
||||||
<item>default</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<!-- Language Preference -->
|
|
||||||
<string-array name="language_entries">
|
|
||||||
<item>@string/english</item>
|
|
||||||
<item>@string/german</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="language_values">
|
|
||||||
<item>en</item>
|
|
||||||
<item>de</item>
|
|
||||||
</string-array>
|
|
||||||
</resources>
|
|
||||||
@@ -9,7 +9,7 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
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"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
|||||||
@@ -16,6 +16,6 @@ org.gradle.jvmargs=-Xmx2048m
|
|||||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
# Automatically convert third-party libraries to use AndroidX
|
# 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 for this project: "official" or "obsolete":
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user