manager: hide root related features if kernelsu not available (#2555)

Without KernelSU installed, root-related features did not take any
effect. So, better to hide it.

Improving this pr:
https://github.com/tiann/KernelSU/pull/2483

Also attempt to address this:
https://github.com/tiann/KernelSU/pull/2483#issuecomment-2692048907

Tested-by: Faris <90097027+rsuntk@users.noreply.github.com>

Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>

---------

Signed-off-by: Faris <90097027+rsuntk@users.noreply.github.com>
Co-authored-by: Rifat Azad <33044977+rifsxd@users.noreply.github.com>
This commit is contained in:
Faris
2025-05-03 21:07:47 +07:00
committed by GitHub
parent 1946876626
commit 2d6890ce05
3 changed files with 106 additions and 73 deletions

View File

@@ -0,0 +1,17 @@
package me.weishu.kernelsu.ui.component
import androidx.compose.runtime.Composable
import me.weishu.kernelsu.Natives
import me.weishu.kernelsu.ksuApp
@Composable
fun KsuIsValid(
content: @Composable () -> Unit
) {
val isManager = Natives.becomeManager(ksuApp.packageName)
val ksuVersion = if (isManager) Natives.version else null
if (ksuVersion != null) {
content()
}
}

View File

@@ -39,6 +39,7 @@ import kotlinx.coroutines.withContext
import me.weishu.kernelsu.* import me.weishu.kernelsu.*
import me.weishu.kernelsu.R import me.weishu.kernelsu.R
import me.weishu.kernelsu.ui.component.rememberConfirmDialog import me.weishu.kernelsu.ui.component.rememberConfirmDialog
import me.weishu.kernelsu.ui.component.KsuIsValid
import me.weishu.kernelsu.ui.util.* import me.weishu.kernelsu.ui.util.*
import me.weishu.kernelsu.ui.util.module.LatestVersionInfo import me.weishu.kernelsu.ui.util.module.LatestVersionInfo
@@ -180,29 +181,31 @@ private fun TopBar(
} }
var showDropdown by remember { mutableStateOf(false) } var showDropdown by remember { mutableStateOf(false) }
IconButton(onClick = { KsuIsValid() {
showDropdown = true IconButton(onClick = {
}) { showDropdown = true
Icon(
imageVector = Icons.Filled.Refresh,
contentDescription = stringResource(id = R.string.reboot)
)
DropdownMenu(expanded = showDropdown, onDismissRequest = {
showDropdown = false
}) { }) {
Icon(
imageVector = Icons.Filled.Refresh,
contentDescription = stringResource(id = R.string.reboot)
)
RebootDropdownItem(id = R.string.reboot) DropdownMenu(expanded = showDropdown, onDismissRequest = {
showDropdown = false
}) {
val pm = LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager? RebootDropdownItem(id = R.string.reboot)
@Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) { val pm = LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace") @Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) {
RebootDropdownItem(id = R.string.reboot_userspace, reason = "userspace")
}
RebootDropdownItem(id = R.string.reboot_recovery, reason = "recovery")
RebootDropdownItem(id = R.string.reboot_bootloader, reason = "bootloader")
RebootDropdownItem(id = R.string.reboot_download, reason = "download")
RebootDropdownItem(id = R.string.reboot_edl, reason = "edl")
} }
RebootDropdownItem(id = R.string.reboot_recovery, reason = "recovery")
RebootDropdownItem(id = R.string.reboot_bootloader, reason = "bootloader")
RebootDropdownItem(id = R.string.reboot_download, reason = "download")
RebootDropdownItem(id = R.string.reboot_edl, reason = "edl")
} }
} }

View File

@@ -85,6 +85,7 @@ import me.weishu.kernelsu.ui.component.AboutDialog
import me.weishu.kernelsu.ui.component.ConfirmResult import me.weishu.kernelsu.ui.component.ConfirmResult
import me.weishu.kernelsu.ui.component.DialogHandle import me.weishu.kernelsu.ui.component.DialogHandle
import me.weishu.kernelsu.ui.component.SwitchItem import me.weishu.kernelsu.ui.component.SwitchItem
import me.weishu.kernelsu.ui.component.KsuIsValid
import me.weishu.kernelsu.ui.component.rememberConfirmDialog import me.weishu.kernelsu.ui.component.rememberConfirmDialog
import me.weishu.kernelsu.ui.component.rememberCustomDialog import me.weishu.kernelsu.ui.component.rememberCustomDialog
import me.weishu.kernelsu.ui.component.rememberLoadingDialog import me.weishu.kernelsu.ui.component.rememberLoadingDialog
@@ -150,42 +151,49 @@ fun SettingScreen(navigator: DestinationsNavigator) {
} }
val profileTemplate = stringResource(id = R.string.settings_profile_template) val profileTemplate = stringResource(id = R.string.settings_profile_template)
ListItem( KsuIsValid() {
leadingContent = { Icon(Icons.Filled.Fence, profileTemplate) }, ListItem(
headlineContent = { Text(profileTemplate) }, leadingContent = { Icon(Icons.Filled.Fence, profileTemplate) },
supportingContent = { Text(stringResource(id = R.string.settings_profile_template_summary)) }, headlineContent = { Text(profileTemplate) },
modifier = Modifier.clickable { supportingContent = { Text(stringResource(id = R.string.settings_profile_template_summary)) },
navigator.navigate(AppProfileTemplateScreenDestination) modifier = Modifier.clickable {
} navigator.navigate(AppProfileTemplateScreenDestination)
) }
)
}
var umountChecked by rememberSaveable { var umountChecked by rememberSaveable {
mutableStateOf(Natives.isDefaultUmountModules()) mutableStateOf(Natives.isDefaultUmountModules())
} }
SwitchItem(
icon = Icons.Filled.FolderDelete, KsuIsValid() {
title = stringResource(id = R.string.settings_umount_modules_default), SwitchItem(
summary = stringResource(id = R.string.settings_umount_modules_default_summary), icon = Icons.Filled.FolderDelete,
checked = umountChecked title = stringResource(id = R.string.settings_umount_modules_default),
) { summary = stringResource(id = R.string.settings_umount_modules_default_summary),
if (Natives.setDefaultUmountModules(it)) { checked = umountChecked
umountChecked = it ) {
if (Natives.setDefaultUmountModules(it)) {
umountChecked = it
}
} }
} }
if (Natives.version >= Natives.MINIMAL_SUPPORTED_SU_COMPAT) { KsuIsValid() {
var isSuDisabled by rememberSaveable { if (Natives.version >= Natives.MINIMAL_SUPPORTED_SU_COMPAT) {
mutableStateOf(!Natives.isSuEnabled()) var isSuDisabled by rememberSaveable {
} mutableStateOf(!Natives.isSuEnabled())
SwitchItem( }
icon = Icons.Filled.RemoveModerator, SwitchItem(
title = stringResource(id = R.string.settings_disable_su), icon = Icons.Filled.RemoveModerator,
summary = stringResource(id = R.string.settings_disable_su_summary), title = stringResource(id = R.string.settings_disable_su),
checked = isSuDisabled, summary = stringResource(id = R.string.settings_disable_su_summary),
) { checked -> checked = isSuDisabled,
val shouldEnable = !checked ) { checked ->
if (Natives.setSuEnabled(shouldEnable)) { val shouldEnable = !checked
isSuDisabled = !shouldEnable if (Natives.setSuEnabled(shouldEnable)) {
isSuDisabled = !shouldEnable
}
} }
} }
} }
@@ -211,14 +219,17 @@ fun SettingScreen(navigator: DestinationsNavigator) {
prefs.getBoolean("enable_web_debugging", false) prefs.getBoolean("enable_web_debugging", false)
) )
} }
SwitchItem(
icon = Icons.Filled.DeveloperMode, KsuIsValid() {
title = stringResource(id = R.string.enable_web_debugging), SwitchItem(
summary = stringResource(id = R.string.enable_web_debugging_summary), icon = Icons.Filled.DeveloperMode,
checked = enableWebDebugging title = stringResource(id = R.string.enable_web_debugging),
) { summary = stringResource(id = R.string.enable_web_debugging_summary),
prefs.edit().putBoolean("enable_web_debugging", it).apply() checked = enableWebDebugging
enableWebDebugging = it ) {
prefs.edit().putBoolean("enable_web_debugging", it).apply()
enableWebDebugging = it
}
} }
var showBottomsheet by remember { mutableStateOf(false) } var showBottomsheet by remember { mutableStateOf(false) }
@@ -332,25 +343,27 @@ fun SettingScreen(navigator: DestinationsNavigator) {
val shrink = stringResource(id = R.string.shrink_sparse_image) val shrink = stringResource(id = R.string.shrink_sparse_image)
val shrinkMessage = stringResource(id = R.string.shrink_sparse_image_message) val shrinkMessage = stringResource(id = R.string.shrink_sparse_image_message)
ListItem( KsuIsValid() {
leadingContent = { ListItem(
Icon( leadingContent = {
Icons.Filled.Compress, Icon(
shrink Icons.Filled.Compress,
) shrink
}, )
headlineContent = { Text(shrink) }, },
modifier = Modifier.clickable { headlineContent = { Text(shrink) },
scope.launch { modifier = Modifier.clickable {
val result = shrinkDialog.awaitConfirm(title = shrink, content = shrinkMessage) scope.launch {
if (result == ConfirmResult.Confirmed) { val result = shrinkDialog.awaitConfirm(title = shrink, content = shrinkMessage)
loadingDialog.withLoading { if (result == ConfirmResult.Confirmed) {
shrinkModules() loadingDialog.withLoading {
shrinkModules()
}
} }
} }
} }
} )
) }
val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode
if (lkmMode) { if (lkmMode) {