app: auto close action fragment only when focus lost

This commit is contained in:
vvb2060 2024-10-22 18:23:29 +08:00 committed by John Wu
parent 7dbb973db5
commit 613f2d31c5
3 changed files with 37 additions and 83 deletions

View File

@ -8,6 +8,7 @@ import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewTreeObserver
import android.widget.Toast
import androidx.core.view.MenuProvider
import androidx.core.view.isVisible
@ -16,8 +17,6 @@ import com.topjohnwu.magisk.arch.BaseFragment
import com.topjohnwu.magisk.arch.viewModel
import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.databinding.FragmentActionMd2Binding
import com.topjohnwu.magisk.ui.flash.FlashViewModel
import timber.log.Timber
import com.topjohnwu.magisk.core.R as CoreR
class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
@ -37,39 +36,32 @@ class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
super.onStart()
activity?.setTitle(viewModel.args.name)
binding.closeBtn.setOnClickListener {
activity?.onBackPressed();
activity?.onBackPressed()
}
viewModel.state.observe(this) {
activity?.supportActionBar?.setSubtitle(
when (it) {
ActionViewModel.State.RUNNING -> CoreR.string.running
ActionViewModel.State.SUCCESS -> CoreR.string.done
ActionViewModel.State.FAILED -> CoreR.string.failure
if (it != ActionViewModel.State.RUNNING) {
binding.closeBtn.apply {
if (!this.isVisible) this.show()
if (!this.isFocused) this.requestFocus()
}
}
if (it != ActionViewModel.State.SUCCESS) return@observe
view?.viewTreeObserver?.addOnWindowFocusChangeListener(
object : ViewTreeObserver.OnWindowFocusChangeListener {
override fun onWindowFocusChanged(hasFocus: Boolean) {
if (hasFocus) return
view?.viewTreeObserver?.removeOnWindowFocusChangeListener(this)
view?.context?.apply {
toast(
getString(CoreR.string.done_action, viewModel.args.name),
Toast.LENGTH_SHORT
)
}
viewModel.back()
}
}
)
when (it) {
ActionViewModel.State.SUCCESS -> {
activity?.apply {
toast(
getString(
com.topjohnwu.magisk.core.R.string.done_action,
this@ActionFragment.viewModel.args.name
), Toast.LENGTH_LONG
)
onBackPressed()
}
}
ActionViewModel.State.FAILED -> {
binding.closeBtn.apply {
if (!this.isVisible) this.show()
if (!this.isFocused) this.requestFocus()
}
}
else -> {}
}
}
}

View File

@ -1,28 +1,26 @@
package com.topjohnwu.magisk.ui.module
import android.view.MenuItem
import androidx.databinding.Bindable
import androidx.databinding.ObservableArrayList
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.map
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.ktx.synchronized
import com.topjohnwu.magisk.core.ktx.timeFormatStandard
import com.topjohnwu.magisk.core.ktx.toTime
import com.topjohnwu.magisk.core.tasks.RunAction
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import com.topjohnwu.magisk.databinding.set
import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.ui.flash.ConsoleItem
import com.topjohnwu.superuser.CallbackList
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.IOException
class ActionViewModel : BaseViewModel() {
@ -32,7 +30,6 @@ class ActionViewModel : BaseViewModel() {
private val _state = MutableLiveData(State.RUNNING)
val state: LiveData<State> get() = _state
val running = state.map { it == State.RUNNING }
val items = ObservableArrayList<ConsoleItem>()
lateinit var args: ActionFragmentArgs
@ -46,10 +43,17 @@ class ActionViewModel : BaseViewModel() {
}
}
fun startRunAction() {
viewModelScope.launch {
onResult(RunAction(args.id, outItems, logItems).exec())
}
fun startRunAction() = viewModelScope.launch {
onResult(withContext(Dispatchers.IO) {
try {
Shell.cmd("run_action \'${args.id}\'")
.to(outItems, logItems)
.exec().isSuccess
} catch (e: IOException) {
Timber.e(e)
false
}
})
}
private fun onResult(success: Boolean) {

View File

@ -1,42 +0,0 @@
package com.topjohnwu.magisk.core.tasks
import android.net.Uri
import androidx.core.net.toFile
import com.topjohnwu.magisk.core.AppContext
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.ktx.writeTo
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.displayName
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.inputStream
import com.topjohnwu.magisk.core.utils.unzip
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.File
import java.io.FileNotFoundException
import java.io.IOException
open class RunAction(
private val module: String,
private val console: MutableList<String>,
private val logs: MutableList<String>
) {
@Throws(IOException::class)
private suspend fun run(): Boolean {
return Shell.cmd("run_action \'$module\'").to(console, logs).exec().isSuccess
}
open suspend fun exec() = withContext(Dispatchers.IO) {
try {
if (!run()) {
console.add("! Run action failed")
false
} else {
true
}
} catch (e: IOException) {
Timber.e(e)
false
}
}
}