Loading app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +22 −0 Original line number Diff line number Diff line Loading @@ -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<FusedApp, ResultStatus> { 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<String>, authData: AuthData, Loading app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt +4 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,10 @@ class FusedAPIRepository @Inject constructor( return fusedAPIImpl.getApplicationDetails(id, packageName, authData, origin) } suspend fun getCleanapkAppDetails(packageName: String): Pair<FusedApp, ResultStatus> { return fusedAPIImpl.getCleanapkAppDetails(packageName) } suspend fun updateFusedDownloadWithDownloadingInfo( authData: AuthData, origin: Origin, Loading app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt +44 −9 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -156,6 +183,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { dismissTimeoutDialog() isDetailsLoaded = true if (applicationViewModel.appStatus.value == null) { applicationViewModel.appStatus.value = it.status } Loading @@ -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) Loading Loading @@ -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( Loading Loading @@ -308,14 +336,21 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { } override fun refreshData(authData: AuthData) { /* 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 { applicationViewModel.getApplicationDetails( args.id, args.packageName, packageName, authData, args.origin origin ) } } private fun observeDownloadStatus(view: View) { applicationViewModel.appStatus.observe(viewLifecycleOwner) { status -> Loading app/src/main/java/foundation/e/apps/application/ApplicationViewModel.kt +20 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading app/src/main/res/navigation/navigation_resource.xml +7 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,13 @@ <deepLink app:action="android.intent.action.VIEW" app:uri="play.google.com/store/apps/details?id={packageName}" /> <!-- Add support for f-droid packages Issue: https://gitlab.e.foundation/e/backlog/-/issues/5509 --> <deepLink app:action="android.intent.action.VIEW" app:uri="f-droid.org/packages/{packageName}" /> <deepLink app:action="android.intent.action.VIEW" app:uri="play.app.goo.gl/?link={playStore_url}?id={packageName}&ddl={pc1}&pcampaignid={pc2}" /> Loading Loading
app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +22 −0 Original line number Diff line number Diff line Loading @@ -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<FusedApp, ResultStatus> { 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<String>, authData: AuthData, Loading
app/src/main/java/foundation/e/apps/api/fused/FusedAPIRepository.kt +4 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,10 @@ class FusedAPIRepository @Inject constructor( return fusedAPIImpl.getApplicationDetails(id, packageName, authData, origin) } suspend fun getCleanapkAppDetails(packageName: String): Pair<FusedApp, ResultStatus> { return fusedAPIImpl.getCleanapkAppDetails(packageName) } suspend fun updateFusedDownloadWithDownloadingInfo( authData: AuthData, origin: Origin, Loading
app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt +44 −9 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading Loading @@ -156,6 +183,7 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { dismissTimeoutDialog() isDetailsLoaded = true if (applicationViewModel.appStatus.value == null) { applicationViewModel.appStatus.value = it.status } Loading @@ -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) Loading Loading @@ -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( Loading Loading @@ -308,14 +336,21 @@ class ApplicationFragment : TimeoutFragment(R.layout.fragment_application) { } override fun refreshData(authData: AuthData) { /* 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 { applicationViewModel.getApplicationDetails( args.id, args.packageName, packageName, authData, args.origin origin ) } } private fun observeDownloadStatus(view: View) { applicationViewModel.appStatus.observe(viewLifecycleOwner) { status -> Loading
app/src/main/java/foundation/e/apps/application/ApplicationViewModel.kt +20 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
app/src/main/res/navigation/navigation_resource.xml +7 −0 Original line number Diff line number Diff line Loading @@ -109,6 +109,13 @@ <deepLink app:action="android.intent.action.VIEW" app:uri="play.google.com/store/apps/details?id={packageName}" /> <!-- Add support for f-droid packages Issue: https://gitlab.e.foundation/e/backlog/-/issues/5509 --> <deepLink app:action="android.intent.action.VIEW" app:uri="f-droid.org/packages/{packageName}" /> <deepLink app:action="android.intent.action.VIEW" app:uri="play.app.goo.gl/?link={playStore_url}?id={packageName}&ddl={pc1}&pcampaignid={pc2}" /> Loading