Migrate search settings
This commit is contained in:
@@ -89,78 +89,4 @@ class Website(
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
return intent
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun search(context: Context, query: String, client: OkHttpClient): Website? {
|
||||
var url = query
|
||||
val prefs = LauncherPreferences.instance
|
||||
if (!prefs.searchWebsite ||
|
||||
NetworkUtils.isOffline(context, prefs.searchWebsitesMobileData)
|
||||
) return null
|
||||
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
|
||||
try {
|
||||
val request = Request.Builder()
|
||||
.url(URL(url))
|
||||
.get()
|
||||
.tag("onlinesearch")
|
||||
.build()
|
||||
val response = client.newCall(request).execute()
|
||||
url = response.request.url.toString()
|
||||
val body = response.body?.string() ?: return null
|
||||
val doc = Jsoup.parse(body)
|
||||
var title = doc.select("meta[property=og:title]").attr("content")
|
||||
if (title.isBlank()) title = doc.title()
|
||||
if (title.isBlank()) title = url
|
||||
var description = doc.select("meta[property=og:description]").attr("content")
|
||||
if (description.isBlank()) description =
|
||||
doc.select("meta[name=description]").attr("content")
|
||||
val color = try {
|
||||
val colorString = doc.select("meta[name=theme-color]").attr("content")
|
||||
if (colorString.isNotEmpty()) colorString.toColorInt()
|
||||
else 0
|
||||
} catch (e: IllegalArgumentException) {
|
||||
0
|
||||
}
|
||||
var image = doc.select("meta[property=og:image]").attr("content")
|
||||
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.select("link[rel=icon]").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 (!image.isBlank()) image = resolve(response.request.url, image)
|
||||
return Website(
|
||||
label = title,
|
||||
url = url,
|
||||
description = description,
|
||||
image = image,
|
||||
favicon = favicon,
|
||||
color = color
|
||||
)
|
||||
} catch (e: IOException) {
|
||||
//Ignore. Not a HTML page or no connection. No result for this query
|
||||
} catch (e: UncheckedIOException) {
|
||||
} catch (e: URISyntaxException) {
|
||||
} catch (e: RuntimeException) {
|
||||
} catch (e: IllegalArgumentException) {
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun resolve(url: HttpUrl, link: String): String {
|
||||
/*if(link.startsWith("http://") || link.startsWith("https://")) return link
|
||||
if(link.startsWith("//")) return "${urlTemplate.scheme()}:$link"
|
||||
if(link.startsWith("/")) return "${urlTemplate.scheme()}:$link"*/
|
||||
return try {
|
||||
URL(url.toUrl(), link).toString()
|
||||
} catch (e: MalformedURLException) {
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,36 @@
|
||||
package de.mm20.launcher2.websites
|
||||
|
||||
import android.content.Context
|
||||
import android.webkit.URLUtil
|
||||
import androidx.core.graphics.toColorInt
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.search.data.Website
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.UncheckedIOException
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import java.io.IOException
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URISyntaxException
|
||||
import java.net.URL
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
interface WebsiteRepository {
|
||||
fun search(query: String): Flow<Website?>
|
||||
}
|
||||
|
||||
class WebsiteRepositoryImpl(val context: Context) : WebsiteRepository {
|
||||
class WebsiteRepositoryImpl(val context: Context) : WebsiteRepository, KoinComponent {
|
||||
|
||||
private val dataStore: LauncherDataStore by inject()
|
||||
|
||||
private val httpClient = OkHttpClient
|
||||
.Builder()
|
||||
@@ -24,18 +41,86 @@ class WebsiteRepositoryImpl(val context: Context) : WebsiteRepository {
|
||||
|
||||
override fun search(query: String): Flow<Website?> = channelFlow {
|
||||
send(null)
|
||||
httpClient.dispatcher.run {
|
||||
runningCalls().forEach {
|
||||
it.cancel()
|
||||
}
|
||||
queuedCalls().forEach {
|
||||
it.cancel()
|
||||
}
|
||||
withContext(Dispatchers.IO) {
|
||||
httpClient.dispatcher.cancelAll()
|
||||
}
|
||||
if (query.isBlank()) return@channelFlow
|
||||
val website = withContext(Dispatchers.IO) {
|
||||
Website.search(context, query, httpClient)
|
||||
|
||||
dataStore.data.map { it.websiteSearch.enabled }.collectLatest {
|
||||
if(it) {
|
||||
val website = queryWebsite(query)
|
||||
send(website)
|
||||
} else {
|
||||
send(null)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private suspend fun queryWebsite(query: String): Website? {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
var url = query
|
||||
val protocol = "https://"
|
||||
if (!query.startsWith("https://") && !query.startsWith("http://")) url =
|
||||
"$protocol$query"
|
||||
if (!URLUtil.isValidUrl(url)) return@withContext null
|
||||
try {
|
||||
val request = Request.Builder()
|
||||
.url(URL(url))
|
||||
.get()
|
||||
.tag("onlinesearch")
|
||||
.build()
|
||||
val response = httpClient.newCall(request).execute()
|
||||
url = response.request.url.toString()
|
||||
val body = response.body?.string() ?: return@withContext null
|
||||
val doc = Jsoup.parse(body)
|
||||
var title = doc.select("meta[property=og:title]").attr("content")
|
||||
if (title.isBlank()) title = doc.title()
|
||||
if (title.isBlank()) title = url
|
||||
var description = doc.select("meta[property=og:description]").attr("content")
|
||||
if (description.isBlank()) description =
|
||||
doc.select("meta[name=description]").attr("content")
|
||||
val color = try {
|
||||
val colorString = doc.select("meta[name=theme-color]").attr("content")
|
||||
if (colorString.isNotEmpty()) colorString.toColorInt()
|
||||
else 0
|
||||
} catch (e: IllegalArgumentException) {
|
||||
0
|
||||
}
|
||||
var image = doc.select("meta[property=og:image]").attr("content")
|
||||
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.select("link[rel=icon]").attr("href")
|
||||
if (favicon.isBlank()) favicon =
|
||||
doc.head().select("link[href~=.*\\.(ico|png)]").attr("href")
|
||||
if (!favicon.isBlank()) favicon = resolveUrl(response.request.url, favicon)
|
||||
if (!image.isBlank()) image = resolveUrl(response.request.url, image)
|
||||
return@withContext Website(
|
||||
label = title,
|
||||
url = url,
|
||||
description = description,
|
||||
image = image,
|
||||
favicon = favicon,
|
||||
color = color
|
||||
)
|
||||
} catch (e: IOException) {
|
||||
//Ignore. Not a HTML page or no connection. No result for this query
|
||||
} catch (e: UncheckedIOException) {
|
||||
} catch (e: URISyntaxException) {
|
||||
} catch (e: RuntimeException) {
|
||||
} catch (e: IllegalArgumentException) {
|
||||
}
|
||||
return@withContext null
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun resolveUrl(url: HttpUrl, link: String): String {
|
||||
return try {
|
||||
URL(url.toUrl(), link).toString()
|
||||
} catch (e: MalformedURLException) {
|
||||
""
|
||||
}
|
||||
send(website)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user