Add possibility to add custom extras to app search actions
This commit is contained in:
parent
47deb3e537
commit
a2e6302cd3
@ -4,11 +4,12 @@ import android.app.SearchManager
|
|||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
import de.mm20.launcher2.ktx.tryStartActivity
|
import de.mm20.launcher2.ktx.tryStartActivity
|
||||||
|
|
||||||
data class AppSearchAction(
|
data class AppSearchAction(
|
||||||
override val label: String,
|
override val label: String,
|
||||||
val componentName: ComponentName,
|
val baseIntent: Intent,
|
||||||
val query: String,
|
val query: String,
|
||||||
override val icon: SearchActionIcon = SearchActionIcon.Custom,
|
override val icon: SearchActionIcon = SearchActionIcon.Custom,
|
||||||
override val iconColor: Int = 1,
|
override val iconColor: Int = 1,
|
||||||
@ -16,8 +17,8 @@ data class AppSearchAction(
|
|||||||
): SearchAction {
|
): SearchAction {
|
||||||
|
|
||||||
override fun start(context: Context) {
|
override fun start(context: Context) {
|
||||||
val intent = Intent(Intent.ACTION_SEARCH).apply {
|
val intent = Intent(baseIntent).apply {
|
||||||
component = componentName
|
action = Intent.ACTION_SEARCH
|
||||||
putExtra(SearchManager.QUERY, query)
|
putExtra(SearchManager.QUERY, query)
|
||||||
putExtra(SearchManager.USER_QUERY, query)
|
putExtra(SearchManager.USER_QUERY, query)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import de.mm20.launcher2.ktx.tryStartActivity
|
|||||||
class CustomIntentAction(
|
class CustomIntentAction(
|
||||||
override val label: String,
|
override val label: String,
|
||||||
val query: String,
|
val query: String,
|
||||||
val queryKey: String,
|
private val queryKey: String,
|
||||||
val baseIntent: Intent,
|
private val baseIntent: Intent,
|
||||||
override val icon: SearchActionIcon = SearchActionIcon.Custom,
|
override val icon: SearchActionIcon = SearchActionIcon.Custom,
|
||||||
override val iconColor: Int = 1,
|
override val iconColor: Int = 1,
|
||||||
override val customIcon: String? = null,
|
override val customIcon: String? = null,
|
||||||
|
|||||||
@ -2,6 +2,8 @@ package de.mm20.launcher2.searchactions.builders
|
|||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||||
import de.mm20.launcher2.searchactions.TextType
|
import de.mm20.launcher2.searchactions.TextType
|
||||||
import de.mm20.launcher2.searchactions.actions.AppSearchAction
|
import de.mm20.launcher2.searchactions.actions.AppSearchAction
|
||||||
@ -10,18 +12,18 @@ import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
|||||||
|
|
||||||
data class AppSearchActionBuilder(
|
data class AppSearchActionBuilder(
|
||||||
override val label: String,
|
override val label: String,
|
||||||
val componentName: ComponentName,
|
val baseIntent: Intent,
|
||||||
override val icon: SearchActionIcon = SearchActionIcon.Custom,
|
override val icon: SearchActionIcon = SearchActionIcon.Custom,
|
||||||
override val iconColor: Int = 0,
|
override val iconColor: Int = 0,
|
||||||
override val customIcon: String? = null,
|
override val customIcon: String? = null,
|
||||||
) : CustomizableSearchActionBuilder {
|
) : CustomizableSearchActionBuilder {
|
||||||
|
|
||||||
override val key: String
|
override val key: String
|
||||||
get() = "app://${componentName.flattenToShortString()}"
|
get() = "app://${baseIntent.toUri(0)}"
|
||||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction? {
|
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction {
|
||||||
return AppSearchAction(
|
return AppSearchAction(
|
||||||
label = label,
|
label = label,
|
||||||
componentName = componentName,
|
baseIntent = baseIntent,
|
||||||
query = classifiedQuery.text,
|
query = classifiedQuery.text,
|
||||||
icon = icon,
|
icon = icon,
|
||||||
iconColor = iconColor,
|
iconColor = iconColor,
|
||||||
|
|||||||
@ -46,7 +46,7 @@ interface SearchActionBuilder {
|
|||||||
"app" -> {
|
"app" -> {
|
||||||
return AppSearchActionBuilder(
|
return AppSearchActionBuilder(
|
||||||
label = entity.label ?: "",
|
label = entity.label ?: "",
|
||||||
componentName = ComponentName.unflattenFromString(entity.data ?: return null) ?: return null,
|
baseIntent = Intent.parseUri(entity.data, 0),
|
||||||
iconColor = entity.color ?: 0,
|
iconColor = entity.color ?: 0,
|
||||||
icon = SearchActionIcon.fromInt(entity.icon),
|
icon = SearchActionIcon.fromInt(entity.icon),
|
||||||
customIcon = entity.customIcon,
|
customIcon = entity.customIcon,
|
||||||
@ -92,7 +92,7 @@ interface SearchActionBuilder {
|
|||||||
position = position,
|
position = position,
|
||||||
type = "app",
|
type = "app",
|
||||||
label = builder.label,
|
label = builder.label,
|
||||||
data = builder.componentName.flattenToShortString(),
|
data = builder.baseIntent.toUri(0),
|
||||||
color = builder.iconColor,
|
color = builder.iconColor,
|
||||||
icon = builder.icon.toInt(),
|
icon = builder.icon.toInt(),
|
||||||
customIcon = builder.customIcon,
|
customIcon = builder.customIcon,
|
||||||
|
|||||||
@ -92,7 +92,7 @@ fun SearchActionIcon(action: SearchAction, size: Dp = 20.dp) {
|
|||||||
icon = action.icon,
|
icon = action.icon,
|
||||||
color = action.iconColor,
|
color = action.iconColor,
|
||||||
customIcon = action.customIcon,
|
customIcon = action.customIcon,
|
||||||
componentName = (action as? AppSearchAction)?.componentName,
|
componentName = (action as? AppSearchAction)?.baseIntent?.component,
|
||||||
size = size,
|
size = size,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ fun SearchActionIcon(builder: CustomizableSearchActionBuilder, size: Dp = 20.dp)
|
|||||||
icon = builder.icon,
|
icon = builder.icon,
|
||||||
color = builder.iconColor,
|
color = builder.iconColor,
|
||||||
customIcon = builder.customIcon,
|
customIcon = builder.customIcon,
|
||||||
componentName = (builder as? AppSearchActionBuilder)?.componentName,
|
componentName = (builder as? AppSearchActionBuilder)?.baseIntent?.component,
|
||||||
size = size,
|
size = size,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package de.mm20.launcher2.ui.settings.searchactions
|
|||||||
|
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@ -21,18 +22,25 @@ import androidx.compose.foundation.lazy.grid.items
|
|||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.Add
|
||||||
import androidx.compose.material.icons.rounded.Android
|
import androidx.compose.material.icons.rounded.Android
|
||||||
import androidx.compose.material.icons.rounded.ArrowDropDown
|
import androidx.compose.material.icons.rounded.ArrowDropDown
|
||||||
import androidx.compose.material.icons.rounded.Delete
|
import androidx.compose.material.icons.rounded.Delete
|
||||||
import androidx.compose.material.icons.rounded.ManageSearch
|
import androidx.compose.material.icons.rounded.ManageSearch
|
||||||
import androidx.compose.material.icons.rounded.MoreVert
|
import androidx.compose.material.icons.rounded.MoreVert
|
||||||
|
import androidx.compose.material.icons.rounded.RemoveCircleOutline
|
||||||
|
import androidx.compose.material.icons.rounded.ToggleOn
|
||||||
import androidx.compose.material.icons.rounded.TravelExplore
|
import androidx.compose.material.icons.rounded.TravelExplore
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.DropdownMenu
|
import androidx.compose.material3.DropdownMenu
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.FilledIconButton
|
||||||
|
import androidx.compose.material3.FilledTonalIconButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@ -60,6 +68,7 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.text.input.OffsetMapping
|
import androidx.compose.ui.text.input.OffsetMapping
|
||||||
import androidx.compose.ui.text.input.TransformedText
|
import androidx.compose.ui.text.input.TransformedText
|
||||||
import androidx.compose.ui.text.input.VisualTransformation
|
import androidx.compose.ui.text.input.VisualTransformation
|
||||||
@ -68,6 +77,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
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.CustomizableSearchActionBuilder
|
import de.mm20.launcher2.searchactions.builders.CustomizableSearchActionBuilder
|
||||||
import de.mm20.launcher2.searchactions.builders.WebsearchActionBuilder
|
import de.mm20.launcher2.searchactions.builders.WebsearchActionBuilder
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
@ -373,7 +383,9 @@ private fun InitWebSearchPage(viewModel: EditSearchActionSheetVM) {
|
|||||||
fun CustomizeWebSearch(viewModel: EditSearchActionSheetVM) {
|
fun CustomizeWebSearch(viewModel: EditSearchActionSheetVM) {
|
||||||
val searchAction by viewModel.searchAction
|
val searchAction by viewModel.searchAction
|
||||||
|
|
||||||
Column {
|
Column(
|
||||||
|
modifier = Modifier.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
|
||||||
if (searchAction != null && searchAction is WebsearchActionBuilder) {
|
if (searchAction != null && searchAction is WebsearchActionBuilder) {
|
||||||
Row(
|
Row(
|
||||||
@ -456,11 +468,16 @@ fun CustomizeAppSearch(viewModel: EditSearchActionSheetVM) {
|
|||||||
initial = emptyList()
|
initial = emptyList()
|
||||||
)
|
)
|
||||||
val selectedApp =
|
val selectedApp =
|
||||||
remember(availableSearchApps, (searchAction as? AppSearchActionBuilder)?.componentName) {
|
remember(
|
||||||
availableSearchApps.find { it.componentName == (searchAction as? AppSearchActionBuilder)?.componentName }
|
availableSearchApps,
|
||||||
|
(searchAction as? AppSearchActionBuilder)?.baseIntent?.component
|
||||||
|
) {
|
||||||
|
availableSearchApps.find { it.componentName == (searchAction as? AppSearchActionBuilder)?.baseIntent?.component }
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column(
|
||||||
|
modifier = Modifier.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
|
||||||
if (searchAction != null) {
|
if (searchAction != null) {
|
||||||
|
|
||||||
@ -538,6 +555,23 @@ fun CustomizeAppSearch(viewModel: EditSearchActionSheetVM) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -547,7 +581,9 @@ fun CustomizeCustomIntent(viewModel: EditSearchActionSheetVM) {
|
|||||||
val searchAction by viewModel.searchAction
|
val searchAction by viewModel.searchAction
|
||||||
|
|
||||||
if (searchAction != null) {
|
if (searchAction != null) {
|
||||||
Column {
|
Column(
|
||||||
|
modifier = Modifier.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.Bottom
|
verticalAlignment = Alignment.Bottom
|
||||||
) {
|
) {
|
||||||
@ -602,7 +638,7 @@ fun PickIcon(viewModel: EditSearchActionSheetVM) {
|
|||||||
}) {
|
}) {
|
||||||
SearchActionIcon(
|
SearchActionIcon(
|
||||||
icon = SearchActionIcon.Custom,
|
icon = SearchActionIcon.Custom,
|
||||||
componentName = (action as AppSearchActionBuilder).componentName,
|
componentName = (action as AppSearchActionBuilder).baseIntent.component,
|
||||||
size = 24.dp,
|
size = 24.dp,
|
||||||
color = 1,
|
color = 1,
|
||||||
)
|
)
|
||||||
@ -704,3 +740,296 @@ private fun SearchActionIconTile(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun IntentExtrasEditor(viewModel: EditSearchActionSheetVM) {
|
||||||
|
|
||||||
|
val action = viewModel.searchAction.value
|
||||||
|
val extras = remember(action?.key) {
|
||||||
|
when (action) {
|
||||||
|
is CustomIntentActionBuilder -> action.baseIntent.extras
|
||||||
|
is AppSearchActionBuilder -> action.baseIntent.extras
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val keys = remember(extras) { extras?.keySet()?.sorted() ?: emptyList() }
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(top = 24.dp)
|
||||||
|
) {
|
||||||
|
Text("Extras", style = MaterialTheme.typography.titleSmall)
|
||||||
|
for (key in keys) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.padding(top = 12.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
val value = extras?.get(key)
|
||||||
|
when (value) {
|
||||||
|
is String -> {
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(bottom = 8.dp),
|
||||||
|
value = value,
|
||||||
|
onValueChange = { viewModel.putStringExtra(key, it) },
|
||||||
|
label = { Text(key) },
|
||||||
|
leadingIcon = {
|
||||||
|
Text("ABC", style = MaterialTheme.typography.labelSmall)
|
||||||
|
},
|
||||||
|
singleLine = true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is Long -> {
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(bottom = 8.dp),
|
||||||
|
value = value.toString(),
|
||||||
|
onValueChange = {
|
||||||
|
viewModel.putLongExtra(
|
||||||
|
key,
|
||||||
|
it.replace(Regex("[^0-9]"), "").toLongOrNull() ?: 0
|
||||||
|
)
|
||||||
|
},
|
||||||
|
label = { Text(key) },
|
||||||
|
leadingIcon = {
|
||||||
|
Text("1234", style = MaterialTheme.typography.labelSmall)
|
||||||
|
},
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
|
singleLine = true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is Int -> {
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(bottom = 8.dp),
|
||||||
|
value = value.toString(),
|
||||||
|
onValueChange = {
|
||||||
|
viewModel.putIntExtra(
|
||||||
|
key,
|
||||||
|
it.replace(Regex("[^0-9]"), "").toIntOrNull() ?: 0
|
||||||
|
)
|
||||||
|
},
|
||||||
|
label = { Text(key) },
|
||||||
|
leadingIcon = {
|
||||||
|
Text("123", style = MaterialTheme.typography.labelSmall)
|
||||||
|
},
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
|
singleLine = true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is Double -> {
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(bottom = 8.dp),
|
||||||
|
value = value.toString(),
|
||||||
|
onValueChange = {
|
||||||
|
viewModel.putDoubleExtra(
|
||||||
|
key,
|
||||||
|
it.replace(Regex("[^0-9.]"), "").toDoubleOrNull() ?: 0.0
|
||||||
|
)
|
||||||
|
},
|
||||||
|
label = { Text(key) },
|
||||||
|
leadingIcon = {
|
||||||
|
Text("1.00", style = MaterialTheme.typography.labelSmall)
|
||||||
|
},
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
|
singleLine = true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is Float -> {
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(bottom = 8.dp),
|
||||||
|
value = value.toString(),
|
||||||
|
onValueChange = {
|
||||||
|
viewModel.putFloatExtra(
|
||||||
|
key,
|
||||||
|
it.replace(Regex("[^0-9.]"), "").toFloatOrNull() ?: 0f
|
||||||
|
)
|
||||||
|
},
|
||||||
|
label = { Text(key) },
|
||||||
|
leadingIcon = {
|
||||||
|
Text("1.0", style = MaterialTheme.typography.labelSmall)
|
||||||
|
},
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
|
singleLine = true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is Boolean -> {
|
||||||
|
Switch(
|
||||||
|
checked = value,
|
||||||
|
onCheckedChange = { viewModel.putBooleanExtra(key, it) })
|
||||||
|
Text(
|
||||||
|
text = key,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(start = 8.dp),
|
||||||
|
style = MaterialTheme.typography.labelSmall,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IconButton(
|
||||||
|
onClick = { viewModel.removeExtra(key) },
|
||||||
|
modifier = Modifier.padding(horizontal = 8.dp)
|
||||||
|
) {
|
||||||
|
Icon(imageVector = Icons.Rounded.RemoveCircleOutline, contentDescription = null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OutlinedCard(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 16.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
shape = MaterialTheme.shapes.medium,
|
||||||
|
) {
|
||||||
|
|
||||||
|
var newKey by remember { mutableStateOf("") }
|
||||||
|
var newType by remember { mutableStateOf("string") }
|
||||||
|
var showTypeDropdown by remember { mutableStateOf(false) }
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
|
||||||
|
) {
|
||||||
|
FilledTonalIconButton(
|
||||||
|
modifier = Modifier.padding(end = 8.dp),
|
||||||
|
onClick = { showTypeDropdown = !showTypeDropdown }
|
||||||
|
) {
|
||||||
|
when (newType) {
|
||||||
|
"bool" -> {
|
||||||
|
Icon(Icons.Rounded.ToggleOn, contentDescription = null)
|
||||||
|
}
|
||||||
|
|
||||||
|
"string" -> {
|
||||||
|
Text("ABC", style = MaterialTheme.typography.labelSmall)
|
||||||
|
}
|
||||||
|
|
||||||
|
"int" -> {
|
||||||
|
Text("123", style = MaterialTheme.typography.labelSmall)
|
||||||
|
}
|
||||||
|
|
||||||
|
"long" -> {
|
||||||
|
Text("1234", style = MaterialTheme.typography.labelSmall)
|
||||||
|
}
|
||||||
|
|
||||||
|
"float" -> {
|
||||||
|
Text("1.0", style = MaterialTheme.typography.labelSmall)
|
||||||
|
}
|
||||||
|
|
||||||
|
"double" -> {
|
||||||
|
Text("1.00", style = MaterialTheme.typography.labelSmall)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = showTypeDropdown,
|
||||||
|
onDismissRequest = { showTypeDropdown = false }) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
leadingIcon = {
|
||||||
|
Text(
|
||||||
|
"ABC",
|
||||||
|
style = MaterialTheme.typography.labelSmall
|
||||||
|
)
|
||||||
|
},
|
||||||
|
text = { Text("String") },
|
||||||
|
onClick = {
|
||||||
|
newType = "string"
|
||||||
|
showTypeDropdown = false
|
||||||
|
})
|
||||||
|
DropdownMenuItem(
|
||||||
|
leadingIcon = {
|
||||||
|
Text(
|
||||||
|
"123",
|
||||||
|
style = MaterialTheme.typography.labelSmall
|
||||||
|
)
|
||||||
|
},
|
||||||
|
text = { Text("Integer") },
|
||||||
|
onClick = {
|
||||||
|
newType = "int"
|
||||||
|
showTypeDropdown = false
|
||||||
|
})
|
||||||
|
DropdownMenuItem(
|
||||||
|
leadingIcon = {
|
||||||
|
Text(
|
||||||
|
"1234",
|
||||||
|
style = MaterialTheme.typography.labelSmall
|
||||||
|
)
|
||||||
|
},
|
||||||
|
text = { Text("Long") },
|
||||||
|
onClick = {
|
||||||
|
newType = "long"
|
||||||
|
showTypeDropdown = false
|
||||||
|
})
|
||||||
|
DropdownMenuItem(
|
||||||
|
leadingIcon = {
|
||||||
|
Text(
|
||||||
|
"1.0",
|
||||||
|
style = MaterialTheme.typography.labelSmall
|
||||||
|
)
|
||||||
|
},
|
||||||
|
text = { Text("Float") },
|
||||||
|
onClick = {
|
||||||
|
newType = "float"
|
||||||
|
showTypeDropdown = false
|
||||||
|
})
|
||||||
|
DropdownMenuItem(
|
||||||
|
leadingIcon = {
|
||||||
|
Text(
|
||||||
|
"1.00",
|
||||||
|
style = MaterialTheme.typography.labelSmall
|
||||||
|
)
|
||||||
|
},
|
||||||
|
text = { Text("Double") },
|
||||||
|
onClick = {
|
||||||
|
newType = "double"
|
||||||
|
showTypeDropdown = false
|
||||||
|
})
|
||||||
|
DropdownMenuItem(
|
||||||
|
leadingIcon = { Icon(Icons.Rounded.ToggleOn, null) },
|
||||||
|
text = { Text("Boolean") },
|
||||||
|
onClick = {
|
||||||
|
newType = "bool"
|
||||||
|
showTypeDropdown = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OutlinedTextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(bottom = 8.dp),
|
||||||
|
label = { Text("Key") },
|
||||||
|
value = newKey,
|
||||||
|
onValueChange = { newKey = it },
|
||||||
|
)
|
||||||
|
FilledIconButton(
|
||||||
|
modifier = Modifier.padding(start = 8.dp),
|
||||||
|
onClick = {
|
||||||
|
when (newType) {
|
||||||
|
"string" -> viewModel.putStringExtra(newKey)
|
||||||
|
"int" -> viewModel.putIntExtra(newKey)
|
||||||
|
"bool" -> viewModel.putBooleanExtra(newKey)
|
||||||
|
"long" -> viewModel.putLongExtra(newKey)
|
||||||
|
"double" -> viewModel.putDoubleExtra(newKey)
|
||||||
|
"float" -> viewModel.putFloatExtra(newKey)
|
||||||
|
}
|
||||||
|
newKey = ""
|
||||||
|
},
|
||||||
|
enabled = newKey.isNotBlank()
|
||||||
|
) {
|
||||||
|
Icon(imageVector = Icons.Rounded.Add, contentDescription = null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import android.content.ComponentName
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.unit.Density
|
import androidx.compose.ui.unit.Density
|
||||||
@ -73,7 +74,9 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
fun selectSearchableApp(app: SearchableApp) {
|
fun selectSearchableApp(app: SearchableApp) {
|
||||||
searchAction.value = AppSearchActionBuilder(
|
searchAction.value = AppSearchActionBuilder(
|
||||||
label = app.label,
|
label = app.label,
|
||||||
componentName = app.componentName,
|
baseIntent = Intent().apply {
|
||||||
|
setComponent(app.componentName)
|
||||||
|
},
|
||||||
icon = SearchActionIcon.Custom,
|
icon = SearchActionIcon.Custom,
|
||||||
customIcon = null,
|
customIcon = null,
|
||||||
iconColor = 1,
|
iconColor = 1,
|
||||||
@ -116,7 +119,9 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
is AppSearchActionBuilder -> action.copy(componentName = componentName)
|
is AppSearchActionBuilder -> action.also {
|
||||||
|
it.baseIntent.setComponent(componentName)
|
||||||
|
}
|
||||||
is WebsearchActionBuilder -> action
|
is WebsearchActionBuilder -> action
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,6 +264,153 @@ class EditSearchActionSheetVM : ViewModel(), KoinComponent {
|
|||||||
setCustomIcon(path)
|
setCustomIcon(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removeExtra(key: String) {
|
||||||
|
val action = searchAction.value ?: return
|
||||||
|
searchAction.value = when(action) {
|
||||||
|
is CustomIntentActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.remove(key)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
is AppSearchActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.remove(key)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
else -> action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putStringExtra(key: String, value: String = "") {
|
||||||
|
val action = searchAction.value ?: return
|
||||||
|
searchAction.value = when(action) {
|
||||||
|
is CustomIntentActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putString(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
is AppSearchActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putString(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
else -> action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putIntExtra(key: String, value: Int = 0) {
|
||||||
|
val action = searchAction.value ?: return
|
||||||
|
searchAction.value = when(action) {
|
||||||
|
is CustomIntentActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putInt(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
is AppSearchActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putInt(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
else -> action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putLongExtra(key: String, value: Long = 0L) {
|
||||||
|
val action = searchAction.value ?: return
|
||||||
|
searchAction.value = when(action) {
|
||||||
|
is CustomIntentActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putLong(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
is AppSearchActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putLong(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
else -> action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putFloatExtra(key: String, value: Float = 0f) {
|
||||||
|
val action = searchAction.value ?: return
|
||||||
|
searchAction.value = when(action) {
|
||||||
|
is CustomIntentActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putFloat(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
is AppSearchActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putFloat(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
else -> action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putDoubleExtra(key: String, value: Double = 0.0) {
|
||||||
|
val action = searchAction.value ?: return
|
||||||
|
searchAction.value = when(action) {
|
||||||
|
is CustomIntentActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putDouble(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
is AppSearchActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putDouble(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
else -> action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putBooleanExtra(key: String, value: Boolean = false) {
|
||||||
|
val action = searchAction.value ?: return
|
||||||
|
searchAction.value = when(action) {
|
||||||
|
is CustomIntentActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putBoolean(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
is AppSearchActionBuilder -> action.copy(
|
||||||
|
baseIntent = action.baseIntent.cloneFilter().also {
|
||||||
|
val extras = action.baseIntent.extras?.deepCopy() ?: Bundle()
|
||||||
|
extras.putBoolean(key, value)
|
||||||
|
it.replaceExtras(extras)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
else -> action
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class EditSearchActionPage {
|
enum class EditSearchActionPage {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user