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 aac88fa671f1c58045a75cdaa3d332c3e1694884..1f94ca7cbfe5c7ef3c5b77d8d92b8ea6ed526d21 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 @@ -350,6 +350,28 @@ class FusedAPIImpl @Inject constructor( return Triple(appsList, nextUrl, status) } + /* + * Function to search cleanapk using package name. + * Will be used to handle f-droid deeplink. + * + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5509 + */ + suspend fun getCleanapkAppDetails(packageName: String): Pair { + var fusedApp = FusedApp() + val status = runCodeBlockWithTimeout({ + val result = cleanAPKRepository.searchApps( + keyword = packageName, + by = "package_name" + ).body() + if (result?.apps?.isNotEmpty() == true && result.numberOfResults == 1) { + fusedApp = + cleanAPKRepository.getAppOrPWADetailsByID(result.apps[0]._id).body()?.app + ?: FusedApp() + } + }) + return Pair(fusedApp, status) + } + 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 f92123cc05b22f02e9e8a5b7ebbf0b45e4cef713..c1cd78252cc338a872a1ce50545f1a4a17875a82 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,6 +68,10 @@ class FusedAPIRepository @Inject constructor( return fusedAPIImpl.getApplicationDetails(id, packageName, authData, origin) } + suspend fun getCleanapkAppDetails(packageName: String): Pair { + return fusedAPIImpl.getCleanapkAppDetails(packageName) + } + suspend fun updateFusedDownloadWithDownloadingInfo( authData: AuthData, origin: Origin, 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 7fcfed4a5d1babb248aaf6653edbc6edabbf5dc1..fa1f7467c64464a3fe5b9aa7b4783d4c115fb280 100644 --- a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt +++ b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt @@ -76,6 +76,33 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { private var _binding: FragmentApplicationBinding? = null private val binding get() = _binding!! + /* + * We have no way to pass an argument for a specific deeplink to signify it is an f-droid link. + * Hence we check the intent from the activity. + * This boolean is later used to lock the origin to Origin.CLEANAPK, + * and call a different method to fetch from cleanapk. + * + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5509 + */ + private val isFdroidDeepLink: Boolean by lazy { + activity?.intent?.data?.host?.equals("f-droid.org") ?: false + } + + /* + * We will use this variable in all cases instead of directly calling args.origin. + * + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5509 + */ + private val origin by lazy { + if (isFdroidDeepLink) { + Origin.CLEANAPK + } else { + args.origin + } + } + + private var isDetailsLoaded = false + @Inject lateinit var pkgManagerModule: PkgManagerModule @@ -125,7 +152,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { val notAvailable = getString(R.string.not_available) - val screenshotsRVAdapter = ApplicationScreenshotsRVAdapter(args.origin) + val screenshotsRVAdapter = ApplicationScreenshotsRVAdapter(origin) binding.recyclerView.apply { adapter = screenshotsRVAdapter layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) @@ -156,6 +183,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { dismissTimeoutDialog() + isDetailsLoaded = true if (applicationViewModel.appStatus.value == null) { applicationViewModel.appStatus.value = it.status } @@ -168,7 +196,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { appAuthor.text = it.author appInfoFetchViewModel.setAuthorNameIfNeeded(appAuthor, it) categoryTitle.text = it.category - if (args.origin == Origin.CLEANAPK) { + if (origin == Origin.CLEANAPK) { appIcon.load(CleanAPKInterface.ASSET_URL + it.icon_image_path) } else { appIcon.load(it.icon_image_path) @@ -227,7 +255,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { binding.infoInclude.apply { appUpdatedOn.text = getString( R.string.updated_on, - if (args.origin == Origin.CLEANAPK) it.updatedOn else it.last_modified + if (origin == Origin.CLEANAPK) it.updatedOn else it.last_modified ) appRequires.text = getString(R.string.min_android_version, notAvailable) appVersion.text = getString( @@ -308,13 +336,20 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { } override fun refreshData(authData: AuthData) { + /* Show the loading bar. */ showLoadingUI() - applicationViewModel.getApplicationDetails( - args.id, - args.packageName, - authData, - args.origin - ) + /* 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 { + applicationViewModel.getApplicationDetails( + args.id, + packageName, + authData, + origin + ) + } } private fun observeDownloadStatus(view: View) { 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 f64c956185cde2fd310ba8d6f342cbe297892460..dc094e5ff0f18a9f8e3a1a99d0d9de6e6901c94f 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,26 @@ class ApplicationViewModel @Inject constructor( } } + /* + * Dedicated method to get app details from cleanapk using package name. + * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5509 + */ + fun getCleanapkAppDetails(packageName: String) { + viewModelScope.launch { + try { + fusedAPIRepository.getCleanapkAppDetails(packageName).run { + if (this.first.package_name.isBlank()) { + _errorMessageLiveData.postValue(R.string.app_not_found) + } else { + fusedApp.postValue(this) + } + } + } catch (e: Exception) { + _errorMessageLiveData.postValue(R.string.unknown_error) + } + } + } + fun transformPermsToString(): String { var permissionString = "" fusedApp.value?.first?.let { diff --git a/app/src/main/res/navigation/navigation_resource.xml b/app/src/main/res/navigation/navigation_resource.xml index 2bacd70dc9775cec97dfafc4a8889ce80d397a52..2e2024e97d34dd4ced822f8409b333a0134e8ad2 100644 --- a/app/src/main/res/navigation/navigation_resource.xml +++ b/app/src/main/res/navigation/navigation_resource.xml @@ -109,6 +109,13 @@ + +