You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iceraven-browser/app/src/main/java/org/mozilla/fenix/wallpapers/LegacyWallpaperDownloader.kt

95 lines
3.7 KiB
Kotlin

/* 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 kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import mozilla.components.concept.fetch.Client
import mozilla.components.concept.fetch.Request
import mozilla.components.concept.fetch.isSuccess
import mozilla.components.support.base.log.logger.Logger
import org.mozilla.fenix.BuildConfig
import java.io.File
/**
* Can download wallpapers from a remote host.
*
* @param context Required for writing files to local storage.
* @param client Required for fetching files from network.
*/
class LegacyWallpaperDownloader(
private val context: Context,
private val client: Client,
) {
private val logger = Logger("WallpaperDownloader")
private val remoteHost = BuildConfig.WALLPAPER_URL
/**
* Downloads a wallpaper from the network. Will try to fetch 4 versions of each wallpaper:
* portrait/light - portrait/dark - landscape/light - landscape/dark. These are expected to be
* found at a remote path in the form:
* <WALLPAPER_URL>/<resolution>/<orientation>/<app theme>/<wallpaper theme>/<wallpaper name>.png
*/
suspend fun downloadWallpaper(wallpaper: Wallpaper) = withContext(Dispatchers.IO) {
if (remoteHost.isNullOrEmpty()) {
return@withContext
}
for (metadata in wallpaper.toMetadata(context)) {
val localFile = File(context.filesDir.absolutePath, metadata.localPath)
if (localFile.exists()) continue
val request = Request(
url = "$remoteHost/${metadata.remotePath}",
method = Request.Method.GET,
)
Result.runCatching {
val response = client.fetch(request)
if (!response.isSuccess) {
logger.error("Download response failure code: ${response.status}")
return@withContext
}
File(localFile.path.substringBeforeLast("/")).mkdirs()
response.body.useStream { input ->
input.copyTo(localFile.outputStream())
}
}.onFailure {
Result.runCatching {
if (localFile.exists()) {
localFile.delete()
}
}.onFailure { e ->
logger.error("Failed to delete stale wallpaper bitmaps while downloading", e)
}
logger.error(it.message ?: "Download failed: no throwable message included.", it)
}
}
}
private data class WallpaperMetadata(val remotePath: String, val localPath: String)
private fun Wallpaper.toMetadata(context: Context): List<WallpaperMetadata> =
listOf("landscape", "portrait").flatMap { orientation ->
listOf("light", "dark").map { theme ->
val localPath = "wallpapers/$orientation/$theme/$name.png"
val remotePath = "${context.resolutionSegment()}/" +
"$orientation/" +
"$theme/" +
"${collection.name}/" +
"$name.png"
WallpaperMetadata(remotePath, localPath)
}
}
@Suppress("MagicNumber")
private fun Context.resolutionSegment(): String = when (resources.displayMetrics.densityDpi) {
// targeting hdpi and greater density resolutions https://developer.android.com/training/multiscreen/screendensities
in 0..240 -> "low"
in 240..320 -> "medium"
else -> "high"
}
}