For #26511: load homescreen wallpaper in blocking coroutine

This commit is contained in:
MatthewTighe 2022-08-17 13:56:38 -07:00 committed by mergify[bot]
parent 9c1f48c982
commit 853778e29a
6 changed files with 93 additions and 20 deletions

View File

@ -114,6 +114,7 @@ import org.mozilla.fenix.home.topsites.DefaultTopSitesView
import org.mozilla.fenix.nimbus.FxNimbus
import org.mozilla.fenix.onboarding.FenixOnboarding
import org.mozilla.fenix.perf.MarkersFragmentLifecycleCallbacks
import org.mozilla.fenix.perf.runBlockingIncrement
import org.mozilla.fenix.tabstray.TabsTrayAccessPoint
import org.mozilla.fenix.utils.Settings.Companion.TOP_SITES_PROVIDER_MAX_THRESHOLD
import org.mozilla.fenix.utils.ToolbarPopupWindow
@ -211,6 +212,10 @@ class HomeFragment : Fragment() {
val activity = activity as HomeActivity
val components = requireComponents
// See https://github.com/mozilla-mobile/fenix/issues/26555 for context as to why
// this is commented out for now
observeWallpaperChanges()
currentMode = CurrentMode(
requireContext(),
onboarding,
@ -390,8 +395,6 @@ class HomeFragment : Fragment() {
FxNimbus.features.homescreen.recordExposure()
displayWallpaperIfEnabled()
binding.root.doOnPreDraw {
requireComponents.appStore.dispatch(AppAction.UpdateFirstFrameDrawn(drawn = true))
}
@ -407,6 +410,7 @@ class HomeFragment : Fragment() {
super.onConfigurationChanged(newConfig)
getMenuButton()?.dismissMenu()
setWallpaperToCurrent()
}
/**
@ -923,30 +927,42 @@ class HomeFragment : Fragment() {
?.isVisible = tabCount > 0
}
private fun displayWallpaperIfEnabled() {
@Suppress("UnusedPrivateMember")
private fun observeWallpaperChanges() {
if (shouldEnableWallpaper()) {
requireComponents.appStore.flow()
.ifChanged { state -> state.wallpaperState.currentWallpaper }
.onEach { state ->
// We only want to update the wallpaper when it's different from the default one
// as the default is applied already on xml by default.
when (val currentWallpaper = state.wallpaperState.currentWallpaper) {
Wallpaper.Default -> {
binding.wallpaperImageView.visibility = View.GONE
}
else -> {
val bitmap = requireComponents.useCases.wallpaperUseCases.loadBitmap(currentWallpaper)
bitmap?.let {
it.scaleToBottomOfView(binding.wallpaperImageView)
binding.wallpaperImageView.visibility = View.VISIBLE
}
}
}
showWallpaper(state.wallpaperState.currentWallpaper)
}
.launchIn(viewLifecycleOwner.lifecycleScope)
}
}
private fun setWallpaperToCurrent() {
if (shouldEnableWallpaper()) {
val wallpaper = requireComponents.appStore.state.wallpaperState.currentWallpaper
runBlockingIncrement {
showWallpaper(wallpaper)
}
}
}
private suspend fun showWallpaper(wallpaper: Wallpaper) = when (wallpaper) {
// We only want to update the wallpaper when it's different from the default one
// as the default is applied already on xml by default.
Wallpaper.Default -> {
binding.wallpaperImageView.visibility = View.GONE
}
else -> {
val bitmap = requireComponents.useCases.wallpaperUseCases.loadBitmap(wallpaper)
bitmap?.let {
it.scaleToBottomOfView(binding.wallpaperImageView)
binding.wallpaperImageView.visibility = View.VISIBLE
}
}
}
private fun shouldEnableWallpaper() =
(activity as? HomeActivity)?.themeManager?.currentTheme?.isPrivate?.not() ?: false

View File

@ -190,6 +190,22 @@ class Settings(private val appContext: Context) : PreferencesHolder {
default = Wallpaper.Default.name
)
/**
* A cache of the text color to use on text overlaying the current wallpaper.
*/
var currentWallpaperTextColor by longPreference(
appContext.getPreferenceKey(R.string.pref_key_current_wallpaper_text_color),
default = 0
)
/**
* A cache of the background color to use on cards overlaying the current wallpaper.
*/
var currentWallpaperCardColor by longPreference(
appContext.getPreferenceKey(R.string.pref_key_current_wallpaper_card_color),
default = 0
)
/**
* Indicates if the wallpaper onboarding dialog should be shown.
*/

View File

@ -4,6 +4,7 @@
package org.mozilla.fenix.wallpapers
import org.mozilla.fenix.utils.Settings
import java.util.Date
/**
@ -84,6 +85,25 @@ data class Wallpaper(
* @param name The name of the wallpaper.
*/
fun getLocalPath(name: String, type: ImageType) = "wallpapers/$name/${type.lowercase()}.png"
/**
* Generate a wallpaper from metadata cached in Settings.
*
* @param settings The local cache.
*/
fun getCurrentWallpaperFromSettings(settings: Settings): Wallpaper? {
val name = settings.currentWallpaperName
val textColor = settings.currentWallpaperTextColor
val cardColor = settings.currentWallpaperCardColor
return if (name.isNotEmpty() && textColor != 0L && cardColor != 0L) {
Wallpaper(
name = name,
textColor = textColor,
cardColor = cardColor,
collection = DefaultCollection
)
} else null
}
}
/**

View File

@ -124,6 +124,11 @@ class WallpapersUseCases(
// This should be cleaned up as improvements are made to the storage, file management,
// and download utilities.
withContext(Dispatchers.IO) {
val dispatchedCurrent = Wallpaper.getCurrentWallpaperFromSettings(settings)?.let {
// Dispatch this ASAP so the home screen can render.
store.dispatch(AppAction.WallpaperAction.UpdateCurrentWallpaper(it))
true
} ?: false
val availableWallpapers = possibleWallpapers.getAvailableWallpapers()
val currentWallpaperName = settings.currentWallpaperName
val currentWallpaper = possibleWallpapers.find { it.name == currentWallpaperName }
@ -136,7 +141,9 @@ class WallpapersUseCases(
)
downloadAllRemoteWallpapers(availableWallpapers)
store.dispatch(AppAction.WallpaperAction.UpdateAvailableWallpapers(availableWallpapers))
store.dispatch(AppAction.WallpaperAction.UpdateCurrentWallpaper(currentWallpaper))
if (!dispatchedCurrent) {
store.dispatch(AppAction.WallpaperAction.UpdateCurrentWallpaper(currentWallpaper))
}
}
}
@ -217,6 +224,9 @@ class WallpapersUseCases(
private val currentLocale: String,
) : InitializeWallpapersUseCase {
override suspend fun invoke() {
Wallpaper.getCurrentWallpaperFromSettings(settings)?.let {
store.dispatch(AppAction.WallpaperAction.UpdateCurrentWallpaper(it))
}
val currentWallpaperName = withContext(Dispatchers.IO) { settings.currentWallpaperName }
val possibleWallpapers = metadataFetcher.downloadWallpaperList().filter {
!it.isExpired() && it.isAvailableInLocale()
@ -225,7 +235,8 @@ class WallpapersUseCases(
?: fileManager.lookupExpiredWallpaper(currentWallpaperName)
?: Wallpaper.Default
// Dispatching this early will make it accessible to the home screen ASAP
// Dispatching this early will make it accessible to the home screen ASAP. If it has been
// dispatched above, we may still need to update other metadata about it.
store.dispatch(AppAction.WallpaperAction.UpdateCurrentWallpaper(currentWallpaper))
fileManager.clean(
@ -383,6 +394,8 @@ class WallpapersUseCases(
*/
override fun invoke(wallpaper: Wallpaper) {
settings.currentWallpaperName = wallpaper.name
settings.currentWallpaperTextColor = wallpaper.textColor ?: 0
settings.currentWallpaperCardColor = wallpaper.cardColor ?: 0
store.dispatch(AppAction.WallpaperAction.UpdateCurrentWallpaper(wallpaper))
Wallpapers.wallpaperSelected.record(
Wallpapers.WallpaperSelectedExtra(

View File

@ -201,6 +201,8 @@
<!-- Wallpaper Settings -->
<string name="pref_key_wallpapers" translatable="false">pref_key_wallpapers</string>
<string name="pref_key_current_wallpaper" translatable="false">pref_key_current_wallpaper</string>
<string name="pref_key_current_wallpaper_text_color" translatable="false">pref_key_current_wallpaper_text_color</string>
<string name="pref_key_current_wallpaper_card_color" translatable="false">pref_key_current_wallpaper_card_color</string>
<string name="pref_key_wallpapers_onboarding" translatable="false">pref_key_wallpapers_onboarding</string>
<string name="pref_key_encryption_key_generated" translatable="false">pref_key_encryption_key_generated</string>

View File

@ -1,6 +1,7 @@
package org.mozilla.fenix.wallpapers
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.mockk.Runs
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
@ -36,7 +37,12 @@ class WallpapersUseCasesTest {
private val fakeCalendar = Calendar.getInstance()
private val appStore = AppStore()
private val mockSettings = mockk<Settings>()
private val mockSettings = mockk<Settings> {
every { currentWallpaperTextColor } returns 0L
every { currentWallpaperTextColor = any() } just Runs
every { currentWallpaperCardColor } returns 0L
every { currentWallpaperCardColor = any() } just Runs
}
private val mockLegacyDownloader = mockk<LegacyWallpaperDownloader>(relaxed = true)
private val mockLegacyFileManager = mockk<LegacyWallpaperFileManager> {
every { clean(any(), any()) } just runs