Re-add websearches to search bar

This commit is contained in:
MM20 2022-11-04 19:35:37 +01:00
parent 872f55625f
commit dbc2c6f62e
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
16 changed files with 138 additions and 26 deletions

View File

@ -46,6 +46,8 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun backupDao(): BackupRestoreDao
abstract fun customAttrsDao(): CustomAttrsDao
abstract fun searchActionDao(): SearchActionDao
companion object {
private var _instance: AppDatabase? = null
fun getInstance(context: Context): AppDatabase {

View File

@ -0,0 +1,12 @@
package de.mm20.launcher2.database
import androidx.room.Dao
import androidx.room.Query
import de.mm20.launcher2.database.entities.SearchActionEntity
import kotlinx.coroutines.flow.Flow
@Dao
interface SearchActionDao {
@Query("SELECT * FROM SearchAction ORDER BY position ASC")
fun getSearchActions(): Flow<List<SearchActionEntity>>
}

View File

@ -8,6 +8,7 @@ import de.mm20.launcher2.ktx.jsonObjectOf
import de.mm20.launcher2.searchactions.builders.SearchActionBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import org.json.JSONArray
import org.json.JSONException
@ -15,7 +16,7 @@ import java.io.File
import java.util.UUID
interface SearchActionRepository {
fun getSearchActionBuilders(filter: TextType?): Flow<List<SearchActionBuilder>>
fun getSearchActionBuilders(): Flow<List<SearchActionBuilder>>
suspend fun export(toDir: File)
suspend fun import(fromDir: File)
@ -25,8 +26,9 @@ internal class SearchActionRepositoryImpl(
private val context: Context,
private val database: AppDatabase
): SearchActionRepository {
override fun getSearchActionBuilders(filter: TextType?): Flow<List<SearchActionBuilder>> {
TODO("Not yet implemented")
override fun getSearchActionBuilders(): Flow<List<SearchActionBuilder>> {
val dao = database.searchActionDao()
return dao.getSearchActions().map { it.mapNotNull { SearchActionBuilder.from(it) } }
}
override suspend fun export(toDir: File) = withContext(Dispatchers.IO) {

View File

@ -1,8 +1,14 @@
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
@ -30,7 +36,9 @@ import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
@ -51,6 +59,7 @@ interface SearchActionService {
suspend fun importWebsearch(url: String, iconSize: Int): WebsearchActionBuilder?
suspend fun createIcon(uri: Uri, size: Int): String?
suspend fun getSearchActivities(): List<ResolveInfo>
}
internal class SearchActionServiceImpl(
@ -80,8 +89,13 @@ internal class SearchActionServiceImpl(
val classificationResult = textClassifier.classify(context, query)
val other = repository.getSearchActionBuilders()
emit(builders.mapNotNull { it.build(context, classificationResult) }.toImmutableList())
emitAll(
other.map {
(builders + it).mapNotNull { it.build(context, classificationResult) }.toImmutableList()
}
)
}
override suspend fun importWebsearch(url: String, iconSize: Int): WebsearchActionBuilder? =
@ -205,4 +219,10 @@ internal class SearchActionServiceImpl(
out.close()
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)
}
}

View File

@ -13,6 +13,7 @@ data class AppSearchAction(
): 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 {

View File

@ -13,6 +13,7 @@ data class CallAction(
override val icon: SearchActionIcon = SearchActionIcon.Phone
override val iconColor: Int = 0
override val customIcon: String? = null
override fun start(context: Context) {
val intent = Intent(Intent.ACTION_DIAL).apply {

View File

@ -13,6 +13,7 @@ class CreateContactAction(
) : SearchAction {
override val icon: SearchActionIcon = SearchActionIcon.Contact
override val iconColor: Int = 0
override val customIcon: String? = null
override fun start(context: Context) {
val intent = Intent(Intent.ACTION_INSERT).apply {

View File

@ -11,7 +11,7 @@ data class EmailAction(
) : SearchAction {
override val icon: SearchActionIcon = SearchActionIcon.Email
override val iconColor: Int = 0
override val customIcon: String? = null
override fun start(context: Context) {
val intent = Intent(Intent.ACTION_SENDTO).apply {
type = "*/*"

View File

@ -11,7 +11,7 @@ data class MessageAction(
): SearchAction {
override val icon: SearchActionIcon = SearchActionIcon.Message
override val iconColor: Int = 0
override val customIcon: String? = null
override fun start(context: Context) {
val intent = Intent(Intent.ACTION_SENDTO).apply {
data = Uri.parse("sms:$number")

View File

@ -8,13 +8,15 @@ import de.mm20.launcher2.ktx.tryStartActivity
data class OpenUrlAction(
override val label: String,
val url: String,
override val icon: SearchActionIcon = SearchActionIcon.Website,
override val iconColor: Int = 0,
override val customIcon: String? = null,
) : SearchAction {
override val icon: SearchActionIcon = SearchActionIcon.Website
override val iconColor: Int = 0
override fun start(context: Context) {
val url = if (url.startsWith("https://") || url.startsWith("http://")) url else "https://$url"
val url =
if (url.startsWith("https://") || url.startsWith("http://")) url else "https://$url"
val intent = Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse(url)
flags = Intent.FLAG_ACTIVITY_NEW_TASK

View File

@ -16,7 +16,7 @@ data class ScheduleEventAction(
) : SearchAction {
override val icon: SearchActionIcon = SearchActionIcon.Calendar
override val iconColor: Int = 0
override val customIcon: String? = null
override fun start(context: Context) {
val startTime = date.let {

View File

@ -2,24 +2,58 @@ package de.mm20.launcher2.searchactions.actions
import android.content.Context
import de.mm20.launcher2.search.Searchable
import de.mm20.launcher2.searchactions.builders.WebsearchActionBuilder
interface SearchAction : Searchable {
val label: String
val icon: SearchActionIcon
val iconColor: Int
val customIcon: String?
fun start(context: Context)
}
enum class SearchActionIcon(value: Int) {
Search(0),
Custom(1),
Website(2),
Alarm(3),
Timer(4),
Contact(5),
Phone(6),
Email(7),
Message(8),
Calendar(9),
Translate(10),
enum class SearchActionIcon {
Search,
Custom,
Website,
Alarm,
Timer,
Contact,
Phone,
Email,
Message,
Calendar,
Translate;
fun toInt(): Int {
return when (this) {
Search -> 0
Custom -> 1
Website -> 2
Alarm -> 3
Timer -> 4
Contact -> 5
Phone -> 6
Email -> 7
Message -> 8
Calendar -> 9
Translate -> 10
}
}
companion object {
fun fromInt(value: Int?): SearchActionIcon {
return when (value) {
1 -> Custom
2 -> Website
3 -> Alarm
4 -> Timer
5 -> Contact
6 -> Phone
7 -> Email
8 -> Message
9 -> Calendar
10 -> Translate
else -> Search
}
}
}
}

View File

@ -12,7 +12,7 @@ data class SetAlarmAction(
) : SearchAction {
override val icon: SearchActionIcon = SearchActionIcon.Alarm
override val iconColor: Int = 0
override val customIcon: String? = null
override fun start(context: Context) {
val intent = Intent(AlarmClock.ACTION_SET_ALARM).apply {
putExtra(AlarmClock.EXTRA_HOUR, time.hour)

View File

@ -13,7 +13,7 @@ data class TimerAction(
override val icon: SearchActionIcon = SearchActionIcon.Timer
override val iconColor: Int = 0
override val customIcon: String? = null
override fun start(context: Context) {
val intent = Intent(AlarmClock.ACTION_SET_TIMER).apply {
putExtra(AlarmClock.EXTRA_LENGTH, length.seconds.toInt())

View File

@ -1,9 +1,42 @@
package de.mm20.launcher2.searchactions.builders
import android.content.Context
import de.mm20.launcher2.searchactions.actions.SearchAction
import de.mm20.launcher2.database.entities.SearchActionEntity
import de.mm20.launcher2.searchactions.TextClassificationResult
import de.mm20.launcher2.searchactions.actions.SearchAction
import de.mm20.launcher2.searchactions.actions.SearchActionIcon
import org.json.JSONException
import org.json.JSONObject
interface SearchActionBuilder {
fun build(context: Context, classifiedQuery: TextClassificationResult): SearchAction?
}
companion object {
fun from(entity: SearchActionEntity): SearchActionBuilder? {
val options = entity.options?.let {
try {
JSONObject(it)
} catch (_: JSONException) {
null
}
}
when (entity.type) {
"url" -> {
return WebsearchActionBuilder(
label = entity.label ?: "",
urlTemplate = entity.data,
color = entity.color,
icon = SearchActionIcon.fromInt(entity.icon),
customIcon = entity.customIcon,
encoding = WebsearchActionBuilder.QueryEncoding.fromInt(options?.optInt("encoding"))
)
}
"app" -> {
return null
}
else -> return null
}
}
}
}

View File

@ -12,6 +12,7 @@ class WebsearchActionBuilder(
val label: String,
val urlTemplate: String,
val icon: SearchActionIcon = SearchActionIcon.Search,
val color: Int = 0,
val customIcon: String? = null,
val encoding: QueryEncoding = QueryEncoding.UrlEncode,
) : SearchActionBuilder {
@ -21,6 +22,9 @@ class WebsearchActionBuilder(
return OpenUrlAction(
label = label,
url = url,
icon = icon,
customIcon = customIcon,
iconColor = color,
)
}