From ad2a23f55e040942475ab137aa46eb642506a78d Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Mon, 17 Nov 2025 12:37:53 +0800 Subject: [PATCH] manager: Move certain settings to the Advanced Settings section. --- .../com/sukisu/ultra/ui/screen/Settings.kt | 140 ----------------- .../screen/moreSettings/MoreSettings.kt | 33 +++- .../moreSettings/MoreSettingsHandlers.kt | 23 +++ .../component/MoreSettingsDialogs.kt | 144 ++++++++++++++++++ .../moreSettings/state/MoreSettingsState.kt | 3 - 5 files changed, 199 insertions(+), 144 deletions(-) diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Settings.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Settings.kt index d9825ce8..22cc0ccd 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Settings.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Settings.kt @@ -330,25 +330,6 @@ fun SettingScreen(navigator: DestinationsNavigator) { } } ) - - // 强制签名验证开关 - var forceSignatureVerification by rememberSaveable { - mutableStateOf(prefs.getBoolean("force_signature_verification", false)) - } - SwitchItem( - icon = Icons.Filled.Security, - title = stringResource(R.string.module_signature_verification), - summary = stringResource(R.string.module_signature_verification_summary), - checked = forceSignatureVerification, - onCheckedChange = { enabled -> - prefs.edit { putBoolean("force_signature_verification", enabled) } - forceSignatureVerification = enabled - } - ) - // UID 扫描开关 - if (Natives.version >= Natives.MINIMAL_SUPPORTED_UID_SCANNER && Natives.version >= Natives.MINIMAL_NEW_IOCTL_KERNEL) { - UidScannerSection(prefs, snackBarHost, scope, context) - } } ) } @@ -1004,124 +985,3 @@ private fun TopBar( scrollBehavior = scrollBehavior ) } - -@Composable -private fun UidScannerSection( - prefs: SharedPreferences, - snackBarHost: SnackbarHostState, - scope: CoroutineScope, - context: Context -) { - if (Natives.version < Natives.MINIMAL_SUPPORTED_UID_SCANNER) return - - val realAuto = Natives.isUidScannerEnabled() - val realMulti = getUidMultiUserScan() - - var autoOn by remember { mutableStateOf(realAuto) } - var multiOn by remember { mutableStateOf(realMulti) } - - LaunchedEffect(Unit) { - autoOn = realAuto - multiOn = realMulti - prefs.edit { - putBoolean("uid_auto_scan", autoOn) - putBoolean("uid_multi_user_scan", multiOn) - } - } - - SwitchItem( - icon = Icons.Filled.Scanner, - title = stringResource(R.string.uid_auto_scan_title), - summary = stringResource(R.string.uid_auto_scan_summary), - checked = autoOn, - onCheckedChange = { target -> - autoOn = target - if (!target) multiOn = false - - scope.launch(Dispatchers.IO) { - setUidAutoScan(target) - val actual = Natives.isUidScannerEnabled() || readUidScannerFile() - withContext(Dispatchers.Main) { - autoOn = actual - if (!actual) multiOn = false - prefs.edit { - putBoolean("uid_auto_scan", actual) - putBoolean("uid_multi_user_scan", multiOn) - } - if (actual != target) { - snackBarHost.showSnackbar( - context.getString(R.string.uid_scanner_setting_failed) - ) - } - } - } - } - ) - - AnimatedVisibility( - visible = autoOn, - enter = fadeIn() + expandVertically(), - exit = fadeOut() + shrinkVertically() - ) { - SwitchItem( - icon = Icons.Filled.Groups, - title = stringResource(R.string.uid_multi_user_scan_title), - summary = stringResource(R.string.uid_multi_user_scan_summary), - checked = multiOn, - onCheckedChange = { target -> - scope.launch(Dispatchers.IO) { - val ok = setUidMultiUserScan(target) - withContext(Dispatchers.Main) { - if (ok) { - multiOn = target - prefs.edit { putBoolean("uid_multi_user_scan", target) } - } else { - snackBarHost.showSnackbar( - context.getString(R.string.uid_scanner_setting_failed) - ) - } - } - } - } - ) - } - - AnimatedVisibility( - visible = autoOn, - enter = fadeIn() + expandVertically(), - exit = fadeOut() + shrinkVertically() - ) { - val confirmDialog = rememberConfirmDialog() - SettingItem( - icon = Icons.Filled.CleaningServices, - title = stringResource(R.string.clean_runtime_environment), - summary = stringResource(R.string.clean_runtime_environment_summary), - onClick = { - scope.launch { - if (confirmDialog.awaitConfirm( - title = context.getString(R.string.clean_runtime_environment), - content = context.getString(R.string.clean_runtime_environment_confirm) - ) == ConfirmResult.Confirmed - ) { - if (cleanRuntimeEnvironment()) { - autoOn = false - multiOn = false - prefs.edit { - putBoolean("uid_auto_scan", false) - putBoolean("uid_multi_user_scan", false) - } - Natives.setUidScannerEnabled(false) - snackBarHost.showSnackbar( - context.getString(R.string.clean_runtime_environment_success) - ) - } else { - snackBarHost.showSnackbar( - context.getString(R.string.clean_runtime_environment_failed) - ) - } - } - } - } - ) - } -} diff --git a/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/MoreSettings.kt b/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/MoreSettings.kt index a2198093..1540d3a6 100644 --- a/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/MoreSettings.kt +++ b/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/MoreSettings.kt @@ -17,6 +17,9 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.* import androidx.compose.material3.* import androidx.compose.runtime.* +import androidx.compose.runtime.getValue +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -25,6 +28,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.core.content.edit import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.navigation.DestinationsNavigator @@ -33,8 +37,8 @@ import com.sukisu.ultra.Natives import com.sukisu.ultra.R import com.sukisu.ultra.ui.theme.component.ImageEditorDialog import com.sukisu.ultra.ui.component.KsuIsValid +import com.sukisu.ultra.ui.screen.SwitchItem import com.sukisu.ultra.ui.theme.* -import com.sukisu.ultra.ui.util.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -45,6 +49,7 @@ import zako.zako.zako.zakoui.screen.moreSettings.component.SettingItem import zako.zako.zako.zakoui.screen.moreSettings.component.SettingsCard import zako.zako.zako.zakoui.screen.moreSettings.component.SettingsDivider import zako.zako.zako.zakoui.screen.moreSettings.component.SwitchSettingItem +import zako.zako.zako.zakoui.screen.moreSettings.component.UidScannerSection import zako.zako.zako.zakoui.screen.moreSettings.state.MoreSettingsState import kotlin.math.roundToInt @@ -341,6 +346,11 @@ private fun AdvancedSettings( state: MoreSettingsState, handlers: MoreSettingsHandlers ) { + val context = LocalContext.current + val scope = rememberCoroutineScope() + val snackBarHost = remember { SnackbarHostState() } + val prefs = remember { context.getSharedPreferences("settings", Context.MODE_PRIVATE) } + SettingsCard(title = stringResource(R.string.advanced_settings)) { // SELinux 开关 SwitchSettingItem( @@ -353,6 +363,27 @@ private fun AdvancedSettings( onChange = handlers::handleSelinuxChange ) + var forceSignatureVerification by rememberSaveable { + mutableStateOf(prefs.getBoolean("force_signature_verification", false)) + } + + // 强制签名验证开关 + SwitchItem( + icon = Icons.Filled.Security, + title = stringResource(R.string.module_signature_verification), + summary = stringResource(R.string.module_signature_verification_summary), + checked = forceSignatureVerification, + onCheckedChange = { enabled -> + prefs.edit { putBoolean("force_signature_verification", enabled) } + forceSignatureVerification = enabled + } + ) + + // UID 扫描开关 + if (Natives.version >= Natives.MINIMAL_SUPPORTED_UID_SCANNER && Natives.version >= Natives.MINIMAL_NEW_IOCTL_KERNEL) { + UidScannerSection(prefs, snackBarHost, scope, context) + } + // 动态管理器设置 if (Natives.version >= Natives.MINIMAL_SUPPORTED_DYNAMIC_MANAGER && Natives.version >= Natives.MINIMAL_NEW_IOCTL_KERNEL) { SettingItem( diff --git a/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/MoreSettingsHandlers.kt b/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/MoreSettingsHandlers.kt index 1584c8d4..b5b9921a 100644 --- a/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/MoreSettingsHandlers.kt +++ b/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/MoreSettingsHandlers.kt @@ -6,15 +6,38 @@ import android.content.SharedPreferences import android.content.res.Configuration import android.net.Uri import android.widget.Toast +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.CleaningServices +import androidx.compose.material.icons.filled.Groups +import androidx.compose.material.icons.filled.Scanner +import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.core.content.edit import com.sukisu.ultra.Natives import com.sukisu.ultra.R +import com.sukisu.ultra.ui.component.ConfirmResult +import com.sukisu.ultra.ui.component.rememberConfirmDialog +import com.sukisu.ultra.ui.screen.SettingItem +import com.sukisu.ultra.ui.screen.SwitchItem import com.sukisu.ultra.ui.theme.* import com.sukisu.ultra.ui.util.* import com.topjohnwu.superuser.Shell +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import zako.zako.zako.zakoui.screen.moreSettings.state.MoreSettingsState import zako.zako.zako.zakoui.screen.moreSettings.util.toggleLauncherIcon diff --git a/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/component/MoreSettingsDialogs.kt b/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/component/MoreSettingsDialogs.kt index c321c93e..cebfd8bb 100644 --- a/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/component/MoreSettingsDialogs.kt +++ b/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/component/MoreSettingsDialogs.kt @@ -1,13 +1,23 @@ package zako.zako.zako.zakoui.screen.moreSettings.component import android.content.Context +import android.content.SharedPreferences +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Check +import androidx.compose.material.icons.filled.CleaningServices +import androidx.compose.material.icons.filled.Groups +import androidx.compose.material.icons.filled.Scanner import androidx.compose.material3.* import androidx.compose.runtime.* +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -20,9 +30,22 @@ import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState import com.maxkeppeler.sheets.list.ListDialog import com.maxkeppeler.sheets.list.models.ListOption import com.maxkeppeler.sheets.list.models.ListSelection +import com.sukisu.ultra.Natives import zako.zako.zako.zakoui.screen.moreSettings.util.LocaleHelper import com.sukisu.ultra.R +import com.sukisu.ultra.ui.component.ConfirmResult +import com.sukisu.ultra.ui.component.rememberConfirmDialog +import com.sukisu.ultra.ui.screen.SwitchItem import com.sukisu.ultra.ui.theme.* +import com.sukisu.ultra.ui.util.cleanRuntimeEnvironment +import com.sukisu.ultra.ui.util.getUidMultiUserScan +import com.sukisu.ultra.ui.util.readUidScannerFile +import com.sukisu.ultra.ui.util.setUidAutoScan +import com.sukisu.ultra.ui.util.setUidMultiUserScan +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import zako.zako.zako.zakoui.screen.moreSettings.MoreSettingsHandlers import zako.zako.zako.zakoui.screen.moreSettings.state.MoreSettingsState @@ -473,4 +496,125 @@ fun DynamicManagerDialog( } } ) +} + +@Composable +fun UidScannerSection( + prefs: SharedPreferences, + snackBarHost: SnackbarHostState, + scope: CoroutineScope, + context: Context +) { + if (Natives.version < Natives.MINIMAL_SUPPORTED_UID_SCANNER) return + + val realAuto = Natives.isUidScannerEnabled() + val realMulti = getUidMultiUserScan() + + var autoOn by remember { mutableStateOf(realAuto) } + var multiOn by remember { mutableStateOf(realMulti) } + + LaunchedEffect(Unit) { + autoOn = realAuto + multiOn = realMulti + prefs.edit { + putBoolean("uid_auto_scan", autoOn) + putBoolean("uid_multi_user_scan", multiOn) + } + } + + SwitchItem( + icon = Icons.Filled.Scanner, + title = stringResource(R.string.uid_auto_scan_title), + summary = stringResource(R.string.uid_auto_scan_summary), + checked = autoOn, + onCheckedChange = { target -> + autoOn = target + if (!target) multiOn = false + + scope.launch(Dispatchers.IO) { + setUidAutoScan(target) + val actual = Natives.isUidScannerEnabled() || readUidScannerFile() + withContext(Dispatchers.Main) { + autoOn = actual + if (!actual) multiOn = false + prefs.edit { + putBoolean("uid_auto_scan", actual) + putBoolean("uid_multi_user_scan", multiOn) + } + if (actual != target) { + snackBarHost.showSnackbar( + context.getString(R.string.uid_scanner_setting_failed) + ) + } + } + } + } + ) + + AnimatedVisibility( + visible = autoOn, + enter = fadeIn() + expandVertically(), + exit = fadeOut() + shrinkVertically() + ) { + SwitchItem( + icon = Icons.Filled.Groups, + title = stringResource(R.string.uid_multi_user_scan_title), + summary = stringResource(R.string.uid_multi_user_scan_summary), + checked = multiOn, + onCheckedChange = { target -> + scope.launch(Dispatchers.IO) { + val ok = setUidMultiUserScan(target) + withContext(Dispatchers.Main) { + if (ok) { + multiOn = target + prefs.edit { putBoolean("uid_multi_user_scan", target) } + } else { + snackBarHost.showSnackbar( + context.getString(R.string.uid_scanner_setting_failed) + ) + } + } + } + } + ) + } + + AnimatedVisibility( + visible = autoOn, + enter = fadeIn() + expandVertically(), + exit = fadeOut() + shrinkVertically() + ) { + val confirmDialog = rememberConfirmDialog() + com.sukisu.ultra.ui.screen.SettingItem( + icon = Icons.Filled.CleaningServices, + title = stringResource(R.string.clean_runtime_environment), + summary = stringResource(R.string.clean_runtime_environment_summary), + onClick = { + scope.launch { + if (confirmDialog.awaitConfirm( + title = context.getString(R.string.clean_runtime_environment), + content = context.getString(R.string.clean_runtime_environment_confirm) + ) == ConfirmResult.Confirmed + ) { + if (cleanRuntimeEnvironment()) { + autoOn = false + multiOn = false + prefs.edit { + putBoolean("uid_auto_scan", false) + putBoolean("uid_multi_user_scan", false) + } + Natives.setUidScannerEnabled(false) + snackBarHost.showSnackbar( + context.getString(R.string.clean_runtime_environment_success) + ) + } else { + snackBarHost.showSnackbar( + context.getString(R.string.clean_runtime_environment_failed) + ) + } + } + } + } + ) + } } \ No newline at end of file diff --git a/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/state/MoreSettingsState.kt b/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/state/MoreSettingsState.kt index ec1abf87..26e9593c 100644 --- a/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/state/MoreSettingsState.kt +++ b/manager/app/src/main/java/zako/zako/zako/zakoui/screen/moreSettings/state/MoreSettingsState.kt @@ -70,9 +70,6 @@ class MoreSettingsState( // SELinux状态 var selinuxEnabled by mutableStateOf(false) - // SuSFS 状态 - var isSusFSEnabled by mutableStateOf(true) - // 卡片配置状态 var cardAlpha by mutableFloatStateOf(CardConfig.cardAlpha) var cardDim by mutableFloatStateOf(CardConfig.cardDim)