diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
index 4cb647cb82..e274841b91 100644
--- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
+++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
@@ -17,6 +17,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.View.AccessibilityDelegate
import android.view.ViewGroup
+import android.view.ViewTreeObserver
import android.view.accessibility.AccessibilityEvent
import android.widget.Button
import android.widget.LinearLayout
@@ -821,6 +822,26 @@ class HomeFragment : Fragment() {
// triggered to cause an automatic update on warm start (no tab selection occurs). So we
// update it manually here.
requireComponents.useCases.sessionUseCases.updateLastAccess()
+
+ if (shouldEnableWallpaper()) {
+ _binding?.sessionControlRecyclerView?.viewTreeObserver?.addOnGlobalLayoutListener(
+ homeLayoutListenerForLogoAnimation
+ )
+ }
+ }
+
+ // To try to find a good time to show the logo animation, we are waiting until all
+ // the sub-recyclerviews (recentBookmarks, collections, recentTabs,recentVisits
+ // and pocketStories) on the home screen have been layout.
+ private val homeLayoutListenerForLogoAnimation = object : ViewTreeObserver.OnGlobalLayoutListener {
+ override fun onGlobalLayout() {
+ _binding?.let { safeBindings ->
+ requireComponents.wallpaperManager.animateLogoIfNeeded(safeBindings.wordmark)
+ safeBindings.sessionControlRecyclerView.viewTreeObserver.removeOnGlobalLayoutListener(
+ this
+ )
+ }
+ }
}
override fun onPause() {
diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt
index e828cabc9a..4aa4037249 100644
--- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt
+++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt
@@ -431,6 +431,16 @@ class Settings(private val appContext: Context) : PreferencesHolder {
featureFlag = FeatureFlags.inactiveTabs
)
+ /**
+ * Indicates if the Firefox logo on the home screen should be animated,
+ * to show users that they can change the wallpaper by tapping on the Firefox logo.
+ */
+ var shouldAnimateFirefoxLogo by featureFlagPreference(
+ appContext.getPreferenceKey(R.string.pref_key_show_logo_animation),
+ default = FeatureFlags.showWallpapers,
+ featureFlag = FeatureFlags.showWallpapers
+ )
+
/**
* Indicates if the user has enabled the search term tab groups feature.
*/
diff --git a/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperManager.kt b/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperManager.kt
index 1192cbe595..e57ada040e 100644
--- a/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperManager.kt
+++ b/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperManager.kt
@@ -4,7 +4,11 @@
package org.mozilla.fenix.wallpapers
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
import android.content.Context
+import android.os.Handler
+import android.os.Looper
import android.view.View
import androidx.appcompat.app.AppCompatDelegate
import mozilla.components.support.base.log.logger.Logger
@@ -96,4 +100,41 @@ class WallpaperManager(private val settings: Settings) {
Wallpaper.valueOf(currentWallpaper)
}
}
+
+ /**
+ * Animates the Firefox logo, if it hasn't been animated before, otherwise nothing will happen.
+ * After animating the first time, the [Settings.shouldAnimateFirefoxLogo] setting
+ * will be updated.
+ */
+ @Suppress("MagicNumber")
+ fun animateLogoIfNeeded(logo: View) {
+ if (!settings.shouldAnimateFirefoxLogo) {
+ return
+ }
+ Handler(Looper.getMainLooper()).postDelayed(
+ {
+ val animator1 = ObjectAnimator.ofFloat(logo, "rotation", 0f, 10f)
+ val animator2 = ObjectAnimator.ofFloat(logo, "rotation", 10f, 0f)
+ val animator4 = ObjectAnimator.ofFloat(logo, "rotation", 10f, 0f)
+ val animator3 = ObjectAnimator.ofFloat(logo, "rotation", 0f, 10f)
+
+ animator1.duration = 200
+ animator2.duration = 200
+ animator3.duration = 200
+ animator4.duration = 200
+
+ val set = AnimatorSet()
+
+ set.play(animator1).before(animator2).after(animator3).before(animator4)
+ set.start()
+
+ settings.shouldAnimateFirefoxLogo = false
+ },
+ ANIMATION_DELAY_MS
+ )
+ }
+
+ companion object {
+ private const val ANIMATION_DELAY_MS = 1500L
+ }
}
diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml
index 7c31662b63..a1693ed8d2 100644
--- a/app/src/main/res/values/preference_keys.xml
+++ b/app/src/main/res/values/preference_keys.xml
@@ -189,6 +189,7 @@
pref_key_current_wallpaper
+ pref_key_show_logo_animation
pref_key_encryption_key_generated