Skip to content

Commit a5bca88

Browse files
authored
app: reset install method when file picker or download dialog is cancelled
1 parent 999bda3 commit a5bca88

3 files changed

Lines changed: 55 additions & 5 deletions

File tree

app/apk/src/main/java/com/topjohnwu/magisk/dialog/DownloadDialog.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import com.topjohnwu.magisk.core.R
88
import com.topjohnwu.magisk.events.DialogBuilder
99
import com.topjohnwu.magisk.view.MagiskDialog
1010

11-
class DownloadDialog(private val callback: (Uri) -> Unit) : DialogBuilder {
11+
class DownloadDialog(
12+
private val callback: (Uri) -> Unit,
13+
private val onCancel: (() -> Unit)? = null,
14+
) : DialogBuilder {
1215

1316
override fun build(dialog: MagiskDialog) {
1417
val editText = EditText(dialog.context).apply {
@@ -17,6 +20,8 @@ class DownloadDialog(private val callback: (Uri) -> Unit) : DialogBuilder {
1720
requestFocus()
1821
}
1922

23+
var confirmed = false
24+
2025
dialog.apply {
2126
setTitle(R.string.download_dialog_title)
2227
setView(editText)
@@ -26,6 +31,7 @@ class DownloadDialog(private val callback: (Uri) -> Unit) : DialogBuilder {
2631
val url = editText.text.toString().trim()
2732
isValidUrl(url)?.let {
2833
doNotDismiss = false
34+
confirmed = true
2935
callback(it)
3036
} ?: run {
3137
doNotDismiss = true
@@ -37,6 +43,9 @@ class DownloadDialog(private val callback: (Uri) -> Unit) : DialogBuilder {
3743
text = android.R.string.cancel
3844
}
3945
setCancelable(true)
46+
setOnDismissListener {
47+
if (!confirmed) onCancel?.invoke()
48+
}
4049
}
4150
}
4251

app/apk/src/main/java/com/topjohnwu/magisk/ui/install/InstallViewModel.kt

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import android.widget.Toast
99
import androidx.databinding.Bindable
1010
import androidx.lifecycle.LiveData
1111
import androidx.lifecycle.MutableLiveData
12+
import androidx.lifecycle.Observer
1213
import androidx.lifecycle.viewModelScope
1314
import com.topjohnwu.magisk.BR
1415
import com.topjohnwu.magisk.R
@@ -46,31 +47,55 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
4647
set(value) = set(value, field, { field = it }, BR.step)
4748

4849
private var methodId = -1
50+
private var spuriousMethodId = -1
4951

5052
@get:Bindable
5153
var method
5254
get() = methodId
5355
set(value) = set(value, methodId, { methodId = it }, BR.method) {
56+
if (it == spuriousMethodId) {
57+
spuriousMethodId = -1
58+
return@set
59+
}
5460
when (it) {
5561
R.id.method_patch -> {
5662
GetContentEvent("*/*", UriCallback()).publish()
5763
}
5864
R.id.method_download -> {
59-
DownloadDialog { url -> uri.value = url }.show()
65+
DownloadDialog(
66+
callback = { url -> _uri.value = url },
67+
onCancel = { resetMethod() },
68+
).show()
6069
}
6170
R.id.method_inactive_slot -> {
6271
SecondSlotWarningDialog().show()
6372
}
6473
}
6574
}
6675

67-
val data: LiveData<Uri?> get() = uri
76+
private fun resetMethod() {
77+
spuriousMethodId = methodId
78+
method = -1
79+
}
80+
81+
private val _uri = MutableLiveData<Uri?>()
82+
val data: LiveData<Uri?> get() = _uri
83+
84+
private val sourceObserver = Observer<PatchSource?> { source ->
85+
when (source) {
86+
is PatchSource.File -> _uri.value = source.uri
87+
PatchSource.Cancelled -> resetMethod()
88+
null -> return@Observer
89+
}
90+
patchSource.value = null
91+
}
6892

6993
@get:Bindable
7094
var notes: Spanned = SpannedString("")
7195
set(value) = set(value, field, { field = it }, BR.notes)
7296

7397
init {
98+
patchSource.observeForever(sourceObserver)
7499
viewModelScope.launch(Dispatchers.IO) {
75100
try {
76101
val noteFile = File(AppContext.cacheDir, "${APP_VERSION_CODE}.md")
@@ -125,14 +150,28 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
125150
}
126151
}
127152

153+
override fun onCleared() {
154+
patchSource.removeObserver(sourceObserver)
155+
super.onCleared()
156+
}
157+
158+
private sealed interface PatchSource {
159+
data class File(val uri: Uri) : PatchSource
160+
data object Cancelled : PatchSource
161+
}
162+
128163
@Parcelize
129164
class UriCallback : ContentResultCallback {
130165
override fun onActivityLaunch() {
131166
AppContext.toast(CoreR.string.patch_file_msg, Toast.LENGTH_LONG)
132167
}
133168

134169
override fun onActivityResult(result: Uri) {
135-
uri.value = result
170+
patchSource.value = PatchSource.File(result)
171+
}
172+
173+
override fun onActivityCancel() {
174+
patchSource.value = PatchSource.Cancelled
136175
}
137176
}
138177

@@ -147,6 +186,6 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
147186

148187
companion object {
149188
private const val INSTALL_STATE_KEY = "install_state"
150-
private val uri = MutableLiveData<Uri?>()
189+
private val patchSource = MutableLiveData<PatchSource?>()
151190
}
152191
}

app/core/src/main/java/com/topjohnwu/magisk/core/base/BaseActivity.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.topjohnwu.magisk.core.utils.RequestInstall
2323

2424
interface ContentResultCallback: ActivityResultCallback<Uri>, Parcelable {
2525
fun onActivityLaunch() {}
26+
fun onActivityCancel() {}
2627
// Make the result type explicitly non-null
2728
override fun onActivityResult(result: Uri)
2829
}
@@ -65,6 +66,7 @@ class ActivityExtension(private val activity: ComponentActivity) {
6566
private var contentCallback: ContentResultCallback? = null
6667
private val getContent = activity.registerForActivityResult(GetContent()) {
6768
if (it != null) contentCallback?.onActivityResult(it)
69+
else contentCallback?.onActivityCancel()
6870
contentCallback = null
6971
}
7072

0 commit comments

Comments
 (0)