From 0968446f0304834cdc32b00f525a9ffa98fe5608 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 21 Jun 2022 21:48:39 +0530 Subject: [PATCH 01/41] issue_5413_2 [WIP]: Create function getCategoriesListOSS() in FusedAPIImpl --- .../foundation/e/apps/api/fused/FusedAPIImpl.kt | 13 +++++++++++++ .../e/apps/api/fused/FusedAPIRepository.kt | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index 409dc93eb..72490d212 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -204,6 +204,19 @@ class FusedAPIImpl @Inject constructor( return Triple(categoriesList, applicationCategoryType, apiStatus) } + /** + * Fetch categories only from cleanapk. + * Useful when GPlay times out and we only need to load info from cleanapk. + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5413 [2] + */ + suspend fun getCategoriesListOSS(type: Category.Type): Triple, String, ResultStatus> { + val categoriesList = mutableListOf() + val preferredApplicationType = preferenceManagerModule.preferredApplicationType() + return handleCleanApkCategories(preferredApplicationType, categoriesList, type).run { + Triple(categoriesList, "open", this) + } + } + /** * Fetches search results from cleanAPK and GPlay servers and returns them * @param query Query diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt index 0cf5b73b7..1806a3f10 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt @@ -105,6 +105,10 @@ class FusedAPIRepository @Inject constructor( return fusedAPIImpl.getCategoriesList(type, authData) } + suspend fun getCategoriesListOSS(type: Category.Type): Triple, String, ResultStatus> { + return fusedAPIImpl.getCategoriesListOSS(type) + } + suspend fun getSearchSuggestions(query: String, authData: AuthData): List { return fusedAPIImpl.getSearchSuggestions(query, authData) } -- GitLab From 417be7c5608a8f1ec19ab443800b5213586057c6 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 21 Jun 2022 21:49:09 +0530 Subject: [PATCH 02/41] issue_5413_2 [WIP]: Implement getCategoriesListOSS() in view model --- .../foundation/e/apps/categories/CategoriesViewModel.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/categories/CategoriesViewModel.kt b/app/src/main/java/foundation/e/apps/categories/CategoriesViewModel.kt index ec72f9150..f918be5ab 100644 --- a/app/src/main/java/foundation/e/apps/categories/CategoriesViewModel.kt +++ b/app/src/main/java/foundation/e/apps/categories/CategoriesViewModel.kt @@ -44,6 +44,12 @@ class CategoriesViewModel @Inject constructor( } } + fun getCategoriesListOSS(type: Category.Type) { + viewModelScope.launch { + categoriesList.postValue(fusedAPIRepository.getCategoriesListOSS(type)) + } + } + fun isCategoriesEmpty(): Boolean { return categoriesList.value?.first?.isEmpty() ?: true } -- GitLab From e10d50937814f328fd371ca6c1f6ee0f36ea3395 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 21 Jun 2022 21:53:37 +0530 Subject: [PATCH 03/41] issue_5413_2 [WIP]: Provision for optional noAuthRefresh() function in TimeoutFragment.kt --- .../utils/parentFragment/TimeoutFragment.kt | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt index 959dc2efb..c67eaa050 100644 --- a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt +++ b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt @@ -70,11 +70,26 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { */ abstract fun refreshData(authData: AuthData) + /* + * Optional function to execute if above refreshData could not be executed because + * authData could not be obtained from network + * i.e mainActivityViewModel.authData.value is null. + * + * Uses: Used to show cleanapk data if GPlay is unavailable. + * + * If returns true, then we do not attempt to refresh the token. + * If returns false, then after running the function, we attempt to refresh GPlay token. + */ + open val noAuthRefresh: (() -> Boolean)? = null + /* * Checks if network connectivity is present. * -- If yes, then checks if valid authData is present. * ---- If yes, then dismiss timeout dialog (if showing) and call refreshData() - * ---- If no, then request new token data. + * ---- If no: + * ------ Run optional noAuthRefresh() function if not null. + * ------ If it returns false or is null, then refresh GPlay token. + * ------ Don't do anything if noRefreshAuth() returns true. */ fun refreshDataOrRefreshToken(mainActivityViewModel: MainActivityViewModel) { if (mainActivityViewModel.internetConnection.value == true) { @@ -82,7 +97,11 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { dismissTimeoutDialog() refreshData(authData) } ?: run { - if (mainActivityViewModel.authValidity.value != null) { // checking at least authvalidity is checked for once + if ( + noAuthRefresh?.invoke() != true && + mainActivityViewModel.authValidity.value != null + // checking at least authValidity is checked for once + ) { mainActivityViewModel.retryFetchingTokenAfterTimeout() } } -- GitLab From 3a9aebf98c652b93020ba2c9640d92bfdee1e98d Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Wed, 22 Jun 2022 08:59:46 +0530 Subject: [PATCH 04/41] issue_5413_2 [WIP]: Improve usage of noAuthRefresh() function in TimeoutFragment.kt --- .../utils/parentFragment/TimeoutFragment.kt | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt index c67eaa050..251c6d8a6 100644 --- a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt +++ b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt @@ -77,10 +77,12 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { * * Uses: Used to show cleanapk data if GPlay is unavailable. * - * If returns true, then we do not attempt to refresh the token. + * If returns true, it means that a fallback logic has been completely implemented, + * then we do not attempt to refresh the token. * If returns false, then after running the function, we attempt to refresh GPlay token. */ - open val noAuthRefresh: (() -> Boolean)? = null + open fun noAuthRefresh(): Boolean = false + private var isNoAuthRefreshExecuted = false /* * Checks if network connectivity is present. @@ -97,8 +99,18 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { dismissTimeoutDialog() refreshData(authData) } ?: run { - if ( - noAuthRefresh?.invoke() != true && + /* + * Run noAuthRefresh() only once. + * Once it has been run, set isNoAuthRefreshExecuted to true. + */ + val noAuthRefreshResult = if (isNoAuthRefreshExecuted) { + false + } else { + isNoAuthRefreshExecuted = true + noAuthRefresh() + } + + if (!noAuthRefreshResult && mainActivityViewModel.authValidity.value != null // checking at least authValidity is checked for once ) { -- GitLab From 975127d0a0b71c8b454124a0430de74cbaa55572 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Wed, 22 Jun 2022 11:58:19 +0530 Subject: [PATCH 05/41] issue_5413_2 [WIP]: getCategoriesListOSS() now shows both open source as well as PWAs --- .../e/apps/api/fused/FusedAPIImpl.kt | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index 72490d212..f80fe64af 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -211,10 +211,23 @@ class FusedAPIImpl @Inject constructor( */ suspend fun getCategoriesListOSS(type: Category.Type): Triple, String, ResultStatus> { val categoriesList = mutableListOf() - val preferredApplicationType = preferenceManagerModule.preferredApplicationType() - return handleCleanApkCategories(preferredApplicationType, categoriesList, type).run { - Triple(categoriesList, "open", this) - } + val status = runCodeBlockWithTimeout({ + getOpenSourceCategories()?.run { + categoriesList.addAll( + getFusedCategoryBasedOnCategoryType( + this, type, AppTag.OpenSource(context.getString(R.string.open_source)) + ) + ) + } + getPWAsCategories()?.run { + categoriesList.addAll( + getFusedCategoryBasedOnCategoryType( + this, type, AppTag.PWA(context.getString(R.string.pwa)) + ) + ) + } + }) + return Triple(categoriesList, "open", status) } /** -- GitLab From bfc696cf3de5e9ffb616490d15e72c420a5680d6 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Wed, 22 Jun 2022 12:47:12 +0530 Subject: [PATCH 06/41] issue_5413_2: AppsFragment - override noAuthRefresh() to call getCategoriesListOSS() --- .../main/java/foundation/e/apps/categories/AppsFragment.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt b/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt index 0335553b1..379c1008a 100644 --- a/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt +++ b/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt @@ -107,6 +107,12 @@ class AppsFragment : TimeoutFragment(R.layout.fragment_apps) { ) } + override fun noAuthRefresh(): Boolean { + showLoadingUI() + categoriesViewModel.getCategoriesListOSS(Category.Type.APPLICATION) + return false // returning false so as to try to get GPlay auth data or show timeout dialog + } + private fun showLoadingUI() { binding.shimmerLayout.startShimmer() binding.shimmerLayout.visibility = View.VISIBLE -- GitLab From 5fdc383f3ba8fe8c29245d09964ff611322d990f Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Wed, 22 Jun 2022 12:49:17 +0530 Subject: [PATCH 07/41] issue_5413_2: GamesFragment - override noAuthRefresh() to call getCategoriesListOSS() --- .../main/java/foundation/e/apps/categories/GamesFragment.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt b/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt index 109451974..bfa3dbeb0 100644 --- a/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt +++ b/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt @@ -102,6 +102,12 @@ class GamesFragment : TimeoutFragment(R.layout.fragment_games) { ) } + override fun noAuthRefresh(): Boolean { + showLoadingUI() + categoriesViewModel.getCategoriesListOSS(Category.Type.GAME) + return false // returning false so as to try to get GPlay auth data or show timeout dialog + } + private fun showLoadingUI() { binding.shimmerLayout.startShimmer() binding.shimmerLayout.visibility = View.VISIBLE -- GitLab From 32d43cca1d701fb2e6c42ea35149e39a7bc08559 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Wed, 22 Jun 2022 13:58:37 +0530 Subject: [PATCH 08/41] issue_5413_2: Minor fixes to package specific search results --- .../main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index f80fe64af..40f4cc32b 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -237,6 +237,7 @@ class FusedAPIImpl @Inject constructor( * @return A livedata Pair of list of non-nullable [FusedApp] and * a Boolean signifying if more search results are being loaded. * Observe this livedata to display new apps as they are fetched from the network. + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5413 [2] */ fun getSearchResults( query: String, @@ -277,11 +278,14 @@ class FusedAPIImpl @Inject constructor( /* * If there was a timeout, return it and don't try to fetch anything else. - * Also send true in the pair to signal more results being loaded. + * Also send false in the pair to signal no more results are being loaded. + * If not timeout then send true in the pair, to signal more results are being loaded. */ if (status != ResultStatus.OK) { - emit(ResultSupreme.create(status, Pair(packageSpecificResults, true))) + emit(ResultSupreme.create(status, Pair(packageSpecificResults, false))) return@liveData + } else if (packageSpecificResults.isNotEmpty()) { + emit(ResultSupreme.create(status, Pair(packageSpecificResults, true))) } /* -- GitLab From 02e846a5f3c54812654699a9d15d55be565585f5 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Wed, 22 Jun 2022 15:27:47 +0530 Subject: [PATCH 09/41] issue_5413_2 [WIP]: create getSearchResultsOSS() in FusedAPIImpl --- .../e/apps/api/fused/FusedAPIImpl.kt | 88 +++++++++++++++++++ .../e/apps/api/fused/FusedAPIRepository.kt | 4 + 2 files changed, 92 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index 40f4cc32b..37315caf2 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -368,6 +368,94 @@ class FusedAPIImpl @Inject constructor( } } + /** + * Similar to [getSearchResults] but this only gets search results from cleanapk and not GPlay. + * @param query Search query. + * @return A livedata Pair of list of non-nullable [FusedApp] and + * a Boolean signifying if more search results are being loaded. + * Observe this livedata to display new apps as they are fetched from the network. + */ + fun getSearchResultsOSS( + query: String + ): LiveData, Boolean>>> { + return liveData { + /* + * Get package name search. + */ + var packageSpecificResult = FusedApp() + val status = runCodeBlockWithTimeout({ + getCleanapkSearchResult(query).let { + /* Cleanapk always returns something, it is never null. + * If nothing is found, it returns a blank FusedApp() object. + * Blank result to be filtered out. + */ + if (it.isSuccess() && it.data!!.package_name.isNotBlank()) { + packageSpecificResult = it.data!! + } + } + }) + + + /* + * If there was a timeout, return it and don't try to fetch anything else. + * Also send false in the pair to signal no more results are being loaded. + * If not timeout then send true in the pair, to signal more results are being loaded. + */ + if (status != ResultStatus.OK) { + emit(ResultSupreme.create(status, Pair(listOf(), false))) + return@liveData + } else if (packageSpecificResult.package_name.isNotBlank()) { + emit(ResultSupreme.create(status, Pair(listOf(packageSpecificResult), true))) + } + + /* + * Load keyword related searches from cleanapk. + */ + val cleanApkResults = mutableListOf() + when (preferenceManagerModule.preferredApplicationType()) { + APP_TYPE_OPEN -> { + val status = runCodeBlockWithTimeout({ + cleanApkResults.addAll(getCleanAPKSearchResults(query)) + }) + /* + * Send false in pair to signal no more results to load, as only cleanapk + * results are fetched, we don't have to wait for GPlay results. + * + * Also filter out apps with same package name as that of packageSpecificResult, + * to avoid duplicates. + */ + emit( + ResultSupreme.create( + status, + Pair( + cleanApkResults.filter { + it.package_name != packageSpecificResult.package_name + }, + false + ) + ) + ) + } + APP_TYPE_PWA -> { + val status = runCodeBlockWithTimeout({ + cleanApkResults.addAll( + getCleanAPKSearchResults( + query, + CleanAPKInterface.APP_SOURCE_ANY, + CleanAPKInterface.APP_TYPE_PWA + ) + ) + }) + /* + * Send false in pair to signal no more results to load, as only cleanapk + * results are fetched for PWAs. + */ + emit(ResultSupreme.create(status, Pair(cleanApkResults, false))) + } + } + } + } + /* * Method to search cleanapk based on package name. * This is to be only used for showing an entry in search results list. diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt index 1806a3f10..0e883531c 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt @@ -125,6 +125,10 @@ class FusedAPIRepository @Inject constructor( return fusedAPIImpl.getSearchResults(query, authData) } + fun getSearchResultsOSS(query: String): LiveData, Boolean>>> { + return fusedAPIImpl.getSearchResultsOSS(query) + } + suspend fun getNextStreamBundle( authData: AuthData, homeUrl: String, -- GitLab From fb48a70e5d75f754a1582abab3157d5c4c96eaa2 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Wed, 22 Jun 2022 15:32:11 +0530 Subject: [PATCH 10/41] issue_5413_2 [WIP]: Implement getCategoriesListOSS() in view model --- .../java/foundation/e/apps/search/SearchViewModel.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/search/SearchViewModel.kt b/app/src/main/java/foundation/e/apps/search/SearchViewModel.kt index 3ae636d47..31966183b 100644 --- a/app/src/main/java/foundation/e/apps/search/SearchViewModel.kt +++ b/app/src/main/java/foundation/e/apps/search/SearchViewModel.kt @@ -59,4 +59,16 @@ class SearchViewModel @Inject constructor( } } } + + /* + * Get cleanapk search results only. + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5413 [2] + */ + fun getSearchResultsOSS(query: String, lifecycleOwner: LifecycleOwner) { + viewModelScope.launch(Dispatchers.Main) { + fusedAPIRepository.getSearchResultsOSS(query).observe(lifecycleOwner) { + searchResult.postValue(it) + } + } + } } -- GitLab From 12a11b4b33d1fca9a61648d5ea2a67a649b9888a Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Wed, 22 Jun 2022 15:34:54 +0530 Subject: [PATCH 11/41] issue_5413_2: use viewLifecycleOwner instead of this in SearchFragment --- app/src/main/java/foundation/e/apps/search/SearchFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt index 9089b59d4..f83c9482a 100644 --- a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt +++ b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt @@ -250,7 +250,7 @@ class SearchFragment : override fun refreshData(authData: AuthData) { showLoadingUI() - searchViewModel.getSearchResults(searchText, authData, this) + searchViewModel.getSearchResults(searchText, authData, viewLifecycleOwner) } private fun showLoadingUI() { -- GitLab From 89806eacd83943237294f92dd41c6a4cbc174850 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Wed, 22 Jun 2022 15:45:59 +0530 Subject: [PATCH 12/41] issue_5413_2 [WIP]: SearchFragment - override noAuthRefresh() to call getSearchResultsOSS() --- .../main/java/foundation/e/apps/search/SearchFragment.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt index f83c9482a..76410207b 100644 --- a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt +++ b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt @@ -253,6 +253,12 @@ class SearchFragment : searchViewModel.getSearchResults(searchText, authData, viewLifecycleOwner) } + override fun noAuthRefresh(): Boolean { + showLoadingUI() + searchViewModel.getSearchResultsOSS(searchText, viewLifecycleOwner) + return false // return false to allow retrying to fetch auth data, else show timeout. + } + private fun showLoadingUI() { binding.shimmerLayout.startShimmer() binding.shimmerLayout.visibility = View.VISIBLE -- GitLab From 5afd3a990c53a7b9762ea4487ead232c8423157c Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Wed, 22 Jun 2022 22:05:33 +0530 Subject: [PATCH 13/41] issue_5413_2 [WIP]: Rename retryFetchingTokenAfterTimeout() to checkTokenOnTimeout() which checks token validity and does not outright request for regeneration. --- .../e/apps/MainActivityViewModel.kt | 23 +++++++++++++++---- .../e/apps/application/ApplicationFragment.kt | 2 +- .../ApplicationListFragment.kt | 2 +- .../e/apps/categories/AppsFragment.kt | 2 +- .../e/apps/categories/GamesFragment.kt | 2 +- .../foundation/e/apps/home/HomeFragment.kt | 2 +- .../e/apps/search/SearchFragment.kt | 2 +- .../e/apps/updates/UpdatesFragment.kt | 2 +- .../utils/parentFragment/TimeoutFragment.kt | 2 +- 9 files changed, 26 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index b66a7d49d..64ce46f86 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -121,17 +121,30 @@ class MainActivityViewModel @Inject constructor( return (SystemClock.uptimeMillis() - firstAuthDataFetchTime) <= timeoutDurationInMillis } - /* + /** * This method resets the last recorded token fetch time. - * Then it posts authValidity as false. This causes the observer in MainActivity to destroyCredentials - * and fetch new token. + * + * Then if [authData] is not null, it checks the validity of it, + * which automatically updates [authValidity]. + * If [authValidity] is true, the observer in MainActivity calls [generateAuthData], + * which passes the same [authData] to the current displaying fragment once more, + * to trigger data refresh. + * + * If [authData] is null, it posts false in [authValidity], which + * causes the observer in MainActivity to destroyCredentials and fetch new token. + * This again causes the current displaying fragment to re-trigger data refresh. * * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5404 + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5413 [2] */ - fun retryFetchingTokenAfterTimeout() { + fun checkTokenOnTimeout() { firstAuthDataFetchTime = 0 setFirstTokenFetchTime() - authValidity.postValue(false) + if (authData.value != null) { + validateAuthData() + } else { + authValidity.postValue(false) + } } fun uploadFaultyTokenToEcloud(description: String) { diff --git a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt index aa826417a..18c9dc898 100644 --- a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt +++ b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt @@ -324,7 +324,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { positiveButtonBlock = { showLoadingUI() resetTimeoutDialogLock() - mainActivityViewModel.retryFetchingTokenAfterTimeout() + mainActivityViewModel.checkTokenOnTimeout() }, negativeButtonText = getString(android.R.string.ok), negativeButtonBlock = { diff --git a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt index 8b99c8866..6c7442159 100644 --- a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt +++ b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt @@ -192,7 +192,7 @@ class ApplicationListFragment : TimeoutFragment(R.layout.fragment_application_li positiveButtonBlock = { showLoadingUI() resetTimeoutDialogLock() - mainActivityViewModel.retryFetchingTokenAfterTimeout() + mainActivityViewModel.checkTokenOnTimeout() }, negativeButtonText = getString(android.R.string.ok), negativeButtonBlock = {}, diff --git a/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt b/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt index 379c1008a..d180f0eda 100644 --- a/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt +++ b/app/src/main/java/foundation/e/apps/categories/AppsFragment.kt @@ -92,7 +92,7 @@ class AppsFragment : TimeoutFragment(R.layout.fragment_apps) { negativeButtonBlock = { showLoadingUI() resetTimeoutDialogLock() - mainActivityViewModel.retryFetchingTokenAfterTimeout() + mainActivityViewModel.checkTokenOnTimeout() }, allowCancel = true, ) diff --git a/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt b/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt index bfa3dbeb0..7f813a5f8 100644 --- a/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt +++ b/app/src/main/java/foundation/e/apps/categories/GamesFragment.kt @@ -87,7 +87,7 @@ class GamesFragment : TimeoutFragment(R.layout.fragment_games) { negativeButtonBlock = { showLoadingUI() resetTimeoutDialogLock() - mainActivityViewModel.retryFetchingTokenAfterTimeout() + mainActivityViewModel.checkTokenOnTimeout() }, allowCancel = true, ) diff --git a/app/src/main/java/foundation/e/apps/home/HomeFragment.kt b/app/src/main/java/foundation/e/apps/home/HomeFragment.kt index e3af670ba..d41582a66 100644 --- a/app/src/main/java/foundation/e/apps/home/HomeFragment.kt +++ b/app/src/main/java/foundation/e/apps/home/HomeFragment.kt @@ -183,7 +183,7 @@ class HomeFragment : TimeoutFragment(R.layout.fragment_home), FusedAPIInterface positiveButtonBlock = { showLoadingUI() resetTimeoutDialogLock() - mainActivityViewModel.retryFetchingTokenAfterTimeout() + mainActivityViewModel.checkTokenOnTimeout() }, negativeButtonText = if (homeViewModel.getApplicationCategoryPreference() == FusedAPIImpl.APP_TYPE_ANY) { diff --git a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt index 76410207b..4e8868ad8 100644 --- a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt +++ b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt @@ -239,7 +239,7 @@ class SearchFragment : positiveButtonBlock = { showLoadingUI() resetTimeoutDialogLock() - mainActivityViewModel.retryFetchingTokenAfterTimeout() + mainActivityViewModel.checkTokenOnTimeout() }, negativeButtonText = getString(android.R.string.ok), negativeButtonBlock = {}, diff --git a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt index 68016394a..c0b398a31 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt @@ -173,7 +173,7 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte positiveButtonBlock = { showLoadingUI() resetTimeoutDialogLock() - mainActivityViewModel.retryFetchingTokenAfterTimeout() + mainActivityViewModel.checkTokenOnTimeout() }, negativeButtonText = if (updatesViewModel.getApplicationCategoryPreference() == FusedAPIImpl.APP_TYPE_ANY) { diff --git a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt index 251c6d8a6..731aed51f 100644 --- a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt +++ b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt @@ -114,7 +114,7 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { mainActivityViewModel.authValidity.value != null // checking at least authValidity is checked for once ) { - mainActivityViewModel.retryFetchingTokenAfterTimeout() + mainActivityViewModel.checkTokenOnTimeout() } } } -- GitLab From 9ce5d0783d8c0baf6f76c0f2efb783f1d2564172 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Thu, 23 Jun 2022 18:49:03 +0530 Subject: [PATCH 14/41] issue_5413_2: Create getApplicationDetailsOSS in FusedAPIImpl --- .../e/apps/api/fused/FusedAPIImpl.kt | 22 +++++++++++++++++++ .../e/apps/api/fused/FusedAPIRepository.kt | 6 +++++ 2 files changed, 28 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index 37315caf2..93daf51f4 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -616,6 +616,28 @@ class FusedAPIImpl @Inject constructor( return Pair(fusedApp, status) } + /* + * Get updates only from cleanapk. + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5413 [2] + */ + suspend fun getApplicationDetailsOSS( + packageNameList: List, + ): Pair, ResultStatus> { + val list = mutableListOf() + + val response: Pair, ResultStatus> = + getAppDetailsListFromCleanapk(packageNameList) + response.first.forEach { + if (it.package_name.isNotBlank()) { + it.updateStatus() + it.updateType() + list.add(it) + } + } + + return Pair(list, response.second) + } + suspend fun getApplicationDetails( packageNameList: List, authData: AuthData, diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt index 0e883531c..b9d157a40 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt @@ -66,6 +66,12 @@ class FusedAPIRepository @Inject constructor( return fusedAPIImpl.getApplicationDetails(packageNameList, authData, origin) } + suspend fun getApplicationDetailsOSS( + packageNameList: List, + ): Pair, ResultStatus> { + return fusedAPIImpl.getApplicationDetailsOSS(packageNameList) + } + suspend fun filterRestrictedGPlayApps( authData: AuthData, appList: List, -- GitLab From 9de5fed94abe22272ed44e3ed7ff4a592d977e0a Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Thu, 23 Jun 2022 18:50:14 +0530 Subject: [PATCH 15/41] issue_5413_2: Create getUpdatesOSS for updates --- .../updates/manager/UpdatesManagerImpl.kt | 20 +++++++++++++++++++ .../manager/UpdatesManagerRepository.kt | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt index 03e485126..1d2ada7ba 100644 --- a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt +++ b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt @@ -77,6 +77,26 @@ class UpdatesManagerImpl @Inject constructor( return Pair(updateList, status) } + /* + * Get updates only from cleanapk. + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5413 [2] + */ + suspend fun getUpdatesOSS(): Pair, ResultStatus> { + val updateList = mutableListOf() + val pkgList = pkgManagerModule.getAllUserApps().map { it.packageName } + + return if (pkgList.isNotEmpty()) { + fusedAPIRepository.getApplicationDetailsOSS(pkgList).run { + this.first.forEach { + if (it.status == Status.UPDATABLE) updateList.add(it) + } + Pair(updateList, this.second) + } + } else { + Pair(listOf(), ResultStatus.OK) + } + } + fun getApplicationCategoryPreference(): String { return fusedAPIRepository.getApplicationCategoryPreference() } diff --git a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerRepository.kt b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerRepository.kt index 649c82261..4e0f46fcc 100644 --- a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerRepository.kt +++ b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerRepository.kt @@ -31,6 +31,10 @@ class UpdatesManagerRepository @Inject constructor( return updatesManagerImpl.getUpdates(authData) } + suspend fun getUpdatesOSS(): Pair, ResultStatus> { + return updatesManagerImpl.getUpdatesOSS() + } + fun getApplicationCategoryPreference(): String { return updatesManagerImpl.getApplicationCategoryPreference() } -- GitLab From d709b46be3a722555908aa9c2997702f99d15d81 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Thu, 23 Jun 2022 18:52:02 +0530 Subject: [PATCH 16/41] issue_5413_2: Implement getUpdatesOSS in UpdatesViewModel --- .../java/foundation/e/apps/updates/UpdatesViewModel.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt b/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt index f630fda7a..6e370e77b 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt @@ -52,6 +52,16 @@ class UpdatesViewModel @Inject constructor( } } + /* + * Get updates only from cleanapk + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5413 [2] + */ + fun getUpdatesOSS() { + viewModelScope.launch { + updatesList.postValue(updatesManagerRepository.getUpdatesOSS()) + } + } + suspend fun checkWorkInfoListHasAnyUpdatableWork(workInfoList: List): Boolean { workInfoList.forEach { workInfo -> if (listOf( -- GitLab From 9520677c4a00be83e70936eb0cde3c371f6c3a3e Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Thu, 23 Jun 2022 18:53:10 +0530 Subject: [PATCH 17/41] issue_5413_2: UpdatesFragment - override noAuthRefresh() to call getUpdatesOSS() --- .../java/foundation/e/apps/updates/UpdatesFragment.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt index c0b398a31..5e00aeff3 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt @@ -196,6 +196,16 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte } } + override fun noAuthRefresh(): Boolean { + showLoadingUI() + updatesViewModel.getUpdatesOSS() + binding.button.setOnClickListener { + UpdatesWorkManager.startUpdateAllWork(requireContext().applicationContext) + binding.button.isEnabled = false + } + return false + } + private fun showLoadingUI() { binding.button.isEnabled = false binding.noUpdates.visibility = View.GONE -- GitLab From d88997870cbdfa5addb9cb18dc88c84286786c73 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Thu, 23 Jun 2022 21:06:03 +0530 Subject: [PATCH 18/41] issue_5413_2: set update data if ResultStatus is OK, else show timeout dialog and don't do anything else. --- .../e/apps/updates/UpdatesFragment.kt | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt index 5e00aeff3..cf102de30 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt @@ -129,31 +129,32 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte } updatesViewModel.updatesList.observe(viewLifecycleOwner) { - listAdapter?.setData(it.first) - if (!isDownloadObserverAdded) { - observeDownloadList() - isDownloadObserverAdded = true - } - stopLoadingUI() - if (!it.first.isNullOrEmpty()) { - binding.button.isEnabled = true - binding.noUpdates.visibility = View.GONE + if (it.second != ResultStatus.OK) { + onTimeout() + return@observe } else { - binding.noUpdates.visibility = View.VISIBLE - binding.button.isEnabled = false - } - - WorkManager.getInstance(requireContext()) - .getWorkInfosForUniqueWorkLiveData(INSTALL_WORK_NAME).observe(viewLifecycleOwner) { - lifecycleScope.launchWhenResumed { - binding.button.isEnabled = - !updatesViewModel.checkWorkInfoListHasAnyUpdatableWork(it) - } + listAdapter?.setData(it.first) + if (!isDownloadObserverAdded) { + observeDownloadList() + isDownloadObserverAdded = true + } + if (it.first.isNotEmpty()) { + binding.button.isEnabled = true + binding.noUpdates.visibility = View.GONE + } else { + binding.noUpdates.visibility = View.VISIBLE + binding.button.isEnabled = false } - if (it.second != ResultStatus.OK) { - onTimeout() + WorkManager.getInstance(requireContext()) + .getWorkInfosForUniqueWorkLiveData(INSTALL_WORK_NAME).observe(viewLifecycleOwner) { + lifecycleScope.launchWhenResumed { + binding.button.isEnabled = + !updatesViewModel.checkWorkInfoListHasAnyUpdatableWork(it) + } + } } + stopLoadingUI() } } -- GitLab From e0c4ff3e85c4905df68ac7c800a613b587611efb Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Sat, 25 Jun 2022 03:11:06 +0530 Subject: [PATCH 19/41] issue_5413_2: TimeoutFragment - refreshData() if authData is not null as well as authValidity is true --- .../e/apps/utils/parentFragment/TimeoutFragment.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt index 731aed51f..b56ea7ca9 100644 --- a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt +++ b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt @@ -95,10 +95,11 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { */ fun refreshDataOrRefreshToken(mainActivityViewModel: MainActivityViewModel) { if (mainActivityViewModel.internetConnection.value == true) { - mainActivityViewModel.authData.value?.let { authData -> + val authData: AuthData? = mainActivityViewModel.authData.value + if (authData != null && mainActivityViewModel.authValidity.value == true) { dismissTimeoutDialog() refreshData(authData) - } ?: run { + } else { /* * Run noAuthRefresh() only once. * Once it has been run, set isNoAuthRefreshExecuted to true. -- GitLab From 2a3ec884f64b7a55a6c40d185ab0e408e0202a19 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Sat, 25 Jun 2022 03:14:20 +0530 Subject: [PATCH 20/41] issue_5413_2: allow getSearchResultsOSS to run even if app preference is APP_TYPE_ANY --- app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index be9c87496..0d75eb7ea 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -413,7 +413,7 @@ class FusedAPIImpl @Inject constructor( */ val cleanApkResults = mutableListOf() when (preferenceManagerModule.preferredApplicationType()) { - APP_TYPE_OPEN -> { + APP_TYPE_OPEN, APP_TYPE_ANY -> { val status = runCodeBlockWithTimeout({ cleanApkResults.addAll(getCleanAPKSearchResults(query)) }) -- GitLab From a82ec1b887a036bbaeb8215e695f5a4cb6f6d9ac Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Sat, 25 Jun 2022 03:59:47 +0530 Subject: [PATCH 21/41] issue_5413_2: TimeoutFragment - remove isNoAuthRefreshExecuted flag --- .../e/apps/utils/parentFragment/TimeoutFragment.kt | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt index b56ea7ca9..f3245ef48 100644 --- a/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt +++ b/app/src/main/java/foundation/e/apps/utils/parentFragment/TimeoutFragment.kt @@ -82,7 +82,6 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { * If returns false, then after running the function, we attempt to refresh GPlay token. */ open fun noAuthRefresh(): Boolean = false - private var isNoAuthRefreshExecuted = false /* * Checks if network connectivity is present. @@ -100,16 +99,7 @@ abstract class TimeoutFragment(@LayoutRes layoutId: Int) : Fragment(layoutId) { dismissTimeoutDialog() refreshData(authData) } else { - /* - * Run noAuthRefresh() only once. - * Once it has been run, set isNoAuthRefreshExecuted to true. - */ - val noAuthRefreshResult = if (isNoAuthRefreshExecuted) { - false - } else { - isNoAuthRefreshExecuted = true - noAuthRefresh() - } + val noAuthRefreshResult = noAuthRefresh() if (!noAuthRefreshResult && mainActivityViewModel.authValidity.value != null -- GitLab From 25dd2c78404c3945d55dd07fe371139f7d515de8 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Sat, 25 Jun 2022 04:14:22 +0530 Subject: [PATCH 22/41] issue_5413_2: SearchFragment - check if searchText is not blank before showing timeout dialog --- .../java/foundation/e/apps/search/SearchFragment.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt index 4e8868ad8..d43c820d5 100644 --- a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt +++ b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt @@ -217,18 +217,18 @@ class SearchFragment : } } }) - if (searchText.isNotBlank() && !it.isSuccess()) { - /* - * If blank check is not performed then timeout dialog keeps - * popping up whenever search tab is opened. - */ + if (!it.isSuccess()) { onTimeout() } } } override fun onTimeout() { - if (!isTimeoutDialogDisplayed()) { + if (searchText.isNotBlank() && !isTimeoutDialogDisplayed()) { + /* + * If blank check is not performed then timeout dialog keeps + * popping up whenever search tab is opened. + */ binding.loadingProgressBar.isVisible = false stopLoadingUI() displayTimeoutAlertDialog( -- GitLab From c161ecece3fa60bab3c37fe61289f0e0d5e297f0 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Sat, 25 Jun 2022 04:46:11 +0530 Subject: [PATCH 23/41] issue_5413_2: create getAppsListOSS() in FusedAPIRepository --- .../e/apps/api/fused/FusedAPIRepository.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt index b9d157a40..457cb7513 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt @@ -171,6 +171,21 @@ class FusedAPIRepository @Inject constructor( } } + /* + * Get only category apps from cleanapk. + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5413 [2] + */ + suspend fun getAppsListOSS( + category: String, + source: String, + ): ResultSupreme> { + return when (source) { + "Open Source" -> fusedAPIImpl.getOpenSourceApps(category) + "PWA" -> fusedAPIImpl.getPWAApps(category) + else -> ResultSupreme.Error() + } + } + fun getFusedAppInstallationStatus(fusedApp: FusedApp): Status { return fusedAPIImpl.getFusedAppInstallationStatus(fusedApp) } -- GitLab From c4deb6433c492d6618deff272eb9d659483236dd Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Sat, 25 Jun 2022 04:46:53 +0530 Subject: [PATCH 24/41] issue_5413_2: create getListOSS() in ApplicationListViewModel --- .../applicationlist/ApplicationListViewModel.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListViewModel.kt b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListViewModel.kt index 0d689ef75..9aad62600 100644 --- a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListViewModel.kt +++ b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListViewModel.kt @@ -97,6 +97,21 @@ class ApplicationListViewModel @Inject constructor( } } + /* + * Get apps list from cleanapk only. + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5413 [2] + */ + fun getListOSS(category: String, source: String) { + viewModelScope.launch(Dispatchers.IO) { + appListLiveData.postValue( + fusedAPIRepository.getAppsListOSS( + category, + source, + ) + ) + } + } + /** * Add a placeholder app at the end if more data can be loaded. * "Placeholder" app shows a simple progress bar in the RecyclerView, indicating that -- GitLab From 3185072e7788cb855fddd92268ac17acaebabfcd Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Sun, 26 Jun 2022 03:39:44 +0530 Subject: [PATCH 25/41] issue_5413_2: ApplicationListFragment - override noAuthRefresh() to call getListOSS() --- .../ApplicationListFragment.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt index 6c7442159..0e245df4c 100644 --- a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt +++ b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt @@ -261,6 +261,43 @@ class ApplicationListFragment : TimeoutFragment(R.layout.fragment_application_li } } + /* + * Load open source apps in case authentication fails. + * Issue: https://gitlab.e.foundation/e/os/backlog/-/issues/5413 [2] + */ + override fun noAuthRefresh(): Boolean { + + if (args.source != "Open Source" && args.source != "PWA") { + /* + * Prevent running this method for GPlay categories. + * For first time run of App Lounge, authData and authValidity will be both null, + * so this method will be executed. + * If the body of the method is allowed to run for GPlay categories, + * 1. we will fetch cleanapk data, + * 2. that data will be shown and isDetailsLoaded will be set to true, + * 3. Then when refreshData() will be called it will not run as isDetailsLoaded is true. + * + * On the other hand, if GPlay really cannot be reached, then categorie list + * will only show open source or PWAs categories. Then this method body can run fine. + */ + return false + } + + if (!isDetailsLoaded) { + showLoadingUI() + viewModel.getListOSS( + args.category, + args.source + ) + } + + appProgressViewModel.downloadProgress.observe(viewLifecycleOwner) { + updateProgressOfDownloadingItems(binding.recyclerView, it) + } + + return false + } + private fun showLoadingUI() { binding.shimmerLayout.startShimmer() binding.shimmerLayout.visibility = View.VISIBLE -- GitLab From 5bec4e891905c0295bf56603aa5c26bc612eb3ec Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Sun, 26 Jun 2022 03:53:11 +0530 Subject: [PATCH 26/41] issue_5413_2: ApplicationListFragment - return true from noAuthRefresh() --- .../e/apps/applicationlist/ApplicationListFragment.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt index 0e245df4c..2db475754 100644 --- a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt +++ b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt @@ -295,7 +295,13 @@ class ApplicationListFragment : TimeoutFragment(R.layout.fragment_application_li updateProgressOfDownloadingItems(binding.recyclerView, it) } - return false + /* + * This method is guaranteed to run only for open source apps. If there is timeout + * from cleanapk, it will be handled by this fragment itself in onTimeout(). + * In normal case, we can assume that the apps details will be fetched from cleanapk, + * hence we don't need to try fetching from GPlay (it is open source category any way.) + */ + return true } private fun showLoadingUI() { -- GitLab From 84aa4454a5577cdb16a3907d9085e0c53a0867ec Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Sun, 26 Jun 2022 04:01:15 +0530 Subject: [PATCH 27/41] issue_5413_2: create getApplicationDetailsOSS(id) in FusedAPIImpl. --- .../foundation/e/apps/api/fused/FusedAPIImpl.kt | 17 +++++++++++++++++ .../e/apps/api/fused/FusedAPIRepository.kt | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index 0d75eb7ea..d31d58957 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -796,6 +796,23 @@ class FusedAPIImpl @Inject constructor( return Pair(response ?: FusedApp(), status) } + suspend fun getApplicationDetailsOSS( + id: String, + ): Pair { + + var response: FusedApp? = null + + val status = runCodeBlockWithTimeout({ + response = cleanAPKRepository.getAppOrPWADetailsByID(id).body()?.app + response?.let { + it.updateStatus() + it.updateType() + } + }) + + return Pair(response ?: FusedApp(), status) + } + /* * Categories-related internal functions */ diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt index 457cb7513..41ea22175 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt @@ -88,6 +88,12 @@ class FusedAPIRepository @Inject constructor( return fusedAPIImpl.getApplicationDetails(id, packageName, authData, origin) } + suspend fun getApplicationDetailsOSS( + id: String, + ): Pair { + return fusedAPIImpl.getApplicationDetailsOSS(id) + } + suspend fun getCleanapkAppDetails(packageName: String): Pair { return fusedAPIImpl.getCleanapkAppDetails(packageName) } -- GitLab From e3cdb6b2c0bb725590c4028aa203ef05eac1425d Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Sun, 26 Jun 2022 04:02:18 +0530 Subject: [PATCH 28/41] issue_5413_2: create getApplicationDetailsOSS() in ApplicationViewModel --- .../e/apps/application/ApplicationViewModel.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/application/ApplicationViewModel.kt b/app/src/main/java/foundation/e/apps/application/ApplicationViewModel.kt index dc094e5ff..8ee451aa8 100644 --- a/app/src/main/java/foundation/e/apps/application/ApplicationViewModel.kt +++ b/app/src/main/java/foundation/e/apps/application/ApplicationViewModel.kt @@ -72,6 +72,20 @@ class ApplicationViewModel @Inject constructor( } } + fun getApplicationDetailsOSS(id: String) { + viewModelScope.launch(Dispatchers.IO) { + try { + fusedApp.postValue( + fusedAPIRepository.getApplicationDetailsOSS(id) + ) + } catch (e: ApiException.AppNotFound) { + _errorMessageLiveData.postValue(R.string.app_not_found) + } catch (e: Exception) { + _errorMessageLiveData.postValue(R.string.unknown_error) + } + } + } + /* * Dedicated method to get app details from cleanapk using package name. * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5509 -- GitLab From f101ccd94228e77cc89b35b5150a1369296f8d17 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Sun, 26 Jun 2022 04:03:17 +0530 Subject: [PATCH 29/41] issue_5413_2: ApplicationFragment - override noAuthRefresh() to call getApplicationDetailsOSS() --- .../e/apps/application/ApplicationFragment.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt index 2d60027e6..066665b4b 100644 --- a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt +++ b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt @@ -353,6 +353,26 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { } } + override fun noAuthRefresh(): Boolean { + if (!isDetailsLoaded) { + /* Show the loading bar. */ + showLoadingUI() + /* Remove trailing slash (if present) that can become part of the packageName */ + val packageName = args.packageName.run { if (endsWith('/')) dropLast(1) else this } + if (isFdroidDeepLink) { + applicationViewModel.getCleanapkAppDetails(packageName) + } else if (args.origin == Origin.CLEANAPK) { + applicationViewModel.getApplicationDetailsOSS( + args.id, + ) + return true + } else { + return false + } + } + return true + } + private fun observeDownloadStatus(view: View) { applicationViewModel.appStatus.observe(viewLifecycleOwner) { status -> val installButton = binding.downloadInclude.installButton -- GitLab From 78367356ef76de3ae1dde3ed26147a59d878aa39 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 5 Jul 2022 16:14:37 +0530 Subject: [PATCH 30/41] issue_5413: Fused API - use ResultSupreme for getApplicationDetailsOSS() --- .../main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt | 8 ++++++-- .../foundation/e/apps/api/fused/FusedAPIRepository.kt | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index d31d58957..81eadeab8 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -622,7 +622,7 @@ class FusedAPIImpl @Inject constructor( */ suspend fun getApplicationDetailsOSS( packageNameList: List, - ): Pair, ResultStatus> { + ): ResultSupreme> { val list = mutableListOf() val response: Pair, ResultStatus> = @@ -635,7 +635,11 @@ class FusedAPIImpl @Inject constructor( } } - return Pair(list, response.second) + return ResultSupreme.create(response.second, list.toList()).apply { + if (!isSuccess()) { + message = true.toString() + } + } } suspend fun getApplicationDetails( diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt index 41ea22175..6a8bfc053 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt @@ -68,7 +68,7 @@ class FusedAPIRepository @Inject constructor( suspend fun getApplicationDetailsOSS( packageNameList: List, - ): Pair, ResultStatus> { + ): ResultSupreme> { return fusedAPIImpl.getApplicationDetailsOSS(packageNameList) } -- GitLab From 67e30854dd2b80b0e22935e5ead5f7a2a8f40db8 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 5 Jul 2022 16:31:37 +0530 Subject: [PATCH 31/41] issue_5413: runCodeBlockWithTimeout add option for custom timeout --- app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index 81eadeab8..ef1189080 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -951,9 +951,10 @@ class FusedAPIImpl @Inject constructor( block: suspend () -> Unit, timeoutBlock: (() -> Unit)? = null, exceptionBlock: (() -> Unit)? = null, + timeoutLimit: Long = timeoutDurationInMillis, ): ResultStatus { return try { - withTimeout(timeoutDurationInMillis) { + withTimeout(timeoutLimit) { block() } ResultStatus.OK -- GitLab From 6be90d3a4d406566ea1313b2910bc6f7ef785b54 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 5 Jul 2022 16:36:55 +0530 Subject: [PATCH 32/41] issue_5413 [WIP]: declare updatesList type as ResultSupreme in UpdatesViewModel --- .../main/java/foundation/e/apps/updates/UpdatesViewModel.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt b/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt index 6e370e77b..c24eb3ef4 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt @@ -24,6 +24,7 @@ import androidx.lifecycle.viewModelScope import androidx.work.WorkInfo import com.aurora.gplayapi.data.models.AuthData import dagger.hilt.android.lifecycle.HiltViewModel +import foundation.e.apps.api.ResultSupreme import foundation.e.apps.api.fused.FusedAPIRepository import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.updates.manager.UpdatesManagerRepository @@ -38,7 +39,7 @@ class UpdatesViewModel @Inject constructor( private val fusedAPIRepository: FusedAPIRepository ) : ViewModel() { - val updatesList: MutableLiveData, ResultStatus?>> = MutableLiveData() + val updatesList: MutableLiveData>> = MutableLiveData() fun getUpdates(authData: AuthData) { viewModelScope.launch { -- GitLab From 69503e9043a0e796905dfd3baf90ce564dd34ef1 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 5 Jul 2022 16:38:49 +0530 Subject: [PATCH 33/41] issue_5413 [WIP]: use ResultSupreme in UpdatesManagerImpl and UpdatesManagerRepository --- .../e/apps/updates/manager/UpdatesManagerImpl.kt | 15 +++++++++------ .../updates/manager/UpdatesManagerRepository.kt | 6 +++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt index 1d2ada7ba..70f297ba2 100644 --- a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt +++ b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt @@ -19,6 +19,7 @@ package foundation.e.apps.updates.manager import com.aurora.gplayapi.data.models.AuthData +import foundation.e.apps.api.ResultSupreme import foundation.e.apps.api.fused.FusedAPIRepository import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.manager.pkg.PkgManagerModule @@ -34,10 +35,11 @@ class UpdatesManagerImpl @Inject constructor( private val TAG = UpdatesManagerImpl::class.java.simpleName // TODO: MAKE THIS LOGIC MORE SANE - suspend fun getUpdates(authData: AuthData): Pair, ResultStatus> { + suspend fun getUpdates(authData: AuthData): ResultSupreme> { val pkgList = mutableListOf() val updateList = mutableListOf() var status = ResultStatus.OK + var cleanapkFailed = false val userApplications = pkgManagerModule.getAllUserApps() userApplications.forEach { pkgList.add(it.packageName) } @@ -56,6 +58,7 @@ class UpdatesManagerImpl @Inject constructor( cleanAPKResult.second.let { if (it != ResultStatus.OK) { status = it + cleanapkFailed = true } } @@ -74,26 +77,26 @@ class UpdatesManagerImpl @Inject constructor( } } } - return Pair(updateList, status) + return ResultSupreme.create(status, updateList, cleanapkFailed.toString()) } /* * Get updates only from cleanapk. * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5413 [2] */ - suspend fun getUpdatesOSS(): Pair, ResultStatus> { + suspend fun getUpdatesOSS(): ResultSupreme> { val updateList = mutableListOf() val pkgList = pkgManagerModule.getAllUserApps().map { it.packageName } return if (pkgList.isNotEmpty()) { fusedAPIRepository.getApplicationDetailsOSS(pkgList).run { - this.first.forEach { + this.data?.forEach { if (it.status == Status.UPDATABLE) updateList.add(it) } - Pair(updateList, this.second) + ResultSupreme.replicate(this, updateList) } } else { - Pair(listOf(), ResultStatus.OK) + ResultSupreme.Success(listOf()) } } diff --git a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerRepository.kt b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerRepository.kt index 4e0f46fcc..f1e3d45d5 100644 --- a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerRepository.kt +++ b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerRepository.kt @@ -19,19 +19,19 @@ package foundation.e.apps.updates.manager import com.aurora.gplayapi.data.models.AuthData +import foundation.e.apps.api.ResultSupreme import foundation.e.apps.api.fused.data.FusedApp -import foundation.e.apps.utils.enums.ResultStatus import javax.inject.Inject class UpdatesManagerRepository @Inject constructor( private val updatesManagerImpl: UpdatesManagerImpl ) { - suspend fun getUpdates(authData: AuthData): Pair, ResultStatus> { + suspend fun getUpdates(authData: AuthData): ResultSupreme> { return updatesManagerImpl.getUpdates(authData) } - suspend fun getUpdatesOSS(): Pair, ResultStatus> { + suspend fun getUpdatesOSS(): ResultSupreme> { return updatesManagerImpl.getUpdatesOSS() } -- GitLab From 3c9073c2190a282b769218eb895abaa4d385da99 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 5 Jul 2022 16:39:54 +0530 Subject: [PATCH 34/41] issue_5413 [WIP]: update other uses of updatesList in UpdatesViewModel for ResultSupreme --- .../java/foundation/e/apps/updates/UpdatesViewModel.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt b/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt index c24eb3ef4..f5f348297 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesViewModel.kt @@ -44,11 +44,9 @@ class UpdatesViewModel @Inject constructor( fun getUpdates(authData: AuthData) { viewModelScope.launch { val updatesResult = updatesManagerRepository.getUpdates(authData) + val filteredList = updatesResult.data?.filter { !(!it.isFree && authData.isAnonymous) } ?: listOf() updatesList.postValue( - Pair( - updatesResult.first.filter { !(!it.isFree && authData.isAnonymous) }, - updatesResult.second - ) + ResultSupreme.replicate(updatesResult, filteredList) ) } } @@ -78,7 +76,7 @@ class UpdatesViewModel @Inject constructor( private fun checkWorkIsForUpdateByTag(tags: List): Boolean { updatesList.value?.let { - it.first.find { fusedApp -> tags.contains(fusedApp._id) }?.let { foundApp -> + it.data?.find { fusedApp -> tags.contains(fusedApp._id) }?.let { foundApp -> return listOf( Status.INSTALLED, Status.UPDATABLE -- GitLab From 4132fd16d277b190dbd869cdcd4b6d3e1e3295b5 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 5 Jul 2022 16:40:31 +0530 Subject: [PATCH 35/41] issue_5413 [WIP]: accommodate for ResultSupreme in UpdatesWorker --- .../java/foundation/e/apps/updates/manager/UpdatesWorker.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt index f73370521..3266d3737 100644 --- a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt +++ b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt @@ -59,7 +59,7 @@ class UpdatesWorker @AssistedInject constructor( loadSettings() val authData = getAuthData() val appsNeededToUpdate = updatesManagerRepository.getUpdates(authData) - .first.filter { !(!it.isFree && authData.isAnonymous) } + .data?.filter { !(!it.isFree && authData.isAnonymous) } ?: listOf() val isConnectedToUnmeteredNetwork = isConnectedToUnmeteredNetwork(applicationContext) /* * Show notification only if enabled. -- GitLab From 8ca289fa9f6fceb2c79511179d27ed6936d86021 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 5 Jul 2022 16:42:28 +0530 Subject: [PATCH 36/41] issue_5413: accommodate for ResultSupreme in UpdatesFragment --- .../e/apps/updates/UpdatesFragment.kt | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt index cf102de30..9a04cc05c 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt @@ -74,6 +74,7 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte private val appProgressViewModel: AppProgressViewModel by viewModels() private var isDownloadObserverAdded = false + private var cleanapkFailed = false override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -129,16 +130,17 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte } updatesViewModel.updatesList.observe(viewLifecycleOwner) { - if (it.second != ResultStatus.OK) { + if (!it.isSuccess()) { + cleanapkFailed = it.message.toBoolean() onTimeout() return@observe } else { - listAdapter?.setData(it.first) + listAdapter?.setData(it.data!!) if (!isDownloadObserverAdded) { observeDownloadList() isDownloadObserverAdded = true } - if (it.first.isNotEmpty()) { + if (it.data!!.isNotEmpty()) { binding.button.isEnabled = true binding.noUpdates.visibility = View.GONE } else { @@ -165,10 +167,10 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte timeoutFragment = this, activity = requireActivity(), message = - if (updatesViewModel.getApplicationCategoryPreference() == FusedAPIImpl.APP_TYPE_ANY) { - getString(R.string.timeout_desc_gplay) - } else { + if (cleanapkFailed) { getString(R.string.timeout_desc_cleanapk) + } else { + getString(R.string.timeout_desc_gplay) }, positiveButtonText = getString(R.string.retry), positiveButtonBlock = { @@ -177,9 +179,9 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte mainActivityViewModel.checkTokenOnTimeout() }, negativeButtonText = - if (updatesViewModel.getApplicationCategoryPreference() == FusedAPIImpl.APP_TYPE_ANY) { - getString(R.string.open_settings) - } else null, + if (cleanapkFailed) null + else getString(R.string.open_settings) + , negativeButtonBlock = { openSettings() }, @@ -229,11 +231,11 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte private fun observeDownloadList() { mainActivityViewModel.downloadList.observe(viewLifecycleOwner) { list -> - val appList = updatesViewModel.updatesList.value?.first?.toMutableList() ?: emptyList() + val appList = updatesViewModel.updatesList.value?.data?.toMutableList() ?: emptyList() appList.let { mainActivityViewModel.updateStatusOfFusedApps(appList, list) } - updatesViewModel.updatesList.apply { value = Pair(appList, value?.second) } + updatesViewModel.updatesList.apply { value?.setData(appList) } } } -- GitLab From e1bdec8db0a9d771e9c8231982815e5e47620ea7 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 5 Jul 2022 16:43:54 +0530 Subject: [PATCH 37/41] issue_5413: UpdatesFragment - show updates data even if timeout --- .../main/java/foundation/e/apps/updates/UpdatesFragment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt index 9a04cc05c..3a6a4f1e1 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt @@ -133,8 +133,8 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte if (!it.isSuccess()) { cleanapkFailed = it.message.toBoolean() onTimeout() - return@observe - } else { + } + if (it.isValidData()) { listAdapter?.setData(it.data!!) if (!isDownloadObserverAdded) { observeDownloadList() -- GitLab From ff2bd286a8d6f55851918b5e22f11d411a2052b9 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 5 Jul 2022 16:52:26 +0530 Subject: [PATCH 38/41] issue_5413: decrease timeout to 10 seconds --- .../java/foundation/e/apps/utils/modules/CommonUtilsModule.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsModule.kt b/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsModule.kt index 8b2b6e000..c881807ca 100644 --- a/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsModule.kt +++ b/app/src/main/java/foundation/e/apps/utils/modules/CommonUtilsModule.kt @@ -47,7 +47,7 @@ import javax.inject.Singleton object CommonUtilsModule { val LIST_OF_NULL = listOf("null") - const val timeoutDurationInMillis: Long = 25000 + const val timeoutDurationInMillis: Long = 10000 /** * Check supported ABIs by device -- GitLab From f21ed9721475408812e875c2e0412e8dea3439f6 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 5 Jul 2022 17:50:55 +0530 Subject: [PATCH 39/41] issue_5413: put timeout in okhttpbuilder for cleanapk, otherwise it just returns blank data instead of timeout --- .../java/foundation/e/apps/api/cleanapk/RetrofitModule.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/api/cleanapk/RetrofitModule.kt b/app/src/main/java/foundation/e/apps/api/cleanapk/RetrofitModule.kt index e0cd5630a..8454cc7ef 100644 --- a/app/src/main/java/foundation/e/apps/api/cleanapk/RetrofitModule.kt +++ b/app/src/main/java/foundation/e/apps/api/cleanapk/RetrofitModule.kt @@ -34,6 +34,7 @@ import foundation.e.apps.api.cleanapk.data.app.Application import foundation.e.apps.api.ecloud.EcloudApiInterface import foundation.e.apps.api.exodus.ExodusTrackerApi import foundation.e.apps.api.fdroid.FdroidApiInterface +import foundation.e.apps.utils.modules.CommonUtilsModule.timeoutDurationInMillis import okhttp3.Cache import okhttp3.Interceptor import okhttp3.MediaType.Companion.toMediaTypeOrNull @@ -47,6 +48,7 @@ import retrofit2.converter.jackson.JacksonConverterFactory import retrofit2.converter.moshi.MoshiConverterFactory import java.net.ConnectException import java.util.Locale +import java.util.concurrent.TimeUnit import javax.inject.Named import javax.inject.Singleton @@ -194,6 +196,10 @@ object RetrofitModule { @Provides fun provideOkHttpClient(cache: Cache, interceptor: Interceptor): OkHttpClient { return OkHttpClient.Builder() + .connectTimeout(timeoutDurationInMillis, TimeUnit.MILLISECONDS) + .readTimeout(timeoutDurationInMillis, TimeUnit.MILLISECONDS) + .writeTimeout(timeoutDurationInMillis, TimeUnit.MILLISECONDS) + .callTimeout(timeoutDurationInMillis, TimeUnit.MILLISECONDS) .addInterceptor(interceptor) .cache(cache) .build() -- GitLab From 54c922d9cf57f48f4a58134968a04f2809e4276b Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Tue, 5 Jul 2022 22:48:36 +0530 Subject: [PATCH 40/41] issue_5413: Change ReactiveNetwork library internetConnection host to http://204.ecloud.global --- .../java/foundation/e/apps/MainActivityViewModel.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index 48d67d9de..5615489b3 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -55,6 +55,8 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import ru.beryukhov.reactivenetwork.ReactiveNetwork +import ru.beryukhov.reactivenetwork.internet.observing.InternetObservingSettings +import ru.beryukhov.reactivenetwork.internet.observing.strategy.SocketInternetObservingStrategy import timber.log.Timber import java.io.ByteArrayOutputStream import javax.inject.Inject @@ -533,7 +535,14 @@ class MainActivityViewModel @Inject constructor( } val internetConnection = liveData { - emitSource(ReactiveNetwork().observeInternetConnectivity().asLiveData(Dispatchers.Default)) + emitSource( + ReactiveNetwork().observeInternetConnectivity( + InternetObservingSettings.builder() + .host("http://204.ecloud.global") + .strategy(SocketInternetObservingStrategy()) + .build() + ).asLiveData(Dispatchers.Default) + ) } fun updateStatusOfFusedApps( -- GitLab From 44d4021f4f36831a6af39e918f27df37d41ceac0 Mon Sep 17 00:00:00 2001 From: SayantanRC Date: Mon, 11 Jul 2022 23:19:32 +0530 Subject: [PATCH 41/41] fix after merging main --- .../main/java/foundation/e/apps/MainActivity.kt | 2 +- .../foundation/e/apps/MainActivityViewModel.kt | 17 ++++++++++++----- .../e/apps/updates/UpdatesFragment.kt | 2 +- .../apps/updates/manager/UpdatesManagerImpl.kt | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index c58ac6990..f6674b8fa 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -308,7 +308,7 @@ class MainActivity : AppCompatActivity() { setTitle(R.string.sign_in_failed_title) setMessage(R.string.sign_in_failed_desc) setPositiveButton(R.string.retry) { _, _ -> - viewModel.retryFetchingTokenAfterTimeout() + viewModel.checkTokenOnTimeout() } setNegativeButton(R.string.logout) { _, _ -> viewModel.postFalseAuthValidity() diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index aa65fad30..003208560 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -154,13 +154,20 @@ class MainActivityViewModel @Inject constructor( firstAuthDataFetchTime = 0 setFirstTokenFetchTime() /* - * Change done to show sign in error dialog for Google login. + * Explanation: + * 1. User type value must be present for all normal functioning. + * If not, post false to log out. + * 2. If authDataJson is empty, we have not yet obtained authData even once. + * Hence generate authData. + * 3. Else condition is where authDataJson is present in shared preferences, meaning + * we had logged in successfully at least once. Thus validate that data. + * * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5709 */ - if (authDataJson.value.isNullOrEmpty()) { - generateAuthDataBasedOnUserType(User.GOOGLE.name) - } else { - validateAuthData() + when { + userType.value == null -> postFalseAuthValidity() + authDataJson.value.isNullOrEmpty() -> generateAuthDataBasedOnUserType(userType.value!!) + else -> validateAuthData() } /* diff --git a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt index 41b8b7a47..53b3eba82 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt @@ -87,7 +87,7 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), FusedAPIInte */ mainActivityViewModel.internetConnection.observe(viewLifecycleOwner) { - if (!updatesViewModel.updatesList.value?.first.isNullOrEmpty()) { + if (!updatesViewModel.updatesList.value?.data.isNullOrEmpty()) { return@observe } refreshDataOrRefreshToken(mainActivityViewModel) diff --git a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt index bbab675d8..ac48a83e8 100644 --- a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt +++ b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt @@ -104,7 +104,7 @@ class UpdatesManagerImpl @Inject constructor( } } - private fun getNonFaultyApps(list: List): List { + private suspend fun getNonFaultyApps(list: List): List { val faultyAppsPackageNames = faultyAppRepository.getAllFaultyApps().map { it.packageName } return list.filter { !faultyAppsPackageNames.contains(it.package_name) } } -- GitLab