Loading app/src/main/java/foundation/e/apps/AppProgressViewModel.kt +13 −6 Original line number Diff line number Diff line Loading @@ -2,7 +2,6 @@ package foundation.e.apps import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel import foundation.e.apps.api.fused.FusedAPIRepository import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.manager.download.data.DownloadProgress import foundation.e.apps.manager.download.data.DownloadProgressLD Loading @@ -17,16 +16,24 @@ class AppProgressViewModel @Inject constructor( val downloadProgress = downloadProgressLD suspend fun calculateProgress(fusedApp: FusedApp?, progress: DownloadProgress): Pair<Long, Long> { suspend fun calculateProgress( fusedApp: FusedApp?, progress: DownloadProgress ): Pair<Long, Long> { fusedApp?.let { app -> val appDownload = fusedManagerRepository.getDownloadList() .singleOrNull { it.id.contentEquals(app._id) } .singleOrNull { it.id.contentEquals(app._id) && it.package_name.contentEquals(app.package_name) } ?: return Pair(1, 0) if (!appDownload.id.contentEquals(app._id) || !appDownload.package_name.contentEquals(app.package_name)) { return@let } val downloadingMap = progress.totalSizeBytes.filter { item -> appDownload?.downloadIdMap?.keys?.contains(item.key) == true appDownload.downloadIdMap.keys.contains(item.key) } val totalSizeBytes = downloadingMap.values.sum() val downloadedSoFar = progress.bytesDownloadedSoFar.filter { item -> appDownload?.downloadIdMap?.keys?.contains(item.key) == true appDownload.downloadIdMap.keys.contains(item.key) }.values.sum() return Pair(totalSizeBytes, downloadedSoFar) Loading app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt +12 −4 Original line number Diff line number Diff line Loading @@ -261,7 +261,7 @@ class ApplicationFragment : Fragment(R.layout.fragment_application) { val fusedApp = applicationViewModel.fusedApp.value ?: FusedApp() when (status) { Status.INSTALLED -> handleInstalled(installButton, view, fusedApp) Status.INSTALLED -> handleInstalled(installButton, view, fusedApp, downloadPB, appSize) Status.UPDATABLE -> handleUpdatable( installButton, view, Loading @@ -270,7 +270,7 @@ class ApplicationFragment : Fragment(R.layout.fragment_application) { appSize ) Status.UNAVAILABLE -> handleUnavaiable(installButton, fusedApp, downloadPB, appSize) Status.QUEUED -> handleQueued(installButton, fusedApp) Status.QUEUED, Status.AWAITING -> handleQueued(installButton, fusedApp, downloadPB, appSize) Status.DOWNLOADING -> handleDownloading( installButton, fusedApp, Loading Loading @@ -367,8 +367,12 @@ class ApplicationFragment : Fragment(R.layout.fragment_application) { private fun handleQueued( installButton: MaterialButton, fusedApp: FusedApp fusedApp: FusedApp, downloadPB: RelativeLayout, appSize: MaterialTextView ) { downloadPB.visibility = View.GONE appSize.visibility = View.VISIBLE installButton.apply { text = getString(R.string.cancel) setOnClickListener { Loading Loading @@ -420,8 +424,12 @@ class ApplicationFragment : Fragment(R.layout.fragment_application) { private fun handleInstalled( installButton: MaterialButton, view: View, fusedApp: FusedApp fusedApp: FusedApp, downloadPB: RelativeLayout, appSize: MaterialTextView ) { downloadPB.visibility = View.GONE appSize.visibility = View.VISIBLE installButton.apply { isEnabled = true text = getString(R.string.open) Loading app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt +42 −36 Original line number Diff line number Diff line Loading @@ -56,21 +56,10 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu private var _binding: FragmentApplicationListBinding? = null private val binding get() = _binding!! private var isDownloadObserverAdded = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mainActivityViewModel.internetConnection.observe(this) { isInternetConnection -> mainActivityViewModel.authData.value?.let { authData -> if (isInternetConnection) { viewModel.getList( args.category, args.browseUrl, authData, args.source ) } } } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { Loading @@ -83,8 +72,33 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu view.findNavController().navigate(R.id.categoriesFragment) } } } private fun observeDownloadList() { mainActivityViewModel.downloadList.observe(viewLifecycleOwner) { list -> val categoryList = viewModel.appListLiveData.value?.toMutableList() if (!categoryList.isNullOrEmpty()) { list.forEach { categoryList.find { app -> app.origin == it.origin && (app.package_name == it.package_name || app._id == it.id) }?.status = it.status } viewModel.appListLiveData.value = categoryList } } } override fun onDestroyView() { super.onDestroyView() _binding = null } override fun onResume() { super.onResume() binding.shimmerLayout.startShimmer() val recyclerView = binding.recyclerView recyclerView.recycledViewPool.setMaxRecycledViews(0, 0) val listAdapter = findNavController().currentDestination?.id?.let { ApplicationListRVAdapter( Loading @@ -97,46 +111,38 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu appProgressViewModel ) } recyclerView.apply { adapter = listAdapter layoutManager = LinearLayoutManager(view.context) layoutManager = LinearLayoutManager(view?.context) } observeDownloadList() viewModel.appListLiveData.observe(viewLifecycleOwner) { listAdapter?.setData(it) if (!isDownloadObserverAdded) { observeDownloadList() isDownloadObserverAdded = true } binding.shimmerLayout.visibility = View.GONE recyclerView.visibility = View.VISIBLE } } private fun observeDownloadList() { mainActivityViewModel.downloadList.observe(viewLifecycleOwner) { list -> val categoryList = viewModel.appListLiveData.value?.toMutableList() if (!categoryList.isNullOrEmpty()) { list.forEach { categoryList.find { app -> app.origin == it.origin && (app.package_name == it.package_name || app._id == it.id) }?.status = it.status } viewModel.appListLiveData.value = categoryList mainActivityViewModel.internetConnection.observe(viewLifecycleOwner) { isInternetConnection -> mainActivityViewModel.authData.value?.let { authData -> if (isInternetConnection) { viewModel.getList( args.category, args.browseUrl, authData, args.source ) } } } override fun onDestroyView() { super.onDestroyView() _binding = null } override fun onResume() { super.onResume() binding.shimmerLayout.startShimmer() } override fun onPause() { isDownloadObserverAdded = false binding.shimmerLayout.stopShimmer() super.onPause() } Loading app/src/main/java/foundation/e/apps/applicationlist/ApplicationListViewModel.kt +9 −4 Original line number Diff line number Diff line Loading @@ -51,10 +51,15 @@ class ApplicationListViewModel @Inject constructor( source ).map { it.package_name } val applicationDetails = fusedAPIRepository.getApplicationDetails( val applicationDetails = if (!source.contentEquals("PWA")) { fusedAPIRepository.getApplicationDetails( packageNames, authData, getOrigin(source) ) } else { fusedAPIRepository.getAppsListBasedOnCategory(category, browseUrl, authData, source) } appListLiveData.postValue(applicationDetails) } } Loading app/src/main/java/foundation/e/apps/applicationlist/model/ApplicationListRVAdapter.kt +76 −16 Original line number Diff line number Diff line Loading @@ -25,7 +25,9 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView import androidx.core.content.ContextCompat import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import androidx.lifecycle.viewModelScope import androidx.navigation.findNavController import androidx.recyclerview.widget.ListAdapter Loading @@ -41,7 +43,6 @@ import foundation.e.apps.R import foundation.e.apps.api.cleanapk.CleanAPKInterface import foundation.e.apps.api.fused.FusedAPIInterface import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.application.ApplicationViewModel import foundation.e.apps.applicationlist.ApplicationListFragmentDirections import foundation.e.apps.databinding.ApplicationListItemBinding import foundation.e.apps.manager.pkg.PkgManagerModule Loading Loading @@ -75,7 +76,54 @@ class ApplicationListRVAdapter( .build() inner class ViewHolder(val binding: ApplicationListItemBinding) : RecyclerView.ViewHolder(binding.root) 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) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder( Loading Loading @@ -156,28 +204,27 @@ class ApplicationListRVAdapter( } else -> Log.wtf(TAG, "${searchApp.package_name} is from an unknown origin") } Log.d(TAG, "onBindViewHolder: ${searchApp.name} : ${searchApp.status}") when (searchApp.status) { Status.INSTALLED -> { handleInstalled(view, searchApp) handleInstalled(view, searchApp, holder) } Status.UPDATABLE -> { handleUpdatable(view, searchApp) } Status.UNAVAILABLE -> { handleUnavailable(view, searchApp) handleUnavailable(view, searchApp, holder) } Status.QUEUED, Status.AWAITING, Status.DOWNLOADING -> { handleDownloading(view, searchApp) handleDownloading(view, searchApp, holder) } Status.INSTALLING, Status.UNINSTALLING -> { handleInstalling(view) handleInstalling(view, holder) } Status.BLOCKED -> { handleBlocked(view) } Status.INSTALLATION_ISSUE -> { handleInstallationIssue(view, searchApp) handleInstallationIssue(view, searchApp, holder) } } Loading @@ -187,8 +234,10 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleInstallationIssue( view: View, searchApp: FusedApp searchApp: FusedApp, holder: ViewHolder ) { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = true text = view.context.getString(R.string.retry) Loading Loading @@ -268,7 +317,8 @@ class ApplicationListRVAdapter( appPrivacyScore.visibility = View.VISIBLE } private fun ApplicationListItemBinding.handleInstalling(view: View) { private fun ApplicationListItemBinding.handleInstalling(view: View, holder: ViewHolder) { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = false setTextColor(context.getColor(R.color.light_grey)) Loading @@ -278,7 +328,11 @@ class ApplicationListRVAdapter( } } private fun ApplicationListItemBinding.handleDownloading(view: View, searchApp: FusedApp) { private fun ApplicationListItemBinding.handleDownloading( view: View, searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true text = context.getString(R.string.cancel) Loading @@ -286,11 +340,10 @@ class ApplicationListRVAdapter( backgroundTintList = ContextCompat.getColorStateList(view.context, android.R.color.transparent) strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) appProgressViewModel.downloadProgress.observe(lifecycleOwner) { appProgressViewModel.downloadProgress.observe(holder) { appProgressViewModel.viewModelScope.launch { val progress = appProgressViewModel.calculateProgress(searchApp, it) Log.d(TAG, "app Progress: $progress") if(progress.second > 0) { if (progress.second > 0 && progress.second <= progress.first) { text = "${((progress.second / progress.first.toDouble()) * 100).toInt()}%" } } Loading @@ -301,7 +354,11 @@ class ApplicationListRVAdapter( } } private fun ApplicationListItemBinding.handleUnavailable(view: View, searchApp: FusedApp) { private fun ApplicationListItemBinding.handleUnavailable( view: View, searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true text = context.getString(R.string.install) Loading @@ -309,6 +366,7 @@ 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 @@ -333,7 +391,8 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleInstalled( view: View, searchApp: FusedApp searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true Loading @@ -341,6 +400,7 @@ 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 Loading
app/src/main/java/foundation/e/apps/AppProgressViewModel.kt +13 −6 Original line number Diff line number Diff line Loading @@ -2,7 +2,6 @@ package foundation.e.apps import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel import foundation.e.apps.api.fused.FusedAPIRepository import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.manager.download.data.DownloadProgress import foundation.e.apps.manager.download.data.DownloadProgressLD Loading @@ -17,16 +16,24 @@ class AppProgressViewModel @Inject constructor( val downloadProgress = downloadProgressLD suspend fun calculateProgress(fusedApp: FusedApp?, progress: DownloadProgress): Pair<Long, Long> { suspend fun calculateProgress( fusedApp: FusedApp?, progress: DownloadProgress ): Pair<Long, Long> { fusedApp?.let { app -> val appDownload = fusedManagerRepository.getDownloadList() .singleOrNull { it.id.contentEquals(app._id) } .singleOrNull { it.id.contentEquals(app._id) && it.package_name.contentEquals(app.package_name) } ?: return Pair(1, 0) if (!appDownload.id.contentEquals(app._id) || !appDownload.package_name.contentEquals(app.package_name)) { return@let } val downloadingMap = progress.totalSizeBytes.filter { item -> appDownload?.downloadIdMap?.keys?.contains(item.key) == true appDownload.downloadIdMap.keys.contains(item.key) } val totalSizeBytes = downloadingMap.values.sum() val downloadedSoFar = progress.bytesDownloadedSoFar.filter { item -> appDownload?.downloadIdMap?.keys?.contains(item.key) == true appDownload.downloadIdMap.keys.contains(item.key) }.values.sum() return Pair(totalSizeBytes, downloadedSoFar) Loading
app/src/main/java/foundation/e/apps/application/ApplicationFragment.kt +12 −4 Original line number Diff line number Diff line Loading @@ -261,7 +261,7 @@ class ApplicationFragment : Fragment(R.layout.fragment_application) { val fusedApp = applicationViewModel.fusedApp.value ?: FusedApp() when (status) { Status.INSTALLED -> handleInstalled(installButton, view, fusedApp) Status.INSTALLED -> handleInstalled(installButton, view, fusedApp, downloadPB, appSize) Status.UPDATABLE -> handleUpdatable( installButton, view, Loading @@ -270,7 +270,7 @@ class ApplicationFragment : Fragment(R.layout.fragment_application) { appSize ) Status.UNAVAILABLE -> handleUnavaiable(installButton, fusedApp, downloadPB, appSize) Status.QUEUED -> handleQueued(installButton, fusedApp) Status.QUEUED, Status.AWAITING -> handleQueued(installButton, fusedApp, downloadPB, appSize) Status.DOWNLOADING -> handleDownloading( installButton, fusedApp, Loading Loading @@ -367,8 +367,12 @@ class ApplicationFragment : Fragment(R.layout.fragment_application) { private fun handleQueued( installButton: MaterialButton, fusedApp: FusedApp fusedApp: FusedApp, downloadPB: RelativeLayout, appSize: MaterialTextView ) { downloadPB.visibility = View.GONE appSize.visibility = View.VISIBLE installButton.apply { text = getString(R.string.cancel) setOnClickListener { Loading Loading @@ -420,8 +424,12 @@ class ApplicationFragment : Fragment(R.layout.fragment_application) { private fun handleInstalled( installButton: MaterialButton, view: View, fusedApp: FusedApp fusedApp: FusedApp, downloadPB: RelativeLayout, appSize: MaterialTextView ) { downloadPB.visibility = View.GONE appSize.visibility = View.VISIBLE installButton.apply { isEnabled = true text = getString(R.string.open) Loading
app/src/main/java/foundation/e/apps/applicationlist/ApplicationListFragment.kt +42 −36 Original line number Diff line number Diff line Loading @@ -56,21 +56,10 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu private var _binding: FragmentApplicationListBinding? = null private val binding get() = _binding!! private var isDownloadObserverAdded = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mainActivityViewModel.internetConnection.observe(this) { isInternetConnection -> mainActivityViewModel.authData.value?.let { authData -> if (isInternetConnection) { viewModel.getList( args.category, args.browseUrl, authData, args.source ) } } } } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { Loading @@ -83,8 +72,33 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu view.findNavController().navigate(R.id.categoriesFragment) } } } private fun observeDownloadList() { mainActivityViewModel.downloadList.observe(viewLifecycleOwner) { list -> val categoryList = viewModel.appListLiveData.value?.toMutableList() if (!categoryList.isNullOrEmpty()) { list.forEach { categoryList.find { app -> app.origin == it.origin && (app.package_name == it.package_name || app._id == it.id) }?.status = it.status } viewModel.appListLiveData.value = categoryList } } } override fun onDestroyView() { super.onDestroyView() _binding = null } override fun onResume() { super.onResume() binding.shimmerLayout.startShimmer() val recyclerView = binding.recyclerView recyclerView.recycledViewPool.setMaxRecycledViews(0, 0) val listAdapter = findNavController().currentDestination?.id?.let { ApplicationListRVAdapter( Loading @@ -97,46 +111,38 @@ class ApplicationListFragment : Fragment(R.layout.fragment_application_list), Fu appProgressViewModel ) } recyclerView.apply { adapter = listAdapter layoutManager = LinearLayoutManager(view.context) layoutManager = LinearLayoutManager(view?.context) } observeDownloadList() viewModel.appListLiveData.observe(viewLifecycleOwner) { listAdapter?.setData(it) if (!isDownloadObserverAdded) { observeDownloadList() isDownloadObserverAdded = true } binding.shimmerLayout.visibility = View.GONE recyclerView.visibility = View.VISIBLE } } private fun observeDownloadList() { mainActivityViewModel.downloadList.observe(viewLifecycleOwner) { list -> val categoryList = viewModel.appListLiveData.value?.toMutableList() if (!categoryList.isNullOrEmpty()) { list.forEach { categoryList.find { app -> app.origin == it.origin && (app.package_name == it.package_name || app._id == it.id) }?.status = it.status } viewModel.appListLiveData.value = categoryList mainActivityViewModel.internetConnection.observe(viewLifecycleOwner) { isInternetConnection -> mainActivityViewModel.authData.value?.let { authData -> if (isInternetConnection) { viewModel.getList( args.category, args.browseUrl, authData, args.source ) } } } override fun onDestroyView() { super.onDestroyView() _binding = null } override fun onResume() { super.onResume() binding.shimmerLayout.startShimmer() } override fun onPause() { isDownloadObserverAdded = false binding.shimmerLayout.stopShimmer() super.onPause() } Loading
app/src/main/java/foundation/e/apps/applicationlist/ApplicationListViewModel.kt +9 −4 Original line number Diff line number Diff line Loading @@ -51,10 +51,15 @@ class ApplicationListViewModel @Inject constructor( source ).map { it.package_name } val applicationDetails = fusedAPIRepository.getApplicationDetails( val applicationDetails = if (!source.contentEquals("PWA")) { fusedAPIRepository.getApplicationDetails( packageNames, authData, getOrigin(source) ) } else { fusedAPIRepository.getAppsListBasedOnCategory(category, browseUrl, authData, source) } appListLiveData.postValue(applicationDetails) } } Loading
app/src/main/java/foundation/e/apps/applicationlist/model/ApplicationListRVAdapter.kt +76 −16 Original line number Diff line number Diff line Loading @@ -25,7 +25,9 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView import androidx.core.content.ContextCompat import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import androidx.lifecycle.viewModelScope import androidx.navigation.findNavController import androidx.recyclerview.widget.ListAdapter Loading @@ -41,7 +43,6 @@ import foundation.e.apps.R import foundation.e.apps.api.cleanapk.CleanAPKInterface import foundation.e.apps.api.fused.FusedAPIInterface import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.application.ApplicationViewModel import foundation.e.apps.applicationlist.ApplicationListFragmentDirections import foundation.e.apps.databinding.ApplicationListItemBinding import foundation.e.apps.manager.pkg.PkgManagerModule Loading Loading @@ -75,7 +76,54 @@ class ApplicationListRVAdapter( .build() inner class ViewHolder(val binding: ApplicationListItemBinding) : RecyclerView.ViewHolder(binding.root) 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) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder( Loading Loading @@ -156,28 +204,27 @@ class ApplicationListRVAdapter( } else -> Log.wtf(TAG, "${searchApp.package_name} is from an unknown origin") } Log.d(TAG, "onBindViewHolder: ${searchApp.name} : ${searchApp.status}") when (searchApp.status) { Status.INSTALLED -> { handleInstalled(view, searchApp) handleInstalled(view, searchApp, holder) } Status.UPDATABLE -> { handleUpdatable(view, searchApp) } Status.UNAVAILABLE -> { handleUnavailable(view, searchApp) handleUnavailable(view, searchApp, holder) } Status.QUEUED, Status.AWAITING, Status.DOWNLOADING -> { handleDownloading(view, searchApp) handleDownloading(view, searchApp, holder) } Status.INSTALLING, Status.UNINSTALLING -> { handleInstalling(view) handleInstalling(view, holder) } Status.BLOCKED -> { handleBlocked(view) } Status.INSTALLATION_ISSUE -> { handleInstallationIssue(view, searchApp) handleInstallationIssue(view, searchApp, holder) } } Loading @@ -187,8 +234,10 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleInstallationIssue( view: View, searchApp: FusedApp searchApp: FusedApp, holder: ViewHolder ) { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = true text = view.context.getString(R.string.retry) Loading Loading @@ -268,7 +317,8 @@ class ApplicationListRVAdapter( appPrivacyScore.visibility = View.VISIBLE } private fun ApplicationListItemBinding.handleInstalling(view: View) { private fun ApplicationListItemBinding.handleInstalling(view: View, holder: ViewHolder) { appProgressViewModel.downloadProgress.removeObservers(holder) installButton.apply { isEnabled = false setTextColor(context.getColor(R.color.light_grey)) Loading @@ -278,7 +328,11 @@ class ApplicationListRVAdapter( } } private fun ApplicationListItemBinding.handleDownloading(view: View, searchApp: FusedApp) { private fun ApplicationListItemBinding.handleDownloading( view: View, searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true text = context.getString(R.string.cancel) Loading @@ -286,11 +340,10 @@ class ApplicationListRVAdapter( backgroundTintList = ContextCompat.getColorStateList(view.context, android.R.color.transparent) strokeColor = ContextCompat.getColorStateList(view.context, R.color.colorAccent) appProgressViewModel.downloadProgress.observe(lifecycleOwner) { appProgressViewModel.downloadProgress.observe(holder) { appProgressViewModel.viewModelScope.launch { val progress = appProgressViewModel.calculateProgress(searchApp, it) Log.d(TAG, "app Progress: $progress") if(progress.second > 0) { if (progress.second > 0 && progress.second <= progress.first) { text = "${((progress.second / progress.first.toDouble()) * 100).toInt()}%" } } Loading @@ -301,7 +354,11 @@ class ApplicationListRVAdapter( } } private fun ApplicationListItemBinding.handleUnavailable(view: View, searchApp: FusedApp) { private fun ApplicationListItemBinding.handleUnavailable( view: View, searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true text = context.getString(R.string.install) Loading @@ -309,6 +366,7 @@ 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 @@ -333,7 +391,8 @@ class ApplicationListRVAdapter( private fun ApplicationListItemBinding.handleInstalled( view: View, searchApp: FusedApp searchApp: FusedApp, holder: ViewHolder ) { installButton.apply { isEnabled = true Loading @@ -341,6 +400,7 @@ 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