diff --git a/app/src/main/java/com/stevesoltys/seedvault/NotificationBackupObserver.kt b/app/src/main/java/com/stevesoltys/seedvault/NotificationBackupObserver.kt index 5a8bcda3..94757671 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/NotificationBackupObserver.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/NotificationBackupObserver.kt @@ -72,5 +72,5 @@ class NotificationBackupObserver(context: Context, private val userInitiated: Bo fun getAppName(pm: PackageManager, packageId: String): CharSequence { if (packageId == MAGIC_PACKAGE_MANAGER) return packageId val appInfo = pm.getApplicationInfo(packageId, 0) - return pm.getApplicationLabel(appInfo) + return pm.getApplicationLabel(appInfo) ?: packageId } diff --git a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreProgressAdapter.kt b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreProgressAdapter.kt new file mode 100644 index 00000000..76b27c9f --- /dev/null +++ b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreProgressAdapter.kt @@ -0,0 +1,78 @@ +package com.stevesoltys.seedvault.restore + +import android.view.LayoutInflater +import android.view.View +import android.view.View.INVISIBLE +import android.view.View.VISIBLE +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.ProgressBar +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView.Adapter +import androidx.recyclerview.widget.RecyclerView.ViewHolder +import com.stevesoltys.seedvault.MAGIC_PACKAGE_MANAGER +import com.stevesoltys.seedvault.R +import com.stevesoltys.seedvault.getAppName +import com.stevesoltys.seedvault.restore.RestoreProgressAdapter.PackageViewHolder +import java.util.* + +internal class RestoreProgressAdapter : Adapter() { + + private val items = LinkedList().apply { add(MAGIC_PACKAGE_MANAGER) } + private var isComplete = false + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PackageViewHolder { + val v = LayoutInflater.from(parent.context).inflate(R.layout.list_item_app_status, parent, false) + return PackageViewHolder(v) + } + + override fun getItemCount() = items.size + + override fun onBindViewHolder(holder: PackageViewHolder, position: Int) { + holder.bind(items[position], position == 0) + } + + fun add(packageName: String) { + items.addFirst(packageName) + notifyItemInserted(0) + notifyItemRangeChanged(1, items.size - 1) + } + + fun setComplete() { + isComplete = true + notifyItemChanged(0) + } + + inner class PackageViewHolder(v: View) : ViewHolder(v) { + + private val context = v.context + private val pm = context.packageManager + private val appIcon: ImageView = v.findViewById(R.id.appIcon) + private val appName: TextView = v.findViewById(R.id.appName) + private val appStatus: ImageView = v.findViewById(R.id.appStatus) + private val progressBar: ProgressBar = v.findViewById(R.id.progressBar) + + init { + appStatus.setImageResource(R.drawable.ic_check_green) + } + + fun bind(item: String, isLast: Boolean) { + if (item == MAGIC_PACKAGE_MANAGER) { + appIcon.setImageDrawable(pm.getApplicationIcon("android")) + appName.text = context.getString(R.string.restore_magic_package) + } else { + appIcon.setImageDrawable(pm.getApplicationIcon(item)) + appName.text = getAppName(pm, item) + } + if (isLast && !isComplete) { + appStatus.visibility = INVISIBLE + progressBar.visibility = VISIBLE + } else { + appStatus.visibility = VISIBLE + progressBar.visibility = INVISIBLE + } + } + + } + +} diff --git a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreProgressFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreProgressFragment.kt index cd877a7b..f4fed4c1 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreProgressFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreProgressFragment.kt @@ -4,16 +4,15 @@ import android.app.Activity.RESULT_OK import android.os.Bundle import android.view.LayoutInflater import android.view.View -import android.view.View.INVISIBLE -import android.view.View.VISIBLE import android.view.ViewGroup import android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON import androidx.core.content.ContextCompat.getColor import androidx.fragment.app.Fragment import androidx.lifecycle.Observer +import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL import com.stevesoltys.seedvault.R -import com.stevesoltys.seedvault.getAppName -import com.stevesoltys.seedvault.isDebugBuild import kotlinx.android.synthetic.main.fragment_restore_progress.* import org.koin.androidx.viewmodel.ext.android.sharedViewModel @@ -21,11 +20,27 @@ class RestoreProgressFragment : Fragment() { private val viewModel: RestoreViewModel by sharedViewModel() + private val layoutManager = LinearLayoutManager(context) + private val adapter = RestoreProgressAdapter() + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_restore_progress, container, false) } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + appList.apply { + layoutManager = this@RestoreProgressFragment.layoutManager + adapter = this@RestoreProgressFragment.adapter + addItemDecoration(DividerItemDecoration(context, VERTICAL)) + } + + button.setOnClickListener { + requireActivity().setResult(RESULT_OK) + requireActivity().finishAfterTransition() + } + } + override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) @@ -37,27 +52,23 @@ class RestoreProgressFragment : Fragment() { }) viewModel.restoreProgress.observe(this, Observer { currentPackage -> - val appName = getAppName(requireActivity().packageManager, currentPackage) - val displayName = if (isDebugBuild()) "$appName (${currentPackage})" else appName - currentPackageView.text = getString(R.string.restore_current_package, displayName) + // TODO maybe check against metadata and add packages that weren't called as failed in the end + val position = layoutManager.findFirstVisibleItemPosition() + adapter.add(currentPackage) + if (position == 0) layoutManager.scrollToPosition(0) }) viewModel.restoreBackupResult.observe(this, Observer { finished -> - progressBar.visibility = INVISIBLE - button.visibility = VISIBLE + adapter.setComplete() + button.isEnabled = true if (finished.hasError()) { - currentPackageView.text = finished.errorMsg - currentPackageView.setTextColor(getColor(requireContext(), R.color.red)) + backupNameView.text = finished.errorMsg + backupNameView.setTextColor(getColor(requireContext(), R.color.red)) } else { - currentPackageView.text = getString(R.string.restore_finished_success) + backupNameView.text = getString(R.string.restore_finished_success) } activity?.window?.clearFlags(FLAG_KEEP_SCREEN_ON) }) - - button.setOnClickListener { - requireActivity().setResult(RESULT_OK) - requireActivity().finishAfterTransition() - } } } diff --git a/app/src/main/res/layout/fragment_restore_progress.xml b/app/src/main/res/layout/fragment_restore_progress.xml index 1ffbe413..bc876533 100644 --- a/app/src/main/res/layout/fragment_restore_progress.xml +++ b/app/src/main/res/layout/fragment_restore_progress.xml @@ -41,30 +41,16 @@ app:layout_constraintTop_toBottomOf="@+id/titleView" tools:text="Pixel 2 XL" /> - - - + tools:listitem="@layout/list_item_app_status" />