添加KPM状态检查功能,并更新相关UI文本

This commit is contained in:
ShirkNeko
2025-03-31 22:11:52 +08:00
parent 8055aed507
commit 37b00d49c8
5 changed files with 158 additions and 52 deletions

View File

@@ -51,6 +51,7 @@ import androidx.compose.animation.shrinkVertically
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import shirkneko.zako.sukisu.ui.theme.CardConfig import shirkneko.zako.sukisu.ui.theme.CardConfig
import androidx.core.content.edit import androidx.core.content.edit
import shirkneko.zako.sukisu.ui.util.KernelConfigUtils.isKpmEnabled
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph>(start = true) @Destination<RootGraph>(start = true)
@@ -157,6 +158,7 @@ fun HomeScreen(navigator: DestinationsNavigator) {
if (!isSimpleMode) { if (!isSimpleMode) {
DonateCard() DonateCard()
LearnMoreCard() LearnMoreCard()
ContributionCard()
} }
Spacer(Modifier) Spacer(Modifier)
@@ -347,6 +349,15 @@ private fun StatusCard(
style = MaterialTheme.typography.bodyMedium style = MaterialTheme.typography.bodyMedium
) )
} }
Spacer(modifier = Modifier.height(4.dp))
if (isKpmEnabled()) {
val kpmVersion = getKpmVersion()
Text(
text = stringResource(R.string.home_kpm_version, kpmVersion),
style = MaterialTheme.typography.bodyMedium
)
}
} }
} }
@@ -404,6 +415,32 @@ fun WarningCard(
} }
} }
} }
@Composable
fun ContributionCard() {
ElevatedCard(
colors = getCardColors(MaterialTheme.colorScheme.secondaryContainer),
elevation = CardDefaults.cardElevation(defaultElevation = getCardElevation())
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(24.dp),
verticalAlignment = Alignment.CenterVertically
) {
Column {
Text(
text = stringResource(R.string.home_ContributionCard_kernelsu),
style = MaterialTheme.typography.titleSmall
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_click_to_ContributionCard_kernelsu),
style = MaterialTheme.typography.bodyMedium
)
}
}
}
}
@Composable @Composable
fun LearnMoreCard() { fun LearnMoreCard() {

View File

@@ -1,6 +1,7 @@
package shirkneko.zako.sukisu.ui.screen package shirkneko.zako.sukisu.ui.screen
import android.app.Activity.RESULT_OK import android.app.Activity.RESULT_OK
import android.content.Context
import android.content.Intent import android.content.Intent
import android.util.Log import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
@@ -35,7 +36,15 @@ import shirkneko.zako.sukisu.ui.viewmodel.KpmViewModel
import shirkneko.zako.sukisu.ui.util.loadKpmModule import shirkneko.zako.sukisu.ui.util.loadKpmModule
import shirkneko.zako.sukisu.ui.util.unloadKpmModule import shirkneko.zako.sukisu.ui.util.unloadKpmModule
import java.io.File import java.io.File
import androidx.core.content.edit
import shirkneko.zako.sukisu.ui.theme.ThemeConfig
/**
* KPM 管理界面
* 以下内核模块功能由KernelPatch开发经过修改后加入SukiSU Ultra的内核模块功能
* 开发者Shirkneko, Liaokong
*/
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Destination<RootGraph> @Destination<RootGraph>
@Composable @Composable
@@ -48,6 +57,11 @@ fun KpmScreen(
val snackBarHost = remember { SnackbarHostState() } val snackBarHost = remember { SnackbarHostState() }
val confirmDialog = rememberConfirmDialog() val confirmDialog = rememberConfirmDialog()
val loadingDialog = rememberLoadingDialog() val loadingDialog = rememberLoadingDialog()
val cardColor = if (!ThemeConfig.useDynamicColor) {
ThemeConfig.currentTheme.ButtonContrast
} else {
MaterialTheme.colorScheme.secondaryContainer
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
@@ -116,6 +130,9 @@ fun KpmScreen(
viewModel.fetchModuleList() viewModel.fetchModuleList()
} }
} }
// 使用 SharedPreferences 存储声明是否关闭的状态
val sharedPreferences = context.getSharedPreferences("app_preferences", Context.MODE_PRIVATE)
var isNoticeClosed by remember { mutableStateOf(sharedPreferences.getBoolean("is_notice_closed", false)) }
Scaffold( Scaffold(
topBar = { topBar = {
@@ -151,69 +168,96 @@ fun KpmScreen(
) )
}, },
text = { Text(stringResource(R.string.kpm_install)) }, text = { Text(stringResource(R.string.kpm_install)) },
containerColor = MaterialTheme.colorScheme.secondaryContainer, containerColor = cardColor.copy(alpha = 1f),
contentColor = MaterialTheme.colorScheme.onSecondaryContainer contentColor = MaterialTheme.colorScheme.onSecondaryContainer
) )
}, },
snackbarHost = { SnackbarHost(snackBarHost) } snackbarHost = { SnackbarHost(snackBarHost) }
) { padding -> ) { padding ->
PullToRefreshBox( Column(modifier = Modifier.padding(padding)) {
onRefresh = { viewModel.fetchModuleList() }, if (!isNoticeClosed) {
isRefreshing = viewModel.isRefreshing, Row(
modifier = Modifier.padding(padding) modifier = Modifier
) { .fillMaxWidth()
if (viewModel.moduleList.isEmpty()) { .padding(16.dp),
Box( horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically
contentAlignment = Alignment.Center
) { ) {
Text( Text(
stringResource(R.string.kpm_empty), text = stringResource(R.string.kernel_module_notice),
modifier = Modifier.weight(1f),
textAlign = TextAlign.Center textAlign = TextAlign.Center
) )
IconButton(onClick = {
isNoticeClosed = true
sharedPreferences.edit() { putBoolean("is_notice_closed", true) }
}) {
Icon(
imageVector = Icons.Outlined.Close,
contentDescription = stringResource(R.string.close_notice)
)
}
} }
} else { }
LazyColumn(
modifier = Modifier.fillMaxSize(), PullToRefreshBox(
contentPadding = PaddingValues(16.dp), onRefresh = { viewModel.fetchModuleList() },
verticalArrangement = Arrangement.spacedBy(16.dp) isRefreshing = viewModel.isRefreshing,
) { modifier = Modifier
items(viewModel.moduleList) { module -> ) {
val kpmUninstallConfirm = String.format(kpmUninstallConfirmTemplate, module.name) if (viewModel.moduleList.isEmpty()) {
KpmModuleItem( Box(
module = module, modifier = Modifier.fillMaxSize(),
onUninstall = { contentAlignment = Alignment.Center
scope.launch { ) {
val confirmResult = confirmDialog.awaitConfirm( Text(
title = kpmUninstall, stringResource(R.string.kpm_empty),
content = kpmUninstallConfirm, textAlign = TextAlign.Center
confirm = uninstall, )
dismiss = cancel }
) } else {
if (confirmResult == ConfirmResult.Confirmed) { LazyColumn(
val success = loadingDialog.withLoading { modifier = Modifier.fillMaxSize(),
unloadKpmModule(module.id) contentPadding = PaddingValues(16.dp),
} verticalArrangement = Arrangement.spacedBy(16.dp)
Log.d("KsuCli", "unloadKpmModule result: $success") ) {
if (success == "success") { items(viewModel.moduleList) { module ->
viewModel.fetchModuleList() val kpmUninstallConfirm = String.format(kpmUninstallConfirmTemplate, module.name)
snackBarHost.showSnackbar( KpmModuleItem(
message = kpmUninstallSuccess, module = module,
duration = SnackbarDuration.Long onUninstall = {
) scope.launch {
} else { val confirmResult = confirmDialog.awaitConfirm(
snackBarHost.showSnackbar( title = kpmUninstall,
message = kpmUninstallFailed, content = kpmUninstallConfirm,
duration = SnackbarDuration.Long confirm = uninstall,
) dismiss = cancel
)
if (confirmResult == ConfirmResult.Confirmed) {
val success = loadingDialog.withLoading {
unloadKpmModule(module.id)
}
Log.d("KsuCli", "unloadKpmModule result: $success")
if (success == "success") {
viewModel.fetchModuleList()
snackBarHost.showSnackbar(
message = kpmUninstallSuccess,
duration = SnackbarDuration.Long
)
} else {
snackBarHost.showSnackbar(
message = kpmUninstallFailed,
duration = SnackbarDuration.Long
)
}
} }
} }
},
onControl = {
viewModel.loadModuleDetail(module.id)
} }
}, )
onControl = { }
viewModel.loadModuleDetail(module.id)
}
)
} }
} }
} }

View File

@@ -0,0 +1,15 @@
package shirkneko.zako.sukisu.ui.util
import java.io.File
object KernelConfigUtils {
fun isKpmEnabled(): Boolean {
return try {
val config = File("/proc/config.gz").readText()
config.contains("CONFIG_KPM=y")
} catch (e: Exception) {
false
}
}
}

View File

@@ -234,4 +234,9 @@
<string name="kpm_install_confirm">确认安装吗?</string> <string name="kpm_install_confirm">确认安装吗?</string>
<string name="kpm_install_success">安装kpm模块成功</string> <string name="kpm_install_success">安装kpm模块成功</string>
<string name="kpm_install_failed">安装kpm模块失败</string> <string name="kpm_install_failed">安装kpm模块失败</string>
<string name="home_kpm_version">KPM 版本: %s</string>
<string name="close_notice">关闭</string>
<string name="kernel_module_notice">以下内核模块功能由KernelPatch开发经过修改后加入SukiSU Ultra的内核模块功能</string>
<string name="home_ContributionCard_kernelsu">SukiSU Ultra展望</string>
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra未来将会成为一个相对独立的KSU分支但是依然感谢官方KernelSU和MKSU等做出的贡献</string>
</resources> </resources>

View File

@@ -236,6 +236,11 @@
<string name="kpm_install_confirm">Confirm installation?</string> <string name="kpm_install_confirm">Confirm installation?</string>
<string name="kpm_install_success">Installation of kpm module successful</string> <string name="kpm_install_success">Installation of kpm module successful</string>
<string name="kpm_install_failed">Installation of kpm module failed</string> <string name="kpm_install_failed">Installation of kpm module failed</string>
<string name="kpm_args">kpm 参数</string> <string name="kpm_args">kpm parameters</string>
<string name="kpm_control">kpm 控制</string> <string name="kpm_control">kpm control</string>
<string name="home_kpm_version">KPM Version: %s</string>
<string name="close_notice">close</string>
<string name="kernel_module_notice">The following kernel module functions were developed by KernelPatch and modified to include the kernel module functions of SukiSU Ultra</string>
<string name="home_ContributionCard_kernelsu">SukiSU Ultra Look forward to</string>
<string name="home_click_to_ContributionCard_kernelsu">SukiSU Ultra will be a relatively independent branch of KSU in the future, but thanks to the official KernelSU and MKSU etc. for their contributions!</string>
</resources> </resources>