From 203784d71816fd197c07fea848542f385b378fc6 Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Thu, 22 Feb 2024 14:16:05 +0100 Subject: [PATCH] fix: Don't crash when displaying update check dialog (#463) Previous code injected `ApplicationContext`, which is not themed, and caused a crash if the "update" dialog was shown. Fix by passing the necesssary context in explicitly when the check is performed. --- .../fdroid/kotlin/app/pachli/updatecheck/UpdateCheck.kt | 5 +---- .../github/kotlin/app/pachli/updatecheck/UpdateCheck.kt | 5 +---- .../google/kotlin/app/pachli/updatecheck/UpdateCheck.kt | 5 +---- app/src/main/java/app/pachli/MainActivity.kt | 2 +- .../pachli/components/preference/PreferencesFragment.kt | 2 +- app/src/main/java/app/pachli/updatecheck/UpdateCheck.kt | 8 ++++---- 6 files changed, 9 insertions(+), 18 deletions(-) diff --git a/app/src/fdroid/kotlin/app/pachli/updatecheck/UpdateCheck.kt b/app/src/fdroid/kotlin/app/pachli/updatecheck/UpdateCheck.kt index 694fa8f45..779fa759e 100644 --- a/app/src/fdroid/kotlin/app/pachli/updatecheck/UpdateCheck.kt +++ b/app/src/fdroid/kotlin/app/pachli/updatecheck/UpdateCheck.kt @@ -17,21 +17,18 @@ package app.pachli.updatecheck -import android.content.Context import android.content.Intent import android.net.Uri import app.pachli.BuildConfig import app.pachli.core.preferences.SharedPreferencesRepository -import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton class UpdateCheck @Inject constructor( - @ApplicationContext context: Context, sharedPreferencesRepository: SharedPreferencesRepository, private val fdroidService: FdroidService, -) : UpdateCheckBase(context, sharedPreferencesRepository) { +) : UpdateCheckBase(sharedPreferencesRepository) { override val updateIntent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("market://details?id=${BuildConfig.APPLICATION_ID}") } diff --git a/app/src/github/kotlin/app/pachli/updatecheck/UpdateCheck.kt b/app/src/github/kotlin/app/pachli/updatecheck/UpdateCheck.kt index 7209c6492..7c5ba3ecd 100644 --- a/app/src/github/kotlin/app/pachli/updatecheck/UpdateCheck.kt +++ b/app/src/github/kotlin/app/pachli/updatecheck/UpdateCheck.kt @@ -17,18 +17,15 @@ package app.pachli.updatecheck -import android.content.Context import android.content.Intent import android.net.Uri import app.pachli.core.preferences.SharedPreferencesRepository -import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject class UpdateCheck @Inject constructor( - @ApplicationContext context: Context, sharedPreferencesRepository: SharedPreferencesRepository, private val gitHubService: GitHubService, -) : UpdateCheckBase(context, sharedPreferencesRepository) { +) : UpdateCheckBase(sharedPreferencesRepository) { private val versionCodeExtractor = """(\d+)\.apk""".toRegex() override val updateIntent = Intent(Intent.ACTION_VIEW).apply { diff --git a/app/src/google/kotlin/app/pachli/updatecheck/UpdateCheck.kt b/app/src/google/kotlin/app/pachli/updatecheck/UpdateCheck.kt index a82f9c9fa..41ae9e3a4 100644 --- a/app/src/google/kotlin/app/pachli/updatecheck/UpdateCheck.kt +++ b/app/src/google/kotlin/app/pachli/updatecheck/UpdateCheck.kt @@ -17,21 +17,18 @@ package app.pachli.updatecheck -import android.content.Context import android.content.Intent import android.net.Uri import app.pachli.BuildConfig import app.pachli.core.preferences.SharedPreferencesRepository import com.google.android.play.core.appupdate.AppUpdateManager -import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import kotlinx.coroutines.suspendCancellableCoroutine class UpdateCheck @Inject constructor( - @ApplicationContext context: Context, sharedPreferencesRepository: SharedPreferencesRepository, private val appUpdateManager: AppUpdateManager, -) : UpdateCheckBase(context, sharedPreferencesRepository) { +) : UpdateCheckBase(sharedPreferencesRepository) { override val updateIntent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse( "https://play.google.com/store/apps/details?id=${BuildConfig.APPLICATION_ID}", diff --git a/app/src/main/java/app/pachli/MainActivity.kt b/app/src/main/java/app/pachli/MainActivity.kt index 59d77bfe7..ef21c4cd9 100644 --- a/app/src/main/java/app/pachli/MainActivity.kt +++ b/app/src/main/java/app/pachli/MainActivity.kt @@ -427,7 +427,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider { showJankyAnimationWarning() } - lifecycleScope.launch { updateCheck.checkForUpdate() } + lifecycleScope.launch { updateCheck.checkForUpdate(this@MainActivity) } } /** Warn the user about possibly-broken animations. */ diff --git a/app/src/main/java/app/pachli/components/preference/PreferencesFragment.kt b/app/src/main/java/app/pachli/components/preference/PreferencesFragment.kt index b3b2870b6..4d7f71fe8 100644 --- a/app/src/main/java/app/pachli/components/preference/PreferencesFragment.kt +++ b/app/src/main/java/app/pachli/components/preference/PreferencesFragment.kt @@ -352,7 +352,7 @@ class PreferencesFragment : PreferenceFragmentCompat() { key = PrefKeys.UPDATE_NOTIFICATION_LAST_NOTIFICATION_MS setOnPreferenceClickListener { lifecycleScope.launch { - if (updateCheck.checkForUpdate(true) == AT_LATEST) { + if (updateCheck.checkForUpdate(this@PreferencesFragment.requireContext(), true) == AT_LATEST) { Toast.makeText( this@PreferencesFragment.requireContext(), getString(R.string.pref_update_check_no_updates), diff --git a/app/src/main/java/app/pachli/updatecheck/UpdateCheck.kt b/app/src/main/java/app/pachli/updatecheck/UpdateCheck.kt index 89a9d3cb4..b34677a8d 100644 --- a/app/src/main/java/app/pachli/updatecheck/UpdateCheck.kt +++ b/app/src/main/java/app/pachli/updatecheck/UpdateCheck.kt @@ -34,7 +34,6 @@ import app.pachli.updatecheck.UpdateCheckResult.DIALOG_SHOWN import app.pachli.updatecheck.UpdateCheckResult.IGNORED import app.pachli.updatecheck.UpdateCheckResult.SKIPPED_BECAUSE_NEVER import app.pachli.updatecheck.UpdateCheckResult.SKIPPED_BECAUSE_TOO_SOON -import dagger.hilt.android.qualifiers.ApplicationContext import java.time.Instant import java.util.Date import javax.inject.Singleton @@ -86,7 +85,6 @@ enum class UpdateCheckResult { @Singleton abstract class UpdateCheckBase( - @ApplicationContext private val context: Context, private val sharedPreferencesRepository: SharedPreferencesRepository, ) : Preference.SummaryProvider { /** An intent that can be used to start the update process (e.g., open a store listing) */ @@ -107,12 +105,14 @@ abstract class UpdateCheckBase( * The user can start an update, ignore this version, or dismiss all future update * notifications. * + * @param context Themed context used to display the "Update" dialog. Must be from an + * activity that uses `Theme.AppCompat` or a descendent. * @param force If true then the user's preferences for update checking frequency are * ignored and the update check is always performed. * * @return The result of performing the update check */ - suspend fun checkForUpdate(force: Boolean = false): UpdateCheckResult { + suspend fun checkForUpdate(context: Context, force: Boolean = false): UpdateCheckResult { val frequency = UpdateNotificationFrequency.from( sharedPreferencesRepository.getString(PrefKeys.UPDATE_NOTIFICATION_FREQUENCY, null), ) @@ -205,7 +205,7 @@ abstract class UpdateCheckBase( val dateString = AbsoluteTimeFormatter().format(Date.from(nextCheck)) - return context.getString(R.string.pref_update_next_scheduled_check, dateString) + return preference.context.getString(R.string.pref_update_next_scheduled_check, dateString) } companion object {