forked from MarcoBuster/Magisk
123 lines
4.1 KiB
Kotlin
123 lines
4.1 KiB
Kotlin
package com.topjohnwu.magisk.ui.flash
|
|
|
|
import android.net.Uri
|
|
import android.view.MenuItem
|
|
import androidx.databinding.Bindable
|
|
import androidx.lifecycle.LiveData
|
|
import androidx.lifecycle.MutableLiveData
|
|
import androidx.lifecycle.viewModelScope
|
|
import com.topjohnwu.magisk.BR
|
|
import com.topjohnwu.magisk.R
|
|
import com.topjohnwu.magisk.arch.BaseViewModel
|
|
import com.topjohnwu.magisk.arch.diffListOf
|
|
import com.topjohnwu.magisk.arch.itemBindingOf
|
|
import com.topjohnwu.magisk.core.Const
|
|
import com.topjohnwu.magisk.core.Info
|
|
import com.topjohnwu.magisk.core.tasks.FlashZip
|
|
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
|
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
|
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
|
import com.topjohnwu.magisk.databinding.RvBindingAdapter
|
|
import com.topjohnwu.magisk.events.SnackbarEvent
|
|
import com.topjohnwu.magisk.ktx.*
|
|
import com.topjohnwu.magisk.utils.set
|
|
import com.topjohnwu.magisk.view.Notifications
|
|
import com.topjohnwu.superuser.CallbackList
|
|
import com.topjohnwu.superuser.Shell
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.launch
|
|
|
|
class FlashViewModel(args: FlashFragmentArgs) : BaseViewModel() {
|
|
|
|
@get:Bindable
|
|
var showReboot = Shell.rootAccess()
|
|
set(value) = set(value, field, { field = it }, BR.showReboot)
|
|
|
|
private val _subtitle = MutableLiveData(R.string.flashing)
|
|
val subtitle get() = _subtitle as LiveData<Int>
|
|
|
|
val adapter = RvBindingAdapter<ConsoleItem>()
|
|
val items = diffListOf<ConsoleItem>()
|
|
val itemBinding = itemBindingOf<ConsoleItem>()
|
|
|
|
private val logItems = mutableListOf<String>().synchronized()
|
|
private val outItems = object : CallbackList<String>() {
|
|
override fun onAddElement(e: String?) {
|
|
e ?: return
|
|
items.add(ConsoleItem(e))
|
|
logItems.add(e)
|
|
}
|
|
}
|
|
|
|
init {
|
|
val (action, uri, id) = args
|
|
if (id != -1)
|
|
Notifications.mgr.cancel(id)
|
|
startFlashing(action, uri)
|
|
}
|
|
|
|
private fun startFlashing(action: String, uri: Uri?) {
|
|
viewModelScope.launch {
|
|
val result = when (action) {
|
|
Const.Value.FLASH_ZIP -> {
|
|
FlashZip(uri!!, outItems, logItems).exec()
|
|
}
|
|
Const.Value.UNINSTALL -> {
|
|
showReboot = false
|
|
MagiskInstaller.Uninstall(outItems, logItems).exec()
|
|
}
|
|
Const.Value.FLASH_MAGISK -> {
|
|
if (Info.isEmulator)
|
|
MagiskInstaller.Emulator(outItems, logItems).exec()
|
|
else
|
|
MagiskInstaller.Direct(outItems, logItems).exec()
|
|
}
|
|
Const.Value.FLASH_INACTIVE_SLOT -> {
|
|
MagiskInstaller.SecondSlot(outItems, logItems).exec()
|
|
}
|
|
Const.Value.PATCH_FILE -> {
|
|
uri ?: return@launch
|
|
showReboot = false
|
|
MagiskInstaller.Patch(uri, outItems, logItems).exec()
|
|
}
|
|
else -> {
|
|
back()
|
|
return@launch
|
|
}
|
|
}
|
|
onResult(result)
|
|
}
|
|
}
|
|
|
|
private fun onResult(success: Boolean) {
|
|
state = if (success) State.LOADED else State.LOADING_FAILED
|
|
when {
|
|
success -> _subtitle.postValue(R.string.done)
|
|
else -> _subtitle.postValue(R.string.failure)
|
|
}
|
|
}
|
|
|
|
fun onMenuItemClicked(item: MenuItem): Boolean {
|
|
when (item.itemId) {
|
|
R.id.action_save -> savePressed()
|
|
}
|
|
return true
|
|
}
|
|
|
|
private fun savePressed() = withExternalRW {
|
|
viewModelScope.launch(Dispatchers.IO) {
|
|
val name = "magisk_install_log_%s.log".format(now.toTime(timeFormatStandard))
|
|
val file = MediaStoreUtils.getFile(name, true)
|
|
file.uri.outputStream().bufferedWriter().use { writer ->
|
|
logItems.forEach {
|
|
writer.write(it)
|
|
writer.newLine()
|
|
}
|
|
}
|
|
SnackbarEvent(file.toString()).publish()
|
|
}
|
|
}
|
|
|
|
fun restartPressed() = reboot()
|
|
}
|