Skip to content

Commit 3941dd1

Browse files
authored
Merge pull request #4 from hegocre/feature/rewrite
Rewrite mobile version
2 parents 3e6ce5b + 121b528 commit 3941dd1

31 files changed

Lines changed: 274 additions & 247 deletions

build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
// Top-level build file where you can add configuration options common to all sub-projects/modules.
22

33
buildscript {
4-
ext.kotlin_version = '1.6.10'
4+
ext.kotlin_version = '1.7.20'
55
ext.lifecycle_version = '2.5.1'
6+
ext.compose_version = '1.3.3'
67
repositories {
78
google()
89
mavenCentral()
910
}
1011
dependencies {
11-
classpath 'com.android.tools.build:gradle:7.3.0'
12+
classpath 'com.android.tools.build:gradle:7.4.1'
1213
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
1314

1415
// NOTE: Do not place your application dependencies here; they belong

gradle.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@
1717
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
1818
# org.gradle.parallel=true
1919
android.enableJetifier=true
20-
android.useAndroidX=true
20+
android.useAndroidX=true
21+
android.enableR8.fullMode=true

gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip

mobile/build.gradle

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ android {
1010
applicationId "es.hegocre.scorecounter"
1111
minSdkVersion 24
1212
targetSdkVersion 33
13-
versionCode 311050000
14-
versionName "1.0.5"
13+
versionCode 311100001
14+
versionName "1.1.0"
15+
resConfigs 'ca', 'es', 'en'
1516
}
1617

1718
buildTypes {
@@ -24,28 +25,37 @@ android {
2425
}
2526

2627
buildFeatures {
27-
viewBinding true
28-
dataBinding true
28+
compose true
2929
}
3030

3131
compileOptions {
32-
sourceCompatibility JavaVersion.VERSION_1_8
33-
targetCompatibility JavaVersion.VERSION_1_8
32+
sourceCompatibility JavaVersion.VERSION_11
33+
targetCompatibility JavaVersion.VERSION_11
34+
}
35+
36+
composeOptions {
37+
kotlinCompilerExtensionVersion '1.3.2'
3438
}
3539

3640
kotlinOptions {
37-
jvmTarget = '1.8'
41+
jvmTarget = '11'
3842
}
3943
namespace 'es.hegocre.scorecounter'
4044
}
4145

4246
dependencies {
4347
implementation fileTree(include: ['*.jar'], dir: 'libs')
44-
implementation 'androidx.preference:preference-ktx:1.2.0'
45-
testImplementation 'junit:junit:4.13.2'
46-
implementation 'androidx.appcompat:appcompat:1.5.1'
48+
49+
//Android dependencies
4750
implementation 'androidx.core:core-ktx:1.9.0'
48-
//noinspection KtxExtensionAvailable
49-
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
50-
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
51+
52+
//Compose
53+
implementation 'androidx.activity:activity-compose:1.6.1'
54+
implementation 'androidx.compose.material3:material3:1.0.1'
55+
implementation "androidx.compose.ui:ui:$compose_version"
56+
57+
testImplementation 'junit:junit:4.13.2'
58+
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
59+
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
60+
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
5161
}

mobile/src/main/AndroidManifest.xml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools">
34

45
<application
56
android:allowBackup="true"
7+
android:dataExtractionRules="@xml/data_extraction_rules"
68
android:fullBackupContent="@xml/backup_descriptor"
79
android:icon="@mipmap/ic_launcher"
810
android:label="@string/app_name"
911
android:supportsRtl="true"
10-
android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen">
12+
android:theme="@android:style/Theme.Material.Light.NoActionBar"
13+
tools:targetApi="s">
1114
<activity
1215
android:name="es.hegocre.scorecounter.MainActivity"
1316
android:configChanges="orientation|screenSize|keyboardHidden"
1417
android:exported="true"
1518
android:screenOrientation="sensorLandscape"
16-
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
19+
android:theme="@android:style/Theme.Material.Light.NoActionBar">
1720
<intent-filter>
1821
<action android:name="android.intent.action.MAIN" />
1922
<category android:name="android.intent.category.LAUNCHER" />
17.5 KB
Loading
-13.6 KB
Binary file not shown.
Lines changed: 128 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,152 @@
11
package es.hegocre.scorecounter
22

3+
import android.content.Context
4+
import android.os.Build
35
import android.os.Bundle
4-
import android.view.View
5-
import androidx.appcompat.app.AlertDialog
6-
import androidx.appcompat.app.AppCompatActivity
6+
import androidx.activity.ComponentActivity
7+
import androidx.activity.compose.setContent
8+
import androidx.activity.viewModels
9+
import androidx.compose.foundation.background
10+
import androidx.compose.foundation.gestures.detectTapGestures
11+
import androidx.compose.foundation.isSystemInDarkTheme
12+
import androidx.compose.foundation.layout.*
13+
import androidx.compose.material3.*
14+
import androidx.compose.runtime.Composable
15+
import androidx.compose.runtime.getValue
16+
import androidx.compose.runtime.mutableStateOf
17+
import androidx.compose.runtime.saveable.rememberSaveable
18+
import androidx.compose.runtime.setValue
19+
import androidx.compose.ui.Alignment
20+
import androidx.compose.ui.Modifier
21+
import androidx.compose.ui.geometry.Offset
22+
import androidx.compose.ui.graphics.Color
23+
import androidx.compose.ui.input.pointer.pointerInput
24+
import androidx.compose.ui.platform.LocalContext
25+
import androidx.compose.ui.res.stringResource
26+
import androidx.compose.ui.unit.dp
27+
import androidx.compose.ui.unit.sp
728
import androidx.core.view.WindowCompat
829
import androidx.core.view.WindowInsetsCompat
930
import androidx.core.view.WindowInsetsControllerCompat
10-
import androidx.databinding.DataBindingUtil
11-
import androidx.preference.PreferenceManager
12-
import es.hegocre.scorecounter.data.Score
13-
import es.hegocre.scorecounter.databinding.ActivityScoreBinding
14-
15-
class MainActivity : AppCompatActivity() {
16-
private lateinit var binding: ActivityScoreBinding
1731

32+
class MainActivity : ComponentActivity() {
1833
override fun onCreate(savedInstanceState: Bundle?) {
1934
super.onCreate(savedInstanceState)
20-
binding = DataBindingUtil.setContentView(this, R.layout.activity_score)
2135

22-
Score.setSharedPreferences(PreferenceManager.getDefaultSharedPreferences(this).also {
23-
if (it.getBoolean("firstRun", true)) {
24-
showTutorialDialog()
25-
it.edit().putBoolean("firstRun", false).apply()
36+
val scoreViewModel by viewModels<ScoreViewModel>()
37+
38+
WindowCompat.setDecorFitsSystemWindows(window, false)
39+
40+
setContent {
41+
val darkTheme = isSystemInDarkTheme()
42+
val colorScheme = when {
43+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
44+
val context = LocalContext.current
45+
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(
46+
context
47+
)
48+
}
49+
darkTheme -> darkColorScheme()
50+
else -> lightColorScheme()
51+
}
52+
MaterialTheme(colorScheme = colorScheme) {
53+
Surface(color = if (darkTheme) Color.Black else MaterialTheme.colorScheme.surface) {
54+
val context = LocalContext.current
55+
56+
var showTutorialDialog by rememberSaveable {
57+
mutableStateOf(
58+
context.getSharedPreferences("preferences", Context.MODE_PRIVATE)
59+
.getBoolean("isFirstLaunch", true)
60+
)
61+
}
62+
63+
Row {
64+
ScoreView(
65+
score = scoreViewModel.score1,
66+
onScoreAdd = { scoreViewModel.score1++ },
67+
onScoreSub = { scoreViewModel.score1-- },
68+
onScoreReset = { scoreViewModel.score1 = 0 },
69+
modifier = Modifier
70+
.weight(1f)
71+
.fillMaxHeight()
72+
)
73+
Spacer(
74+
modifier = Modifier
75+
.fillMaxHeight()
76+
.width(4.dp)
77+
.background(MaterialTheme.colorScheme.onSurface)
78+
)
79+
ScoreView(
80+
score = scoreViewModel.score2,
81+
onScoreAdd = { scoreViewModel.score2++ },
82+
onScoreSub = { scoreViewModel.score2-- },
83+
onScoreReset = { scoreViewModel.score2 = 0 },
84+
modifier = Modifier
85+
.weight(1f)
86+
.fillMaxHeight()
87+
)
88+
}
89+
90+
if (showTutorialDialog) {
91+
context.getSharedPreferences("preferences", Context.MODE_PRIVATE)
92+
.edit().putBoolean("isFirstLaunch", false).apply()
93+
94+
AlertDialog(
95+
onDismissRequest = { showTutorialDialog = false },
96+
confirmButton = {
97+
TextButton(onClick = { showTutorialDialog = false }) {
98+
Text(text = stringResource(id = android.R.string.ok))
99+
}
100+
},
101+
title = { Text(text = stringResource(id = R.string.dialog_tutorial_title)) },
102+
text = { Text(text = stringResource(id = R.string.dialog_tutorial_message)) }
103+
)
104+
}
105+
}
26106
}
27-
})
28-
Score("score1").let { score ->
29-
binding.score1 = score
30-
loadScore(score, binding.add1Layout, binding.sub1Layout)
31-
}
32-
Score("score2").let { score ->
33-
binding.score2 = score
34-
loadScore(score, binding.add2Layout, binding.sub2Layout)
35107
}
36108
}
37109

38-
private fun hideSystemUI() {
110+
override fun onResume() {
111+
super.onResume()
39112
WindowCompat.setDecorFitsSystemWindows(window, false)
40-
WindowInsetsControllerCompat(window, binding.root).let { controller ->
113+
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
41114
controller.hide(WindowInsetsCompat.Type.statusBars() or WindowInsetsCompat.Type.navigationBars())
42115
controller.systemBarsBehavior =
43116
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
44117
}
45118
}
119+
}
46120

47-
override fun onResume() {
48-
hideSystemUI()
49-
super.onResume()
50-
}
51-
52-
private fun loadScore(score: Score, addLayout: View, subLayout: View) {
53-
addLayout.setOnClickListener {
54-
score.inc()
121+
@Composable
122+
fun ScoreView(
123+
score: Int,
124+
onScoreAdd: (Offset) -> Unit,
125+
onScoreSub: (Offset) -> Unit,
126+
onScoreReset: (Offset) -> Unit,
127+
modifier: Modifier = Modifier
128+
) {
129+
Box(modifier = modifier, contentAlignment = Alignment.Center) {
130+
Text(
131+
text = "$score",
132+
fontSize = 70.sp,
133+
color = MaterialTheme.colorScheme.onSurface
134+
)
135+
Column(modifier = Modifier.fillMaxSize()) {
136+
Box(modifier = Modifier
137+
.fillMaxWidth()
138+
.weight(1f)
139+
.pointerInput(Unit) {
140+
detectTapGestures(onTap = onScoreAdd, onLongPress = onScoreReset)
141+
}
142+
)
143+
Box(modifier = Modifier
144+
.fillMaxWidth()
145+
.weight(1f)
146+
.pointerInput(Unit) {
147+
detectTapGestures(onTap = onScoreSub, onLongPress = onScoreReset)
148+
}
149+
)
55150
}
56-
addLayout.setOnLongClickListener {
57-
score.reset()
58-
true
59-
}
60-
subLayout.setOnClickListener {
61-
score.dec()
62-
}
63-
subLayout.setOnLongClickListener {
64-
score.reset()
65-
true
66-
}
67-
}
68-
69-
private fun showTutorialDialog() {
70-
AlertDialog.Builder(this)
71-
.setTitle(R.string.dialog_tutorial_title)
72-
.setMessage(R.string.dialog_tutorial_message)
73-
.setPositiveButton(android.R.string.ok, null)
74-
.show()
75151
}
76152
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package es.hegocre.scorecounter
2+
3+
import android.app.Application
4+
import android.content.Context
5+
import androidx.compose.runtime.mutableStateOf
6+
import androidx.lifecycle.AndroidViewModel
7+
8+
class ScoreViewModel(application: Application) : AndroidViewModel(application) {
9+
private val _preferencesManager =
10+
application.getSharedPreferences("scores", Context.MODE_PRIVATE)
11+
12+
private val _score1 = mutableStateOf(_preferencesManager.getInt("score1", 0))
13+
var score1: Int
14+
get() = _score1.value
15+
set(value) {
16+
_score1.value = value
17+
_preferencesManager.edit().putInt("score1", value).apply()
18+
}
19+
private val _score2 = mutableStateOf(_preferencesManager.getInt("score2", 0))
20+
var score2: Int
21+
get() = _score2.value
22+
set(value) {
23+
_score2.value = value
24+
_preferencesManager.edit().putInt("score2", value).apply()
25+
}
26+
}

mobile/src/main/java/es/hegocre/scorecounter/data/Score.kt

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)