mirror of
https://github.com/topjohnwu/Magisk.git
synced 2026-04-21 18:36:55 -04:00
Add Compose reboot menu to Home and fix navigation icon padding
Replace the View-based RebootMenu with a native Compose SuperListPopup in the Home top bar, with proper state tracking for the safe mode toggle. Remove the now-unused RebootMenu.kt. Also fix missing start padding on the SuperuserDetail back button to match all other sub-screens. Made-with: Cursor
This commit is contained in:
@@ -3,8 +3,11 @@ package com.topjohnwu.magisk.ui.home
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
@@ -20,6 +23,10 @@ import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -27,18 +34,28 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.net.toUri
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.ktx.reboot
|
||||
import com.topjohnwu.magisk.ui.component.ListPopupDefaults.MenuPositionProvider
|
||||
import com.topjohnwu.magisk.core.R as CoreR
|
||||
import top.yukonga.miuix.kmp.basic.Card
|
||||
import top.yukonga.miuix.kmp.basic.DropdownImpl
|
||||
import top.yukonga.miuix.kmp.basic.Icon
|
||||
import top.yukonga.miuix.kmp.basic.IconButton
|
||||
import top.yukonga.miuix.kmp.basic.LinearProgressIndicator
|
||||
import top.yukonga.miuix.kmp.basic.ListPopupColumn
|
||||
import top.yukonga.miuix.kmp.basic.MiuixScrollBehavior
|
||||
import top.yukonga.miuix.kmp.basic.PopupPositionProvider
|
||||
import top.yukonga.miuix.kmp.basic.Scaffold
|
||||
import top.yukonga.miuix.kmp.basic.Text
|
||||
import top.yukonga.miuix.kmp.basic.TextButton
|
||||
import top.yukonga.miuix.kmp.basic.TopAppBar
|
||||
import top.yukonga.miuix.kmp.extra.SuperListPopup
|
||||
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
||||
|
||||
@Composable
|
||||
@@ -51,7 +68,12 @@ fun HomeScreen(viewModel: HomeViewModel) {
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = stringResource(CoreR.string.section_home),
|
||||
scrollBehavior = scrollBehavior
|
||||
scrollBehavior = scrollBehavior,
|
||||
actions = {
|
||||
if (Info.isRooted) {
|
||||
RebootButton()
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
popupHost = { }
|
||||
@@ -88,6 +110,72 @@ fun HomeScreen(viewModel: HomeViewModel) {
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RebootButton() {
|
||||
val showMenu = remember { mutableStateOf(false) }
|
||||
val context = LocalContext.current
|
||||
var safeModeEnabled by remember { mutableIntStateOf(Config.bootloop) }
|
||||
|
||||
val showUserspace = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
|
||||
context.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true
|
||||
val showSafeMode = Const.Version.atLeast_28_0()
|
||||
|
||||
val items = buildList {
|
||||
add(RebootOption(CoreR.string.reboot) { reboot() })
|
||||
if (showUserspace) {
|
||||
add(RebootOption(CoreR.string.reboot_userspace) { reboot("userspace") })
|
||||
}
|
||||
add(RebootOption(CoreR.string.reboot_recovery) { reboot("recovery") })
|
||||
add(RebootOption(CoreR.string.reboot_bootloader) { reboot("bootloader") })
|
||||
add(RebootOption(CoreR.string.reboot_download) { reboot("download") })
|
||||
add(RebootOption(CoreR.string.reboot_edl) { reboot("edl") })
|
||||
if (showSafeMode) {
|
||||
add(RebootOption(CoreR.string.reboot_safe_mode) {
|
||||
val newVal = if (safeModeEnabled >= 2) 0 else 2
|
||||
Config.bootloop = newVal
|
||||
safeModeEnabled = newVal
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
IconButton(
|
||||
modifier = Modifier.padding(end = 16.dp),
|
||||
onClick = { showMenu.value = true },
|
||||
holdDownState = showMenu.value,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_restart),
|
||||
contentDescription = stringResource(CoreR.string.reboot),
|
||||
)
|
||||
}
|
||||
SuperListPopup(
|
||||
show = showMenu,
|
||||
popupPositionProvider = MenuPositionProvider,
|
||||
alignment = PopupPositionProvider.Align.End,
|
||||
onDismissRequest = { showMenu.value = false }
|
||||
) {
|
||||
ListPopupColumn {
|
||||
items.forEachIndexed { index, item ->
|
||||
val isSafeMode = item.labelRes == CoreR.string.reboot_safe_mode
|
||||
DropdownImpl(
|
||||
text = stringResource(item.labelRes),
|
||||
optionSize = items.size,
|
||||
isSelected = isSafeMode && safeModeEnabled >= 2,
|
||||
index = index,
|
||||
onSelectedIndexChange = {
|
||||
item.action()
|
||||
if (!isSafeMode) showMenu.value = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class RebootOption(val labelRes: Int, val action: () -> Unit)
|
||||
|
||||
@Composable
|
||||
private fun NoticeCard(onHide: () -> Unit) {
|
||||
Card(modifier = Modifier.fillMaxWidth()) {
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
package com.topjohnwu.magisk.ui.home
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.MenuItem
|
||||
import android.widget.PopupMenu
|
||||
import androidx.core.content.getSystemService
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.ktx.reboot as systemReboot
|
||||
|
||||
object RebootMenu {
|
||||
|
||||
private fun reboot(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_reboot_normal -> systemReboot()
|
||||
R.id.action_reboot_userspace -> systemReboot("userspace")
|
||||
R.id.action_reboot_bootloader -> systemReboot("bootloader")
|
||||
R.id.action_reboot_download -> systemReboot("download")
|
||||
R.id.action_reboot_edl -> systemReboot("edl")
|
||||
R.id.action_reboot_recovery -> systemReboot("recovery")
|
||||
R.id.action_reboot_safe_mode -> {
|
||||
val status = !item.isChecked
|
||||
item.isChecked = status
|
||||
Config.bootloop = if (status) 2 else 0
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun inflate(activity: Activity): PopupMenu {
|
||||
val themeWrapper = ContextThemeWrapper(activity, R.style.Foundation_PopupMenu)
|
||||
val menu = PopupMenu(themeWrapper, activity.window.decorView)
|
||||
activity.menuInflater.inflate(R.menu.menu_reboot, menu.menu)
|
||||
menu.setOnMenuItemClickListener(RebootMenu::reboot)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
|
||||
activity.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true) {
|
||||
menu.menu.findItem(R.id.action_reboot_userspace).isVisible = true
|
||||
}
|
||||
if (Const.Version.atLeast_28_0()) {
|
||||
menu.menu.findItem(R.id.action_reboot_safe_mode).isChecked = Config.bootloop >= 2
|
||||
} else {
|
||||
menu.menu.findItem(R.id.action_reboot_safe_mode).isVisible = false
|
||||
}
|
||||
return menu
|
||||
}
|
||||
|
||||
}
|
||||
@@ -55,7 +55,10 @@ fun SuperuserDetailScreen(
|
||||
TopAppBar(
|
||||
title = stringResource(CoreR.string.superuser_setting),
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onBack) {
|
||||
IconButton(
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
onClick = onBack
|
||||
) {
|
||||
Icon(
|
||||
imageVector = MiuixIcons.Back,
|
||||
contentDescription = stringResource(CoreR.string.back),
|
||||
|
||||
Reference in New Issue
Block a user