[manager]: Use MD3

This commit is contained in:
tiann
2022-12-10 21:14:43 +08:00
parent 51c84400cf
commit 1c1c7e0352
13 changed files with 351 additions and 326 deletions

6
manager/.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View File

@@ -9,10 +9,10 @@ android {
defaultConfig { defaultConfig {
applicationId "me.weishu.kernelsu" applicationId "me.weishu.kernelsu"
minSdk 31 minSdk 26
targetSdk 32 targetSdk 32
versionCode 1 versionCode 10000
versionName "1.0" versionName "0.1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { vectorDrawables {
@@ -27,7 +27,7 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
} }
} }
@@ -61,16 +61,17 @@ dependencies {
implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
implementation 'androidx.activity:activity-compose:1.6.0' implementation 'androidx.activity:activity-compose:1.6.1'
implementation "androidx.compose.ui:ui:$compose_ui_version" implementation "androidx.compose.ui:ui:$compose_ui_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
implementation 'androidx.compose.material:material:1.3.1'
implementation "androidx.compose.material3:material3:1.0.1"
implementation "androidx.compose.material3:material3-window-size-class:1.0.1"
def nav_version = "2.5.3" def nav_version = "2.5.3"
implementation "androidx.navigation:navigation-compose:$nav_version" implementation "androidx.navigation:navigation-compose:$nav_version"
implementation "com.google.accompanist:accompanist-drawablepainter:0.28.0" implementation "com.google.accompanist:accompanist-drawablepainter:0.28.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1" implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"

View File

@@ -1,73 +1,91 @@
package me.weishu.kernelsu package me.weishu.kernelsu
import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.TextUnit import java.util.regex.Pattern
@Composable @Composable
fun HyperlinkText( fun LinkifyText(text: String, modifier: Modifier = Modifier) {
modifier: Modifier = Modifier, val uriHandler = LocalUriHandler.current
fullText: String, val layoutResult = remember {
hyperLinks: Map<String, String>, mutableStateOf<TextLayoutResult?>(null)
textStyle: TextStyle = TextStyle.Default, }
linkTextColor: Color = Color.Blue, val linksList = extractUrls(text)
linkTextFontWeight: FontWeight = FontWeight.Normal,
linkTextDecoration: TextDecoration = TextDecoration.None,
fontSize: TextUnit = TextUnit.Unspecified
) {
val annotatedString = buildAnnotatedString { val annotatedString = buildAnnotatedString {
append(fullText) append(text)
linksList.forEach {
for((key, value) in hyperLinks){
val startIndex = fullText.indexOf(key)
val endIndex = startIndex + key.length
addStyle( addStyle(
style = SpanStyle( style = SpanStyle(
color = linkTextColor, color = Color.Companion.Blue,
fontSize = fontSize, textDecoration = TextDecoration.Underline
fontWeight = linkTextFontWeight,
textDecoration = linkTextDecoration
), ),
start = startIndex, start = it.start,
end = endIndex end = it.end
) )
addStringAnnotation( addStringAnnotation(
tag = "URL", tag = "URL",
annotation = value, annotation = it.url,
start = startIndex, start = it.start,
end = endIndex end = it.end
) )
} }
addStyle(
style = SpanStyle(
fontSize = fontSize
),
start = 0,
end = fullText.length
)
} }
Text(text = annotatedString, modifier = modifier.pointerInput(Unit) {
val uriHandler = LocalUriHandler.current detectTapGestures { offsetPosition ->
layoutResult.value?.let {
ClickableText( val position = it.getOffsetForPosition(offsetPosition)
modifier = modifier, annotatedString.getStringAnnotations(position, position).firstOrNull()
text = annotatedString, ?.let { result ->
style = textStyle, if (result.tag == "URL") {
onClick = { uriHandler.openUri(result.item)
annotatedString }
.getStringAnnotations("URL", it, it) }
.firstOrNull()?.let { stringAnnotation -> }
uriHandler.openUri(stringAnnotation.item)
}
} }
},
onTextLayout = { layoutResult.value = it }
) )
} }
private val urlPattern: Pattern = Pattern.compile(
"(?:^|[\\W])((ht|f)tp(s?):\\/\\/|www\\.)"
+ "(([\\w\\-]+\\.){1,}?([\\w\\-.~]+\\/?)*"
+ "[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*$~@!:/{};']*)",
Pattern.CASE_INSENSITIVE or Pattern.MULTILINE or Pattern.DOTALL
)
fun extractUrls(text: String): List<LinkInfos> {
val matcher = urlPattern.matcher(text)
var matchStart: Int
var matchEnd: Int
val links = arrayListOf<LinkInfos>()
while (matcher.find()) {
matchStart = matcher.start(1)
matchEnd = matcher.end()
var url = text.substring(matchStart, matchEnd)
if (!url.startsWith("http://") && !url.startsWith("https://"))
url = "https://$url"
links.add(LinkInfos(url, matchStart, matchEnd))
}
return links
}
data class LinkInfos(
val url: String,
val start: Int,
val end: Int
)

View File

@@ -1,31 +1,29 @@
@file:OptIn(ExperimentalMaterial3Api::class)
package me.weishu.kernelsu package me.weishu.kernelsu
import AboutDialog import AboutDialog
import Home import Home
import Module import Module
import SuperUser import SuperUser
import SuperUserData
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.* import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.* import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Color.Companion.Gray
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
@@ -35,14 +33,14 @@ import me.weishu.kernelsu.ui.theme.KernelSUTheme
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
KernelSUTheme { KernelSUTheme {
// A surface container using the 'background' color from the theme
Surface( Surface(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background color = MaterialTheme.colorScheme.background
) { ) {
Greeting() MainScreen()
} }
} }
} }
@@ -50,7 +48,68 @@ class MainActivity : ComponentActivity() {
} }
@Composable @Composable
fun Greeting() { fun MainTopAppBar(onMoreClick: () -> Unit) {
TopAppBar(
title = {
Text(
"KernelSU",
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
},
actions = {
IconButton(onClick = onMoreClick) {
Icon(
imageVector = Icons.Filled.MoreVert,
contentDescription = "Localized description"
)
}
}
)
}
@Composable
fun MainBottomNavigation(items: List<Screen>, navController: NavHostController) {
NavigationBar {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
items.forEachIndexed { index, item ->
NavigationBarItem(
icon = {
Icon(
painter = painterResource(id = item.icon),
contentDescription = ""
)
},
label = { Text(text = stringResource(id = item.resourceId)) },
selected = currentDestination?.hierarchy?.any { it.route == item.route } == true,
onClick = {
navController.navigate(item.route) {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
// Avoid multiple copies of the same destination when
// reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
}
)
}
}
}
@Composable
fun MainScreen() {
val items = listOf( val items = listOf(
Screen.Home, Screen.Home,
@@ -68,68 +127,25 @@ fun Greeting() {
Scaffold( Scaffold(
topBar = { topBar = {
TopAppBar( MainTopAppBar {
title = { showAboutDialog = true
Text(text = "KernelSU") }
},
backgroundColor = MaterialTheme.colors.primary,
contentColor = Color.White,
elevation = 12.dp,
actions = {
IconButton(onClick = { /*TODO*/ }) {
Icon(Icons.Filled.Search, contentDescription = "Search")
}
IconButton(onClick = {
showAboutDialog = true
}) {
Icon(Icons.Filled.MoreVert, contentDescription = "More")
}
}
)
}, },
bottomBar = { bottomBar = {
BottomNavigation( MainBottomNavigation(items = items, navController = navController)
backgroundColor = MaterialTheme.colors.background, },
content = { innerPadding ->
NavHost(
navController,
startDestination = Screen.Home.route,
Modifier.padding(innerPadding)
) { ) {
val navBackStackEntry by navController.currentBackStackEntryAsState() composable(Screen.Home.route) { Home() }
val currentDestination = navBackStackEntry?.destination composable(Screen.SuperUser.route) { SuperUser() }
items.forEach { screen -> composable(Screen.Module.route) { Module() }
BottomNavigationItem(
icon = { Icon(painterResource(id = screen.icon), null) },
label = { Text(stringResource(screen.resourceId)) },
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
selectedContentColor = MaterialTheme.colors.primary,
unselectedContentColor = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium),
onClick = {
navController.navigate(screen.route) {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
// Avoid multiple copies of the same destination when
// reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
}
)
}
} }
} }
) { innerPadding -> )
NavHost(
navController,
startDestination = Screen.Home.route,
Modifier.padding(innerPadding)
) {
composable(Screen.Home.route) { Home() }
composable(Screen.SuperUser.route) { SuperUser() }
composable(Screen.Module.route) { Module() }
}
}
} }
@@ -137,13 +153,13 @@ fun Greeting() {
@Composable @Composable
fun DefaultPreview() { fun DefaultPreview() {
KernelSUTheme { KernelSUTheme {
Greeting() MainScreen()
} }
} }
sealed class Screen(val route: String, @StringRes val resourceId: Int, val icon: Int) { sealed class Screen(val route: String, @StringRes val resourceId: Int, val icon: Int) {
object Home : Screen("home", R.string.home, R.drawable.ic_home) object Home : Screen("home", R.string.home, R.drawable.ic_home)
object SuperUser : Screen("superuser", R.string.superuser, R.drawable.ic_superuser) object SuperUser : Screen("superuser", R.string.superuser, R.drawable.ic_superuser)
object Module: Screen("module", R.string.module, R.drawable.ic_module) object Module : Screen("module", R.string.module, R.drawable.ic_module)
} }

View File

@@ -1,86 +1,70 @@
import android.text.method.LinkMovementMethod
import android.text.util.Linkify
import android.util.Patterns
import android.widget.TextView
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.material.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material.Button import androidx.compose.material3.Text
import androidx.compose.material.MaterialTheme import androidx.compose.material3.TextButton
import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color import androidx.compose.runtime.remember
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.platform.LocalContext
import me.weishu.kernelsu.HyperlinkText import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.text.util.LinkifyCompat
import me.weishu.kernelsu.LinkifyText
@Composable
fun DefaultLinkifyText(modifier: Modifier = Modifier, text: String?) {
val context = LocalContext.current
val customLinkifyTextView = remember {
TextView(context)
}
AndroidView(modifier = modifier, factory = { customLinkifyTextView }) { textView ->
textView.text = text ?: ""
LinkifyCompat.addLinks(textView, Linkify.ALL)
Linkify.addLinks(textView, Patterns.PHONE,"tel:",
Linkify.sPhoneNumberMatchFilter, Linkify.sPhoneNumberTransformFilter)
textView.movementMethod = LinkMovementMethod.getInstance()
}
}
@Composable @Composable
fun AboutDialog(openDialog: Boolean, onDismiss: () -> Unit) { fun AboutDialog(openDialog: Boolean, onDismiss: () -> Unit) {
if (openDialog) { if (!openDialog) {
AlertDialog( return
onDismissRequest = {
onDismiss()
},
title = {
Text(text = "About")
},
text = {
Column {
HyperlinkText(
fullText = "Author: weishu",
hyperLinks = mutableMapOf(
"weishu" to "https://github.com/tiann",
),
textStyle = TextStyle(
textAlign = TextAlign.Center,
color = Color.Gray
),
linkTextColor = MaterialTheme.colors.secondary,
)
HyperlinkText(
fullText = "Github: https://github.com/tiann/KernelSU",
hyperLinks = mutableMapOf(
"https://github.com/tiann/KernelSU" to "https://github.com/tiann/KernelSU",
),
textStyle = TextStyle(
textAlign = TextAlign.Center,
color = Color.Gray
),
linkTextColor = MaterialTheme.colors.secondary,
)
HyperlinkText(
fullText = "Telegram: https://t.me/KernelSU",
hyperLinks = mutableMapOf(
"https://t.me/KernelSU" to "https://t.me/KernelSU",
),
textStyle = TextStyle(
textAlign = TextAlign.Center,
color = Color.Gray
),
linkTextColor = MaterialTheme.colors.secondary,
)
HyperlinkText(
fullText = "QQ: https://pd.qq.com/s/8lipl1brp",
hyperLinks = mutableMapOf(
"https://pd.qq.com/s/8lipl1brp" to "https://pd.qq.com/s/8lipl1brp",
),
textStyle = TextStyle(
textAlign = TextAlign.Center,
color = Color.Gray
),
linkTextColor = MaterialTheme.colors.secondary,
)
}
},
confirmButton = {
Button(
onClick = {
onDismiss()
}) {
Text("OK")
}
},
)
} }
AlertDialog(
onDismissRequest = {
onDismiss()
},
title = {
Text(text = "About")
},
text = {
Column {
LinkifyText(text = "Author: weishu")
LinkifyText(text = "Github: https://github.com/tiann/KernelSU")
LinkifyText(text = "Telegram: https://t.me/KernelSU")
LinkifyText(text = "QQ: https://pd.qq.com/s/8lipl1brp")
}
},
confirmButton = {
TextButton(
onClick = {
onDismiss()
}) {
Text("OK")
}
},
)
}
@Preview
@Composable
fun Preview_AboutDialog() {
AboutDialog(true, {})
} }

View File

@@ -3,15 +3,13 @@ import android.system.Os
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material.Card
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Done import androidx.compose.material.icons.filled.Done
import androidx.compose.material.icons.filled.Warning import androidx.compose.material.icons.filled.Warning
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ClipboardManager
import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
@@ -19,7 +17,6 @@ import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import me.weishu.kernelsu.Natives import me.weishu.kernelsu.Natives
import java.util.*
@Composable @Composable
fun Info(label: String, value: String) { fun Info(label: String, value: String) {
@@ -29,7 +26,6 @@ fun Info(label: String, value: String) {
withStyle( withStyle(
style = SpanStyle( style = SpanStyle(
fontWeight = FontWeight.W900, fontWeight = FontWeight.W900,
color = MaterialTheme.colors.secondary
) )
) { ) {
append(value) append(value)
@@ -50,8 +46,6 @@ fun Home() {
.fillMaxWidth() .fillMaxWidth()
.padding(6.dp) .padding(6.dp)
.clickable { }, .clickable { },
elevation = 10.dp,
backgroundColor = MaterialTheme.colors.secondary
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@@ -89,8 +83,6 @@ fun Home() {
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(6.dp) .padding(6.dp)
.clickable { },
elevation = 10.dp
) { ) {
Column( Column(
modifier = Modifier.padding(10.dp) modifier = Modifier.padding(10.dp)

View File

@@ -1,29 +1,20 @@
import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.Text
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Card
import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.tooling.preview.Preview
@Composable @Composable
fun Module() { fun Module() {
Card( Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
modifier = Modifier Text(text = "Coming Soon..")
.fillMaxWidth()
.padding(6.dp)
.clickable { },
elevation = 10.dp
) {
Column(
modifier = Modifier.padding(10.dp)
) {
Text("Coming Soon..")
}
} }
}
@Preview
@Composable
fun Preview() {
Module()
} }

View File

@@ -1,27 +1,29 @@
@file:OptIn(ExperimentalMaterial3Api::class)
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Build
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.Checkbox import androidx.compose.material3.*
import androidx.compose.material.Switch
import androidx.compose.material.Text
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.accompanist.drawablepainter.rememberDrawablePainter import com.google.accompanist.drawablepainter.rememberDrawablePainter
import me.weishu.kernelsu.Natives import me.weishu.kernelsu.Natives
import java.util.* import java.util.*
private const val TAG = "SuperUser"
class SuperUserData( class SuperUserData(
val name: CharSequence, val name: CharSequence,
val description: String, val description: String,
@@ -39,43 +41,30 @@ fun SuperUserItem(
onCheckedChange: (Boolean) -> Unit, onCheckedChange: (Boolean) -> Unit,
onItemClick: () -> Unit onItemClick: () -> Unit
) { ) {
Row(modifier = Modifier
.fillMaxWidth()
.clickable {
onItemClick()
}) {
Image( Column {
painter = rememberDrawablePainter(drawable = superUserData.icon), ListItem(
contentDescription = superUserData.name.toString(), headlineText = { Text(superUserData.name.toString()) },
modifier = Modifier supportingText = { Text(superUserData.description) },
.padding(4.dp) leadingContent = {
.width(48.dp) Image(
.height(48.dp) painter = rememberDrawablePainter(drawable = superUserData.icon),
) contentDescription = superUserData.name.toString(),
modifier = Modifier
Column { .padding(4.dp)
Text( .width(48.dp)
superUserData.name.toString(), .height(48.dp)
modifier = Modifier.padding(4.dp), )
color = Color.Black, },
fontSize = 16.sp trailingContent = {
) Switch(
Text( checked = checked,
superUserData.description, onCheckedChange = onCheckedChange,
modifier = Modifier.padding(4.dp), modifier = Modifier.padding(4.dp)
color = Color.Gray, )
fontSize = 12.sp }
)
}
Spacer(modifier = Modifier.weight(1f))
Switch(
checked = checked,
onCheckedChange = onCheckedChange,
modifier = Modifier.padding(4.dp)
) )
Divider(thickness = Dp.Hairline)
} }
} }
@@ -84,8 +73,8 @@ private fun getAppList(context: Context): List<SuperUserData> {
val allowList = Natives.getAllowList() val allowList = Natives.getAllowList()
val denyList = Natives.getDenyList(); val denyList = Natives.getDenyList();
Log.i("mylog", "allowList: ${Arrays.toString(allowList)}") Log.i(TAG, "allowList: ${Arrays.toString(allowList)}")
Log.i("mylog", "denyList: ${Arrays.toString(denyList)}") Log.i(TAG, "denyList: ${Arrays.toString(denyList)}")
val result = mutableListOf<SuperUserData>() val result = mutableListOf<SuperUserData>()
@@ -110,8 +99,16 @@ private fun getAppList(context: Context): List<SuperUserData> {
} }
} }
val defaultDenyList = denyList.toMutableList()
val shellUid = if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) android.os.Process.SHELL_UID else 2000;
if (!allowList.contains(shellUid)) {
// shell uid is not in allow list, add it to default deny list
defaultDenyList.add(shellUid)
}
// add deny list // add deny list
for (uid in denyList) { for (uid in defaultDenyList) {
val packagesForUid = pm.getPackagesForUid(uid) val packagesForUid = pm.getPackagesForUid(uid)
if (packagesForUid == null || packagesForUid.isEmpty()) { if (packagesForUid == null || packagesForUid.isEmpty()) {
continue continue
@@ -144,7 +141,9 @@ fun SuperUser() {
val apps = remember { list.toMutableStateList() } val apps = remember { list.toMutableStateList() }
if (apps.isEmpty()) { if (apps.isEmpty()) {
Text("No apps found") Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text("No apps request superuser")
}
return return
} }
@@ -171,4 +170,10 @@ fun SuperUser() {
) )
} }
} }
}
@Preview
@Composable
fun Preview_SuperUser() {
SuperUser()
} }

View File

@@ -1,11 +0,0 @@
package me.weishu.kernelsu.ui.theme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Shapes
import androidx.compose.ui.unit.dp
val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(4.dp),
large = RoundedCornerShape(0.dp)
)

View File

@@ -1,36 +1,55 @@
package me.weishu.kernelsu.ui.theme package me.weishu.kernelsu.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material.MaterialTheme import androidx.compose.material3.*
import androidx.compose.material.darkColors
import androidx.compose.material.lightColors
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.ViewCompat
private val DarkColorPalette = darkColors( private val DarkColorScheme = darkColorScheme(
primary = YELLOW, primary = YELLOW,
primaryVariant = YELLOW_DARK, secondary = YELLOW_DARK,
secondary = SECONDARY_DARK tertiary = SECONDARY_DARK
) )
private val LightColorPalette = lightColors( private val LightColorScheme = lightColorScheme(
primary = YELLOW, primary = YELLOW,
primaryVariant = YELLOW_LIGHT, secondary = YELLOW_LIGHT,
secondary = SECONDARY_LIGHT tertiary = SECONDARY_LIGHT
) )
@Composable @Composable
fun KernelSUTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { fun KernelSUTheme(
val colors = if (darkTheme) { darkTheme: Boolean = isSystemInDarkTheme(),
DarkColorPalette // Dynamic color is available on Android 12+
} else { dynamicColor: Boolean = true,
LightColorPalette content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
(view.context as Activity).window.statusBarColor = colorScheme.primary.toArgb()
ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = darkTheme
}
} }
MaterialTheme( MaterialTheme(
colors = colors, colorScheme = colorScheme,
typography = Typography, typography = Typography,
shapes = Shapes,
content = content content = content
) )
} }

View File

@@ -1,28 +1,33 @@
package me.weishu.kernelsu.ui.theme package me.weishu.kernelsu.ui.theme
import androidx.compose.material.Typography
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
// Set of Material typography styles to start with // Set of Material typography styles to start with
val Typography = Typography( val Typography = androidx.compose.material3.Typography(
body1 = TextStyle( bodyLarge = TextStyle(
fontFamily = FontFamily.Default, fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal, fontWeight = FontWeight.Normal,
fontSize = 16.sp fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
) )
/* Other default text styles to override /* Other default text styles to override
button = TextStyle( titleLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.W500,
fontSize = 14.sp
),
caption = TextStyle(
fontFamily = FontFamily.Default, fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal, fontWeight = FontWeight.Normal,
fontSize = 12.sp fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
) )
*/ */
) )

View File

@@ -2,6 +2,5 @@
<resources> <resources>
<style name="Theme.KernelSU" parent="android:Theme.Material.Light.NoActionBar"> <style name="Theme.KernelSU" parent="android:Theme.Material.Light.NoActionBar">
<item name="android:statusBarColor">@color/yellow_700</item>
</style> </style>
</resources> </resources>

View File

@@ -1,6 +1,6 @@
buildscript { buildscript {
ext { ext {
compose_ui_version = '1.1.1' compose_ui_version = '1.3.0'
} }
}// Top-level build file where you can add configuration options common to all sub-projects/modules. }// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { plugins {