mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-24 18:47:38 +00:00
Handle Activty recreation on content result
Credits to @canyie for the initial PR and finding the bug Close #5791, fix #5789
This commit is contained in:
parent
0469f0b5ae
commit
4eb9240806
@ -36,9 +36,14 @@ abstract class BaseFragment<Binding : ViewDataBinding> : Fragment(), ViewModelHo
|
|||||||
it.setVariable(BR.viewModel, viewModel)
|
it.setVariable(BR.viewModel, viewModel)
|
||||||
it.lifecycleOwner = viewLifecycleOwner
|
it.lifecycleOwner = viewLifecycleOwner
|
||||||
}
|
}
|
||||||
|
savedInstanceState?.let { viewModel.onRestoreState(it) }
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
viewModel.onSaveState(outState)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
activity?.supportActionBar?.subtitle = null
|
activity?.supportActionBar?.subtitle = null
|
||||||
|
@ -3,6 +3,7 @@ package com.topjohnwu.magisk.arch
|
|||||||
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
||||||
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.os.Bundle
|
||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import androidx.databinding.Observable
|
import androidx.databinding.Observable
|
||||||
@ -58,6 +59,9 @@ abstract class BaseViewModel(
|
|||||||
isConnected.addOnPropertyChangedCallback(refreshCallback)
|
isConnected.addOnPropertyChangedCallback(refreshCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun onSaveState(state: Bundle) {}
|
||||||
|
open fun onRestoreState(state: Bundle) {}
|
||||||
|
|
||||||
/** This should probably never be called manually, it's called manually via delegate. */
|
/** This should probably never be called manually, it's called manually via delegate. */
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun requestRefresh() {
|
fun requestRefresh() {
|
||||||
|
@ -2,25 +2,37 @@ package com.topjohnwu.magisk.core.base
|
|||||||
|
|
||||||
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
|
||||||
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Parcelable
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.result.ActivityResultCallback
|
||||||
import androidx.activity.result.contract.ActivityResultContracts.GetContent
|
import androidx.activity.result.contract.ActivityResultContracts.GetContent
|
||||||
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
|
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||||
import com.topjohnwu.magisk.core.utils.RequestInstall
|
import com.topjohnwu.magisk.core.utils.RequestInstall
|
||||||
import com.topjohnwu.magisk.core.utils.UninstallPackage
|
import com.topjohnwu.magisk.core.utils.UninstallPackage
|
||||||
import com.topjohnwu.magisk.core.utils.currentLocale
|
import com.topjohnwu.magisk.core.utils.currentLocale
|
||||||
import com.topjohnwu.magisk.core.wrap
|
import com.topjohnwu.magisk.core.wrap
|
||||||
import com.topjohnwu.magisk.ktx.reflectField
|
import com.topjohnwu.magisk.ktx.reflectField
|
||||||
|
import com.topjohnwu.magisk.utils.Utils
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
interface ContentResultCallback: ActivityResultCallback<Uri>, Parcelable {
|
||||||
|
fun onActivityLaunch() {}
|
||||||
|
// Make the result type explicitly non-null
|
||||||
|
override fun onActivityResult(result: Uri)
|
||||||
|
}
|
||||||
|
|
||||||
abstract class BaseActivity : AppCompatActivity() {
|
abstract class BaseActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private var permissionCallback: ((Boolean) -> Unit)? = null
|
private var permissionCallback: ((Boolean) -> Unit)? = null
|
||||||
@ -33,9 +45,9 @@ abstract class BaseActivity : AppCompatActivity() {
|
|||||||
permissionCallback = null
|
permissionCallback = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private var contentCallback: ((Uri) -> Unit)? = null
|
private var contentCallback: ContentResultCallback? = null
|
||||||
private val getContent = registerForActivityResult(GetContent()) {
|
private val getContent = registerForActivityResult(GetContent()) {
|
||||||
if (it != null) contentCallback?.invoke(it)
|
if (it != null) contentCallback?.onActivityResult(it)
|
||||||
contentCallback = null
|
contentCallback = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,9 +74,17 @@ abstract class BaseActivity : AppCompatActivity() {
|
|||||||
clz.reflectField("mActivityHandlesUiModeChecked").set(delegate, true)
|
clz.reflectField("mActivityHandlesUiModeChecked").set(delegate, true)
|
||||||
clz.reflectField("mActivityHandlesUiMode").set(delegate, false)
|
clz.reflectField("mActivityHandlesUiMode").set(delegate, false)
|
||||||
}
|
}
|
||||||
|
contentCallback = savedInstanceState?.getParcelable(CONTENT_CALLBACK_KEY)
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
contentCallback?.let {
|
||||||
|
outState.putParcelable(CONTENT_CALLBACK_KEY, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun withPermission(permission: String, callback: (Boolean) -> Unit) {
|
fun withPermission(permission: String, callback: (Boolean) -> Unit) {
|
||||||
if (permission == WRITE_EXTERNAL_STORAGE && Build.VERSION.SDK_INT >= 30) {
|
if (permission == WRITE_EXTERNAL_STORAGE && Build.VERSION.SDK_INT >= 30) {
|
||||||
// We do not need external rw on 30+
|
// We do not need external rw on 30+
|
||||||
@ -79,9 +99,14 @@ abstract class BaseActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getContent(type: String, callback: (Uri) -> Unit) {
|
fun getContent(type: String, callback: ContentResultCallback) {
|
||||||
contentCallback = callback
|
contentCallback = callback
|
||||||
getContent.launch(type)
|
try {
|
||||||
|
getContent.launch(type)
|
||||||
|
callback.onActivityLaunch()
|
||||||
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
Utils.toast(R.string.app_not_found, Toast.LENGTH_SHORT)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
@ -100,4 +125,8 @@ abstract class BaseActivity : AppCompatActivity() {
|
|||||||
startActivity(Intent(intent).setFlags(0))
|
startActivity(Intent(intent).setFlags(0))
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val CONTENT_CALLBACK_KEY = "content_callback"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,13 @@
|
|||||||
package com.topjohnwu.magisk.events
|
package com.topjohnwu.magisk.events
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.navigation.NavDirections
|
import androidx.navigation.NavDirections
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.topjohnwu.magisk.MainDirections
|
|
||||||
import com.topjohnwu.magisk.R
|
|
||||||
import com.topjohnwu.magisk.arch.*
|
import com.topjohnwu.magisk.arch.*
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.base.ContentResultCallback
|
||||||
import com.topjohnwu.magisk.utils.TextHolder
|
import com.topjohnwu.magisk.utils.TextHolder
|
||||||
import com.topjohnwu.magisk.utils.Utils
|
|
||||||
import com.topjohnwu.magisk.utils.asText
|
import com.topjohnwu.magisk.utils.asText
|
||||||
import com.topjohnwu.magisk.view.Shortcuts
|
import com.topjohnwu.magisk.view.Shortcuts
|
||||||
|
|
||||||
@ -52,16 +46,12 @@ class RecreateEvent : ViewEvent(), ActivityExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MagiskInstallFileEvent(
|
class GetContentEvent(
|
||||||
private val callback: (Uri) -> Unit
|
private val type: String,
|
||||||
|
private val callback: ContentResultCallback
|
||||||
) : ViewEvent(), ActivityExecutor {
|
) : ViewEvent(), ActivityExecutor {
|
||||||
override fun invoke(activity: UIActivity<*>) {
|
override fun invoke(activity: UIActivity<*>) {
|
||||||
try {
|
activity.getContent(type, callback)
|
||||||
activity.getContent("*/*", callback)
|
|
||||||
Utils.toast(R.string.patch_file_msg, Toast.LENGTH_LONG)
|
|
||||||
} catch (e: ActivityNotFoundException) {
|
|
||||||
Utils.toast(R.string.app_not_found, Toast.LENGTH_SHORT)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,20 +73,6 @@ class AddHomeIconEvent : ViewEvent(), ContextExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SelectModuleEvent : ViewEvent(), FragmentExecutor {
|
|
||||||
override fun invoke(fragment: BaseFragment<*>) {
|
|
||||||
try {
|
|
||||||
fragment.apply {
|
|
||||||
activity?.getContent("application/zip") {
|
|
||||||
MainDirections.actionFlashFragment(Const.Value.FLASH_ZIP, it).navigate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: ActivityNotFoundException) {
|
|
||||||
Utils.toast(R.string.app_not_found, Toast.LENGTH_SHORT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SnackbarEvent(
|
class SnackbarEvent(
|
||||||
private val msg: TextHolder,
|
private val msg: TextHolder,
|
||||||
private val length: Int = Snackbar.LENGTH_SHORT,
|
private val length: Int = Snackbar.LENGTH_SHORT,
|
||||||
|
@ -53,7 +53,8 @@ class FlashViewModel : BaseViewModel() {
|
|||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val result = when (action) {
|
val result = when (action) {
|
||||||
Const.Value.FLASH_ZIP -> {
|
Const.Value.FLASH_ZIP -> {
|
||||||
FlashZip(uri!!, outItems, logItems).exec()
|
uri ?: return@launch
|
||||||
|
FlashZip(uri, outItems, logItems).exec()
|
||||||
}
|
}
|
||||||
Const.Value.UNINSTALL -> {
|
Const.Value.UNINSTALL -> {
|
||||||
showReboot = false
|
showReboot = false
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
package com.topjohnwu.magisk.ui.install
|
package com.topjohnwu.magisk.ui.install
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.arch.BaseFragment
|
import com.topjohnwu.magisk.arch.BaseFragment
|
||||||
import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding
|
||||||
@ -18,21 +14,4 @@ class InstallFragment : BaseFragment<FragmentInstallMd2Binding>() {
|
|||||||
super.onStart()
|
super.onStart()
|
||||||
requireActivity().setTitle(R.string.install)
|
requireActivity().setTitle(R.string.install)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
viewModel._method = savedInstanceState?.getInt(KEY_CURRENT_METHOD, -1) ?: -1
|
|
||||||
return super.onCreateView(inflater, container, savedInstanceState)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
|
||||||
outState.putInt(KEY_CURRENT_METHOD, viewModel.method)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val KEY_CURRENT_METHOD = "current_method"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,34 @@
|
|||||||
package com.topjohnwu.magisk.ui.install
|
package com.topjohnwu.magisk.ui.install
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Parcelable
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.Spanned
|
import android.text.Spanned
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.BuildConfig
|
import com.topjohnwu.magisk.BuildConfig
|
||||||
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.Config
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
|
import com.topjohnwu.magisk.core.base.ContentResultCallback
|
||||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||||
import com.topjohnwu.magisk.databinding.set
|
import com.topjohnwu.magisk.databinding.set
|
||||||
import com.topjohnwu.magisk.di.AppContext
|
import com.topjohnwu.magisk.di.AppContext
|
||||||
import com.topjohnwu.magisk.di.ServiceLocator
|
import com.topjohnwu.magisk.di.ServiceLocator
|
||||||
import com.topjohnwu.magisk.events.MagiskInstallFileEvent
|
import com.topjohnwu.magisk.events.GetContentEvent
|
||||||
import com.topjohnwu.magisk.events.dialog.SecondSlotWarningDialog
|
import com.topjohnwu.magisk.events.dialog.SecondSlotWarningDialog
|
||||||
import com.topjohnwu.magisk.ui.flash.FlashFragment
|
import com.topjohnwu.magisk.ui.flash.FlashFragment
|
||||||
|
import com.topjohnwu.magisk.utils.Utils
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -37,15 +46,15 @@ class InstallViewModel(
|
|||||||
var step = if (skipOptions) 1 else 0
|
var step = if (skipOptions) 1 else 0
|
||||||
set(value) = set(value, field, { field = it }, BR.step)
|
set(value) = set(value, field, { field = it }, BR.step)
|
||||||
|
|
||||||
var _method = -1
|
private var methodId = -1
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var method
|
var method
|
||||||
get() = _method
|
get() = methodId
|
||||||
set(value) = set(value, _method, { _method = it }, BR.method) {
|
set(value) = set(value, methodId, { methodId = it }, BR.method) {
|
||||||
when (it) {
|
when (it) {
|
||||||
R.id.method_patch -> {
|
R.id.method_patch -> {
|
||||||
MagiskInstallFileEvent { uri -> data = uri }.publish()
|
GetContentEvent("*/*", UriCallback()).publish()
|
||||||
}
|
}
|
||||||
R.id.method_inactive_slot -> {
|
R.id.method_inactive_slot -> {
|
||||||
SecondSlotWarningDialog().publish()
|
SecondSlotWarningDialog().publish()
|
||||||
@ -53,9 +62,7 @@ class InstallViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:Bindable
|
val data: LiveData<Uri?> get() = uri
|
||||||
var data: Uri? = null
|
|
||||||
set(value) = set(value, field, { field = it }, BR.data)
|
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var notes: Spanned = SpannableStringBuilder()
|
var notes: Spanned = SpannableStringBuilder()
|
||||||
@ -81,17 +88,60 @@ class InstallViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun step(nextStep: Int) {
|
|
||||||
step = nextStep
|
|
||||||
}
|
|
||||||
|
|
||||||
fun install() {
|
fun install() {
|
||||||
when (method) {
|
when (method) {
|
||||||
R.id.method_patch -> FlashFragment.patch(data!!).navigate(true)
|
R.id.method_patch -> FlashFragment.patch(data.value!!).navigate(true)
|
||||||
R.id.method_direct -> FlashFragment.flash(false).navigate(true)
|
R.id.method_direct -> FlashFragment.flash(false).navigate(true)
|
||||||
R.id.method_inactive_slot -> FlashFragment.flash(true).navigate(true)
|
R.id.method_inactive_slot -> FlashFragment.flash(true).navigate(true)
|
||||||
else -> error("Unknown value")
|
else -> error("Unknown value")
|
||||||
}
|
}
|
||||||
state = State.LOADING
|
state = State.LOADING
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSaveState(state: Bundle) {
|
||||||
|
state.putParcelable(INSTALL_STATE_KEY, InstallState(
|
||||||
|
methodId,
|
||||||
|
step,
|
||||||
|
Config.keepVerity,
|
||||||
|
Config.keepEnc,
|
||||||
|
Config.patchVbmeta,
|
||||||
|
Config.recovery
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRestoreState(state: Bundle) {
|
||||||
|
state.getParcelable<InstallState>(INSTALL_STATE_KEY)?.let {
|
||||||
|
methodId = it.method
|
||||||
|
step = it.step
|
||||||
|
Config.keepVerity = it.keepVerity
|
||||||
|
Config.keepEnc = it.keepEnc
|
||||||
|
Config.patchVbmeta = it.patchVbmeta
|
||||||
|
Config.recovery = it.recovery
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
class UriCallback : ContentResultCallback {
|
||||||
|
override fun onActivityLaunch() {
|
||||||
|
Utils.toast(R.string.patch_file_msg, Toast.LENGTH_LONG)
|
||||||
|
}
|
||||||
|
override fun onActivityResult(result: Uri) {
|
||||||
|
uri.value = result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
class InstallState(
|
||||||
|
val method: Int,
|
||||||
|
val step: Int,
|
||||||
|
val keepVerity: Boolean,
|
||||||
|
val keepEnc: Boolean,
|
||||||
|
val patchVbmeta: Boolean,
|
||||||
|
val recovery: Boolean,
|
||||||
|
) : Parcelable
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val INSTALL_STATE_KEY = "install_state"
|
||||||
|
private val uri = MutableLiveData<Uri?>()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@ package com.topjohnwu.magisk.ui.module
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import com.topjohnwu.magisk.MainDirections
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.arch.BaseFragment
|
import com.topjohnwu.magisk.arch.BaseFragment
|
||||||
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding
|
||||||
import com.topjohnwu.magisk.databinding.RvItem
|
import com.topjohnwu.magisk.databinding.RvItem
|
||||||
import com.topjohnwu.magisk.databinding.adapterOf
|
import com.topjohnwu.magisk.databinding.adapterOf
|
||||||
@ -20,8 +22,12 @@ class ModuleFragment : BaseFragment<FragmentModuleMd2Binding>() {
|
|||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
setHasOptionsMenu(true)
|
|
||||||
activity?.title = resources.getString(R.string.modules)
|
activity?.title = resources.getString(R.string.modules)
|
||||||
|
viewModel.data.observe(this) {
|
||||||
|
it ?: return@observe
|
||||||
|
MainDirections.actionFlashFragment(Const.Value.FLASH_ZIP, it).navigate()
|
||||||
|
viewModel.data.value = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
@ -1,22 +1,26 @@
|
|||||||
package com.topjohnwu.magisk.ui.module
|
package com.topjohnwu.magisk.ui.module
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
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.Info
|
||||||
|
import com.topjohnwu.magisk.core.base.ContentResultCallback
|
||||||
import com.topjohnwu.magisk.core.model.module.LocalModule
|
import com.topjohnwu.magisk.core.model.module.LocalModule
|
||||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||||
import com.topjohnwu.magisk.databinding.RvItem
|
import com.topjohnwu.magisk.databinding.RvItem
|
||||||
import com.topjohnwu.magisk.databinding.diffListOf
|
import com.topjohnwu.magisk.databinding.diffListOf
|
||||||
import com.topjohnwu.magisk.databinding.itemBindingOf
|
import com.topjohnwu.magisk.databinding.itemBindingOf
|
||||||
import com.topjohnwu.magisk.events.SelectModuleEvent
|
import com.topjohnwu.magisk.events.GetContentEvent
|
||||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||||
import com.topjohnwu.magisk.events.dialog.ModuleInstallDialog
|
import com.topjohnwu.magisk.events.dialog.ModuleInstallDialog
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
import me.tatarka.bindingcollectionadapter2.collections.MergeObservableList
|
import me.tatarka.bindingcollectionadapter2.collections.MergeObservableList
|
||||||
|
|
||||||
class ModuleViewModel : BaseViewModel() {
|
class ModuleViewModel : BaseViewModel() {
|
||||||
@ -30,6 +34,8 @@ class ModuleViewModel : BaseViewModel() {
|
|||||||
it.bindExtra(BR.viewModel, this)
|
it.bindExtra(BR.viewModel, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val data get() = uri
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (Info.env.isActive) {
|
if (Info.env.isActive) {
|
||||||
items.insertItem(InstallModule)
|
items.insertItem(InstallModule)
|
||||||
@ -70,6 +76,18 @@ class ModuleViewModel : BaseViewModel() {
|
|||||||
SnackbarEvent(R.string.no_connection).publish()
|
SnackbarEvent(R.string.no_connection).publish()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun installPressed() = withExternalRW { SelectModuleEvent().publish() }
|
fun installPressed() = withExternalRW {
|
||||||
|
GetContentEvent("application/zip", UriCallback()).publish()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
class UriCallback : ContentResultCallback {
|
||||||
|
override fun onActivityResult(result: Uri) {
|
||||||
|
uri.value = result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val uri = MutableLiveData<Uri?>()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
gone="@{viewModel.step != 0}"
|
gone="@{viewModel.step != 0}"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:onClick="@{() -> viewModel.step(1)}"
|
android:onClick="@{() -> viewModel.setStep(1)}"
|
||||||
android:text="@string/install_next" />
|
android:text="@string/install_next" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user