-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
InstallProgressFragment.kt
150 lines (126 loc) · 5.5 KB
/
InstallProgressFragment.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package com.stevesoltys.seedvault.restore.install
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ProgressBar
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContract
import androidx.appcompat.app.AlertDialog
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 androidx.recyclerview.widget.RecyclerView
import com.stevesoltys.seedvault.R
import com.stevesoltys.seedvault.restore.RestoreViewModel
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
class InstallProgressFragment : Fragment(), InstallItemListener {
private val viewModel: RestoreViewModel by sharedViewModel()
private val layoutManager = LinearLayoutManager(context)
private val adapter = InstallProgressAdapter(this)
private lateinit var progressBar: ProgressBar
private lateinit var titleView: TextView
private lateinit var backupNameView: TextView
private lateinit var appList: RecyclerView
private lateinit var button: Button
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val v: View = inflater.inflate(R.layout.fragment_restore_progress, container, false)
progressBar = v.findViewById(R.id.progressBar)
titleView = v.findViewById(R.id.titleView)
backupNameView = v.findViewById(R.id.backupNameView)
appList = v.findViewById(R.id.appList)
button = v.findViewById(R.id.button)
return v
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
titleView.setText(R.string.restore_installing_packages)
appList.apply {
layoutManager = this@InstallProgressFragment.layoutManager
adapter = this@InstallProgressFragment.adapter
addItemDecoration(DividerItemDecoration(context, VERTICAL))
}
button.setText(R.string.restore_next)
button.setOnClickListener { viewModel.onNextClicked() }
viewModel.chosenRestorableBackup.observe(viewLifecycleOwner, Observer { restorableBackup ->
backupNameView.text = restorableBackup.name
})
viewModel.installResult.observe(viewLifecycleOwner, Observer { result ->
onInstallResult(result)
})
viewModel.nextButtonEnabled.observe(viewLifecycleOwner, Observer { enabled ->
button.isEnabled = enabled
})
}
private fun onInstallResult(installResult: InstallResult) {
// skip this screen, if there are no apps to install
if (installResult.isEmpty) viewModel.onNextClicked()
// if finished, treat all still queued apps as failed and resort/redisplay adapter items
if (installResult.isFinished) {
installResult.queuedToFailed()
adapter.setFinished()
}
// update progress bar
progressBar.progress = installResult.progress
progressBar.max = installResult.total
// just update adapter, or perform final action, if finished
if (installResult.isFinished) onFinished(installResult)
else updateAdapter(installResult.getNotQueued())
}
private fun onFinished(installResult: InstallResult) {
if (installResult.hasFailed) {
AlertDialog.Builder(requireContext())
.setIcon(R.drawable.ic_warning)
.setTitle(R.string.restore_installing_error_title)
.setMessage(R.string.restore_installing_error_message)
.setPositiveButton(android.R.string.ok) { dialog, _ ->
dialog.dismiss()
}
.setOnDismissListener {
updateAdapter(installResult.getNotQueued())
}
.show()
} else {
updateAdapter(installResult.getNotQueued())
}
}
private fun updateAdapter(items: Collection<ApkInstallResult>) {
val position = layoutManager.findFirstVisibleItemPosition()
adapter.update(items)
if (position == 0) layoutManager.scrollToPosition(0)
}
override fun onFailedItemClicked(item: ApkInstallResult) {
installAppLauncher.launch(item)
}
private val installAppLauncher = registerForActivityResult(InstallApp()) { packageName ->
val result = viewModel.installResult.value ?: return@registerForActivityResult
if (result.isFinished) {
val changed = result.reCheckFailedPackage(
requireContext().packageManager,
packageName.toString()
)
if (changed) adapter.update(result.getNotQueued())
}
}
private inner class InstallApp : ActivityResultContract<ApkInstallResult, CharSequence>() {
private lateinit var packageName: CharSequence
override fun createIntent(context: Context, input: ApkInstallResult): Intent {
packageName = input.packageName
return viewModel.installIntentCreator.getIntent(
input.packageName,
input.installerPackageName
)
}
override fun parseResult(resultCode: Int, intent: Intent?): CharSequence {
return packageName
}
}
}