Compare commits
12 Commits
1.1.0Beta1
...
2.0-Beta1
| Author | SHA1 | Date | |
|---|---|---|---|
| 4d37e77f55 | |||
| 984afb610f | |||
| c3c6c253bc | |||
| 9189d79982 | |||
| ad0236556e | |||
| 52a73bf204 | |||
| 6d0192df18 | |||
| 63f213bc75 | |||
| 68a5d34e45 | |||
| 98ea66772f | |||
| 84a63a2bcb | |||
| c5de57c416 |
@@ -15,6 +15,8 @@ def versionPropertiesFile = rootProject.file("version.properties")
|
|||||||
def keystoreProperties = new Properties()
|
def keystoreProperties = new Properties()
|
||||||
def versionProperties = new Properties()
|
def versionProperties = new Properties()
|
||||||
|
|
||||||
|
def versionMajor = 2
|
||||||
|
def versionMinor = 0
|
||||||
|
|
||||||
// Load your keystore.properties file into the keystoreProperties object.
|
// Load your keystore.properties file into the keystoreProperties object.
|
||||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||||
@@ -29,13 +31,19 @@ android {
|
|||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 33
|
targetSdkVersion 33
|
||||||
versionCode versionProperties["versionCode"].toInteger()
|
versionCode versionProperties["versionCode"].toInteger()
|
||||||
versionName "1.1.0Beta1"
|
versionName "${versionMajor}.${versionMinor}.${versionProperties["versionCode"].toInteger()}"
|
||||||
resConfigs 'de', 'en'
|
resConfigs 'de', 'en'
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
useSupportLibrary true
|
useSupportLibrary true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
javaCompileOptions {
|
||||||
|
annotationProcessorOptions {
|
||||||
|
arguments += ["room.schemaLocation": "$projectDir/schemas".toString()]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
create("release") {
|
create("release") {
|
||||||
@@ -86,7 +94,7 @@ dependencies {
|
|||||||
implementation "androidx.compose.material3:material3:1.0.1"
|
implementation "androidx.compose.material3:material3:1.0.1"
|
||||||
implementation 'com.google.android.play:core-ktx:1.8.1'
|
implementation 'com.google.android.play:core-ktx:1.8.1'
|
||||||
implementation 'com.google.android.play:core-ktx:1.8.1'
|
implementation 'com.google.android.play:core-ktx:1.8.1'
|
||||||
implementation 'com.google.code.gson:gson:2.8.9'
|
implementation 'com.google.code.gson:gson:2.9.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
|
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
|
||||||
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
|
implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
|
||||||
|
|||||||
102
app/schemas/me.zobrist.tichucounter.data.AppDatabase/1.json
Normal file
102
app/schemas/me.zobrist.tichucounter.data.AppDatabase/1.json
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 1,
|
||||||
|
"identityHash": "f07e88c78e54c69c73890495a2121bf4",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "Round",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`gameId` INTEGER NOT NULL, `scoreA` INTEGER NOT NULL, `scoreB` INTEGER NOT NULL, `uid` INTEGER PRIMARY KEY AUTOINCREMENT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "gameId",
|
||||||
|
"columnName": "gameId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "scoreA",
|
||||||
|
"columnName": "scoreA",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "scoreB",
|
||||||
|
"columnName": "scoreB",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "Game",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`active` INTEGER NOT NULL, `nameA` TEXT NOT NULL, `nameB` TEXT NOT NULL, `created` INTEGER NOT NULL, `modified` INTEGER NOT NULL, `uid` INTEGER PRIMARY KEY AUTOINCREMENT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "active",
|
||||||
|
"columnName": "active",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "nameA",
|
||||||
|
"columnName": "nameA",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "nameB",
|
||||||
|
"columnName": "nameB",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "created",
|
||||||
|
"columnName": "created",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "modified",
|
||||||
|
"columnName": "modified",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uid",
|
||||||
|
"columnName": "uid",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"autoGenerate": true,
|
||||||
|
"columnNames": [
|
||||||
|
"uid"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"views": [],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f07e88c78e54c69c73890495a2121bf4')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -75,7 +75,7 @@ abstract class BaseActivity : AppCompatActivity(),
|
|||||||
private fun setLanguage(language: Language) {
|
private fun setLanguage(language: Language) {
|
||||||
val currentLocale = AppCompatDelegate.getApplicationLocales()[0].toString()
|
val currentLocale = AppCompatDelegate.getApplicationLocales()[0].toString()
|
||||||
|
|
||||||
if (language.value != null && language.value != currentLocale) {
|
if (language.value != currentLocale) {
|
||||||
val newLocale = LocaleListCompat.forLanguageTags(language.value)
|
val newLocale = LocaleListCompat.forLanguageTags(language.value)
|
||||||
AppCompatDelegate.setApplicationLocales(newLocale)
|
AppCompatDelegate.setApplicationLocales(newLocale)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class MainActivity : BaseActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
AppTheme() {
|
AppTheme {
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
systemUiController.setStatusBarColor(MaterialTheme.colorScheme.background)
|
systemUiController.setStatusBarColor(MaterialTheme.colorScheme.background)
|
||||||
NavigationDrawer()
|
NavigationDrawer()
|
||||||
@@ -67,10 +67,20 @@ class MainActivity : BaseActivity() {
|
|||||||
fun MyScaffoldLayout(
|
fun MyScaffoldLayout(
|
||||||
drawerState: DrawerState,
|
drawerState: DrawerState,
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
navController: NavHostController
|
navController: NavHostController,
|
||||||
|
showFab: Boolean,
|
||||||
|
fabAction: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
floatingActionButton = {
|
||||||
|
if (showFab) {
|
||||||
|
FloatingActionButton(
|
||||||
|
onClick = { fabAction() }) {
|
||||||
|
Icon(Icons.Outlined.Keyboard, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
topBar = {
|
topBar = {
|
||||||
TopBar(
|
TopBar(
|
||||||
mainViewModel.topBarTitle,
|
mainViewModel.topBarTitle,
|
||||||
@@ -104,20 +114,35 @@ class MainActivity : BaseActivity() {
|
|||||||
NavigationAction { scope.launch { drawerState.open() } }
|
NavigationAction { scope.launch { drawerState.open() } }
|
||||||
}
|
}
|
||||||
composable("history") {
|
composable("history") {
|
||||||
HistoryList(historyViewModel)
|
|
||||||
mainViewModel.topBarActions = emptyList()
|
var openDialog by remember { mutableStateOf(false) }
|
||||||
mainViewModel.topBarIcon = Icons.Outlined.ArrowBack
|
|
||||||
|
HistoryList(historyViewModel, openDialog, { deleteAll ->
|
||||||
|
if (deleteAll) {
|
||||||
|
mainViewModel.deleteAllInactiveGames()
|
||||||
|
}
|
||||||
|
openDialog = false
|
||||||
|
}) { navController.navigate("counter") }
|
||||||
|
mainViewModel.topBarActions = listOf(
|
||||||
|
TopBarAction(
|
||||||
|
Icons.Outlined.DeleteForever,
|
||||||
|
true
|
||||||
|
) {
|
||||||
|
openDialog = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
mainViewModel.topBarIcon = Icons.Outlined.Menu
|
||||||
mainViewModel.topBarTitle = stringResource(R.string.menu_history)
|
mainViewModel.topBarTitle = stringResource(R.string.menu_history)
|
||||||
mainViewModel.topBarNavigationAction =
|
mainViewModel.topBarNavigationAction =
|
||||||
NavigationAction { navController.navigate("counter") }
|
NavigationAction { scope.launch { drawerState.open() } }
|
||||||
}
|
}
|
||||||
composable("settings") {
|
composable("settings") {
|
||||||
SettingsView(settingsViewModel)
|
SettingsView(settingsViewModel)
|
||||||
mainViewModel.topBarActions = emptyList()
|
mainViewModel.topBarActions = emptyList()
|
||||||
mainViewModel.topBarIcon = Icons.Outlined.ArrowBack
|
mainViewModel.topBarIcon = Icons.Outlined.Menu
|
||||||
mainViewModel.topBarTitle = stringResource(R.string.menu_settings)
|
mainViewModel.topBarTitle = stringResource(R.string.menu_settings)
|
||||||
mainViewModel.topBarNavigationAction =
|
mainViewModel.topBarNavigationAction =
|
||||||
NavigationAction { navController.navigate("counter") }
|
NavigationAction { scope.launch { drawerState.open() } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,7 +193,9 @@ class MainActivity : BaseActivity() {
|
|||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
|
|
||||||
val items = listOf(
|
val items = listOf(
|
||||||
Screen("history", Icons.Outlined.List, R.string.menu_history),Screen("settings", Icons.Outlined.Settings, R.string.menu_settings)
|
Screen("counter", Icons.Outlined.Calculate, R.string.app_name),
|
||||||
|
Screen("history", Icons.Outlined.List, R.string.menu_history),
|
||||||
|
Screen("settings", Icons.Outlined.Settings, R.string.menu_settings)
|
||||||
)
|
)
|
||||||
|
|
||||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
@@ -176,6 +203,7 @@ class MainActivity : BaseActivity() {
|
|||||||
|
|
||||||
ModalNavigationDrawer(
|
ModalNavigationDrawer(
|
||||||
drawerState = drawerState,
|
drawerState = drawerState,
|
||||||
|
gesturesEnabled = false,
|
||||||
drawerContent = {
|
drawerContent = {
|
||||||
ModalDrawerSheet {
|
ModalDrawerSheet {
|
||||||
|
|
||||||
@@ -184,7 +212,7 @@ class MainActivity : BaseActivity() {
|
|||||||
NavigationDrawerItem(
|
NavigationDrawerItem(
|
||||||
icon = { Icon(Icons.Outlined.RestartAlt, contentDescription = null) },
|
icon = { Icon(Icons.Outlined.RestartAlt, contentDescription = null) },
|
||||||
colors = NavigationDrawerItemDefaults.colors(
|
colors = NavigationDrawerItemDefaults.colors(
|
||||||
unselectedContainerColor = MaterialTheme.colorScheme.secondaryContainer
|
unselectedContainerColor = MaterialTheme.colorScheme.primaryContainer
|
||||||
),
|
),
|
||||||
label = { Text(stringResource(R.string.newGame)) },
|
label = { Text(stringResource(R.string.newGame)) },
|
||||||
selected = false,
|
selected = false,
|
||||||
@@ -192,25 +220,17 @@ class MainActivity : BaseActivity() {
|
|||||||
scope.launch { drawerState.close() }
|
scope.launch { drawerState.close() }
|
||||||
mainViewModel.newGame()
|
mainViewModel.newGame()
|
||||||
navController.navigate("counter") {
|
navController.navigate("counter") {
|
||||||
// Pop up to the start destination of the graph to
|
|
||||||
// avoid building up a large stack of destinations
|
|
||||||
// on the back stack as users select items
|
|
||||||
popUpTo(navController.graph.findStartDestination().id) {
|
popUpTo(navController.graph.findStartDestination().id) {
|
||||||
saveState = true
|
saveState = true
|
||||||
}
|
}
|
||||||
// Avoid multiple copies of the same destination when
|
|
||||||
// reselecting the same item
|
|
||||||
launchSingleTop = true
|
launchSingleTop = true
|
||||||
// Restore state when reselecting a previously selected item
|
|
||||||
restoreState = true
|
restoreState = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.height(20.dp))
|
Divider(Modifier.padding(top = 20.dp, bottom = 20.dp))
|
||||||
|
|
||||||
Divider()
|
|
||||||
|
|
||||||
items.forEach { screen ->
|
items.forEach { screen ->
|
||||||
NavigationDrawerItem(
|
NavigationDrawerItem(
|
||||||
@@ -237,9 +257,15 @@ class MainActivity : BaseActivity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
content = { MyScaffoldLayout(drawerState, scope, navController) }
|
) {
|
||||||
)
|
MyScaffoldLayout(
|
||||||
|
drawerState,
|
||||||
|
scope,
|
||||||
|
navController,
|
||||||
|
counterViewModel.keyboardHidden
|
||||||
|
) { counterViewModel.keyboardHidden = false }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Screen(val route: String, val icon: ImageVector, @StringRes val resourceId: Int)
|
private class Screen(val route: String, val icon: ImageVector, @StringRes val resourceId: Int)
|
||||||
|
|||||||
@@ -16,4 +16,7 @@ interface DaoBase<T> {
|
|||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
fun delete(entity: T)
|
fun delete(entity: T)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
fun delete(entity: List<T>)
|
||||||
}
|
}
|
||||||
@@ -13,5 +13,4 @@ data class GameAndScore(
|
|||||||
override var gameId: Long,
|
override var gameId: Long,
|
||||||
override var scoreA: Int,
|
override var scoreA: Int,
|
||||||
override var scoreB: Int,
|
override var scoreB: Int,
|
||||||
) : IGame, IRound {
|
) : IGame, IRound
|
||||||
}
|
|
||||||
@@ -6,6 +6,9 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
@Dao
|
@Dao
|
||||||
interface RoundDao : DaoBase<Round> {
|
interface RoundDao : DaoBase<Round> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM round")
|
||||||
|
fun getAll(): List<Round>
|
||||||
|
|
||||||
@Query("SELECT * FROM round WHERE gameId is :gameId")
|
@Query("SELECT * FROM round WHERE gameId is :gameId")
|
||||||
fun getAllForGame(gameId: Long?): List<Round>
|
fun getAllForGame(gameId: Long?): List<Round>
|
||||||
|
|
||||||
@@ -15,6 +18,7 @@ interface RoundDao : DaoBase<Round> {
|
|||||||
"LEFT JOIN game ON game.uid = round.gameId " +
|
"LEFT JOIN game ON game.uid = round.gameId " +
|
||||||
"WHERE game.active == 1"
|
"WHERE game.active == 1"
|
||||||
)
|
)
|
||||||
|
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
|
||||||
fun getRoundSumForActiveGame(): Flow<Round>
|
fun getRoundSumForActiveGame(): Flow<Round>
|
||||||
|
|
||||||
@Query(
|
@Query(
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package me.zobrist.tichucounter.domain
|
package me.zobrist.tichucounter.domain
|
||||||
|
|
||||||
import kotlin.math.abs
|
|
||||||
|
|
||||||
|
|
||||||
fun Int.isMultipleOf5(): Boolean {
|
fun Int.isMultipleOf5(): Boolean {
|
||||||
return (this % 5) == 0
|
return (this % 5) == 0
|
||||||
@@ -11,6 +9,3 @@ fun Int.isMultipleOf100(): Boolean {
|
|||||||
return (this % 100) == 0
|
return (this % 100) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Int.getAbsoluteDifference(other: Int): Int {
|
|
||||||
return abs(this - other)
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
package me.zobrist.tichucounter.domain
|
package me.zobrist.tichucounter.domain
|
||||||
|
|
||||||
class NavigationAction(val aciton: () -> Unit)
|
class NavigationAction(val action: () -> Unit)
|
||||||
@@ -16,13 +16,14 @@ class SettingsAdapter @Inject constructor(@ApplicationContext private val contex
|
|||||||
|
|
||||||
val language: Language
|
val language: Language
|
||||||
get() {
|
get() {
|
||||||
|
return try {
|
||||||
var setting = sharedPreferences.getString(Language::class.simpleName, null)
|
var setting = sharedPreferences.getString(Language::class.simpleName, null)
|
||||||
if (setting == null) {
|
enumValueOf(setting!!)
|
||||||
setCurrentLanguage()
|
} catch (_: NullPointerException) {
|
||||||
setting =
|
val current = getCurrentAppLanguage()
|
||||||
sharedPreferences.getString(Language::class.simpleName, Language.ENGLISH.name)
|
setLanguage(current)
|
||||||
|
current
|
||||||
}
|
}
|
||||||
return enumValueOf(setting!!)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val theme: Theme
|
val theme: Theme
|
||||||
@@ -36,30 +37,29 @@ class SettingsAdapter @Inject constructor(@ApplicationContext private val contex
|
|||||||
return sharedPreferences.getBoolean("keep_screen_on", false)
|
return sharedPreferences.getBoolean("keep_screen_on", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setCurrentLanguage() {
|
private fun getCurrentAppLanguage(): Language {
|
||||||
var setting = when (getApplicationLocales()[0].toString()) {
|
return when (getApplicationLocales()[0].toString()) {
|
||||||
"de" -> Language.GERMAN
|
"de" -> Language.GERMAN
|
||||||
else -> Language.ENGLISH
|
else -> Language.ENGLISH
|
||||||
}
|
}
|
||||||
setLanguage(setting)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setLanguage(language: Language) {
|
fun setLanguage(language: Language) {
|
||||||
val editor = sharedPreferences.edit()
|
val editor = sharedPreferences.edit()
|
||||||
editor.putString(Language::class.simpleName, language.name)
|
editor.putString(Language::class.simpleName, language.name)
|
||||||
editor.commit()
|
editor.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setTheme(theme: Theme) {
|
fun setTheme(theme: Theme) {
|
||||||
val editor = sharedPreferences.edit()
|
val editor = sharedPreferences.edit()
|
||||||
editor.putString(Theme::class.simpleName, theme.name)
|
editor.putString(Theme::class.simpleName, theme.name)
|
||||||
editor.commit()
|
editor.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setKeepScreenOn(setting: Boolean) {
|
fun setKeepScreenOn(setting: Boolean) {
|
||||||
val editor = sharedPreferences.edit()
|
val editor = sharedPreferences.edit()
|
||||||
editor.putBoolean("keep_screen_on", setting)
|
editor.putBoolean("keep_screen_on", setting)
|
||||||
editor.commit()
|
editor.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5,9 +5,6 @@ import javax.inject.Inject
|
|||||||
class Tichu @Inject constructor() {
|
class Tichu @Inject constructor() {
|
||||||
|
|
||||||
fun calculateOtherScore(score: Int): Int? {
|
fun calculateOtherScore(score: Int): Int? {
|
||||||
if (score == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
if (!score.isMultipleOf5()) {
|
if (!score.isMultipleOf5()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -24,6 +21,6 @@ class Tichu @Inject constructor() {
|
|||||||
if (scoreA == null || scoreB == null) {
|
if (scoreA == null || scoreB == null) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return (scoreA!!.isMultipleOf5()) && scoreB!!.isMultipleOf5() && (scoreA!! + scoreB!!).isMultipleOf100()
|
return (scoreA.isMultipleOf5()) && scoreB.isMultipleOf5() && (scoreA + scoreB).isMultipleOf100()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package me.zobrist.tichucounter.framework
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.annotation.MainThread
|
|
||||||
import androidx.lifecycle.LifecycleOwner
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A lifecycle-aware observable that sends only new updates after subscription, used for events like
|
|
||||||
* navigation and Snackbar messages.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* This avoids a common problem with events: on configuration change (like rotation) an update
|
|
||||||
* can be emitted if the observer is active. This LiveData only calls the observable if there's an
|
|
||||||
* explicit call to setValue() or call().
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Note that only one observer is going to be notified of changes.
|
|
||||||
*/
|
|
||||||
class SingleLiveEvent<T> : MutableLiveData<T>() {
|
|
||||||
private val pending = AtomicBoolean(false)
|
|
||||||
|
|
||||||
@MainThread
|
|
||||||
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
|
|
||||||
if (hasActiveObservers()) {
|
|
||||||
Log.w(TAG, "Multiple observers registered but only one will be notified of changes.")
|
|
||||||
}
|
|
||||||
// Observe the internal MutableLiveData
|
|
||||||
super.observe(owner) { t ->
|
|
||||||
if (pending.compareAndSet(true, false)) {
|
|
||||||
observer.onChanged(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainThread
|
|
||||||
override fun setValue(t: T?) {
|
|
||||||
pending.set(true)
|
|
||||||
super.setValue(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used for cases where T is Void, to make calls cleaner.
|
|
||||||
*/
|
|
||||||
@MainThread
|
|
||||||
fun call() {
|
|
||||||
value = null
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "me.zobrist.tichucounter.framework.SingleLiveEvent"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,7 @@ package me.zobrist.tichucounter.repository
|
|||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.take
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import me.zobrist.tichucounter.data.Game
|
import me.zobrist.tichucounter.data.Game
|
||||||
@@ -50,7 +51,7 @@ class GameRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun setActive(id: Long) {
|
suspend fun setActive(id: Long) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
gameDao.setActive(id)
|
gameDao.setActive(id)
|
||||||
gameDao.setOthersInactive(id)
|
gameDao.setOthersInactive(id)
|
||||||
@@ -85,4 +86,34 @@ class GameRepository @Inject constructor(
|
|||||||
gameDao.update(active)
|
gameDao.update(active)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun deleteGame(uid: Long) {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
gameDao.getGameById(uid).take(1).collect() {
|
||||||
|
gameDao.delete(it)
|
||||||
|
val rounds = roundDao.getAllForGame(it.uid)
|
||||||
|
roundDao.delete(rounds)
|
||||||
|
}
|
||||||
|
} catch (_: NullPointerException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun deleteAllInactive() {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
gameDao.getAll().take(1).collect() { games ->
|
||||||
|
|
||||||
|
val activeId = games.first { it.active }.uid
|
||||||
|
val gamesToDelete = games.filter { !it.active }
|
||||||
|
val roundsToDelete = roundDao.getAll().filter { it.gameId != activeId }
|
||||||
|
|
||||||
|
gameDao.delete(gamesToDelete)
|
||||||
|
roundDao.delete(roundsToDelete)
|
||||||
|
}
|
||||||
|
} catch (_: NullPointerException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@file:Suppress("unused", "unused", "unused")
|
||||||
|
|
||||||
package me.zobrist.tichucounter.ui
|
package me.zobrist.tichucounter.ui
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class MainViewModel @Inject constructor(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
roundDao.getForActiveGame().collect() {
|
roundDao.getForActiveGame().collect {
|
||||||
isUndoActionActive = it.isNotEmpty()
|
isUndoActionActive = it.isNotEmpty()
|
||||||
|
|
||||||
if (expectedRoundCount != it.count()) {
|
if (expectedRoundCount != it.count()) {
|
||||||
@@ -51,7 +51,7 @@ class MainViewModel @Inject constructor(
|
|||||||
|
|
||||||
|
|
||||||
fun onNavigateClicked() {
|
fun onNavigateClicked() {
|
||||||
topBarNavigationAction.aciton()
|
topBarNavigationAction.action()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun undoLastRound() {
|
fun undoLastRound() {
|
||||||
@@ -77,14 +77,16 @@ class MainViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearRedoList() {
|
|
||||||
redoRounds.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun newGame() {
|
fun newGame() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
redoRounds.clear()
|
redoRounds.clear()
|
||||||
gameRepository.newGame()
|
gameRepository.newGame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun deleteAllInactiveGames() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
gameRepository.deleteAllInactive()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ private val DarkColors = darkColorScheme(
|
|||||||
@Composable
|
@Composable
|
||||||
fun AppTheme(
|
fun AppTheme(
|
||||||
useDarkTheme: Boolean = isSystemInDarkTheme(),
|
useDarkTheme: Boolean = isSystemInDarkTheme(),
|
||||||
content: @Composable() () -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val dynamicColor = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
|
val dynamicColor = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
|
||||||
|
|||||||
@@ -61,11 +61,11 @@ fun Landscape(viewModel: ICounterViewModel) {
|
|||||||
{ viewModel.digitClicked(it) },
|
{ viewModel.digitClicked(it) },
|
||||||
{ viewModel.addSub100Clicked(it) },
|
{ viewModel.addSub100Clicked(it) },
|
||||||
{ viewModel.deleteClicked() },
|
{ viewModel.deleteClicked() },
|
||||||
{ viewModel.negateClicked() }
|
{ viewModel.negateClicked() },
|
||||||
) { viewModel.submitClicked() }
|
{ viewModel.submitClicked() },
|
||||||
|
{ viewModel.keyboardHidden = true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -89,6 +89,7 @@ fun Portrait(viewModel: ICounterViewModel) {
|
|||||||
Modifier.weight(1f)
|
Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!viewModel.keyboardHidden) {
|
||||||
KeyboardView(
|
KeyboardView(
|
||||||
viewModel.currentScoreA,
|
viewModel.currentScoreA,
|
||||||
viewModel.currentScoreB,
|
viewModel.currentScoreB,
|
||||||
@@ -99,8 +100,10 @@ fun Portrait(viewModel: ICounterViewModel) {
|
|||||||
{ viewModel.digitClicked(it) },
|
{ viewModel.digitClicked(it) },
|
||||||
{ viewModel.addSub100Clicked(it) },
|
{ viewModel.addSub100Clicked(it) },
|
||||||
{ viewModel.deleteClicked() },
|
{ viewModel.deleteClicked() },
|
||||||
{ viewModel.negateClicked() }
|
{ viewModel.negateClicked() },
|
||||||
) { viewModel.submitClicked() }
|
{ viewModel.submitClicked() },
|
||||||
|
{ viewModel.keyboardHidden = true })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +132,7 @@ internal class PreviewViewModel : ICounterViewModel {
|
|||||||
override var requestFocusA: FocusRequester = FocusRequester()
|
override var requestFocusA: FocusRequester = FocusRequester()
|
||||||
override var activeValue: String = currentScoreA
|
override var activeValue: String = currentScoreA
|
||||||
override var inactiveValue: String = currentScoreB
|
override var inactiveValue: String = currentScoreB
|
||||||
|
override var keyboardHidden: Boolean = false
|
||||||
|
|
||||||
override fun giveFocusToAIfNone() {
|
override fun giveFocusToAIfNone() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ interface ICounterViewModel {
|
|||||||
var requestFocusA: FocusRequester
|
var requestFocusA: FocusRequester
|
||||||
var activeValue: String
|
var activeValue: String
|
||||||
var inactiveValue: String
|
var inactiveValue: String
|
||||||
|
var keyboardHidden: Boolean
|
||||||
|
|
||||||
fun giveFocusToAIfNone()
|
fun giveFocusToAIfNone()
|
||||||
fun updateOtherScore()
|
fun updateOtherScore()
|
||||||
@@ -75,6 +76,8 @@ class CounterViewModel @Inject constructor(
|
|||||||
|
|
||||||
override var requestFocusA by mutableStateOf(FocusRequester())
|
override var requestFocusA by mutableStateOf(FocusRequester())
|
||||||
|
|
||||||
|
override var keyboardHidden by mutableStateOf(false)
|
||||||
|
|
||||||
override var activeValue: String
|
override var activeValue: String
|
||||||
get() {
|
get() {
|
||||||
return if (isBFocused) {
|
return if (isBFocused) {
|
||||||
|
|||||||
@@ -5,15 +5,16 @@ import androidx.compose.foundation.layout.*
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.Backspace
|
import androidx.compose.material.icons.outlined.Backspace
|
||||||
import androidx.compose.material.icons.outlined.Check
|
import androidx.compose.material.icons.outlined.Check
|
||||||
|
import androidx.compose.material.icons.outlined.KeyboardHide
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.scale
|
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.focus.onFocusChanged
|
import androidx.compose.ui.focus.onFocusChanged
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
@@ -34,7 +35,8 @@ fun KeyboardView(
|
|||||||
addSub100Clicked: (Int) -> Unit,
|
addSub100Clicked: (Int) -> Unit,
|
||||||
deleteClicked: () -> Unit,
|
deleteClicked: () -> Unit,
|
||||||
negateClicked: () -> Unit,
|
negateClicked: () -> Unit,
|
||||||
submitClicked: () -> Unit
|
submitClicked: () -> Unit,
|
||||||
|
hideKeyboardClicked: () -> Unit
|
||||||
) {
|
) {
|
||||||
val keyboardController = LocalSoftwareKeyboardController.current
|
val keyboardController = LocalSoftwareKeyboardController.current
|
||||||
|
|
||||||
@@ -137,8 +139,8 @@ fun KeyboardView(
|
|||||||
|
|
||||||
Row {
|
Row {
|
||||||
Column(Modifier.weight(1f)) {
|
Column(Modifier.weight(1f)) {
|
||||||
KeyboardTextButton("+/-") {
|
KeyboardIconButton(Icons.Outlined.KeyboardHide) {
|
||||||
negateClicked()
|
hideKeyboardClicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Column(Modifier.weight(1f)) {
|
Column(Modifier.weight(1f)) {
|
||||||
@@ -146,7 +148,13 @@ fun KeyboardView(
|
|||||||
digitClicked("0")
|
digitClicked("0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Column(Modifier.weight(2f)) {
|
|
||||||
|
Column(Modifier.weight(1f)) {
|
||||||
|
KeyboardTextButton("+/-") {
|
||||||
|
negateClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column(Modifier.weight(1f)) {
|
||||||
KeyboardIconButton(Icons.Outlined.Check, enableSubmit) {
|
KeyboardIconButton(Icons.Outlined.Check, enableSubmit) {
|
||||||
submitClicked()
|
submitClicked()
|
||||||
}
|
}
|
||||||
@@ -157,10 +165,24 @@ fun KeyboardView(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun KeyboardTextButton(text: String, onClicked: () -> Unit) {
|
fun KeyboardTextButton(text: String, onClicked: () -> Unit) {
|
||||||
|
|
||||||
|
val configuration = LocalConfiguration.current
|
||||||
|
|
||||||
|
val screenWidth = configuration.screenWidthDp.dp
|
||||||
|
|
||||||
|
val style = if (screenWidth < 350.dp) {
|
||||||
|
MaterialTheme.typography.labelSmall
|
||||||
|
} else {
|
||||||
|
MaterialTheme.typography.labelLarge
|
||||||
|
}
|
||||||
|
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
modifier = Modifier.fillMaxWidth().height(50.dp).padding(2.dp),
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(50.dp)
|
||||||
|
.padding(2.dp),
|
||||||
onClick = { onClicked() },
|
onClick = { onClicked() },
|
||||||
) { Text(text) }
|
) { Text(text, style = style) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -168,7 +190,10 @@ fun KeyboardIconButton(icon: ImageVector, enabled: Boolean = true, onClicked: ()
|
|||||||
|
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onClick = { onClicked() },
|
onClick = { onClicked() },
|
||||||
modifier = Modifier.fillMaxWidth().height(50.dp).padding(2.dp),
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(50.dp)
|
||||||
|
.padding(2.dp),
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
@@ -220,6 +245,7 @@ fun KeyboardViewPreview() {
|
|||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
|
{},
|
||||||
{})
|
{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@@ -28,7 +27,7 @@ fun RoundListView(rounds: List<Round>, modifier: Modifier) {
|
|||||||
|
|
||||||
LazyColumn(state = lazyListState, modifier = modifier) {
|
LazyColumn(state = lazyListState, modifier = modifier) {
|
||||||
itemsIndexed(rounds) { index, item ->
|
itemsIndexed(rounds) { index, item ->
|
||||||
RoundListItem(item, index, lazyListState)
|
RoundListItem(item, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
@@ -38,7 +37,7 @@ fun RoundListView(rounds: List<Round>, modifier: Modifier) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun RoundListItem(round: Round, index: Int, lazyListState: LazyListState) {
|
private fun RoundListItem(round: Round, index: Int) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -51,7 +50,7 @@ private fun RoundListItem(round: Round, index: Int, lazyListState: LazyListState
|
|||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = index.toString(),
|
text = (index + 1).toString(),
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import me.zobrist.tichucounter.ui.AppTheme
|
import me.zobrist.tichucounter.ui.AppTheme
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -18,13 +19,19 @@ fun TeamNamesView(
|
|||||||
updateA: (String) -> Unit,
|
updateA: (String) -> Unit,
|
||||||
updateB: (String) -> Unit
|
updateB: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
Row() {
|
|
||||||
|
val color = TextFieldDefaults.textFieldColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Row {
|
||||||
TextField(
|
TextField(
|
||||||
value = nameA,
|
value = nameA,
|
||||||
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
|
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
|
||||||
onValueChange = { updateA(it) },
|
onValueChange = { updateA(it) },
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f),
|
||||||
|
colors = color
|
||||||
)
|
)
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
@@ -32,7 +39,8 @@ fun TeamNamesView(
|
|||||||
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
|
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
|
||||||
onValueChange = { updateB(it) },
|
onValueChange = { updateB(it) },
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f),
|
||||||
|
colors = color
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,7 @@ import android.content.res.Configuration
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.ElevatedCard
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Surface
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
@@ -19,8 +16,8 @@ import me.zobrist.tichucounter.ui.AppTheme
|
|||||||
@Composable
|
@Composable
|
||||||
fun TeamScoresView(scoreA: Int, scoreB: Int) {
|
fun TeamScoresView(scoreA: Int, scoreB: Int) {
|
||||||
|
|
||||||
ElevatedCard() {
|
ElevatedCard(elevation = CardDefaults.elevatedCardElevation(3.dp)) {
|
||||||
Row() {
|
Row {
|
||||||
Text(
|
Text(
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
text = scoreA.toString(),
|
text = scoreA.toString(),
|
||||||
|
|||||||
@@ -1,78 +1,142 @@
|
|||||||
package me.zobrist.tichucounter.ui.history
|
package me.zobrist.tichucounter.ui.history
|
||||||
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material.icons.outlined.Delete
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material.icons.outlined.OpenInFull
|
||||||
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import me.zobrist.tichucounter.R
|
||||||
import me.zobrist.tichucounter.data.GameAndScore
|
import me.zobrist.tichucounter.data.GameAndScore
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HistoryList(viewModel: HistoryViewModel) {
|
fun HistoryList(
|
||||||
HistoryList(viewModel.gameAndHistory)
|
viewModel: HistoryViewModel,
|
||||||
|
showDeleteDialog: Boolean,
|
||||||
|
onDialogExecuted: (Boolean) -> Unit,
|
||||||
|
navigateToCalculator: () -> Unit
|
||||||
|
) {
|
||||||
|
|
||||||
|
DeleteConfirmDialog(showDeleteDialog, onDialogExecuted)
|
||||||
|
|
||||||
|
HistoryList(viewModel.gameAndHistory,
|
||||||
|
{
|
||||||
|
viewModel.activateGame(it)
|
||||||
|
navigateToCalculator()
|
||||||
|
},
|
||||||
|
{ viewModel.deleteGame(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun DeleteConfirmDialog(show: Boolean = true, onExecuted: (Boolean) -> Unit = {}) {
|
||||||
|
if (show) {
|
||||||
|
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { onExecuted(false) },
|
||||||
|
dismissButton = {
|
||||||
|
TextButton({ onExecuted(false) })
|
||||||
|
{
|
||||||
|
Text(stringResource(R.string.cancel))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton({ onExecuted(true) })
|
||||||
|
{
|
||||||
|
Text(stringResource(R.string.ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = { Text(stringResource(R.string.delete_inactive_title)) },
|
||||||
|
text = { Text(stringResource(R.string.delete_inactive_text)) },
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HistoryList(games: List<GameAndScore>) {
|
fun HistoryList(
|
||||||
|
games: List<GameAndScore>,
|
||||||
|
onOpenClicked: (GameId: Long) -> Unit,
|
||||||
|
onDeleteClicked: (GameId: Long) -> Unit
|
||||||
|
) {
|
||||||
|
Row {
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
items(games) {
|
items(games) {
|
||||||
HistoryListItem(it)
|
HistoryListItem(it, onOpenClicked, onDeleteClicked)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HistoryListItem(game: GameAndScore) {
|
fun HistoryListItem(
|
||||||
|
game: GameAndScore,
|
||||||
|
onOpenClicked: (GameId: Long) -> Unit,
|
||||||
|
onDeleteClicked: (GameId: Long) -> Unit
|
||||||
|
) {
|
||||||
val format =
|
val format =
|
||||||
DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, Locale.getDefault())
|
DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, Locale.getDefault())
|
||||||
|
|
||||||
|
|
||||||
|
val cardColor = if (game.active) {
|
||||||
|
CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.secondaryContainer)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
CardDefaults.cardColors()
|
||||||
|
}
|
||||||
|
|
||||||
Card(
|
Card(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(all = 4.dp),
|
.padding(all = 4.dp),
|
||||||
|
colors = cardColor
|
||||||
) {
|
) {
|
||||||
Column(
|
Row(
|
||||||
Modifier
|
Modifier
|
||||||
.padding(all = 12.dp),
|
.padding(all = 12.dp)
|
||||||
) {
|
) {
|
||||||
Row() {
|
Column(Modifier.weight(4f)) {
|
||||||
Text(
|
Text(
|
||||||
text = game.nameA,
|
text = game.nameA + " vs " + game.nameB,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
style = MaterialTheme.typography.headlineSmall
|
style = MaterialTheme.typography.headlineSmall
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = game.scoreA.toString(),
|
text = game.scoreA.toString() + " : " + game.scoreB.toString(),
|
||||||
style = MaterialTheme.typography.headlineSmall
|
style = MaterialTheme.typography.bodyLarge
|
||||||
)
|
)
|
||||||
}
|
Spacer(modifier = Modifier.padding(5.dp))
|
||||||
Row() {
|
|
||||||
Text(
|
|
||||||
text = game.nameB,
|
|
||||||
style = MaterialTheme.typography.headlineSmall
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = game.scoreB.toString(),
|
|
||||||
style = MaterialTheme.typography.headlineSmall
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Row() {
|
|
||||||
Text(
|
Text(
|
||||||
text = format.format(game.modified),
|
text = format.format(game.modified),
|
||||||
style = MaterialTheme.typography.labelSmall
|
style = MaterialTheme.typography.labelSmall
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Column(
|
||||||
|
Modifier
|
||||||
|
.wrapContentSize()
|
||||||
|
.width(70.dp)
|
||||||
|
) {
|
||||||
|
|
||||||
|
ElevatedButton(onClick = { onOpenClicked(game.gameId) }, enabled = true) {
|
||||||
|
Icon(Icons.Outlined.OpenInFull, null)
|
||||||
|
}
|
||||||
|
ElevatedButton(
|
||||||
|
onClick = { onDeleteClicked(game.gameId) }, enabled = !game.active
|
||||||
|
) {
|
||||||
|
Icon(Icons.Outlined.Delete, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,12 +144,12 @@ fun HistoryListItem(game: GameAndScore) {
|
|||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun HistoryListPreview() {
|
private fun HistoryListPreview() {
|
||||||
val tempData = listOf<GameAndScore>(
|
val tempData = listOf(
|
||||||
GameAndScore(false, "abc", "def", Date(), Date(), 1, 10, 50),
|
GameAndScore(true, "abc", "def", Date(), Date(), 1, 10, 50),
|
||||||
GameAndScore(true, "ADTH", "dogfg", Date(), Date(), 2, 20, 60),
|
GameAndScore(false, "ADTH", "dogfg", Date(), Date(), 2, 20, 60),
|
||||||
GameAndScore(false, "TeamA3", "TeamB3", Date(), Date(), 3, 30, 70),
|
GameAndScore(false, "TeamA3 langer Name", "TeamB3", Date(), Date(), 3, 30, 70),
|
||||||
GameAndScore(false, "TeamA4", "TeamB4", Date(), Date(), 4, 40, 80),
|
GameAndScore(false, "TeamA4", "TeamB4", Date(), Date(), 4, 40, 80),
|
||||||
GameAndScore(false, "TeamA5", "TeamB5", Date(), Date(), 5, 50, 90)
|
GameAndScore(false, "TeamA5", "TeamB5", Date(), Date(), 5, 50, 90)
|
||||||
)
|
)
|
||||||
HistoryList(tempData)
|
HistoryList(tempData, {}) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.zobrist.tichucounter.data.GameAndScore
|
import me.zobrist.tichucounter.data.GameAndScore
|
||||||
import me.zobrist.tichucounter.data.GameDao
|
import me.zobrist.tichucounter.data.GameDao
|
||||||
|
import me.zobrist.tichucounter.repository.GameRepository
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class HistoryViewModel @Inject constructor(
|
class HistoryViewModel @Inject constructor(
|
||||||
private val gameDao: GameDao
|
private val gameDao: GameDao,
|
||||||
|
private val gameRepository: GameRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
var gameAndHistory by mutableStateOf(emptyList<GameAndScore>())
|
var gameAndHistory by mutableStateOf(emptyList<GameAndScore>())
|
||||||
@@ -27,4 +29,17 @@ class HistoryViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun deleteGame(gameId: Long) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
gameRepository.deleteGame(gameId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun activateGame(gameId: Long) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
gameRepository.setActive(gameId)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,10 @@ package me.zobrist.tichucounter.ui.settings
|
|||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.ArrowDropDown
|
import androidx.compose.material.icons.outlined.ArrowDropDown
|
||||||
import androidx.compose.material.icons.outlined.Check
|
import androidx.compose.material.icons.outlined.Check
|
||||||
@@ -52,7 +55,7 @@ fun SettingsView(
|
|||||||
updateLanguage: (Language) -> Unit = {},
|
updateLanguage: (Language) -> Unit = {},
|
||||||
updateTheme: (Theme) -> Unit = {}
|
updateTheme: (Theme) -> Unit = {}
|
||||||
) {
|
) {
|
||||||
Column() {
|
Column {
|
||||||
BooleanSetting(
|
BooleanSetting(
|
||||||
stringResource(R.string.keep_screen_on),
|
stringResource(R.string.keep_screen_on),
|
||||||
valueScreenOn
|
valueScreenOn
|
||||||
@@ -72,7 +75,6 @@ fun SettingsView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BooleanSetting(name: String, value: Boolean, updateValue: (Boolean) -> Unit) {
|
fun BooleanSetting(name: String, value: Boolean, updateValue: (Boolean) -> Unit) {
|
||||||
|
|
||||||
@@ -153,8 +155,8 @@ fun <T> StringSetting(name: String, map: Map<T, Int>, selected: T, onSelected: (
|
|||||||
@Composable
|
@Composable
|
||||||
fun SettingsViewPreview() {
|
fun SettingsViewPreview() {
|
||||||
|
|
||||||
AppTheme() {
|
AppTheme {
|
||||||
Surface() {
|
Surface {
|
||||||
SettingsView()
|
SettingsView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M9,2L7.17,4H4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2H9zm3,15c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M22,16V4c0,-1.1 -0.9,-2 -2,-2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zm-11,-4l2.03,2.71L16,11l4,5H8l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2H4V6H2z" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24.0"
|
|
||||||
android:viewportHeight="24.0">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6zm16,-4H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zm-8,12.5v-9l6,4.5 -6,4.5z" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:tint="#FFFFFF"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="@color/primaryColor"
|
|
||||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:autoMirrored="true"
|
|
||||||
android:tint="#FFFFFF"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="@color/primaryColor"
|
|
||||||
android:pathData="M12.5,8c-2.65,0 -5.05,0.99 -6.9,2.6L2,7v9h9l-3.62,-3.62c1.39,-1.16 3.16,-1.88 5.12,-1.88 3.54,0 6.55,2.31 7.6,5.5l2.37,-0.78C21.08,11.03 17.15,8 12.5,8z" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shape="rectangle">
|
|
||||||
<gradient
|
|
||||||
android:angle="135"
|
|
||||||
android:centerColor="#009688"
|
|
||||||
android:endColor="#00695C"
|
|
||||||
android:startColor="#4DB6AC"
|
|
||||||
android:type="linear" />
|
|
||||||
</shape>
|
|
||||||
@@ -1,29 +1,23 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="clear">Neues Spiel starten</string>
|
|
||||||
<string name="undo">Letzte Runde löschen</string>
|
|
||||||
<string name="choose_theme_text">Theme auswählen</string>
|
<string name="choose_theme_text">Theme auswählen</string>
|
||||||
<string name="keep_screen_on">Bildschirm eingeschaltet lassen</string>
|
<string name="keep_screen_on">Bildschirm eingeschaltet lassen</string>
|
||||||
<string name="confirmNew">Möchten Sie wirklich ein neues Spiel starten?</string>
|
|
||||||
<string name="yes">Ja</string>
|
|
||||||
<string name="no">Nein</string>
|
|
||||||
<string name="back">Zurück</string>
|
|
||||||
<string name="choose_language_text">Sprache wählen</string>
|
<string name="choose_language_text">Sprache wählen</string>
|
||||||
<string name="android_default_text">Android Standard</string>
|
<string name="android_default_text">Android Standard</string>
|
||||||
<string name="english">Englisch</string>
|
<string name="english">Englisch</string>
|
||||||
<string name="german">Deutsch</string>
|
<string name="german">Deutsch</string>
|
||||||
<string name="light">Hell</string>
|
<string name="light">Hell</string>
|
||||||
<string name="dark">Dunkel</string>
|
<string name="dark">Dunkel</string>
|
||||||
<string name="settings">Einstellungen</string>
|
|
||||||
<string name="display">Anzeige</string>
|
|
||||||
<string name="activate">Aktivieren</string>
|
|
||||||
<string name="delete">Löschen</string>
|
|
||||||
<string name="menu_history">Verlauf</string>
|
<string name="menu_history">Verlauf</string>
|
||||||
<string name="menu_settings">Einstellungen</string>
|
<string name="menu_settings">Einstellungen</string>
|
||||||
<string name="menu_counter">Counter</string>
|
|
||||||
<string name="submit">Übermitteln</string>
|
|
||||||
<string name="on">Ein</string>
|
<string name="on">Ein</string>
|
||||||
<string name="off">Aus</string>
|
<string name="off">Aus</string>
|
||||||
<string name="newGame">Neues Spiel</string>
|
<string name="newGame">Neues Spiel</string>
|
||||||
|
<string name="created">"Erstellt: %s "</string>
|
||||||
|
<string name="modified">Bearbeitet: %s</string>
|
||||||
|
<string name="delete_inactive_title">Verlauf löschen</string>
|
||||||
|
<string name="delete_inactive_text">Wirklich den gesamten Verlauf löschen? Diese Aktion kann nicht rückgängig gemacht werden.</string>
|
||||||
|
<string name="cancel">Abbrechen</string>
|
||||||
|
<string name="ok">Ok</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<dimen name="fab_margin">48dp</dimen>
|
|
||||||
</resources>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<dimen name="fab_margin">200dp</dimen>
|
|
||||||
</resources>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<dimen name="fab_margin">48dp</dimen>
|
|
||||||
</resources>
|
|
||||||
@@ -1,12 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="primaryColor">#d50000</color>
|
<color name="primaryColor">#d50000</color>
|
||||||
<color name="primaryLightColor">#ff5131</color>
|
|
||||||
<color name="primaryDarkColor">#9b0000</color>
|
|
||||||
<color name="secondaryColor">#ffccbc</color>
|
|
||||||
<color name="secondaryLightColor">#ffffee</color>
|
|
||||||
<color name="secondaryDarkColor">#cb9b8c</color>
|
|
||||||
<color name="primaryTextColor">#ffffff</color>
|
|
||||||
<color name="secondaryTextColor">#000000</color>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
|
||||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
|
||||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
|
||||||
<dimen name="nav_header_vertical_spacing">8dp</dimen>
|
|
||||||
<dimen name="nav_header_height">176dp</dimen>
|
|
||||||
<dimen name="fab_margin">16dp</dimen>
|
|
||||||
<dimen name="text_margin">16dp</dimen>
|
|
||||||
</resources>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item name="ic_menu_camera" type="drawable">@android:drawable/ic_menu_camera</item>
|
|
||||||
<item name="ic_menu_gallery" type="drawable">@android:drawable/ic_menu_gallery</item>
|
|
||||||
<item name="ic_menu_slideshow" type="drawable">@android:drawable/ic_menu_slideshow</item>
|
|
||||||
<item name="ic_menu_manage" type="drawable">@android:drawable/ic_menu_manage</item>
|
|
||||||
<item name="ic_menu_share" type="drawable">@android:drawable/ic_menu_share</item>
|
|
||||||
<item name="ic_menu_send" type="drawable">@android:drawable/ic_menu_send</item>
|
|
||||||
</resources>
|
|
||||||
@@ -1,34 +1,25 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name" translatable="false">Tichu Counter</string>
|
<string name="app_name" translatable="false">Tichu Counter</string>
|
||||||
<string name="team_a" translatable="false">Team A</string>
|
|
||||||
<string name="team_b" translatable="false">Team B</string>
|
|
||||||
<string name="title_activity_settings" translatable="false">SettingsActivity</string>
|
|
||||||
|
|
||||||
<string name="clear">Start new game</string>
|
|
||||||
<string name="undo">Undo last round</string>
|
|
||||||
<string name="choose_theme_text">Choose theme</string>
|
<string name="choose_theme_text">Choose theme</string>
|
||||||
<string name="keep_screen_on">Keep screen on</string>
|
<string name="keep_screen_on">Keep screen on</string>
|
||||||
<string name="confirmNew">Do you really want to start a new Game?</string>
|
|
||||||
<string name="yes">Yes</string>
|
|
||||||
<string name="no">No</string>
|
|
||||||
<string name="back">Back</string>
|
|
||||||
<string name="choose_language_text">Choose language</string>
|
<string name="choose_language_text">Choose language</string>
|
||||||
<string name="android_default_text">Android Default</string>
|
<string name="android_default_text">Android Default</string>
|
||||||
<string name="english">English</string>
|
<string name="english">English</string>
|
||||||
<string name="german">German</string>
|
<string name="german">German</string>
|
||||||
<string name="light">Light</string>
|
<string name="light">Light</string>
|
||||||
<string name="dark">Dark</string>
|
<string name="dark">Dark</string>
|
||||||
<string name="display">Display</string>
|
|
||||||
<string name="settings">Settings</string>
|
|
||||||
|
|
||||||
<string name="menu_counter">Counter</string>
|
|
||||||
<string name="menu_history">History</string>
|
<string name="menu_history">History</string>
|
||||||
<string name="menu_settings">Settings</string>
|
<string name="menu_settings">Settings</string>
|
||||||
<string name="activate">Activate</string>
|
|
||||||
<string name="delete">Delete</string>
|
|
||||||
<string name="submit">Submit</string>
|
|
||||||
<string name="on">On</string>
|
<string name="on">On</string>
|
||||||
<string name="off">Off</string>
|
<string name="off">Off</string>
|
||||||
<string name="newGame">New Game</string>
|
<string name="newGame">New Game</string>
|
||||||
|
<string name="created">Created: %s</string>
|
||||||
|
<string name="modified">Modified: %s</string>
|
||||||
|
<string name="delete_inactive_title">Delete history</string>
|
||||||
|
<string name="delete_inactive_text">You really want to delete the the history? This action can\'t be undone.</string>
|
||||||
|
<string name="cancel">Cancel</string>
|
||||||
|
<string name="ok">Ok</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar"></style>
|
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar" />
|
||||||
|
|
||||||
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.MaterialComponents.Dark.ActionBar" />
|
|
||||||
|
|
||||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.MaterialComponents.Light" />
|
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user