From e45c7402790d49c5f6b86db29a530d7ba49f56c2 Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Fri, 9 Aug 2024 17:42:15 +0200 Subject: [PATCH 1/4] chore(deps): Update JVM toolchain, kotlin, gradle dependencies Remove unnecessary API dependency on Kotlin stdlib. --- build.gradle | 4 ++-- connector/build.gradle | 6 +----- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index 4c68f2e..3d1bad3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,12 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.7.20' + ext.kotlin_version = '2.0.0' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.2.0' + classpath 'com.android.tools.build:gradle:8.5.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/connector/build.gradle b/connector/build.gradle index 0847f7c..1e08998 100644 --- a/connector/build.gradle +++ b/connector/build.gradle @@ -7,7 +7,7 @@ plugins { } kotlin { - jvmToolchain(8) + jvmToolchain(17) } android { @@ -41,10 +41,6 @@ android { namespace "org.unifiedpush.android.connector" } -dependencies { - api("org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version") -} - // jitpack build afterEvaluate { publishing { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1986c1c..ae1221b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Dec 27 08:55:12 CET 2023 +#Fri Aug 09 16:31:50 CEST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 52ba3e483ebbe9f565e225f138841935ec2e0be4 Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Sat, 10 Aug 2024 12:21:08 +0200 Subject: [PATCH 2/4] fix: Re-register if the active distributor was deleted The user might register with a distributor, and then delete the distributor app. If that happens the user is not prompted if there are no distributors, and re-registration does not happen. Fix this by checking the ack'ed distributor is still in the list of installed distributors. --- .../java/org/unifiedpush/android/connector/UnifiedPush.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt b/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt index 669ecc8..d247dcb 100644 --- a/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt +++ b/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt @@ -72,7 +72,10 @@ object UnifiedPush { features: ArrayList = DEFAULT_FEATURES, messageForDistributor: String = "" ) { - getAckDistributor(context)?.let { + val distributors = getDistributors(context, features) + val ackDistributor = getAckDistributor(context) + + if (ackDistributor != null && distributors.contains(ackDistributor)) { registerApp(context, instance) return } From 5d452a0678d4406babd7854e3000d826a98feedf Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Sat, 10 Aug 2024 12:30:08 +0200 Subject: [PATCH 3/4] fix: Update "No distributor found" dialog Previous code ignored the dialog's default layout and set its own textview. I think this was so a LinkMovementMethod could be set on the message. This meant the view didn't follow normal Android dialog dimensions (e.g., padding, margins, text layout), and looked out of place. Fix this. Use the normal AlertDialog message. Set an onShowListener that sets the LinkMovementMethod when the dialog is shown. --- .../android/connector/UnifiedPush.kt | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt b/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt index d247dcb..a8add8e 100644 --- a/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt +++ b/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt @@ -85,23 +85,24 @@ object UnifiedPush { when (distributors.size) { 0 -> { if (!Store(context).getNoDistributorAck()) { - val message = TextView(context) - val builder = AlertDialog.Builder(context) - val s = SpannableString(registrationDialogContent.noDistributorDialog.message) - Linkify.addLinks(s, Linkify.WEB_URLS) - message.text = s - message.movementMethod = LinkMovementMethod.getInstance() - message.setPadding(32, 32, 32, 32) - builder.setTitle(registrationDialogContent.noDistributorDialog.title) - builder.setView(message) - builder.setPositiveButton(registrationDialogContent.noDistributorDialog.okButton) { - _, _ -> + val builder = AlertDialog.Builder(context).apply { + setTitle(registrationDialogContent.noDistributorDialog.title) + val msg = + SpannableString(registrationDialogContent.noDistributorDialog.message) + Linkify.addLinks(msg, Linkify.WEB_URLS) + setMessage(msg) + setPositiveButton(registrationDialogContent.noDistributorDialog.okButton) { _, _ -> } + setNegativeButton(registrationDialogContent.noDistributorDialog.ignoreButton) { _, _ -> + Store(context).saveNoDistributorAck() + } } - builder.setNegativeButton(registrationDialogContent.noDistributorDialog.ignoreButton) { - _, _ -> - Store(context).saveNoDistributorAck() + val dialog = builder.create() + dialog.setOnShowListener { + dialog.findViewById(android.R.id.message)?.let { + it.movementMethod = LinkMovementMethod.getInstance() + } } - builder.show() + dialog.show() } else { Log.d(LOG_TAG, "User already know there isn't any distributor") } From 65d4e6ff8113b6fe07e2a556042ae8ad942c581d Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Sat, 10 Aug 2024 14:16:28 +0200 Subject: [PATCH 4/4] fix(l10n): Use resource strings for default dialog string resources The strings used in default dialogs were hardcoded. This meant they couldn't be translated, or use the default platform strings (e.g., android.R.string.ok). Fix that. Convert `RegistrationDialogContent`, `NoDistributorDialog`, and `ChooseDialog` to interfaces, and provide implementations of those interfaces that --- .../connector/RegistrationDialogContent.kt | 81 ++++++++++++++----- .../android/connector/UnifiedPush.kt | 6 +- connector/src/main/res/values/strings.xml | 9 +++ 3 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 connector/src/main/res/values/strings.xml diff --git a/connector/src/main/java/org/unifiedpush/android/connector/RegistrationDialogContent.kt b/connector/src/main/java/org/unifiedpush/android/connector/RegistrationDialogContent.kt index 96ffcba..cde2cd2 100644 --- a/connector/src/main/java/org/unifiedpush/android/connector/RegistrationDialogContent.kt +++ b/connector/src/main/java/org/unifiedpush/android/connector/RegistrationDialogContent.kt @@ -1,20 +1,65 @@ package org.unifiedpush.android.connector -data class RegistrationDialogContent( - val noDistributorDialog: NoDistributorDialog = NoDistributorDialog(), - val chooseDialog: ChooseDialog = ChooseDialog() -) - -data class NoDistributorDialog( - var title: String = "No distributor found", - var message: String = "You need to install a distributor " + - "for push notifications to work.\n" + - "For more information, visit\n" + - "https://unifiedpush.org/", - var okButton: String = "OK", - var ignoreButton: String = "Ignore" -) - -data class ChooseDialog( - var title: String = "Choose a distributor" -) +import android.content.Context + +/** Defines content that can be shown during [UnifiedPush.registerAppWithDialog]. */ +interface RegistrationDialogContent { + /** Content if no distributor is installed. */ + val noDistributorDialog: NoDistributorDialog + + /** Content if multiple distributors are installed. */ + val chooseDialog: ChooseDialog +} + +/** + * Default [RegistrationDialogContent] + * + * @param context Context for fetching resources. + */ +data class DefaultRegistrationDialogContent(val context: Context) : RegistrationDialogContent { + override val noDistributorDialog = DefaultNoDistributorDialog(context) + override val chooseDialog = DefaultChooseDialog(context) +} + +/** Defines content for the dialog if no distributors are installed. */ +interface NoDistributorDialog { + /** Dialog title. */ + val title: String + + /** Dialog message. */ + var message: String + + /** Text on positive button */ + val okButton: String + + /** Text on negative button. */ + val ignoreButton: String +} + +/** + * Default [NoDistributorDialog]. + * + * @param context Context for fetching resources. + */ +data class DefaultNoDistributorDialog(val context: Context) : NoDistributorDialog { + override val title = context.getString(R.string.unified_push_dialog_no_distributor_title) + override var message = context.getString(R.string.unified_push_dialog_no_distributor_message) + override val okButton = context.getString(android.R.string.ok) + override val ignoreButton = + context.getString(R.string.unified_push_dialog_no_distributor_negative) +} + +/** Defines content for the dialog if multiple distributors are installed. */ +interface ChooseDialog { + /** Dialog title. */ + val title: String +} + +/** + * Default [ChooseDialog]. + * + * @param context Context for fetching resources. + */ +data class DefaultChooseDialog(val context: Context) : ChooseDialog { + override val title = context.getString(R.string.unified_push_dialog_choose_title) +} diff --git a/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt b/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt index a8add8e..527b8e2 100644 --- a/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt +++ b/connector/src/main/java/org/unifiedpush/android/connector/UnifiedPush.kt @@ -57,7 +57,9 @@ object UnifiedPush { registerAppWithDialog( context, instance, - RegistrationDialogContent().apply { noDistributorDialog.message = dialogMessage }, + DefaultRegistrationDialogContent(context).apply { + noDistributorDialog.message = dialogMessage + }, features, messageForDistributor ) @@ -68,7 +70,7 @@ object UnifiedPush { context: Context, instance: String = INSTANCE_DEFAULT, registrationDialogContent: RegistrationDialogContent = - RegistrationDialogContent(), + DefaultRegistrationDialogContent(context), features: ArrayList = DEFAULT_FEATURES, messageForDistributor: String = "" ) { diff --git a/connector/src/main/res/values/strings.xml b/connector/src/main/res/values/strings.xml new file mode 100644 index 0000000..53cd4d1 --- /dev/null +++ b/connector/src/main/res/values/strings.xml @@ -0,0 +1,9 @@ + + + + No distributor found + You need to install a distributor for push notifications to work\n\nFor more information visit https://unifiedpush.org. + Don\'t tell me again + + Choose a distributor +