manager: support meta module (#616)
This commit is contained in:
@@ -33,6 +33,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
|
||||
@@ -52,8 +54,10 @@ import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import androidx.core.content.edit
|
||||
import com.sukisu.ultra.ui.component.rememberCustomDialog
|
||||
import com.sukisu.ultra.ui.util.module.ModuleOperationUtils
|
||||
import com.sukisu.ultra.ui.util.module.ModuleUtils
|
||||
import com.topjohnwu.superuser.io.SuFile
|
||||
|
||||
/**
|
||||
* @author ShirkNeko
|
||||
@@ -152,6 +156,7 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
var tempText: String
|
||||
val logContent = rememberSaveable { StringBuilder() }
|
||||
var showFloatAction by rememberSaveable { mutableStateOf(false) }
|
||||
var shouldWarningUserMetaModule by rememberSaveable { mutableStateOf(false) }
|
||||
// 添加状态跟踪是否已经完成刷写
|
||||
var hasFlashCompleted by rememberSaveable { mutableStateOf(false) }
|
||||
var hasExecuted by rememberSaveable { mutableStateOf(false) }
|
||||
@@ -170,6 +175,39 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
val logSavedString = stringResource(R.string.log_saved)
|
||||
val installingModuleString = stringResource(R.string.installing_module)
|
||||
|
||||
val alertDialog = rememberCustomDialog { dismiss: () -> Unit ->
|
||||
val uriHandler = LocalUriHandler.current
|
||||
AlertDialog(
|
||||
onDismissRequest = { dismiss() },
|
||||
icon = {
|
||||
Icon(Icons.Outlined.Info, contentDescription = null)
|
||||
},
|
||||
title = {
|
||||
Row(modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
Text(text = stringResource(R.string.warning_of_meta_module_title))
|
||||
}
|
||||
},
|
||||
text = {
|
||||
Text(text = stringResource(R.string.warning_of_meta_module_summary))
|
||||
},
|
||||
confirmButton = {
|
||||
FilledTonalButton(onClick = { dismiss() }) {
|
||||
Text(text = stringResource(id = android.R.string.ok))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
OutlinedButton(onClick = {
|
||||
uriHandler.openUri("https://kernelsu.org/guide/metamodule.html")
|
||||
}) {
|
||||
Text(text = stringResource(id = R.string.learn_more))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// 当前模块安装状态
|
||||
val currentStatus = moduleInstallStatus.value
|
||||
|
||||
@@ -182,16 +220,19 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
totalModules = flashIt.uris.size,
|
||||
currentModule = 1
|
||||
)
|
||||
shouldWarningUserMetaModule = false
|
||||
hasFlashCompleted = false
|
||||
hasExecuted = false
|
||||
moduleVerificationMap.clear()
|
||||
}
|
||||
}
|
||||
is FlashIt.FlashModuleUpdate -> {
|
||||
shouldWarningUserMetaModule = false
|
||||
hasUpdateCompleted = false
|
||||
hasUpdateExecuted = false
|
||||
}
|
||||
else -> {
|
||||
shouldWarningUserMetaModule = false
|
||||
hasFlashCompleted = false
|
||||
hasExecuted = false
|
||||
}
|
||||
@@ -240,10 +281,29 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
}
|
||||
hasUpdateCompleted = true
|
||||
|
||||
if (!hasMetaModule() && code == 0) {
|
||||
// 如果没安装 MetaModule,且此模块需要挂载,并且当前模块安装成功,警告用户
|
||||
scope.launch {
|
||||
val mountOldDirectory = SuFile.open("/data/adb/modules/${getModuleIdFromUri(context,flashIt.uri)}/system")
|
||||
val mountNewDirectory = SuFile.open("/data/adb/modules_update/${getModuleIdFromUri(context,flashIt.uri)}/system")
|
||||
if (!(mountNewDirectory.isDirectory) && !(mountOldDirectory.isDirectory)) return@launch
|
||||
shouldWarningUserMetaModule = true
|
||||
|
||||
alertDialog.show()
|
||||
shouldWarningUserMetaModule = false
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是外部安装或需要自动退出的模块更新且不需要重启,延迟后自动返回
|
||||
if (isExternalInstall || shouldAutoExit) {
|
||||
scope.launch {
|
||||
while (shouldWarningUserMetaModule) {
|
||||
kotlinx.coroutines.delay(100)
|
||||
}
|
||||
kotlinx.coroutines.delay(1000)
|
||||
while (shouldWarningUserMetaModule) {
|
||||
kotlinx.coroutines.delay(100)
|
||||
}
|
||||
if (shouldAutoExit) {
|
||||
val sharedPref = context.getSharedPreferences("kernel_flash_prefs", Context.MODE_PRIVATE)
|
||||
sharedPref.edit { remove("auto_exit_after_flash") }
|
||||
@@ -334,6 +394,38 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
}
|
||||
|
||||
hasFlashCompleted = true
|
||||
if (!hasMetaModule() && code == 0) {
|
||||
// 没有 MetaModule,且安装成功,检查此模块是否有自动挂载
|
||||
scope.launch {
|
||||
var mountOldDirectory : File
|
||||
var mountNewDirectory : File
|
||||
when (flashIt) {
|
||||
is FlashIt.FlashModules -> {
|
||||
mountOldDirectory = SuFile.open("/data/adb/modules/${getModuleIdFromUri(context,flashIt.uris[flashIt.currentIndex])}/system")
|
||||
mountNewDirectory = SuFile.open("/data/adb/modules_update/${getModuleIdFromUri(context,flashIt.uris[flashIt.currentIndex])}/system")
|
||||
}
|
||||
|
||||
is FlashIt.FlashModule -> {
|
||||
mountOldDirectory = SuFile.open("/data/adb/modules/${getModuleIdFromUri(context,flashIt.uri)}/system")
|
||||
mountNewDirectory = SuFile.open("/data/adb/modules_update/${getModuleIdFromUri(context,flashIt.uri)}/system")
|
||||
}
|
||||
|
||||
is FlashIt.FlashModuleUpdate -> {
|
||||
mountOldDirectory = SuFile.open("/data/adb/modules/${getModuleIdFromUri(context,flashIt.uri)}/system")
|
||||
mountNewDirectory = SuFile.open("/data/adb/modules_update/${getModuleIdFromUri(context,flashIt.uri)}/system")
|
||||
}
|
||||
|
||||
else -> return@launch
|
||||
}
|
||||
if (!mountNewDirectory.isDirectory && !mountOldDirectory.isDirectory) return@launch
|
||||
shouldWarningUserMetaModule = true
|
||||
|
||||
if (!hasMetaModule() && (flashIt !is FlashIt.FlashModules || flashIt.currentIndex >= flashIt.uris.size - 1)) {
|
||||
// 如果没有 MetaModule,且当前不是多模块刷写或是最后一个需要自动刷写的模块,而且有模块需要挂载,警告用户
|
||||
alertDialog.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flashIt is FlashIt.FlashModules && flashIt.currentIndex < flashIt.uris.size - 1) {
|
||||
val nextFlashIt = flashIt.copy(
|
||||
@@ -346,7 +438,13 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
} else if ((isExternalInstall || shouldAutoExit) && flashIt is FlashIt.FlashModules && flashIt.currentIndex >= flashIt.uris.size - 1) {
|
||||
// 如果是外部安装或需要自动退出且是最后一个模块,安装完成后自动返回
|
||||
scope.launch {
|
||||
while (shouldWarningUserMetaModule) {
|
||||
kotlinx.coroutines.delay(100)
|
||||
}
|
||||
kotlinx.coroutines.delay(1000)
|
||||
while (shouldWarningUserMetaModule) {
|
||||
kotlinx.coroutines.delay(100)
|
||||
}
|
||||
if (shouldAutoExit) {
|
||||
val sharedPref = context.getSharedPreferences("kernel_flash_prefs", Context.MODE_PRIVATE)
|
||||
sharedPref.edit { remove("auto_exit_after_flash") }
|
||||
@@ -356,7 +454,13 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||
} else if ((isExternalInstall || shouldAutoExit) && flashIt is FlashIt.FlashModule) {
|
||||
// 如果是外部安装或需要自动退出的单个模块,安装完成后自动返回
|
||||
scope.launch {
|
||||
while (shouldWarningUserMetaModule) {
|
||||
kotlinx.coroutines.delay(100)
|
||||
}
|
||||
kotlinx.coroutines.delay(1000)
|
||||
while (shouldWarningUserMetaModule) {
|
||||
kotlinx.coroutines.delay(100)
|
||||
}
|
||||
if (shouldAutoExit) {
|
||||
val sharedPref = context.getSharedPreferences("kernel_flash_prefs", Context.MODE_PRIVATE)
|
||||
sharedPref.edit { remove("auto_exit_after_flash") }
|
||||
@@ -705,6 +809,22 @@ suspend fun getModuleNameFromUri(context: Context, uri: Uri): String {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getModuleIdFromUri(context: Context, uri: Uri): String? {
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
if (uri == Uri.EMPTY) {
|
||||
return@withContext null
|
||||
}
|
||||
if (!ModuleUtils.isUriAccessible(context, uri)) {
|
||||
return@withContext null
|
||||
}
|
||||
ModuleUtils.extractModuleId(context, uri)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
sealed class FlashIt : Parcelable {
|
||||
data class FlashBoot(val boot: Uri? = null, val lkm: LkmSelection, val ota: Boolean, val partition: String? = null) : FlashIt()
|
||||
|
||||
@@ -182,6 +182,7 @@ fun HomeScreen(navigator: DestinationsNavigator) {
|
||||
isSimpleMode = viewModel.isSimpleMode,
|
||||
isHideSusfsStatus = viewModel.isHideSusfsStatus,
|
||||
isHideZygiskImplement = viewModel.isHideZygiskImplement,
|
||||
isHideMetaModuleImplement = viewModel.isHideMetaModuleImplement,
|
||||
showKpmInfo = viewModel.showKpmInfo,
|
||||
lkmMode = viewModel.systemStatus.lkmMode,
|
||||
)
|
||||
@@ -652,6 +653,7 @@ private fun InfoCard(
|
||||
isSimpleMode: Boolean,
|
||||
isHideSusfsStatus: Boolean,
|
||||
isHideZygiskImplement: Boolean,
|
||||
isHideMetaModuleImplement: Boolean,
|
||||
showKpmInfo: Boolean,
|
||||
lkmMode: Boolean?
|
||||
) {
|
||||
@@ -784,6 +786,14 @@ private fun InfoCard(
|
||||
)
|
||||
}
|
||||
|
||||
if (!isHideMetaModuleImplement && !isSimpleMode && systemInfo.metaModuleImplement != "None") {
|
||||
InfoCardItem(
|
||||
stringResource(R.string.home_meta_module_implement),
|
||||
systemInfo.metaModuleImplement,
|
||||
icon = Icons.Default.Extension,
|
||||
)
|
||||
}
|
||||
|
||||
if (!isSimpleMode) {
|
||||
if (lkmMode != true && !showKpmInfo) {
|
||||
val displayVersion =
|
||||
|
||||
@@ -752,6 +752,7 @@ private fun ModuleList(
|
||||
val uninstall = stringResource(R.string.uninstall)
|
||||
val cancel = stringResource(android.R.string.cancel)
|
||||
val moduleUninstallConfirm = stringResource(R.string.module_uninstall_confirm)
|
||||
val metaModuleUninstallConfirm = stringResource(R.string.metamodule_uninstall_confirm)
|
||||
val updateText = stringResource(R.string.module_update)
|
||||
val changelogText = stringResource(R.string.module_changelog)
|
||||
val downloadingText = stringResource(R.string.module_downloading)
|
||||
@@ -847,9 +848,10 @@ private fun ModuleList(
|
||||
suspend fun onModuleUninstallClicked(module: ModuleViewModel.ModuleInfo) {
|
||||
val isUninstall = !module.remove
|
||||
if (isUninstall) {
|
||||
val formatter = if (module.metamodule) metaModuleUninstallConfirm else moduleUninstallConfirm
|
||||
val confirmResult = confirmDialog.awaitConfirm(
|
||||
moduleStr,
|
||||
content = moduleUninstallConfirm.format(module.name),
|
||||
content = formatter.format(module.name),
|
||||
confirm = uninstall,
|
||||
dismiss = cancel
|
||||
)
|
||||
@@ -1199,6 +1201,22 @@ fun ModuleItem(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
if (module.metamodule) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(4.dp),
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier
|
||||
) {
|
||||
Text(
|
||||
text = "META",
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
modifier = Modifier.padding(horizontal = 4.dp, vertical = 1.dp),
|
||||
color = MaterialTheme.colorScheme.onPrimary,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
Surface(
|
||||
shape = RoundedCornerShape(4.dp),
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
@@ -1329,8 +1347,9 @@ fun ModuleItemPreview() {
|
||||
update = true,
|
||||
remove = false,
|
||||
updateJson = "",
|
||||
hasWebUi = false,
|
||||
hasActionScript = false,
|
||||
hasWebUi = true,
|
||||
hasActionScript = true,
|
||||
metamodule = true,
|
||||
dirId = "dirId",
|
||||
config = ModuleConfig(),
|
||||
isVerified = true,
|
||||
|
||||
@@ -19,8 +19,10 @@ import kotlinx.parcelize.Parcelize
|
||||
import com.sukisu.ultra.BuildConfig
|
||||
import com.sukisu.ultra.Natives
|
||||
import com.sukisu.ultra.ksuApp
|
||||
import com.topjohnwu.superuser.io.SuFile
|
||||
import org.json.JSONArray
|
||||
import java.io.File
|
||||
import java.util.Properties
|
||||
|
||||
|
||||
/**
|
||||
@@ -111,6 +113,10 @@ fun install() {
|
||||
Log.w(TAG, "install result: $result, cost: ${SystemClock.elapsedRealtime() - start}ms")
|
||||
}
|
||||
|
||||
fun hasMetaModule(): Boolean {
|
||||
return getMetaModuleImplement() != "None"
|
||||
}
|
||||
|
||||
fun listModules(): String {
|
||||
val shell = getRootShell()
|
||||
|
||||
@@ -575,6 +581,26 @@ fun getSuSFSFeatures(): String {
|
||||
return runCmd(shell, cmd)
|
||||
}
|
||||
|
||||
fun getMetaModuleImplement(): String {
|
||||
try {
|
||||
val metaModuleProp = SuFile.open("/data/adb/metamodule/module.prop")
|
||||
if (!metaModuleProp.isFile) {
|
||||
Log.i(TAG, "Meta module implement: None")
|
||||
return "None"
|
||||
}
|
||||
|
||||
val prop = Properties()
|
||||
prop.load(metaModuleProp.newInputStream())
|
||||
|
||||
val name = prop.getProperty("name")
|
||||
Log.i(TAG, "Meta module implement: $name")
|
||||
return name
|
||||
} catch (t : Throwable) {
|
||||
Log.i(TAG, "Meta module implement: None")
|
||||
return "None"
|
||||
}
|
||||
}
|
||||
|
||||
fun getZygiskImplement(): String {
|
||||
val zygiskModuleIds = listOf(
|
||||
"zygisksu",
|
||||
|
||||
@@ -54,7 +54,8 @@ class HomeViewModel : ViewModel() {
|
||||
val kpmModuleCount: Int = 0,
|
||||
val managersList: Natives.ManagersList? = null,
|
||||
val isDynamicSignEnabled: Boolean = false,
|
||||
val zygiskImplement: String = ""
|
||||
val zygiskImplement: String = "",
|
||||
val metaModuleImplement: String = ""
|
||||
)
|
||||
|
||||
// 状态变量
|
||||
@@ -79,6 +80,8 @@ class HomeViewModel : ViewModel() {
|
||||
private set
|
||||
var isHideZygiskImplement by mutableStateOf(false)
|
||||
private set
|
||||
var isHideMetaModuleImplement by mutableStateOf(false)
|
||||
private set
|
||||
var isHideLinkCard by mutableStateOf(false)
|
||||
private set
|
||||
var showKpmInfo by mutableStateOf(false)
|
||||
@@ -109,6 +112,7 @@ class HomeViewModel : ViewModel() {
|
||||
isHideSusfsStatus = settingsPrefs.getBoolean("is_hide_susfs_status", false)
|
||||
isHideLinkCard = settingsPrefs.getBoolean("is_hide_link_card", false)
|
||||
isHideZygiskImplement = settingsPrefs.getBoolean("is_hide_zygisk_Implement", false)
|
||||
isHideMetaModuleImplement = settingsPrefs.getBoolean("is_hide_meta_module_Implement", false)
|
||||
showKpmInfo = settingsPrefs.getBoolean("show_kpm_info", false)
|
||||
}
|
||||
}
|
||||
@@ -222,7 +226,8 @@ class HomeViewModel : ViewModel() {
|
||||
superuserCount = moduleInfo.second,
|
||||
moduleCount = moduleInfo.third,
|
||||
kpmModuleCount = moduleInfo.fourth,
|
||||
zygiskImplement = moduleInfo.fifth
|
||||
zygiskImplement = moduleInfo.fifth,
|
||||
metaModuleImplement = moduleInfo.sixth
|
||||
)
|
||||
}
|
||||
|
||||
@@ -398,7 +403,7 @@ class HomeViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadModuleInfo(): Tuple5<String, Int, Int, Int, String> {
|
||||
private suspend fun loadModuleInfo(): Tuple6<String, Int, Int, Int, String, String> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val kpmVersion = try {
|
||||
getKpmVersion()
|
||||
@@ -430,7 +435,13 @@ class HomeViewModel : ViewModel() {
|
||||
"None"
|
||||
}
|
||||
|
||||
Tuple5(kpmVersion, superuserCount, moduleCount, kpmModuleCount, zygiskImplement)
|
||||
val metaModuleImplement = try {
|
||||
getMetaModuleImplement()
|
||||
} catch (_: Exception) {
|
||||
"None"
|
||||
}
|
||||
|
||||
Tuple6(kpmVersion, superuserCount, moduleCount, kpmModuleCount, zygiskImplement, metaModuleImplement)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,6 +578,15 @@ class HomeViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
data class Tuple6<T1, T2, T3, T4, T5, T6>(
|
||||
val first: T1,
|
||||
val second: T2,
|
||||
val third: T3,
|
||||
val fourth: T4,
|
||||
val fifth: T5,
|
||||
val sixth: T6
|
||||
)
|
||||
|
||||
data class Tuple5<T1, T2, T3, T4, T5>(
|
||||
val first: T1,
|
||||
val second: T2,
|
||||
|
||||
@@ -85,6 +85,7 @@ class ModuleViewModel : ViewModel() {
|
||||
val updateJson: String,
|
||||
val hasWebUi: Boolean,
|
||||
val hasActionScript: Boolean,
|
||||
val metamodule: Boolean,
|
||||
val dirId: String, // real module id (dir name)
|
||||
var config: ModuleConfig? = null,
|
||||
var isVerified: Boolean = false, // 添加验证状态字段
|
||||
@@ -151,6 +152,7 @@ class ModuleViewModel : ViewModel() {
|
||||
obj.optString("updateJson"),
|
||||
obj.getBooleanCompat("web"),
|
||||
obj.getBooleanCompat("action"),
|
||||
obj.getBooleanCompat("metamodule"),
|
||||
obj.optString("dir_id", obj.getString("id"))
|
||||
)
|
||||
}.toList()
|
||||
@@ -305,6 +307,7 @@ fun ModuleViewModel.ModuleInfo.copy(
|
||||
updateJson: String = this.updateJson,
|
||||
hasWebUi: Boolean = this.hasWebUi,
|
||||
hasActionScript: Boolean = this.hasActionScript,
|
||||
metamodule: Boolean = this.metamodule,
|
||||
dirId: String = this.dirId,
|
||||
config: ModuleConfig? = this.config,
|
||||
isVerified: Boolean = this.isVerified,
|
||||
@@ -312,7 +315,7 @@ fun ModuleViewModel.ModuleInfo.copy(
|
||||
): ModuleViewModel.ModuleInfo {
|
||||
return ModuleViewModel.ModuleInfo(
|
||||
id, name, author, version, versionCode, description,
|
||||
enabled, update, remove, updateJson, hasWebUi, hasActionScript,
|
||||
enabled, update, remove, updateJson, hasWebUi, hasActionScript, metamodule,
|
||||
dirId, config, isVerified, verificationTimestamp
|
||||
)
|
||||
}
|
||||
|
||||
@@ -312,6 +312,16 @@ private fun HideOptionsSettings(
|
||||
onChange = handlers::handleHideZygiskImplementChange
|
||||
)
|
||||
|
||||
// 元模块实现状态信息
|
||||
SwitchSettingItem(
|
||||
icon = Icons.Filled.VisibilityOff,
|
||||
title = stringResource(R.string.hide_meta_module_implement),
|
||||
summary = stringResource(R.string.hide_meta_module_implement_summary),
|
||||
checked = state.isHideMetaModuleImplement,
|
||||
onChange = handlers::handleHideMetaModuleImplementChange
|
||||
)
|
||||
|
||||
// KPM 状态信息隐藏
|
||||
if (Natives.version >= Natives.MINIMAL_SUPPORTED_KPM) {
|
||||
SwitchSettingItem(
|
||||
icon = Icons.Filled.VisibilityOff,
|
||||
|
||||
@@ -341,6 +341,14 @@ class MoreSettingsHandlers(
|
||||
state.isHideZygiskImplement = newValue
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理隐藏元模块实现变更
|
||||
*/
|
||||
fun handleHideMetaModuleImplementChange(newValue: Boolean) {
|
||||
prefs.edit { putBoolean("is_hide_meta_module_Implement", newValue) }
|
||||
state.isHideMetaModuleImplement = newValue
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理隐藏链接卡片变更
|
||||
*/
|
||||
|
||||
@@ -60,6 +60,7 @@ class MoreSettingsState(
|
||||
var isHideOtherInfo by mutableStateOf(prefs.getBoolean("is_hide_other_info", false))
|
||||
var isShowKpmInfo by mutableStateOf(prefs.getBoolean("show_kpm_info", false))
|
||||
var isHideZygiskImplement by mutableStateOf(prefs.getBoolean("is_hide_zygisk_Implement", false))
|
||||
var isHideMetaModuleImplement by mutableStateOf(prefs.getBoolean("is_hide_meta_module_Implement", false))
|
||||
var isHideSusfsStatus by mutableStateOf(prefs.getBoolean("is_hide_susfs_status", false))
|
||||
var isHideLinkCard by mutableStateOf(prefs.getBoolean("is_hide_link_card", false))
|
||||
var isHideTagRow by mutableStateOf(prefs.getBoolean("is_hide_tag_row", false))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="learn_more">了解更多</string>
|
||||
<string name="home">主页</string>
|
||||
<string name="home_not_installed">未安装</string>
|
||||
<string name="home_click_to_install">点击安装</string>
|
||||
@@ -34,6 +35,7 @@
|
||||
<string name="reboot_edl">重启到 EDL</string>
|
||||
<string name="about">关于</string>
|
||||
<string name="module_uninstall_confirm">确定要卸载模块 %s 吗?</string>
|
||||
<string name="metamodule_uninstall_confirm">"您确定要卸载模块 %s 吗?此操作将影响所有模块,并且元模块提供的某些功能(如挂载)将不再工作。 "</string>
|
||||
<string name="module_uninstall_success">%s 已卸载</string>
|
||||
<string name="module_uninstall_failed">卸载失败:%s</string>
|
||||
<string name="module_version">版本</string>
|
||||
@@ -188,10 +190,12 @@
|
||||
<string name="hide_susfs_status_summary">隐藏主页上的 SuSFS 状态信息</string>
|
||||
<string name="hide_zygisk_implement">隐藏 Zygisk 状态信息</string>
|
||||
<string name="hide_zygisk_implement_summary">隐藏主页上的 Zygisk 实现状态信息</string>
|
||||
<string name="hide_meta_module_implement">隐藏元模块状态信息</string>
|
||||
<string name="hide_meta_module_implement_summary">隐藏主页上的元模块实现状态信息</string>
|
||||
<string name="hide_link_card">隐藏链接卡片</string>
|
||||
<string name="hide_link_card_summary">隐藏主页上的链接卡片信息</string>
|
||||
<string name="hide_tag_card">隐藏模块标签行</string>
|
||||
<string name="hide_tag_card_summary">隐藏模块卡片中的文件夹名称和大小标签</string>
|
||||
<string name="hide_tag_card_summary">隐藏模块卡片中的文件夹名称、大小标签和是否为元模块</string>
|
||||
<string name="theme_mode">主题模式</string>
|
||||
<string name="theme_follow_system">跟随系统</string>
|
||||
<string name="theme_light">浅色</string>
|
||||
@@ -328,6 +332,8 @@
|
||||
<string name="module_failed_count">%d 个模块安装失败</string>
|
||||
<string name="module_download_error">模块下载失败</string>
|
||||
<string name="kernel_flashing">内核刷写</string>
|
||||
<string name="warning_of_meta_module_title">需要元模块</string>
|
||||
<string name="warning_of_meta_module_summary">这个模块需要挂载一些文件。需要安装元模块,使它正常工作</string>
|
||||
<!-- 分类相关 -->
|
||||
<string name="category_all_apps">全部</string>
|
||||
<string name="category_root_apps">Root</string>
|
||||
@@ -588,6 +594,7 @@
|
||||
<string name="no_active_manager">无活跃管理器</string>
|
||||
<string name="default_signature">SukiSU</string>
|
||||
<string name="home_zygisk_implement">Zygisk 实现</string>
|
||||
<string name="home_meta_module_implement">元模块实现</string>
|
||||
<!-- 循环路径相关 -->
|
||||
<string name="susfs_tab_sus_loop_paths">SuS 循环路径</string>
|
||||
<string name="susfs_add_sus_loop_path">添加 SuS 循环路径</string>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">SukiSU Ultra</string>
|
||||
<string name="home">Home</string>
|
||||
<string name="learn_more">Learn more</string>
|
||||
<string name="home_not_installed">Not installed</string>
|
||||
<string name="home_click_to_install">Click to install</string>
|
||||
<string name="home_working">Working</string>
|
||||
@@ -35,6 +36,7 @@
|
||||
<string name="reboot_edl">Reboot to EDL</string>
|
||||
<string name="about">About</string>
|
||||
<string name="module_uninstall_confirm">Are you sure you want to uninstall module %s?</string>
|
||||
<string name="metamodule_uninstall_confirm">"Are you sure you want to uninstall module %s? This action will affect all modules, and certain features provided by the metamodule (such as mounting) will no longer work. "</string>
|
||||
<string name="module_uninstall_success">%s uninstalled</string>
|
||||
<string name="module_uninstall_failed">Failed to uninstall: %s</string>
|
||||
<string name="module_version">Version</string>
|
||||
@@ -190,10 +192,12 @@
|
||||
<string name="hide_susfs_status_summary">Hide SuSFS status information on the home page</string>
|
||||
<string name="hide_zygisk_implement">Hide Zygisk status</string>
|
||||
<string name="hide_zygisk_implement_summary">Hide Zygisk implementation information on the home page</string>
|
||||
<string name="hide_meta_module_implement">Hide Meta Module status</string>
|
||||
<string name="hide_meta_module_implement_summary">Hide Meta Module implementation information on the home page</string>
|
||||
<string name="hide_link_card">Hide Link Card Status</string>
|
||||
<string name="hide_link_card_summary">Hide link card information on the home page</string>
|
||||
<string name="hide_tag_card">Hide module label rows</string>
|
||||
<string name="hide_tag_card_summary">Hide folder name and size labels in module cards</string>
|
||||
<string name="hide_tag_card_summary">Hide folder name,size,metamodule notice labels in module cards</string>
|
||||
<string name="theme_mode">Theme</string>
|
||||
<string name="theme_follow_system">Follow system</string>
|
||||
<string name="theme_light">Light</string>
|
||||
@@ -331,6 +335,8 @@
|
||||
<string name="module_failed_count">%d Failed to install a new module</string>
|
||||
<string name="module_download_error">Module download failed</string>
|
||||
<string name="kernel_flashing">Kernel Flashing</string>
|
||||
<string name="warning_of_meta_module_title">Require Meta module</string>
|
||||
<string name="warning_of_meta_module_summary">This module want to mount /system, meta module will handle that. Otherwise, it might not work.</string>
|
||||
<!-- 分类相关 -->
|
||||
<string name="category_all_apps">All</string>
|
||||
<string name="category_root_apps">Root</string>
|
||||
@@ -591,6 +597,7 @@
|
||||
<string name="no_active_manager">No active manager</string>
|
||||
<string name="default_signature">SukiSU</string>
|
||||
<string name="home_zygisk_implement">Zygisk implement</string>
|
||||
<string name="home_meta_module_implement">Meta Module implement</string>
|
||||
<!-- 循环路径相关 -->
|
||||
<string name="susfs_tab_sus_loop_paths">SUS Loop Paths</string>
|
||||
<string name="susfs_add_sus_loop_path">Add SUS Loop Path</string>
|
||||
|
||||
Reference in New Issue
Block a user