Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c47d403 authored by Fahim M. Choudhury's avatar Fahim M. Choudhury
Browse files

refactor: modify dummy search behaviour

While searching for an app in App Lounge, initially we'll be using a dummy search for Facebook in the background in parallel with the original search to probe Google Play. We will expect both Facebook and Messenger apps to be returned in the search results. If it doesn't happen, then we'll refresh the token and try to search again.

Besides, if the token used in App Lounge gets refreshed in the process (or in any other scenario), we'll show a Toast to the user in debug builds.

Finally, HTTP logging level is set to request and headers only to avoid overflowing Logcat.
parent 4309dd3a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.os.Bundle
import android.view.View
import android.widget.Toast
import android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Lifecycle
@@ -466,6 +467,9 @@ class MainActivity : AppCompatActivity() {
        }.distinctUntilChanged { old, new ->
            ((old.data is String) && (new.data is String) && old.data == new.data)
        }.collectLatest {
            if (BuildConfig.DEBUG) {
                Toast.makeText(this, "Refreshing token...", Toast.LENGTH_SHORT).show()
            }
            validatedAuthObject(it)
        }
    }
+32 −15
Original line number Diff line number Diff line
/*
 * Copyright MURENA SAS 2023
 * Apps  Quickly and easily install Android apps onto your device!
 * Copyright (C) 2024 MURENA SAS
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
@@ -14,6 +13,7 @@
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package foundation.e.apps.data.application.search
@@ -28,11 +28,11 @@ import foundation.e.apps.data.AppSourcesContainer
import foundation.e.apps.data.ResultSupreme
import foundation.e.apps.data.application.ApplicationDataManager
import foundation.e.apps.data.application.apps.AppsApi
import foundation.e.apps.data.application.data.Application
import foundation.e.apps.data.application.data.Home
import foundation.e.apps.data.application.search.SearchApi.Companion.APP_TYPE_ANY
import foundation.e.apps.data.application.search.SearchApi.Companion.APP_TYPE_OPEN
import foundation.e.apps.data.application.search.SearchApi.Companion.APP_TYPE_PWA
import foundation.e.apps.data.application.data.Application
import foundation.e.apps.data.application.data.Home
import foundation.e.apps.data.application.utils.toApplication
import foundation.e.apps.data.enums.Origin
import foundation.e.apps.data.enums.ResultStatus
@@ -43,7 +43,9 @@ import foundation.e.apps.ui.search.SearchResult
import foundation.e.apps.utils.eventBus.AppEvent
import foundation.e.apps.utils.eventBus.EventBus
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@@ -65,6 +67,11 @@ class SearchApiImpl @Inject constructor(

    companion object {
        private const val KEYWORD_TEST_SEARCH = "facebook"

        private val DUMMY_SEARCH_EXPECTED_APPS = listOf(
            "Facebook" to "com.facebook.katana",
            "Messenger" to "com.facebook.orca"
        )
    }

    override fun getSelectedAppTypes(): List<String> {
@@ -327,6 +334,8 @@ class SearchApiImpl @Inject constructor(
        nextPageSubBundle: Set<SearchBundle.SubBundle>?
    ): GplaySearchResult {
        return handleNetworkResult {
            coroutineScope { launch(Dispatchers.IO) { doDummySearch() } }

            val searchResults =
                appSources.gplayRepo.getSearchResult(query, nextPageSubBundle?.toMutableSet())

@@ -339,8 +348,6 @@ class SearchApiImpl @Inject constructor(

            val fusedAppList = replaceWithFDroid(searchResults.first).toMutableList()

            handleLimitedResult(fusedAppList)

            if (searchResults.second.isNotEmpty()) {
                fusedAppList.add(Application(isPlaceHolder = true))
            }
@@ -349,15 +356,25 @@ class SearchApiImpl @Inject constructor(
        }
    }

    private suspend fun handleLimitedResult(appList: List<Application>?) {
        if (appList.isNullOrEmpty()) {
            // Call search api with a common keyword (ex: facebook)
            // to ensure Gplay is returning empty as search result for other keywords as well
            val searchResult = appSources.gplayRepo.getSearchResult(KEYWORD_TEST_SEARCH, null)
            if (searchResult.first.isEmpty()) {
                Timber.w("Limited result for search is found...")
    // Initiate a dummy search to ensure Google Play returns enough results for the search query
    private suspend fun doDummySearch() {
        val (searchedApps, _) = appSources.gplayRepo.getSearchResult(KEYWORD_TEST_SEARCH, null)

        if (searchedApps.isEmpty()) {
            Timber.d("Search returned empty results, refreshing token...")
            refreshToken()
            return
        }

        val dummySearchPackageNames = DUMMY_SEARCH_EXPECTED_APPS.map { it.second }
        val searchedAppsPackageNames = searchedApps.map { it.packageName }

        val isSearchContainingResults = searchedAppsPackageNames.containsAll(dummySearchPackageNames)

        if (!isSearchContainingResults) {
            Timber.d("Search didn't return enough results, refreshing token...")
            refreshToken()
            return
        }
    }

+6 −5
Original line number Diff line number Diff line
@@ -79,7 +79,7 @@ class PlayStoreRepositoryImpl @Inject constructor(
        query: String,
        subBundle: MutableSet<SearchBundle.SubBundle>?
    ): Pair<List<App>, MutableSet<SearchBundle.SubBundle>> {
        var authData = authenticatorRepository.gplayAuth!!
        val authData = authenticatorRepository.gplayAuth!!
        val searchHelper = SearchHelper(authData).using(gPlayHttpClient)

        Timber.d("Fetching search result for $query, subBundle: $subBundle")
@@ -87,18 +87,19 @@ class PlayStoreRepositoryImpl @Inject constructor(
        subBundle?.let {
            val searchResult = searchHelper.next(it)
            Timber.d("fetching next page search data...")
            return getSearchResultPair(searchResult)
            return getSearchResultPair(searchResult, query)
        }

        val searchResult = searchHelper.searchResults(query)
        return getSearchResultPair(searchResult)
        return getSearchResultPair(searchResult, query)
    }

    private fun getSearchResultPair(
        searchBundle: SearchBundle
        searchBundle: SearchBundle,
        query: String
    ): Pair<MutableList<App>, MutableSet<SearchBundle.SubBundle>> {
        val apps = searchBundle.appList
        Timber.d("Search result is found: ${apps.size}")
        Timber.d("Found ${apps.size} apps for query, $query")
        return Pair(apps, searchBundle.subBundles)
    }

+1 −1
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ class InterceptorModule {
    fun provideLoggingInterceptor(): HttpLoggingInterceptor {
        return HttpLoggingInterceptor().apply {
            level = when {
                BuildConfig.DEBUG -> HttpLoggingInterceptor.Level.BODY
                BuildConfig.DEBUG -> HttpLoggingInterceptor.Level.HEADERS
                else -> HttpLoggingInterceptor.Level.NONE
            }
        }