Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4e3c6a2 authored by Hasib Prince's avatar Hasib Prince
Browse files

App lounge: showing percentage strategy app list

Showing percentage strategy is changed. lifecycle awrare list item views are removed as they are error prone and creates memory leaks

fixed showing percentage from different category of homepage
fixed livedata isActive issue due to job cancellation
refactoring
parent e2388fbc
Loading
Loading
Loading
Loading
Loading
+39 −2
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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
                )
            }

@@ -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) {
@@ -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()
+5 −69
Original line number Diff line number Diff line
@@ -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
@@ -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(
@@ -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)
@@ -224,7 +176,7 @@ class ApplicationListRVAdapter(
                    handleBlocked(view)
                }
                Status.INSTALLATION_ISSUE -> {
                    handleInstallationIssue(view, searchApp, holder)
                    handleInstallationIssue(view, searchApp)
                }
            }

@@ -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)
@@ -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))
@@ -331,7 +280,6 @@ class ApplicationListRVAdapter(
    private fun ApplicationListItemBinding.handleDownloading(
        view: View,
        searchApp: FusedApp,
        holder: ViewHolder
    ) {
        installButton.apply {
            isEnabled = true
@@ -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)
            }
@@ -357,7 +297,6 @@ class ApplicationListRVAdapter(
    private fun ApplicationListItemBinding.handleUnavailable(
        view: View,
        searchApp: FusedApp,
        holder: ViewHolder
    ) {
        installButton.apply {
            isEnabled = true
@@ -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)
            }
@@ -392,7 +330,6 @@ class ApplicationListRVAdapter(
    private fun ApplicationListItemBinding.handleInstalled(
        view: View,
        searchApp: FusedApp,
        holder: ViewHolder
    ) {
        installButton.apply {
            isEnabled = true
@@ -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))
            }
+51 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ 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
@@ -34,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
@@ -78,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 {
@@ -91,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() {
+2 −26
Original line number Diff line number Diff line
@@ -51,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()
@@ -64,30 +63,7 @@ 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 onCreated() {
            lifecycleRegistry.currentState = Lifecycle.State.CREATED
        }

        fun onAppear() {
            lifecycleRegistry.currentState = Lifecycle.State.STARTED
            lifecycleRegistry.currentState = Lifecycle.State.RESUMED
        }

        fun onDisappear() {
            lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
        }

        override fun getLifecycle(): Lifecycle {
            return lifecycleRegistry
        }
    }
        RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val viewHolder = ViewHolder(
+2 −24
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@

package foundation.e.apps.home.model

import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.lifecycle.LifecycleOwner
@@ -43,8 +42,7 @@ class HomeParentRVAdapter(
    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()
@@ -61,7 +59,7 @@ class HomeParentRVAdapter(
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val fusedHome = getItem(position)
        val homeChildRVAdapter =
            HomeChildRVAdapter(fusedAPIInterface, pkgManagerModule, user, appProgressViewModel)
            HomeChildRVAdapter(fusedAPIInterface, pkgManagerModule, user)
        homeChildRVAdapter.setData(fusedHome.list)

        holder.binding.titleTV.text = fusedHome.title
@@ -76,26 +74,6 @@ class HomeParentRVAdapter(
                )
            setRecycledViewPool(viewPool)
        }

        appProgressViewModel.downloadProgress.observe(lifecycleOwner) {
            val childRV = holder.binding.childRV
            val adapter = childRV.adapter as HomeChildRVAdapter
            appProgressViewModel.viewModelScope.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 = childRV.findViewHolderForAdapterPosition(adapter.currentList.indexOf(fusedApp))
                        viewHolder?.let {
                            (viewHolder as HomeChildRVAdapter.ViewHolder).binding.installButton.text = "$downloadProgress%"
                        }
                    }
                }

            }
        }
        observeAppInstall(fusedHome, homeChildRVAdapter)
    }

Loading