Reorganize Searchable data types
This commit is contained in:
@@ -42,7 +42,6 @@ dependencies {
|
||||
|
||||
implementation(libs.koin.android)
|
||||
|
||||
implementation(project(":search"))
|
||||
implementation(project(":preferences"))
|
||||
implementation(project(":ktx"))
|
||||
implementation(project(":base"))
|
||||
|
||||
@@ -5,16 +5,18 @@ import android.provider.ContactsContract
|
||||
import de.mm20.launcher2.permissions.PermissionGroup
|
||||
import de.mm20.launcher2.permissions.PermissionsManager
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.search.SearchableRepository
|
||||
import de.mm20.launcher2.search.data.Contact
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
interface ContactRepository {
|
||||
fun search(query: String): Flow<List<Contact>>
|
||||
}
|
||||
interface ContactRepository: SearchableRepository<Contact>
|
||||
|
||||
internal class ContactRepositoryImpl(
|
||||
private val context: Context,
|
||||
@@ -23,13 +25,13 @@ internal class ContactRepositoryImpl(
|
||||
private val permissionsManager: PermissionsManager by inject()
|
||||
private val dataStore: LauncherDataStore by inject()
|
||||
|
||||
override fun search(query: String): Flow<List<Contact>> {
|
||||
override fun search(query: String): Flow<ImmutableList<Contact>> {
|
||||
val searchContacts = dataStore.data.map { it.contactsSearch.enabled }
|
||||
val hasPermission = permissionsManager.hasPermission(PermissionGroup.Contacts)
|
||||
|
||||
if (query.length < 3) {
|
||||
return flow {
|
||||
emit(emptyList())
|
||||
emit(persistentListOf())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,12 +41,12 @@ internal class ContactRepositoryImpl(
|
||||
if (it) {
|
||||
queryContacts(query)
|
||||
} else {
|
||||
emptyList()
|
||||
persistentListOf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun queryContacts(query: String): List<Contact> {
|
||||
private suspend fun queryContacts(query: String): ImmutableList<Contact> {
|
||||
val results = withContext(Dispatchers.IO) {
|
||||
val proj = arrayOf(
|
||||
ContactsContract.RawContacts.CONTACT_ID,
|
||||
@@ -67,6 +69,6 @@ internal class ContactRepositoryImpl(
|
||||
}
|
||||
results
|
||||
}
|
||||
return results
|
||||
return results.toImmutableList()
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,15 @@ import android.content.pm.PackageManager
|
||||
import android.provider.ContactsContract
|
||||
import androidx.core.content.ContextCompat
|
||||
import de.mm20.launcher2.ktx.jsonObjectOf
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.SearchableDeserializer
|
||||
import de.mm20.launcher2.search.SearchableSerializer
|
||||
import de.mm20.launcher2.search.data.Contact
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import org.json.JSONObject
|
||||
|
||||
class ContactSerializer : SearchableSerializer {
|
||||
override fun serialize(searchable: Searchable): String {
|
||||
override fun serialize(searchable: PinnableSearchable): String {
|
||||
searchable as Contact
|
||||
return jsonObjectOf(
|
||||
"id" to searchable.id
|
||||
@@ -25,7 +26,7 @@ class ContactSerializer : SearchableSerializer {
|
||||
}
|
||||
|
||||
class ContactDeserializer(val context: Context) : SearchableDeserializer {
|
||||
override fun deserialize(serialized: String): Searchable? {
|
||||
override fun deserialize(serialized: String): PinnableSearchable? {
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
Manifest.permission.READ_CONTACTS
|
||||
|
||||
@@ -3,20 +3,21 @@ package de.mm20.launcher2.search.data
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.ContactsContract
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.database.getStringOrNull
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import de.mm20.launcher2.contacts.R
|
||||
import de.mm20.launcher2.icons.*
|
||||
import de.mm20.launcher2.ktx.asBitmap
|
||||
import de.mm20.launcher2.ktx.tryStartActivity
|
||||
import de.mm20.launcher2.search.PinnableSearchable
|
||||
import de.mm20.launcher2.search.Searchable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.net.URLEncoder
|
||||
|
||||
class Contact(
|
||||
data class Contact(
|
||||
val id: Long,
|
||||
val firstName: String,
|
||||
val lastName: String,
|
||||
@@ -27,12 +28,21 @@ class Contact(
|
||||
val telegram: Set<ContactInfo>,
|
||||
val whatsapp: Set<ContactInfo>,
|
||||
val postals: Set<ContactInfo>,
|
||||
) : Searchable() {
|
||||
override val labelOverride: String? = null
|
||||
) : Searchable, PinnableSearchable {
|
||||
|
||||
override val domain: String = Domain
|
||||
override val key: String
|
||||
get() = "contact://$id"
|
||||
get() = "${Domain}://$id"
|
||||
override val label: String
|
||||
get() = "$firstName $lastName"
|
||||
|
||||
override fun overrideLabel(label: String): Contact {
|
||||
return this.copy(labelOverride = label)
|
||||
}
|
||||
|
||||
override val preferDetailsOverLaunch: Boolean = true
|
||||
|
||||
val summary: String
|
||||
get() {
|
||||
return phones.union(emails).joinToString(separator = ", ") { it.label }
|
||||
@@ -69,7 +79,12 @@ class Contact(
|
||||
)
|
||||
}
|
||||
|
||||
override fun getLaunchIntent(context: Context): Intent {
|
||||
override fun launch(context: Context, options: Bundle?): Boolean {
|
||||
val intent = getLaunchIntent()
|
||||
return context.tryStartActivity(intent, options)
|
||||
}
|
||||
|
||||
private fun getLaunchIntent(): Intent {
|
||||
val uri =
|
||||
ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id)
|
||||
return Intent(Intent.ACTION_VIEW).setData(uri).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
@@ -202,7 +217,10 @@ class Contact(
|
||||
)
|
||||
}
|
||||
|
||||
const val Domain = "contact"
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class ContactInfo(
|
||||
|
||||
Reference in New Issue
Block a user