Skip to content

Commit

Permalink
For mozilla-mobile#26423: add wallpaper metadata fetcher
Browse files Browse the repository at this point in the history
  • Loading branch information
MatthewTighe committed Aug 17, 2022
1 parent 7bfd6ca commit ae26141
Show file tree
Hide file tree
Showing 8 changed files with 493 additions and 52 deletions.
46 changes: 34 additions & 12 deletions app/src/main/java/org/mozilla/fenix/wallpapers/Wallpaper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,37 @@ import java.util.Date
* Type that represents wallpapers.
*
* @property name The name of the wallpaper.
* @property collectionName The name of the collection the wallpaper belongs to.
* @property availableLocales The locales that this wallpaper is restricted to. If null, the wallpaper
* @property collection The name of the collection the wallpaper belongs to.
* is not restricted.
* @property startDate The date the wallpaper becomes available in a promotion. If null, it is available
* from any date.
* @property endDate The date the wallpaper stops being available in a promotion. If null,
* the wallpaper will be available to any date.
* @property textColor The 8 digit hex code color that should be used for text overlaying the wallpaper.
* @property cardColor The 8 digit hex code color that should be used for cards overlaying the wallpaper.
*/
data class Wallpaper(
val name: String,
val collectionName: String,
val availableLocales: List<String>?,
val startDate: Date?,
val endDate: Date?
val collection: Collection,
val textColor: Long?,
val cardColor: Long?,
) {
/**
* Type that represents a collection that a [Wallpaper] belongs to.
*
* @property name The name of the collection the wallpaper belongs to.
* @property learnMoreUrl The URL that can be visited to learn more about a collection, if any.
* @property availableLocales The locales that this wallpaper is restricted to. If null, the wallpaper
* is not restricted.
* @property startDate The date the wallpaper becomes available in a promotion. If null, it is available
* from any date.
* @property endDate The date the wallpaper stops being available in a promotion. If null,
* the wallpaper will be available to any date.
*/
data class Collection(
val name: String,
val learnMoreUrl: String?,
val availableLocales: List<String>?,
val startDate: Date?,
val endDate: Date?,
)

companion object {
const val amethystName = "amethyst"
const val ceruleanName = "cerulean"
Expand All @@ -33,13 +49,19 @@ data class Wallpaper(
const val beachVibeName = "beach-vibe"
const val firefoxCollectionName = "firefox"
const val defaultName = "default"
val Default = Wallpaper(
val DefaultCollection = Collection(
name = defaultName,
collectionName = defaultName,
learnMoreUrl = null,
availableLocales = null,
startDate = null,
endDate = null,
)
val Default = Wallpaper(
name = defaultName,
collection = DefaultCollection,
textColor = null,
cardColor = null,
)

/**
* Defines the standard path at which a wallpaper resource is kept on disk.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class WallpaperDownloader(
val remotePath = "${context.resolutionSegment()}/" +
"$orientation/" +
"$theme/" +
"$collectionName/" +
"${collection.name}/" +
"$name.png"
WallpaperMetadata(remotePath, localPath)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@ class WallpaperFileManager(
if (getAllLocalWallpaperPaths(name).all { File(rootDirectory, it).exists() }) {
Wallpaper(
name = name,
collectionName = "",
availableLocales = null,
startDate = null,
endDate = null,
collection = Wallpaper.DefaultCollection,
textColor = null,
cardColor = null,
)
} else null
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/* 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 kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import mozilla.components.concept.fetch.Client
import mozilla.components.concept.fetch.Request
import org.json.JSONArray
import org.json.JSONObject
import org.mozilla.fenix.BuildConfig
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

/**
* Utility class for downloading wallpaper metadata from the remote server.
*
* @property client The client that will be used to fetch metadata.
*/
class WallpaperMetadataFetcher(
private val client: Client
) {
private val metadataUrl = BuildConfig.WALLPAPER_URL.substringBefore("android") +
"metadata/v$currentJsonVersion/wallpapers.json"

/**
* Downloads the list of wallpapers from the remote source. Failures will return an empty list.
*/
suspend fun downloadWallpaperList(): List<Wallpaper> = withContext(Dispatchers.IO) {
Result.runCatching {
val request = Request(url = metadataUrl, method = Request.Method.GET)
val response = client.fetch(request)
response.body.useBufferedReader {
val json = it.readText()
JSONObject(json).parseAsWallpapers()
}
}.getOrElse { listOf() }
}

private fun JSONObject.parseAsWallpapers(): List<Wallpaper> = with(getJSONArray("collections")) {
(0 until length()).map { index ->
getJSONObject(index).toCollectionOfWallpapers()
}.flatten()
}

private fun JSONObject.toCollectionOfWallpapers(): List<Wallpaper> {
val collectionId = getString("id")
val availableLocales = optJSONArray("available-locales")?.getAvailableLocales()
val availabilityRange = optJSONObject("availability-range")?.getAvailabilityRange()
val learnMoreUrl = optString("learn-more-url")
val collection = Wallpaper.Collection(
name = collectionId,
availableLocales = availableLocales,
startDate = availabilityRange?.first,
endDate = availabilityRange?.second,
learnMoreUrl = learnMoreUrl,
)
return getJSONArray("wallpapers").toWallpaperList(collection)
}

private fun JSONArray.getAvailableLocales(): List<String>? =
(0 until length()).map { getString(it) }

private fun JSONObject.getAvailabilityRange(): Pair<Date, Date>? {
val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.US)
return Result.runCatching {
formatter.parse(getString("start"))!! to formatter.parse(getString("end"))!!
}.getOrNull()
}

private fun JSONArray.toWallpaperList(collection: Wallpaper.Collection): List<Wallpaper> =
(0 until length()).map { index ->
with(getJSONObject(index)) {
Wallpaper(
name = getString("id"),
textColor = getArgbValueAsLong("text-color"),
cardColor = getArgbValueAsLong("card-color"),
collection = collection,
)
}
}

/**
* The wallpaper metadata has 6 digit hex color codes for compatibility with iOS. Since Android
* expects 8 digit ARBG values, we prepend FF for the "fully visible" version of the color
* listed in the metadata.
*/
private fun JSONObject.getArgbValueAsLong(propName: String): Long = "FF${getString(propName)}"
.toLong(radix = 16)

companion object {
internal const val currentJsonVersion = 1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,51 +124,53 @@ class WallpapersUseCases(
}

private fun Wallpaper.isExpired(): Boolean {
val expired = this.endDate?.let { Date().after(it) } ?: false
val expired = this.collection.endDate?.let { Date().after(it) } ?: false
return expired && this.name != settings.currentWallpaper
}

private fun Wallpaper.isAvailableInLocale(): Boolean =
this.availableLocales?.contains(currentLocale) ?: true
this.collection.availableLocales?.contains(currentLocale) ?: true

companion object {
private val firefoxClassicCollection = Wallpaper.Collection(
name = Wallpaper.firefoxCollectionName,
availableLocales = null,
startDate = null,
endDate = null,
learnMoreUrl = null
)
private val localWallpapers: List<Wallpaper> = listOf(
Wallpaper(
name = Wallpaper.amethystName,
collectionName = Wallpaper.firefoxCollectionName,
availableLocales = null,
startDate = null,
endDate = null,
collection = firefoxClassicCollection,
textColor = null,
cardColor = null,
),
Wallpaper(
name = Wallpaper.ceruleanName,
collectionName = Wallpaper.firefoxCollectionName,
availableLocales = null,
startDate = null,
endDate = null,
collection = firefoxClassicCollection,
textColor = null,
cardColor = null,
),
Wallpaper(
name = Wallpaper.sunriseName,
collectionName = Wallpaper.firefoxCollectionName,
availableLocales = null,
startDate = null,
endDate = null,
collection = firefoxClassicCollection,
textColor = null,
cardColor = null,
),
)
private val remoteWallpapers: List<Wallpaper> = listOf(
Wallpaper(
name = Wallpaper.twilightHillsName,
collectionName = Wallpaper.firefoxCollectionName,
availableLocales = null,
startDate = null,
endDate = null,
collection = firefoxClassicCollection,
textColor = null,
cardColor = null,
),
Wallpaper(
name = Wallpaper.beachVibeName,
collectionName = Wallpaper.firefoxCollectionName,
availableLocales = null,
startDate = null,
endDate = null,
collection = firefoxClassicCollection,
textColor = null,
cardColor = null,
),
)
val allWallpapers = listOf(Wallpaper.Default) + localWallpapers + remoteWallpapers
Expand Down Expand Up @@ -278,7 +280,7 @@ class WallpapersUseCases(
Wallpapers.wallpaperSelected.record(
Wallpapers.WallpaperSelectedExtra(
name = wallpaper.name,
themeCollection = wallpaper.collectionName
themeCollection = wallpaper.collection.name
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,14 @@ class WallpaperFileManagerTest {

private fun generateWallpaper(name: String) = Wallpaper(
name = name,
collectionName = "",
availableLocales = null,
startDate = null,
endDate = null
textColor = null,
cardColor = null,
collection = Wallpaper.Collection(
name = Wallpaper.defaultName,
availableLocales = null,
startDate = null,
endDate = null,
learnMoreUrl = null
),
)
}
Loading

0 comments on commit ae26141

Please sign in to comment.