Merge branch 'dev' of https://github.com/ShirkNeko/SukiSU-Ultra into dev
This commit is contained in:
@@ -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() {
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user