diff --git a/CHANGELOG.md b/CHANGELOG.md
index c40eff41..10e0255b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -50,7 +50,7 @@ Emojis for the following are chosen based on [gitmoji](https://gitmoji.dev/).
- The application and community's relationship to the Wikimedia movement is explained in app ([#52](https://github.com/scribe-org/Scribe-Android/issues/52)).
- Vibrate on keypress and key click functionalities are included ([#405](https://github.com/scribe-org/Scribe-Android/issues/405), [#406](https://github.com/scribe-org/Scribe-Android/issues/406)).
- An in-app tutorial is provided to detail functionalities of the application ([#602](https://github.com/scribe-org/Scribe-Android/issues/602), [#615](https://github.com/scribe-org/Scribe-Android/issues/615), [#616](https://github.com/scribe-org/Scribe-Android/issues/616)).
-- The user is able to easily rate the application ([#165](https://github.com/scribe-org/Scribe-Android/issues/165), [#640](https://github.com/scribe-org/Scribe-Android/issues/640)).
+- The user is able to easily rate the application, with installer-aware routing to the appropriate store ([#165](https://github.com/scribe-org/Scribe-Android/issues/165), [#640](https://github.com/scribe-org/Scribe-Android/issues/640)).
### 🗃️ Data
diff --git a/CHANGELOG_CONJUGATE.md b/CHANGELOG_CONJUGATE.md
index 91fd8f97..6c62a4a5 100644
--- a/CHANGELOG_CONJUGATE.md
+++ b/CHANGELOG_CONJUGATE.md
@@ -31,7 +31,7 @@ Emojis for the following are chosen based on [gitmoji](https://gitmoji.dev/).
- The Settings tab for the Scribe keyboard application was migrated to allow base settings for the app interface ([#562](https://github.com/scribe-org/Scribe-Android/issues/562)).
- The About tab for the Scribe keyboard application was migrated to provide information on the application and community ([#561](https://github.com/scribe-org/Scribe-Android/issues/561)).
- The application and community's relationship to the Wikimedia movement is explained in app ([#52](https://github.com/scribe-org/Scribe-Android/issues/52)).
-- The user is able to easily rate the application ([#165](https://github.com/scribe-org/Scribe-Android/issues/165), [#640](https://github.com/scribe-org/Scribe-Android/issues/640)).
+- The user is able to easily rate the application, with installer-aware routing to the appropriate store ([#165](https://github.com/scribe-org/Scribe-Android/issues/165), [#640](https://github.com/scribe-org/Scribe-Android/issues/640)).
### 🗃️ Data
diff --git a/app/src/main/assets/i18n b/app/src/main/assets/i18n
index 88ffe39c..77247dae 160000
--- a/app/src/main/assets/i18n
+++ b/app/src/main/assets/i18n
@@ -1 +1 @@
-Subproject commit 88ffe39cb72c192ea8f987f4ccb18d486d04f403
+Subproject commit 77247daeaa90eea2e7a0ac4e285986a1c01822ff
diff --git a/app/src/main/java/be/scri/helpers/ui/RatingHelper.kt b/app/src/main/java/be/scri/helpers/ui/RatingHelper.kt
index 87823929..96b6bc11 100644
--- a/app/src/main/java/be/scri/helpers/ui/RatingHelper.kt
+++ b/app/src/main/java/be/scri/helpers/ui/RatingHelper.kt
@@ -1,13 +1,16 @@
// SPDX-License-Identifier: GPL-3.0-or-later
package be.scri.helpers.ui
+import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
+import android.os.Build
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
+import be.scri.R
import com.google.android.play.core.review.ReviewManagerFactory
/**
@@ -20,6 +23,13 @@ import com.google.android.play.core.review.ReviewManagerFactory
object RatingHelper {
private const val INSTALLER_PLAY_STORE = "com.android.vending"
private const val INSTALLER_FDROID = "org.fdroid.fdroid"
+ private const val INSTALLER_AMAZON = "com.amazon.venezia"
+ private const val INSTALLER_SAMSUNG = "com.sec.android.app.samsungapps"
+
+ private const val URL_PLAY_STORE = "https://play.google.com/store/apps/details?id=%s"
+ private const val URL_FDROID = "https://f-droid.org/packages/%s"
+ private const val URL_AMAZON = "https://www.amazon.com/gp/mas/dl/android?p=%s"
+ private const val URL_SAMSUNG = "https://galaxystore.samsung.com/detail/%s"
/**
* Gets the package name of the app that installed this app.
@@ -31,12 +41,54 @@ object RatingHelper {
*/
private fun getInstallSource(context: Context): String? =
try {
- context.packageManager.getInstallerPackageName(context.packageName)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ context.packageManager.getInstallSourceInfo(context.packageName).installingPackageName
+ } else {
+ @Suppress("DEPRECATION")
+ context.packageManager.getInstallerPackageName(context.packageName)
+ }
} catch (e: PackageManager.NameNotFoundException) {
Log.e("RatingHelper", "Failed to get install source", e)
null
}
+ /**
+ * Gets the store description text (e.g. "Rate us on Google Play Store").
+ *
+ * @param context App context.
+ * @return String for the description.
+ */
+ fun getStoreDesc(context: Context): String? =
+ when (getInstallSource(context)) {
+ INSTALLER_PLAY_STORE -> context.getString(R.string.i18n_app_about_feedback_rate_description_google_play)
+ INSTALLER_FDROID -> context.getString(R.string.i18n_app_about_feedback_rate_description_f_droid)
+ INSTALLER_AMAZON -> context.getString(R.string.i18n_app_about_feedback_rate_description_amazon)
+ INSTALLER_SAMSUNG -> context.getString(R.string.i18n_app_about_feedback_rate_description_galaxy)
+ else -> context.getString(R.string.i18n_app_about_feedback_rate_description_google_play)
+ }
+
+ /**
+ * Opens store page in browser
+ *
+ * @param context App context.
+ * @param urlTemplate URL format string.
+ * @param storeName Store name.
+ */
+ private fun openStore(
+ context: Context,
+ urlTemplate: String,
+ storeName: String,
+ ) {
+ val url = urlTemplate.format(context.packageName)
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
+ try {
+ context.startActivity(intent)
+ } catch (e: ActivityNotFoundException) {
+ Toast.makeText(context, "No browser found to open $storeName page", Toast.LENGTH_SHORT).show()
+ Log.e("RatingHelper", "Unable to open $storeName link", e)
+ }
+ }
+
/**
* Initiates the app rating process based on the installation source.
*
@@ -51,7 +103,8 @@ object RatingHelper {
context: Context,
activity: ComponentActivity,
) {
- when (getInstallSource(context)) {
+ val installer = getInstallSource(context)
+ when (installer) {
INSTALLER_PLAY_STORE -> {
val reviewManager = ReviewManagerFactory.create(context)
val request = reviewManager.requestReviewFlow()
@@ -63,25 +116,18 @@ object RatingHelper {
.launchReviewFlow(activity, reviewInfo)
.addOnCompleteListener { }
} else {
- Toast.makeText(context, "Failed to launch review flow", Toast.LENGTH_SHORT).show()
+ openStore(context, URL_PLAY_STORE, "Play Store")
}
}
}
- INSTALLER_FDROID -> {
- val url = "https://f-droid.org/packages/${context.packageName}"
- val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
- try {
- context.startActivity(intent)
- } catch (e: PackageManager.NameNotFoundException) {
- Toast.makeText(context, "No browser found to open F-Droid page", Toast.LENGTH_SHORT).show()
- Log.e("RatingHelper", "Unable to open F-Droid link", e)
- }
- }
+ INSTALLER_FDROID -> openStore(context, URL_FDROID, "F-Droid")
- else -> {
- Toast.makeText(context, "Unknown installation source", Toast.LENGTH_SHORT).show()
- }
+ INSTALLER_AMAZON -> openStore(context, URL_AMAZON, "Amazon")
+
+ INSTALLER_SAMSUNG -> openStore(context, URL_SAMSUNG, "Galaxy Store")
+
+ else -> openStore(context, URL_PLAY_STORE, "Play Store")
}
}
}
diff --git a/app/src/main/java/be/scri/ui/common/components/AboutPageItemComp.kt b/app/src/main/java/be/scri/ui/common/components/AboutPageItemComp.kt
index 4bc29fc6..fa0aab14 100644
--- a/app/src/main/java/be/scri/ui/common/components/AboutPageItemComp.kt
+++ b/app/src/main/java/be/scri/ui/common/components/AboutPageItemComp.kt
@@ -36,6 +36,7 @@ fun AboutPageItemComp(
trailingIcon: Int,
onClick: () -> Unit,
modifier: Modifier = Modifier,
+ descText: String? = null,
altText: String? = null,
) {
val semanticsModifier =
@@ -72,12 +73,23 @@ fun AboutPageItemComp(
contentDescription = "Leading Icon",
)
Spacer(modifier = Modifier.width(8.dp))
- Text(
- text = title,
+ androidx.compose.foundation.layout.Column(
modifier = Modifier.weight(1f).padding(start = 4.dp),
- color = MaterialTheme.colorScheme.onSurface,
- style = MaterialTheme.typography.bodyMedium,
- )
+ ) {
+ Text(
+ text = title,
+ color = MaterialTheme.colorScheme.onSurface,
+ style = MaterialTheme.typography.bodyMedium,
+ )
+ if (descText != null) {
+ Text(
+ text = descText,
+ color = Color.Gray,
+ style = MaterialTheme.typography.bodySmall,
+ modifier = Modifier.padding(top = 4.dp),
+ )
+ }
+ }
Icon(
painter = painterResource(trailingIcon),
modifier =
diff --git a/app/src/main/java/be/scri/ui/common/components/ItemCardContainer.kt b/app/src/main/java/be/scri/ui/common/components/ItemCardContainer.kt
index d92e4ab4..bfc948bb 100644
--- a/app/src/main/java/be/scri/ui/common/components/ItemCardContainer.kt
+++ b/app/src/main/java/be/scri/ui/common/components/ItemCardContainer.kt
@@ -64,6 +64,7 @@ fun ItemsCardContainer(
is ScribeItem.ExternalLinkItem -> {
AboutPageItemComp(
title = stringResource(item.title),
+ descText = item.descText,
altText = item.altText?.let { stringResource(it) },
leadingIcon = item.leadingIcon,
trailingIcon = item.trailingIcon,
diff --git a/app/src/main/java/be/scri/ui/models/ScribeItem.kt b/app/src/main/java/be/scri/ui/models/ScribeItem.kt
index c52eaee9..1a56f28b 100644
--- a/app/src/main/java/be/scri/ui/models/ScribeItem.kt
+++ b/app/src/main/java/be/scri/ui/models/ScribeItem.kt
@@ -64,6 +64,7 @@ sealed class ScribeItem(
data class ExternalLinkItem(
override val title: Int,
override val desc: Int? = null,
+ val descText: String? = null,
override val altText: Int? = null,
@DrawableRes val leadingIcon: Int,
@DrawableRes val trailingIcon: Int,
diff --git a/app/src/main/java/be/scri/ui/screens/about/AboutUtil.kt b/app/src/main/java/be/scri/ui/screens/about/AboutUtil.kt
index 6eb6e342..5af84924 100644
--- a/app/src/main/java/be/scri/ui/screens/about/AboutUtil.kt
+++ b/app/src/main/java/be/scri/ui/screens/about/AboutUtil.kt
@@ -143,6 +143,7 @@ fun feedbackAndSupportList(
} else {
R.string.i18n_app_about_feedback_rate_scribe
},
+ descText = RatingHelper.getStoreDesc(context),
trailingIcon = R.drawable.external_link,
url = null,
onClick = { onRateScribeClick() },
diff --git a/app/src/main/res/values/string.xml b/app/src/main/res/values/string.xml
index 7fba4313..117e8923 100644
--- a/app/src/main/res/values/string.xml
+++ b/app/src/main/res/values/string.xml
@@ -51,6 +51,10 @@
Wikipedia is a multilingual free online encyclopedia written and maintained by a community of volunteers through open collaboration and a wiki-based editing system. Scribe uses data from Wikipedia to produce autosuggestions by deriving the most common words in a language as well as the most common words that follow them.
Report a bug
Rate Scribe Conjugate
+ Rate us on Amazon Appstore
+ Rate us on F-Droid
+ Rate us on Galaxy Store
+ Rate us on Google Play Store
Rate Scribe
Reset app hints
Send us an email