mirror of
https://github.com/topjohnwu/Magisk.git
synced 2026-06-02 06:03:44 +02:00
Port new download feature to apk-ng
Assist-by: Gemini
This commit is contained in:
@@ -111,6 +111,13 @@ class FlashViewModel : BaseViewModel() {
|
||||
MagiskInstaller.Patch(uri, outItems, logItems).exec()
|
||||
})
|
||||
}
|
||||
Const.Value.DOWNLOAD -> {
|
||||
uri ?: return@launch
|
||||
_showReboot.value = false
|
||||
onResult(withContext(Dispatchers.IO) {
|
||||
MagiskInstaller.Download(uri.toString(), outItems, logItems).exec()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.topjohnwu.magisk.ui.home
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import android.widget.Toast
|
||||
@@ -21,6 +22,8 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
@@ -67,9 +70,12 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.net.toUri
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.BuildConfig
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
@@ -111,6 +117,7 @@ fun HomeScreen(viewModel: HomeViewModel, installVm: InstallViewModel) {
|
||||
var showHideDialog by rememberSaveable { mutableStateOf(false) }
|
||||
var showRestoreDialog by rememberSaveable { mutableStateOf(false) }
|
||||
val showInstallSheet = rememberSaveable { mutableStateOf(false) }
|
||||
val showDownloadDialog = rememberSaveable { mutableStateOf(false) }
|
||||
var envFixCode by remember { mutableIntStateOf(0) }
|
||||
|
||||
val filePicker = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri ->
|
||||
@@ -138,6 +145,13 @@ fun HomeScreen(viewModel: HomeViewModel, installVm: InstallViewModel) {
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(installUiState.showDownloadDialog) {
|
||||
if (installUiState.showDownloadDialog) {
|
||||
showDownloadDialog.value = true
|
||||
installVm.onDownloadDialogConsumed()
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(uiState.showUninstall) {
|
||||
if (uiState.showUninstall) {
|
||||
showUninstallDialog.value = true
|
||||
@@ -218,6 +232,13 @@ fun HomeScreen(viewModel: HomeViewModel, installVm: InstallViewModel) {
|
||||
)
|
||||
}
|
||||
|
||||
if (showDownloadDialog.value) {
|
||||
DownloadComposableDialog(
|
||||
showDialog = showDownloadDialog,
|
||||
onConfirm = { url -> installVm.onDownloadUrlSelected(url) }
|
||||
)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
@@ -788,7 +809,14 @@ private fun InstallBottomSheet(
|
||||
show.value = false
|
||||
installVm.selectMethod(InstallViewModel.Method.PATCH)
|
||||
},
|
||||
// enabled = installUiState.step >= 1 || installVm.skipOptions
|
||||
)
|
||||
|
||||
SettingsArrow(
|
||||
title = stringResource(CoreR.string.download_patch_file),
|
||||
onClick = {
|
||||
show.value = false
|
||||
installVm.selectMethod(InstallViewModel.Method.DOWNLOAD)
|
||||
},
|
||||
)
|
||||
|
||||
if (installVm.isRooted) {
|
||||
@@ -800,7 +828,6 @@ private fun InstallBottomSheet(
|
||||
installVm.selectMethod(InstallViewModel.Method.DIRECT)
|
||||
installVm.install()
|
||||
},
|
||||
// enabled = installUiState.step >= 1 || installVm.skipOptions
|
||||
)
|
||||
}
|
||||
|
||||
@@ -812,7 +839,6 @@ private fun InstallBottomSheet(
|
||||
show.value = false
|
||||
installVm.selectMethod(InstallViewModel.Method.INACTIVE_SLOT)
|
||||
},
|
||||
// enabled = installUiState.step >= 1 || installVm.skipOptions
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -891,6 +917,87 @@ private fun CheckboxRow(label: String, checked: Boolean, onCheckedChange: (Boole
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DownloadComposableDialog(
|
||||
showDialog: MutableState<Boolean>,
|
||||
onConfirm: (Uri) -> Unit
|
||||
) {
|
||||
if (!showDialog.value) return
|
||||
|
||||
var url by rememberSaveable { mutableStateOf("") }
|
||||
var isError by rememberSaveable { mutableStateOf(false) }
|
||||
|
||||
fun isValidUrl(url: String): Uri? {
|
||||
if (url.isEmpty()) return null
|
||||
val uri = url.toUri()
|
||||
if (!uri.scheme.equals("https", ignoreCase = true)) return null
|
||||
if (uri.host.isNullOrEmpty()) return null
|
||||
if (uri.path.isNullOrEmpty()) return null
|
||||
return uri
|
||||
}
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = { showDialog.value = false },
|
||||
title = { Text(stringResource(CoreR.string.download_dialog_title)) },
|
||||
text = {
|
||||
Column(modifier = Modifier.padding(top = 8.dp)) {
|
||||
OutlinedTextField(
|
||||
value = url,
|
||||
onValueChange = {
|
||||
url = it
|
||||
isError = false
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
label = { Text(stringResource(CoreR.string.download_dialog_msg)) },
|
||||
isError = isError,
|
||||
singleLine = true,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Uri,
|
||||
imeAction = ImeAction.Done
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = {
|
||||
isValidUrl(url.trim())?.let {
|
||||
showDialog.value = false
|
||||
onConfirm(it)
|
||||
} ?: run {
|
||||
isError = true
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
if (isError) {
|
||||
Text(
|
||||
text = stringResource(CoreR.string.download_dialog_title),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
modifier = Modifier.padding(start = 16.dp, top = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
isValidUrl(url.trim())?.let {
|
||||
showDialog.value = false
|
||||
onConfirm(it)
|
||||
} ?: run {
|
||||
isError = true
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(stringResource(android.R.string.ok))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { showDialog.value = false }) {
|
||||
Text(stringResource(android.R.string.cancel))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun UninstallComposableDialog(
|
||||
showDialog: MutableState<Boolean>,
|
||||
|
||||
@@ -25,7 +25,7 @@ import com.topjohnwu.magisk.core.R as CoreR
|
||||
|
||||
class InstallViewModel(svc: NetworkService) : BaseViewModel() {
|
||||
|
||||
enum class Method { NONE, PATCH, DIRECT, INACTIVE_SLOT }
|
||||
enum class Method { NONE, PATCH, DIRECT, INACTIVE_SLOT, DOWNLOAD }
|
||||
|
||||
data class UiState(
|
||||
val step: Int = 0,
|
||||
@@ -34,6 +34,7 @@ class InstallViewModel(svc: NetworkService) : BaseViewModel() {
|
||||
val patchUri: Uri? = null,
|
||||
val requestFilePicker: Boolean = false,
|
||||
val showSecondSlotWarning: Boolean = false,
|
||||
val showDownloadDialog: Boolean = false,
|
||||
)
|
||||
|
||||
val isRooted get() = Info.isRooted
|
||||
@@ -79,6 +80,9 @@ class InstallViewModel(svc: NetworkService) : BaseViewModel() {
|
||||
Method.INACTIVE_SLOT -> {
|
||||
_uiState.update { it.copy(showSecondSlotWarning = true) }
|
||||
}
|
||||
Method.DOWNLOAD -> {
|
||||
_uiState.update { it.copy(showDownloadDialog = true) }
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -91,6 +95,10 @@ class InstallViewModel(svc: NetworkService) : BaseViewModel() {
|
||||
_uiState.update { it.copy(showSecondSlotWarning = false) }
|
||||
}
|
||||
|
||||
fun onDownloadDialogConsumed() {
|
||||
_uiState.update { it.copy(showDownloadDialog = false) }
|
||||
}
|
||||
|
||||
fun onPatchFileSelected(uri: Uri) {
|
||||
_uiState.update { it.copy(patchUri = uri) }
|
||||
if (_uiState.value.method == Method.PATCH) {
|
||||
@@ -98,12 +106,23 @@ class InstallViewModel(svc: NetworkService) : BaseViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
fun onDownloadUrlSelected(uri: Uri) {
|
||||
_uiState.update { it.copy(patchUri = uri) }
|
||||
if (_uiState.value.method == Method.DOWNLOAD) {
|
||||
install()
|
||||
}
|
||||
}
|
||||
|
||||
fun install() {
|
||||
when (_uiState.value.method) {
|
||||
Method.PATCH -> navigateTo(Route.Flash(
|
||||
action = Const.Value.PATCH_FILE,
|
||||
additionalData = _uiState.value.patchUri!!.toString()
|
||||
))
|
||||
Method.DOWNLOAD -> navigateTo(Route.Flash(
|
||||
action = Const.Value.DOWNLOAD,
|
||||
additionalData = _uiState.value.patchUri!!.toString()
|
||||
))
|
||||
Method.DIRECT -> navigateTo(Route.Flash(
|
||||
action = Const.Value.FLASH_MAGISK
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user