Make search action order customizable
This commit is contained in:
+41
-1
@@ -5,10 +5,21 @@ import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.database.AppDatabase
|
||||
import de.mm20.launcher2.database.entities.SearchActionEntity
|
||||
import de.mm20.launcher2.ktx.jsonObjectOf
|
||||
import de.mm20.launcher2.searchactions.builders.CallActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.CreateContactActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.EmailActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.MessageActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.OpenUrlActionBuilder
|
||||
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 kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
@@ -17,6 +28,9 @@ import java.util.UUID
|
||||
|
||||
interface SearchActionRepository {
|
||||
fun getSearchActionBuilders(): Flow<List<SearchActionBuilder>>
|
||||
fun getBuiltinSearchActionBuilders(): List<SearchActionBuilder>
|
||||
|
||||
fun saveSearchActionBuilders(builders: List<SearchActionBuilder>)
|
||||
|
||||
suspend fun export(toDir: File)
|
||||
suspend fun import(fromDir: File)
|
||||
@@ -26,9 +40,35 @@ internal class SearchActionRepositoryImpl(
|
||||
private val context: Context,
|
||||
private val database: AppDatabase
|
||||
): SearchActionRepository {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
override fun getSearchActionBuilders(): Flow<List<SearchActionBuilder>> {
|
||||
val dao = database.searchActionDao()
|
||||
return dao.getSearchActions().map { it.mapNotNull { SearchActionBuilder.from(it) } }
|
||||
return dao.getSearchActions().map { it.mapNotNull { SearchActionBuilder.from(context, it) } }
|
||||
}
|
||||
|
||||
override fun getBuiltinSearchActionBuilders(): List<SearchActionBuilder> {
|
||||
val allActions = listOf(
|
||||
CallActionBuilder(context),
|
||||
MessageActionBuilder(context),
|
||||
CreateContactActionBuilder(context),
|
||||
EmailActionBuilder(context),
|
||||
ScheduleEventActionBuilder(context),
|
||||
SetAlarmActionBuilder(context),
|
||||
TimerActionBuilder(context),
|
||||
OpenUrlActionBuilder(context),
|
||||
)
|
||||
|
||||
return allActions
|
||||
}
|
||||
|
||||
override fun saveSearchActionBuilders(builders: List<SearchActionBuilder>) {
|
||||
scope.launch {
|
||||
val dao = database.searchActionDao()
|
||||
dao.replaceAll(
|
||||
builders.mapIndexed { i, it -> SearchActionBuilder.toDatabaseEntity(it, i) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun export(toDir: File) = withContext(Dispatchers.IO) {
|
||||
|
||||
+27
-33
@@ -2,13 +2,9 @@ package de.mm20.launcher2.searchactions
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.LauncherActivityInfo
|
||||
import android.content.pm.LauncherApps
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.ResolveInfo
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.UserHandle
|
||||
import android.util.Log
|
||||
import android.util.Xml
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
@@ -16,20 +12,10 @@ import coil.imageLoader
|
||||
import coil.request.ImageRequest
|
||||
import coil.size.Scale
|
||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.database.entities.WebsearchEntity
|
||||
import de.mm20.launcher2.ktx.jsonObjectOf
|
||||
import de.mm20.launcher2.preferences.Settings.SearchActionSettings
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
import de.mm20.launcher2.searchactions.builders.CallActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.CreateContactActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.EmailActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.MessageActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.OpenUrlActionBuilder
|
||||
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.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
@@ -42,8 +28,6 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.jsoup.Jsoup
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import org.xmlpull.v1.XmlPullParserException
|
||||
@@ -54,12 +38,18 @@ import java.net.URL
|
||||
import java.util.UUID
|
||||
|
||||
interface SearchActionService {
|
||||
fun search(settings: SearchActionSettings, query: String): Flow<ImmutableList<SearchAction>>
|
||||
fun search(query: String): Flow<ImmutableList<SearchAction>>
|
||||
|
||||
fun getSearchActionBuilders(): Flow<List<SearchActionBuilder>>
|
||||
fun getDisabledActionBuilders(): Flow<List<SearchActionBuilder>>
|
||||
|
||||
fun saveSearchActionBuilders(builders: List<SearchActionBuilder>)
|
||||
|
||||
suspend fun importWebsearch(url: String, iconSize: Int): WebsearchActionBuilder?
|
||||
suspend fun createIcon(uri: Uri, size: Int): String?
|
||||
|
||||
suspend fun getSearchActivities(): List<ResolveInfo>
|
||||
|
||||
suspend fun createIcon(uri: Uri, size: Int): String?
|
||||
}
|
||||
|
||||
internal class SearchActionServiceImpl(
|
||||
@@ -68,7 +58,6 @@ internal class SearchActionServiceImpl(
|
||||
private val textClassifier: TextClassifier,
|
||||
) : SearchActionService {
|
||||
override fun search(
|
||||
settings: SearchActionSettings,
|
||||
query: String
|
||||
): Flow<ImmutableList<SearchAction>> = flow {
|
||||
if (query.isBlank()) {
|
||||
@@ -76,28 +65,33 @@ internal class SearchActionServiceImpl(
|
||||
return@flow
|
||||
}
|
||||
|
||||
val builders = mutableListOf<SearchActionBuilder>()
|
||||
|
||||
if (settings.call) builders.add(CallActionBuilder)
|
||||
if (settings.message) builders.add(MessageActionBuilder)
|
||||
if (settings.contact) builders.add(CreateContactActionBuilder)
|
||||
if (settings.email) builders.add(EmailActionBuilder)
|
||||
if (settings.openUrl) builders.add(OpenUrlActionBuilder)
|
||||
if (settings.scheduleEvent) builders.add(ScheduleEventActionBuilder)
|
||||
if (settings.setAlarm) builders.add(SetAlarmActionBuilder)
|
||||
if (settings.startTimer) builders.add(TimerActionBuilder)
|
||||
|
||||
val classificationResult = textClassifier.classify(context, query)
|
||||
|
||||
val other = repository.getSearchActionBuilders()
|
||||
val builders = repository.getSearchActionBuilders()
|
||||
|
||||
emitAll(
|
||||
other.map {
|
||||
(builders + it).mapNotNull { it.build(context, classificationResult) }.toImmutableList()
|
||||
builders.map {
|
||||
it.mapNotNull { it.build(context, classificationResult) }.toImmutableList()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun getSearchActionBuilders(): Flow<List<SearchActionBuilder>> {
|
||||
return repository.getSearchActionBuilders()
|
||||
}
|
||||
|
||||
override fun getDisabledActionBuilders(): Flow<List<SearchActionBuilder>> {
|
||||
val allActions = repository.getBuiltinSearchActionBuilders()
|
||||
|
||||
return getSearchActionBuilders().map { enabled ->
|
||||
allActions.filter { action -> !enabled.any { it.key == action.key } }
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveSearchActionBuilders(builders: List<SearchActionBuilder>) {
|
||||
repository.saveSearchActionBuilders(builders)
|
||||
}
|
||||
|
||||
override suspend fun importWebsearch(url: String, iconSize: Int): WebsearchActionBuilder? =
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
|
||||
+12
-6
@@ -1,21 +1,27 @@
|
||||
package de.mm20.launcher2.searchactions.builders
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.pm.LauncherActivityInfo
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.TextType
|
||||
import de.mm20.launcher2.searchactions.actions.AppSearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
|
||||
class AppSearchActionBuilder(
|
||||
val label: String,
|
||||
val activity: LauncherActivityInfo,
|
||||
val filter: TextType? = null,
|
||||
) : SearchActionBuilder {
|
||||
override val label: String,
|
||||
val componentName: ComponentName,
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Search,
|
||||
override val iconColor: Int = 0,
|
||||
override val customIcon: String? = null,
|
||||
) : CustomizableSearchActionBuilder {
|
||||
|
||||
override val key: String
|
||||
get() = "app://${componentName.flattenToShortString()}"
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
||||
return AppSearchAction(
|
||||
label = label,
|
||||
componentName = activity.componentName,
|
||||
componentName = componentName,
|
||||
query = classifiedQuery.text,
|
||||
)
|
||||
}
|
||||
|
||||
+11
-1
@@ -5,8 +5,18 @@ import de.mm20.launcher2.searchactions.R
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.CallAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
|
||||
object CallActionBuilder: SearchActionBuilder {
|
||||
class CallActionBuilder(
|
||||
override val label: String
|
||||
): SearchActionBuilder {
|
||||
|
||||
constructor(context: Context): this(context.getString(R.string.search_action_call))
|
||||
|
||||
override val key: String
|
||||
get() = "call"
|
||||
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Phone
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
||||
if (classifiedQuery.phoneNumber != null) {
|
||||
|
||||
+11
-1
@@ -5,8 +5,18 @@ import de.mm20.launcher2.searchactions.R
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.CreateContactAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
|
||||
object CreateContactActionBuilder : SearchActionBuilder {
|
||||
class CreateContactActionBuilder(
|
||||
override val label: String
|
||||
) : SearchActionBuilder {
|
||||
|
||||
constructor(context: Context) : this(context.getString(R.string.search_action_contact))
|
||||
|
||||
override val key: String
|
||||
get() = "contact"
|
||||
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Contact
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
||||
if (classifiedQuery.phoneNumber != null || classifiedQuery.email != null) {
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package de.mm20.launcher2.searchactions.builders
|
||||
|
||||
sealed interface CustomizableSearchActionBuilder: SearchActionBuilder
|
||||
+11
-1
@@ -5,8 +5,18 @@ import de.mm20.launcher2.searchactions.R
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.EmailAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
|
||||
object EmailActionBuilder: SearchActionBuilder {
|
||||
class EmailActionBuilder(
|
||||
override val label: String
|
||||
): SearchActionBuilder {
|
||||
|
||||
constructor(context: Context) : this(context.getString(R.string.search_action_email))
|
||||
|
||||
override val key: String
|
||||
get() = "email"
|
||||
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Email
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
||||
if (classifiedQuery.email != null) {
|
||||
|
||||
+11
-1
@@ -5,8 +5,18 @@ import de.mm20.launcher2.searchactions.R
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.MessageAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
|
||||
object MessageActionBuilder: SearchActionBuilder {
|
||||
class MessageActionBuilder(
|
||||
override val label: String
|
||||
): SearchActionBuilder {
|
||||
|
||||
constructor(context: Context) : this(context.getString(R.string.search_action_message))
|
||||
|
||||
override val key: String
|
||||
get() = "message"
|
||||
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Message
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
||||
if (classifiedQuery.phoneNumber != null) {
|
||||
|
||||
+11
-1
@@ -6,8 +6,18 @@ import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.MessageAction
|
||||
import de.mm20.launcher2.searchactions.actions.OpenUrlAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
|
||||
object OpenUrlActionBuilder : SearchActionBuilder {
|
||||
class OpenUrlActionBuilder(
|
||||
override val label: String
|
||||
) : SearchActionBuilder {
|
||||
|
||||
constructor(context: Context) : this(context.getString(R.string.search_action_open_url))
|
||||
|
||||
override val key: String
|
||||
get() = "website"
|
||||
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Website
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
||||
if (classifiedQuery.url != null) {
|
||||
|
||||
+11
-1
@@ -6,9 +6,19 @@ import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.MessageAction
|
||||
import de.mm20.launcher2.searchactions.actions.ScheduleEventAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
import java.time.LocalDateTime
|
||||
|
||||
object ScheduleEventActionBuilder : SearchActionBuilder {
|
||||
class ScheduleEventActionBuilder(
|
||||
override val label: String
|
||||
) : SearchActionBuilder {
|
||||
|
||||
constructor(context: Context) : this(context.getString(R.string.search_action_event))
|
||||
|
||||
override val key: String
|
||||
get() = "calendar"
|
||||
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Calendar
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
||||
if (classifiedQuery.date != null) {
|
||||
|
||||
+43
-4
@@ -1,7 +1,9 @@
|
||||
package de.mm20.launcher2.searchactions.builders
|
||||
|
||||
import android.content.Context
|
||||
import android.media.metrics.Event
|
||||
import de.mm20.launcher2.database.entities.SearchActionEntity
|
||||
import de.mm20.launcher2.ktx.jsonObjectOf
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
@@ -9,10 +11,18 @@ import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
|
||||
interface SearchActionBuilder {
|
||||
val label: String
|
||||
val icon: SearchActionIcon
|
||||
val iconColor: Int
|
||||
get() = 0
|
||||
val customIcon: String?
|
||||
get() = null
|
||||
|
||||
val key: String
|
||||
fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction?
|
||||
|
||||
companion object {
|
||||
fun from(entity: SearchActionEntity): SearchActionBuilder? {
|
||||
internal fun from(context: Context, entity: SearchActionEntity): SearchActionBuilder? {
|
||||
val options = entity.options?.let {
|
||||
try {
|
||||
JSONObject(it)
|
||||
@@ -24,8 +34,8 @@ interface SearchActionBuilder {
|
||||
"url" -> {
|
||||
return WebsearchActionBuilder(
|
||||
label = entity.label ?: "",
|
||||
urlTemplate = entity.data,
|
||||
color = entity.color,
|
||||
urlTemplate = entity.data ?: return null,
|
||||
iconColor = entity.color ?: 0,
|
||||
icon = SearchActionIcon.fromInt(entity.icon),
|
||||
customIcon = entity.customIcon,
|
||||
encoding = WebsearchActionBuilder.QueryEncoding.fromInt(options?.optInt("encoding"))
|
||||
@@ -34,9 +44,38 @@ interface SearchActionBuilder {
|
||||
"app" -> {
|
||||
return null
|
||||
}
|
||||
"call" -> return CallActionBuilder(context)
|
||||
"message" -> return MessageActionBuilder(context)
|
||||
"email" -> return EmailActionBuilder(context)
|
||||
"contact" -> return CreateContactActionBuilder(context)
|
||||
"alarm" -> return SetAlarmActionBuilder(context)
|
||||
"timer" -> return TimerActionBuilder(context)
|
||||
"calendar" -> return ScheduleEventActionBuilder(context)
|
||||
"website" -> return OpenUrlActionBuilder(context)
|
||||
else -> return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun toDatabaseEntity(builder: SearchActionBuilder, position: Int): SearchActionEntity {
|
||||
return when(builder) {
|
||||
is WebsearchActionBuilder -> SearchActionEntity(
|
||||
position = position,
|
||||
type = "url",
|
||||
label = builder.label,
|
||||
data = builder.urlTemplate,
|
||||
color = builder.iconColor,
|
||||
icon = builder.icon.toInt(),
|
||||
customIcon = builder.customIcon,
|
||||
options = jsonObjectOf(
|
||||
"encoding" to builder.encoding.toInt()
|
||||
).toString()
|
||||
)
|
||||
//is AppSearchActionBuilder -> null
|
||||
else -> SearchActionEntity(
|
||||
position = position,
|
||||
type = builder.key,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-1
@@ -4,10 +4,20 @@ import android.content.Context
|
||||
import de.mm20.launcher2.searchactions.R
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
import de.mm20.launcher2.searchactions.actions.SetAlarmAction
|
||||
import java.time.LocalDate
|
||||
|
||||
object SetAlarmActionBuilder : SearchActionBuilder {
|
||||
class SetAlarmActionBuilder(
|
||||
override val label: String
|
||||
) : SearchActionBuilder {
|
||||
|
||||
constructor(context: Context) : this(context.getString(R.string.search_action_alarm))
|
||||
|
||||
override val key: String
|
||||
get() = "alarm"
|
||||
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Alarm
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
||||
if (classifiedQuery.time != null) {
|
||||
|
||||
+11
-2
@@ -3,10 +3,19 @@ package de.mm20.launcher2.searchactions.builders
|
||||
import android.content.Context
|
||||
import de.mm20.launcher2.searchactions.R
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.TimerAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
import de.mm20.launcher2.searchactions.actions.TimerAction
|
||||
|
||||
object TimerActionBuilder : SearchActionBuilder {
|
||||
class TimerActionBuilder(
|
||||
override val label: String,
|
||||
) : SearchActionBuilder {
|
||||
constructor(context: Context) : this(context.getString(R.string.search_action_timer))
|
||||
|
||||
override val key: String
|
||||
get() = "timer"
|
||||
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Timer
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
||||
if (classifiedQuery.timespan != null && classifiedQuery.timespan.seconds <= 86400) {
|
||||
|
||||
+9
-6
@@ -9,13 +9,16 @@ import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
import java.net.URLEncoder
|
||||
|
||||
class WebsearchActionBuilder(
|
||||
val label: String,
|
||||
override val label: String,
|
||||
val urlTemplate: String,
|
||||
val icon: SearchActionIcon = SearchActionIcon.Search,
|
||||
val color: Int = 0,
|
||||
val customIcon: String? = null,
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Search,
|
||||
override val iconColor: Int = 0,
|
||||
override val customIcon: String? = null,
|
||||
val encoding: QueryEncoding = QueryEncoding.UrlEncode,
|
||||
) : SearchActionBuilder {
|
||||
) : 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))
|
||||
@@ -24,7 +27,7 @@ class WebsearchActionBuilder(
|
||||
url = url,
|
||||
icon = icon,
|
||||
customIcon = customIcon,
|
||||
iconColor = color,
|
||||
iconColor = iconColor,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user