Refactor search, favorites and calendar widget

This commit is contained in:
MM20
2021-12-31 20:16:08 +01:00
parent 0193d4e495
commit a2ccef64ce
81 changed files with 1335 additions and 1671 deletions
@@ -1,53 +0,0 @@
package de.mm20.launcher2.search
import kotlinx.coroutines.*
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
abstract class BaseSearchableRepository: KoinComponent {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
val searchRepository: SearchRepository by inject()
private val searchQuery = searchRepository.currentQuery
init {
searchQuery.observeForever {
onQueryChange(it)
}
}
protected open fun onCancel() {
}
protected fun launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
) {
scope.launch(context, start, block)
}
private var searchJob: Job? = null
private fun onQueryChange(query: String) {
scope.launch {
onCancel()
searchJob?.takeIf { !it.isCompleted || !it.isCancelled }?.cancelAndJoin()
searchJob = scope.launch {
searchRepository.startSearch()
search(query)
}.also {
it.invokeOnCompletion { searchRepository.endSearch() }
}
}
}
/**
* Called when the query string changes. This method should change the current data presented
* by this SearchableRepository.
*/
protected abstract suspend fun search(query: String)
}
@@ -1,12 +1,9 @@
package de.mm20.launcher2.search
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.dsl.module
val searchModule = module {
single { SearchRepository() }
viewModel { SearchViewModel(get()) }
single { WebsearchRepository(androidContext()) }
single<WebsearchRepository> { WebsearchRepositoryImpl(get()) }
viewModel { WebsearchViewModel(get()) }
}
@@ -22,9 +22,4 @@ class SearchRepository {
}
}
fun endSearch() {
synchronized(runningSearches) {
runningSearches--
}
}
}
@@ -1,16 +0,0 @@
package de.mm20.launcher2.search
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
class SearchViewModel(
private val searchRepository: SearchRepository
) : ViewModel() {
val isSearching: LiveData<Boolean> = searchRepository.isSearching
fun search(query: String) {
searchRepository.currentQuery.value = query
}
}
@@ -1,54 +1,56 @@
package de.mm20.launcher2.search
import android.content.Context
import android.content.Intent
import android.graphics.Color
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import de.mm20.launcher2.database.AppDatabase
import de.mm20.launcher2.search.data.Websearch
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
class WebsearchRepository(val context: Context) : BaseSearchableRepository() {
interface WebsearchRepository {
fun search(query: String): Flow<List<Websearch>>
val websearches = MutableLiveData<List<Websearch>>(emptyList())
fun getWebsearches(): Flow<List<Websearch>>
val allWebsearches = MediatorLiveData<List<Websearch>>()
fun insertWebsearch(websearch: Websearch)
fun deleteWebsearch(websearch: Websearch)
}
init {
val databaseWebsearches = AppDatabase.getInstance(context).searchDao().getWebSearchesLiveData()
allWebsearches.addSource(databaseWebsearches) {
allWebsearches.value = it.map { Websearch(it) }
}
}
class WebsearchRepositoryImpl(
private val database: AppDatabase
) : WebsearchRepository {
override suspend fun search(query: String) {
private val scope = CoroutineScope(Job() + Dispatchers.Main)
override fun search(query: String): Flow<List<Websearch>> = channelFlow {
if (query.isEmpty()) {
websearches.value = emptyList()
return
send(emptyList())
return@channelFlow
}
val searches = withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).searchDao().getWebSearches().map {
Websearch(it, query)
withContext(Dispatchers.IO) {
database.searchDao().getWebSearches().map {
it.map { Websearch(it, query) }
}
}.collectLatest {
send(it)
}
websearches.value = searches
}
fun insertWebsearch(websearch: Websearch) {
launch {
override fun getWebsearches(): Flow<List<Websearch>> =
database.searchDao().getWebSearches().map {
it.map { Websearch(it) }
}
override fun insertWebsearch(websearch: Websearch) {
scope.launch {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).searchDao().insertWebsearch(websearch.toDatabaseEntity())
database.searchDao().insertWebsearch(websearch.toDatabaseEntity())
}
}
}
fun deleteWebsearch(websearch: Websearch) {
launch {
override fun deleteWebsearch(websearch: Websearch) {
scope.launch {
withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).searchDao().deleteWebsearch(websearch.toDatabaseEntity())
database.searchDao().deleteWebsearch(websearch.toDatabaseEntity())
}
}
}
@@ -1,6 +1,7 @@
package de.mm20.launcher2.search
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import de.mm20.launcher2.search.data.Websearch
class WebsearchViewModel(
@@ -16,7 +17,6 @@ class WebsearchViewModel(
websearchRepository.deleteWebsearch(websearch)
}
val websearches = websearchRepository.websearches
val allWebsearches = websearchRepository.allWebsearches
val allWebsearches = websearchRepository.getWebsearches().asLiveData()
}