parent
afd407dfc2
commit
f4b217b30c
@ -85,7 +85,7 @@ import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
|||||||
import de.mm20.launcher2.searchactions.builders.AppSearchActionBuilder
|
import de.mm20.launcher2.searchactions.builders.AppSearchActionBuilder
|
||||||
import de.mm20.launcher2.searchactions.builders.CustomIntentActionBuilder
|
import de.mm20.launcher2.searchactions.builders.CustomIntentActionBuilder
|
||||||
import de.mm20.launcher2.searchactions.builders.CustomizableSearchActionBuilder
|
import de.mm20.launcher2.searchactions.builders.CustomizableSearchActionBuilder
|
||||||
import de.mm20.launcher2.searchactions.builders.WebsearchActionBuilder
|
import de.mm20.launcher2.searchactions.builders.CustomWebsearchActionBuilder
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
import de.mm20.launcher2.ui.component.BottomSheetDialog
|
||||||
import de.mm20.launcher2.ui.component.ExperimentalBadge
|
import de.mm20.launcher2.ui.component.ExperimentalBadge
|
||||||
@ -406,7 +406,7 @@ fun CustomizeWebSearch(viewModel: EditSearchActionSheetVM, paddingValues: Paddin
|
|||||||
.padding(paddingValues)
|
.padding(paddingValues)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
if (searchAction != null && searchAction is WebsearchActionBuilder) {
|
if (searchAction != null && searchAction is CustomWebsearchActionBuilder) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.padding(bottom = 16.dp),
|
modifier = Modifier.padding(bottom = 16.dp),
|
||||||
verticalAlignment = Alignment.Bottom
|
verticalAlignment = Alignment.Bottom
|
||||||
@ -436,7 +436,7 @@ fun CustomizeWebSearch(viewModel: EditSearchActionSheetVM, paddingValues: Paddin
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
value = (searchAction as WebsearchActionBuilder).urlTemplate,
|
value = (searchAction as CustomWebsearchActionBuilder).urlTemplate,
|
||||||
onValueChange = { viewModel.setUrlTemplate(it) },
|
onValueChange = { viewModel.setUrlTemplate(it) },
|
||||||
label = { Text(stringResource(R.string.search_action_websearch_url)) },
|
label = { Text(stringResource(R.string.search_action_websearch_url)) },
|
||||||
supportingText = {
|
supportingText = {
|
||||||
@ -507,11 +507,11 @@ fun CustomizeWebSearch(viewModel: EditSearchActionSheetVM, paddingValues: Paddin
|
|||||||
ListPreference(
|
ListPreference(
|
||||||
title = stringResource(R.string.websearch_dialog_query_encoding),
|
title = stringResource(R.string.websearch_dialog_query_encoding),
|
||||||
items = listOf(
|
items = listOf(
|
||||||
stringResource(id = R.string.websearch_dialog_query_encoding_url) to WebsearchActionBuilder.QueryEncoding.UrlEncode,
|
stringResource(id = R.string.websearch_dialog_query_encoding_url) to CustomWebsearchActionBuilder.QueryEncoding.UrlEncode,
|
||||||
stringResource(id = R.string.websearch_dialog_query_encoding_form) to WebsearchActionBuilder.QueryEncoding.FormData,
|
stringResource(id = R.string.websearch_dialog_query_encoding_form) to CustomWebsearchActionBuilder.QueryEncoding.FormData,
|
||||||
stringResource(id = R.string.websearch_dialog_query_encoding_none) to WebsearchActionBuilder.QueryEncoding.None,
|
stringResource(id = R.string.websearch_dialog_query_encoding_none) to CustomWebsearchActionBuilder.QueryEncoding.None,
|
||||||
),
|
),
|
||||||
value = (searchAction as WebsearchActionBuilder).encoding,
|
value = (searchAction as CustomWebsearchActionBuilder).encoding,
|
||||||
onValueChanged = {
|
onValueChanged = {
|
||||||
viewModel.setQueryEncoding(it)
|
viewModel.setQueryEncoding(it)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
|||||||
import de.mm20.launcher2.searchactions.builders.AppSearchActionBuilder
|
import de.mm20.launcher2.searchactions.builders.AppSearchActionBuilder
|
||||||
import de.mm20.launcher2.searchactions.builders.CustomIntentActionBuilder
|
import de.mm20.launcher2.searchactions.builders.CustomIntentActionBuilder
|
||||||
import de.mm20.launcher2.searchactions.builders.CustomizableSearchActionBuilder
|
import de.mm20.launcher2.searchactions.builders.CustomizableSearchActionBuilder
|
||||||
import de.mm20.launcher2.searchactions.builders.WebsearchActionBuilder
|
import de.mm20.launcher2.searchactions.builders.CustomWebsearchActionBuilder
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -41,7 +41,7 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
initialCustomIcon = searchAction?.customIcon
|
initialCustomIcon = searchAction?.customIcon
|
||||||
currentPage.value = when (searchAction) {
|
currentPage.value = when (searchAction) {
|
||||||
is AppSearchActionBuilder -> EditSearchActionPage.CustomizeAppSearch
|
is AppSearchActionBuilder -> EditSearchActionPage.CustomizeAppSearch
|
||||||
is WebsearchActionBuilder -> EditSearchActionPage.CustomizeWebSearch
|
is CustomWebsearchActionBuilder -> EditSearchActionPage.CustomizeWebSearch
|
||||||
is CustomIntentActionBuilder -> EditSearchActionPage.CustomizeCustomIntent
|
is CustomIntentActionBuilder -> EditSearchActionPage.CustomizeCustomIntent
|
||||||
else -> EditSearchActionPage.SelectType
|
else -> EditSearchActionPage.SelectType
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
val newAction = when (action) {
|
val newAction = when (action) {
|
||||||
is CustomIntentActionBuilder -> action.copy(label = label)
|
is CustomIntentActionBuilder -> action.copy(label = label)
|
||||||
is AppSearchActionBuilder -> action.copy(label = label)
|
is AppSearchActionBuilder -> action.copy(label = label)
|
||||||
is WebsearchActionBuilder -> action.copy(label = label)
|
is CustomWebsearchActionBuilder -> action.copy(label = label)
|
||||||
}
|
}
|
||||||
|
|
||||||
searchAction.value = newAction
|
searchAction.value = newAction
|
||||||
@ -120,7 +120,7 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
it.baseIntent.setComponent(componentName)
|
it.baseIntent.setComponent(componentName)
|
||||||
}
|
}
|
||||||
|
|
||||||
is WebsearchActionBuilder -> action
|
is CustomWebsearchActionBuilder -> action
|
||||||
}
|
}
|
||||||
|
|
||||||
searchAction.value = newAction
|
searchAction.value = newAction
|
||||||
@ -160,7 +160,7 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun skipWebsearchImport() {
|
fun skipWebsearchImport() {
|
||||||
searchAction.value = WebsearchActionBuilder(
|
searchAction.value = CustomWebsearchActionBuilder(
|
||||||
urlTemplate = "",
|
urlTemplate = "",
|
||||||
iconColor = 0,
|
iconColor = 0,
|
||||||
icon = SearchActionIcon.Search,
|
icon = SearchActionIcon.Search,
|
||||||
@ -171,7 +171,7 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
|
|
||||||
fun setUrlTemplate(template: String) {
|
fun setUrlTemplate(template: String) {
|
||||||
val action = searchAction.value ?: return
|
val action = searchAction.value ?: return
|
||||||
if (action is WebsearchActionBuilder) {
|
if (action is CustomWebsearchActionBuilder) {
|
||||||
searchAction.value = action.copy(
|
searchAction.value = action.copy(
|
||||||
urlTemplate = template
|
urlTemplate = template
|
||||||
)
|
)
|
||||||
@ -181,12 +181,12 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
|
|
||||||
private val invalidWebsearchUrl = mutableStateOf<String?>(null)
|
private val invalidWebsearchUrl = mutableStateOf<String?>(null)
|
||||||
val websearchInvalidUrlError =
|
val websearchInvalidUrlError =
|
||||||
derivedStateOf { invalidWebsearchUrl.value == (searchAction.value as? WebsearchActionBuilder)?.urlTemplate }
|
derivedStateOf { invalidWebsearchUrl.value == (searchAction.value as? CustomWebsearchActionBuilder)?.urlTemplate }
|
||||||
val customIntentKeyError = mutableStateOf(false)
|
val customIntentKeyError = mutableStateOf(false)
|
||||||
fun validate(): Boolean {
|
fun validate(): Boolean {
|
||||||
val action = searchAction.value ?: return false
|
val action = searchAction.value ?: return false
|
||||||
|
|
||||||
if (action is WebsearchActionBuilder) {
|
if (action is CustomWebsearchActionBuilder) {
|
||||||
val valid = action.urlTemplate.contains("\${1}")
|
val valid = action.urlTemplate.contains("\${1}")
|
||||||
invalidWebsearchUrl.value = if (valid) null else action.urlTemplate
|
invalidWebsearchUrl.value = if (valid) null else action.urlTemplate
|
||||||
return valid
|
return valid
|
||||||
@ -218,7 +218,7 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
deleteCustomIcon(action.customIcon)
|
deleteCustomIcon(action.customIcon)
|
||||||
}
|
}
|
||||||
searchAction.value = when (action) {
|
searchAction.value = when (action) {
|
||||||
is WebsearchActionBuilder -> action.copy(icon = icon, customIcon = null, iconColor = 0)
|
is CustomWebsearchActionBuilder -> action.copy(icon = icon, customIcon = null, iconColor = 0)
|
||||||
is CustomIntentActionBuilder -> action.copy(
|
is CustomIntentActionBuilder -> action.copy(
|
||||||
icon = icon,
|
icon = icon,
|
||||||
customIcon = null,
|
customIcon = null,
|
||||||
@ -235,7 +235,7 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
deleteCustomIcon(action.customIcon)
|
deleteCustomIcon(action.customIcon)
|
||||||
}
|
}
|
||||||
searchAction.value = when (action) {
|
searchAction.value = when (action) {
|
||||||
is WebsearchActionBuilder -> action.copy(
|
is CustomWebsearchActionBuilder -> action.copy(
|
||||||
customIcon = iconPath,
|
customIcon = iconPath,
|
||||||
iconColor = 1,
|
iconColor = 1,
|
||||||
icon = SearchActionIcon.Custom
|
icon = SearchActionIcon.Custom
|
||||||
@ -269,7 +269,7 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
fun applyIcon() {
|
fun applyIcon() {
|
||||||
currentPage.value = when (searchAction.value) {
|
currentPage.value = when (searchAction.value) {
|
||||||
is AppSearchActionBuilder -> EditSearchActionPage.CustomizeAppSearch
|
is AppSearchActionBuilder -> EditSearchActionPage.CustomizeAppSearch
|
||||||
is WebsearchActionBuilder -> EditSearchActionPage.CustomizeWebSearch
|
is CustomWebsearchActionBuilder -> EditSearchActionPage.CustomizeWebSearch
|
||||||
is CustomIntentActionBuilder -> EditSearchActionPage.CustomizeCustomIntent
|
is CustomIntentActionBuilder -> EditSearchActionPage.CustomizeCustomIntent
|
||||||
null -> EditSearchActionPage.SelectType
|
null -> EditSearchActionPage.SelectType
|
||||||
}
|
}
|
||||||
@ -278,7 +278,7 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
fun setIconColor(color: Int) {
|
fun setIconColor(color: Int) {
|
||||||
val action = searchAction.value ?: return
|
val action = searchAction.value ?: return
|
||||||
searchAction.value = when (action) {
|
searchAction.value = when (action) {
|
||||||
is WebsearchActionBuilder -> action.copy(iconColor = color)
|
is CustomWebsearchActionBuilder -> action.copy(iconColor = color)
|
||||||
is CustomIntentActionBuilder -> action.copy(iconColor = color)
|
is CustomIntentActionBuilder -> action.copy(iconColor = color)
|
||||||
is AppSearchActionBuilder -> action.copy(iconColor = color)
|
is AppSearchActionBuilder -> action.copy(iconColor = color)
|
||||||
}
|
}
|
||||||
@ -495,10 +495,10 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setQueryEncoding(encoding: WebsearchActionBuilder.QueryEncoding) {
|
fun setQueryEncoding(encoding: CustomWebsearchActionBuilder.QueryEncoding) {
|
||||||
val action = searchAction.value ?: return
|
val action = searchAction.value ?: return
|
||||||
searchAction.value = when (action) {
|
searchAction.value = when (action) {
|
||||||
is WebsearchActionBuilder -> action.copy(
|
is CustomWebsearchActionBuilder -> action.copy(
|
||||||
encoding = encoding
|
encoding = encoding
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -727,6 +727,7 @@
|
|||||||
<string name="search_action_email">Email</string>
|
<string name="search_action_email">Email</string>
|
||||||
<string name="search_action_alarm">Set alarm</string>
|
<string name="search_action_alarm">Set alarm</string>
|
||||||
<string name="search_action_timer">Start timer</string>
|
<string name="search_action_timer">Start timer</string>
|
||||||
|
<string name="search_action_websearch">Web search</string>
|
||||||
<string name="search_action_contact">Add to contacts</string>
|
<string name="search_action_contact">Add to contacts</string>
|
||||||
<string name="search_action_open_url">View website</string>
|
<string name="search_action_open_url">View website</string>
|
||||||
<string name="search_action_event">Schedule event</string>
|
<string name="search_action_event">Schedule event</string>
|
||||||
|
|||||||
@ -1,21 +1,21 @@
|
|||||||
package de.mm20.launcher2.searchactions
|
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
|
// List of popular web search engines that do not implement the OpenSearch standard
|
||||||
return when(hostname) {
|
return when(hostname) {
|
||||||
"google.com" -> WebsearchActionBuilder(label = "Google", urlTemplate = "https://google.com/search?q=\${1}")
|
"google.com" -> CustomWebsearchActionBuilder(label = "Google", urlTemplate = "https://google.com/search?q=\${1}")
|
||||||
"bing.com" -> WebsearchActionBuilder(label = "Google", urlTemplate = "https://bing.com/search?q=\${1}")
|
"bing.com" -> CustomWebsearchActionBuilder(label = "Google", urlTemplate = "https://bing.com/search?q=\${1}")
|
||||||
"amazon.com" -> WebsearchActionBuilder(label = "Amazon", urlTemplate = "https://www.amazon.com/s?k=\${1}")
|
"amazon.com" -> CustomWebsearchActionBuilder(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.de" -> CustomWebsearchActionBuilder(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.co.uk" -> CustomWebsearchActionBuilder(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.fr" -> CustomWebsearchActionBuilder(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.co.jp" -> CustomWebsearchActionBuilder(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.ca" -> CustomWebsearchActionBuilder(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}")
|
"amazon.cn" -> CustomWebsearchActionBuilder(label = "Amazon CN", urlTemplate = "https://www.amazon.cn/s?k=\${1}")
|
||||||
"duckduckgo.com" -> WebsearchActionBuilder(label = "DuckDuckGo", urlTemplate = "https://duckduckgo.com/?q=\${1}")
|
"duckduckgo.com" -> CustomWebsearchActionBuilder(label = "DuckDuckGo", urlTemplate = "https://duckduckgo.com/?q=\${1}")
|
||||||
"yahoo.com" -> WebsearchActionBuilder(label = "DuckDuckGo", urlTemplate = "https://search.yahoo.com/search?p=\${1}")
|
"yahoo.com" -> CustomWebsearchActionBuilder(label = "Yahoo", urlTemplate = "https://search.yahoo.com/search?p=\${1}")
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -14,6 +14,7 @@ import de.mm20.launcher2.searchactions.builders.ScheduleEventActionBuilder
|
|||||||
import de.mm20.launcher2.searchactions.builders.SearchActionBuilder
|
import de.mm20.launcher2.searchactions.builders.SearchActionBuilder
|
||||||
import de.mm20.launcher2.searchactions.builders.SetAlarmActionBuilder
|
import de.mm20.launcher2.searchactions.builders.SetAlarmActionBuilder
|
||||||
import de.mm20.launcher2.searchactions.builders.TimerActionBuilder
|
import de.mm20.launcher2.searchactions.builders.TimerActionBuilder
|
||||||
|
import de.mm20.launcher2.searchactions.builders.WebsearchActionBuilder
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
@ -57,6 +58,7 @@ internal class SearchActionRepositoryImpl(
|
|||||||
SetAlarmActionBuilder(context),
|
SetAlarmActionBuilder(context),
|
||||||
TimerActionBuilder(context),
|
TimerActionBuilder(context),
|
||||||
OpenUrlActionBuilder(context),
|
OpenUrlActionBuilder(context),
|
||||||
|
WebsearchActionBuilder(context),
|
||||||
)
|
)
|
||||||
|
|
||||||
return allActions
|
return allActions
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import de.mm20.launcher2.crashreporter.CrashReporter
|
|||||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||||
import de.mm20.launcher2.searchactions.builders.SearchActionBuilder
|
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.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
@ -43,7 +43,7 @@ interface SearchActionService {
|
|||||||
|
|
||||||
fun saveSearchActionBuilders(builders: List<SearchActionBuilder>)
|
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>
|
suspend fun getSearchActivities(): List<ComponentName>
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ internal class SearchActionServiceImpl(
|
|||||||
repository.saveSearchActionBuilders(builders)
|
repository.saveSearchActionBuilders(builders)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun importWebsearch(url: String, iconSize: Int): WebsearchActionBuilder? =
|
override suspend fun importWebsearch(url: String, iconSize: Int): CustomWebsearchActionBuilder? =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val u = if (url.startsWith("http://") || url.startsWith("https://")) {
|
val u = if (url.startsWith("http://") || url.startsWith("https://")) {
|
||||||
@ -98,7 +98,7 @@ internal class SearchActionServiceImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (u.contains("${1}")) {
|
if (u.contains("${1}")) {
|
||||||
return@withContext WebsearchActionBuilder(
|
return@withContext CustomWebsearchActionBuilder(
|
||||||
urlTemplate = u,
|
urlTemplate = u,
|
||||||
label = "",
|
label = "",
|
||||||
iconColor = 0,
|
iconColor = 0,
|
||||||
@ -136,7 +136,7 @@ internal class SearchActionServiceImpl(
|
|||||||
private suspend fun importOpenSearch(
|
private suspend fun importOpenSearch(
|
||||||
openSearchHref: String,
|
openSearchHref: String,
|
||||||
iconSize: Int
|
iconSize: Int
|
||||||
): WebsearchActionBuilder? {
|
): CustomWebsearchActionBuilder? {
|
||||||
try {
|
try {
|
||||||
val httpClient = OkHttpClient()
|
val httpClient = OkHttpClient()
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
@ -207,7 +207,7 @@ internal class SearchActionServiceImpl(
|
|||||||
createIcon(uri, iconSize)
|
createIcon(uri, iconSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
return WebsearchActionBuilder(
|
return CustomWebsearchActionBuilder(
|
||||||
label = label ?: "",
|
label = label ?: "",
|
||||||
icon = if (localIconUrl == null) SearchActionIcon.Search else SearchActionIcon.Custom,
|
icon = if (localIconUrl == null) SearchActionIcon.Search else SearchActionIcon.Custom,
|
||||||
customIcon = localIconUrl,
|
customIcon = localIconUrl,
|
||||||
|
|||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,7 @@
|
|||||||
package de.mm20.launcher2.searchactions.builders
|
package de.mm20.launcher2.searchactions.builders
|
||||||
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.media.metrics.Event
|
|
||||||
import de.mm20.launcher2.database.entities.SearchActionEntity
|
import de.mm20.launcher2.database.entities.SearchActionEntity
|
||||||
import de.mm20.launcher2.ktx.jsonObjectOf
|
import de.mm20.launcher2.ktx.jsonObjectOf
|
||||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||||
@ -34,13 +32,13 @@ interface SearchActionBuilder {
|
|||||||
}
|
}
|
||||||
when (entity.type) {
|
when (entity.type) {
|
||||||
"url" -> {
|
"url" -> {
|
||||||
return WebsearchActionBuilder(
|
return CustomWebsearchActionBuilder(
|
||||||
label = entity.label ?: "",
|
label = entity.label ?: "",
|
||||||
urlTemplate = entity.data ?: return null,
|
urlTemplate = entity.data ?: return null,
|
||||||
iconColor = entity.color ?: 0,
|
iconColor = entity.color ?: 0,
|
||||||
icon = SearchActionIcon.fromInt(entity.icon),
|
icon = SearchActionIcon.fromInt(entity.icon),
|
||||||
customIcon = entity.customIcon,
|
customIcon = entity.customIcon,
|
||||||
encoding = WebsearchActionBuilder.QueryEncoding.fromInt(options?.optInt("encoding"))
|
encoding = CustomWebsearchActionBuilder.QueryEncoding.fromInt(options?.optInt("encoding"))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
"app" -> {
|
"app" -> {
|
||||||
@ -70,13 +68,14 @@ interface SearchActionBuilder {
|
|||||||
"timer" -> return TimerActionBuilder(context)
|
"timer" -> return TimerActionBuilder(context)
|
||||||
"calendar" -> return ScheduleEventActionBuilder(context)
|
"calendar" -> return ScheduleEventActionBuilder(context)
|
||||||
"website" -> return OpenUrlActionBuilder(context)
|
"website" -> return OpenUrlActionBuilder(context)
|
||||||
|
"websearch" -> return WebsearchActionBuilder(context)
|
||||||
else -> return null
|
else -> return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun toDatabaseEntity(builder: SearchActionBuilder, position: Int): SearchActionEntity {
|
internal fun toDatabaseEntity(builder: SearchActionBuilder, position: Int): SearchActionEntity {
|
||||||
return when(builder) {
|
return when(builder) {
|
||||||
is WebsearchActionBuilder -> SearchActionEntity(
|
is CustomWebsearchActionBuilder -> SearchActionEntity(
|
||||||
position = position,
|
position = position,
|
||||||
type = "url",
|
type = "url",
|
||||||
label = builder.label,
|
label = builder.label,
|
||||||
|
|||||||
@ -1,66 +1,25 @@
|
|||||||
package de.mm20.launcher2.searchactions.builders
|
package de.mm20.launcher2.searchactions.builders
|
||||||
|
|
||||||
import android.content.Context
|
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.TextClassificationResult
|
||||||
import de.mm20.launcher2.searchactions.actions.OpenUrlAction
|
|
||||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
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,
|
override val label: String,
|
||||||
val urlTemplate: String,
|
) : SearchActionBuilder {
|
||||||
override val icon: SearchActionIcon = SearchActionIcon.Search,
|
|
||||||
override val iconColor: Int = 0,
|
|
||||||
override val customIcon: String? = null,
|
|
||||||
val encoding: QueryEncoding = QueryEncoding.UrlEncode,
|
|
||||||
) : CustomizableSearchActionBuilder {
|
|
||||||
|
|
||||||
|
constructor(context: Context) : this(context.getString(R.string.search_action_websearch))
|
||||||
|
|
||||||
|
override val icon: SearchActionIcon = SearchActionIcon.WebSearch
|
||||||
override val key: String
|
override val key: String
|
||||||
get() = "web://$urlTemplate"
|
get() = "websearch"
|
||||||
|
|
||||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction {
|
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
||||||
val url = urlTemplate.replace("\${1}", encodeQuery(classifiedQuery.text, encoding))
|
return WebsearchAction(
|
||||||
return OpenUrlAction(
|
context.getString(R.string.search_action_websearch), classifiedQuery.text
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user