Add more options for custom intent search actions
This commit is contained in:
@@ -9,6 +9,7 @@ import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
@@ -21,6 +22,7 @@ fun <T> ListPreference(
|
||||
items: List<ListPreferenceItem<T>>,
|
||||
value: T,
|
||||
summary: String? = items.firstOrNull { value == it.value }?.label,
|
||||
containerColor: Color = MaterialTheme.colorScheme.surface,
|
||||
onValueChanged: (T) -> Unit,
|
||||
enabled: Boolean = true,
|
||||
itemLabel: @Composable RowScope.(item: ListPreferenceItem<T>) -> Unit = {
|
||||
@@ -36,6 +38,7 @@ fun <T> ListPreference(
|
||||
icon = icon,
|
||||
iconPadding = iconPadding,
|
||||
enabled = enabled,
|
||||
containerColor = containerColor,
|
||||
onClick = {
|
||||
showDialog = true
|
||||
}
|
||||
|
||||
@@ -51,6 +51,9 @@ import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.OutlinedCard
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.OutlinedTextFieldDefaults
|
||||
import androidx.compose.material3.SegmentedButton
|
||||
import androidx.compose.material3.SegmentedButtonDefaults
|
||||
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
@@ -65,6 +68,7 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
@@ -114,7 +118,9 @@ fun EditSearchActionSheet(
|
||||
Column(
|
||||
modifier = when (page) {
|
||||
EditSearchActionPage.InitAppSearch, EditSearchActionPage.PickIcon -> Modifier
|
||||
else -> Modifier.verticalScroll(rememberScrollState()).padding(it)
|
||||
else -> Modifier
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(it)
|
||||
}
|
||||
) {
|
||||
when (page) {
|
||||
@@ -184,7 +190,9 @@ fun EditSearchActionSheet(
|
||||
|
||||
if (button != null) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().padding(vertical = 16.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 16.dp),
|
||||
horizontalArrangement = Arrangement.End,
|
||||
) {
|
||||
button()
|
||||
@@ -400,6 +408,7 @@ fun CustomizeWebSearch(viewModel: EditSearchActionSheetVM) {
|
||||
value = searchAction!!.label,
|
||||
onValueChange = { viewModel.setLabel(it) },
|
||||
label = { Text(stringResource(R.string.search_action_label)) },
|
||||
singleLine = true,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -490,7 +499,8 @@ fun CustomizeWebSearch(viewModel: EditSearchActionSheetVM) {
|
||||
onValueChanged = {
|
||||
viewModel.setQueryEncoding(it)
|
||||
},
|
||||
iconPadding = false
|
||||
iconPadding = false,
|
||||
containerColor = Color.Transparent
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -538,13 +548,15 @@ fun CustomizeAppSearch(viewModel: EditSearchActionSheetVM) {
|
||||
value = searchAction!!.label,
|
||||
onValueChange = { viewModel.setLabel(it) },
|
||||
label = { Text(stringResource(R.string.search_action_label)) },
|
||||
singleLine = true,
|
||||
)
|
||||
}
|
||||
|
||||
var showAppDropdown by remember { mutableStateOf(false) }
|
||||
Box(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { showAppDropdown = !showAppDropdown }) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { showAppDropdown = !showAppDropdown }) {
|
||||
OutlinedTextFieldDefaults.DecorationBox(
|
||||
value = selectedApp?.label ?: "",
|
||||
enabled = true,
|
||||
@@ -563,7 +575,7 @@ fun CustomizeAppSearch(viewModel: EditSearchActionSheetVM) {
|
||||
SearchActionIcon(
|
||||
size = 24.dp,
|
||||
componentName = selectedApp.componentName,
|
||||
icon = de.mm20.launcher2.searchactions.actions.SearchActionIcon.Custom,
|
||||
icon = SearchActionIcon.Custom,
|
||||
color = 1,
|
||||
)
|
||||
}
|
||||
@@ -586,7 +598,7 @@ fun CustomizeAppSearch(viewModel: EditSearchActionSheetVM) {
|
||||
SearchActionIcon(
|
||||
size = 24.dp,
|
||||
componentName = app.componentName,
|
||||
icon = de.mm20.launcher2.searchactions.actions.SearchActionIcon.Custom,
|
||||
icon = SearchActionIcon.Custom,
|
||||
color = 1,
|
||||
)
|
||||
}
|
||||
@@ -619,81 +631,180 @@ fun CustomizeAppSearch(viewModel: EditSearchActionSheetVM) {
|
||||
fun CustomizeCustomIntent(viewModel: EditSearchActionSheetVM) {
|
||||
val searchAction by viewModel.searchAction
|
||||
|
||||
val action = searchAction
|
||||
val action = (searchAction as? CustomIntentActionBuilder) ?: return
|
||||
|
||||
if (action is CustomIntentActionBuilder) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.Bottom
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.Bottom
|
||||
) {
|
||||
SearchActionIconTile(onClick = {
|
||||
viewModel.openIconPicker()
|
||||
}) {
|
||||
SearchActionIcon(
|
||||
builder = searchAction!!, size = 24.dp
|
||||
)
|
||||
}
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(start = 16.dp),
|
||||
value = action.label,
|
||||
onValueChange = { viewModel.setLabel(it) },
|
||||
label = { Text(stringResource(R.string.search_action_label)) },
|
||||
SearchActionIconTile(onClick = {
|
||||
viewModel.openIconPicker()
|
||||
}) {
|
||||
SearchActionIcon(
|
||||
builder = searchAction!!, size = 24.dp
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp),
|
||||
value = action.baseIntent.action ?: "",
|
||||
onValueChange = { viewModel.setIntentAction(it) },
|
||||
label = { Text("Action") },
|
||||
.weight(1f)
|
||||
.padding(start = 16.dp),
|
||||
value = action.label,
|
||||
onValueChange = { viewModel.setLabel(it) },
|
||||
label = { Text(stringResource(R.string.search_action_label)) },
|
||||
singleLine = true,
|
||||
)
|
||||
}
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
value = action.baseIntent.categories?.firstOrNull() ?: "",
|
||||
onValueChange = { viewModel.setIntentCategory(it) },
|
||||
label = { Text("Category") },
|
||||
)
|
||||
Text(
|
||||
text = "Query",
|
||||
modifier = Modifier.padding(top = 24.dp, bottom = 8.dp),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
value = action.queryKey,
|
||||
onValueChange = { viewModel.setIntentQueryExtra(it) },
|
||||
label = { Text("Extra key") },
|
||||
supportingText = {
|
||||
Text("The key of the string extra that the search term is passed as.")
|
||||
SingleChoiceSegmentedButtonRow(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
SegmentedButton(
|
||||
selected = action.queryKey == null,
|
||||
onClick = {
|
||||
viewModel.setQueryKey(null)
|
||||
},
|
||||
shape = SegmentedButtonDefaults.itemShape(0, 2)
|
||||
) {
|
||||
Text("Data")
|
||||
}
|
||||
SegmentedButton(
|
||||
selected = action.queryKey != null,
|
||||
onClick = {
|
||||
viewModel.setQueryKey("")
|
||||
},
|
||||
shape = SegmentedButtonDefaults.itemShape(1, 2)
|
||||
) {
|
||||
Text("String extra")
|
||||
}
|
||||
}
|
||||
|
||||
if (action.queryKey != null) {
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
value = action.queryKey ?: "",
|
||||
onValueChange = { viewModel.setQueryKey(it) },
|
||||
label = { Text("Extra key") },
|
||||
singleLine = true,
|
||||
isError = viewModel.customIntentKeyError.value
|
||||
)
|
||||
}
|
||||
|
||||
var showAdvanced by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
val placeholderBackground = MaterialTheme.colorScheme.tertiary
|
||||
val placeholderColor = MaterialTheme.colorScheme.onTertiary
|
||||
|
||||
AnimatedVisibility(!showAdvanced) {
|
||||
TextButton(
|
||||
modifier = Modifier.padding(top = 16.dp),
|
||||
onClick = { showAdvanced = true }) {
|
||||
Text(stringResource(id = R.string.websearch_dialog_advanced))
|
||||
}
|
||||
}
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
value = action.queryTemplate ?: "",
|
||||
onValueChange = { viewModel.setIntentQueryTemplate(it) },
|
||||
label = { Text(if (action.queryKey == null) "Data template" else "String extra template") },
|
||||
supportingText = {
|
||||
Text(
|
||||
if (action.queryKey == null) {
|
||||
"The URI template that is used to construct the intent\\'s data URI. Use ‘\${1}’ as a placeholder for the actual search term, e.g. geo:0,0?q=,\${1}"
|
||||
} else {
|
||||
"The template that is used to construct the string that is passed to the intent as a string extra. Use ‘\${1}’ as a placeholder for the actual search term"
|
||||
}
|
||||
)
|
||||
},
|
||||
singleLine = true,
|
||||
visualTransformation = {
|
||||
TransformedText(buildAnnotatedString {
|
||||
append(it)
|
||||
val placeholderIndex = it.indexOf("\${1}")
|
||||
if (placeholderIndex != -1) {
|
||||
addStyle(
|
||||
SpanStyle(
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = placeholderColor,
|
||||
background = placeholderBackground,
|
||||
),
|
||||
placeholderIndex, placeholderIndex + 4
|
||||
)
|
||||
}
|
||||
}, OffsetMapping.Identity)
|
||||
},
|
||||
isError = viewModel.customIntentTemplateError.value
|
||||
)
|
||||
|
||||
AnimatedVisibility(showAdvanced) {
|
||||
IntentExtrasEditor(viewModel)
|
||||
Text(
|
||||
text = "Base intent",
|
||||
modifier = Modifier.padding(top = 24.dp, bottom = 8.dp),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp),
|
||||
value = action.baseIntent.action ?: "",
|
||||
onValueChange = { viewModel.setIntentAction(it) },
|
||||
label = { Text("Action") },
|
||||
singleLine = true,
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
value = action.baseIntent.categories?.firstOrNull() ?: "",
|
||||
onValueChange = { viewModel.setIntentCategory(it) },
|
||||
label = { Text("Category") },
|
||||
singleLine = true,
|
||||
)
|
||||
|
||||
if (action.queryKey != null) {
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
value = action.baseIntent.dataString ?: "",
|
||||
onValueChange = { viewModel.setIntentData(it) },
|
||||
label = { Text("Data") },
|
||||
singleLine = true,
|
||||
)
|
||||
}
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
value = action.baseIntent.type ?: "",
|
||||
onValueChange = { viewModel.setIntentType(it) },
|
||||
label = { Text("Type") },
|
||||
singleLine = true,
|
||||
)
|
||||
|
||||
|
||||
var showAdvanced by remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
AnimatedVisibility(!showAdvanced) {
|
||||
TextButton(
|
||||
modifier = Modifier.padding(top = 16.dp),
|
||||
onClick = { showAdvanced = true }) {
|
||||
Text(stringResource(id = R.string.websearch_dialog_advanced))
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(showAdvanced) {
|
||||
IntentExtrasEditor(viewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -765,7 +876,9 @@ fun PickIcon(viewModel: EditSearchActionSheetVM, paddingValues: PaddingValues) {
|
||||
} else {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.padding(paddingValues).fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.padding(paddingValues)
|
||||
.fillMaxWidth()
|
||||
|
||||
) {
|
||||
SearchActionIconTile {
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.unit.Density
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.ktx.romanize
|
||||
@@ -16,8 +17,8 @@ import de.mm20.launcher2.searchactions.SearchActionService
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
import de.mm20.launcher2.searchactions.builders.AppSearchActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.CustomIntentActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.CustomizableSearchActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.CustomWebsearchActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.CustomizableSearchActionBuilder
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -182,6 +183,7 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
||||
private val invalidWebsearchUrl = mutableStateOf<String?>(null)
|
||||
val websearchInvalidUrlError =
|
||||
derivedStateOf { invalidWebsearchUrl.value == (searchAction.value as? CustomWebsearchActionBuilder)?.urlTemplate }
|
||||
val customIntentTemplateError = mutableStateOf(false)
|
||||
val customIntentKeyError = mutableStateOf(false)
|
||||
fun validate(): Boolean {
|
||||
val action = searchAction.value ?: return false
|
||||
@@ -192,9 +194,9 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
||||
return valid
|
||||
}
|
||||
if (action is CustomIntentActionBuilder) {
|
||||
val valid = action.queryKey.isNotBlank()
|
||||
customIntentKeyError.value = !valid
|
||||
return valid
|
||||
customIntentTemplateError.value = !(action.queryTemplate.isNullOrEmpty() || action.queryTemplate!!.contains("\${1}"))
|
||||
customIntentKeyError.value = action.queryKey != null && action.queryKey!!.isEmpty()
|
||||
return !customIntentTemplateError.value && !customIntentKeyError.value
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -218,7 +220,12 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
||||
deleteCustomIcon(action.customIcon)
|
||||
}
|
||||
searchAction.value = when (action) {
|
||||
is CustomWebsearchActionBuilder -> action.copy(icon = icon, customIcon = null, iconColor = 0)
|
||||
is CustomWebsearchActionBuilder -> action.copy(
|
||||
icon = icon,
|
||||
customIcon = null,
|
||||
iconColor = 0
|
||||
)
|
||||
|
||||
is CustomIntentActionBuilder -> action.copy(
|
||||
icon = icon,
|
||||
customIcon = null,
|
||||
@@ -484,7 +491,37 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
fun setIntentQueryExtra(key: String) {
|
||||
fun setIntentType(type: String) {
|
||||
val searchAction = searchAction.value ?: return
|
||||
this.searchAction.value = when (searchAction) {
|
||||
is CustomIntentActionBuilder -> searchAction.copy(
|
||||
baseIntent = searchAction.baseIntent.cloneFilter().also {
|
||||
val extras = searchAction.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||
it.replaceExtras(extras)
|
||||
it.setDataAndType(it.data, type.takeIf { it.isNotBlank() })
|
||||
},
|
||||
)
|
||||
|
||||
else -> searchAction
|
||||
}
|
||||
}
|
||||
|
||||
fun setIntentData(data: String) {
|
||||
val searchAction = searchAction.value ?: return
|
||||
this.searchAction.value = when (searchAction) {
|
||||
is CustomIntentActionBuilder -> searchAction.copy(
|
||||
baseIntent = searchAction.baseIntent.cloneFilter().also {
|
||||
val extras = searchAction.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||
it.replaceExtras(extras)
|
||||
it.setDataAndType(data.takeIf { it.isNotEmpty() }?.toUri(), it.type)
|
||||
},
|
||||
)
|
||||
|
||||
else -> searchAction
|
||||
}
|
||||
}
|
||||
|
||||
fun setQueryKey(key: String?) {
|
||||
val action = searchAction.value ?: return
|
||||
searchAction.value = when (action) {
|
||||
is CustomIntentActionBuilder -> action.copy(
|
||||
@@ -495,6 +532,17 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
fun setIntentQueryTemplate(template: String) {
|
||||
val action = searchAction.value ?: return
|
||||
searchAction.value = when (action) {
|
||||
is CustomIntentActionBuilder -> action.copy(
|
||||
queryTemplate = template.takeIf { it.isNotEmpty() },
|
||||
)
|
||||
|
||||
else -> action
|
||||
}
|
||||
}
|
||||
|
||||
fun setQueryEncoding(encoding: CustomWebsearchActionBuilder.QueryEncoding) {
|
||||
val action = searchAction.value ?: return
|
||||
searchAction.value = when (action) {
|
||||
|
||||
@@ -2,20 +2,33 @@ package de.mm20.launcher2.searchactions.actions
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.core.net.toUri
|
||||
import de.mm20.launcher2.ktx.tryStartActivity
|
||||
|
||||
class CustomIntentAction(
|
||||
override val label: String,
|
||||
val query: String,
|
||||
private val queryKey: String,
|
||||
private val queryKey: String?,
|
||||
private val queryTemplate: String? = null,
|
||||
private val baseIntent: Intent,
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Custom,
|
||||
override val iconColor: Int = 1,
|
||||
override val customIcon: String? = null,
|
||||
) : SearchAction {
|
||||
override fun start(context: Context) {
|
||||
val query = if (queryTemplate.isNullOrBlank()) {
|
||||
query
|
||||
} else {
|
||||
queryTemplate.replace("\${1}", query)
|
||||
}
|
||||
|
||||
val intent = Intent(baseIntent).also {
|
||||
it.putExtra(queryKey, query)
|
||||
if (queryKey == null) {
|
||||
it.setDataAndType(query.toUri(), baseIntent.type)
|
||||
} else {
|
||||
it.putExtra(queryKey, query)
|
||||
}
|
||||
}
|
||||
context.tryStartActivity(intent)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,11 @@ import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
|
||||
data class CustomIntentActionBuilder(
|
||||
override val label: String,
|
||||
val queryKey: String,
|
||||
/**
|
||||
* The extra of the intent to put the query in. If null, the query will be passed in the data URI.
|
||||
*/
|
||||
val queryKey: String?,
|
||||
val queryTemplate: String? = null,
|
||||
val baseIntent: Intent,
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Custom,
|
||||
override val iconColor: Int = 1,
|
||||
@@ -20,7 +24,7 @@ data class CustomIntentActionBuilder(
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction {
|
||||
return CustomIntentAction(
|
||||
label, classifiedQuery.text, queryKey, baseIntent, icon, iconColor, customIcon
|
||||
label, classifiedQuery.text, queryKey, queryTemplate, baseIntent, icon, iconColor, customIcon
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,8 @@ interface SearchActionBuilder {
|
||||
iconColor = entity.color ?: 0,
|
||||
icon = SearchActionIcon.fromInt(entity.icon),
|
||||
customIcon = entity.customIcon,
|
||||
queryKey = options?.getString("extra")?.takeIf { it.isNotEmpty() } ?: return null
|
||||
queryKey = options?.optString("extra"),
|
||||
queryTemplate = options?.optString("template")?.takeIf { it.isNotBlank() }
|
||||
)
|
||||
}
|
||||
"call" -> return CallActionBuilder(context)
|
||||
@@ -107,7 +108,8 @@ interface SearchActionBuilder {
|
||||
icon = builder.icon.toInt(),
|
||||
customIcon = builder.customIcon,
|
||||
options = jsonObjectOf(
|
||||
"extra" to builder.queryKey
|
||||
"extra" to builder.queryKey,
|
||||
"template" to builder.queryTemplate,
|
||||
).toString()
|
||||
)
|
||||
else -> SearchActionEntity(
|
||||
|
||||
Reference in New Issue
Block a user