manager: remake home page
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
package me.weishu.kernelsu.ui.screen
|
package me.weishu.kernelsu.ui.screen
|
||||||
|
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
@@ -30,14 +28,10 @@ import androidx.compose.ui.unit.dp
|
|||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.annotation.RootNavGraph
|
import com.ramcosta.composedestinations.annotation.RootNavGraph
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import me.weishu.kernelsu.*
|
import me.weishu.kernelsu.*
|
||||||
import me.weishu.kernelsu.R
|
import me.weishu.kernelsu.R
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.SettingScreenDestination
|
import me.weishu.kernelsu.ui.screen.destinations.SettingScreenDestination
|
||||||
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
import me.weishu.kernelsu.ui.util.*
|
||||||
import me.weishu.kernelsu.ui.util.reboot
|
|
||||||
import me.weishu.kernelsu.ui.util.getSELinuxStatus
|
|
||||||
import me.weishu.kernelsu.ui.util.install
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@RootNavGraph(start = true)
|
@RootNavGraph(start = true)
|
||||||
@@ -67,6 +61,8 @@ fun HomeScreen(navigator: DestinationsNavigator) {
|
|||||||
|
|
||||||
StatusCard(kernelVersion, ksuVersion)
|
StatusCard(kernelVersion, ksuVersion)
|
||||||
InfoCard()
|
InfoCard()
|
||||||
|
DonateCard()
|
||||||
|
AboutCard()
|
||||||
Spacer(Modifier)
|
Spacer(Modifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +98,8 @@ private fun TopBar(onSettingsClick: () -> Unit) {
|
|||||||
|
|
||||||
RebootDropdownItem(id = R.string.reboot)
|
RebootDropdownItem(id = R.string.reboot)
|
||||||
|
|
||||||
val pm = LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
|
val pm =
|
||||||
|
LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && pm?.isRebootingUserspaceSupported == true) {
|
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_userspace, reason = "userspace")
|
||||||
}
|
}
|
||||||
@@ -161,6 +158,16 @@ private fun StatusCard(kernelVersion: KernelVersion, ksuVersion: Int?) {
|
|||||||
text = stringResource(R.string.home_working_version, ksuVersion),
|
text = stringResource(R.string.home_working_version, ksuVersion),
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyMedium
|
||||||
)
|
)
|
||||||
|
Spacer(Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.home_superuser_count, getSuperuserCount()),
|
||||||
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.home_module_count, getModuleCount()),
|
||||||
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kernelVersion.isGKI() -> {
|
kernelVersion.isGKI() -> {
|
||||||
@@ -197,11 +204,69 @@ private fun StatusCard(kernelVersion: KernelVersion, ksuVersion: Int?) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AboutCard() {
|
||||||
|
val uriHandler = LocalUriHandler.current
|
||||||
|
|
||||||
|
ElevatedCard {
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable {
|
||||||
|
uriHandler.openUri("https://kernelsu.org/guide/what-is-kernelsu.html")
|
||||||
|
}
|
||||||
|
.padding(24.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Column() {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.home_learn_kernelsu),
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.home_click_to_learn_kernelsu),
|
||||||
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DonateCard() {
|
||||||
|
val uriHandler = LocalUriHandler.current
|
||||||
|
|
||||||
|
ElevatedCard {
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable {
|
||||||
|
uriHandler.openUri("https://patreon.com/weishu")
|
||||||
|
}
|
||||||
|
.padding(24.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Column() {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.home_support_title),
|
||||||
|
style = MaterialTheme.typography.titleSmall
|
||||||
|
)
|
||||||
|
Spacer(Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.home_support_content),
|
||||||
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun InfoCard() {
|
private fun InfoCard() {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val snackbarHost = LocalSnackbarHost.current
|
|
||||||
val scope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
ElevatedCard {
|
ElevatedCard {
|
||||||
Column(
|
Column(
|
||||||
@@ -221,39 +286,19 @@ private fun InfoCard() {
|
|||||||
|
|
||||||
InfoCardItem(stringResource(R.string.home_kernel), uname.release)
|
InfoCardItem(stringResource(R.string.home_kernel), uname.release)
|
||||||
|
|
||||||
Spacer(Modifier.height(24.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
InfoCardItem(stringResource(R.string.home_manager_version), getManagerVersion(context))
|
InfoCardItem(stringResource(R.string.home_manager_version), getManagerVersion(context))
|
||||||
|
|
||||||
Spacer(Modifier.height(24.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
InfoCardItem(stringResource(R.string.home_api), Build.VERSION.SDK_INT.toString())
|
|
||||||
|
|
||||||
Spacer(Modifier.height(24.dp))
|
|
||||||
InfoCardItem(stringResource(R.string.home_abi), Build.SUPPORTED_ABIS.joinToString(", "))
|
|
||||||
|
|
||||||
Spacer(Modifier.height(24.dp))
|
|
||||||
InfoCardItem(stringResource(R.string.home_fingerprint), Build.FINGERPRINT)
|
InfoCardItem(stringResource(R.string.home_fingerprint), Build.FINGERPRINT)
|
||||||
|
|
||||||
Spacer(Modifier.height(24.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
InfoCardItem(stringResource(R.string.home_securitypatch), Build.VERSION.SECURITY_PATCH)
|
|
||||||
|
|
||||||
Spacer(Modifier.height(24.dp))
|
|
||||||
InfoCardItem(stringResource(R.string.home_selinux_status), getSELinuxStatus())
|
InfoCardItem(stringResource(R.string.home_selinux_status), getSELinuxStatus())
|
||||||
|
|
||||||
val copiedMessage = stringResource(R.string.home_copied_to_clipboard)
|
|
||||||
TextButton(
|
|
||||||
modifier = Modifier.align(Alignment.End),
|
|
||||||
onClick = {
|
|
||||||
val cm = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
cm.setPrimaryClip(ClipData.newPlainText("KernelSU", contents.toString()))
|
|
||||||
scope.launch { snackbarHost.showSnackbar(copiedMessage) }
|
|
||||||
},
|
|
||||||
content = { Text(stringResource(android.R.string.copy)) }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getManagerVersion(context: Context) : String {
|
fun getManagerVersion(context: Context): String {
|
||||||
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
|
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
|
||||||
return "${packageInfo.versionName} (${packageInfo.versionCode})"
|
return "${packageInfo.versionName} (${packageInfo.versionCode})"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ import com.topjohnwu.superuser.CallbackList
|
|||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
import me.weishu.kernelsu.BuildConfig
|
import me.weishu.kernelsu.BuildConfig
|
||||||
|
import me.weishu.kernelsu.Natives
|
||||||
import me.weishu.kernelsu.ksuApp
|
import me.weishu.kernelsu.ksuApp
|
||||||
|
import me.weishu.kernelsu.ui.viewmodel.ModuleViewModel
|
||||||
|
import org.json.JSONArray
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
@@ -54,10 +57,23 @@ fun install() {
|
|||||||
fun listModules(): String {
|
fun listModules(): String {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
|
|
||||||
val out = shell.newJob().add("${getKsuDaemonPath()} module list").to(ArrayList(), null).exec().out
|
val out =
|
||||||
|
shell.newJob().add("${getKsuDaemonPath()} module list").to(ArrayList(), null).exec().out
|
||||||
return out.joinToString("\n").ifBlank { "[]" }
|
return out.joinToString("\n").ifBlank { "[]" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getModuleCount(): Int {
|
||||||
|
val result = listModules()
|
||||||
|
runCatching {
|
||||||
|
val array = JSONArray(result)
|
||||||
|
return array.length()
|
||||||
|
}.getOrElse { return 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSuperuserCount(): Int {
|
||||||
|
return Natives.getAllowList().size
|
||||||
|
}
|
||||||
|
|
||||||
fun toggleModule(id: String, enable: Boolean): Boolean {
|
fun toggleModule(id: String, enable: Boolean): Boolean {
|
||||||
val cmd = if (enable) {
|
val cmd = if (enable) {
|
||||||
"module enable $id"
|
"module enable $id"
|
||||||
@@ -69,14 +85,14 @@ fun toggleModule(id: String, enable: Boolean): Boolean {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun uninstallModule(id: String) : Boolean {
|
fun uninstallModule(id: String): Boolean {
|
||||||
val cmd = "module uninstall $id"
|
val cmd = "module uninstall $id"
|
||||||
val result = execKsud(cmd)
|
val result = execKsud(cmd)
|
||||||
Log.i(TAG, "uninstall module $id result: $result")
|
Log.i(TAG, "uninstall module $id result: $result")
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun installModule(uri: Uri, onFinish: (Boolean)->Unit, onOutput: (String) -> Unit) : Boolean {
|
fun installModule(uri: Uri, onFinish: (Boolean) -> Unit, onOutput: (String) -> Unit): Boolean {
|
||||||
val resolver = ksuApp.contentResolver
|
val resolver = ksuApp.contentResolver
|
||||||
with(resolver.openInputStream(uri)) {
|
with(resolver.openInputStream(uri)) {
|
||||||
val file = File(ksuApp.cacheDir, "module.zip")
|
val file = File(ksuApp.cacheDir, "module.zip")
|
||||||
@@ -93,7 +109,8 @@ fun installModule(uri: Uri, onFinish: (Boolean)->Unit, onOutput: (String) -> Uni
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = shell.newJob().add("${getKsuDaemonPath()} $cmd").to(callbackList, callbackList).exec()
|
val result =
|
||||||
|
shell.newJob().add("${getKsuDaemonPath()} $cmd").to(callbackList, callbackList).exec()
|
||||||
Log.i("KernelSU", "install module $uri result: $result")
|
Log.i("KernelSU", "install module $uri result: $result")
|
||||||
|
|
||||||
file.delete()
|
file.delete()
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name" translatable="false">KernelSU</string>
|
<string name="home">ホーム</string>
|
||||||
<string name="home">ホーム</string>
|
|
||||||
<string name="home_not_installed">未インストール</string>
|
<string name="home_not_installed">未インストール</string>
|
||||||
<string name="home_click_to_install">タップでインストール</string>
|
<string name="home_click_to_install">タップでインストール</string>
|
||||||
<string name="home_working">動作中</string>
|
<string name="home_working">動作中</string>
|
||||||
@@ -40,6 +39,7 @@
|
|||||||
<string name="reboot_edl">EDLで再起動</string>
|
<string name="reboot_edl">EDLで再起動</string>
|
||||||
<string name="about">アプリについて</string>
|
<string name="about">アプリについて</string>
|
||||||
<string name="require_kernel_version_8">KernelSU バージョン8以降が必要です</string>
|
<string name="require_kernel_version_8">KernelSU バージョン8以降が必要です</string>
|
||||||
|
<string name="module_uninstall_confirm">モジュール %s をアンインストールしますか?</string>
|
||||||
<string name="module_uninstall_success">%sをアンインストールしました</string>
|
<string name="module_uninstall_success">%sをアンインストールしました</string>
|
||||||
<string name="module_uninstall_failed">アンインストールに失敗: %s</string>
|
<string name="module_uninstall_failed">アンインストールに失敗: %s</string>
|
||||||
<string name="module_version">バージョン</string>
|
<string name="module_version">バージョン</string>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<string name="home_click_to_install">点击安装</string>
|
<string name="home_click_to_install">点击安装</string>
|
||||||
<string name="home_working">工作中</string>
|
<string name="home_working">工作中</string>
|
||||||
<string name="home_working_version">版本: %d</string>
|
<string name="home_working_version">版本: %d</string>
|
||||||
|
<string name="home_superuser_count">超级用户数:%d</string>
|
||||||
<string name="home_unsupported">不支持</string>
|
<string name="home_unsupported">不支持</string>
|
||||||
<string name="home_unsupported_reason">KernelSU 现在只支持 GKI 内核</string>
|
<string name="home_unsupported_reason">KernelSU 现在只支持 GKI 内核</string>
|
||||||
<string name="home_copied_to_clipboard">已复制到剪贴板</string>
|
<string name="home_copied_to_clipboard">已复制到剪贴板</string>
|
||||||
@@ -53,4 +54,9 @@
|
|||||||
<string name="safe_mode">安全模式</string>
|
<string name="safe_mode">安全模式</string>
|
||||||
<string name="reboot_to_apply">重启生效</string>
|
<string name="reboot_to_apply">重启生效</string>
|
||||||
<string name="module_magisk_conflict">所有模块已被禁用,因为它与 Magisk 的模块系统有冲突!</string>
|
<string name="module_magisk_conflict">所有模块已被禁用,因为它与 Magisk 的模块系统有冲突!</string>
|
||||||
|
<string name="home_module_count">模块数:%d</string>
|
||||||
|
<string name="home_learn_kernelsu">了解 KernelSU</string>
|
||||||
|
<string name="home_click_to_learn_kernelsu">了解如何安装 KernelSU 以及如何开发模块</string>
|
||||||
|
<string name="home_support_title">支持开发</string>
|
||||||
|
<string name="home_support_content">KernelSU 将保持免费和开源,向开发者捐赠以表示支持。</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
<string name="home_click_to_install">Click to install</string>
|
<string name="home_click_to_install">Click to install</string>
|
||||||
<string name="home_working">Working</string>
|
<string name="home_working">Working</string>
|
||||||
<string name="home_working_version">Version: %d</string>
|
<string name="home_working_version">Version: %d</string>
|
||||||
|
<string name="home_superuser_count">Superusers: %d</string>
|
||||||
|
<string name="home_module_count">Modules: %d</string>
|
||||||
<string name="home_unsupported">Unsupported</string>
|
<string name="home_unsupported">Unsupported</string>
|
||||||
<string name="home_unsupported_reason">KernelSU only supports GKI kernels now</string>
|
<string name="home_unsupported_reason">KernelSU only supports GKI kernels now</string>
|
||||||
<string name="home_copied_to_clipboard">Copied to clipboard</string>
|
<string name="home_copied_to_clipboard">Copied to clipboard</string>
|
||||||
@@ -57,5 +59,8 @@
|
|||||||
<string name="safe_mode">Safe mode</string>
|
<string name="safe_mode">Safe mode</string>
|
||||||
<string name="reboot_to_apply">Reboot to take effect</string>
|
<string name="reboot_to_apply">Reboot to take effect</string>
|
||||||
<string name="module_magisk_conflict">Modules are disabled because it is conflict with Magisk\'s!</string>
|
<string name="module_magisk_conflict">Modules are disabled because it is conflict with Magisk\'s!</string>
|
||||||
|
<string name="home_learn_kernelsu">Learn KernelSU</string>
|
||||||
|
<string name="home_click_to_learn_kernelsu">Learn how to install KernelSU and use modules</string>
|
||||||
|
<string name="home_support_title">Support Us</string>
|
||||||
|
<string name="home_support_content">KernelSU is, and always will be, free, and open source. You can however show us that you care by making a donation.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user