5 Commits

Author SHA1 Message Date
6977fc45d6 Animate keyboard fadein/fadeout.
All checks were successful
Build Android / build (push) Successful in 3m32s
Closes #27
2026-03-30 19:23:20 +02:00
c6e8d093cb Update more dependencies and remove RepositoryInstrumentedTest 2026-03-30 18:54:03 +02:00
0e041b79cf Update dependencies and Gradle, Minimum SDK bumped to 23
All checks were successful
Build Android / build (push) Successful in 5m7s
2026-03-30 18:24:52 +02:00
ea84eeffc2 Update gradle 2026-01-29 21:57:01 +01:00
8f27412108 Merge pull request 'main' (#59) from main into develop
All checks were successful
Build Android / build (push) Successful in 2m48s
Reviewed-on: #59
2025-07-29 07:37:09 +02:00
22 changed files with 145 additions and 403 deletions

View File

@@ -1,9 +1,8 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.google.dagger.hilt.android'
id 'kotlin-kapt'
id 'com.google.devtools.ksp'
id 'org.jetbrains.kotlin.plugin.compose'
}
// Create a variable called keystorePropertiesFile, and initialize it to your
@@ -29,7 +28,7 @@ android {
defaultConfig {
applicationId "me.zobrist.tichucounter"
minSdkVersion 21
minSdkVersion 23
targetSdkVersion 36
versionCode versionProperties["versionCode"].toInteger()
versionName "${versionMajor}.${versionMinor}.${versionProperties["versionCode"].toInteger()}"
@@ -47,7 +46,7 @@ android {
}
}
signingConfigs {
create("release") {
register("release") {
keyAlias = keystoreProperties["keyAlias"]
keyPassword = keystoreProperties["keyPassword"]
storeFile = file(keystoreProperties["storeFile"])
@@ -65,19 +64,14 @@ android {
buildFeatures {
compose = true
buildConfig true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.14"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
namespace 'me.zobrist.tichucounter'
packagingOptions {
resources {
@@ -88,48 +82,42 @@ android {
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.13.1'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation "androidx.compose.material3:material3:1.2.1"
implementation 'com.google.android.play:review:2.0.1'
implementation 'com.google.android.play:review-ktx:2.0.1'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.7.7'
implementation 'androidx.navigation:navigation-ui-ktx:2.7.7'
implementation "org.jetbrains.kotlin:kotlin-stdlib:2.3.20"
implementation 'androidx.core:core-ktx:1.18.0'
implementation 'androidx.appcompat:appcompat:1.7.1'
implementation "androidx.compose.material3:material3:1.4.0"
implementation 'com.google.android.play:review:2.0.2'
implementation 'com.google.android.play:review-ktx:2.0.2'
implementation 'com.google.code.gson:gson:2.13.2'
implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
implementation 'androidx.navigation:navigation-fragment-ktx:2.9.7'
implementation 'androidx.navigation:navigation-ui-ktx:2.9.7'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.8.4'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.4'
implementation 'androidx.fragment:fragment-ktx:1.8.2'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.10.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.10.0'
implementation 'androidx.fragment:fragment-ktx:1.8.9'
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.4'
implementation 'androidx.compose.material:material-icons-extended:1.6.8'
implementation "com.google.accompanist:accompanist-systemuicontroller:0.27.0"
implementation 'androidx.activity:activity-compose:1.9.1'
implementation "androidx.compose.ui:ui:1.6.8"
implementation "androidx.compose.ui:ui-tooling-preview:1.6.8"
implementation "androidx.compose.runtime:runtime-livedata:1.6.8"
implementation "androidx.navigation:navigation-compose:2.7.7"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4"
implementation 'androidx.recyclerview:recyclerview:1.4.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.10.0'
implementation 'androidx.compose.material:material-icons-extended:1.7.8'
implementation "com.google.accompanist:accompanist-systemuicontroller:0.36.0"
implementation 'androidx.activity:activity-compose:1.13.0'
implementation "androidx.compose.ui:ui:1.10.6"
implementation "androidx.compose.ui:ui-tooling-preview:1.10.6"
implementation "androidx.compose.runtime:runtime-livedata:1.10.6"
implementation "androidx.navigation:navigation-compose:2.9.7"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
implementation "com.google.dagger:hilt-android:2.51.1"
androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.6.8"
debugImplementation "androidx.compose.ui:ui-tooling:1.6.8"
debugImplementation "androidx.compose.ui:ui-test-manifest:1.6.8"
kapt "com.google.dagger:hilt-compiler:2.51.1"
annotationProcessor "androidx.room:room-compiler:2.6.1"
implementation "androidx.room:room-runtime:2.6.1"
ksp "androidx.room:room-compiler:2.6.1"
implementation "androidx.room:room-ktx:2.6.1"
implementation "androidx.multidex:multidex:2.0.1"
api "androidx.navigation:navigation-fragment-ktx:2.7.7"
}
// Allow references to generated code
kapt {
correctErrorTypes true
androidTestImplementation 'androidx.test.ext:junit:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0'
implementation "com.google.dagger:hilt-android:2.59.2"
androidTestImplementation "androidx.compose.ui:ui-test-junit4:1.10.6"
debugImplementation "androidx.compose.ui:ui-tooling:1.10.6"
debugImplementation "androidx.compose.ui:ui-test-manifest:1.10.6"
ksp "com.google.dagger:hilt-compiler:2.59.2"
annotationProcessor "androidx.room:room-compiler:2.8.4"
implementation "androidx.room:room-runtime:2.8.4"
ksp "androidx.room:room-compiler:2.8.4"
implementation "androidx.room:room-ktx:2.8.4"
api "androidx.navigation:navigation-fragment-ktx:2.9.7"
}

View File

@@ -1,275 +0,0 @@
package me.zobrist.tichucounter
import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.runTest
import me.zobrist.tichucounter.data.AppDatabase
import me.zobrist.tichucounter.data.GameDao
import me.zobrist.tichucounter.data.RoundDao
import me.zobrist.tichucounter.repository.GameRepository
import org.junit.After
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.io.IOException
import java.util.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class RepositoryInstrumentedTest {
private lateinit var gameDao: GameDao
private lateinit var roundDao: RoundDao
private lateinit var repository: GameRepository
private lateinit var db: AppDatabase
@Before
fun createDb() {
val context = ApplicationProvider.getApplicationContext<Context>()
db = Room.inMemoryDatabaseBuilder(
context, AppDatabase::class.java
).build()
roundDao = db.roundDao()
gameDao = db.gameDao()
repository = GameRepository(gameDao, roundDao)
}
@After
@Throws(IOException::class)
fun closeDb() {
db.close()
}
@Test
@Throws(Exception::class)
fun gameInitialisation() = runTest {
repository.getActiveGameFlow().take(1).collect {
assertEquals("TeamA", it.game.nameA)
assertEquals("TeamB", it.game.nameB)
assertTrue(it.game.active)
assertEquals(0, it.rounds.count())
}
}
@Test
@Throws(Exception::class)
fun modifyNames() = runTest {
repository.getActiveGameFlow().take(1).collect {
}
repository.updateActiveTeamName(nameA = "aaa")
repository.getActiveGameFlow().take(1).collect {
assertEquals("aaa", it.game.nameA)
assertEquals("TeamB", it.game.nameB)
}
repository.updateActiveTeamName(nameB = "bbb")
repository.getActiveGameFlow().take(1).collect {
assertEquals("aaa", it.game.nameA)
assertEquals("bbb", it.game.nameB)
}
}
@Test
@Throws(Exception::class)
fun newGame() = runTest {
repository.getActiveGameFlow().take(1).collect {
}
repository.newGame()
repository.newGame()
repository.newGame()
repository.newGame()
repository.newGame()
repository.getAllWithRoundFlow().take(1).collect() { it ->
assertEquals(6, it.count())
var uid: Long = 1
it.forEach { game ->
assertEquals(uid++, game.game.uid)
assertEquals(0, game.rounds.count())
}
}
}
@Test
@Throws(Exception::class)
fun setActive() = runTest {
repository.getActiveGameFlow().take(1).collect {
}
repository.newGame()
repository.newGame()
repository.newGame()
repository.newGame()
repository.newGame()
repository.getAllWithRoundFlow().take(1).collect() { it ->
val filtered = it.filter { it.game.active }
assertEquals(1, filtered.count())
assertEquals(6, filtered.first().game.uid)
}
repository.setActive(2)
repository.getAllWithRoundFlow().take(1).collect() { it ->
val filtered = it.filter { it.game.active }
assertEquals(1, filtered.count())
assertEquals(2, filtered.first().game.uid)
}
}
@Test
@Throws(Exception::class)
fun addRoundToActiveGame() = runTest {
repository.getActiveGameFlow().take(1).collect {
}
repository.newGame()
repository.newGame()
repository.newGame()
repository.newGame()
repository.newGame()
repository.addRoundToActiveGame(1, 1)
repository.addRoundToActiveGame(2, 2)
repository.addRoundToActiveGame(3, 3)
repository.addRoundToActiveGame(4, 4)
repository.addRoundToActiveGame(5, 5)
repository.addRoundToActiveGame(6, 6)
repository.getAllWithRoundFlow().take(1).collect() { it ->
val filtered = it.filter { it.rounds.isNotEmpty() }
assertEquals(1, filtered.count())
assertEquals(6, filtered.first().rounds.count())
}
}
@Test
@Throws(Exception::class)
fun lastRound() = runTest {
repository.getActiveGameFlow().take(1).collect {
}
repository.newGame()
repository.newGame()
repository.newGame()
repository.newGame()
repository.newGame()
assertNull(repository.getLastRound())
repository.addRoundToActiveGame(1, 1)
repository.addRoundToActiveGame(2, 2)
repository.addRoundToActiveGame(3, 3)
repository.addRoundToActiveGame(4, 4)
repository.addRoundToActiveGame(5, 5)
repository.addRoundToActiveGame(6, 6)
var lastRound = repository.getLastRound()
assertEquals(6, lastRound?.scoreA)
assertEquals(6, lastRound?.scoreB)
repository.deleteLastRound()
lastRound = repository.getLastRound()
assertEquals(5, lastRound?.scoreA)
assertEquals(5, lastRound?.scoreB)
repository.deleteLastRound()
repository.deleteLastRound()
repository.deleteLastRound()
repository.deleteLastRound()
repository.deleteLastRound()
assertNull(repository.getLastRound())
// No error thrown
repository.deleteLastRound()
}
@Test
@Throws(Exception::class)
fun deleteInactive() = runTest {
repository.getActiveGameFlow().take(1).collect {
}
for (i in 1..6) {
repository.newGame()
repository.addRoundToActiveGame(1, 1)
repository.addRoundToActiveGame(2, 2)
repository.addRoundToActiveGame(3, 3)
repository.addRoundToActiveGame(4, 4)
repository.addRoundToActiveGame(5, 5)
repository.addRoundToActiveGame(6, 6)
}
assertEquals(6 * 6, roundDao.getAll().count())
repository.deleteAllInactive()
// Consists of two transactions. Delete games then delete rounds.
repository.getAllWithRoundFlow().take(1).collect() { it ->
assertEquals(1, it.count())
assertEquals(6, it.first().rounds.count())
}
assertEquals(6, roundDao.getAll().count())
}
@Test
@Throws(Exception::class)
fun deleteById() = runTest {
repository.getActiveGameFlow().take(1).collect {
}
for (i in 1..6) {
repository.newGame()
repository.addRoundToActiveGame(1, 1)
repository.addRoundToActiveGame(2, 2)
repository.addRoundToActiveGame(3, 3)
repository.addRoundToActiveGame(4, 4)
repository.addRoundToActiveGame(5, 5)
repository.addRoundToActiveGame(6, 6)
}
// Non existing Id
repository.deleteGame(10)
repository.getAllWithRoundFlow().take(1).collect() { it ->
assertEquals(7, it.count())
}
// Non existing Id
val toDelete: Long = 3
repository.deleteGame(toDelete)
repository.getAllWithRoundFlow().take(1).collect() { it ->
assertEquals(6, it.count())
assertEquals(0, it.count { it.game.uid == toDelete })
}
}
}

View File

@@ -53,7 +53,6 @@ import me.zobrist.tichucounter.domain.SettingsAdapter
import me.zobrist.tichucounter.domain.Theme
import me.zobrist.tichucounter.domain.TopBarAction
import me.zobrist.tichucounter.domain.TopBarState
import me.zobrist.tichucounter.domain.navigate
import me.zobrist.tichucounter.repository.GameRepository
import me.zobrist.tichucounter.ui.AppTheme
import me.zobrist.tichucounter.ui.MainViewModel
@@ -198,7 +197,7 @@ class MainActivity : AppCompatActivity() {
drawerState.close()
}
navController.navigate(it)
navController.navigate(it.name)
}
}
) {
@@ -292,7 +291,7 @@ class MainActivity : AppCompatActivity() {
HistoryList(
historyViewModel,
snackbarHostState
) { navController.navigate(Route.COUNTER) }
) { navController.navigate(Route.COUNTER.name) }
}
composable(Route.SETTINGS.name) {
topBarState =

View File

@@ -7,27 +7,28 @@ import com.google.android.play.core.review.ReviewManagerFactory
import dagger.hilt.android.qualifiers.ActivityContext
import java.util.Date
import javax.inject.Inject
import androidx.core.content.edit
class ReviewService @Inject constructor(@ActivityContext private val appContext: Context) {
private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext)
private val THREE_MONTHS: Long = 7776000000
private val threeMonths: Long = 7776000000
private var requestCalled: Int
get() = sharedPreferences.getInt("requestCalled", 0)
set(value) {
val editor = sharedPreferences.edit()
editor.putInt("requestCalled", value)
editor.apply()
sharedPreferences.edit {
putInt("requestCalled", value)
}
}
private var nextReviewedDate: Date
get() = Date(sharedPreferences.getLong("lastReviewedDate", 0))
set(value) {
val editor = sharedPreferences.edit()
editor.putLong("lastReviewedDate", value.time)
editor.apply()
sharedPreferences.edit {
putLong("lastReviewedDate", value.time)
}
}
fun request() {
@@ -36,7 +37,7 @@ class ReviewService @Inject constructor(@ActivityContext private val appContext:
if (requestCalled >= 3) {
if (nextReviewedDate.time < System.currentTimeMillis()) {
requestCalled = 0
nextReviewedDate = Date(System.currentTimeMillis() + THREE_MONTHS)
nextReviewedDate = Date(System.currentTimeMillis() + threeMonths)
val manager = ReviewManagerFactory.create(appContext)

View File

@@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
import javax.inject.Singleton
import androidx.core.content.edit
enum class Theme { DEFAULT, DARK, LIGHT }
enum class Language(val value: LocaleListCompat) {
@@ -93,20 +94,20 @@ class SettingsAdapter @Inject constructor(@ApplicationContext private val contex
}
private fun updatePreference(name: String?, value: String) {
val editor = sharedPreferences.edit()
editor.putString(name, value)
editor.apply()
sharedPreferences.edit {
putString(name, value)
}
}
private fun updatePreference(name: String?, value: Boolean) {
val editor = sharedPreferences.edit()
editor.putBoolean(name, value)
editor.apply()
sharedPreferences.edit {
putBoolean(name, value)
}
}
private fun updatePreference(name: String?, value: Int) {
val editor = sharedPreferences.edit()
editor.putInt(name, value)
editor.apply()
sharedPreferences.edit {
putInt(name, value)
}
}
}

View File

@@ -117,17 +117,15 @@ class GameRepository @Inject constructor(
}
suspend fun restoreLastDeletedGame() {
if (deletedGame == null) {
return
}
val revert = deletedGame!!
val snapshot = deletedGame ?: return
deletedGame = null
withContext(Dispatchers.IO) {
gameDao.insert(revert.game)
val uid = gameDao.insert(snapshot.game.copy(uid = 0))
revert.rounds.forEach {
roundDao.insert(it)
snapshot.rounds.forEach {
roundDao.insert(Round(uid, it.scoreA, it.scoreB))
}
}
}

View File

@@ -1,6 +1,12 @@
package me.zobrist.tichucounter.ui.counter
import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.scaleIn
import androidx.compose.animation.scaleOut
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.material.icons.Icons
@@ -17,6 +23,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@@ -75,10 +82,21 @@ fun Landscape(viewModel: ICounterViewModel) {
Modifier.weight(1f)
)
}
if (!viewModel.keyboardHidden) {
Column(Modifier.weight(1f)) {
KeyBoardView(viewModel = viewModel)
}
AnimatedVisibility(
visible = !viewModel.keyboardHidden,
enter = fadeIn(animationSpec = tween(100)) + scaleIn(
animationSpec = tween(100),
initialScale = 0.8f,
transformOrigin = TransformOrigin(1f, 1f)
),
exit = fadeOut(animationSpec = tween(100)) + scaleOut(
animationSpec = tween(100),
targetScale = 0.8f,
transformOrigin = TransformOrigin(1f, 1f)
),
modifier = Modifier.weight(1f)
) {
KeyBoardView(viewModel = viewModel)
}
}
}
@@ -106,7 +124,19 @@ fun Portrait(viewModel: ICounterViewModel) {
Modifier.weight(1f)
)
if (!viewModel.keyboardHidden) {
AnimatedVisibility(
visible = !viewModel.keyboardHidden,
enter = fadeIn(animationSpec = tween(100)) + scaleIn(
animationSpec = tween(100),
initialScale = 0.8f,
transformOrigin = TransformOrigin(1f, 1f)
),
exit = fadeOut(animationSpec = tween(100)) + scaleOut(
animationSpec = tween(100),
targetScale = 0.8f,
transformOrigin = TransformOrigin(1f, 1f)
)
) {
KeyBoardView(viewModel = viewModel)
}
}

View File

@@ -1,5 +1,6 @@
package me.zobrist.tichucounter.ui.counter
import android.annotation.SuppressLint
import android.content.res.Configuration
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
@@ -343,6 +344,7 @@ fun CenteredTextField(
}
@SuppressLint("RememberInComposition")
@Preview(name = "Light Mode")
@Preview(name = "Dark Mode", uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true)
@Composable

View File

@@ -3,7 +3,6 @@ package me.zobrist.tichucounter.ui.history
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -26,7 +25,6 @@ import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Badge
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SnackbarDuration
@@ -153,7 +151,6 @@ fun DeleteConfirmDialog(show: Boolean = true, onExecuted: (Boolean) -> Unit = {}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun HistoryList(
games: List<GameWithScores>,
@@ -166,18 +163,18 @@ fun HistoryList(
LazyColumn(state = lazyListState) {
items(
items = games,
key = { it.hashCode() }) {
key = { it.game.uid} ) {
if (it.game.active) {
HistoryListItem(
it,
Modifier
.animateItemPlacement()
.animateItem()
.padding(2.dp)
)
} else {
DismissibleHistoryListItem(
it,
Modifier.animateItemPlacement(),
Modifier.animateItem(),
onOpenClicked,
onDeleteClicked
)
@@ -190,7 +187,7 @@ fun HistoryList(
.padding(start = 4.dp, end = 4.dp, top = 10.dp)
.align(CenterVertically)
.fillMaxWidth()
.animateItemPlacement(),
.animateItem(),
onClick = { onDeleteAllClicked() }) {
Icon(imageVector = Icons.Outlined.DeleteForever, contentDescription = null)
Text(text = stringResource(id = R.string.deleteAll))
@@ -202,7 +199,6 @@ fun HistoryList(
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DismissibleHistoryListItem(
game: GameWithScores,
@@ -212,32 +208,25 @@ fun DismissibleHistoryListItem(
) {
val density = LocalDensity.current
val dismissState =
rememberSwipeToDismissBoxState(positionalThreshold = { with(density) { 100.dp.toPx() } },
confirmValueChange = {
if (it == SwipeToDismissBoxValue.EndToStart) {
onDeleteClicked(game.game.uid)
}
if (it == SwipeToDismissBoxValue.StartToEnd) {
onOpenClicked(game.game.uid)
}
true
})
val dismissState = rememberSwipeToDismissBoxState(positionalThreshold = { with(density) { 100.dp.toPx() } })
SwipeToDismissBox(
modifier = modifier,
state = dismissState,
enableDismissFromEndToStart = true,
enableDismissFromStartToEnd = true,
backgroundContent = {
ItemBackground(dismissState.targetValue)
}, content = {
HistoryListItem(game = game, modifier = Modifier.padding(2.dp))
backgroundContent = { ItemBackground(dismissState.targetValue) },
content = { HistoryListItem(game = game, modifier = Modifier.padding(2.dp)) },
onDismiss = {
when(it)
{
SwipeToDismissBoxValue.EndToStart -> onDeleteClicked(game.game.uid)
SwipeToDismissBoxValue.StartToEnd -> onOpenClicked(game.game.uid)
else -> {}
}
})
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ItemBackground(
dismissBoxValue: SwipeToDismissBoxValue
@@ -248,7 +237,7 @@ fun ItemBackground(
SwipeToDismissBoxValue.StartToEnd -> MaterialTheme.colorScheme.primary
else -> MaterialTheme.colorScheme.background
}, label = ""
}
)
val textColor by animateColorAsState(
when (dismissBoxValue) {
@@ -256,10 +245,10 @@ fun ItemBackground(
SwipeToDismissBoxValue.StartToEnd -> MaterialTheme.colorScheme.onPrimary
else -> MaterialTheme.colorScheme.onBackground
}, label = ""
}
)
val scale by animateFloatAsState(
if (dismissBoxValue == SwipeToDismissBoxValue.Settled) 0.75f else 1f, label = ""
if (dismissBoxValue == SwipeToDismissBoxValue.Settled) 0.75f else 1f
)
Box(
@@ -299,7 +288,6 @@ fun ItemBackground(
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Preview
@Composable
private fun BackgroundPreview() {

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -20,7 +20,6 @@
<string name="delete">Löschen</string>
<string name="deleteAll">Alle löschen</string>
<string name="active">Aktives Spiel</string>
<string name="inactive">Vergangene Spiele</string>
<string name="menu_counter">Counter</string>
<string name="menu_about">About</string>
<string name="contact_us">Schreib uns</string>

View File

@@ -23,7 +23,6 @@
<string name="delete">Delete</string>
<string name="deleteAll">Delete all</string>
<string name="active">Current Game</string>
<string name="inactive">Old Games</string>
<string name="menu_counter">Counter</string>
<string name="menu_about">About</string>
<string name="contact_us">Contact us</string>

View File

@@ -1,12 +1,11 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.9.24"
ext.kotlin_version = '2.2.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.11.0'
classpath 'com.android.tools.build:gradle:9.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
@@ -15,9 +14,10 @@ buildscript {
}
plugins {
id 'com.google.dagger.hilt.android' version '2.51.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
id 'com.google.devtools.ksp' version '1.9.24-1.0.20' apply false
id 'com.google.dagger.hilt.android' version '2.59' apply false
id 'org.jetbrains.kotlin.android' version '2.3.20' apply false
id 'com.google.devtools.ksp' version '2.3.5' apply false
id 'org.jetbrains.kotlin.plugin.compose' version '2.3.20' apply false
}
allprojects {

View File

@@ -19,6 +19,7 @@ android.useAndroidX=true
android.enableJetifier=false
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=true
android.nonFinalResIds=false
android.uniquePackageNames=false
android.dependency.useConstraints=true
android.r8.strictFullModeForKeepRules=false

View File

@@ -0,0 +1,13 @@
#This file is generated by updateDaemonJvm
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/536afcd1dff540251f85e5d2c80458cf/redirect
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/ecd23fd7707c683afbcd6052998cb6a9/redirect
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/536afcd1dff540251f85e5d2c80458cf/redirect
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/ecd23fd7707c683afbcd6052998cb6a9/redirect
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/e99bae143b75f9a10ead10248f02055e/redirect
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/04e088f8677de3b384108493cc9481d0/redirect
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/536afcd1dff540251f85e5d2c80458cf/redirect
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/ecd23fd7707c683afbcd6052998cb6a9/redirect
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/248ffb1098f61659502d0c09aa348294/redirect
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/056dc25d3b9d168ede8b94d3d2f99942/redirect
toolchainVendor=JETBRAINS
toolchainVersion=21

View File

@@ -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-8.13-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-all.zip

View File

@@ -1,2 +1,5 @@
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
}
include ':app'
rootProject.name = "Tichu Counter"