From 453adab89198cdd0be98c22974471e93af68070d Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 21:29:28 +0100 Subject: [PATCH 01/15] Enable kotlin compiler --- app/build.gradle | 5 +++++ build.gradle | 2 ++ gradle.properties | 3 +++ 3 files changed, 10 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 1e85d85bd2..a597ca366c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,6 +3,7 @@ import com.github.spotbugs.snom.SpotBugsTask plugins { id 'com.android.application' id 'com.github.spotbugs' + id 'org.jetbrains.kotlin.android' } spotbugs { @@ -127,3 +128,7 @@ tasks.withType(SpotBugsTask) { html.enabled = true } } + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + kotlinOptions.jvmTarget = "11" +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8132cb54c1..4943247242 100644 --- a/build.gradle +++ b/build.gradle @@ -3,6 +3,8 @@ plugins { id 'com.android.application' version '7.0.4' apply false id 'com.github.spotbugs' version "4.7.5" apply false + + id 'org.jetbrains.kotlin.android' version '1.7.10' apply false } allprojects { diff --git a/gradle.properties b/gradle.properties index acf164f6cd..ee812f1995 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,3 +18,6 @@ # org.gradle.parallel=true android.enableJetifier=true android.useAndroidX=true + +#Kotlin +kotlin.code.style=official \ No newline at end of file From 046b65af851b066fca4b517b50f0197e0af44726 Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 21:33:25 +0100 Subject: [PATCH 02/15] Rename .java to .kt --- .../protect/card_locker/{AboutContent.java => AboutContent.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/protect/card_locker/{AboutContent.java => AboutContent.kt} (100%) diff --git a/app/src/main/java/protect/card_locker/AboutContent.java b/app/src/main/java/protect/card_locker/AboutContent.kt similarity index 100% rename from app/src/main/java/protect/card_locker/AboutContent.java rename to app/src/main/java/protect/card_locker/AboutContent.kt From 5ce7d1f87ac3f4215f253203b2141b5b5d7ab44f Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 21:33:26 +0100 Subject: [PATCH 03/15] AboutContent auto convert to kotlin --- .../java/protect/card_locker/AboutContent.kt | 258 +++++++++++------- 1 file changed, 155 insertions(+), 103 deletions(-) diff --git a/app/src/main/java/protect/card_locker/AboutContent.kt b/app/src/main/java/protect/card_locker/AboutContent.kt index a05ab333c5..c60ecc6b61 100644 --- a/app/src/main/java/protect/card_locker/AboutContent.kt +++ b/app/src/main/java/protect/card_locker/AboutContent.kt @@ -1,111 +1,163 @@ -package protect.card_locker; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.util.Log; - -import androidx.core.text.HtmlCompat; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; - -public class AboutContent { - - public static final String TAG = "Catima"; - - public Context context; - - public AboutContent(Context context) { - this.context = context; - } - - public void destroy() { - this.context = null; - } - - public String getPageTitle() { - return String.format(context.getString(R.string.about_title_fmt), context.getString(R.string.app_name)); +package protect.card_locker + +import android.content.Context +import android.content.pm.PackageManager +import android.util.Log +import androidx.core.text.HtmlCompat +import java.io.IOException +import java.lang.StringBuilder +import java.util.* + +class AboutContent(var context: Context?) { + fun destroy() { + context = null } - public String getAppVersion() { - String version = "?"; - try { - PackageInfo pi = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); - version = pi.versionName; - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Package name not found", e); + val pageTitle: String + get() = String.format( + context!!.getString(R.string.about_title_fmt), + context!!.getString(R.string.app_name) + ) + val appVersion: String + get() { + var version = "?" + try { + val pi = context!!.packageManager.getPackageInfo( + context!!.packageName, 0 + ) + version = pi.versionName + } catch (e: PackageManager.NameNotFoundException) { + Log.w(TAG, "Package name not found", e) + } + return version } - - return version; - } - - public int getCurrentYear() { - return Calendar.getInstance().get(Calendar.YEAR); - } - - public String getCopyright() { - return String.format(context.getString(R.string.app_copyright_fmt), getCurrentYear()); - } - - public String getContributors() { - String contributors; - try { - contributors = "
" + Utils.readTextFile(context, R.raw.contributors); - } catch (IOException ignored) { - return ""; + val currentYear: Int + get() = Calendar.getInstance()[Calendar.YEAR] + val copyright: String + get() = String.format(context!!.getString(R.string.app_copyright_fmt), currentYear) + val contributors: String + get() { + val contributors: String + contributors = try { + "
" + Utils.readTextFile(context, R.raw.contributors) + } catch (ignored: IOException) { + return "" + } + return contributors.replace("\n", "
") } - return contributors.replace("\n", "
"); - } - - public String getThirdPartyLibraries() { - final List usedLibraries = new ArrayList<>(); - usedLibraries.add(new ThirdPartyInfo("Color Picker", "https://github.com/jaredrummler/ColorPicker", "Apache 2.0")); - usedLibraries.add(new ThirdPartyInfo("Commons CSV", "https://commons.apache.org/proper/commons-csv/", "Apache 2.0")); - usedLibraries.add(new ThirdPartyInfo("NumberPickerPreference", "https://github.com/invissvenska/NumberPickerPreference", "GNU LGPL 3.0")); - usedLibraries.add(new ThirdPartyInfo("uCrop", "https://github.com/Yalantis/uCrop", "Apache 2.0")); - usedLibraries.add(new ThirdPartyInfo("Zip4j", "https://github.com/srikanth-lingala/zip4j", "Apache 2.0")); - usedLibraries.add(new ThirdPartyInfo("ZXing", "https://github.com/zxing/zxing", "Apache 2.0")); - usedLibraries.add(new ThirdPartyInfo("ZXing Android Embedded", "https://github.com/journeyapps/zxing-android-embedded", "Apache 2.0")); - - StringBuilder result = new StringBuilder("
"); - for (ThirdPartyInfo entry : usedLibraries) { - result.append("
") - .append(entry.toHtml()); + val thirdPartyLibraries: String + get() { + val usedLibraries: MutableList = ArrayList() + usedLibraries.add( + ThirdPartyInfo( + "Color Picker", + "https://github.com/jaredrummler/ColorPicker", + "Apache 2.0" + ) + ) + usedLibraries.add( + ThirdPartyInfo( + "Commons CSV", + "https://commons.apache.org/proper/commons-csv/", + "Apache 2.0" + ) + ) + usedLibraries.add( + ThirdPartyInfo( + "NumberPickerPreference", + "https://github.com/invissvenska/NumberPickerPreference", + "GNU LGPL 3.0" + ) + ) + usedLibraries.add( + ThirdPartyInfo( + "uCrop", + "https://github.com/Yalantis/uCrop", + "Apache 2.0" + ) + ) + usedLibraries.add( + ThirdPartyInfo( + "Zip4j", + "https://github.com/srikanth-lingala/zip4j", + "Apache 2.0" + ) + ) + usedLibraries.add( + ThirdPartyInfo( + "ZXing", + "https://github.com/zxing/zxing", + "Apache 2.0" + ) + ) + usedLibraries.add( + ThirdPartyInfo( + "ZXing Android Embedded", + "https://github.com/journeyapps/zxing-android-embedded", + "Apache 2.0" + ) + ) + val result = StringBuilder("
") + for (entry in usedLibraries) { + result.append("
") + .append(entry.toHtml()) + } + return result.toString() } - - return result.toString(); - } - - public String getUsedThirdPartyAssets() { - final List usedAssets = new ArrayList<>(); - usedAssets.add(new ThirdPartyInfo("Android icons", "https://fonts.google.com/icons?selected=Material+Icons", "Apache 2.0")); - - StringBuilder result = new StringBuilder().append("
"); - for (ThirdPartyInfo entry : usedAssets) { - result.append("
") - .append(entry.toHtml()); + val usedThirdPartyAssets: String + get() { + val usedAssets: MutableList = ArrayList() + usedAssets.add( + ThirdPartyInfo( + "Android icons", + "https://fonts.google.com/icons?selected=Material+Icons", + "Apache 2.0" + ) + ) + val result = StringBuilder().append("
") + for (entry in usedAssets) { + result.append("
") + .append(entry.toHtml()) + } + return result.toString() } + val contributorInfo: String + get() { + val contributorInfo = StringBuilder() + contributorInfo.append( + HtmlCompat.fromHtml( + String.format( + context!!.getString(R.string.app_contributors), + contributors + ), HtmlCompat.FROM_HTML_MODE_COMPACT + ) + ) + contributorInfo.append("\n\n") + contributorInfo.append(context!!.getString(R.string.app_copyright_old)) + contributorInfo.append("\n\n") + contributorInfo.append( + HtmlCompat.fromHtml( + String.format( + context!!.getString(R.string.app_libraries), + thirdPartyLibraries + ), HtmlCompat.FROM_HTML_MODE_COMPACT + ) + ) + contributorInfo.append("\n\n") + contributorInfo.append( + HtmlCompat.fromHtml( + String.format( + context!!.getString(R.string.app_resources), + usedThirdPartyAssets + ), HtmlCompat.FROM_HTML_MODE_COMPACT + ) + ) + return contributorInfo.toString() + } + val versionHistory: String + get() = String.format(context!!.getString(R.string.debug_version_fmt), appVersion) - return result.toString(); - } - - public String getContributorInfo() { - StringBuilder contributorInfo = new StringBuilder(); - contributorInfo.append(HtmlCompat.fromHtml(String.format(context.getString(R.string.app_contributors), getContributors()), HtmlCompat.FROM_HTML_MODE_COMPACT)); - contributorInfo.append("\n\n"); - contributorInfo.append(context.getString(R.string.app_copyright_old)); - contributorInfo.append("\n\n"); - contributorInfo.append(HtmlCompat.fromHtml(String.format(context.getString(R.string.app_libraries), getThirdPartyLibraries()), HtmlCompat.FROM_HTML_MODE_COMPACT)); - contributorInfo.append("\n\n"); - contributorInfo.append(HtmlCompat.fromHtml(String.format(context.getString(R.string.app_resources), getUsedThirdPartyAssets()), HtmlCompat.FROM_HTML_MODE_COMPACT)); - - return contributorInfo.toString(); - } - - public String getVersionHistory() { - return String.format(context.getString(R.string.debug_version_fmt), getAppVersion()); + companion object { + const val TAG = "Catima" } -} +} \ No newline at end of file From 820b787147e615bb6bbfe6309ec88ddf17313e16 Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 21:53:49 +0100 Subject: [PATCH 04/15] Optimize Kotlin code. Remove unsafe nullable types --- .../java/protect/card_locker/AboutContent.kt | 154 +++++++++--------- .../main/java/protect/card_locker/Utils.java | 19 --- 2 files changed, 74 insertions(+), 99 deletions(-) diff --git a/app/src/main/java/protect/card_locker/AboutContent.kt b/app/src/main/java/protect/card_locker/AboutContent.kt index c60ecc6b61..fd011eaf7f 100644 --- a/app/src/main/java/protect/card_locker/AboutContent.kt +++ b/app/src/main/java/protect/card_locker/AboutContent.kt @@ -5,25 +5,30 @@ import android.content.pm.PackageManager import android.util.Log import androidx.core.text.HtmlCompat import java.io.IOException -import java.lang.StringBuilder import java.util.* class AboutContent(var context: Context?) { + fun destroy() { context = null } val pageTitle: String - get() = String.format( - context!!.getString(R.string.about_title_fmt), - context!!.getString(R.string.app_name) - ) - val appVersion: String get() { + val context = context ?: return "" + return String.format( + context.getString(R.string.about_title_fmt), + context.getString(R.string.app_name) + ) + } + + private val appVersion: String + get() { + val context = context ?: return "" var version = "?" try { - val pi = context!!.packageManager.getPackageInfo( - context!!.packageName, 0 + val pi = context.packageManager.getPackageInfo( + context.packageName, 0 ) version = pi.versionName } catch (e: PackageManager.NameNotFoundException) { @@ -31,131 +36,120 @@ class AboutContent(var context: Context?) { } return version } - val currentYear: Int - get() = Calendar.getInstance()[Calendar.YEAR] + + private val currentYear: Int = Calendar.getInstance()[Calendar.YEAR] + val copyright: String - get() = String.format(context!!.getString(R.string.app_copyright_fmt), currentYear) - val contributors: String get() { - val contributors: String - contributors = try { - "
" + Utils.readTextFile(context, R.raw.contributors) + val context = context ?: return "" + return String.format(context.getString(R.string.app_copyright_fmt), currentYear) + } + + private val contributors: String + get() { + val context = context ?: return "" + val contributors = try { + "
" + context.resources.openRawResource(R.raw.contributors) + .bufferedReader(Charsets.UTF_8) + .readText() } catch (ignored: IOException) { return "" } return contributors.replace("\n", "
") } - val thirdPartyLibraries: String + + val versionHistory: String + get() { + val context = context ?: return "" + return String.format(context.getString(R.string.debug_version_fmt), appVersion) + } + + private val thirdPartyLibraries: String get() { - val usedLibraries: MutableList = ArrayList() - usedLibraries.add( + val usedLibraries = listOf( ThirdPartyInfo( "Color Picker", "https://github.com/jaredrummler/ColorPicker", "Apache 2.0" - ) - ) - usedLibraries.add( + ), ThirdPartyInfo( "Commons CSV", "https://commons.apache.org/proper/commons-csv/", "Apache 2.0" - ) - ) - usedLibraries.add( + ), ThirdPartyInfo( "NumberPickerPreference", "https://github.com/invissvenska/NumberPickerPreference", "GNU LGPL 3.0" - ) - ) - usedLibraries.add( + ), ThirdPartyInfo( "uCrop", "https://github.com/Yalantis/uCrop", "Apache 2.0" - ) - ) - usedLibraries.add( + ), ThirdPartyInfo( "Zip4j", "https://github.com/srikanth-lingala/zip4j", "Apache 2.0" - ) - ) - usedLibraries.add( + ), ThirdPartyInfo( "ZXing", "https://github.com/zxing/zxing", "Apache 2.0" - ) - ) - usedLibraries.add( + ), ThirdPartyInfo( "ZXing Android Embedded", "https://github.com/journeyapps/zxing-android-embedded", "Apache 2.0" ) ) - val result = StringBuilder("
") - for (entry in usedLibraries) { - result.append("
") - .append(entry.toHtml()) - } - return result.toString() + return "
" + usedLibraries.joinToString("
") { it.toHtml() } } - val usedThirdPartyAssets: String + + private val usedThirdPartyAssets: String get() { - val usedAssets: MutableList = ArrayList() - usedAssets.add( + val usedAssets = listOf( ThirdPartyInfo( "Android icons", "https://fonts.google.com/icons?selected=Material+Icons", "Apache 2.0" ) ) - val result = StringBuilder().append("
") - for (entry in usedAssets) { - result.append("
") - .append(entry.toHtml()) - } - return result.toString() + return "
" + usedAssets.joinToString("
") { it.toHtml() } } + val contributorInfo: String get() { - val contributorInfo = StringBuilder() - contributorInfo.append( - HtmlCompat.fromHtml( - String.format( - context!!.getString(R.string.app_contributors), - contributors - ), HtmlCompat.FROM_HTML_MODE_COMPACT - ) + val context = context ?: return "" + val contributors = HtmlCompat.fromHtml( + String.format( + context.getString(R.string.app_contributors), + contributors + ), HtmlCompat.FROM_HTML_MODE_COMPACT ) - contributorInfo.append("\n\n") - contributorInfo.append(context!!.getString(R.string.app_copyright_old)) - contributorInfo.append("\n\n") - contributorInfo.append( - HtmlCompat.fromHtml( - String.format( - context!!.getString(R.string.app_libraries), - thirdPartyLibraries - ), HtmlCompat.FROM_HTML_MODE_COMPACT - ) + val copyright = context.getString(R.string.app_copyright_old) + val thirdPartyLibraries = HtmlCompat.fromHtml( + String.format( + context.getString(R.string.app_libraries), + thirdPartyLibraries + ), HtmlCompat.FROM_HTML_MODE_COMPACT ) - contributorInfo.append("\n\n") - contributorInfo.append( - HtmlCompat.fromHtml( - String.format( - context!!.getString(R.string.app_resources), - usedThirdPartyAssets - ), HtmlCompat.FROM_HTML_MODE_COMPACT - ) + val thirdPartyAssets = HtmlCompat.fromHtml( + String.format( + context.getString(R.string.app_resources), + usedThirdPartyAssets + ), HtmlCompat.FROM_HTML_MODE_COMPACT ) - return contributorInfo.toString() + return """ +$contributors + +$copyright + +$thirdPartyLibraries + +$thirdPartyAssets + """.trimIndent() } - val versionHistory: String - get() = String.format(context!!.getString(R.string.debug_version_fmt), appVersion) companion object { const val TAG = "Catima" diff --git a/app/src/main/java/protect/card_locker/Utils.java b/app/src/main/java/protect/card_locker/Utils.java index 0b466a0cbf..8cf806356d 100644 --- a/app/src/main/java/protect/card_locker/Utils.java +++ b/app/src/main/java/protect/card_locker/Utils.java @@ -556,23 +556,4 @@ public static int getRandomHeaderColor(Context context) { final int color = (int) (Math.random() * colors.length()); return colors.getColor(color, Color.BLACK); } - - public static String readTextFile(Context context, @RawRes int resourceId) throws IOException { - InputStream input = context.getResources().openRawResource(resourceId); - BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); - StringBuilder result = new StringBuilder(); - while (true) { - String nextLine = reader.readLine(); - - if (nextLine == null || nextLine.isEmpty()) { - reader.close(); - break; - } - - result.append("\n"); - result.append(nextLine); - } - - return result.toString(); - } } From 4b6806dd696a09f937c3510ec1339f1a9c0708cc Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 22:03:23 +0100 Subject: [PATCH 05/15] Rename .java to .kt --- .../{OpenWebLinkHandler.java => OpenWebLinkHandler.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/protect/card_locker/{OpenWebLinkHandler.java => OpenWebLinkHandler.kt} (100%) diff --git a/app/src/main/java/protect/card_locker/OpenWebLinkHandler.java b/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt similarity index 100% rename from app/src/main/java/protect/card_locker/OpenWebLinkHandler.java rename to app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt From 82d0160ec3e544af2b5c1d7404da3b9d862736f7 Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 22:03:23 +0100 Subject: [PATCH 06/15] OpenWebLinkHandler auto convert to kotlin --- .../protect/card_locker/OpenWebLinkHandler.kt | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt b/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt index 1586ac4f28..274466837b 100644 --- a/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt +++ b/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt @@ -1,29 +1,28 @@ -package protect.card_locker; +package protect.card_locker -import android.content.ActivityNotFoundException; -import android.content.Intent; -import android.net.Uri; -import android.util.Log; -import android.widget.Toast; +import androidx.appcompat.app.AppCompatActivity +import android.content.Intent +import android.content.ActivityNotFoundException +import android.net.Uri +import android.util.Log +import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity; - -public class OpenWebLinkHandler { - - private static final String TAG = "Catima"; - - public void openBrowser(AppCompatActivity activity, String url) { +class OpenWebLinkHandler { + fun open(activity: AppCompatActivity, url: String?) { if (url == null) { - return; + return } - - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); + val intent = Intent(Intent.ACTION_VIEW) + intent.data = Uri.parse(url) try { - activity.startActivity(intent); - } catch (ActivityNotFoundException e) { - Toast.makeText(activity, R.string.failedToOpenUrl, Toast.LENGTH_LONG).show(); - Log.e(TAG, "No activity found to handle intent", e); + activity.startActivity(intent) + } catch (e: ActivityNotFoundException) { + Toast.makeText(activity, R.string.failedToOpenUrl, Toast.LENGTH_LONG).show() + Log.e(TAG, "No activity found to handle intent", e) } } -} + + companion object { + private const val TAG = "Catima" + } +} \ No newline at end of file From 3f2a46982ecc2662a7abb6bc269e0d7afb3c783f Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 22:05:31 +0100 Subject: [PATCH 07/15] OpenWebLinkHandler remove not required nullability --- app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt b/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt index 274466837b..de8aa78d39 100644 --- a/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt +++ b/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt @@ -8,10 +8,7 @@ import android.util.Log import android.widget.Toast class OpenWebLinkHandler { - fun open(activity: AppCompatActivity, url: String?) { - if (url == null) { - return - } + fun open(activity: AppCompatActivity, url: String) { val intent = Intent(Intent.ACTION_VIEW) intent.data = Uri.parse(url) try { From 43a82ce20178ed7ab9857301b8caf06b4959c881 Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 22:06:30 +0100 Subject: [PATCH 08/15] Rename .java to .kt --- .../protect/card_locker/{AboutActivity.java => AboutActivity.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/protect/card_locker/{AboutActivity.java => AboutActivity.kt} (100%) diff --git a/app/src/main/java/protect/card_locker/AboutActivity.java b/app/src/main/java/protect/card_locker/AboutActivity.kt similarity index 100% rename from app/src/main/java/protect/card_locker/AboutActivity.java rename to app/src/main/java/protect/card_locker/AboutActivity.kt From 851acd85539fe6ffaeb11525d962abadbf57684e Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 22:06:31 +0100 Subject: [PATCH 09/15] AboutActivity auto convert to kotlin --- .../java/protect/card_locker/AboutActivity.kt | 168 +++++++++--------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/app/src/main/java/protect/card_locker/AboutActivity.kt b/app/src/main/java/protect/card_locker/AboutActivity.kt index 867b4c6bbc..5142c87be4 100644 --- a/app/src/main/java/protect/card_locker/AboutActivity.kt +++ b/app/src/main/java/protect/card_locker/AboutActivity.kt @@ -1,99 +1,99 @@ -package protect.card_locker; - -import android.os.Bundle; -import android.view.MenuItem; -import android.view.View; -import android.widget.TextView; - -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - - -import protect.card_locker.databinding.AboutActivityBinding; - -public class AboutActivity extends CatimaAppCompatActivity { - - private static final String TAG = "Catima"; - - private AboutActivityBinding binding; - private AboutContent content; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - binding = AboutActivityBinding.inflate(getLayoutInflater()); - content = new AboutContent(this); - setTitle(content.getPageTitle()); - setContentView(binding.getRoot()); - setSupportActionBar(binding.toolbar); - enableToolbarBackButton(); - - TextView copyright = binding.creditsSub; - copyright.setText(content.getCopyright()); - TextView versionHistory = binding.versionHistorySub; - versionHistory.setText(content.getVersionHistory()); - - binding.versionHistory.setTag("https://catima.app/changelog/"); - binding.translate.setTag("https://hosted.weblate.org/engage/catima/"); - binding.license.setTag("https://github.com/CatimaLoyalty/Android/blob/master/LICENSE"); - binding.repo.setTag("https://github.com/CatimaLoyalty/Android/"); - binding.privacy.setTag("https://catima.app/privacy-policy/"); - binding.reportError.setTag("https://github.com/CatimaLoyalty/Android/issues"); - binding.rate.setTag("https://play.google.com/store/apps/details?id=me.hackerchick.catima"); - - bindClickListeners(); +package protect.card_locker + +import protect.card_locker.AboutContent.pageTitle +import protect.card_locker.AboutContent.copyright +import protect.card_locker.AboutContent.versionHistory +import protect.card_locker.AboutContent.destroy +import protect.card_locker.OpenWebLinkHandler.open +import protect.card_locker.AboutContent.contributorInfo +import protect.card_locker.CatimaAppCompatActivity +import protect.card_locker.AboutContent +import android.os.Bundle +import android.view.MenuItem +import android.view.View +import android.widget.TextView +import protect.card_locker.OpenWebLinkHandler +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import protect.card_locker.R +import protect.card_locker.databinding.AboutActivityBinding + +class AboutActivity : CatimaAppCompatActivity() { + private var binding: AboutActivityBinding? = null + private var content: AboutContent? = null + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = AboutActivityBinding.inflate(layoutInflater) + content = AboutContent(this) + title = content!!.pageTitle + setContentView(binding!!.root) + setSupportActionBar(binding!!.toolbar) + enableToolbarBackButton() + val copyright = binding!!.creditsSub + copyright.text = content!!.copyright + val versionHistory = binding!!.versionHistorySub + versionHistory.text = content!!.versionHistory + binding!!.versionHistory.tag = "https://catima.app/changelog/" + binding!!.translate.tag = "https://hosted.weblate.org/engage/catima/" + binding!!.license.tag = "https://github.com/CatimaLoyalty/Android/blob/master/LICENSE" + binding!!.repo.tag = "https://github.com/CatimaLoyalty/Android/" + binding!!.privacy.tag = "https://catima.app/privacy-policy/" + binding!!.reportError.tag = "https://github.com/CatimaLoyalty/Android/issues" + binding!!.rate.tag = "https://play.google.com/store/apps/details?id=me.hackerchick.catima" + bindClickListeners() } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); + override fun onOptionsItemSelected(item: MenuItem): Boolean { + val id = item.itemId if (id == android.R.id.home) { - finish(); + finish() } - return super.onOptionsItemSelected(item); + return super.onOptionsItemSelected(item) } - @Override - protected void onDestroy() { - super.onDestroy(); - content.destroy(); - clearClickListeners(); - binding = null; + override fun onDestroy() { + super.onDestroy() + content!!.destroy() + clearClickListeners() + binding = null } - private void bindClickListeners() { - View.OnClickListener openExternalBrowser = view -> { - Object tag = view.getTag(); - if (tag instanceof String && ((String) tag).startsWith("https://")) { - (new OpenWebLinkHandler()).openBrowser(this, (String) tag); + private fun bindClickListeners() { + val openExternalBrowser = View.OnClickListener { view: View -> + val tag = view.tag + if (tag is String && tag.startsWith("https://")) { + OpenWebLinkHandler().open(this, tag) } - }; - binding.versionHistory.setOnClickListener(openExternalBrowser); - binding.translate.setOnClickListener(openExternalBrowser); - binding.license.setOnClickListener(openExternalBrowser); - binding.repo.setOnClickListener(openExternalBrowser); - binding.privacy.setOnClickListener(openExternalBrowser); - binding.reportError.setOnClickListener(openExternalBrowser); - binding.rate.setOnClickListener(openExternalBrowser); + } + binding!!.versionHistory.setOnClickListener(openExternalBrowser) + binding!!.translate.setOnClickListener(openExternalBrowser) + binding!!.license.setOnClickListener(openExternalBrowser) + binding!!.repo.setOnClickListener(openExternalBrowser) + binding!!.privacy.setOnClickListener(openExternalBrowser) + binding!!.reportError.setOnClickListener(openExternalBrowser) + binding!!.rate.setOnClickListener(openExternalBrowser) + binding!!.credits.setOnClickListener { view: View? -> showCredits() } + } - binding.credits.setOnClickListener(view -> showCredits()); + private fun clearClickListeners() { + binding!!.versionHistory.setOnClickListener(null) + binding!!.translate.setOnClickListener(null) + binding!!.license.setOnClickListener(null) + binding!!.repo.setOnClickListener(null) + binding!!.privacy.setOnClickListener(null) + binding!!.reportError.setOnClickListener(null) + binding!!.rate.setOnClickListener(null) + binding!!.credits.setOnClickListener(null) } - private void clearClickListeners() { - binding.versionHistory.setOnClickListener(null); - binding.translate.setOnClickListener(null); - binding.license.setOnClickListener(null); - binding.repo.setOnClickListener(null); - binding.privacy.setOnClickListener(null); - binding.reportError.setOnClickListener(null); - binding.rate.setOnClickListener(null); - binding.credits.setOnClickListener(null); + private fun showCredits() { + MaterialAlertDialogBuilder(this) + .setTitle(R.string.credits) + .setMessage(content!!.contributorInfo) + .setPositiveButton(R.string.ok, null) + .show() } - private void showCredits() { - new MaterialAlertDialogBuilder(this) - .setTitle(R.string.credits) - .setMessage(content.getContributorInfo()) - .setPositiveButton(R.string.ok, null) - .show(); + companion object { + private const val TAG = "Catima" } -} +} \ No newline at end of file From 8f16942c05be456fd8da55e2958357b42efd0a40 Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 22:11:44 +0100 Subject: [PATCH 10/15] Optimize Kotlin code of AboutActivity --- .../java/protect/card_locker/AboutActivity.kt | 93 ++++++++++--------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/protect/card_locker/AboutActivity.kt b/app/src/main/java/protect/card_locker/AboutActivity.kt index 5142c87be4..d180f846fe 100644 --- a/app/src/main/java/protect/card_locker/AboutActivity.kt +++ b/app/src/main/java/protect/card_locker/AboutActivity.kt @@ -1,20 +1,9 @@ package protect.card_locker -import protect.card_locker.AboutContent.pageTitle -import protect.card_locker.AboutContent.copyright -import protect.card_locker.AboutContent.versionHistory -import protect.card_locker.AboutContent.destroy -import protect.card_locker.OpenWebLinkHandler.open -import protect.card_locker.AboutContent.contributorInfo -import protect.card_locker.CatimaAppCompatActivity -import protect.card_locker.AboutContent import android.os.Bundle import android.view.MenuItem import android.view.View -import android.widget.TextView -import protect.card_locker.OpenWebLinkHandler import com.google.android.material.dialog.MaterialAlertDialogBuilder -import protect.card_locker.R import protect.card_locker.databinding.AboutActivityBinding class AboutActivity : CatimaAppCompatActivity() { @@ -22,23 +11,31 @@ class AboutActivity : CatimaAppCompatActivity() { private var content: AboutContent? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - binding = AboutActivityBinding.inflate(layoutInflater) - content = AboutContent(this) - title = content!!.pageTitle - setContentView(binding!!.root) - setSupportActionBar(binding!!.toolbar) + + val binding = AboutActivityBinding.inflate(layoutInflater) + .also { this.binding = it } + val content = AboutContent(this) + .also { this.content = it } + + title = content.pageTitle + + setContentView(binding.root) + setSupportActionBar(binding.toolbar) enableToolbarBackButton() - val copyright = binding!!.creditsSub - copyright.text = content!!.copyright - val versionHistory = binding!!.versionHistorySub - versionHistory.text = content!!.versionHistory - binding!!.versionHistory.tag = "https://catima.app/changelog/" - binding!!.translate.tag = "https://hosted.weblate.org/engage/catima/" - binding!!.license.tag = "https://github.com/CatimaLoyalty/Android/blob/master/LICENSE" - binding!!.repo.tag = "https://github.com/CatimaLoyalty/Android/" - binding!!.privacy.tag = "https://catima.app/privacy-policy/" - binding!!.reportError.tag = "https://github.com/CatimaLoyalty/Android/issues" - binding!!.rate.tag = "https://play.google.com/store/apps/details?id=me.hackerchick.catima" + + val copyright = binding.creditsSub + copyright.text = content.copyright + val versionHistory = binding.versionHistorySub + versionHistory.text = content.versionHistory + + binding.versionHistory.tag = "https://catima.app/changelog/" + binding.translate.tag = "https://hosted.weblate.org/engage/catima/" + binding.license.tag = "https://github.com/CatimaLoyalty/Android/blob/master/LICENSE" + binding.repo.tag = "https://github.com/CatimaLoyalty/Android/" + binding.privacy.tag = "https://catima.app/privacy-policy/" + binding.reportError.tag = "https://github.com/CatimaLoyalty/Android/issues" + binding.rate.tag = "https://play.google.com/store/apps/details?id=me.hackerchick.catima" + bindClickListeners() } @@ -52,43 +49,49 @@ class AboutActivity : CatimaAppCompatActivity() { override fun onDestroy() { super.onDestroy() - content!!.destroy() + content?.destroy() + content = null clearClickListeners() binding = null } private fun bindClickListeners() { + val binding = binding ?: return + val openExternalBrowser = View.OnClickListener { view: View -> val tag = view.tag if (tag is String && tag.startsWith("https://")) { OpenWebLinkHandler().open(this, tag) } } - binding!!.versionHistory.setOnClickListener(openExternalBrowser) - binding!!.translate.setOnClickListener(openExternalBrowser) - binding!!.license.setOnClickListener(openExternalBrowser) - binding!!.repo.setOnClickListener(openExternalBrowser) - binding!!.privacy.setOnClickListener(openExternalBrowser) - binding!!.reportError.setOnClickListener(openExternalBrowser) - binding!!.rate.setOnClickListener(openExternalBrowser) - binding!!.credits.setOnClickListener { view: View? -> showCredits() } + + binding.versionHistory.setOnClickListener(openExternalBrowser) + binding.translate.setOnClickListener(openExternalBrowser) + binding.license.setOnClickListener(openExternalBrowser) + binding.repo.setOnClickListener(openExternalBrowser) + binding.privacy.setOnClickListener(openExternalBrowser) + binding.reportError.setOnClickListener(openExternalBrowser) + binding.rate.setOnClickListener(openExternalBrowser) + binding.credits.setOnClickListener { showCredits() } } private fun clearClickListeners() { - binding!!.versionHistory.setOnClickListener(null) - binding!!.translate.setOnClickListener(null) - binding!!.license.setOnClickListener(null) - binding!!.repo.setOnClickListener(null) - binding!!.privacy.setOnClickListener(null) - binding!!.reportError.setOnClickListener(null) - binding!!.rate.setOnClickListener(null) - binding!!.credits.setOnClickListener(null) + val binding = binding ?: return + binding.versionHistory.setOnClickListener(null) + binding.translate.setOnClickListener(null) + binding.license.setOnClickListener(null) + binding.repo.setOnClickListener(null) + binding.privacy.setOnClickListener(null) + binding.reportError.setOnClickListener(null) + binding.rate.setOnClickListener(null) + binding.credits.setOnClickListener(null) } private fun showCredits() { + val content = content ?: return MaterialAlertDialogBuilder(this) .setTitle(R.string.credits) - .setMessage(content!!.contributorInfo) + .setMessage(content.contributorInfo) .setPositiveButton(R.string.ok, null) .show() } From 9f6661df53b8733882382b34475767b7058c6a1f Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 22:31:42 +0100 Subject: [PATCH 11/15] Rename .java to .kt --- .../card_locker/{ThirdPartyInfo.java => ThirdPartyInfo.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/protect/card_locker/{ThirdPartyInfo.java => ThirdPartyInfo.kt} (100%) diff --git a/app/src/main/java/protect/card_locker/ThirdPartyInfo.java b/app/src/main/java/protect/card_locker/ThirdPartyInfo.kt similarity index 100% rename from app/src/main/java/protect/card_locker/ThirdPartyInfo.java rename to app/src/main/java/protect/card_locker/ThirdPartyInfo.kt From dc6543dd156e3e225a5148887f3b11b8d288aa38 Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 22:31:42 +0100 Subject: [PATCH 12/15] Convert ThirdPartyInfo to kotlin --- .../protect/card_locker/ThirdPartyInfo.kt | 36 +++++-------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/protect/card_locker/ThirdPartyInfo.kt b/app/src/main/java/protect/card_locker/ThirdPartyInfo.kt index e32472babc..db1de7ab0d 100644 --- a/app/src/main/java/protect/card_locker/ThirdPartyInfo.kt +++ b/app/src/main/java/protect/card_locker/ThirdPartyInfo.kt @@ -1,29 +1,11 @@ -package protect.card_locker; +package protect.card_locker -public class ThirdPartyInfo { - private final String mName; - private final String mUrl; - private final String mLicense; - - public ThirdPartyInfo(String name, String url, String license) { - mName = name; - mUrl = url; - mLicense = license; - } - - public String name() { - return mName; - } - - public String url() { - return mUrl; - } - - public String license() { - return mLicense; - } - - public String toHtml() { - return String.format("%s (%s)", url(), name(), license()); +data class ThirdPartyInfo( + val name: String, + val url: String, + val license: String +) { + fun toHtml(): String { + return "$name ($license)" } -} +} \ No newline at end of file From 6a3a16cc8eab94f724be79b9e270e05528a377ab Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Sun, 30 Oct 2022 22:50:52 +0100 Subject: [PATCH 13/15] Add format and html extension for string resource ids --- .../java/protect/card_locker/AboutContent.kt | 64 ++++++++----------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/protect/card_locker/AboutContent.kt b/app/src/main/java/protect/card_locker/AboutContent.kt index fd011eaf7f..bfb276359b 100644 --- a/app/src/main/java/protect/card_locker/AboutContent.kt +++ b/app/src/main/java/protect/card_locker/AboutContent.kt @@ -13,14 +13,7 @@ class AboutContent(var context: Context?) { context = null } - val pageTitle: String - get() { - val context = context ?: return "" - return String.format( - context.getString(R.string.about_title_fmt), - context.getString(R.string.app_name) - ) - } + val pageTitle: String = R.string.about_title_fmt.format(R.string.app_name.getString()) private val appVersion: String get() { @@ -39,11 +32,7 @@ class AboutContent(var context: Context?) { private val currentYear: Int = Calendar.getInstance()[Calendar.YEAR] - val copyright: String - get() { - val context = context ?: return "" - return String.format(context.getString(R.string.app_copyright_fmt), currentYear) - } + val copyright: String = R.string.app_copyright_fmt.format(currentYear) private val contributors: String get() { @@ -58,11 +47,7 @@ class AboutContent(var context: Context?) { return contributors.replace("\n", "
") } - val versionHistory: String - get() { - val context = context ?: return "" - return String.format(context.getString(R.string.debug_version_fmt), appVersion) - } + val versionHistory: String = R.string.debug_version_fmt.format(appVersion) private val thirdPartyLibraries: String get() { @@ -121,25 +106,16 @@ class AboutContent(var context: Context?) { val contributorInfo: String get() { val context = context ?: return "" - val contributors = HtmlCompat.fromHtml( - String.format( - context.getString(R.string.app_contributors), - contributors - ), HtmlCompat.FROM_HTML_MODE_COMPACT - ) + val contributors = R.string.app_contributors + .format(contributors) + .toHtml() val copyright = context.getString(R.string.app_copyright_old) - val thirdPartyLibraries = HtmlCompat.fromHtml( - String.format( - context.getString(R.string.app_libraries), - thirdPartyLibraries - ), HtmlCompat.FROM_HTML_MODE_COMPACT - ) - val thirdPartyAssets = HtmlCompat.fromHtml( - String.format( - context.getString(R.string.app_resources), - usedThirdPartyAssets - ), HtmlCompat.FROM_HTML_MODE_COMPACT - ) + val thirdPartyLibraries = R.string.app_libraries + .format(thirdPartyLibraries) + .toHtml() + val thirdPartyAssets = R.string.app_resources + .format(usedThirdPartyAssets) + .toHtml() return """ $contributors @@ -151,6 +127,22 @@ $thirdPartyAssets """.trimIndent() } + private fun Int.getString(): String { + val context = context ?: return "" + + return context.getString(this) + } + + private fun Int.format(vararg args: Any?): String { + val context = context ?: return "" + + return String.format(context.getString(this), *args) + } + + private fun String.toHtml(): CharSequence { + return HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_COMPACT) + } + companion object { const val TAG = "Catima" } From ef99f40b9b990f9cab243379997340c60ddc3785 Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Tue, 1 Nov 2022 10:53:08 +0100 Subject: [PATCH 14/15] Rename open to openBrowser --- app/src/main/java/protect/card_locker/AboutActivity.kt | 2 +- app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/protect/card_locker/AboutActivity.kt b/app/src/main/java/protect/card_locker/AboutActivity.kt index d180f846fe..7339bb33c5 100644 --- a/app/src/main/java/protect/card_locker/AboutActivity.kt +++ b/app/src/main/java/protect/card_locker/AboutActivity.kt @@ -61,7 +61,7 @@ class AboutActivity : CatimaAppCompatActivity() { val openExternalBrowser = View.OnClickListener { view: View -> val tag = view.tag if (tag is String && tag.startsWith("https://")) { - OpenWebLinkHandler().open(this, tag) + OpenWebLinkHandler().openBrowser(this, tag) } } diff --git a/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt b/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt index de8aa78d39..d3e4540b77 100644 --- a/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt +++ b/app/src/main/java/protect/card_locker/OpenWebLinkHandler.kt @@ -8,7 +8,7 @@ import android.util.Log import android.widget.Toast class OpenWebLinkHandler { - fun open(activity: AppCompatActivity, url: String) { + fun openBrowser(activity: AppCompatActivity, url: String) { val intent = Intent(Intent.ACTION_VIEW) intent.data = Uri.parse(url) try { From 3f56441efe79de9c5515db0fa02b1e401bb4d20e Mon Sep 17 00:00:00 2001 From: Pfaffenrodt Date: Wed, 11 Jan 2023 10:32:51 +0100 Subject: [PATCH 15/15] Prefer nullpointer instead of doing nothing --- .../main/java/protect/card_locker/AboutActivity.kt | 6 +++--- .../main/java/protect/card_locker/AboutContent.kt | 14 +++++--------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/protect/card_locker/AboutActivity.kt b/app/src/main/java/protect/card_locker/AboutActivity.kt index 7339bb33c5..5b55a01668 100644 --- a/app/src/main/java/protect/card_locker/AboutActivity.kt +++ b/app/src/main/java/protect/card_locker/AboutActivity.kt @@ -56,7 +56,7 @@ class AboutActivity : CatimaAppCompatActivity() { } private fun bindClickListeners() { - val binding = binding ?: return + val binding = binding!! val openExternalBrowser = View.OnClickListener { view: View -> val tag = view.tag @@ -76,7 +76,7 @@ class AboutActivity : CatimaAppCompatActivity() { } private fun clearClickListeners() { - val binding = binding ?: return + val binding = binding!! binding.versionHistory.setOnClickListener(null) binding.translate.setOnClickListener(null) binding.license.setOnClickListener(null) @@ -88,7 +88,7 @@ class AboutActivity : CatimaAppCompatActivity() { } private fun showCredits() { - val content = content ?: return + val content = content!! MaterialAlertDialogBuilder(this) .setTitle(R.string.credits) .setMessage(content.contributorInfo) diff --git a/app/src/main/java/protect/card_locker/AboutContent.kt b/app/src/main/java/protect/card_locker/AboutContent.kt index bfb276359b..2192bd570b 100644 --- a/app/src/main/java/protect/card_locker/AboutContent.kt +++ b/app/src/main/java/protect/card_locker/AboutContent.kt @@ -17,7 +17,7 @@ class AboutContent(var context: Context?) { private val appVersion: String get() { - val context = context ?: return "" + val context = context!! var version = "?" try { val pi = context.packageManager.getPackageInfo( @@ -36,7 +36,7 @@ class AboutContent(var context: Context?) { private val contributors: String get() { - val context = context ?: return "" + val context = context!! val contributors = try { "
" + context.resources.openRawResource(R.raw.contributors) .bufferedReader(Charsets.UTF_8) @@ -105,7 +105,7 @@ class AboutContent(var context: Context?) { val contributorInfo: String get() { - val context = context ?: return "" + val context = context!! val contributors = R.string.app_contributors .format(contributors) .toHtml() @@ -128,15 +128,11 @@ $thirdPartyAssets } private fun Int.getString(): String { - val context = context ?: return "" - - return context.getString(this) + return context!!.getString(this) } private fun Int.format(vararg args: Any?): String { - val context = context ?: return "" - - return String.format(context.getString(this), *args) + return String.format(context!!.getString(this), *args) } private fun String.toHtml(): CharSequence {