Skip to content
Merged
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG_CONJUGATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/assets/i18n
78 changes: 62 additions & 16 deletions app/src/main/java/be/scri/helpers/ui/RatingHelper.kt
Original file line number Diff line number Diff line change
@@ -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

/**
Expand All @@ -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.
Expand All @@ -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()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: This Toast would also ideally be localized, but maybe we can do an audit of the toasts to see if there are others that aren't localized? Do you want to look into that, @ashb155?

Log.e("RatingHelper", "Unable to open $storeName link", e)
}
}

/**
* Initiates the app rating process based on the installation source.
*
Expand All @@ -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()
Expand All @@ -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")
}
Comment thread
angrezichatterbox marked this conversation as resolved.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ fun AboutPageItemComp(
trailingIcon: Int,
onClick: () -> Unit,
modifier: Modifier = Modifier,
descText: String? = null,
altText: String? = null,
) {
val semanticsModifier =
Expand Down Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/be/scri/ui/models/ScribeItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/be/scri/ui/screens/about/AboutUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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() },
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/string.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
<string name="i18n.app.about.community.wikimedia.text_3">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.</string>
<string name="i18n.app.about.feedback.bug_report">Report a bug</string>
<string name="i18n.app.about.feedback.rate_conjugate">Rate Scribe Conjugate</string>
<string name="i18n.app.about.feedback.rate_description_amazon">Rate us on Amazon Appstore</string>
<string name="i18n.app.about.feedback.rate_description_f_droid">Rate us on F-Droid</string>
<string name="i18n.app.about.feedback.rate_description_galaxy">Rate us on Galaxy Store</string>
<string name="i18n.app.about.feedback.rate_description_google_play">Rate us on Google Play Store</string>
<string name="i18n.app.about.feedback.rate_scribe">Rate Scribe</string>
<string name="i18n.app.about.feedback.reset_app_hints">Reset app hints</string>
<string name="i18n.app.about.feedback.send_email">Send us an email</string>
Expand Down
Loading