diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/common/SearchablePickerVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/common/SearchablePickerVM.kt index d6933651..4f6f5991 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/common/SearchablePickerVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/common/SearchablePickerVM.kt @@ -40,6 +40,7 @@ class SearchablePickerVM : ViewModel(), KoinComponent { searchJob = viewModelScope.launch { searchService.search( query = query, + allowNetwork = true, ).collectLatest { if (searchQuery != query) return@collectLatest items = withContext(Dispatchers.Default) { diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt index 0e6291cd..f149a180 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt @@ -127,7 +127,8 @@ class SearchVM : ViewModel(), KoinComponent { searchJob = viewModelScope.launch { searchUiSettings.resultOrder.collectLatest { resultOrder -> searchService.search( - query + query, + allowNetwork = true, ).collectLatest { results -> var resultsList = withContext(Dispatchers.Default) { listOfNotNull( diff --git a/core/base/src/main/java/de/mm20/launcher2/search/SearchableRepository.kt b/core/base/src/main/java/de/mm20/launcher2/search/SearchableRepository.kt index 20667186..be6761a9 100644 --- a/core/base/src/main/java/de/mm20/launcher2/search/SearchableRepository.kt +++ b/core/base/src/main/java/de/mm20/launcher2/search/SearchableRepository.kt @@ -4,5 +4,5 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.flow.Flow interface SearchableRepository { - fun search(query: String): Flow> + fun search(query: String, allowNetwork: Boolean): Flow> } \ No newline at end of file diff --git a/core/shared/src/main/java/de/mm20/launcher2/plugin/contracts/SearchPluginContract.kt b/core/shared/src/main/java/de/mm20/launcher2/plugin/contracts/SearchPluginContract.kt index 04ea5f31..23eaf05e 100644 --- a/core/shared/src/main/java/de/mm20/launcher2/plugin/contracts/SearchPluginContract.kt +++ b/core/shared/src/main/java/de/mm20/launcher2/plugin/contracts/SearchPluginContract.kt @@ -5,5 +5,6 @@ abstract class SearchPluginContract { const val Search = "search" const val Root = "root" const val QueryParam = "query" + const val AllowNetworkParam = "network" } } \ No newline at end of file diff --git a/data/applications/src/debug/java/de/mm20/launcher2/applications/FakeAppRepository.kt b/data/applications/src/debug/java/de/mm20/launcher2/applications/FakeAppRepository.kt index ecbc45c5..f60f0f19 100644 --- a/data/applications/src/debug/java/de/mm20/launcher2/applications/FakeAppRepository.kt +++ b/data/applications/src/debug/java/de/mm20/launcher2/applications/FakeAppRepository.kt @@ -21,7 +21,7 @@ import kotlinx.coroutines.flow.map class FakeAppRepository(private val context: Context, private val fakePackages: Int) : SearchableRepository { - override fun search(query: String): Flow> { + override fun search(query: String, allowNetwork: Boolean): Flow> { return if (query.isEmpty()) { buildList { repeat(fakePackages) { diff --git a/data/applications/src/main/java/de/mm20/launcher2/applications/AppRepository.kt b/data/applications/src/main/java/de/mm20/launcher2/applications/AppRepository.kt index 9f806b21..16af3d6f 100644 --- a/data/applications/src/main/java/de/mm20/launcher2/applications/AppRepository.kt +++ b/data/applications/src/main/java/de/mm20/launcher2/applications/AppRepository.kt @@ -29,8 +29,6 @@ import org.apache.commons.text.similarity.FuzzyScore import java.util.Locale interface AppRepository : SearchableRepository { - override fun search(query: String): Flow> - fun findMany(): Flow> } @@ -197,7 +195,7 @@ internal class AppRepositoryImpl( return installedApps.map { it.toImmutableList() } } - override fun search(query: String): Flow> { + override fun search(query: String, allowNetwork: Boolean): Flow> { return installedApps.map { apps -> withContext(Dispatchers.Default) { val appResults = mutableListOf() diff --git a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt index fd12e104..d26a4b0d 100644 --- a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt +++ b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt @@ -111,7 +111,7 @@ internal class AppShortcutRepositoryImpl( return flags } - override fun search(query: String): Flow> { + override fun search(query: String, allowNetwork: Boolean): Flow> { if (query.length < 3) { return flowOf(persistentListOf()) } diff --git a/data/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarRepository.kt b/data/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarRepository.kt index 63874231..fcc973fa 100644 --- a/data/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarRepository.kt +++ b/data/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarRepository.kt @@ -40,7 +40,7 @@ internal class CalendarRepositoryImpl( private val settings: CalendarSearchSettings, ) : CalendarRepository { - override fun search(query: String): Flow> { + override fun search(query: String, allowNetwork: Boolean): Flow> { if (query.isBlank() || query.length < 2) { return flow { emit(persistentListOf()) diff --git a/data/contacts/src/main/java/de/mm20/launcher2/contacts/ContactRepository.kt b/data/contacts/src/main/java/de/mm20/launcher2/contacts/ContactRepository.kt index b0a0e0d2..ed2f8d92 100644 --- a/data/contacts/src/main/java/de/mm20/launcher2/contacts/ContactRepository.kt +++ b/data/contacts/src/main/java/de/mm20/launcher2/contacts/ContactRepository.kt @@ -164,7 +164,7 @@ internal class ContactRepository( ) } - override fun search(query: String): Flow> { + override fun search(query: String, allowNetwork: Boolean): Flow> { val hasPermission = permissionsManager.hasPermission(PermissionGroup.Contacts) if (query.length < 2) { diff --git a/data/files/src/main/java/de/mm20/launcher2/files/FilesRepository.kt b/data/files/src/main/java/de/mm20/launcher2/files/FilesRepository.kt index bdb65c9a..7be86ad8 100644 --- a/data/files/src/main/java/de/mm20/launcher2/files/FilesRepository.kt +++ b/data/files/src/main/java/de/mm20/launcher2/files/FilesRepository.kt @@ -32,6 +32,7 @@ internal class FileRepository( override fun search( query: String, + allowNetwork: Boolean, ) = channelFlow { if (query.isBlank()) { send(persistentListOf()) @@ -55,7 +56,7 @@ internal class FileRepository( } val results = mutableListOf() for (provider in providers) { - results.addAll(provider.search(query)) + results.addAll(provider.search(query, allowNetwork)) send(results.toImmutableList()) } } diff --git a/data/files/src/main/java/de/mm20/launcher2/files/providers/FileProvider.kt b/data/files/src/main/java/de/mm20/launcher2/files/providers/FileProvider.kt index 2ab5374c..7861428a 100644 --- a/data/files/src/main/java/de/mm20/launcher2/files/providers/FileProvider.kt +++ b/data/files/src/main/java/de/mm20/launcher2/files/providers/FileProvider.kt @@ -3,5 +3,5 @@ package de.mm20.launcher2.files.providers import de.mm20.launcher2.search.File internal interface FileProvider { - suspend fun search(query: String): List + suspend fun search(query: String, allowNetwork: Boolean): List } \ No newline at end of file diff --git a/data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFileProvider.kt b/data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFileProvider.kt index 11137c7e..6f8266e2 100644 --- a/data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFileProvider.kt +++ b/data/files/src/main/java/de/mm20/launcher2/files/providers/GDriveFileProvider.kt @@ -12,8 +12,8 @@ import kotlinx.collections.immutable.toImmutableMap internal class GDriveFileProvider( private val context: Context ) : FileProvider { - override suspend fun search(query: String): List { - if (query.length < 4) return emptyList() + override suspend fun search(query: String, allowNetwork: Boolean): List { + if (query.length < 4 || !allowNetwork) return emptyList() val driveFiles = GoogleApiHelper.getInstance(context).queryGDriveFiles(query) return driveFiles.map { GDriveFile( diff --git a/data/files/src/main/java/de/mm20/launcher2/files/providers/LocalFileProvider.kt b/data/files/src/main/java/de/mm20/launcher2/files/providers/LocalFileProvider.kt index 74e2a591..f40e0603 100644 --- a/data/files/src/main/java/de/mm20/launcher2/files/providers/LocalFileProvider.kt +++ b/data/files/src/main/java/de/mm20/launcher2/files/providers/LocalFileProvider.kt @@ -13,7 +13,7 @@ internal class LocalFileProvider( private val context: Context, private val permissionsManager: PermissionsManager ): FileProvider { - override suspend fun search(query: String): List = withContext(Dispatchers.IO) { + override suspend fun search(query: String, allowNetwork: Boolean): List = withContext(Dispatchers.IO) { if (!permissionsManager.checkPermissionOnce(PermissionGroup.ExternalStorage)) { return@withContext emptyList() } diff --git a/data/files/src/main/java/de/mm20/launcher2/files/providers/NextcloudFileProvider.kt b/data/files/src/main/java/de/mm20/launcher2/files/providers/NextcloudFileProvider.kt index 242eb8d0..efd84752 100644 --- a/data/files/src/main/java/de/mm20/launcher2/files/providers/NextcloudFileProvider.kt +++ b/data/files/src/main/java/de/mm20/launcher2/files/providers/NextcloudFileProvider.kt @@ -12,8 +12,8 @@ import kotlin.math.min internal class NextcloudFileProvider( private val nextcloudClient: NextcloudApiHelper ) : FileProvider { - override suspend fun search(query: String): List { - if (query.length < 4) return emptyList() + override suspend fun search(query: String, allowNetwork: Boolean): List { + if (query.length < 4 || !allowNetwork) return emptyList() val server = nextcloudClient.getServer() ?: return emptyList() return withContext(Dispatchers.IO) { nextcloudClient.files.search(query).let { it.subList(0, min(10, it.size)) }.map { diff --git a/data/files/src/main/java/de/mm20/launcher2/files/providers/OwncloudFileProvider.kt b/data/files/src/main/java/de/mm20/launcher2/files/providers/OwncloudFileProvider.kt index b4e5c47b..d8440479 100644 --- a/data/files/src/main/java/de/mm20/launcher2/files/providers/OwncloudFileProvider.kt +++ b/data/files/src/main/java/de/mm20/launcher2/files/providers/OwncloudFileProvider.kt @@ -9,8 +9,8 @@ import kotlinx.collections.immutable.persistentMapOf internal class OwncloudFileProvider( private val owncloudClient: OwncloudClient ) : FileProvider { - override suspend fun search(query: String): List { - if (query.length < 4) return emptyList() + override suspend fun search(query: String, allowNetwork: Boolean): List { + if (query.length < 4 || !allowNetwork) return emptyList() val server = owncloudClient.getServer() ?: return emptyList() return owncloudClient.files.query(query).map { OwncloudFile( diff --git a/data/files/src/main/java/de/mm20/launcher2/files/providers/PluginFileProvider.kt b/data/files/src/main/java/de/mm20/launcher2/files/providers/PluginFileProvider.kt index ad04e820..5ea0d6a0 100644 --- a/data/files/src/main/java/de/mm20/launcher2/files/providers/PluginFileProvider.kt +++ b/data/files/src/main/java/de/mm20/launcher2/files/providers/PluginFileProvider.kt @@ -26,12 +26,13 @@ class PluginFileProvider( private val context: Context, private val pluginAuthority: String, ) : FileProvider { - override suspend fun search(query: String): List = withContext(Dispatchers.IO) { + override suspend fun search(query: String, allowNetwork: Boolean): List = withContext(Dispatchers.IO) { val uri = Uri.Builder() .scheme("content") .authority(pluginAuthority) .path(SearchPluginContract.Paths.Search) .appendQueryParameter(SearchPluginContract.Paths.QueryParam, query) + .appendQueryParameter(SearchPluginContract.Paths.AllowNetworkParam, allowNetwork.toString()) .build() val cancellationSignal = CancellationSignal() diff --git a/data/websites/src/main/java/de/mm20/launcher2/websites/WebsiteRepository.kt b/data/websites/src/main/java/de/mm20/launcher2/websites/WebsiteRepository.kt index 9b6bc8e7..f32ab7b6 100644 --- a/data/websites/src/main/java/de/mm20/launcher2/websites/WebsiteRepository.kt +++ b/data/websites/src/main/java/de/mm20/launcher2/websites/WebsiteRepository.kt @@ -2,7 +2,6 @@ package de.mm20.launcher2.websites import android.content.Context import android.webkit.URLUtil -import androidx.compose.runtime.Immutable import androidx.core.graphics.toColorInt import de.mm20.launcher2.preferences.search.WebsiteSearchSettings import de.mm20.launcher2.search.SearchableRepository @@ -11,8 +10,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.channelFlow -import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.transformLatest import kotlinx.coroutines.withContext import okhttp3.HttpUrl @@ -20,7 +18,6 @@ import okhttp3.OkHttpClient import okhttp3.Request import org.jsoup.Jsoup import org.jsoup.UncheckedIOException -import org.koin.core.component.KoinComponent import java.io.IOException import java.net.MalformedURLException import java.net.URISyntaxException @@ -40,8 +37,9 @@ internal class WebsiteRepository( .writeTimeout(1000, TimeUnit.MILLISECONDS) .build() - override fun search(query: String): Flow> { - return settings.enabled.transformLatest {enabled -> + override fun search(query: String, allowNetwork: Boolean): Flow> { + if (!allowNetwork) return flowOf(persistentListOf()) + return settings.enabled.transformLatest { enabled -> emit(persistentListOf()) withContext(Dispatchers.IO) { httpClient.dispatcher.cancelAll() diff --git a/data/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaRepository.kt b/data/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaRepository.kt index 1c27c779..21f0bfe7 100644 --- a/data/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaRepository.kt +++ b/data/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaRepository.kt @@ -53,8 +53,8 @@ internal class WikipediaRepository( private lateinit var wikipediaService: WikipediaApi - override fun search(query: String): Flow> { - if (query.length < 4) return flowOf(persistentListOf()) + override fun search(query: String, allowNetwork: Boolean): Flow> { + if (query.length < 4 || !allowNetwork) return flowOf(persistentListOf()) return settings.enabled.transformLatest { emit(persistentListOf()) diff --git a/plugins/sdk/src/main/java/de/mm20/launcher2/sdk/base/SearchPluginProvider.kt b/plugins/sdk/src/main/java/de/mm20/launcher2/sdk/base/SearchPluginProvider.kt index 43297cb3..72d8de45 100644 --- a/plugins/sdk/src/main/java/de/mm20/launcher2/sdk/base/SearchPluginProvider.kt +++ b/plugins/sdk/src/main/java/de/mm20/launcher2/sdk/base/SearchPluginProvider.kt @@ -19,7 +19,7 @@ abstract class SearchPluginProvider( * Search for items matching the given query * @param query The query to search for */ - abstract suspend fun search(query: String): List + abstract suspend fun search(query: String, allowNetwork: Boolean): List abstract suspend fun get(id: String): T? override fun onCreate(): Boolean { @@ -48,7 +48,10 @@ abstract class SearchPluginProvider( uri.pathSegments.size == 1 && uri.pathSegments.first() == SearchPluginContract.Paths.Search -> { val query = uri.getQueryParameter(SearchPluginContract.Paths.QueryParam) ?: return null - val results = search(query, cancellationSignal) + val allowNetwork = + uri.getQueryParameter(SearchPluginContract.Paths.AllowNetworkParam)?.toBoolean() + ?: false + val results = search(query, allowNetwork, cancellationSignal) val cursor = createCursor(results.size) for (result in results) { writeToCursor(cursor, result) @@ -95,10 +98,11 @@ abstract class SearchPluginProvider( private fun search( query: String, + allowNetwork: Boolean, cancellationSignal: CancellationSignal? ): List { return launchWithCancellationSignal(cancellationSignal) { - search(query) + search(query, allowNetwork) } } diff --git a/services/search/src/main/java/de/mm20/launcher2/search/SearchService.kt b/services/search/src/main/java/de/mm20/launcher2/search/SearchService.kt index 42321875..7c3592f0 100644 --- a/services/search/src/main/java/de/mm20/launcher2/search/SearchService.kt +++ b/services/search/src/main/java/de/mm20/launcher2/search/SearchService.kt @@ -23,6 +23,7 @@ import kotlinx.coroutines.supervisorScope interface SearchService { fun search( query: String, + allowNetwork: Boolean = false, ): Flow } @@ -42,6 +43,7 @@ internal class SearchServiceImpl( override fun search( query: String, + allowNetwork: Boolean, ): Flow = channelFlow { val results = MutableStateFlow(SearchResults()) supervisorScope { @@ -54,7 +56,7 @@ internal class SearchServiceImpl( } } launch { - appRepository.search(query) + appRepository.search(query, allowNetwork) .withCustomLabels(customAttributesRepository) .collectLatest { r -> results.update { @@ -63,7 +65,7 @@ internal class SearchServiceImpl( } } launch { - appShortcutRepository.search(query) + appShortcutRepository.search(query, allowNetwork) .withCustomLabels(customAttributesRepository) .collectLatest { r -> results.update { @@ -72,7 +74,7 @@ internal class SearchServiceImpl( } } launch { - contactRepository.search(query) + contactRepository.search(query, allowNetwork) .withCustomLabels(customAttributesRepository) .collectLatest { r -> results.update { @@ -81,7 +83,7 @@ internal class SearchServiceImpl( } } launch { - calendarRepository.search(query) + calendarRepository.search(query, allowNetwork) .withCustomLabels(customAttributesRepository) .collectLatest { r -> results.update { @@ -107,7 +109,7 @@ internal class SearchServiceImpl( } } launch { - websiteRepository.search(query) + websiteRepository.search(query, allowNetwork) .withCustomLabels(customAttributesRepository) .collectLatest { r -> results.update { @@ -117,7 +119,7 @@ internal class SearchServiceImpl( } launch { delay(750) - articleRepository.search(query) + articleRepository.search(query, allowNetwork) .withCustomLabels(customAttributesRepository) .collectLatest { r -> results.update { @@ -128,6 +130,7 @@ internal class SearchServiceImpl( launch { fileRepository.search( query, + allowNetwork ) .withCustomLabels(customAttributesRepository) .collectLatest { r ->