Fix website icon loading on main thread

This commit is contained in:
MM20 2021-12-04 13:54:30 +01:00
parent fa22eb4d71
commit 2273a0912a
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389

View File

@ -6,7 +6,6 @@ import android.graphics.Color
import android.graphics.Typeface import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.net.Uri import android.net.Uri
import android.util.Log
import android.webkit.URLUtil import android.webkit.URLUtil
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.graphics.toColorInt import androidx.core.graphics.toColorInt
@ -15,15 +14,15 @@ import com.bumptech.glide.Glide
import de.mm20.launcher2.graphics.TextDrawable import de.mm20.launcher2.graphics.TextDrawable
import de.mm20.launcher2.helper.NetworkUtils import de.mm20.launcher2.helper.NetworkUtils
import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.jsonObjectOf
import de.mm20.launcher2.ktx.sp import de.mm20.launcher2.ktx.sp
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.preferences.WebsiteProtocols import de.mm20.launcher2.preferences.WebsiteProtocols
import de.mm20.launcher2.websites.R import de.mm20.launcher2.websites.R
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.json.JSONObject
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.UncheckedIOException import org.jsoup.UncheckedIOException
import java.io.IOException import java.io.IOException
@ -33,34 +32,36 @@ import java.net.URL
import java.util.concurrent.ExecutionException import java.util.concurrent.ExecutionException
class Website( class Website(
override val label: String, override val label: String,
val url: String, val url: String,
val description: String, val description: String,
val image: String, val image: String,
val favicon: String, val favicon: String,
val color: Int val color: Int
) : Searchable() { ) : Searchable() {
override val key = "web://$url" override val key = "web://$url"
override suspend fun loadIconAsync(context: Context, size: Int): LauncherIcon? { override suspend fun loadIconAsync(context: Context, size: Int): LauncherIcon? {
if (favicon.isEmpty()) return null if (favicon.isEmpty()) return null
try { try {
val icon = Glide.with(context) return withContext(Dispatchers.IO) {
val icon = Glide.with(context)
.asDrawable() .asDrawable()
.load(favicon) .load(favicon)
.submit() .submit()
.get() .get()
val color = if (color != 0) color else { val color = if (color != 0) color else {
Palette Palette
.from(icon.toBitmap()) .from(icon.toBitmap())
.generate() .generate()
.getLightMutedColor(Color.WHITE) .getLightMutedColor(Color.WHITE)
} }
return LauncherIcon( LauncherIcon(
foreground = icon, foreground = icon,
background = ColorDrawable(color), background = ColorDrawable(color),
foregroundScale = 0.7f foregroundScale = 0.7f
) )
}
} catch (e: ExecutionException) { } catch (e: ExecutionException) {
return null return null
} }
@ -69,12 +70,16 @@ class Website(
override fun getPlaceholderIcon(context: Context): LauncherIcon { override fun getPlaceholderIcon(context: Context): LauncherIcon {
val drawable = if (label.isNotEmpty()) { val drawable = if (label.isNotEmpty()) {
TextDrawable(label[0].toString(), typeface = Typeface.DEFAULT_BOLD, fontSize = 40 * context.sp) TextDrawable(
label[0].toString(),
typeface = Typeface.DEFAULT_BOLD,
fontSize = 40 * context.sp
)
} else context.getDrawable(R.drawable.ic_website)!! } else context.getDrawable(R.drawable.ic_website)!!
return LauncherIcon( return LauncherIcon(
foreground = drawable, foreground = drawable,
background = ColorDrawable(if (color != 0) color else Color.LTGRAY), background = ColorDrawable(if (color != 0) color else Color.LTGRAY),
foregroundScale = 1f foregroundScale = 1f
) )
} }
@ -90,16 +95,19 @@ class Website(
var url = query var url = query
val prefs = LauncherPreferences.instance val prefs = LauncherPreferences.instance
if (!prefs.searchWebsite || if (!prefs.searchWebsite ||
NetworkUtils.isOffline(context, prefs.searchWebsitesMobileData)) return null NetworkUtils.isOffline(context, prefs.searchWebsitesMobileData)
val protocol = if (LauncherPreferences.instance.searchWebsitesProtocol == WebsiteProtocols.HTTPS) "https://" else "http://" ) return null
if (!query.startsWith("https://") && !query.startsWith("http://")) url = "$protocol$query" val protocol =
if (LauncherPreferences.instance.searchWebsitesProtocol == WebsiteProtocols.HTTPS) "https://" else "http://"
if (!query.startsWith("https://") && !query.startsWith("http://")) url =
"$protocol$query"
if (!URLUtil.isValidUrl(url)) return null if (!URLUtil.isValidUrl(url)) return null
try { try {
val request = Request.Builder() val request = Request.Builder()
.url(URL(url)) .url(URL(url))
.get() .get()
.tag("onlinesearch") .tag("onlinesearch")
.build() .build()
val response = client.newCall(request).execute() val response = client.newCall(request).execute()
url = response.request.url.toString() url = response.request.url.toString()
val body = response.body?.string() ?: return null val body = response.body?.string() ?: return null
@ -108,7 +116,8 @@ class Website(
if (title.isBlank()) title = doc.title() if (title.isBlank()) title = doc.title()
if (title.isBlank()) title = url if (title.isBlank()) title = url
var description = doc.select("meta[property=og:description]").attr("content") var description = doc.select("meta[property=og:description]").attr("content")
if (description.isBlank()) description = doc.select("meta[name=description]").attr("content") if (description.isBlank()) description =
doc.select("meta[name=description]").attr("content")
val color = try { val color = try {
val colorString = doc.select("meta[name=theme-color]").attr("content") val colorString = doc.select("meta[name=theme-color]").attr("content")
if (colorString.isNotEmpty()) colorString.toColorInt() if (colorString.isNotEmpty()) colorString.toColorInt()
@ -118,18 +127,21 @@ class Website(
} }
var image = doc.select("meta[property=og:image]").attr("content") var image = doc.select("meta[property=og:image]").attr("content")
var favicon = doc.select("link[rel=apple-touch-icon]").attr("href") var favicon = doc.select("link[rel=apple-touch-icon]").attr("href")
if (favicon.isBlank()) favicon = doc.head().select("meta[itemprop=image]").attr("content") if (favicon.isBlank()) favicon =
doc.head().select("meta[itemprop=image]").attr("content")
if (favicon.isBlank()) favicon = doc.select("link[rel=icon]").attr("href") if (favicon.isBlank()) favicon = doc.select("link[rel=icon]").attr("href")
if (favicon.isBlank()) favicon = doc.head().select("link[href~=.*\\.(ico|png)]").attr("href") if (favicon.isBlank()) favicon =
doc.head().select("link[href~=.*\\.(ico|png)]").attr("href")
if (!favicon.isBlank()) favicon = resolve(response.request.url, favicon) if (!favicon.isBlank()) favicon = resolve(response.request.url, favicon)
if (!image.isBlank()) image = resolve(response.request.url, image) if (!image.isBlank()) image = resolve(response.request.url, image)
return Website( return Website(
label = title, label = title,
url = url, url = url,
description = description, description = description,
image = image, image = image,
favicon = favicon, favicon = favicon,
color = color) color = color
)
} catch (e: IOException) { } catch (e: IOException) {
//Ignore. Not a HTML page or no connection. No result for this query //Ignore. Not a HTML page or no connection. No result for this query
} catch (e: UncheckedIOException) { } catch (e: UncheckedIOException) {