feat: Warn the user about an Android animation bug (#274)

Upgrading to this version of Pachli may trigger an Android bug where
cached animation specifications are not cleared, resulting in incorrect
animations (e.g., when navigating between activities).

This is an Android bug triggered by the Android Material library,
https://github.com/material-components/material-components-android/issues/3644.

Show the user a dialog (once) when launching after an upgrade, so they
know to restart their device if necessary.
This commit is contained in:
Nik Clayton 2023-11-21 16:05:42 +01:00 committed by GitHub
parent 806991f8a8
commit 123c251fc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 1 deletions

View File

@ -47,6 +47,7 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.app.ActivityCompat
import androidx.core.content.IntentCompat
import androidx.core.content.edit
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.GravityCompat
@ -410,9 +411,24 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
recreate()
}
// TODO: This can be removed after 2024-03-01, assume everyone has upgraded by then
if (sharedPreferencesRepository.getBoolean(PrefKeys.SHOW_JANKY_ANIMATION_WARNING, true)) {
showJankyAnimationWarning()
}
checkForUpdate()
}
/** Warn the user about possibly-broken animations. */
private fun showJankyAnimationWarning() = lifecycleScope.launch {
AlertDialog.Builder(this@MainActivity)
.setTitle(R.string.janky_animation_title)
.setMessage(R.string.janky_animation_msg)
.create()
.await(android.R.string.ok)
sharedPreferencesRepository.edit { putBoolean(PrefKeys.SHOW_JANKY_ANIMATION_WARNING, false) }
}
/**
* Check for available updates, and prompt user to update.
*
@ -772,6 +788,7 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
arrayOf(
"Clear home timeline cache",
"Remove first 40 statuses",
"Reset janky animation warning flag",
),
) { _, which ->
Timber.d("Developer tools: $which")
@ -792,6 +809,9 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
}
}
}
2 -> {
developerToolsUseCase.resetJankyAnimationWarningFlag()
}
}
}
.create()

View File

@ -18,6 +18,7 @@
package app.pachli
import android.app.Application
import androidx.core.content.edit
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
@ -120,6 +121,14 @@ class PachliApplication : Application() {
Timber.d("Upgrading shared preferences: $oldVersion -> $newVersion")
val editor = sharedPreferencesRepository.edit()
if (oldVersion != NEW_INSTALL_SCHEMA_VERSION) {
// Upgrading rather than a new install. Possibly show the janky animation warning,
// see https://github.com/material-components/material-components-android/issues/3644
if (!sharedPreferencesRepository.contains(PrefKeys.SHOW_JANKY_ANIMATION_WARNING)) {
sharedPreferencesRepository.edit { putBoolean(PrefKeys.SHOW_JANKY_ANIMATION_WARNING, true) }
}
}
// General usage is:
//
// if (oldVersion < ...) {

View File

@ -112,6 +112,9 @@ object PrefKeys {
const val UPDATE_NOTIFICATION_VERSIONCODE = "updateNotificationVersioncode"
const val UPDATE_NOTIFICATION_LAST_NOTIFICATION_MS = "updateNotificationLastNotificationMs"
/* Flag to show the "janky animation" warning dialog */
const val SHOW_JANKY_ANIMATION_WARNING = "showJankyAnimationWarning"
/** Keys that are no longer used (e.g., the preference has been removed */
object Deprecated {
// Empty at this time

View File

@ -17,8 +17,11 @@
package app.pachli.usecase
import androidx.core.content.edit
import app.pachli.db.TimelineDao
import app.pachli.di.TransactionProvider
import app.pachli.settings.PrefKeys
import app.pachli.util.SharedPreferencesRepository
import javax.inject.Inject
/**
@ -28,6 +31,7 @@ import javax.inject.Inject
class DeveloperToolsUseCase @Inject constructor(
private val transactionProvider: TransactionProvider,
private val timelineDao: TimelineDao,
private val sharedPreferencesRepository: SharedPreferencesRepository,
) {
/**
* Clear the home timeline cache.
@ -45,4 +49,9 @@ class DeveloperToolsUseCase @Inject constructor(
timelineDao.deleteRange(accountId, ids.last(), ids.first())
}
}
/** Reset the SHOW_JANKY_ANIMATION_WARNING flag */
fun resetJankyAnimationWarningFlag() = sharedPreferencesRepository.edit {
putBoolean(PrefKeys.SHOW_JANKY_ANIMATION_WARNING, true)
}
}

View File

@ -709,4 +709,6 @@
<string name="reaction_name_and_count">%1$s %2$d</string>
<string name="announcement_date">%1$s %2$s</string>
<string name="announcement_date_updated">(Aktualisiert: %1$s)</string>
</resources>
<string name="janky_animation_title">Möglicherweise müssen Sie Ihr Gerät neu starten</string>
<string name="janky_animation_msg">Diese Version von Pachli kann auf einigen Geräten einen Android-Bug auslösen und fehlerhafte Animationen anzeigen.\n\nZum Beispiel, wenn Sie auf einen Beitrag tippen, um ein Thema anzuzeigen.\n\nWenn Sie dies sehen, müssen Sie Ihr Gerät neu starten.\n\nSie müssen dies nur einmal tun.\n\nDies ist ein Android-Fehler, für den Pachli nichts kann.</string>
</resources>

View File

@ -844,4 +844,7 @@
<string name="translating">Translating…</string>
<string name="translation_provider_fmt">%1$s</string>
<string name="janky_animation_title">You may need to restart your device</string>
<string name="janky_animation_msg">This version of Pachli may trigger an Android bug on some devices, and show broken animations.\n\nFor example, when tapping a post to view a thread.\n\nIf you see this you will need to restart your device.\n\nYou only need to do this once.\n\nThis is Android bug, there is nothing Pachli can do.</string>
</resources>