[manager]: Use MD3
This commit is contained in:
@@ -9,10 +9,10 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "me.weishu.kernelsu"
|
||||
minSdk 31
|
||||
minSdk 26
|
||||
targetSdk 32
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
versionCode 10000
|
||||
versionName "0.1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
@@ -27,7 +27,7 @@ android {
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
@@ -61,16 +61,17 @@ dependencies {
|
||||
|
||||
implementation 'androidx.core:core-ktx:1.9.0'
|
||||
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-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"
|
||||
implementation "androidx.navigation:navigation-compose:$nav_version"
|
||||
|
||||
implementation "com.google.accompanist:accompanist-drawablepainter:0.28.0"
|
||||
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
|
||||
|
||||
|
||||
|
||||
@@ -1,73 +1,91 @@
|
||||
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.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
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.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@Composable
|
||||
fun HyperlinkText(
|
||||
modifier: Modifier = Modifier,
|
||||
fullText: String,
|
||||
hyperLinks: Map<String, String>,
|
||||
textStyle: TextStyle = TextStyle.Default,
|
||||
linkTextColor: Color = Color.Blue,
|
||||
linkTextFontWeight: FontWeight = FontWeight.Normal,
|
||||
linkTextDecoration: TextDecoration = TextDecoration.None,
|
||||
fontSize: TextUnit = TextUnit.Unspecified
|
||||
) {
|
||||
fun LinkifyText(text: String, modifier: Modifier = Modifier) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val layoutResult = remember {
|
||||
mutableStateOf<TextLayoutResult?>(null)
|
||||
}
|
||||
val linksList = extractUrls(text)
|
||||
val annotatedString = buildAnnotatedString {
|
||||
append(fullText)
|
||||
|
||||
for((key, value) in hyperLinks){
|
||||
|
||||
val startIndex = fullText.indexOf(key)
|
||||
val endIndex = startIndex + key.length
|
||||
append(text)
|
||||
linksList.forEach {
|
||||
addStyle(
|
||||
style = SpanStyle(
|
||||
color = linkTextColor,
|
||||
fontSize = fontSize,
|
||||
fontWeight = linkTextFontWeight,
|
||||
textDecoration = linkTextDecoration
|
||||
color = Color.Companion.Blue,
|
||||
textDecoration = TextDecoration.Underline
|
||||
),
|
||||
start = startIndex,
|
||||
end = endIndex
|
||||
start = it.start,
|
||||
end = it.end
|
||||
)
|
||||
addStringAnnotation(
|
||||
tag = "URL",
|
||||
annotation = value,
|
||||
start = startIndex,
|
||||
end = endIndex
|
||||
annotation = it.url,
|
||||
start = it.start,
|
||||
end = it.end
|
||||
)
|
||||
}
|
||||
addStyle(
|
||||
style = SpanStyle(
|
||||
fontSize = fontSize
|
||||
),
|
||||
start = 0,
|
||||
end = fullText.length
|
||||
)
|
||||
}
|
||||
|
||||
val uriHandler = LocalUriHandler.current
|
||||
|
||||
ClickableText(
|
||||
modifier = modifier,
|
||||
text = annotatedString,
|
||||
style = textStyle,
|
||||
onClick = {
|
||||
annotatedString
|
||||
.getStringAnnotations("URL", it, it)
|
||||
.firstOrNull()?.let { stringAnnotation ->
|
||||
uriHandler.openUri(stringAnnotation.item)
|
||||
}
|
||||
Text(text = annotatedString, modifier = modifier.pointerInput(Unit) {
|
||||
detectTapGestures { offsetPosition ->
|
||||
layoutResult.value?.let {
|
||||
val position = it.getOffsetForPosition(offsetPosition)
|
||||
annotatedString.getStringAnnotations(position, position).firstOrNull()
|
||||
?.let { result ->
|
||||
if (result.tag == "URL") {
|
||||
uriHandler.openUri(result.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
|
||||
)
|
||||
@@ -1,31 +1,29 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package me.weishu.kernelsu
|
||||
|
||||
import AboutDialog
|
||||
import Home
|
||||
import Module
|
||||
import SuperUser
|
||||
import SuperUserData
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
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.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.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavDestination.Companion.hierarchy
|
||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
@@ -35,14 +33,14 @@ import me.weishu.kernelsu.ui.theme.KernelSUTheme
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContent {
|
||||
KernelSUTheme {
|
||||
// A surface container using the 'background' color from the theme
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colors.background
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
Greeting()
|
||||
MainScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,7 +48,68 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
|
||||
@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(
|
||||
Screen.Home,
|
||||
@@ -68,68 +127,25 @@ fun Greeting() {
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = {
|
||||
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")
|
||||
}
|
||||
}
|
||||
)
|
||||
MainTopAppBar {
|
||||
showAboutDialog = true
|
||||
}
|
||||
},
|
||||
bottomBar = {
|
||||
BottomNavigation(
|
||||
backgroundColor = MaterialTheme.colors.background,
|
||||
MainBottomNavigation(items = items, navController = navController)
|
||||
},
|
||||
content = { innerPadding ->
|
||||
NavHost(
|
||||
navController,
|
||||
startDestination = Screen.Home.route,
|
||||
Modifier.padding(innerPadding)
|
||||
) {
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val currentDestination = navBackStackEntry?.destination
|
||||
items.forEach { screen ->
|
||||
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
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
composable(Screen.Home.route) { Home() }
|
||||
composable(Screen.SuperUser.route) { SuperUser() }
|
||||
composable(Screen.Module.route) { Module() }
|
||||
}
|
||||
}
|
||||
) { 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
|
||||
fun DefaultPreview() {
|
||||
KernelSUTheme {
|
||||
Greeting()
|
||||
MainScreen()
|
||||
}
|
||||
}
|
||||
|
||||
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 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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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.material.AlertDialog
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import me.weishu.kernelsu.HyperlinkText
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
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
|
||||
fun AboutDialog(openDialog: Boolean, onDismiss: () -> Unit) {
|
||||
|
||||
if (openDialog) {
|
||||
AlertDialog(
|
||||
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")
|
||||
}
|
||||
},
|
||||
)
|
||||
if (!openDialog) {
|
||||
return
|
||||
}
|
||||
|
||||
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, {})
|
||||
}
|
||||
@@ -3,15 +3,13 @@ import android.system.Os
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
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.filled.Done
|
||||
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.ui.Modifier
|
||||
import androidx.compose.ui.platform.ClipboardManager
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
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.sp
|
||||
import me.weishu.kernelsu.Natives
|
||||
import java.util.*
|
||||
|
||||
@Composable
|
||||
fun Info(label: String, value: String) {
|
||||
@@ -29,7 +26,6 @@ fun Info(label: String, value: String) {
|
||||
withStyle(
|
||||
style = SpanStyle(
|
||||
fontWeight = FontWeight.W900,
|
||||
color = MaterialTheme.colors.secondary
|
||||
)
|
||||
) {
|
||||
append(value)
|
||||
@@ -50,8 +46,6 @@ fun Home() {
|
||||
.fillMaxWidth()
|
||||
.padding(6.dp)
|
||||
.clickable { },
|
||||
elevation = 10.dp,
|
||||
backgroundColor = MaterialTheme.colors.secondary
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
@@ -89,8 +83,6 @@ fun Home() {
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(6.dp)
|
||||
.clickable { },
|
||||
elevation = 10.dp
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(10.dp)
|
||||
|
||||
@@ -1,29 +1,20 @@
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
||||
@Composable
|
||||
fun Module() {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(6.dp)
|
||||
.clickable { },
|
||||
elevation = 10.dp
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(10.dp)
|
||||
) {
|
||||
|
||||
|
||||
Text("Coming Soon..")
|
||||
|
||||
}
|
||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
|
||||
Text(text = "Coming Soon..")
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun Preview() {
|
||||
Module()
|
||||
}
|
||||
@@ -1,27 +1,29 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.Checkbox
|
||||
import androidx.compose.material.Switch
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
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.sp
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import me.weishu.kernelsu.Natives
|
||||
import java.util.*
|
||||
|
||||
private const val TAG = "SuperUser"
|
||||
|
||||
class SuperUserData(
|
||||
val name: CharSequence,
|
||||
val description: String,
|
||||
@@ -39,43 +41,30 @@ fun SuperUserItem(
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
onItemClick: () -> Unit
|
||||
) {
|
||||
Row(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
onItemClick()
|
||||
}) {
|
||||
|
||||
Image(
|
||||
painter = rememberDrawablePainter(drawable = superUserData.icon),
|
||||
contentDescription = superUserData.name.toString(),
|
||||
modifier = Modifier
|
||||
.padding(4.dp)
|
||||
.width(48.dp)
|
||||
.height(48.dp)
|
||||
)
|
||||
|
||||
Column {
|
||||
Text(
|
||||
superUserData.name.toString(),
|
||||
modifier = Modifier.padding(4.dp),
|
||||
color = Color.Black,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
Text(
|
||||
superUserData.description,
|
||||
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)
|
||||
Column {
|
||||
ListItem(
|
||||
headlineText = { Text(superUserData.name.toString()) },
|
||||
supportingText = { Text(superUserData.description) },
|
||||
leadingContent = {
|
||||
Image(
|
||||
painter = rememberDrawablePainter(drawable = superUserData.icon),
|
||||
contentDescription = superUserData.name.toString(),
|
||||
modifier = Modifier
|
||||
.padding(4.dp)
|
||||
.width(48.dp)
|
||||
.height(48.dp)
|
||||
)
|
||||
},
|
||||
trailingContent = {
|
||||
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 denyList = Natives.getDenyList();
|
||||
|
||||
Log.i("mylog", "allowList: ${Arrays.toString(allowList)}")
|
||||
Log.i("mylog", "denyList: ${Arrays.toString(denyList)}")
|
||||
Log.i(TAG, "allowList: ${Arrays.toString(allowList)}")
|
||||
Log.i(TAG, "denyList: ${Arrays.toString(denyList)}")
|
||||
|
||||
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
|
||||
for (uid in denyList) {
|
||||
for (uid in defaultDenyList) {
|
||||
val packagesForUid = pm.getPackagesForUid(uid)
|
||||
if (packagesForUid == null || packagesForUid.isEmpty()) {
|
||||
continue
|
||||
@@ -144,7 +141,9 @@ fun SuperUser() {
|
||||
val apps = remember { list.toMutableStateList() }
|
||||
|
||||
if (apps.isEmpty()) {
|
||||
Text("No apps found")
|
||||
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Text("No apps request superuser")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -171,4 +170,10 @@ fun SuperUser() {
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun Preview_SuperUser() {
|
||||
SuperUser()
|
||||
}
|
||||
@@ -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)
|
||||
)
|
||||
@@ -1,36 +1,55 @@
|
||||
package me.weishu.kernelsu.ui.theme
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.darkColors
|
||||
import androidx.compose.material.lightColors
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
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,
|
||||
primaryVariant = YELLOW_DARK,
|
||||
secondary = SECONDARY_DARK
|
||||
secondary = YELLOW_DARK,
|
||||
tertiary = SECONDARY_DARK
|
||||
)
|
||||
|
||||
private val LightColorPalette = lightColors(
|
||||
private val LightColorScheme = lightColorScheme(
|
||||
primary = YELLOW,
|
||||
primaryVariant = YELLOW_LIGHT,
|
||||
secondary = SECONDARY_LIGHT
|
||||
secondary = YELLOW_LIGHT,
|
||||
tertiary = SECONDARY_LIGHT
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun KernelSUTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
|
||||
val colors = if (darkTheme) {
|
||||
DarkColorPalette
|
||||
} else {
|
||||
LightColorPalette
|
||||
fun KernelSUTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
// Dynamic color is available on Android 12+
|
||||
dynamicColor: Boolean = true,
|
||||
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(
|
||||
colors = colors,
|
||||
colorScheme = colorScheme,
|
||||
typography = Typography,
|
||||
shapes = Shapes,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
@@ -1,28 +1,33 @@
|
||||
package me.weishu.kernelsu.ui.theme
|
||||
|
||||
import androidx.compose.material.Typography
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
// Set of Material typography styles to start with
|
||||
val Typography = Typography(
|
||||
body1 = TextStyle(
|
||||
val Typography = androidx.compose.material3.Typography(
|
||||
bodyLarge = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
/* Other default text styles to override
|
||||
button = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.W500,
|
||||
fontSize = 14.sp
|
||||
),
|
||||
caption = TextStyle(
|
||||
titleLarge = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
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
|
||||
)
|
||||
*/
|
||||
)
|
||||
@@ -2,6 +2,5 @@
|
||||
<resources>
|
||||
|
||||
<style name="Theme.KernelSU" parent="android:Theme.Material.Light.NoActionBar">
|
||||
<item name="android:statusBarColor">@color/yellow_700</item>
|
||||
</style>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user