Filter hidden items in UI layer
This commit is contained in:
parent
aa0cd9a062
commit
5ae0ec42b7
@ -120,7 +120,6 @@ dependencies {
|
||||
implementation(project(":favorites"))
|
||||
implementation(project(":files"))
|
||||
implementation(project(":g-services"))
|
||||
implementation(project(":hiddenitems"))
|
||||
implementation(project(":i18n"))
|
||||
implementation(project(":icons"))
|
||||
implementation(project(":ktx"))
|
||||
|
||||
@ -15,7 +15,6 @@ import de.mm20.launcher2.contacts.contactsModule
|
||||
import de.mm20.launcher2.debug.Debug
|
||||
import de.mm20.launcher2.favorites.favoritesModule
|
||||
import de.mm20.launcher2.files.filesModule
|
||||
import de.mm20.launcher2.hiddenitems.hiddenItemsModule
|
||||
import de.mm20.launcher2.icons.iconsModule
|
||||
import de.mm20.launcher2.music.musicModule
|
||||
import de.mm20.launcher2.search.searchModule
|
||||
@ -61,7 +60,6 @@ class LauncherApplication : Application(), CoroutineScope, ImageLoaderFactory {
|
||||
databaseModule,
|
||||
favoritesModule,
|
||||
filesModule,
|
||||
hiddenItemsModule,
|
||||
iconsModule,
|
||||
musicModule,
|
||||
notificationsModule,
|
||||
|
||||
@ -51,7 +51,6 @@ dependencies {
|
||||
implementation(project(":base"))
|
||||
implementation(project(":preferences"))
|
||||
implementation(project(":ktx"))
|
||||
implementation(project(":hiddenitems"))
|
||||
implementation(project(":compat"))
|
||||
|
||||
}
|
||||
@ -11,7 +11,6 @@ import android.os.Process
|
||||
import android.os.UserHandle
|
||||
import android.util.Log
|
||||
import com.github.promeg.pinyinhelper.Pinyin
|
||||
import de.mm20.launcher2.hiddenitems.HiddenItemsRepository
|
||||
import de.mm20.launcher2.search.data.AppInstallation
|
||||
import de.mm20.launcher2.search.data.Application
|
||||
import de.mm20.launcher2.search.data.LauncherApp
|
||||
@ -23,13 +22,12 @@ import java.util.*
|
||||
|
||||
interface AppRepository {
|
||||
fun search(query: String): Flow<List<Application>>
|
||||
fun getAllInstalledApps(includeHidden: Boolean = false): Flow<List<Application>>
|
||||
fun getAllInstalledApps(): Flow<List<Application>>
|
||||
fun getSuspendedPackages(): Flow<List<String>>
|
||||
}
|
||||
|
||||
internal class AppRepositoryImpl(
|
||||
private val context: Context,
|
||||
hiddenItemsRepository: HiddenItemsRepository,
|
||||
) : AppRepository {
|
||||
|
||||
private val launcherApps =
|
||||
@ -37,7 +35,6 @@ internal class AppRepositoryImpl(
|
||||
|
||||
private val installedApps = MutableStateFlow<List<LauncherApp>>(emptyList())
|
||||
private val installations = MutableStateFlow<MutableList<AppInstallation>>(mutableListOf())
|
||||
private val hiddenItems = hiddenItemsRepository.hiddenItemsKeys
|
||||
private val suspendedPackages = MutableStateFlow<List<String>>(emptyList())
|
||||
|
||||
|
||||
@ -191,7 +188,7 @@ internal class AppRepositoryImpl(
|
||||
|
||||
override fun search(query: String): Flow<List<Application>> = channelFlow {
|
||||
|
||||
merge(installedApps, hiddenItems, installations).collectLatest {
|
||||
merge(installedApps, installations).collectLatest {
|
||||
withContext(Dispatchers.Default) {
|
||||
val appResults = mutableListOf<Application>()
|
||||
if (query.isEmpty()) {
|
||||
@ -204,13 +201,11 @@ internal class AppRepositoryImpl(
|
||||
appResults.addAll(installations.value.filter {
|
||||
matches(it.label, query)
|
||||
})
|
||||
|
||||
val componentName = ComponentName.unflattenFromString(query)
|
||||
getActivityByComponentName(componentName)?.let { appResults.add(it) }
|
||||
}
|
||||
|
||||
val componentName = ComponentName.unflattenFromString(query)
|
||||
getActivityByComponentName(componentName)?.let { appResults.add(it) }
|
||||
|
||||
appResults.removeAll { hiddenItems.value.contains(it.key) }
|
||||
|
||||
appResults.sort()
|
||||
|
||||
send(appResults)
|
||||
@ -218,18 +213,8 @@ internal class AppRepositoryImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAllInstalledApps(includeHidden: Boolean): Flow<List<Application>> {
|
||||
return if (!includeHidden) {
|
||||
channelFlow {
|
||||
hiddenItems.collectLatest { hidden ->
|
||||
installedApps.collectLatest { apps ->
|
||||
send(apps.filter { !hidden.contains(it.key) })
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
installedApps
|
||||
}
|
||||
override fun getAllInstalledApps(): Flow<List<Application>> {
|
||||
return installedApps
|
||||
}
|
||||
|
||||
private fun matches(label: String, query: String): Boolean {
|
||||
|
||||
@ -5,5 +5,5 @@ import org.koin.androidx.viewmodel.dsl.viewModel
|
||||
import org.koin.dsl.module
|
||||
|
||||
val applicationsModule = module {
|
||||
single<AppRepository> { AppRepositoryImpl(androidContext(), get()) }
|
||||
single<AppRepository> { AppRepositoryImpl(androidContext()) }
|
||||
}
|
||||
@ -46,7 +46,6 @@ dependencies {
|
||||
|
||||
implementation(project(":search"))
|
||||
implementation(project(":permissions"))
|
||||
implementation(project(":hiddenitems"))
|
||||
implementation(project(":base"))
|
||||
implementation(project(":preferences"))
|
||||
implementation(project(":ktx"))
|
||||
|
||||
@ -7,7 +7,6 @@ import android.content.pm.PackageManager
|
||||
import android.os.Process
|
||||
import androidx.core.content.getSystemService
|
||||
import com.github.promeg.pinyinhelper.Pinyin
|
||||
import de.mm20.launcher2.hiddenitems.HiddenItemsRepository
|
||||
import de.mm20.launcher2.permissions.PermissionGroup
|
||||
import de.mm20.launcher2.permissions.PermissionsManager
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
@ -33,7 +32,6 @@ interface AppShortcutRepository {
|
||||
internal class AppShortcutRepositoryImpl(
|
||||
private val context: Context,
|
||||
private val permissionsManager: PermissionsManager,
|
||||
private val hiddenItemsRepository: HiddenItemsRepository,
|
||||
private val dataStore: LauncherDataStore,
|
||||
) : AppShortcutRepository {
|
||||
|
||||
@ -110,22 +108,20 @@ internal class AppShortcutRepositoryImpl(
|
||||
val pm = context.packageManager
|
||||
|
||||
|
||||
hiddenItemsRepository.hiddenItemsKeys.collectLatest { hidden ->
|
||||
send(
|
||||
shortcuts.mapNotNull {
|
||||
val label = try {
|
||||
pm.getApplicationInfo(it.`package`, 0).loadLabel(pm).toString()
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
""
|
||||
}
|
||||
AppShortcut(
|
||||
context,
|
||||
it,
|
||||
label
|
||||
).takeIf { !hidden.contains(it.key) }
|
||||
}.sorted()
|
||||
)
|
||||
}
|
||||
send(
|
||||
shortcuts.mapNotNull {
|
||||
val label = try {
|
||||
pm.getApplicationInfo(it.`package`, 0).loadLabel(pm).toString()
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
""
|
||||
}
|
||||
AppShortcut(
|
||||
context,
|
||||
it,
|
||||
label
|
||||
)
|
||||
}.sorted()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,5 +4,5 @@ import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.dsl.module
|
||||
|
||||
val appShortcutsModule = module {
|
||||
single<AppShortcutRepository> { AppShortcutRepositoryImpl(androidContext(), get(), get(), get()) }
|
||||
single<AppShortcutRepository> { AppShortcutRepositoryImpl(androidContext(), get(), get()) }
|
||||
}
|
||||
@ -46,7 +46,6 @@ dependencies {
|
||||
implementation(project(":preferences"))
|
||||
implementation(project(":ktx"))
|
||||
implementation(project(":base"))
|
||||
implementation(project(":hiddenitems"))
|
||||
implementation(project(":permissions"))
|
||||
implementation(project(":material-color-utilities"))
|
||||
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
package de.mm20.launcher2.calendar
|
||||
|
||||
import android.Manifest
|
||||
import android.content.ContentUris
|
||||
import android.content.Context
|
||||
import android.provider.CalendarContract
|
||||
import androidx.core.database.getStringOrNull
|
||||
import de.mm20.launcher2.hiddenitems.HiddenItemsRepository
|
||||
import de.mm20.launcher2.ktx.checkPermission
|
||||
import de.mm20.launcher2.permissions.PermissionGroup
|
||||
import de.mm20.launcher2.permissions.PermissionsManager
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
@ -29,23 +26,21 @@ interface CalendarRepository {
|
||||
|
||||
internal class CalendarRepositoryImpl(
|
||||
private val context: Context,
|
||||
hiddenItemsRepository: HiddenItemsRepository
|
||||
) : CalendarRepository, KoinComponent {
|
||||
|
||||
private val dataStore: LauncherDataStore by inject()
|
||||
private val permissionsManager: PermissionsManager by inject()
|
||||
|
||||
private val hiddenItems = hiddenItemsRepository.hiddenItemsKeys
|
||||
|
||||
override fun search(query: String): Flow<List<CalendarEvent>> = channelFlow {
|
||||
override fun search(query: String): Flow<List<CalendarEvent>> {
|
||||
if (query.isBlank() || query.length < 3) {
|
||||
send(emptyList())
|
||||
return@channelFlow
|
||||
return flow {
|
||||
emit(emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
val hasPermission = permissionsManager.hasPermission(PermissionGroup.Calendar)
|
||||
val searchCalendar = dataStore.data.map { it.calendarSearch.enabled }
|
||||
combine(hasPermission, searchCalendar) { permission, search ->
|
||||
return combine(hasPermission, searchCalendar) { permission, search ->
|
||||
permission && search
|
||||
}.map {
|
||||
if (it) {
|
||||
@ -58,12 +53,6 @@ internal class CalendarRepositoryImpl(
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}.flatMapLatest { events ->
|
||||
hiddenItems.map { hidden ->
|
||||
events.filter { !hidden.contains(it.key) }
|
||||
}
|
||||
}.collectLatest {
|
||||
send(it)
|
||||
}
|
||||
|
||||
}
|
||||
@ -160,23 +149,19 @@ internal class CalendarRepositoryImpl(
|
||||
hasPermission.collectLatest {
|
||||
if (it) {
|
||||
dataStore.data.map { it.calendarWidget }.collectLatest { settings ->
|
||||
hiddenItems.collectLatest { hidden ->
|
||||
val now = System.currentTimeMillis()
|
||||
val end = now + 14 * 24 * 60 * 60 * 1000L
|
||||
val events = withContext(Dispatchers.IO) {
|
||||
queryCalendarEvents(
|
||||
query = "",
|
||||
intervalStart = now,
|
||||
intervalEnd = end,
|
||||
limit = 700,
|
||||
excludeAllDayEvents = settings.hideAlldayEvents,
|
||||
excludeCalendars = settings.excludeCalendarsList
|
||||
).filter {
|
||||
!hiddenItems.value.contains(it.key)
|
||||
}
|
||||
}
|
||||
send(events)
|
||||
val now = System.currentTimeMillis()
|
||||
val end = now + 14 * 24 * 60 * 60 * 1000L
|
||||
val events = withContext(Dispatchers.IO) {
|
||||
queryCalendarEvents(
|
||||
query = "",
|
||||
intervalStart = now,
|
||||
intervalEnd = end,
|
||||
limit = 700,
|
||||
excludeAllDayEvents = settings.hideAlldayEvents,
|
||||
excludeCalendars = settings.excludeCalendarsList
|
||||
)
|
||||
}
|
||||
send(events)
|
||||
}
|
||||
} else {
|
||||
send(emptyList())
|
||||
|
||||
@ -5,5 +5,5 @@ import org.koin.androidx.viewmodel.dsl.viewModel
|
||||
import org.koin.dsl.module
|
||||
|
||||
val calendarModule = module {
|
||||
single<CalendarRepository> { CalendarRepositoryImpl(androidContext(), get()) }
|
||||
single<CalendarRepository> { CalendarRepositoryImpl(androidContext()) }
|
||||
}
|
||||
@ -46,7 +46,6 @@ dependencies {
|
||||
implementation(project(":preferences"))
|
||||
implementation(project(":ktx"))
|
||||
implementation(project(":base"))
|
||||
implementation(project(":hiddenitems"))
|
||||
implementation(project(":permissions"))
|
||||
|
||||
}
|
||||
@ -2,7 +2,6 @@ package de.mm20.launcher2.contacts
|
||||
|
||||
import android.content.Context
|
||||
import android.provider.ContactsContract
|
||||
import de.mm20.launcher2.hiddenitems.HiddenItemsRepository
|
||||
import de.mm20.launcher2.permissions.PermissionGroup
|
||||
import de.mm20.launcher2.permissions.PermissionsManager
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
@ -19,23 +18,22 @@ interface ContactRepository {
|
||||
|
||||
internal class ContactRepositoryImpl(
|
||||
private val context: Context,
|
||||
hiddenItemsRepository: HiddenItemsRepository
|
||||
) : ContactRepository, KoinComponent {
|
||||
|
||||
private val permissionsManager: PermissionsManager by inject()
|
||||
private val dataStore: LauncherDataStore by inject()
|
||||
private val hiddenItems = hiddenItemsRepository.hiddenItemsKeys
|
||||
|
||||
override fun search(query: String): Flow<List<Contact>> = channelFlow {
|
||||
override fun search(query: String): Flow<List<Contact>> {
|
||||
val searchContacts = dataStore.data.map { it.contactsSearch.enabled }
|
||||
val hasPermission = permissionsManager.hasPermission(PermissionGroup.Contacts)
|
||||
|
||||
if (query.length < 3) {
|
||||
send(emptyList())
|
||||
return@channelFlow
|
||||
return flow {
|
||||
emit(emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
combine(searchContacts, hasPermission) { search, permission ->
|
||||
return combine(searchContacts, hasPermission) { search, permission ->
|
||||
search && permission
|
||||
}.map {
|
||||
if (it) {
|
||||
@ -43,12 +41,6 @@ internal class ContactRepositoryImpl(
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}.flatMapLatest { contacts ->
|
||||
hiddenItems.map { hidden ->
|
||||
contacts.filter { !hidden.contains(it.key) }
|
||||
}
|
||||
}.collectLatest {
|
||||
send(it)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,5 +5,5 @@ import org.koin.androidx.viewmodel.dsl.viewModel
|
||||
import org.koin.dsl.module
|
||||
|
||||
val contactsModule = module {
|
||||
single<ContactRepository> { ContactRepositoryImpl(androidContext(), get()) }
|
||||
single<ContactRepository> { ContactRepositoryImpl(androidContext()) }
|
||||
}
|
||||
@ -24,6 +24,9 @@ interface SearchDao {
|
||||
@Query("SELECT * FROM Searchable WHERE pinned > 0 AND `key` LIKE 'calendar://%' ORDER BY pinned DESC, launchCount DESC")
|
||||
fun getPinnedCalendarEvents(): Flow<List<FavoritesItemEntity>>
|
||||
|
||||
@Query("SELECT `key` FROM Searchable WHERE hidden = 1 AND `key` LIKE 'calendar://%'")
|
||||
fun getHiddenCalendarEventKeys(): Flow<List<String>>
|
||||
|
||||
|
||||
@Query("SELECT COUNT(key) as count FROM Searchable WHERE pinned = 1;")
|
||||
fun getPinCount(): Int
|
||||
|
||||
@ -27,6 +27,7 @@ interface FavoritesRepository {
|
||||
): Flow<List<Searchable>>
|
||||
|
||||
fun getPinnedCalendarEvents(): Flow<List<Searchable>>
|
||||
fun getHiddenCalendarEventKeys(): Flow<List<String>>
|
||||
fun isPinned(searchable: Searchable): Flow<Boolean>
|
||||
fun pinItem(searchable: Searchable)
|
||||
fun unpinItem(searchable: Searchable)
|
||||
@ -37,6 +38,7 @@ interface FavoritesRepository {
|
||||
suspend fun getAllFavoriteItems(): List<FavoritesItem>
|
||||
fun saveFavorites(favorites: List<FavoritesItem>)
|
||||
fun getHiddenItems(): Flow<List<Searchable>>
|
||||
fun getHiddenItemKeys(): Flow<List<String>>
|
||||
|
||||
suspend fun export(toDir: File)
|
||||
suspend fun import(fromDir: File)
|
||||
@ -91,6 +93,10 @@ internal class FavoritesRepositoryImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getHiddenCalendarEventKeys(): Flow<List<String>> {
|
||||
return database.searchDao().getHiddenCalendarEventKeys()
|
||||
}
|
||||
|
||||
override fun isPinned(searchable: Searchable): Flow<Boolean> {
|
||||
return AppDatabase.getInstance(context).searchDao().isPinned(searchable.key)
|
||||
}
|
||||
@ -184,6 +190,10 @@ internal class FavoritesRepositoryImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getHiddenItemKeys(): Flow<List<String>> {
|
||||
return database.searchDao().getHiddenItemKeys()
|
||||
}
|
||||
|
||||
|
||||
private fun fromDatabaseEntity(entity: FavoritesItemEntity): FavoritesItem {
|
||||
val deserializer: SearchableDeserializer =
|
||||
|
||||
@ -45,7 +45,6 @@ dependencies {
|
||||
implementation(libs.koin.android)
|
||||
|
||||
implementation(project(":search"))
|
||||
implementation(project(":hiddenitems"))
|
||||
implementation(project(":preferences"))
|
||||
implementation(project(":base"))
|
||||
implementation(project(":ktx"))
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
package de.mm20.launcher2.files
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import de.mm20.launcher2.files.providers.*
|
||||
import de.mm20.launcher2.hiddenitems.HiddenItemsRepository
|
||||
import de.mm20.launcher2.nextcloud.NextcloudApiHelper
|
||||
import de.mm20.launcher2.owncloud.OwncloudClient
|
||||
import de.mm20.launcher2.permissions.PermissionsManager
|
||||
@ -22,14 +20,12 @@ interface FileRepository {
|
||||
|
||||
internal class FileRepositoryImpl(
|
||||
private val context: Context,
|
||||
hiddenItemsRepository: HiddenItemsRepository,
|
||||
private val dataStore: LauncherDataStore,
|
||||
private val permissionsManager: PermissionsManager,
|
||||
) : FileRepository {
|
||||
|
||||
private val scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||
|
||||
private val hiddenItems = hiddenItemsRepository.hiddenItemsKeys
|
||||
|
||||
private val providers = MutableStateFlow<List<FileProvider>>(emptyList())
|
||||
|
||||
@ -75,12 +71,10 @@ internal class FileRepositoryImpl(
|
||||
send(emptyList())
|
||||
return@collectLatest
|
||||
}
|
||||
hiddenItems.collectLatest { hiddenItems ->
|
||||
val results = mutableListOf<File>()
|
||||
for (provider in providers) {
|
||||
results.addAll(provider.search(query))
|
||||
send(results.toList())
|
||||
}
|
||||
val results = mutableListOf<File>()
|
||||
for (provider in providers) {
|
||||
results.addAll(provider.search(query))
|
||||
send(results.toList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,5 +5,5 @@ import org.koin.androidx.viewmodel.dsl.viewModel
|
||||
import org.koin.dsl.module
|
||||
|
||||
val filesModule = module {
|
||||
single<FileRepository> { FileRepositoryImpl(androidContext(), get(), get(), get()) }
|
||||
single<FileRepository> { FileRepositoryImpl(androidContext(), get(), get()) }
|
||||
}
|
||||
1
hiddenitems/.gitignore
vendored
1
hiddenitems/.gitignore
vendored
@ -1 +0,0 @@
|
||||
/build
|
||||
@ -1,46 +0,0 @@
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
id("kotlin-android")
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk = sdk.versions.compileSdk.get().toInt()
|
||||
|
||||
defaultConfig {
|
||||
minSdk = sdk.versions.minSdk.get().toInt()
|
||||
targetSdk = sdk.versions.targetSdk.get().toInt()
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles("consumer-rules.pro")
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
namespace = "de.mm20.launcher2.hiddenitems"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.bundles.kotlin)
|
||||
implementation(libs.androidx.core)
|
||||
implementation(libs.androidx.appcompat)
|
||||
|
||||
implementation(libs.koin.android)
|
||||
|
||||
implementation(project(":database"))
|
||||
implementation(project(":search"))
|
||||
}
|
||||
21
hiddenitems/proguard-rules.pro
vendored
21
hiddenitems/proguard-rules.pro
vendored
@ -1,21 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.kts.kts.kts.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@ -1,4 +0,0 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
/
|
||||
</manifest>
|
||||
@ -1,38 +0,0 @@
|
||||
package de.mm20.launcher2.hiddenitems
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import de.mm20.launcher2.database.AppDatabase
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* A low level repository for hidden items. This can only be used to retrieve keys and to check
|
||||
* whether an item is hidden. To retrieve actual Searchable objects, use FavoritesRepository.
|
||||
*/
|
||||
class HiddenItemsRepository(val context: Context, database: AppDatabase) {
|
||||
|
||||
val scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||
val hiddenItemsKeys = MutableStateFlow<List<String>>(emptyList())
|
||||
|
||||
init {
|
||||
scope.launch {
|
||||
AppDatabase.getInstance(context).searchDao().getHiddenItemKeys().collectLatest {
|
||||
hiddenItemsKeys.value = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun isHidden(item: Searchable): Flow<Boolean> {
|
||||
return AppDatabase.getInstance(context).searchDao().isHidden(item.key)
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
package de.mm20.launcher2.hiddenitems
|
||||
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.androidx.viewmodel.dsl.viewModel
|
||||
import org.koin.dsl.module
|
||||
|
||||
val hiddenItemsModule = module {
|
||||
single { HiddenItemsRepository(androidContext(), get()) }
|
||||
}
|
||||
@ -11,7 +11,6 @@ include(":contacts")
|
||||
include(":g-services")
|
||||
include(":files")
|
||||
include(":calculator")
|
||||
include(":hiddenitems")
|
||||
include(":badges")
|
||||
include(":applications")
|
||||
include(":ms-services")
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package de.mm20.launcher2.ui.launcher.search
|
||||
|
||||
import android.util.Log
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
@ -21,10 +22,7 @@ import de.mm20.launcher2.websites.WebsiteRepository
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
import de.mm20.launcher2.wikipedia.WikipediaRepository
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
@ -65,6 +63,10 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
|
||||
val hideFavorites = MutableLiveData(false)
|
||||
|
||||
private val hiddenItemKeys = favoritesRepository
|
||||
.getHiddenItemKeys()
|
||||
.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), replay = 1)
|
||||
|
||||
init {
|
||||
search("")
|
||||
viewModelScope.launch {
|
||||
@ -100,18 +102,24 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
isSearching.postValue(true)
|
||||
val jobs = mutableListOf<Deferred<Any>>()
|
||||
jobs += async {
|
||||
appRepository.search(query).collectLatest {
|
||||
appResults.postValue(it)
|
||||
appRepository.search(query).collectLatest { apps ->
|
||||
hiddenItemKeys.collectLatest { hidden ->
|
||||
appResults.postValue(apps.filter { !hidden.contains(it.key) })
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs += async {
|
||||
contactRepository.search(query).collectLatest {
|
||||
contactResults.postValue(it)
|
||||
contactRepository.search(query).collectLatest { contacts ->
|
||||
hiddenItemKeys.collectLatest { hidden ->
|
||||
contactResults.postValue(contacts.filter { !hidden.contains(it.key) })
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs += async {
|
||||
calendarRepository.search(query).collectLatest {
|
||||
calendarResults.postValue(it)
|
||||
calendarRepository.search(query).collectLatest { events ->
|
||||
hiddenItemKeys.collectLatest { hidden ->
|
||||
calendarResults.postValue(events.filter { !hidden.contains(it.key) })
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs += async {
|
||||
@ -135,8 +143,10 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
}
|
||||
jobs += async {
|
||||
fileRepository.search(query).collectLatest {
|
||||
fileResults.postValue(it)
|
||||
fileRepository.search(query).collectLatest { files ->
|
||||
hiddenItemKeys.collectLatest { hidden ->
|
||||
fileResults.postValue(files.filter { !hidden.contains(it.key) })
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs += async {
|
||||
@ -145,8 +155,10 @@ class SearchVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
}
|
||||
jobs += async {
|
||||
appShortcutRepository.search(query).collectLatest {
|
||||
appShortcutResults.postValue(it)
|
||||
appShortcutRepository.search(query).collectLatest { shortcuts ->
|
||||
hiddenItemKeys.collectLatest { hidden ->
|
||||
appShortcutResults.postValue(shortcuts.filter { !hidden.contains(it.key) })
|
||||
}
|
||||
}
|
||||
}
|
||||
jobs.map { it.await() }
|
||||
|
||||
@ -143,8 +143,10 @@ class CalendarWidgetVM : ViewModel(), KoinComponent {
|
||||
}
|
||||
|
||||
suspend fun onActive() {
|
||||
calendarRepository.getUpcomingEvents().collectLatest {
|
||||
upcomingEvents = it
|
||||
calendarRepository.getUpcomingEvents().collectLatest { events ->
|
||||
favoritesRepository.getHiddenCalendarEventKeys().collectLatest { hidden ->
|
||||
upcomingEvents = events.filter { !hidden.contains(it.key) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ class HiddenItemsSettingsScreenVM : ViewModel(), KoinComponent {
|
||||
private val favoritesRepository: FavoritesRepository by inject()
|
||||
private val iconRepository: IconRepository by inject()
|
||||
|
||||
val allApps = appRepository.getAllInstalledApps(true).map {
|
||||
val allApps = appRepository.getAllInstalledApps().map {
|
||||
withContext(Dispatchers.Default) { it.sorted() }
|
||||
}.asLiveData()
|
||||
val hiddenItems: LiveData<List<Searchable>> = liveData {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user