[fenix] For https://github.com/mozilla-mobile/fenix/issues/23432 - Use the imageUrl as the favicon for a provided top site

pull/600/head
Gabriel Luong 2 years ago committed by mergify[bot]
parent 4cc353c6fb
commit 60d9bcec18

@ -0,0 +1,29 @@
/* 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.ext
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import mozilla.components.concept.fetch.Client
import mozilla.components.concept.fetch.Request
import java.io.IOException
/**
* Given an image [url], fetches and returns a [Bitmap] if possible, otherwise null.
*
* @param url The image URL to fetch from.
*/
suspend fun Client.bitmapForUrl(url: String): Bitmap? = withContext(Dispatchers.IO) {
// Code below will cache it in Gecko's cache, which ensures that as long as we've fetched it once,
// we will be able to display this avatar as long as the cache isn't purged (e.g. via 'clear user data').
val body = try {
fetch(Request(url, useCaches = true)).body
} catch (e: IOException) {
return@withContext null
}
body.useStream { BitmapFactory.decodeStream(it) }
}

@ -4,20 +4,13 @@
package org.mozilla.fenix.ext package org.mozilla.fenix.ext
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri import android.net.Uri
import android.text.Editable import android.text.Editable
import android.util.Patterns import android.util.Patterns
import android.webkit.URLUtil import android.webkit.URLUtil
import androidx.core.net.toUri import androidx.core.net.toUri
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import mozilla.components.concept.fetch.Client
import mozilla.components.concept.fetch.Request
import mozilla.components.lib.publicsuffixlist.PublicSuffixList import mozilla.components.lib.publicsuffixlist.PublicSuffixList
import mozilla.components.support.ktx.android.net.hostWithoutCommonPrefixes import mozilla.components.support.ktx.android.net.hostWithoutCommonPrefixes
import java.io.IOException
import java.net.IDN import java.net.IDN
import java.util.Locale import java.util.Locale
@ -110,14 +103,3 @@ fun String.simplifiedUrl(): String {
* Returns an [Editable] for the provided string. * Returns an [Editable] for the provided string.
*/ */
fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this) fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this)
suspend fun bitmapForUrl(url: String, client: Client): Bitmap? = withContext(Dispatchers.IO) {
// Code below will cache it in Gecko's cache, which ensures that as long as we've fetched it once,
// we will be able to display this avatar as long as the cache isn't purged (e.g. via 'clear user data').
val body = try {
client.fetch(Request(url, useCaches = true)).body
} catch (e: IOException) {
return@withContext null
}
body.useStream { BitmapFactory.decodeStream(it) }
}

@ -10,12 +10,18 @@ import android.view.MotionEvent
import android.view.View import android.view.View
import android.widget.PopupWindow import android.widget.PopupWindow
import androidx.appcompat.content.res.AppCompatResources.getDrawable import androidx.appcompat.content.res.AppCompatResources.getDrawable
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import mozilla.components.browser.menu.BrowserMenuBuilder import mozilla.components.browser.menu.BrowserMenuBuilder
import mozilla.components.browser.menu.item.SimpleBrowserMenuItem import mozilla.components.browser.menu.item.SimpleBrowserMenuItem
import mozilla.components.feature.top.sites.TopSite import mozilla.components.feature.top.sites.TopSite
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.databinding.TopSiteItemBinding import org.mozilla.fenix.databinding.TopSiteItemBinding
import org.mozilla.fenix.ext.bitmapForUrl
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.loadIntoView import org.mozilla.fenix.ext.loadIntoView
import org.mozilla.fenix.home.sessioncontrol.TopSiteInteractor import org.mozilla.fenix.home.sessioncontrol.TopSiteInteractor
@ -72,6 +78,15 @@ class TopSiteItemViewHolder(
binding.topSiteTitle.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null) binding.topSiteTitle.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
} }
if (topSite is TopSite.Provided) {
CoroutineScope(IO).launch {
itemView.context.components.core.client.bitmapForUrl(topSite.imageUrl)?.let { bitmap ->
withContext(Main) {
binding.faviconImage.setImageBitmap(bitmap)
}
}
}
} else {
when (topSite.url) { when (topSite.url) {
SupportUtils.POCKET_TRENDING_URL -> { SupportUtils.POCKET_TRENDING_URL -> {
binding.faviconImage.setImageDrawable(getDrawable(itemView.context, R.drawable.ic_pocket)) binding.faviconImage.setImageDrawable(getDrawable(itemView.context, R.drawable.ic_pocket))
@ -95,6 +110,7 @@ class TopSiteItemViewHolder(
itemView.context.components.core.icons.loadIntoView(binding.faviconImage, topSite.url) itemView.context.components.core.icons.loadIntoView(binding.faviconImage, topSite.url)
} }
} }
}
this.topSite = topSite this.topSite = topSite
} }

@ -114,7 +114,7 @@ class AccountUiView(
private suspend fun toRoundedDrawable( private suspend fun toRoundedDrawable(
url: String, url: String,
context: Context context: Context
) = bitmapForUrl(url, httpClient)?.let { bitmap -> ) = httpClient.bitmapForUrl(url)?.let { bitmap ->
RoundedBitmapDrawableFactory.create(context.resources, bitmap).apply { RoundedBitmapDrawableFactory.create(context.resources, bitmap).apply {
isCircular = true isCircular = true
setAntiAlias(true) setAntiAlias(true)

Loading…
Cancel
Save