2
0
mirror of https://github.com/fork-maintainers/iceraven-browser synced 2024-11-17 15:26:23 +00:00

[fenix] For https://github.com/mozilla-mobile/fenix/issues/22851: Load wallpapers dynamically from the assets directory.

This commit is contained in:
Arturo Mejia 2022-01-06 17:21:35 -05:00 committed by mergify[bot]
parent 6118e24b39
commit c04363f337
12 changed files with 190 additions and 28 deletions

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,14 @@
[
{
"name": "wallpaper_1",
"portrait": "wallpapers/wallpaper_1.png",
"landscape": "wallpapers/wallpaper_1.png",
"isDark":true
},
{
"name": "wallpaper_2",
"portrait": "wallpapers/wallpaper_2.png",
"landscape": "wallpapers/wallpaper_2.png",
"isDark":false
}
]

View File

@ -37,6 +37,7 @@ import org.mozilla.fenix.perf.lazyMonitored
import org.mozilla.fenix.utils.ClipboardHandler import org.mozilla.fenix.utils.ClipboardHandler
import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.Settings
import org.mozilla.fenix.wallpapers.WallpaperManager import org.mozilla.fenix.wallpapers.WallpaperManager
import org.mozilla.fenix.wallpapers.WallpapersAssetsStorage
import org.mozilla.fenix.wifi.WifiConnectionMonitor import org.mozilla.fenix.wifi.WifiConnectionMonitor
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -144,7 +145,7 @@ class Components(private val context: Context) {
} }
val wallpaperManager by lazyMonitored { val wallpaperManager by lazyMonitored {
WallpaperManager(settings) WallpaperManager(settings, WallpapersAssetsStorage(context))
} }
val analytics by lazyMonitored { Analytics(context) } val analytics by lazyMonitored { Analytics(context) }

View File

@ -126,7 +126,7 @@ import org.mozilla.fenix.settings.deletebrowsingdata.deleteAndQuit
import org.mozilla.fenix.theme.ThemeManager import org.mozilla.fenix.theme.ThemeManager
import org.mozilla.fenix.utils.ToolbarPopupWindow import org.mozilla.fenix.utils.ToolbarPopupWindow
import org.mozilla.fenix.utils.allowUndo import org.mozilla.fenix.utils.allowUndo
import org.mozilla.fenix.wallpapers.Wallpaper import org.mozilla.fenix.wallpapers.WallpaperManager
import org.mozilla.fenix.whatsnew.WhatsNew import org.mozilla.fenix.whatsnew.WhatsNew
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import kotlin.math.min import kotlin.math.min
@ -395,7 +395,7 @@ class HomeFragment : Fragment() {
val wallpaperManger = requireComponents.wallpaperManager val wallpaperManger = requireComponents.wallpaperManager
// We only want to update the wallpaper when it's different from the default one // 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. // as the default is applied already on xml by default.
if (wallpaperManger.currentWallpaper != Wallpaper.NONE) { if (wallpaperManger.currentWallpaper != WallpaperManager.defaultWallpaper) {
wallpaperManger.updateWallpaper(binding.homeLayout, wallpaperManger.currentWallpaper) wallpaperManger.updateWallpaper(binding.homeLayout, wallpaperManger.currentWallpaper)
} }
} }

View File

@ -4,6 +4,7 @@
package org.mozilla.fenix.settings.wallpaper package org.mozilla.fenix.settings.wallpaper
import android.graphics.Bitmap
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
@ -29,8 +30,9 @@ import androidx.compose.material.rememberScaffoldState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
@ -41,8 +43,10 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.FirefoxTheme
import org.mozilla.fenix.wallpapers.Wallpaper import org.mozilla.fenix.wallpapers.Wallpaper
import org.mozilla.fenix.wallpapers.WallpaperManager
import java.util.Locale import java.util.Locale
/** /**
@ -55,8 +59,11 @@ import java.util.Locale
* @param onViewWallpaper Callback for when the view action is clicked from snackbar. * @param onViewWallpaper Callback for when the view action is clicked from snackbar.
*/ */
@Composable @Composable
@Suppress("LongParameterList")
fun WallpaperSettings( fun WallpaperSettings(
wallpapers: List<Wallpaper>, wallpapers: List<Wallpaper>,
defaultWallpaper: Wallpaper,
loadWallpaperResource: (Wallpaper) -> Bitmap,
selectedWallpaper: Wallpaper, selectedWallpaper: Wallpaper,
onSelectWallpaper: (Wallpaper) -> Unit, onSelectWallpaper: (Wallpaper) -> Unit,
onViewWallpaper: () -> Unit, onViewWallpaper: () -> Unit,
@ -76,6 +83,8 @@ fun WallpaperSettings(
Surface(color = FirefoxTheme.colors.layer2) { Surface(color = FirefoxTheme.colors.layer2) {
WallpaperThumbnails( WallpaperThumbnails(
wallpapers = wallpapers, wallpapers = wallpapers,
defaultWallpaper = defaultWallpaper,
loadWallpaperResource = loadWallpaperResource,
selectedWallpaper = selectedWallpaper, selectedWallpaper = selectedWallpaper,
onSelectWallpaper = { updatedWallpaper -> onSelectWallpaper = { updatedWallpaper ->
coroutineScope.launch { coroutineScope.launch {
@ -140,8 +149,11 @@ private fun WallpaperSnackbar(
*/ */
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
@Suppress("LongParameterList")
private fun WallpaperThumbnails( private fun WallpaperThumbnails(
wallpapers: List<Wallpaper>, wallpapers: List<Wallpaper>,
defaultWallpaper: Wallpaper,
loadWallpaperResource: (Wallpaper) -> Bitmap,
selectedWallpaper: Wallpaper, selectedWallpaper: Wallpaper,
numColumns: Int = 3, numColumns: Int = 3,
onSelectWallpaper: (Wallpaper) -> Unit, onSelectWallpaper: (Wallpaper) -> Unit,
@ -153,6 +165,8 @@ private fun WallpaperThumbnails(
items(wallpapers) { wallpaper -> items(wallpapers) { wallpaper ->
WallpaperThumbnailItem( WallpaperThumbnailItem(
wallpaper = wallpaper, wallpaper = wallpaper,
defaultWallpaper = defaultWallpaper,
loadWallpaperResource = loadWallpaperResource,
isSelected = selectedWallpaper == wallpaper, isSelected = selectedWallpaper == wallpaper,
onSelect = onSelectWallpaper onSelect = onSelectWallpaper
) )
@ -169,8 +183,11 @@ private fun WallpaperThumbnails(
* @param onSelect Action to take when this wallpaper is selected. * @param onSelect Action to take when this wallpaper is selected.
*/ */
@Composable @Composable
@Suppress("LongParameterList")
private fun WallpaperThumbnailItem( private fun WallpaperThumbnailItem(
wallpaper: Wallpaper, wallpaper: Wallpaper,
defaultWallpaper: Wallpaper,
loadWallpaperResource: (Wallpaper) -> Bitmap,
isSelected: Boolean, isSelected: Boolean,
aspectRatio: Float = 1.1f, aspectRatio: Float = 1.1f,
onSelect: (Wallpaper) -> Unit onSelect: (Wallpaper) -> Unit
@ -196,12 +213,12 @@ private fun WallpaperThumbnailItem(
.then(border) .then(border)
.clickable { onSelect(wallpaper) } .clickable { onSelect(wallpaper) }
) { ) {
if (wallpaper != Wallpaper.NONE) { if (wallpaper != defaultWallpaper) {
val contentDescription = stringResource( val contentDescription = stringResource(
R.string.wallpapers_item_name_content_description, wallpaper.name R.string.wallpapers_item_name_content_description, wallpaper.name
) )
Image( Image(
painterResource(id = wallpaper.drawable), bitmap = loadWallpaperResource(wallpaper).asImageBitmap(),
contentScale = ContentScale.FillBounds, contentScale = ContentScale.FillBounds,
contentDescription = contentDescription, contentDescription = contentDescription,
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
@ -214,9 +231,16 @@ private fun WallpaperThumbnailItem(
@Composable @Composable
private fun WallpaperThumbnailsPreview() { private fun WallpaperThumbnailsPreview() {
FirefoxTheme { FirefoxTheme {
val context = LocalContext.current
val wallpaperManager = context.components.wallpaperManager
WallpaperSettings( WallpaperSettings(
wallpapers = Wallpaper.values().toList(), defaultWallpaper = WallpaperManager.defaultWallpaper,
selectedWallpaper = Wallpaper.NONE, loadWallpaperResource = {
wallpaperManager.loadWallpaperFromAssets(it, context)
},
wallpapers = wallpaperManager.availableWallpapers,
selectedWallpaper = wallpaperManager.currentWallpaper,
onSelectWallpaper = {}, onSelectWallpaper = {},
onViewWallpaper = {}, onViewWallpaper = {},
) )

View File

@ -20,6 +20,7 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.FirefoxTheme
import org.mozilla.fenix.wallpapers.Wallpaper import org.mozilla.fenix.wallpapers.Wallpaper
import org.mozilla.fenix.wallpapers.WallpaperManager
class WallpaperSettingsFragment : Fragment() { class WallpaperSettingsFragment : Fragment() {
private val wallpaperManager by lazy { private val wallpaperManager by lazy {
@ -37,7 +38,11 @@ class WallpaperSettingsFragment : Fragment() {
FirefoxTheme { FirefoxTheme {
var currentWallpaper by remember { mutableStateOf(wallpaperManager.currentWallpaper) } var currentWallpaper by remember { mutableStateOf(wallpaperManager.currentWallpaper) }
WallpaperSettings( WallpaperSettings(
wallpapers = Wallpaper.values().toList(), wallpapers = wallpaperManager.availableWallpapers,
defaultWallpaper = WallpaperManager.defaultWallpaper,
loadWallpaperResource = {
wallpaperManager.loadWallpaperFromAssets(it, requireContext())
},
selectedWallpaper = currentWallpaper, selectedWallpaper = currentWallpaper,
onSelectWallpaper = { selectedWallpaper: Wallpaper -> onSelectWallpaper = { selectedWallpaper: Wallpaper ->
currentWallpaper = selectedWallpaper currentWallpaper = selectedWallpaper

View File

@ -41,13 +41,13 @@ import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.getPreferenceKey
import org.mozilla.fenix.ext.withExperiment import org.mozilla.fenix.ext.withExperiment
import org.mozilla.fenix.settings.PhoneFeature import org.mozilla.fenix.settings.PhoneFeature
import org.mozilla.fenix.wallpapers.Wallpaper
import org.mozilla.fenix.settings.deletebrowsingdata.DeleteBrowsingDataOnQuitType import org.mozilla.fenix.settings.deletebrowsingdata.DeleteBrowsingDataOnQuitType
import org.mozilla.fenix.settings.logins.SavedLoginsSortingStrategyMenu import org.mozilla.fenix.settings.logins.SavedLoginsSortingStrategyMenu
import org.mozilla.fenix.settings.logins.SortingStrategy import org.mozilla.fenix.settings.logins.SortingStrategy
import org.mozilla.fenix.settings.registerOnSharedPreferenceChangeListener import org.mozilla.fenix.settings.registerOnSharedPreferenceChangeListener
import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_BLOCK_ALL import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_BLOCK_ALL
import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_BLOCK_AUDIBLE import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_BLOCK_AUDIBLE
import org.mozilla.fenix.wallpapers.WallpaperManager
import java.security.InvalidParameterException import java.security.InvalidParameterException
private const val AUTOPLAY_USER_SETTING = "AUTOPLAY_USER_SETTING" private const val AUTOPLAY_USER_SETTING = "AUTOPLAY_USER_SETTING"
@ -168,7 +168,7 @@ class Settings(private val appContext: Context) : PreferencesHolder {
var currentWallpaper by stringPreference( var currentWallpaper by stringPreference(
appContext.getPreferenceKey(R.string.pref_key_current_wallpaper), appContext.getPreferenceKey(R.string.pref_key_current_wallpaper),
default = Wallpaper.NONE.name default = WallpaperManager.defaultWallpaper.name
) )
var openLinksInAPrivateTab by booleanPreference( var openLinksInAPrivateTab by booleanPreference(

View File

@ -4,13 +4,16 @@
package org.mozilla.fenix.wallpapers package org.mozilla.fenix.wallpapers
import org.mozilla.fenix.R
/** /**
* A enum that represents the available wallpapers and their states. * A class that represents an available wallpaper and its state.
* @property name Indicates the name of this wallpaper.
* @property portraitPath A file path for the portrait version of this wallpaper.
* @property landscapePath A file path for the landscape version of this wallpaper.
* @property isDark Indicates if the most predominant color on the wallpaper is dark.
*/ */
enum class Wallpaper(val drawable: Int, val isDark: Boolean) { data class Wallpaper(
NONE(drawable = R.attr.homeBackground, isDark = false), val name: String,
FIRST(drawable = R.drawable.wallpaper_1, isDark = true), val portraitPath: String,
SECOND(drawable = R.drawable.wallpaper_2, isDark = false); val landscapePath: String,
} val isDark: Boolean
)

View File

@ -5,18 +5,29 @@
package org.mozilla.fenix.wallpapers package org.mozilla.fenix.wallpapers
import android.content.Context import android.content.Context
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import mozilla.components.support.base.log.logger.Logger import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.ktx.android.content.getColorFromAttr
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.asActivity import org.mozilla.fenix.ext.asActivity
import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.Settings
/** /**
* Provides access to available wallpapers and manages their states. * Provides access to available wallpapers and manages their states.
*/ */
class WallpaperManager(private val settings: Settings) { class WallpaperManager(
private val settings: Settings,
private val wallpaperStorage: WallpaperStorage
) {
val logger = Logger("WallpaperManager") val logger = Logger("WallpaperManager")
var availableWallpapers: List<Wallpaper> = loadWallpapers()
private set
var currentWallpaper: Wallpaper = getCurrentWallpaperFromSettings() var currentWallpaper: Wallpaper = getCurrentWallpaperFromSettings()
set(value) { set(value) {
settings.currentWallpaper = value.name settings.currentWallpaper = value.name
@ -27,13 +38,14 @@ class WallpaperManager(private val settings: Settings) {
* Apply the [newWallpaper] into the [wallpaperContainer] and update the [currentWallpaper]. * Apply the [newWallpaper] into the [wallpaperContainer] and update the [currentWallpaper].
*/ */
fun updateWallpaper(wallpaperContainer: View, newWallpaper: Wallpaper) { fun updateWallpaper(wallpaperContainer: View, newWallpaper: Wallpaper) {
if (newWallpaper == Wallpaper.NONE) { val context = wallpaperContainer.context
val context = wallpaperContainer.context if (newWallpaper == defaultWallpaper) {
wallpaperContainer.setBackgroundColor(context.getColorFromAttr(newWallpaper.drawable)) wallpaperContainer.setBackgroundColor(context.getColorFromAttr(DEFAULT_RESOURCE))
logger.info("Wallpaper update to default background") logger.info("Wallpaper update to default background")
} else { } else {
logger.info("Wallpaper update to ${newWallpaper.name}") logger.info("Wallpaper update to ${newWallpaper.name}")
wallpaperContainer.setBackgroundResource(newWallpaper.drawable) val bitmap = loadWallpaperFromAssets(newWallpaper, context)
wallpaperContainer.background = BitmapDrawable(context.resources, bitmap)
} }
currentWallpaper = newWallpaper currentWallpaper = newWallpaper
@ -41,7 +53,7 @@ class WallpaperManager(private val settings: Settings) {
} }
private fun adjustTheme(context: Context) { private fun adjustTheme(context: Context) {
val mode = if (currentWallpaper != Wallpaper.NONE) { val mode = if (currentWallpaper != defaultWallpaper) {
if (currentWallpaper.isDark) { if (currentWallpaper.isDark) {
updateThemePreference(useDarkTheme = true) updateThemePreference(useDarkTheme = true)
logger.info("theme changed to useDarkTheme") logger.info("theme changed to useDarkTheme")
@ -79,7 +91,7 @@ class WallpaperManager(private val settings: Settings) {
* the first available [Wallpaper] will be returned. * the first available [Wallpaper] will be returned.
*/ */
fun switchToNextWallpaper(): Wallpaper { fun switchToNextWallpaper(): Wallpaper {
val values = Wallpaper.values() val values = availableWallpapers
val index = values.indexOf(currentWallpaper) + 1 val index = values.indexOf(currentWallpaper) + 1
return if (index >= values.size) { return if (index >= values.size) {
@ -92,9 +104,43 @@ class WallpaperManager(private val settings: Settings) {
private fun getCurrentWallpaperFromSettings(): Wallpaper { private fun getCurrentWallpaperFromSettings(): Wallpaper {
val currentWallpaper = settings.currentWallpaper val currentWallpaper = settings.currentWallpaper
return if (currentWallpaper.isEmpty()) { return if (currentWallpaper.isEmpty()) {
Wallpaper.NONE defaultWallpaper
} else { } else {
Wallpaper.valueOf(currentWallpaper) availableWallpapers.find { it.name == currentWallpaper } ?: defaultWallpaper
} }
} }
fun loadWallpaperFromAssets(wallpaper: Wallpaper, context: Context): Bitmap {
val path = if (isLandscape(context)) {
wallpaper.landscapePath
} else {
wallpaper.portraitPath
}
return context.assets.open(path).use {
BitmapFactory.decodeStream(it)
}
}
private fun isLandscape(context: Context): Boolean {
return context.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
}
private fun loadWallpapers(): List<Wallpaper> {
val wallpapersFromStorage = wallpaperStorage.loadAll()
return if (wallpapersFromStorage.isNotEmpty()) {
listOf(defaultWallpaper) + wallpapersFromStorage
} else {
listOf(defaultWallpaper)
}
}
companion object {
const val DEFAULT_RESOURCE = R.attr.homeBackground
val defaultWallpaper = Wallpaper(
name = "default_wallpaper",
portraitPath = "",
landscapePath = "",
isDark = false
)
}
} }

View File

@ -0,0 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.wallpapers
/**
* Represents a storage to store [Wallpaper]s.
*/
interface WallpaperStorage {
/**
* Returns all [Wallpaper] from the storage.
*/
fun loadAll(): List<Wallpaper>
}

View File

@ -0,0 +1,55 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.wallpapers
import android.content.Context
import android.content.res.AssetManager
import mozilla.components.support.base.log.logger.Logger
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.lang.Exception
class WallpapersAssetsStorage(private val context: Context) : WallpaperStorage {
val logger = Logger("WallpapersAssetsStorage")
private val wallpapersDirectory = "wallpapers"
@Suppress("TooGenericExceptionCaught")
override fun loadAll(): List<Wallpaper> {
val assetsManager = context.assets
return try {
assetsManager.readArray("$wallpapersDirectory/wallpapers.json").toWallpapers()
} catch (e: Exception) {
logger.error("Unable to load wallpaper", e)
emptyList()
}
}
private fun JSONArray.toWallpapers(): List<Wallpaper> {
return (0 until this.length()).mapNotNull { index ->
this.getJSONObject(index).toWallpaper()
}
}
private fun JSONObject.toWallpaper(): Wallpaper? {
return try {
Wallpaper(
name = getString("name"),
portraitPath = getString("portrait"),
landscapePath = getString("landscape"),
isDark = getBoolean("isDark")
)
} catch (e: JSONException) {
logger.error("unable to parse json for wallpaper $this", e)
null
}
}
private fun AssetManager.readArray(fileName: String) = JSONArray(
open(fileName).bufferedReader().use {
it.readText()
}
)
}