From 2de26e1f861d52fa47495077b78df12813cb4edc Mon Sep 17 00:00:00 2001 From: Hasib Prince Date: Tue, 29 Mar 2022 23:02:40 +0600 Subject: [PATCH] App Lounge: implemented UX for paidapps --- .../e/apps/api/fused/FusedAPIImpl.kt | 13 ++++---- .../e/apps/api/fused/data/FusedApp.kt | 1 + .../e/apps/application/ApplicationFragment.kt | 30 ++++++++++++++++--- .../subFrags/ApplicationDialogFragment.kt | 27 ++++++++++++----- .../ApplicationListFragment.kt | 12 +++++++- .../model/ApplicationListRVAdapter.kt | 9 ++++-- .../foundation/e/apps/home/HomeFragment.kt | 12 +++++++- .../e/apps/home/model/HomeChildRVAdapter.kt | 12 ++++++-- .../e/apps/home/model/HomeParentRVAdapter.kt | 5 ++-- .../e/apps/search/SearchFragment.kt | 12 +++++++- .../e/apps/updates/UpdatesFragment.kt | 12 +++++++- app/src/main/res/values/strings.xml | 6 ++++ 12 files changed, 122 insertions(+), 29 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 9adb16161..45aad5268 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 @@ -20,6 +20,7 @@ package foundation.e.apps.api.fused import android.content.Context import android.text.format.Formatter +import android.util.Log import com.aurora.gplayapi.SearchSuggestEntry import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.Artwork @@ -638,19 +639,17 @@ class FusedAPIImpl @Inject constructor( origin = Origin.GPLAY, shareUrl = this.shareUrl, appSize = Formatter.formatFileSize(context, this.size), - isFree = this.isFree + isFree = this.isFree, + price = this.price ) app.updateStatus() return app } private fun FusedApp.updateStatus() { - this.status = if (this.isFree) { - pkgManagerModule.getPackageStatus(this.package_name, this.latest_version_code) - } else if (this.status == Status.INSTALLATION_ISSUE) { - this.status - } else { - Status.BLOCKED + if (this.status != Status.INSTALLATION_ISSUE) { + this.status = + pkgManagerModule.getPackageStatus(this.package_name, this.latest_version_code) } } diff --git a/app/src/main/java/foundation/e/apps/api/fused/data/FusedApp.kt b/app/src/main/java/foundation/e/apps/api/fused/data/FusedApp.kt index 1429dec05..c676eeed2 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/data/FusedApp.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/data/FusedApp.kt @@ -44,6 +44,7 @@ data class FusedApp( val shareUrl: String = String(), val appSize: String = String(), var source: String = String(), + val price: String = String(), val isFree: Boolean = true, val is_pwa: Boolean = false, val url: String = 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 61175a9a8..9cfe4eeec 100644 --- a/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt +++ b/app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt @@ -261,7 +261,13 @@ class ApplicationFragment : Fragment(R.layout.fragment_application) { val fusedApp = applicationViewModel.fusedApp.value ?: FusedApp() when (status) { - Status.INSTALLED -> handleInstalled(installButton, view, fusedApp, downloadPB, appSize) + Status.INSTALLED -> handleInstalled( + installButton, + view, + fusedApp, + downloadPB, + appSize + ) Status.UPDATABLE -> handleUpdatable( installButton, view, @@ -270,7 +276,12 @@ class ApplicationFragment : Fragment(R.layout.fragment_application) { appSize ) Status.UNAVAILABLE -> handleUnavaiable(installButton, fusedApp, downloadPB, appSize) - Status.QUEUED, Status.AWAITING -> handleQueued(installButton, fusedApp, downloadPB, appSize) + Status.QUEUED, Status.AWAITING -> handleQueued( + installButton, + fusedApp, + downloadPB, + appSize + ) Status.DOWNLOADING -> handleDownloading( installButton, fusedApp, @@ -388,10 +399,21 @@ class ApplicationFragment : Fragment(R.layout.fragment_application) { appSize: MaterialTextView ) { installButton.apply { - text = getString(R.string.install) + text = if (fusedApp.isFree) getString(R.string.install) else fusedApp.price setOnClickListener { applicationIcon?.let { - mainActivityViewModel.getApplication(fusedApp, it) + if (fusedApp.isFree) { + mainActivityViewModel.getApplication(fusedApp, it) + } else { + ApplicationDialogFragment( + title = getString(R.string.dialog_title_paid_app, fusedApp.name), + message = getString(R.string.dialog_paidapp_message, fusedApp.name, fusedApp.price), + positiveButtonText = getString(R.string.dialog_confirm), + positiveButtonAction = { + }, + cancelButtonText = getString(R.string.dialog_cancel), + ).show(childFragmentManager, "ApplicationFragment") + } } } } diff --git a/app/src/main/java/foundation/e/apps/application/subFrags/ApplicationDialogFragment.kt b/app/src/main/java/foundation/e/apps/application/subFrags/ApplicationDialogFragment.kt index 202d3b8e6..c3e5a455a 100644 --- a/app/src/main/java/foundation/e/apps/application/subFrags/ApplicationDialogFragment.kt +++ b/app/src/main/java/foundation/e/apps/application/subFrags/ApplicationDialogFragment.kt @@ -33,20 +33,33 @@ import foundation.e.apps.R @AndroidEntryPoint class ApplicationDialogFragment( - private val drawable: Int, + private val drawable: Int = -1, private val title: String, - private val message: String + private val message: String, + private val positiveButtonText: String = "", + private val positiveButtonAction: (() -> Unit)? = null, + private val cancelButtonText: String = "", + private val cancelButtonAction: (() -> Unit)? = null, ) : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return MaterialAlertDialogBuilder(requireContext()) - .setIcon(drawable) - .setTitle(title) + val positiveButtonText = + positiveButtonText.ifEmpty { getString(R.string.ok) } + val materialAlertDialogBuilder = MaterialAlertDialogBuilder(requireContext()) + .setTitle(Html.fromHtml(title, Html.FROM_HTML_MODE_COMPACT)) .setMessage(Html.fromHtml(message, Html.FROM_HTML_MODE_COMPACT)) - .setPositiveButton(getString(R.string.ok)) { _, _ -> + .setPositiveButton(positiveButtonText) { _, _ -> + positiveButtonAction?.invoke() this.dismiss() } - .create() + .setNegativeButton(cancelButtonText) { _, _ -> + cancelButtonAction?.invoke() + this.dismiss() + } + if (drawable != -1) { + materialAlertDialogBuilder.setIcon(drawable) + } + return materialAlertDialogBuilder.create() } override fun onResume() { 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 aeb6fb05c..c7b02d519 100644 --- a/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt +++ b/app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt @@ -38,6 +38,7 @@ import foundation.e.apps.PrivacyInfoViewModel import foundation.e.apps.R import foundation.e.apps.api.fused.FusedAPIInterface import foundation.e.apps.api.fused.data.FusedApp +import foundation.e.apps.application.subFrags.ApplicationDialogFragment import foundation.e.apps.applicationlist.model.ApplicationListRVAdapter import foundation.e.apps.databinding.FragmentApplicationListBinding import foundation.e.apps.manager.download.data.DownloadProgress @@ -114,7 +115,16 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu pkgManagerModule, User.valueOf(mainActivityViewModel.userType.value ?: User.UNAVAILABLE.name), viewLifecycleOwner - ) + ) { fusedApp -> + ApplicationDialogFragment( + title = getString(R.string.dialog_title_paid_app, fusedApp.name), + message = getString(R.string.dialog_paidapp_message, fusedApp.name, fusedApp.price), + positiveButtonText = getString(R.string.dialog_confirm), + positiveButtonAction = { + }, + cancelButtonText = getString(R.string.dialog_cancel), + ).show(childFragmentManager, "HomeFragment") + } } recyclerView.apply { diff --git a/app/src/main/java/foundation/e/apps/applicationlist/model/ApplicationListRVAdapter.kt b/app/src/main/java/foundation/e/apps/applicationlist/model/ApplicationListRVAdapter.kt index 3179ce134..048d23f7f 100644 --- a/app/src/main/java/foundation/e/apps/applicationlist/model/ApplicationListRVAdapter.kt +++ b/app/src/main/java/foundation/e/apps/applicationlist/model/ApplicationListRVAdapter.kt @@ -57,6 +57,7 @@ class ApplicationListRVAdapter( private val pkgManagerModule: PkgManagerModule, private val user: User, private val lifecycleOwner: LifecycleOwner, + private val paidAppHandler: ((FusedApp) -> Unit)? = null ) : ListAdapter(ApplicationDiffUtil()) { private val TAG = ApplicationListRVAdapter::class.java.simpleName @@ -295,13 +296,17 @@ class ApplicationListRVAdapter( ) { installButton.apply { isEnabled = true - text = context.getString(R.string.install) + text = if (searchApp.isFree) context.getString(R.string.install) else searchApp.price setTextColor(context.getColor(R.color.colorAccent)) backgroundTintList = ContextCompat.getColorStateList(view.context, android.R.color.transparent) strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) setOnClickListener { - installApplication(searchApp, appIcon) + if (searchApp.isFree) { + installApplication(searchApp, appIcon) + } else { + paidAppHandler?.invoke(searchApp) + } } } } 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 7773a4537..5c30d86c2 100644 --- a/app/src/main/java/foundation/e/apps/home/HomeFragment.kt +++ b/app/src/main/java/foundation/e/apps/home/HomeFragment.kt @@ -34,6 +34,7 @@ import foundation.e.apps.MainActivityViewModel import foundation.e.apps.R import foundation.e.apps.api.fused.FusedAPIInterface import foundation.e.apps.api.fused.data.FusedApp +import foundation.e.apps.application.subFrags.ApplicationDialogFragment import foundation.e.apps.databinding.FragmentHomeBinding import foundation.e.apps.home.model.HomeChildRVAdapter import foundation.e.apps.home.model.HomeParentRVAdapter @@ -84,7 +85,16 @@ class HomeFragment : Fragment(R.layout.fragment_home), FusedAPIInterface { pkgManagerModule, User.valueOf(mainActivityViewModel.userType.value ?: User.UNAVAILABLE.name), mainActivityViewModel, viewLifecycleOwner - ) + ) { fusedApp -> + ApplicationDialogFragment( + title = getString(R.string.dialog_title_paid_app, fusedApp.name), + message = getString(R.string.dialog_paidapp_message, fusedApp.name, fusedApp.price), + positiveButtonText = getString(R.string.dialog_confirm), + positiveButtonAction = { + }, + cancelButtonText = getString(R.string.dialog_cancel), + ).show(childFragmentManager, "HomeFragment") + } binding.parentRV.apply { adapter = homeParentRVAdapter diff --git a/app/src/main/java/foundation/e/apps/home/model/HomeChildRVAdapter.kt b/app/src/main/java/foundation/e/apps/home/model/HomeChildRVAdapter.kt index a877dcd14..0d4b74f32 100644 --- a/app/src/main/java/foundation/e/apps/home/model/HomeChildRVAdapter.kt +++ b/app/src/main/java/foundation/e/apps/home/model/HomeChildRVAdapter.kt @@ -44,7 +44,8 @@ import foundation.e.apps.utils.enums.User class HomeChildRVAdapter( private val fusedAPIInterface: FusedAPIInterface, private val pkgManagerModule: PkgManagerModule, - private val user: User + private val user: User, + private val paidAppHandler: ((FusedApp) -> Unit)? = null ) : ListAdapter(HomeChildFusedAppDiffUtil()) { private val shimmer = Shimmer.ColorHighlightBuilder() @@ -124,7 +125,8 @@ class HomeChildRVAdapter( } Status.UNAVAILABLE -> { installButton.apply { - text = context.getString(R.string.install) + text = + if (homeApp.isFree) context.getString(R.string.install) else homeApp.price setTextColor(context.getColor(R.color.colorAccent)) backgroundTintList = ContextCompat.getColorStateList( view.context, @@ -133,7 +135,11 @@ class HomeChildRVAdapter( strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) setOnClickListener { - installApplication(homeApp, appIcon) + if (homeApp.isFree) { + installApplication(homeApp, appIcon) + } else { + paidAppHandler?.invoke(homeApp) + } } } } diff --git a/app/src/main/java/foundation/e/apps/home/model/HomeParentRVAdapter.kt b/app/src/main/java/foundation/e/apps/home/model/HomeParentRVAdapter.kt index 30ca74d22..1595866c3 100644 --- a/app/src/main/java/foundation/e/apps/home/model/HomeParentRVAdapter.kt +++ b/app/src/main/java/foundation/e/apps/home/model/HomeParentRVAdapter.kt @@ -38,7 +38,8 @@ class HomeParentRVAdapter( private val pkgManagerModule: PkgManagerModule, private val user: User, private val mainActivityViewModel: MainActivityViewModel, - private val lifecycleOwner: LifecycleOwner + private val lifecycleOwner: LifecycleOwner, + private val paidAppHandler: ((FusedApp) -> Unit)? = null ) : ListAdapter(FusedHomeDiffUtil()) { private val viewPool = RecyclerView.RecycledViewPool() @@ -55,7 +56,7 @@ class HomeParentRVAdapter( override fun onBindViewHolder(holder: ViewHolder, position: Int) { val fusedHome = getItem(position) val homeChildRVAdapter = - HomeChildRVAdapter(fusedAPIInterface, pkgManagerModule, user) + HomeChildRVAdapter(fusedAPIInterface, pkgManagerModule, user, paidAppHandler) homeChildRVAdapter.setData(fusedHome.list) holder.binding.titleTV.text = fusedHome.title 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 3bc4bb727..c5ea9d887 100644 --- a/app/src/main/java/foundation/e/apps/search/SearchFragment.kt +++ b/app/src/main/java/foundation/e/apps/search/SearchFragment.kt @@ -46,6 +46,7 @@ import foundation.e.apps.PrivacyInfoViewModel import foundation.e.apps.R import foundation.e.apps.api.fused.FusedAPIInterface import foundation.e.apps.api.fused.data.FusedApp +import foundation.e.apps.application.subFrags.ApplicationDialogFragment import foundation.e.apps.applicationlist.model.ApplicationListRVAdapter import foundation.e.apps.databinding.FragmentSearchBinding import foundation.e.apps.manager.pkg.PkgManagerModule @@ -118,7 +119,16 @@ class SearchFragment : pkgManagerModule, User.valueOf(mainActivityViewModel.userType.value ?: User.UNAVAILABLE.name), viewLifecycleOwner - ) + ) { fusedApp -> + ApplicationDialogFragment( + title = getString(R.string.dialog_title_paid_app, fusedApp.name), + message = getString(R.string.dialog_paidapp_message, fusedApp.name, fusedApp.price), + positiveButtonText = getString(R.string.dialog_confirm), + positiveButtonAction = { + }, + cancelButtonText = getString(R.string.dialog_cancel), + ).show(childFragmentManager, "SearchFragment") + } } recyclerView?.apply { 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 4fb3b683f..f9b2962e9 100644 --- a/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt +++ b/app/src/main/java/foundation/e/apps/updates/UpdatesFragment.kt @@ -35,6 +35,7 @@ import foundation.e.apps.PrivacyInfoViewModel import foundation.e.apps.R import foundation.e.apps.api.fused.FusedAPIInterface import foundation.e.apps.api.fused.data.FusedApp +import foundation.e.apps.application.subFrags.ApplicationDialogFragment import foundation.e.apps.applicationlist.model.ApplicationListRVAdapter import foundation.e.apps.databinding.FragmentUpdatesBinding import foundation.e.apps.manager.download.data.DownloadProgress @@ -86,7 +87,16 @@ class UpdatesFragment : Fragment(R.layout.fragment_updates), FusedAPIInterface { pkgManagerModule, User.valueOf(mainActivityViewModel.userType.value ?: User.UNAVAILABLE.name), viewLifecycleOwner, - ) + ) { fusedApp -> + ApplicationDialogFragment( + title = getString(R.string.dialog_title_paid_app, fusedApp.name), + message = getString(R.string.dialog_paidapp_message, fusedApp.name, fusedApp.price), + positiveButtonText = getString(R.string.dialog_confirm), + positiveButtonAction = { + }, + cancelButtonText = getString(R.string.dialog_cancel), + ).show(childFragmentManager, "UpdatesFragment") + } } recyclerView.apply { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e2a657ddb..751f3ac38 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -149,4 +149,10 @@ Can\'t connect! Please check your internet connection and try again + + %1$s]]> + When clicked confirm, it will take you to Google Play page for the app to complete the purchase using your browser. Click confirm to purchase %1$s for %2$s. + CONFIRM + CANCEL + -- GitLab