Skip to content

Commit 80a7ef9

Browse files
WIP
1 parent 18a2c3d commit 80a7ef9

File tree

7 files changed

+210
-524
lines changed

7 files changed

+210
-524
lines changed

app/build.gradle.kts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ plugins {
55
id("com.android.application")
66
id("com.github.spotbugs")
77
id("org.jetbrains.kotlin.android")
8+
id("org.jetbrains.kotlin.plugin.compose") version "2.1.20"
89
}
910

1011
spotbugs {
@@ -51,6 +52,7 @@ android {
5152

5253
buildFeatures {
5354
buildConfig = true
55+
compose = true
5456
viewBinding = true
5557
}
5658

@@ -110,6 +112,7 @@ android {
110112

111113
dependencies {
112114
// AndroidX
115+
implementation("androidx.activity:activity-compose:1.10.1")
113116
implementation("androidx.appcompat:appcompat:1.7.0")
114117
implementation("androidx.constraintlayout:constraintlayout:2.2.1")
115118
implementation("androidx.core:core-ktx:1.16.0")
@@ -120,6 +123,14 @@ dependencies {
120123
implementation("com.google.android.material:material:1.12.0")
121124
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
122125

126+
// Compose
127+
val composeBom = platform("androidx.compose:compose-bom:2025.04.01")
128+
implementation(composeBom)
129+
androidTestImplementation(composeBom)
130+
implementation("androidx.compose.material3:material3")
131+
implementation("androidx.compose.ui:ui-tooling-preview")
132+
debugImplementation("androidx.compose.ui:ui-tooling")
133+
123134
// Third-party
124135
implementation("com.journeyapps:zxing-android-embedded:4.3.0@aar")
125136
implementation("com.github.yalantis:ucrop:2.2.10")

app/src/main/java/protect/card_locker/AboutActivity.kt

Lines changed: 130 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -2,119 +2,154 @@ package protect.card_locker
22

33
import android.os.Bundle
44
import android.text.Spanned
5-
import android.view.MenuItem
6-
import android.view.View
75
import android.widget.ScrollView
86
import android.widget.TextView
9-
10-
import androidx.annotation.StringRes
11-
import androidx.core.view.isVisible
7+
import androidx.activity.ComponentActivity
8+
import androidx.activity.compose.setContent
9+
import androidx.compose.foundation.layout.Column
10+
import androidx.compose.foundation.layout.padding
11+
import androidx.compose.material.icons.Icons
12+
import androidx.compose.material.icons.automirrored.filled.ArrowBack
13+
import androidx.compose.material3.ExperimentalMaterial3Api
14+
import androidx.compose.material3.Icon
15+
import androidx.compose.material3.IconButton
16+
17+
import androidx.compose.material3.MaterialTheme
18+
import androidx.compose.material3.Scaffold
19+
import androidx.compose.material3.Text
20+
import androidx.compose.material3.TopAppBar
21+
import androidx.compose.material3.TopAppBarDefaults
22+
import androidx.compose.ui.Modifier
1223

1324
import com.google.android.material.dialog.MaterialAlertDialogBuilder
25+
import protect.card_locker.ui.CatimaAboutSection
26+
import protect.card_locker.ui.CatimaTopAppBar
1427

15-
import protect.card_locker.databinding.AboutActivityBinding
1628

17-
class AboutActivity : CatimaAppCompatActivity() {
29+
class AboutActivity : ComponentActivity() {
1830
private companion object {
1931
private const val TAG = "Catima"
2032
}
2133

22-
private lateinit var binding: AboutActivityBinding
2334
private lateinit var content: AboutContent
2435

36+
@OptIn(ExperimentalMaterial3Api::class)
2537
override fun onCreate(savedInstanceState: Bundle?) {
2638
super.onCreate(savedInstanceState)
27-
binding = AboutActivityBinding.inflate(layoutInflater)
2839
content = AboutContent(this)
2940
title = content.pageTitle
30-
setContentView(binding.root)
31-
setSupportActionBar(binding.toolbar)
32-
enableToolbarBackButton()
33-
34-
binding.apply {
35-
creditsSub.text = content.copyrightShort
36-
versionHistorySub.text = content.versionHistory
37-
38-
versionHistory.tag = "https://catima.app/changelog/"
39-
translate.tag = "https://hosted.weblate.org/engage/catima/"
40-
license.tag = "https://github.com/CatimaLoyalty/Android/blob/main/LICENSE"
41-
repo.tag = "https://github.com/CatimaLoyalty/Android/"
42-
privacy.tag = "https://catima.app/privacy-policy/"
43-
reportError.tag = "https://github.com/CatimaLoyalty/Android/issues"
44-
rate.tag = "https://play.google.com/store/apps/details?id=me.hackerchick.catima"
45-
donate.tag = "https://catima.app/donate"
46-
47-
// Hide Google Play rate button if not on Google Play
48-
rate.isVisible = BuildConfig.showRateOnGooglePlay
49-
// Hide donate button on Google Play (Google Play doesn't allow donation links)
50-
donate.isVisible = BuildConfig.showDonate
51-
}
52-
53-
bindClickListeners()
54-
}
5541

56-
override fun onOptionsItemSelected(item: MenuItem): Boolean {
57-
return when (item.itemId) {
58-
android.R.id.home -> {
59-
finish()
60-
true
42+
setContent {
43+
MaterialTheme {
44+
Scaffold(
45+
topBar = { CatimaTopAppBar(title.toString(), onBackPressedDispatcher) }
46+
) { innerPadding ->
47+
Column(modifier = Modifier.padding(innerPadding)) {
48+
CatimaAboutSection(
49+
getString(R.string.version_history),
50+
content.versionHistory,
51+
{
52+
showHTML(
53+
getString(R.string.version_history),
54+
content.historyInfo,
55+
this as ComponentActivity,
56+
"https://catima.app/changelog/"
57+
)
58+
}
59+
)
60+
CatimaAboutSection(
61+
getString(R.string.credits),
62+
content.copyrightShort,
63+
{
64+
showHTML(
65+
getString(R.string.credits),
66+
content.contributorInfo,
67+
this as ComponentActivity,
68+
null
69+
)
70+
}
71+
)
72+
CatimaAboutSection(
73+
getString(R.string.help_translate_this_app),
74+
getString(R.string.translate_platform),
75+
{
76+
OpenWebLinkHandler().openBrowser(
77+
this as ComponentActivity?,
78+
"https://hosted.weblate.org/engage/catima/"
79+
)
80+
}
81+
)
82+
CatimaAboutSection(
83+
getString(R.string.license),
84+
getString(R.string.app_license),
85+
{
86+
showHTML(
87+
getString(R.string.license),
88+
content.licenseInfo,
89+
this as ComponentActivity,
90+
"https://github.com/CatimaLoyalty/Android/blob/main/LICENSE"
91+
)
92+
}
93+
)
94+
CatimaAboutSection(
95+
getString(R.string.source_repository),
96+
getString(R.string.on_github),
97+
{
98+
OpenWebLinkHandler().openBrowser(
99+
this as ComponentActivity?,
100+
"https://github.com/CatimaLoyalty/Android/"
101+
)
102+
}
103+
)
104+
CatimaAboutSection(
105+
getString(R.string.privacy_policy),
106+
getString(R.string.and_data_usage),
107+
{
108+
showHTML(
109+
getString(R.string.privacy_policy),
110+
content.privacyInfo,
111+
this as ComponentActivity,
112+
"https://catima.app/privacy-policy/"
113+
)
114+
}
115+
)
116+
CatimaAboutSection(
117+
getString(R.string.donate),
118+
"",
119+
{
120+
OpenWebLinkHandler().openBrowser(
121+
this as ComponentActivity?,
122+
"https://catima.app/donate"
123+
)
124+
}
125+
)
126+
CatimaAboutSection(
127+
getString(R.string.rate_this_app),
128+
getString(R.string.on_google_play),
129+
{
130+
OpenWebLinkHandler().openBrowser(
131+
this as ComponentActivity?,
132+
"https://play.google.com/store/apps/details?id=me.hackerchick.catima"
133+
)
134+
}
135+
)
136+
CatimaAboutSection(
137+
getString(R.string.report_error),
138+
getString(R.string.on_github),
139+
{
140+
OpenWebLinkHandler().openBrowser(
141+
this as ComponentActivity?,
142+
"https://github.com/CatimaLoyalty/Android/issues"
143+
)
144+
}
145+
)
146+
}
147+
}
61148
}
62-
63-
else -> super.onOptionsItemSelected(item)
64149
}
65150
}
66151

67-
override fun onDestroy() {
68-
super.onDestroy()
69-
content.destroy()
70-
clearClickListeners()
71-
}
72-
73-
private fun bindClickListeners() {
74-
binding.apply {
75-
versionHistory.setOnClickListener { showHistory(it) }
76-
translate.setOnClickListener { openExternalBrowser(it) }
77-
license.setOnClickListener { showLicense(it) }
78-
repo.setOnClickListener { openExternalBrowser(it) }
79-
privacy.setOnClickListener { showPrivacy(it) }
80-
reportError.setOnClickListener { openExternalBrowser(it) }
81-
rate.setOnClickListener { openExternalBrowser(it) }
82-
donate.setOnClickListener { openExternalBrowser(it) }
83-
credits.setOnClickListener { showCredits() }
84-
}
85-
}
86-
87-
private fun clearClickListeners() {
88-
binding.apply {
89-
versionHistory.setOnClickListener(null)
90-
translate.setOnClickListener(null)
91-
license.setOnClickListener(null)
92-
repo.setOnClickListener(null)
93-
privacy.setOnClickListener(null)
94-
reportError.setOnClickListener(null)
95-
rate.setOnClickListener(null)
96-
donate.setOnClickListener(null)
97-
credits.setOnClickListener(null)
98-
}
99-
}
100-
101-
private fun showCredits() {
102-
showHTML(R.string.credits, content.contributorInfo, null)
103-
}
104-
105-
private fun showHistory(view: View) {
106-
showHTML(R.string.version_history, content.historyInfo, view)
107-
}
108-
109-
private fun showLicense(view: View) {
110-
showHTML(R.string.license, content.licenseInfo, view)
111-
}
112-
113-
private fun showPrivacy(view: View) {
114-
showHTML(R.string.privacy_policy, content.privacyInfo, view)
115-
}
116-
117-
private fun showHTML(@StringRes title: Int, text: Spanned, view: View?) {
152+
private fun showHTML(title: String, text: Spanned, activity: ComponentActivity, url: String?) {
118153
val dialogContentPadding = resources.getDimensionPixelSize(R.dimen.alert_dialog_content_padding)
119154
val textView = TextView(this).apply {
120155
setText(text)
@@ -131,19 +166,12 @@ class AboutActivity : CatimaAppCompatActivity() {
131166
setView(scrollView)
132167
setPositiveButton(R.string.ok, null)
133168

134-
// Add View online button if an URL is linked to this view
135-
view?.tag?.let {
136-
setNeutralButton(R.string.view_online) { _, _ -> openExternalBrowser(view) }
169+
// Add View online button if an URL is given
170+
url?.let {
171+
setNeutralButton(R.string.view_online) { _, _ -> OpenWebLinkHandler().openBrowser(activity, url) }
137172
}
138173

139174
show()
140175
}
141176
}
142-
143-
private fun openExternalBrowser(view: View) {
144-
val tag = view.tag
145-
if (tag is String && tag.startsWith("https://")) {
146-
OpenWebLinkHandler().openBrowser(this, tag)
147-
}
148-
}
149177
}

app/src/main/java/protect/card_locker/OpenWebLinkHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
import android.util.Log;
77
import android.widget.Toast;
88

9+
import androidx.activity.ComponentActivity;
910
import androidx.appcompat.app.AppCompatActivity;
1011

1112
public class OpenWebLinkHandler {
1213

1314
private static final String TAG = "Catima";
1415

15-
public void openBrowser(AppCompatActivity activity, String url) {
16+
public void openBrowser(ComponentActivity activity, String url) {
1617
if (url == null) {
1718
return;
1819
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package protect.card_locker.ui
2+
3+
import androidx.compose.foundation.clickable
4+
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.Row
6+
import androidx.compose.foundation.layout.padding
7+
import androidx.compose.material3.MaterialTheme
8+
import androidx.compose.material3.Text
9+
import androidx.compose.runtime.Composable
10+
import androidx.compose.ui.Alignment
11+
import androidx.compose.ui.Modifier
12+
import androidx.compose.ui.unit.dp
13+
14+
@Composable
15+
fun CatimaAboutSection(title: String, message: String, onClick: () -> Unit) {
16+
Column(
17+
modifier = Modifier
18+
.padding(8.dp)
19+
.clickable(onClick = onClick)
20+
) {
21+
Row {
22+
Column(modifier = Modifier.weight(1F)) {
23+
Text(
24+
text = title,
25+
style = MaterialTheme.typography.titleLarge
26+
)
27+
Text(text = message)
28+
}
29+
Text(modifier = Modifier.align(Alignment.CenterVertically),
30+
text = ">",
31+
style = MaterialTheme.typography.titleMedium
32+
)
33+
}
34+
}
35+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package protect.card_locker.ui
2+
3+
import androidx.activity.OnBackPressedDispatcher
4+
import androidx.compose.material.icons.Icons
5+
import androidx.compose.material.icons.automirrored.filled.ArrowBack
6+
import androidx.compose.material3.ExperimentalMaterial3Api
7+
import androidx.compose.material3.Icon
8+
import androidx.compose.material3.IconButton
9+
import androidx.compose.material3.Text
10+
import androidx.compose.material3.TopAppBar
11+
import androidx.compose.runtime.Composable
12+
import androidx.compose.ui.res.stringResource
13+
import protect.card_locker.R
14+
15+
@OptIn(ExperimentalMaterial3Api::class)
16+
@Composable
17+
fun CatimaTopAppBar(title: String, onBackPressedDispatcher: OnBackPressedDispatcher?) {
18+
TopAppBar(
19+
title = {
20+
Text(text = title)
21+
},
22+
navigationIcon = { if (onBackPressedDispatcher != null) {
23+
IconButton(onClick = { onBackPressedDispatcher.onBackPressed() }) {
24+
Icon(
25+
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
26+
contentDescription = stringResource(R.string.back)
27+
)
28+
}
29+
} else null }
30+
)
31+
}

0 commit comments

Comments
 (0)