Search actions settings [wip]
This commit is contained in:
+30
-7
@@ -1,8 +1,11 @@
|
||||
package de.mm20.launcher2.searchactions
|
||||
|
||||
import android.app.SearchManager
|
||||
import android.app.SearchableInfo
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ResolveInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
@@ -14,7 +17,6 @@ import coil.size.Scale
|
||||
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
import de.mm20.launcher2.searchactions.builders.CallActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.SearchActionBuilder
|
||||
import de.mm20.launcher2.searchactions.builders.WebsearchActionBuilder
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
@@ -47,7 +49,7 @@ interface SearchActionService {
|
||||
|
||||
suspend fun importWebsearch(url: String, iconSize: Int): WebsearchActionBuilder?
|
||||
|
||||
suspend fun getSearchActivities(): List<ResolveInfo>
|
||||
suspend fun getSearchActivities(): List<ComponentName>
|
||||
|
||||
suspend fun createIcon(uri: Uri, size: Int): String?
|
||||
}
|
||||
@@ -100,6 +102,16 @@ internal class SearchActionServiceImpl(
|
||||
} else {
|
||||
"https://$url"
|
||||
}
|
||||
|
||||
if (u.contains("${1}")) {
|
||||
return@withContext WebsearchActionBuilder(
|
||||
urlTemplate = u,
|
||||
label = "",
|
||||
iconColor = 0,
|
||||
icon = SearchActionIcon.Search,
|
||||
)
|
||||
}
|
||||
|
||||
val document = Jsoup.parse(URL(u), 5000)
|
||||
val metaElements =
|
||||
document.select("link[rel=\"search\"][href][type=\"application/opensearchdescription+xml\"]")
|
||||
@@ -185,6 +197,7 @@ internal class SearchActionServiceImpl(
|
||||
label = label ?: "",
|
||||
icon = if (localIconUrl == null) SearchActionIcon.Search else SearchActionIcon.Custom,
|
||||
customIcon = localIconUrl,
|
||||
iconColor = if (localIconUrl == null) 0 else 1,
|
||||
urlTemplate = urlTemplate ?: ""
|
||||
)
|
||||
}
|
||||
@@ -214,9 +227,19 @@ internal class SearchActionServiceImpl(
|
||||
return@withContext file.absolutePath
|
||||
}
|
||||
|
||||
override suspend fun getSearchActivities(): List<ResolveInfo> {
|
||||
val packageManager = context.packageManager
|
||||
val intent = Intent(Intent.ACTION_SEARCH)
|
||||
return packageManager.queryIntentActivities(intent, 0)
|
||||
override suspend fun getSearchActivities(): List<ComponentName> {
|
||||
return withContext(Dispatchers.Default) {
|
||||
val resolveInfos = context.packageManager.queryIntentActivities(
|
||||
Intent(Intent.ACTION_SEARCH).addCategory(Intent.CATEGORY_DEFAULT), PackageManager.GET_META_DATA,
|
||||
)
|
||||
resolveInfos.mapNotNull {
|
||||
if (!it.activityInfo.exported || !it.activityInfo.enabled) return@mapNotNull null
|
||||
if (it.activityInfo.permission != null && context.checkSelfPermission(it.activityInfo.permission) != PackageManager.PERMISSION_GRANTED) {
|
||||
return@mapNotNull null
|
||||
}
|
||||
val componentName = ComponentName(it.activityInfo.packageName, it.activityInfo.name)
|
||||
componentName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -10,15 +10,16 @@ data class AppSearchAction(
|
||||
override val label: String,
|
||||
val componentName: ComponentName,
|
||||
val query: String,
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Custom,
|
||||
override val iconColor: Int = 1,
|
||||
override val customIcon: String? = null,
|
||||
): SearchAction {
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Search
|
||||
override val iconColor: Int = 0
|
||||
override val customIcon: String? = null
|
||||
|
||||
override fun start(context: Context) {
|
||||
val intent = Intent(Intent.ACTION_SEARCH).apply {
|
||||
component = componentName
|
||||
putExtra(SearchManager.QUERY, query)
|
||||
putExtra(SearchManager.USER_QUERY, query)
|
||||
}
|
||||
context.tryStartActivity(intent)
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package de.mm20.launcher2.searchactions.actions
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import de.mm20.launcher2.ktx.tryStartActivity
|
||||
|
||||
class CustomIntentAction(
|
||||
override val label: String,
|
||||
val query: String,
|
||||
val queryKey: String,
|
||||
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 intent = Intent(baseIntent).also {
|
||||
it.putExtra(queryKey, query)
|
||||
}
|
||||
context.tryStartActivity(intent)
|
||||
}
|
||||
}
|
||||
+5
-2
@@ -8,10 +8,10 @@ import de.mm20.launcher2.searchactions.actions.AppSearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
|
||||
class AppSearchActionBuilder(
|
||||
data class AppSearchActionBuilder(
|
||||
override val label: String,
|
||||
val componentName: ComponentName,
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Search,
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Custom,
|
||||
override val iconColor: Int = 0,
|
||||
override val customIcon: String? = null,
|
||||
) : CustomizableSearchActionBuilder {
|
||||
@@ -23,6 +23,9 @@ class AppSearchActionBuilder(
|
||||
label = label,
|
||||
componentName = componentName,
|
||||
query = classifiedQuery.text,
|
||||
icon = icon,
|
||||
iconColor = iconColor,
|
||||
customIcon = customIcon,
|
||||
)
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package de.mm20.launcher2.searchactions.builders
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import de.mm20.launcher2.searchactions.TextClassificationResult
|
||||
import de.mm20.launcher2.searchactions.actions.CustomIntentAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
|
||||
data class CustomIntentActionBuilder(
|
||||
override val label: String,
|
||||
val queryKey: String,
|
||||
val baseIntent: Intent,
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Custom,
|
||||
override val iconColor: Int = 1,
|
||||
override val customIcon: String? = null,
|
||||
) : CustomizableSearchActionBuilder {
|
||||
override val key: String
|
||||
get() = "intent://${baseIntent.toUri(0)}"
|
||||
|
||||
override fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction {
|
||||
return CustomIntentAction(
|
||||
label, classifiedQuery.text, queryKey, baseIntent, icon, iconColor, customIcon
|
||||
)
|
||||
}
|
||||
}
|
||||
+41
-2
@@ -1,6 +1,8 @@
|
||||
package de.mm20.launcher2.searchactions.builders
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.media.metrics.Event
|
||||
import de.mm20.launcher2.database.entities.SearchActionEntity
|
||||
import de.mm20.launcher2.ktx.jsonObjectOf
|
||||
@@ -42,7 +44,23 @@ interface SearchActionBuilder {
|
||||
)
|
||||
}
|
||||
"app" -> {
|
||||
return null
|
||||
return AppSearchActionBuilder(
|
||||
label = entity.label ?: "",
|
||||
componentName = ComponentName.unflattenFromString(entity.data ?: return null) ?: return null,
|
||||
iconColor = entity.color ?: 0,
|
||||
icon = SearchActionIcon.fromInt(entity.icon),
|
||||
customIcon = entity.customIcon,
|
||||
)
|
||||
}
|
||||
"intent" -> {
|
||||
return CustomIntentActionBuilder(
|
||||
entity.label ?: "",
|
||||
baseIntent = Intent.parseUri(entity.data, 0),
|
||||
iconColor = entity.color ?: 0,
|
||||
icon = SearchActionIcon.fromInt(entity.icon),
|
||||
customIcon = entity.customIcon,
|
||||
queryKey = options?.getString("extra")?.takeIf { it.isNotEmpty() } ?: return null
|
||||
)
|
||||
}
|
||||
"call" -> return CallActionBuilder(context)
|
||||
"message" -> return MessageActionBuilder(context)
|
||||
@@ -70,7 +88,28 @@ interface SearchActionBuilder {
|
||||
"encoding" to builder.encoding.toInt()
|
||||
).toString()
|
||||
)
|
||||
//is AppSearchActionBuilder -> null
|
||||
is AppSearchActionBuilder -> SearchActionEntity(
|
||||
position = position,
|
||||
type = "app",
|
||||
label = builder.label,
|
||||
data = builder.componentName.flattenToShortString(),
|
||||
color = builder.iconColor,
|
||||
icon = builder.icon.toInt(),
|
||||
customIcon = builder.customIcon,
|
||||
options = null
|
||||
)
|
||||
is CustomIntentActionBuilder -> SearchActionEntity(
|
||||
position = position,
|
||||
type = "intent",
|
||||
label = builder.label,
|
||||
data = builder.baseIntent.toUri(0),
|
||||
color = builder.iconColor,
|
||||
icon = builder.icon.toInt(),
|
||||
customIcon = builder.customIcon,
|
||||
options = jsonObjectOf(
|
||||
"extra" to builder.queryKey
|
||||
).toString()
|
||||
)
|
||||
else -> SearchActionEntity(
|
||||
position = position,
|
||||
type = builder.key,
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ import de.mm20.launcher2.searchactions.actions.SearchAction
|
||||
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
|
||||
import java.net.URLEncoder
|
||||
|
||||
class WebsearchActionBuilder(
|
||||
data class WebsearchActionBuilder(
|
||||
override val label: String,
|
||||
val urlTemplate: String,
|
||||
override val icon: SearchActionIcon = SearchActionIcon.Search,
|
||||
|
||||
Reference in New Issue
Block a user