+13
-13
@@ -1,21 +1,21 @@
|
||||
package de.mm20.launcher2.searchactions
|
||||
|
||||
import de.mm20.launcher2.searchactions.builders.WebsearchActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.CustomWebsearchActionBuilder
|
||||
|
||||
fun knownWebsearchByHostname(hostname: String): WebsearchActionBuilder? {
|
||||
fun knownWebsearchByHostname(hostname: String): CustomWebsearchActionBuilder? {
|
||||
// List of popular web search engines that do not implement the OpenSearch standard
|
||||
return when(hostname) {
|
||||
"google.com" -> WebsearchActionBuilder(label = "Google", urlTemplate = "https://google.com/search?q=\${1}")
|
||||
"bing.com" -> WebsearchActionBuilder(label = "Google", urlTemplate = "https://bing.com/search?q=\${1}")
|
||||
"amazon.com" -> WebsearchActionBuilder(label = "Amazon", urlTemplate = "https://www.amazon.com/s?k=\${1}")
|
||||
"amazon.de" -> WebsearchActionBuilder(label = "Amazon DE", urlTemplate = "https://www.amazon.de/s?k=\${1}")
|
||||
"amazon.co.uk" -> WebsearchActionBuilder(label = "Amazon UK", urlTemplate = "https://www.amazon.co.uk/s?k=\${1}")
|
||||
"amazon.fr" -> WebsearchActionBuilder(label = "Amazon FR", urlTemplate = "https://www.amazon.fr/s?k=\${1}")
|
||||
"amazon.co.jp" -> WebsearchActionBuilder(label = "Amazon JP", urlTemplate = "https://www.amazon.co.jp/s?k=\${1}")
|
||||
"amazon.ca" -> WebsearchActionBuilder(label = "Amazon CA", urlTemplate = "https://www.amazon.ca/s?k=\${1}")
|
||||
"amazon.cn" -> WebsearchActionBuilder(label = "Amazon CN", urlTemplate = "https://www.amazon.cn/s?k=\${1}")
|
||||
"duckduckgo.com" -> WebsearchActionBuilder(label = "DuckDuckGo", urlTemplate = "https://duckduckgo.com/?q=\${1}")
|
||||
"yahoo.com" -> WebsearchActionBuilder(label = "DuckDuckGo", urlTemplate = "https://search.yahoo.com/search?p=\${1}")
|
||||
"google.com" -> CustomWebsearchActionBuilder(label = "Google", urlTemplate = "https://google.com/search?q=\${1}")
|
||||
"bing.com" -> CustomWebsearchActionBuilder(label = "Google", urlTemplate = "https://bing.com/search?q=\${1}")
|
||||
"amazon.com" -> CustomWebsearchActionBuilder(label = "Amazon", urlTemplate = "https://www.amazon.com/s?k=\${1}")
|
||||
"amazon.de" -> CustomWebsearchActionBuilder(label = "Amazon DE", urlTemplate = "https://www.amazon.de/s?k=\${1}")
|
||||
"amazon.co.uk" -> CustomWebsearchActionBuilder(label = "Amazon UK", urlTemplate = "https://www.amazon.co.uk/s?k=\${1}")
|
||||
"amazon.fr" -> CustomWebsearchActionBuilder(label = "Amazon FR", urlTemplate = "https://www.amazon.fr/s?k=\${1}")
|
||||
"amazon.co.jp" -> CustomWebsearchActionBuilder(label = "Amazon JP", urlTemplate = "https://www.amazon.co.jp/s?k=\${1}")
|
||||
"amazon.ca" -> CustomWebsearchActionBuilder(label = "Amazon CA", urlTemplate = "https://www.amazon.ca/s?k=\${1}")
|
||||
"amazon.cn" -> CustomWebsearchActionBuilder(label = "Amazon CN", urlTemplate = "https://www.amazon.cn/s?k=\${1}")
|
||||
"duckduckgo.com" -> CustomWebsearchActionBuilder(label = "DuckDuckGo", urlTemplate = "https://duckduckgo.com/?q=\${1}")
|
||||
"yahoo.com" -> CustomWebsearchActionBuilder(label = "Yahoo", urlTemplate = "https://search.yahoo.com/search?p=\${1}")
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
+2
@@ -14,6 +14,7 @@ import de.mm20.launcher2.searchactions.builders.ScheduleEventActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.SearchActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.SetAlarmActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.TimerActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.WebsearchActionBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
@@ -57,6 +58,7 @@ internal class SearchActionRepositoryImpl(
|
||||
SetAlarmActionBuilder(context),
|
||||
TimerActionBuilder(context),
|
||||
OpenUrlActionBuilder(context),
|
||||
WebsearchActionBuilder(context),
|
||||
)
|
||||
|
||||
return allActions
|
||||
|
||||
+6
-6
@@ -15,7 +15,7 @@ import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
import de.mm20.launcher2.searchactions.builders.SearchActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.WebsearchActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.CustomWebsearchActionBuilder
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
@@ -43,7 +43,7 @@ interface SearchActionService {
|
||||
|
||||
fun saveSearchActionBuilders(builders: List<SearchActionBuilder>)
|
||||
|
||||
suspend fun importWebsearch(url: String, iconSize: Int): WebsearchActionBuilder?
|
||||
suspend fun importWebsearch(url: String, iconSize: Int): CustomWebsearchActionBuilder?
|
||||
|
||||
suspend fun getSearchActivities(): List<ComponentName>
|
||||
|
||||
@@ -88,7 +88,7 @@ internal class SearchActionServiceImpl(
|
||||
repository.saveSearchActionBuilders(builders)
|
||||
}
|
||||
|
||||
override suspend fun importWebsearch(url: String, iconSize: Int): WebsearchActionBuilder? =
|
||||
override suspend fun importWebsearch(url: String, iconSize: Int): CustomWebsearchActionBuilder? =
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val u = if (url.startsWith("http://") || url.startsWith("https://")) {
|
||||
@@ -98,7 +98,7 @@ internal class SearchActionServiceImpl(
|
||||
}
|
||||
|
||||
if (u.contains("${1}")) {
|
||||
return@withContext WebsearchActionBuilder(
|
||||
return@withContext CustomWebsearchActionBuilder(
|
||||
urlTemplate = u,
|
||||
label = "",
|
||||
iconColor = 0,
|
||||
@@ -136,7 +136,7 @@ internal class SearchActionServiceImpl(
|
||||
private suspend fun importOpenSearch(
|
||||
openSearchHref: String,
|
||||
iconSize: Int
|
||||
): WebsearchActionBuilder? {
|
||||
): CustomWebsearchActionBuilder? {
|
||||
try {
|
||||
val httpClient = OkHttpClient()
|
||||
val request = Request.Builder()
|
||||
@@ -207,7 +207,7 @@ internal class SearchActionServiceImpl(
|
||||
createIcon(uri, iconSize)
|
||||
}
|
||||
|
||||
return WebsearchActionBuilder(
|
||||
return CustomWebsearchActionBuilder(
|
||||
label = label ?: "",
|
||||
icon = if (localIconUrl == null) SearchActionIcon.Search else SearchActionIcon.Custom,
|
||||
customIcon = localIconUrl,
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package de.mm20.launcher2.searchactions.actions
|
||||
|
||||
import android.app.SearchManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import de.mm20.launcher2.ktx.tryStartActivity
|
||||
|
||||
data class WebsearchAction(
|
||||
override val label: String,
|
||||
val query: String,
|
||||
): SearchAction {
|
||||
override val icon: SearchActionIcon = SearchActionIcon.WebSearch
|
||||
override val iconColor: Int = 0
|
||||
override val customIcon: String? = null
|
||||
|
||||
override fun start(context: Context) {
|
||||
val intent = Intent(Intent.ACTION_WEB_SEARCH).apply {
|
||||
putExtra(SearchManager.QUERY, query)
|
||||
}
|
||||
context.tryStartActivity(intent)
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package de.mm20.launcher2.searchactions.builders
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.OpenUrlAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
import java.net.URLEncoder
|
||||
|
||||
data class CustomWebsearchActionBuilder(
|
||||
override val label: String,
|
||||
val urlTemplate: String,
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Search,
|
||||
override val iconColor: Int = 0,
|
||||
override val customIcon: String? = null,
|
||||
val encoding: QueryEncoding = QueryEncoding.UrlEncode,
|
||||
) : CustomizableSearchActionBuilder {
|
||||
|
||||
override val key: String
|
||||
get() = "web://$urlTemplate"
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction {
|
||||
val url = urlTemplate.replace("\${1}", encodeQuery(classifiedQuery.text, encoding))
|
||||
return OpenUrlAction(
|
||||
label = label,
|
||||
url = url,
|
||||
icon = icon,
|
||||
customIcon = customIcon,
|
||||
iconColor = iconColor,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private fun encodeQuery(query: String, encoding: QueryEncoding): String {
|
||||
return when (encoding) {
|
||||
QueryEncoding.UrlEncode -> Uri.encode(query)
|
||||
QueryEncoding.FormData -> URLEncoder.encode(query, "UTF-8")
|
||||
QueryEncoding.None -> query
|
||||
}
|
||||
}
|
||||
|
||||
enum class QueryEncoding {
|
||||
UrlEncode,
|
||||
FormData,
|
||||
None;
|
||||
|
||||
fun toInt(): Int {
|
||||
return when (this) {
|
||||
UrlEncode -> 0
|
||||
FormData -> 1
|
||||
None -> 2
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromInt(value: Int?): QueryEncoding {
|
||||
return when (value) {
|
||||
1 -> FormData
|
||||
2 -> None
|
||||
else -> UrlEncode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-5
@@ -1,9 +1,7 @@
|
||||
package de.mm20.launcher2.searchactions.builders
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.metrics.Event
|
||||
import de.mm20.launcher2.database.entities.SearchActionEntity
|
||||
import de.mm20.launcher2.ktx.jsonObjectOf
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
@@ -34,13 +32,13 @@ interface SearchActionBuilder {
|
||||
}
|
||||
when (entity.type) {
|
||||
"url" -> {
|
||||
return WebsearchActionBuilder(
|
||||
return CustomWebsearchActionBuilder(
|
||||
label = entity.label ?: "",
|
||||
urlTemplate = entity.data ?: return null,
|
||||
iconColor = entity.color ?: 0,
|
||||
icon = SearchActionIcon.fromInt(entity.icon),
|
||||
customIcon = entity.customIcon,
|
||||
encoding = WebsearchActionBuilder.QueryEncoding.fromInt(options?.optInt("encoding"))
|
||||
encoding = CustomWebsearchActionBuilder.QueryEncoding.fromInt(options?.optInt("encoding"))
|
||||
)
|
||||
}
|
||||
"app" -> {
|
||||
@@ -70,13 +68,14 @@ interface SearchActionBuilder {
|
||||
"timer" -> return TimerActionBuilder(context)
|
||||
"calendar" -> return ScheduleEventActionBuilder(context)
|
||||
"website" -> return OpenUrlActionBuilder(context)
|
||||
"websearch" -> return WebsearchActionBuilder(context)
|
||||
else -> return null
|
||||
}
|
||||
}
|
||||
|
||||
internal fun toDatabaseEntity(builder: SearchActionBuilder, position: Int): SearchActionEntity {
|
||||
return when(builder) {
|
||||
is WebsearchActionBuilder -> SearchActionEntity(
|
||||
is CustomWebsearchActionBuilder -> SearchActionEntity(
|
||||
position = position,
|
||||
type = "url",
|
||||
label = builder.label,
|
||||
|
||||
+11
-52
@@ -1,66 +1,25 @@
|
||||
package de.mm20.launcher2.searchactions.builders
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import de.mm20.launcher2.searchactions.R
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.OpenUrlAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
import java.net.URLEncoder
|
||||
import de.mm20.launcher2.searchactions.actions.WebsearchAction
|
||||
|
||||
data class WebsearchActionBuilder(
|
||||
class WebsearchActionBuilder(
|
||||
override val label: String,
|
||||
val urlTemplate: String,
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Search,
|
||||
override val iconColor: Int = 0,
|
||||
override val customIcon: String? = null,
|
||||
val encoding: QueryEncoding = QueryEncoding.UrlEncode,
|
||||
) : CustomizableSearchActionBuilder {
|
||||
) : SearchActionBuilder {
|
||||
|
||||
constructor(context: Context) : this(context.getString(R.string.search_action_websearch))
|
||||
|
||||
override val icon: SearchActionIcon = SearchActionIcon.WebSearch
|
||||
override val key: String
|
||||
get() = "web://$urlTemplate"
|
||||
get() = "websearch"
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction {
|
||||
val url = urlTemplate.replace("\${1}", encodeQuery(classifiedQuery.text, encoding))
|
||||
return OpenUrlAction(
|
||||
label = label,
|
||||
url = url,
|
||||
icon = icon,
|
||||
customIcon = customIcon,
|
||||
iconColor = iconColor,
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
||||
return WebsearchAction(
|
||||
context.getString(R.string.search_action_websearch), classifiedQuery.text
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private fun encodeQuery(query: String, encoding: QueryEncoding): String {
|
||||
return when (encoding) {
|
||||
QueryEncoding.UrlEncode -> Uri.encode(query)
|
||||
QueryEncoding.FormData -> URLEncoder.encode(query, "UTF-8")
|
||||
QueryEncoding.None -> query
|
||||
}
|
||||
}
|
||||
|
||||
enum class QueryEncoding {
|
||||
UrlEncode,
|
||||
FormData,
|
||||
None;
|
||||
|
||||
fun toInt(): Int {
|
||||
return when (this) {
|
||||
UrlEncode -> 0
|
||||
FormData -> 1
|
||||
None -> 2
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromInt(value: Int?): QueryEncoding {
|
||||
return when (value) {
|
||||
1 -> FormData
|
||||
2 -> None
|
||||
else -> UrlEncode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user