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.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewTreeObserver
import android.widget.Toast import android.widget.Toast
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import androidx.core.view.isVisible 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.arch.viewModel
import com.topjohnwu.magisk.core.ktx.toast import com.topjohnwu.magisk.core.ktx.toast
import com.topjohnwu.magisk.databinding.FragmentActionMd2Binding 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 import com.topjohnwu.magisk.core.R as CoreR
class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider { class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
@ -37,39 +36,32 @@ class ActionFragment : BaseFragment<FragmentActionMd2Binding>(), MenuProvider {
super.onStart() super.onStart()
activity?.setTitle(viewModel.args.name) activity?.setTitle(viewModel.args.name)
binding.closeBtn.setOnClickListener { binding.closeBtn.setOnClickListener {
activity?.onBackPressed(); activity?.onBackPressed()
} }
viewModel.state.observe(this) { viewModel.state.observe(this) {
activity?.supportActionBar?.setSubtitle( if (it != ActionViewModel.State.RUNNING) {
when (it) { binding.closeBtn.apply {
ActionViewModel.State.RUNNING -> CoreR.string.running if (!this.isVisible) this.show()
ActionViewModel.State.SUCCESS -> CoreR.string.done if (!this.isFocused) this.requestFocus()
ActionViewModel.State.FAILED -> CoreR.string.failure }
}
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 package com.topjohnwu.magisk.ui.module
import android.view.MenuItem import android.view.MenuItem
import androidx.databinding.Bindable
import androidx.databinding.ObservableArrayList import androidx.databinding.ObservableArrayList
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.map
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel 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.synchronized
import com.topjohnwu.magisk.core.ktx.timeFormatStandard import com.topjohnwu.magisk.core.ktx.timeFormatStandard
import com.topjohnwu.magisk.core.ktx.toTime 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
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import com.topjohnwu.magisk.databinding.set
import com.topjohnwu.magisk.events.SnackbarEvent import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.ui.flash.ConsoleItem import com.topjohnwu.magisk.ui.flash.ConsoleItem
import com.topjohnwu.superuser.CallbackList import com.topjohnwu.superuser.CallbackList
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.IOException
class ActionViewModel : BaseViewModel() { class ActionViewModel : BaseViewModel() {
@ -32,7 +30,6 @@ class ActionViewModel : BaseViewModel() {
private val _state = MutableLiveData(State.RUNNING) private val _state = MutableLiveData(State.RUNNING)
val state: LiveData<State> get() = _state val state: LiveData<State> get() = _state
val running = state.map { it == State.RUNNING }
val items = ObservableArrayList<ConsoleItem>() val items = ObservableArrayList<ConsoleItem>()
lateinit var args: ActionFragmentArgs lateinit var args: ActionFragmentArgs
@ -46,10 +43,17 @@ class ActionViewModel : BaseViewModel() {
} }
} }
fun startRunAction() { fun startRunAction() = viewModelScope.launch {
viewModelScope.launch { onResult(withContext(Dispatchers.IO) {
onResult(RunAction(args.id, outItems, logItems).exec()) try {
} Shell.cmd("run_action \'${args.id}\'")
.to(outItems, logItems)
.exec().isSuccess
} catch (e: IOException) {
Timber.e(e)
false
}
})
} }
private fun onResult(success: Boolean) { 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
}
}
}