Use dependency injection for most singletons
This commit is contained in:
@@ -42,6 +42,8 @@ dependencies {
|
||||
|
||||
implementation(libs.textdrawable)
|
||||
|
||||
implementation(libs.koin.android)
|
||||
|
||||
implementation(project(":search"))
|
||||
implementation(project(":preferences"))
|
||||
implementation(project(":ktx"))
|
||||
|
||||
@@ -9,12 +9,15 @@ import de.mm20.launcher2.search.data.Contact
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class ContactRepository private constructor(val context: Context) : BaseSearchableRepository() {
|
||||
class ContactRepository(
|
||||
val context: Context,
|
||||
hiddenItemsRepository: HiddenItemsRepository
|
||||
) : BaseSearchableRepository() {
|
||||
|
||||
val contacts = MediatorLiveData<List<Contact>?>()
|
||||
|
||||
private val allContacts = MutableLiveData<List<Contact>?>(emptyList())
|
||||
private val hiddenItemKeys = HiddenItemsRepository.getInstance(context).hiddenItemsKeys
|
||||
private val hiddenItemKeys = hiddenItemsRepository.hiddenItemsKeys
|
||||
|
||||
init {
|
||||
contacts.addSource(hiddenItemKeys) { keys ->
|
||||
@@ -35,13 +38,4 @@ class ContactRepository private constructor(val context: Context) : BaseSearchab
|
||||
}
|
||||
allContacts.value = results
|
||||
}
|
||||
|
||||
companion object {
|
||||
private lateinit var instance: ContactRepository
|
||||
|
||||
fun getInstance(context: Context): ContactRepository {
|
||||
if (!::instance.isInitialized) instance = ContactRepository(context.applicationContext)
|
||||
return instance
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package de.mm20.launcher2.contacts
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
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.SearchableDeserializer
|
||||
import de.mm20.launcher2.search.SearchableSerializer
|
||||
import de.mm20.launcher2.search.data.Contact
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import org.json.JSONObject
|
||||
|
||||
class ContactSerializer : SearchableSerializer {
|
||||
override fun serialize(searchable: Searchable): String {
|
||||
searchable as Contact
|
||||
return jsonObjectOf(
|
||||
"id" to searchable.id
|
||||
).toString()
|
||||
}
|
||||
|
||||
override val typePrefix: String
|
||||
get() = "contact"
|
||||
}
|
||||
|
||||
class ContactDeserializer(val context: Context) : SearchableDeserializer {
|
||||
override fun deserialize(serialized: String): Searchable? {
|
||||
if (ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
Manifest.permission.READ_CONTACTS
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) return null
|
||||
val id = JSONObject(serialized).getLong("id")
|
||||
val rawContactsCursor = context.contentResolver.query(
|
||||
ContactsContract.RawContacts.CONTENT_URI,
|
||||
arrayOf(ContactsContract.RawContacts._ID),
|
||||
"${ContactsContract.RawContacts.CONTACT_ID} = ?",
|
||||
arrayOf(id.toString()),
|
||||
null
|
||||
) ?: return null
|
||||
val rawContacts = mutableSetOf<Long>()
|
||||
while (rawContactsCursor.moveToNext()) {
|
||||
rawContacts.add(rawContactsCursor.getLong(0))
|
||||
}
|
||||
rawContactsCursor.close()
|
||||
if (rawContacts.isEmpty()) return null
|
||||
|
||||
return Contact.contactById(context, id, rawContacts)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
package de.mm20.launcher2.contacts
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import de.mm20.launcher2.search.data.Contact
|
||||
|
||||
class ContactViewModel(app: Application) : AndroidViewModel(app) {
|
||||
val contacts: LiveData<List<Contact>?> = ContactRepository.getInstance(app).contacts
|
||||
class ContactViewModel(
|
||||
contactRepository: ContactRepository
|
||||
) : ViewModel() {
|
||||
val contacts: LiveData<List<Contact>?> = contactRepository.contacts
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package de.mm20.launcher2.contacts
|
||||
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.androidx.viewmodel.dsl.viewModel
|
||||
import org.koin.dsl.module
|
||||
|
||||
val contactsModule = module {
|
||||
single { ContactRepository(androidContext(), get()) }
|
||||
viewModel { ContactViewModel(get()) }
|
||||
}
|
||||
@@ -39,12 +39,6 @@ class Contact(
|
||||
return phones.union(emails).joinToString(separator = ", ")
|
||||
}
|
||||
|
||||
override fun serialize(): String {
|
||||
return jsonObjectOf(
|
||||
"id" to id
|
||||
).toString()
|
||||
}
|
||||
|
||||
override fun getPlaceholderIcon(context: Context): LauncherIcon {
|
||||
val iconText = if (firstName.isNotEmpty()) firstName[0].toString() else "" + if (lastName.isNotEmpty()) lastName[0].toString() else ""
|
||||
return LauncherIcon(
|
||||
@@ -96,7 +90,7 @@ class Contact(
|
||||
return results.sortedBy { it }
|
||||
}
|
||||
|
||||
private fun contactById(context: Context, id: Long, rawIds: Set<Long>): Contact? {
|
||||
internal fun contactById(context: Context, id: Long, rawIds: Set<Long>): Contact? {
|
||||
val s = "(" + rawIds.joinToString(separator = " OR ",
|
||||
transform = { "${ContactsContract.Data.RAW_CONTACT_ID} = $it" }) + ")" +
|
||||
" AND (${ContactsContract.Data.MIMETYPE} = \"${ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE}\"" +
|
||||
@@ -187,24 +181,5 @@ class Contact(
|
||||
)
|
||||
}
|
||||
|
||||
fun deserialize(context: Context, serialized: String): Contact? {
|
||||
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) return null
|
||||
val id = JSONObject(serialized).getLong("id")
|
||||
val rawContactsCursor = context.contentResolver.query(
|
||||
ContactsContract.RawContacts.CONTENT_URI,
|
||||
arrayOf(ContactsContract.RawContacts._ID),
|
||||
"${ContactsContract.RawContacts.CONTACT_ID} = ?",
|
||||
arrayOf(id.toString()),
|
||||
null
|
||||
) ?: return null
|
||||
val rawContacts = mutableSetOf<Long>()
|
||||
while (rawContactsCursor.moveToNext()) {
|
||||
rawContacts.add(rawContactsCursor.getLong(0))
|
||||
}
|
||||
rawContactsCursor.close()
|
||||
if (rawContacts.isEmpty()) return null
|
||||
|
||||
return contactById(context, id, rawContacts)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user