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.
95 lines
3.7 KiB
Kotlin
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"
|
|
}
|
|
}
|