Loading app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt +39 −2 Original line number Diff line number Diff line Loading @@ -19,15 +19,18 @@ package foundation.e.apps.applicationlist import android.os.Bundle import android.util.Log import android.view.View import android.widget.ImageView import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.findNavController import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.hilt.android.AndroidEntryPoint import foundation.e.apps.AppProgressViewModel import foundation.e.apps.MainActivityViewModel Loading @@ -37,8 +40,12 @@ import foundation.e.apps.api.fused.FusedAPIInterface import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.applicationlist.model.ApplicationListRVAdapter import foundation.e.apps.databinding.FragmentApplicationListBinding import foundation.e.apps.home.model.HomeChildRVAdapter import foundation.e.apps.manager.download.data.DownloadProgress import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.User import kotlinx.coroutines.launch import javax.inject.Inject @AndroidEntryPoint Loading Loading @@ -107,8 +114,7 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu it, pkgManagerModule, User.valueOf(mainActivityViewModel.userType.value ?: User.UNAVAILABLE.name), viewLifecycleOwner, appProgressViewModel viewLifecycleOwner ) } Loading @@ -117,6 +123,10 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu layoutManager = LinearLayoutManager(view?.context) } appProgressViewModel.downloadProgress.observe(viewLifecycleOwner) { updateProgressOfDownloadingItems(recyclerView, it) } viewModel.appListLiveData.observe(viewLifecycleOwner) { listAdapter?.setData(it) if (!isDownloadObserverAdded) { Loading @@ -141,6 +151,33 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu } } private fun updateProgressOfDownloadingItems( recyclerView: RecyclerView, it: DownloadProgress ) { val adapter = recyclerView.adapter as ApplicationListRVAdapter lifecycleScope.launch { adapter.currentList.forEach { fusedApp -> if (fusedApp.status == Status.DOWNLOADING) { val progress = appProgressViewModel.calculateProgress(fusedApp, it) val downloadProgress = ((progress.second / progress.first.toDouble()) * 100).toInt() Log.d( "HomeParentAdapter", "download progress of ===> ${fusedApp.name} : $downloadProgress" ) val viewHolder = recyclerView.findViewHolderForAdapterPosition( adapter.currentList.indexOf(fusedApp) ) viewHolder?.let { (viewHolder as ApplicationListRVAdapter.ViewHolder).binding.installButton.text = "$downloadProgress%" } } } } } override fun onPause() { isDownloadObserverAdded = false binding.shimmerLayout.stopShimmer() Loading app/src/main/java/foundation/e/apps/applicationlist/model/ApplicationListRVAdapter.kt +5 −69 Original line number Diff line number Diff line Loading @@ -62,7 +62,6 @@ class ApplicationListRVAdapter( private val pkgManagerModule: PkgManagerModule, private val user: User, private val lifecycleOwner: LifecycleOwner, private val appProgressViewModel: AppProgressViewModel ) : ListAdapter<FusedApp, ApplicationListRVAdapter.ViewHolder>(ApplicationDiffUtil()) { private val TAG = ApplicationListRVAdapter::class.java.simpleName Loading @@ -76,54 +75,7 @@ class ApplicationListRVAdapter( .build() inner class ViewHolder(val binding: ApplicationListItemBinding) : RecyclerView.ViewHolder(binding.root), LifecycleOwner { private val lifecycleRegistry = LifecycleRegistry(this) init { lifecycleRegistry.currentState = Lifecycle.State.INITIALIZED } fun onAppear() { lifecycleRegistry.currentState = Lifecycle.State.RESUMED } fun onDisappear() { lifecycleRegistry.currentState = Lifecycle.State.DESTROYED } override fun getLifecycle(): Lifecycle { return lifecycleRegistry } } override fun onViewAttachedToWindow(holder: ViewHolder) { super.onViewAttachedToWindow(holder) Log.d(TAG, "onViewAttachedToWindow: Appeared: ${holder.absoluteAdapterPosition}") holder.onAppear() } override fun onViewDetachedFromWindow(holder: ViewHolder) { holder.onDisappear() Log.d(TAG, "onViewAttachedToWindow: Disappeared: ${holder.absoluteAdapterPosition}") super.onViewDetachedFromWindow(holder) } override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { Log.d(TAG, "onDetachedFromRecyclerView: ") for (i in 0..recyclerView.childCount) { val view = recyclerView.getChildAt(i) if (view != null) { val holder = recyclerView.getChildViewHolder(view) holder?.let { appProgressViewModel.downloadProgress.removeObservers(holder as LifecycleOwner) (holder as ViewHolder).onDisappear() } } } super.onDetachedFromRecyclerView(recyclerView) } RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder( Loading Loading @@ -206,16 +158,16 @@ class ApplicationListRVAdapter( } when (searchApp.status) { Status.INSTALLED -> { handleInstalled(view, searchApp, holder) handleInstalled(view, searchApp) } Status.UPDATABLE -> { handleUpdatable(view, searchApp) } Status.UNAVAILABLE -> { handleUnavailable(view, searchApp, holder) handleUnavailable(view, searchApp) } Status.QUEUED, Status.AWAITING, Status.DOWNLOADING -> { handleDownloading(view, searchApp, holder) handleDownloading(view, searchApp) } Status.INSTALLING, Status.UNINSTALLING -> { handleInstalling(view, holder) Loading @@ -224,7 +176,7 @@ class ApplicationListRVAdapter( handleBlocked(view) } Status.INSTALLATION_ISSUE -> { handleInstallationIssue(view, searchApp, holder) handleInstallationIssue(view, searchApp) } } Loading @@ -235,9 +187,7 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleInstallationIssue( view: View, searchApp: FusedApp, holder: ViewHolder ) { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = true text = view.context.getString(R.string.retry) Loading Loading @@ -318,7 +268,6 @@ class ApplicationListRVAdapter( } private fun ApplicationListItemBinding.handleInstalling(view: View, holder: ViewHolder) { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = false setTextColor(context.getColor(R.color.light_grey)) Loading @@ -331,7 +280,6 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleDownloading( view: View, searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true Loading @@ -340,14 +288,6 @@ class ApplicationListRVAdapter( backgroundTintList = ContextCompat.getColorStateList(view.context, android.R.color.transparent) strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) appProgressViewModel.downloadProgress.observe(holder) { appProgressViewModel.viewModelScope.launch { val progress = appProgressViewModel.calculateProgress(searchApp, it) if (progress.second > 0 && progress.second <= progress.first) { text = "${((progress.second / progress.first.toDouble()) * 100).toInt()}%" } } } setOnClickListener { cancelDownload(searchApp) } Loading @@ -357,7 +297,6 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleUnavailable( view: View, searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true Loading @@ -366,7 +305,6 @@ class ApplicationListRVAdapter( backgroundTintList = ContextCompat.getColorStateList(view.context, android.R.color.transparent) strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) appProgressViewModel.downloadProgress.removeObservers(holder) setOnClickListener { installApplication(searchApp, appIcon) } Loading @@ -392,7 +330,6 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleInstalled( view: View, searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true Loading @@ -400,7 +337,6 @@ class ApplicationListRVAdapter( setTextColor(Color.WHITE) backgroundTintList = ContextCompat.getColorStateList(view.context, R.color.colorAccent) strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) appProgressViewModel.downloadProgress.removeObservers(holder) setOnClickListener { context.startActivity(pkgManagerModule.getLaunchIntent(searchApp.package_name)) } Loading app/src/main/java/foundation/e/apps/home/HomeFragment.kt +52 −1 Original line number Diff line number Diff line Loading @@ -24,8 +24,10 @@ import android.widget.ImageView import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.hilt.android.AndroidEntryPoint import foundation.e.apps.AppProgressViewModel import foundation.e.apps.MainActivityViewModel Loading @@ -33,9 +35,13 @@ import foundation.e.apps.R import foundation.e.apps.api.fused.FusedAPIInterface import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.databinding.FragmentHomeBinding import foundation.e.apps.home.model.HomeChildRVAdapter import foundation.e.apps.home.model.HomeParentRVAdapter import foundation.e.apps.manager.download.data.DownloadProgress import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.User import kotlinx.coroutines.launch import javax.inject.Inject @AndroidEntryPoint Loading Loading @@ -77,7 +83,7 @@ class HomeFragment : Fragment(R.layout.fragment_home), FusedAPIInterface { this, pkgManagerModule, User.valueOf(mainActivityViewModel.userType.value ?: User.UNAVAILABLE.name), mainActivityViewModel, viewLifecycleOwner, appProgressViewModel mainActivityViewModel, viewLifecycleOwner ) binding.parentRV.apply { Loading @@ -90,6 +96,51 @@ class HomeFragment : Fragment(R.layout.fragment_home), FusedAPIInterface { binding.shimmerLayout.visibility = View.GONE binding.parentRV.visibility = View.VISIBLE } appProgressViewModel.downloadProgress.observe(viewLifecycleOwner) { updateProgressOfDownloadingAppItemViews(homeParentRVAdapter, it) } } private fun updateProgressOfDownloadingAppItemViews( homeParentRVAdapter: HomeParentRVAdapter, downloadProgress: DownloadProgress ) { homeParentRVAdapter.currentList.forEach { fusedHome -> val viewHolder = binding.parentRV.findViewHolderForAdapterPosition( homeParentRVAdapter.currentList.indexOf(fusedHome) ) viewHolder?.let { parentViewHolder -> val childRV = (parentViewHolder as HomeParentRVAdapter.ViewHolder).binding.childRV val adapter = childRV.adapter as HomeChildRVAdapter findDownloadingItemsToShowProgress(adapter, downloadProgress, childRV) } } } private fun findDownloadingItemsToShowProgress( adapter: HomeChildRVAdapter, downloadProgress: DownloadProgress, childRV: RecyclerView ) { lifecycleScope.launch { adapter.currentList.forEach { fusedApp -> if (fusedApp.status == Status.DOWNLOADING) { val progress = appProgressViewModel.calculateProgress(fusedApp, downloadProgress) val downloadProgress = ((progress.second / progress.first.toDouble()) * 100).toInt() val childViewHolder = childRV.findViewHolderForAdapterPosition( adapter.currentList.indexOf(fusedApp) ) childViewHolder?.let { (childViewHolder as HomeChildRVAdapter.ViewHolder).binding.installButton.text = "$downloadProgress%" } } } } } override fun onResume() { Loading app/src/main/java/foundation/e/apps/home/model/HomeChildRVAdapter.kt +6 −61 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package foundation.e.apps.home.model import android.graphics.Color import android.util.Log import android.view.LayoutInflater import android.view.ViewGroup import android.widget.ImageView Loading Loading @@ -50,8 +51,7 @@ import kotlinx.coroutines.launch class HomeChildRVAdapter( private val fusedAPIInterface: FusedAPIInterface, private val pkgManagerModule: PkgManagerModule, private val user: User, private val appProgressViewModel: AppProgressViewModel private val user: User ) : ListAdapter<FusedApp, HomeChildRVAdapter.ViewHolder>(HomeChildFusedAppDiffUtil()) { private val shimmer = Shimmer.ColorHighlightBuilder() Loading @@ -63,58 +63,17 @@ class HomeChildRVAdapter( .build() inner class ViewHolder(val binding: HomeChildListItemBinding) : RecyclerView.ViewHolder(binding.root), LifecycleOwner { private val lifecycleRegistry = LifecycleRegistry(this) init { lifecycleRegistry.currentState = Lifecycle.State.INITIALIZED } fun onAppear() { lifecycleRegistry.currentState = Lifecycle.State.RESUMED } fun onDisappear() { lifecycleRegistry.currentState = Lifecycle.State.DESTROYED } override fun getLifecycle(): Lifecycle { return lifecycleRegistry } } override fun onViewAttachedToWindow(holder: HomeChildRVAdapter.ViewHolder) { super.onViewAttachedToWindow(holder) holder.onAppear() } override fun onViewDetachedFromWindow(holder: HomeChildRVAdapter.ViewHolder) { holder.onDisappear() super.onViewDetachedFromWindow(holder) } override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { for (i in 0..recyclerView.childCount) { val view = recyclerView.getChildAt(i) if (view != null) { val holder = recyclerView.getChildViewHolder(view) holder?.let { appProgressViewModel.downloadProgress.removeObservers(holder as LifecycleOwner) (holder as HomeChildRVAdapter.ViewHolder).onDisappear() } } } super.onDetachedFromRecyclerView(recyclerView) } RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder( val viewHolder = ViewHolder( HomeChildListItemBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) return viewHolder } override fun onBindViewHolder(holder: ViewHolder, position: Int) { Loading @@ -141,9 +100,9 @@ class HomeChildRVAdapter( ) holder.itemView.findNavController().navigate(action) } when (homeApp.status) { Status.INSTALLED -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = true text = context.getString(R.string.open) Loading @@ -158,7 +117,6 @@ class HomeChildRVAdapter( } } Status.UPDATABLE -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { text = context.getString(R.string.update) setTextColor(Color.WHITE) Loading @@ -172,7 +130,6 @@ class HomeChildRVAdapter( } } Status.UNAVAILABLE -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { text = context.getString(R.string.install) setTextColor(context.getColor(R.color.colorAccent)) Loading @@ -198,22 +155,12 @@ class HomeChildRVAdapter( strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) appProgressViewModel.downloadProgress.observe(holder) { appProgressViewModel.viewModelScope.launch { val progress = appProgressViewModel.calculateProgress(homeApp, it) if (progress.second > 0 && progress.second <= progress.first) { text = "${((progress.second / progress.first.toDouble()) * 100).toInt()}%" } } } setOnClickListener { cancelDownload(homeApp) } } } Status.INSTALLING, Status.UNINSTALLING -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = false setTextColor(context.getColor(R.color.light_grey)) Loading @@ -226,7 +173,6 @@ class HomeChildRVAdapter( } } Status.BLOCKED -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.setOnClickListener { val errorMsg = when (user) { User.ANONYMOUS, Loading @@ -239,7 +185,6 @@ class HomeChildRVAdapter( } } Status.INSTALLATION_ISSUE -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { text = view.context.getString(R.string.retry) setTextColor(context.getColor(R.color.colorAccent)) Loading app/src/main/java/foundation/e/apps/home/model/HomeParentRVAdapter.kt +6 −3 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ package foundation.e.apps.home.model import android.view.LayoutInflater import android.view.ViewGroup import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.viewModelScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView Loading @@ -32,15 +33,16 @@ import foundation.e.apps.api.fused.data.FusedHome import foundation.e.apps.databinding.HomeParentListItemBinding import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.User import kotlinx.coroutines.launch class HomeParentRVAdapter( private val fusedAPIInterface: FusedAPIInterface, private val pkgManagerModule: PkgManagerModule, private val user: User, private val mainActivityViewModel: MainActivityViewModel, private val lifecycleOwner: LifecycleOwner, private val appProgressViewModel: AppProgressViewModel private val lifecycleOwner: LifecycleOwner ) : ListAdapter<FusedHome, HomeParentRVAdapter.ViewHolder>(FusedHomeDiffUtil()) { private val viewPool = RecyclerView.RecycledViewPool() Loading @@ -56,7 +58,8 @@ class HomeParentRVAdapter( override fun onBindViewHolder(holder: ViewHolder, position: Int) { val fusedHome = getItem(position) val homeChildRVAdapter = HomeChildRVAdapter(fusedAPIInterface, pkgManagerModule, user, appProgressViewModel) val homeChildRVAdapter = HomeChildRVAdapter(fusedAPIInterface, pkgManagerModule, user) homeChildRVAdapter.setData(fusedHome.list) holder.binding.titleTV.text = fusedHome.title Loading Loading
app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt +39 −2 Original line number Diff line number Diff line Loading @@ -19,15 +19,18 @@ package foundation.e.apps.applicationlist import android.os.Bundle import android.util.Log import android.view.View import android.widget.ImageView import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.findNavController import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.hilt.android.AndroidEntryPoint import foundation.e.apps.AppProgressViewModel import foundation.e.apps.MainActivityViewModel Loading @@ -37,8 +40,12 @@ import foundation.e.apps.api.fused.FusedAPIInterface import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.applicationlist.model.ApplicationListRVAdapter import foundation.e.apps.databinding.FragmentApplicationListBinding import foundation.e.apps.home.model.HomeChildRVAdapter import foundation.e.apps.manager.download.data.DownloadProgress import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.User import kotlinx.coroutines.launch import javax.inject.Inject @AndroidEntryPoint Loading Loading @@ -107,8 +114,7 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu it, pkgManagerModule, User.valueOf(mainActivityViewModel.userType.value ?: User.UNAVAILABLE.name), viewLifecycleOwner, appProgressViewModel viewLifecycleOwner ) } Loading @@ -117,6 +123,10 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu layoutManager = LinearLayoutManager(view?.context) } appProgressViewModel.downloadProgress.observe(viewLifecycleOwner) { updateProgressOfDownloadingItems(recyclerView, it) } viewModel.appListLiveData.observe(viewLifecycleOwner) { listAdapter?.setData(it) if (!isDownloadObserverAdded) { Loading @@ -141,6 +151,33 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu } } private fun updateProgressOfDownloadingItems( recyclerView: RecyclerView, it: DownloadProgress ) { val adapter = recyclerView.adapter as ApplicationListRVAdapter lifecycleScope.launch { adapter.currentList.forEach { fusedApp -> if (fusedApp.status == Status.DOWNLOADING) { val progress = appProgressViewModel.calculateProgress(fusedApp, it) val downloadProgress = ((progress.second / progress.first.toDouble()) * 100).toInt() Log.d( "HomeParentAdapter", "download progress of ===> ${fusedApp.name} : $downloadProgress" ) val viewHolder = recyclerView.findViewHolderForAdapterPosition( adapter.currentList.indexOf(fusedApp) ) viewHolder?.let { (viewHolder as ApplicationListRVAdapter.ViewHolder).binding.installButton.text = "$downloadProgress%" } } } } } override fun onPause() { isDownloadObserverAdded = false binding.shimmerLayout.stopShimmer() Loading
app/src/main/java/foundation/e/apps/applicationlist/model/ApplicationListRVAdapter.kt +5 −69 Original line number Diff line number Diff line Loading @@ -62,7 +62,6 @@ class ApplicationListRVAdapter( private val pkgManagerModule: PkgManagerModule, private val user: User, private val lifecycleOwner: LifecycleOwner, private val appProgressViewModel: AppProgressViewModel ) : ListAdapter<FusedApp, ApplicationListRVAdapter.ViewHolder>(ApplicationDiffUtil()) { private val TAG = ApplicationListRVAdapter::class.java.simpleName Loading @@ -76,54 +75,7 @@ class ApplicationListRVAdapter( .build() inner class ViewHolder(val binding: ApplicationListItemBinding) : RecyclerView.ViewHolder(binding.root), LifecycleOwner { private val lifecycleRegistry = LifecycleRegistry(this) init { lifecycleRegistry.currentState = Lifecycle.State.INITIALIZED } fun onAppear() { lifecycleRegistry.currentState = Lifecycle.State.RESUMED } fun onDisappear() { lifecycleRegistry.currentState = Lifecycle.State.DESTROYED } override fun getLifecycle(): Lifecycle { return lifecycleRegistry } } override fun onViewAttachedToWindow(holder: ViewHolder) { super.onViewAttachedToWindow(holder) Log.d(TAG, "onViewAttachedToWindow: Appeared: ${holder.absoluteAdapterPosition}") holder.onAppear() } override fun onViewDetachedFromWindow(holder: ViewHolder) { holder.onDisappear() Log.d(TAG, "onViewAttachedToWindow: Disappeared: ${holder.absoluteAdapterPosition}") super.onViewDetachedFromWindow(holder) } override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { Log.d(TAG, "onDetachedFromRecyclerView: ") for (i in 0..recyclerView.childCount) { val view = recyclerView.getChildAt(i) if (view != null) { val holder = recyclerView.getChildViewHolder(view) holder?.let { appProgressViewModel.downloadProgress.removeObservers(holder as LifecycleOwner) (holder as ViewHolder).onDisappear() } } } super.onDetachedFromRecyclerView(recyclerView) } RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder( Loading Loading @@ -206,16 +158,16 @@ class ApplicationListRVAdapter( } when (searchApp.status) { Status.INSTALLED -> { handleInstalled(view, searchApp, holder) handleInstalled(view, searchApp) } Status.UPDATABLE -> { handleUpdatable(view, searchApp) } Status.UNAVAILABLE -> { handleUnavailable(view, searchApp, holder) handleUnavailable(view, searchApp) } Status.QUEUED, Status.AWAITING, Status.DOWNLOADING -> { handleDownloading(view, searchApp, holder) handleDownloading(view, searchApp) } Status.INSTALLING, Status.UNINSTALLING -> { handleInstalling(view, holder) Loading @@ -224,7 +176,7 @@ class ApplicationListRVAdapter( handleBlocked(view) } Status.INSTALLATION_ISSUE -> { handleInstallationIssue(view, searchApp, holder) handleInstallationIssue(view, searchApp) } } Loading @@ -235,9 +187,7 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleInstallationIssue( view: View, searchApp: FusedApp, holder: ViewHolder ) { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = true text = view.context.getString(R.string.retry) Loading Loading @@ -318,7 +268,6 @@ class ApplicationListRVAdapter( } private fun ApplicationListItemBinding.handleInstalling(view: View, holder: ViewHolder) { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = false setTextColor(context.getColor(R.color.light_grey)) Loading @@ -331,7 +280,6 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleDownloading( view: View, searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true Loading @@ -340,14 +288,6 @@ class ApplicationListRVAdapter( backgroundTintList = ContextCompat.getColorStateList(view.context, android.R.color.transparent) strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) appProgressViewModel.downloadProgress.observe(holder) { appProgressViewModel.viewModelScope.launch { val progress = appProgressViewModel.calculateProgress(searchApp, it) if (progress.second > 0 && progress.second <= progress.first) { text = "${((progress.second / progress.first.toDouble()) * 100).toInt()}%" } } } setOnClickListener { cancelDownload(searchApp) } Loading @@ -357,7 +297,6 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleUnavailable( view: View, searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true Loading @@ -366,7 +305,6 @@ class ApplicationListRVAdapter( backgroundTintList = ContextCompat.getColorStateList(view.context, android.R.color.transparent) strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) appProgressViewModel.downloadProgress.removeObservers(holder) setOnClickListener { installApplication(searchApp, appIcon) } Loading @@ -392,7 +330,6 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleInstalled( view: View, searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true Loading @@ -400,7 +337,6 @@ class ApplicationListRVAdapter( setTextColor(Color.WHITE) backgroundTintList = ContextCompat.getColorStateList(view.context, R.color.colorAccent) strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) appProgressViewModel.downloadProgress.removeObservers(holder) setOnClickListener { context.startActivity(pkgManagerModule.getLaunchIntent(searchApp.package_name)) } Loading
app/src/main/java/foundation/e/apps/home/HomeFragment.kt +52 −1 Original line number Diff line number Diff line Loading @@ -24,8 +24,10 @@ import android.widget.ImageView import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.hilt.android.AndroidEntryPoint import foundation.e.apps.AppProgressViewModel import foundation.e.apps.MainActivityViewModel Loading @@ -33,9 +35,13 @@ import foundation.e.apps.R import foundation.e.apps.api.fused.FusedAPIInterface import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.databinding.FragmentHomeBinding import foundation.e.apps.home.model.HomeChildRVAdapter import foundation.e.apps.home.model.HomeParentRVAdapter import foundation.e.apps.manager.download.data.DownloadProgress import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.User import kotlinx.coroutines.launch import javax.inject.Inject @AndroidEntryPoint Loading Loading @@ -77,7 +83,7 @@ class HomeFragment : Fragment(R.layout.fragment_home), FusedAPIInterface { this, pkgManagerModule, User.valueOf(mainActivityViewModel.userType.value ?: User.UNAVAILABLE.name), mainActivityViewModel, viewLifecycleOwner, appProgressViewModel mainActivityViewModel, viewLifecycleOwner ) binding.parentRV.apply { Loading @@ -90,6 +96,51 @@ class HomeFragment : Fragment(R.layout.fragment_home), FusedAPIInterface { binding.shimmerLayout.visibility = View.GONE binding.parentRV.visibility = View.VISIBLE } appProgressViewModel.downloadProgress.observe(viewLifecycleOwner) { updateProgressOfDownloadingAppItemViews(homeParentRVAdapter, it) } } private fun updateProgressOfDownloadingAppItemViews( homeParentRVAdapter: HomeParentRVAdapter, downloadProgress: DownloadProgress ) { homeParentRVAdapter.currentList.forEach { fusedHome -> val viewHolder = binding.parentRV.findViewHolderForAdapterPosition( homeParentRVAdapter.currentList.indexOf(fusedHome) ) viewHolder?.let { parentViewHolder -> val childRV = (parentViewHolder as HomeParentRVAdapter.ViewHolder).binding.childRV val adapter = childRV.adapter as HomeChildRVAdapter findDownloadingItemsToShowProgress(adapter, downloadProgress, childRV) } } } private fun findDownloadingItemsToShowProgress( adapter: HomeChildRVAdapter, downloadProgress: DownloadProgress, childRV: RecyclerView ) { lifecycleScope.launch { adapter.currentList.forEach { fusedApp -> if (fusedApp.status == Status.DOWNLOADING) { val progress = appProgressViewModel.calculateProgress(fusedApp, downloadProgress) val downloadProgress = ((progress.second / progress.first.toDouble()) * 100).toInt() val childViewHolder = childRV.findViewHolderForAdapterPosition( adapter.currentList.indexOf(fusedApp) ) childViewHolder?.let { (childViewHolder as HomeChildRVAdapter.ViewHolder).binding.installButton.text = "$downloadProgress%" } } } } } override fun onResume() { Loading
app/src/main/java/foundation/e/apps/home/model/HomeChildRVAdapter.kt +6 −61 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package foundation.e.apps.home.model import android.graphics.Color import android.util.Log import android.view.LayoutInflater import android.view.ViewGroup import android.widget.ImageView Loading Loading @@ -50,8 +51,7 @@ import kotlinx.coroutines.launch class HomeChildRVAdapter( private val fusedAPIInterface: FusedAPIInterface, private val pkgManagerModule: PkgManagerModule, private val user: User, private val appProgressViewModel: AppProgressViewModel private val user: User ) : ListAdapter<FusedApp, HomeChildRVAdapter.ViewHolder>(HomeChildFusedAppDiffUtil()) { private val shimmer = Shimmer.ColorHighlightBuilder() Loading @@ -63,58 +63,17 @@ class HomeChildRVAdapter( .build() inner class ViewHolder(val binding: HomeChildListItemBinding) : RecyclerView.ViewHolder(binding.root), LifecycleOwner { private val lifecycleRegistry = LifecycleRegistry(this) init { lifecycleRegistry.currentState = Lifecycle.State.INITIALIZED } fun onAppear() { lifecycleRegistry.currentState = Lifecycle.State.RESUMED } fun onDisappear() { lifecycleRegistry.currentState = Lifecycle.State.DESTROYED } override fun getLifecycle(): Lifecycle { return lifecycleRegistry } } override fun onViewAttachedToWindow(holder: HomeChildRVAdapter.ViewHolder) { super.onViewAttachedToWindow(holder) holder.onAppear() } override fun onViewDetachedFromWindow(holder: HomeChildRVAdapter.ViewHolder) { holder.onDisappear() super.onViewDetachedFromWindow(holder) } override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { for (i in 0..recyclerView.childCount) { val view = recyclerView.getChildAt(i) if (view != null) { val holder = recyclerView.getChildViewHolder(view) holder?.let { appProgressViewModel.downloadProgress.removeObservers(holder as LifecycleOwner) (holder as HomeChildRVAdapter.ViewHolder).onDisappear() } } } super.onDetachedFromRecyclerView(recyclerView) } RecyclerView.ViewHolder(binding.root) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder( val viewHolder = ViewHolder( HomeChildListItemBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) return viewHolder } override fun onBindViewHolder(holder: ViewHolder, position: Int) { Loading @@ -141,9 +100,9 @@ class HomeChildRVAdapter( ) holder.itemView.findNavController().navigate(action) } when (homeApp.status) { Status.INSTALLED -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = true text = context.getString(R.string.open) Loading @@ -158,7 +117,6 @@ class HomeChildRVAdapter( } } Status.UPDATABLE -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { text = context.getString(R.string.update) setTextColor(Color.WHITE) Loading @@ -172,7 +130,6 @@ class HomeChildRVAdapter( } } Status.UNAVAILABLE -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { text = context.getString(R.string.install) setTextColor(context.getColor(R.color.colorAccent)) Loading @@ -198,22 +155,12 @@ class HomeChildRVAdapter( strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) appProgressViewModel.downloadProgress.observe(holder) { appProgressViewModel.viewModelScope.launch { val progress = appProgressViewModel.calculateProgress(homeApp, it) if (progress.second > 0 && progress.second <= progress.first) { text = "${((progress.second / progress.first.toDouble()) * 100).toInt()}%" } } } setOnClickListener { cancelDownload(homeApp) } } } Status.INSTALLING, Status.UNINSTALLING -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = false setTextColor(context.getColor(R.color.light_grey)) Loading @@ -226,7 +173,6 @@ class HomeChildRVAdapter( } } Status.BLOCKED -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.setOnClickListener { val errorMsg = when (user) { User.ANONYMOUS, Loading @@ -239,7 +185,6 @@ class HomeChildRVAdapter( } } Status.INSTALLATION_ISSUE -> { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { text = view.context.getString(R.string.retry) setTextColor(context.getColor(R.color.colorAccent)) Loading
app/src/main/java/foundation/e/apps/home/model/HomeParentRVAdapter.kt +6 −3 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ package foundation.e.apps.home.model import android.view.LayoutInflater import android.view.ViewGroup import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.viewModelScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView Loading @@ -32,15 +33,16 @@ import foundation.e.apps.api.fused.data.FusedHome import foundation.e.apps.databinding.HomeParentListItemBinding import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.User import kotlinx.coroutines.launch class HomeParentRVAdapter( private val fusedAPIInterface: FusedAPIInterface, private val pkgManagerModule: PkgManagerModule, private val user: User, private val mainActivityViewModel: MainActivityViewModel, private val lifecycleOwner: LifecycleOwner, private val appProgressViewModel: AppProgressViewModel private val lifecycleOwner: LifecycleOwner ) : ListAdapter<FusedHome, HomeParentRVAdapter.ViewHolder>(FusedHomeDiffUtil()) { private val viewPool = RecyclerView.RecycledViewPool() Loading @@ -56,7 +58,8 @@ class HomeParentRVAdapter( override fun onBindViewHolder(holder: ViewHolder, position: Int) { val fusedHome = getItem(position) val homeChildRVAdapter = HomeChildRVAdapter(fusedAPIInterface, pkgManagerModule, user, appProgressViewModel) val homeChildRVAdapter = HomeChildRVAdapter(fusedAPIInterface, pkgManagerModule, user) homeChildRVAdapter.setData(fusedHome.list) holder.binding.titleTV.text = fusedHome.title Loading