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

Commit 9d179274 authored by Hasib Prince's avatar Hasib Prince
Browse files

refactoring of GplayApiImpl

Settings page updated for multiple app source selection
parent 4bfdb1f8
Loading
Loading
Loading
Loading
+285 −181
Original line number Original line Diff line number Diff line
@@ -228,28 +228,148 @@ class FusedAPIImpl @Inject constructor(
         */
         */
        return liveData {
        return liveData {
            val packageSpecificResults = ArrayList<FusedApp>()
            val packageSpecificResults = ArrayList<FusedApp>()
            var gplayPackageResult: FusedApp? = null
            fetchPackageSpecificResult(authData, query, packageSpecificResults)?.let {
            var cleanapkPackageResult: FusedApp? = null
                emit(it)
                return@liveData
            }

            val searchResult = mutableListOf<FusedApp>()
            val cleanApkResults = mutableListOf<FusedApp>()

            if (preferenceManagerModule.isOpenSourceSelected()) {
                fetchOpenSourceSearchResult(
                    this@FusedAPIImpl,
                    cleanApkResults,
                    query,
                    searchResult,
                    packageSpecificResults
                )?.let { emit(it) }
            }


            val status = runCodeBlockWithTimeout({
            if (preferenceManagerModule.isGplaySelected()) {
            if (preferenceManagerModule.isGplaySelected()) {
                    try {
                emitSource(
                        getApplicationDetails(query, query, authData, Origin.GPLAY).let {
                    fetchGplaySearchResults(
                            if (it.second == ResultStatus.OK) {
                        query,
                                gplayPackageResult = it.first
                        authData,
                        searchResult,
                        packageSpecificResults
                    )
                )
            }
            }

            if (preferenceManagerModule.isPWASelected()) {
                fetchPWASearchResult(
                    this@FusedAPIImpl,
                    query,
                    searchResult,
                    packageSpecificResults
                )?.let { emit(it) }
            }
            }
                    } catch (e: Exception) {
                        Timber.e(e)
        }
        }
    }
    }


                if (preferenceManagerModule.isOpenSourceSelected()) {
    private suspend fun fetchPWASearchResult(
                    getCleanapkSearchResult(query).let {
        fusedAPIImpl: FusedAPIImpl,
                        if (it.isSuccess() && it.data!!.package_name.isNotBlank()) {
        query: String,
                            cleanapkPackageResult = it.data!!
        searchResult: MutableList<FusedApp>,
        packageSpecificResults: ArrayList<FusedApp>
    ): ResultSupreme<Pair<List<FusedApp>, Boolean>>? {
        val pwaApps: MutableList<FusedApp> = mutableListOf()
        val status = fusedAPIImpl.runCodeBlockWithTimeout({
            getCleanAPKSearchResults(
                query,
                CleanAPKInterface.APP_SOURCE_ANY,
                CleanAPKInterface.APP_TYPE_PWA
            ).apply {
                if (this.isNotEmpty()) {
                    pwaApps.addAll(this)
                }
            }
        })

        if (pwaApps.isNotEmpty() || status != ResultStatus.OK) {
            searchResult.addAll(pwaApps)
            return ResultSupreme.create(
                status,
                Pair(
                    filterWithKeywordSearch(
                        searchResult,
                        packageSpecificResults,
                        query
                    ),
                    false
                )
            )
        }
        return null
    }

    private fun fetchGplaySearchResults(
        query: String,
        authData: AuthData,
        searchResult: MutableList<FusedApp>,
        packageSpecificResults: ArrayList<FusedApp>
    ): LiveData<ResultSupreme<Pair<List<FusedApp>, Boolean>>> =
        getGplaySearchResults(query, authData).map {
            if (it.first.isNotEmpty()) {
                searchResult.addAll(it.first)
            }
            ResultSupreme.Success(
                Pair(
                    filterWithKeywordSearch(
                        searchResult,
                        packageSpecificResults,
                        query
                    ), it.second
                )
            )
        }
        }

    private suspend fun fetchOpenSourceSearchResult(
        fusedAPIImpl: FusedAPIImpl,
        cleanApkResults: MutableList<FusedApp>,
        query: String,
        searchResult: MutableList<FusedApp>,
        packageSpecificResults: ArrayList<FusedApp>
    ): ResultSupreme<Pair<List<FusedApp>, Boolean>>? {
        val status = fusedAPIImpl.runCodeBlockWithTimeout({
            cleanApkResults.addAll(getCleanAPKSearchResults(query))
        })

        if (cleanApkResults.isNotEmpty() || status != ResultStatus.OK) {
            searchResult.addAll(cleanApkResults)
            return ResultSupreme.create(
                status,
                Pair(
                    filterWithKeywordSearch(
                        searchResult,
                        packageSpecificResults,
                        query
                    ),
                    preferenceManagerModule.isGplaySelected() || preferenceManagerModule.isPWASelected()
                )
            )

        }
        return null
    }
    }

    private suspend fun fetchPackageSpecificResult(
        authData: AuthData,
        query: String,
        packageSpecificResults: MutableList<FusedApp>
    ): ResultSupreme<Pair<List<FusedApp>, Boolean>>? {
        var gplayPackageResult: FusedApp? = null
        var cleanapkPackageResult: FusedApp? = null


        val status = runCodeBlockWithTimeout({
            if (preferenceManagerModule.isGplaySelected()) {
                getGplayPackagResult(query, authData, gplayPackageResult)
            }

            if (preferenceManagerModule.isOpenSourceSelected()) {
                getCleanApkPackageResult(query, cleanapkPackageResult)
            }
            }
        })
        })


@@ -268,8 +388,9 @@ class FusedAPIImpl @Inject constructor(
         * Also send true in the pair to signal more results being loaded.
         * Also send true in the pair to signal more results being loaded.
         */
         */
        if (status != ResultStatus.OK) {
        if (status != ResultStatus.OK) {
                emit(ResultSupreme.create(status, Pair(packageSpecificResults, true)))
            return ResultSupreme.create(status, Pair(packageSpecificResults, true))
                return@liveData
        }
        return null
    }
    }


    /*
    /*
@@ -280,76 +401,42 @@ class FusedAPIImpl @Inject constructor(
             * But for the other keyword related search results, we do not allow duplicate package names.
             * But for the other keyword related search results, we do not allow duplicate package names.
             * We also filter out apps which are already present in packageSpecificResults list.
             * We also filter out apps which are already present in packageSpecificResults list.
             */
             */
            fun filterWithKeywordSearch(list: List<FusedApp>): List<FusedApp> {
    private fun filterWithKeywordSearch(
        list: List<FusedApp>,
        packageSpecificResults: List<FusedApp>,
        query: String
    ): List<FusedApp> {
        val filteredResults = list.distinctBy { it.package_name }
        val filteredResults = list.distinctBy { it.package_name }
            .filter { packageSpecificResults.isEmpty() || it.package_name != query }
            .filter { packageSpecificResults.isEmpty() || it.package_name != query }
        return packageSpecificResults + filteredResults
        return packageSpecificResults + filteredResults
    }
    }


            val searchResult = mutableListOf<FusedApp>()
    private suspend fun getCleanApkPackageResult(
            val cleanApkResults = mutableListOf<FusedApp>()
        query: String,

        cleanapkPackageResult: FusedApp?
            if (preferenceManagerModule.isOpenSourceSelected()) {
    ) {
                val status = runCodeBlockWithTimeout({
        var cleanapkPackageResultReference = cleanapkPackageResult
                    cleanApkResults.addAll(getCleanAPKSearchResults(query))
        getCleanapkSearchResult(query).let {
                })
            if (it.isSuccess() && it.data!!.package_name.isNotBlank()) {

                cleanapkPackageResultReference = it.data!!
                if (cleanApkResults.isNotEmpty() || status != ResultStatus.OK) {
                    /*
                     * If cleanapk results are empty, dont emit emit data as it may
                     * briefly show "No apps found..."
                     * If status is timeout, then do emit the value.
                     * Send true in the pair to signal more results (i.e from GPlay) being loaded.
                     */
                    searchResult.addAll(cleanApkResults)
                    emit(
                        ResultSupreme.create(
                            status,
                            Pair(
                                filterWithKeywordSearch(searchResult),
                                preferenceManagerModule.isGplaySelected() || preferenceManagerModule.isPWASelected()
                            )
                        )
                    )
                }
            }

            if (preferenceManagerModule.isGplaySelected()) {
                emitSource(getGplaySearchResults(query, authData).map {
                    if (it.first.isNotEmpty()) {
                        searchResult.addAll(it.first)
            }
            }
                    ResultSupreme.Success(Pair(filterWithKeywordSearch(searchResult), it.second))
                })
        }
        }

            if (preferenceManagerModule.isPWASelected()) {
                val pwaApps: MutableList<FusedApp> = mutableListOf()
                val status = runCodeBlockWithTimeout({
                    getCleanAPKSearchResults(
                        query,
                        CleanAPKInterface.APP_SOURCE_ANY,
                        CleanAPKInterface.APP_TYPE_PWA
                    ).apply {
                        if (this.isNotEmpty()) {
                            pwaApps.addAll(this)
    }
    }
                    }
                })


                if (pwaApps.isNotEmpty() || status != ResultStatus.OK) {
    private suspend fun getGplayPackagResult(
                    searchResult.addAll(pwaApps)
        query: String,
                    emit(
        authData: AuthData,
                        ResultSupreme.create(
        gplayPackageResult: FusedApp?
                            status,
    ) {
                            Pair(
        var gplayPackageResultReference = gplayPackageResult
                                filterWithKeywordSearch(searchResult),
        try {
                                false
            getApplicationDetails(query, query, authData, Origin.GPLAY).let {
                            )
                if (it.second == ResultStatus.OK) {
                        )
                    gplayPackageResultReference = it.first
                    )
                }
                }
            }
            }
        } catch (e: Exception) {
            Timber.e(e)
        }
        }
    }
    }


@@ -398,7 +485,13 @@ class FusedAPIImpl @Inject constructor(
        versionCode: Int,
        versionCode: Int,
        offerType: Int
        offerType: Int
    ): String? {
    ): String? {
        val list = gPlayAPIRepository.getOnDemandModule(packageName, moduleName, versionCode, offerType, authData)
        val list = gPlayAPIRepository.getOnDemandModule(
            packageName,
            moduleName,
            versionCode,
            offerType,
            authData
        )
        for (element in list) {
        for (element in list) {
            if (element.name == "$moduleName.apk") {
            if (element.name == "$moduleName.apk") {
                return element.url
                return element.url
@@ -821,43 +914,69 @@ class FusedAPIImpl @Inject constructor(
        type: Category.Type,
        type: Category.Type,
        authData: AuthData
        authData: AuthData
    ): Pair<ResultStatus, String> {
    ): Pair<ResultStatus, String> {
        var data: Categories? = null
        var apiStatus = ResultStatus.OK
        var apiStatus = ResultStatus.OK
        var errorApplicationCategory = ""
        var errorApplicationCategory = ""


        if (preferenceManagerModule.isOpenSourceSelected()) {
        if (preferenceManagerModule.isOpenSourceSelected()) {
            /*
            val openSourceCategoryResult = fetchOpenSourceCategories(type)
         * Try within timeout limit for open source native apps categories.
            categoriesList.addAll(openSourceCategoryResult.second)
         */
            apiStatus = openSourceCategoryResult.first
            runCodeBlockWithTimeout({
            errorApplicationCategory = openSourceCategoryResult.third
                data = getOpenSourceCategories()
        }
                data?.let {

                    categoriesList.addAll(
        if (preferenceManagerModule.isPWASelected()) {
                        getFusedCategoryBasedOnCategoryType(
            val pwaCategoriesResult = fetchPWACategories(type)
                            it,
            categoriesList.addAll(pwaCategoriesResult.second)
            apiStatus = pwaCategoriesResult.first
            errorApplicationCategory = pwaCategoriesResult.third
        }

        if (preferenceManagerModule.isGplaySelected()) {
            val gplayCategoryResult = fetchGplayCategories(
                type,
                type,
                            AppTag.OpenSource(context.getString(R.string.open_source))
                authData
                        )
            )
            )
            categoriesList.addAll(gplayCategoryResult.second)
            apiStatus = gplayCategoryResult.first
            errorApplicationCategory = gplayCategoryResult.third
        }
        }

        return Pair(apiStatus, errorApplicationCategory)
    }

    private suspend fun FusedAPIImpl.fetchGplayCategories(
        type: Category.Type,
        authData: AuthData,
    ): Triple<ResultStatus, List<FusedCategory>,String> {
        var errorApplicationCategory = ""
        var apiStatus = ResultStatus.OK
        val categoryList = mutableListOf<FusedCategory>()
        runCodeBlockWithTimeout({
            val playResponse = gPlayAPIRepository.getCategoriesList(type, authData).map { app ->
                val category = app.transformToFusedCategory()
                updateCategoryDrawable(category, app)
                category
            }
            categoryList.addAll(playResponse)
        }, {
        }, {
                errorApplicationCategory = APP_TYPE_OPEN
            errorApplicationCategory = APP_TYPE_ANY
            apiStatus = ResultStatus.TIMEOUT
            apiStatus = ResultStatus.TIMEOUT
        }, {
        }, {
                errorApplicationCategory = APP_TYPE_OPEN
            errorApplicationCategory = APP_TYPE_ANY
            apiStatus = ResultStatus.UNKNOWN
            apiStatus = ResultStatus.UNKNOWN
        })
        })
        return Triple(apiStatus, categoryList, errorApplicationCategory)
    }
    }


        if (preferenceManagerModule.isPWASelected()) {
    private suspend fun FusedAPIImpl.fetchPWACategories(

        type: Category.Type,
            /*
    ): Triple<ResultStatus, List<FusedCategory>, String> {
         * Try within timeout limit to get PWA categories
        var errorApplicationCategory = ""
         */
        var apiStatus: ResultStatus = ResultStatus.OK
        val fusedCategoriesList = mutableListOf<FusedCategory>()
        runCodeBlockWithTimeout({
        runCodeBlockWithTimeout({
                data = getPWAsCategories()
            getPWAsCategories()?.let {
                data?.let {
                fusedCategoriesList.addAll(
                    categoriesList.addAll(
                    getFusedCategoryBasedOnCategoryType(
                    getFusedCategoryBasedOnCategoryType(
                        it, type, AppTag.PWA(context.getString(R.string.pwa))
                        it, type, AppTag.PWA(context.getString(R.string.pwa))
                    )
                    )
@@ -870,30 +989,33 @@ class FusedAPIImpl @Inject constructor(
            errorApplicationCategory = APP_TYPE_PWA
            errorApplicationCategory = APP_TYPE_PWA
            apiStatus = ResultStatus.UNKNOWN
            apiStatus = ResultStatus.UNKNOWN
        })
        })
        return Triple(apiStatus, fusedCategoriesList, errorApplicationCategory)
    }
    }


        if (preferenceManagerModule.isGplaySelected()) {
    private suspend fun FusedAPIImpl.fetchOpenSourceCategories(

        type: Category.Type,
            /*
    ): Triple<ResultStatus, List<FusedCategory>, String> {
         * Try within timeout limit to get native app categories from Play Store
        var errorApplicationCategory = ""
         */
        var apiStatus: ResultStatus = ResultStatus.OK
        val fusedCategoryList = mutableListOf<FusedCategory>()
        runCodeBlockWithTimeout({
        runCodeBlockWithTimeout({
                val playResponse = gPlayAPIRepository.getCategoriesList(type, authData).map { app ->
            getOpenSourceCategories()?.let {
                    val category = app.transformToFusedCategory()
                fusedCategoryList.addAll(
                    updateCategoryDrawable(category, app)
                    getFusedCategoryBasedOnCategoryType(
                    category
                        it,
                        type,
                        AppTag.OpenSource(context.getString(R.string.open_source))
                    )
                )
            }
            }
                categoriesList.addAll(playResponse)
        }, {
        }, {
                errorApplicationCategory = APP_TYPE_ANY
            errorApplicationCategory = APP_TYPE_OPEN
            apiStatus = ResultStatus.TIMEOUT
            apiStatus = ResultStatus.TIMEOUT
        }, {
        }, {
                errorApplicationCategory = APP_TYPE_ANY
            errorApplicationCategory = APP_TYPE_OPEN
            apiStatus = ResultStatus.UNKNOWN
            apiStatus = ResultStatus.UNKNOWN
        })
        })
        }
        return Triple(apiStatus, fusedCategoryList, errorApplicationCategory)

        return Pair(apiStatus, errorApplicationCategory)
    }
    }


    /**
    /**
@@ -1074,24 +1196,6 @@ class FusedAPIImpl @Inject constructor(
        return list
        return list
    }
    }


    /*
     * Function to return a livedata with value from cleanapk and Google Play store combined.
     * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5171
     */
    private fun getGplayAndCleanapkCombinedResults(
        query: String,
        authData: AuthData,
        cleanApkResults: List<FusedApp>
    ): LiveData<Pair<List<FusedApp>, Boolean>> {
        val localList = ArrayList<FusedApp>(cleanApkResults)
        return getGplaySearchResults(query, authData).map { pair ->
            Pair(
                localList.apply { addAll(pair.first) }.distinctBy { it.package_name },
                pair.second
            )
        }
    }

    private fun getGplaySearchResults(
    private fun getGplaySearchResults(
        query: String,
        query: String,
        authData: AuthData
        authData: AuthData
+0 −21
Original line number Original line Diff line number Diff line
@@ -88,27 +88,6 @@ class SettingsFragment : PreferenceFragmentCompat() {
            true
            true
        }
        }


        showAllApplications?.setOnPreferenceChangeListener { _, _ ->
//            showFOSSApplications?.isChecked = false
//            showPWAApplications?.isChecked = false
            backToMainActivity()
            true
        }

        showFOSSApplications?.setOnPreferenceChangeListener { _, _ ->
//            showAllApplications?.isChecked = false
//            showPWAApplications?.isChecked = false
            backToMainActivity()
            true
        }

        showPWAApplications?.setOnPreferenceChangeListener { _, _ ->
//            showFOSSApplications?.isChecked = false
//            showAllApplications?.isChecked = false
            backToMainActivity()
            true
        }

        val versionInfo = findPreference<LongPressPreference>("versionInfo")
        val versionInfo = findPreference<LongPressPreference>("versionInfo")
        versionInfo?.apply {
        versionInfo?.apply {
            summary = BuildConfig.VERSION_NAME
            summary = BuildConfig.VERSION_NAME