You've already forked KernelSU
mirror of
https://github.com/tiann/KernelSU.git
synced 2025-08-27 23:46:34 +00:00
manager: Insets stuffs for Android 15 (#2100)
Fix insets on Android 15 Bump dependencies Migrate Compose Destination to v2 Ready for review now
This commit is contained in:
@@ -61,7 +61,6 @@ android {
|
|||||||
val output = it as BaseVariantOutputImpl
|
val output = it as BaseVariantOutputImpl
|
||||||
output.outputFileName = "KernelSU_${managerVersionName}_${managerVersionCode}-$name.apk"
|
output.outputFileName = "KernelSU_${managerVersionName}_${managerVersionCode}-$name.apk"
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin.sourceSets {
|
kotlin.sourceSets {
|
||||||
getByName(name) {
|
getByName(name) {
|
||||||
kotlin.srcDir("build/generated/ksp/$name/kotlin")
|
kotlin.srcDir("build/generated/ksp/$name/kotlin")
|
||||||
@@ -90,10 +89,9 @@ dependencies {
|
|||||||
|
|
||||||
implementation(libs.com.google.accompanist.drawablepainter)
|
implementation(libs.com.google.accompanist.drawablepainter)
|
||||||
implementation(libs.com.google.accompanist.navigation.animation)
|
implementation(libs.com.google.accompanist.navigation.animation)
|
||||||
implementation(libs.com.google.accompanist.systemuicontroller)
|
|
||||||
implementation(libs.com.google.accompanist.webview)
|
implementation(libs.com.google.accompanist.webview)
|
||||||
|
|
||||||
implementation(libs.compose.destinations.animations.core)
|
implementation(libs.compose.destinations.core)
|
||||||
ksp(libs.compose.destinations.ksp)
|
ksp(libs.compose.destinations.ksp)
|
||||||
|
|
||||||
implementation(libs.com.github.topjohnwu.libsu.core)
|
implementation(libs.com.github.topjohnwu.libsu.core)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
android:theme="@style/Theme.KernelSU">
|
android:theme="@style/Theme.KernelSU">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
package me.weishu.kernelsu.ui
|
package me.weishu.kernelsu.ui
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
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.activity.enableEdgeToEdge
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawing
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.NavigationBar
|
import androidx.compose.material3.NavigationBar
|
||||||
import androidx.compose.material3.NavigationBarItem
|
import androidx.compose.material3.NavigationBarItem
|
||||||
@@ -21,12 +27,12 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.ramcosta.composedestinations.DestinationsNavHost
|
import com.ramcosta.composedestinations.DestinationsNavHost
|
||||||
import com.ramcosta.composedestinations.navigation.popBackStack
|
import com.ramcosta.composedestinations.generated.NavGraphs
|
||||||
import com.ramcosta.composedestinations.utils.isRouteOnBackStackAsState
|
import com.ramcosta.composedestinations.utils.isRouteOnBackStackAsState
|
||||||
|
import com.ramcosta.composedestinations.utils.rememberDestinationsNavigator
|
||||||
import me.weishu.kernelsu.Natives
|
import me.weishu.kernelsu.Natives
|
||||||
import me.weishu.kernelsu.ksuApp
|
import me.weishu.kernelsu.ksuApp
|
||||||
import me.weishu.kernelsu.ui.screen.BottomBarDestination
|
import me.weishu.kernelsu.ui.screen.BottomBarDestination
|
||||||
import me.weishu.kernelsu.ui.screen.NavGraphs
|
|
||||||
import me.weishu.kernelsu.ui.theme.KernelSUTheme
|
import me.weishu.kernelsu.ui.theme.KernelSUTheme
|
||||||
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
||||||
import me.weishu.kernelsu.ui.util.rootAvailable
|
import me.weishu.kernelsu.ui.util.rootAvailable
|
||||||
@@ -34,6 +40,13 @@ import me.weishu.kernelsu.ui.util.rootAvailable
|
|||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
||||||
|
// Enable edge to edge
|
||||||
|
enableEdgeToEdge()
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
window.isNavigationBarContrastEnforced = false
|
||||||
|
}
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
@@ -42,7 +55,8 @@ class MainActivity : ComponentActivity() {
|
|||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
Scaffold(
|
Scaffold(
|
||||||
bottomBar = { BottomBar(navController) },
|
bottomBar = { BottomBar(navController) },
|
||||||
snackbarHost = { SnackbarHost(snackbarHostState) }
|
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||||
|
contentWindowInsets = WindowInsets(0, 0, 0, 0)
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalSnackbarHost provides snackbarHostState,
|
LocalSnackbarHost provides snackbarHostState,
|
||||||
@@ -61,9 +75,13 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun BottomBar(navController: NavHostController) {
|
private fun BottomBar(navController: NavHostController) {
|
||||||
|
val navigator = navController.rememberDestinationsNavigator()
|
||||||
val isManager = Natives.becomeManager(ksuApp.packageName)
|
val isManager = Natives.becomeManager(ksuApp.packageName)
|
||||||
val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable()
|
val fullFeatured = isManager && !Natives.requireNewKernel() && rootAvailable()
|
||||||
NavigationBar(tonalElevation = 8.dp) {
|
NavigationBar(
|
||||||
|
tonalElevation = 8.dp,
|
||||||
|
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Bottom + WindowInsetsSides.Horizontal)
|
||||||
|
) {
|
||||||
BottomBarDestination.entries.forEach { destination ->
|
BottomBarDestination.entries.forEach { destination ->
|
||||||
if (!fullFeatured && destination.rootRequired) return@forEach
|
if (!fullFeatured && destination.rootRequired) return@forEach
|
||||||
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
|
val isCurrentDestOnBackStack by navController.isRouteOnBackStackAsState(destination.direction)
|
||||||
@@ -71,11 +89,10 @@ private fun BottomBar(navController: NavHostController) {
|
|||||||
selected = isCurrentDestOnBackStack,
|
selected = isCurrentDestOnBackStack,
|
||||||
onClick = {
|
onClick = {
|
||||||
if (isCurrentDestOnBackStack) {
|
if (isCurrentDestOnBackStack) {
|
||||||
navController.popBackStack(destination.direction, false)
|
navigator.popBackStack(destination.direction, false)
|
||||||
}
|
}
|
||||||
|
navigator.navigate(destination.direction) {
|
||||||
navController.navigate(destination.direction.route) {
|
popUpTo(NavGraphs.root) {
|
||||||
popUpTo(NavGraphs.root.route) {
|
|
||||||
saveState = true
|
saveState = true
|
||||||
}
|
}
|
||||||
launchSingleTop = true
|
launchSingleTop = true
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package me.weishu.kernelsu.ui.component
|
package me.weishu.kernelsu.ui.component
|
||||||
|
|
||||||
import android.graphics.text.LineBreaker
|
import android.graphics.text.LineBreaker
|
||||||
|
import android.os.Build
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.text.Layout
|
import android.text.Layout
|
||||||
import android.text.method.LinkMovementMethod
|
import android.text.method.LinkMovementMethod
|
||||||
@@ -96,8 +97,8 @@ interface ConfirmDialogHandle : DialogHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private abstract class DialogHandleBase(
|
private abstract class DialogHandleBase(
|
||||||
protected val visible: MutableState<Boolean>,
|
val visible: MutableState<Boolean>,
|
||||||
protected val coroutineScope: CoroutineScope
|
val coroutineScope: CoroutineScope
|
||||||
) : DialogHandle {
|
) : DialogHandle {
|
||||||
override val isShown: Boolean
|
override val isShown: Boolean
|
||||||
get() = visible.value
|
get() = visible.value
|
||||||
@@ -432,7 +433,9 @@ private fun MarkdownContent(content: String) {
|
|||||||
TextView(context).apply {
|
TextView(context).apply {
|
||||||
movementMethod = LinkMovementMethod.getInstance()
|
movementMethod = LinkMovementMethod.getInstance()
|
||||||
setSpannableFactory(NoCopySpannableFactory.getInstance())
|
setSpannableFactory(NoCopySpannableFactory.getInstance())
|
||||||
breakStrategy = LineBreaker.BREAK_STRATEGY_SIMPLE
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
breakStrategy = LineBreaker.BREAK_STRATEGY_SIMPLE
|
||||||
|
}
|
||||||
hyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE
|
hyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE
|
||||||
layoutParams = ViewGroup.LayoutParams(
|
layoutParams = ViewGroup.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT
|
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
|||||||
@@ -5,8 +5,12 @@ import androidx.compose.animation.AnimatedVisibility
|
|||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawing
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
@@ -132,7 +136,8 @@ fun SearchAppBar(
|
|||||||
dropdownContent()
|
dropdownContent()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
},
|
||||||
|
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
|
|
||||||
package me.weishu.kernelsu.ui.component.profile
|
package me.weishu.kernelsu.ui.component.profile
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||||
import androidx.compose.foundation.layout.FlowRow
|
import androidx.compose.foundation.layout.FlowRow
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
@@ -20,12 +19,14 @@ import androidx.compose.material3.ExposedDropdownMenuBox
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.MenuAnchorType
|
||||||
import androidx.compose.material3.OutlinedCard
|
import androidx.compose.material3.OutlinedCard
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.OutlinedTextFieldDefaults
|
import androidx.compose.material3.OutlinedTextFieldDefaults
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@@ -86,7 +87,7 @@ fun RootProfileConfig(
|
|||||||
) {
|
) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.menuAnchor()
|
.menuAnchor(MenuAnchorType.PrimaryNotEditable)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
label = { Text(stringResource(R.string.profile_namespace)) },
|
label = { Text(stringResource(R.string.profile_namespace)) },
|
||||||
@@ -184,7 +185,7 @@ fun RootProfileConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun GroupsPanel(selected: List<Groups>, closeSelection: (selection: Set<Groups>) -> Unit) {
|
fun GroupsPanel(selected: List<Groups>, closeSelection: (selection: Set<Groups>) -> Unit) {
|
||||||
val selectGroupsDialog = rememberCustomDialog { dismiss: () -> Unit ->
|
val selectGroupsDialog = rememberCustomDialog { dismiss: () -> Unit ->
|
||||||
@@ -234,14 +235,20 @@ fun GroupsPanel(selected: List<Groups>, closeSelection: (selection: Set<Groups>)
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
OutlinedCard(modifier = Modifier
|
OutlinedCard(
|
||||||
.fillMaxWidth()
|
modifier = Modifier
|
||||||
.padding(16.dp)
|
.fillMaxWidth()
|
||||||
.clickable {
|
.padding(16.dp)
|
||||||
selectGroupsDialog.show()
|
) {
|
||||||
}) {
|
|
||||||
|
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.clickable {
|
||||||
|
selectGroupsDialog.show()
|
||||||
|
}
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
Text(stringResource(R.string.profile_groups))
|
Text(stringResource(R.string.profile_groups))
|
||||||
FlowRow {
|
FlowRow {
|
||||||
selected.forEach { group ->
|
selected.forEach { group ->
|
||||||
@@ -256,7 +263,7 @@ fun GroupsPanel(selected: List<Groups>, closeSelection: (selection: Set<Groups>)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun CapsPanel(
|
fun CapsPanel(
|
||||||
selected: Collection<Capabilities>,
|
selected: Collection<Capabilities>,
|
||||||
@@ -299,14 +306,20 @@ fun CapsPanel(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
OutlinedCard(modifier = Modifier
|
OutlinedCard(
|
||||||
.fillMaxWidth()
|
modifier = Modifier
|
||||||
.padding(16.dp)
|
.fillMaxWidth()
|
||||||
.clickable {
|
.padding(16.dp)
|
||||||
selectCapabilitiesDialog.show()
|
) {
|
||||||
}) {
|
|
||||||
|
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.clickable {
|
||||||
|
selectCapabilitiesDialog.show()
|
||||||
|
}
|
||||||
|
.padding(16.dp)
|
||||||
|
) {
|
||||||
Text(stringResource(R.string.profile_capabilities))
|
Text(stringResource(R.string.profile_capabilities))
|
||||||
FlowRow {
|
FlowRow {
|
||||||
selected.forEach { group ->
|
selected.forEach { group ->
|
||||||
@@ -329,10 +342,10 @@ private fun UidPanel(uid: Int, label: String, onUidChange: (Int) -> Unit) {
|
|||||||
mutableStateOf(false)
|
mutableStateOf(false)
|
||||||
}
|
}
|
||||||
var lastValidUid by remember {
|
var lastValidUid by remember {
|
||||||
mutableStateOf(uid)
|
mutableIntStateOf(uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
val keyboardController = LocalSoftwareKeyboardController.current
|
val keyboardController = LocalSoftwareKeyboardController.current
|
||||||
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
label = { Text(label) },
|
label = { Text(label) },
|
||||||
@@ -365,6 +378,7 @@ private fun UidPanel(uid: Int, label: String, onUidChange: (Int) -> Unit) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun SELinuxPanel(
|
private fun SELinuxPanel(
|
||||||
profile: Natives.Profile,
|
profile: Natives.Profile,
|
||||||
@@ -452,7 +466,7 @@ private fun SELinuxPanel(
|
|||||||
),
|
),
|
||||||
label = { Text(text = stringResource(R.string.profile_selinux_context)) },
|
label = { Text(text = stringResource(R.string.profile_selinux_context)) },
|
||||||
value = profile.context,
|
value = profile.context,
|
||||||
onValueChange = { },
|
onValueChange = { }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import androidx.compose.material3.ExposedDropdownMenuBox
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.MenuAnchorType
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -54,7 +55,7 @@ fun TemplateConfig(
|
|||||||
) {
|
) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.menuAnchor()
|
.menuAnchor(MenuAnchorType.PrimaryNotEditable)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
label = { Text(stringResource(R.string.profile_template)) },
|
label = { Text(stringResource(R.string.profile_template)) },
|
||||||
|
|||||||
@@ -7,10 +7,14 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawing
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
@@ -50,6 +54,9 @@ import androidx.compose.ui.unit.dp
|
|||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.AppProfileTemplateScreenDestination
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.TemplateEditorScreenDestination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.weishu.kernelsu.Natives
|
import me.weishu.kernelsu.Natives
|
||||||
@@ -58,8 +65,6 @@ import me.weishu.kernelsu.ui.component.SwitchItem
|
|||||||
import me.weishu.kernelsu.ui.component.profile.AppProfileConfig
|
import me.weishu.kernelsu.ui.component.profile.AppProfileConfig
|
||||||
import me.weishu.kernelsu.ui.component.profile.RootProfileConfig
|
import me.weishu.kernelsu.ui.component.profile.RootProfileConfig
|
||||||
import me.weishu.kernelsu.ui.component.profile.TemplateConfig
|
import me.weishu.kernelsu.ui.component.profile.TemplateConfig
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.AppProfileTemplateScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.TemplateEditorScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
||||||
import me.weishu.kernelsu.ui.util.forceStopApp
|
import me.weishu.kernelsu.ui.util.forceStopApp
|
||||||
import me.weishu.kernelsu.ui.util.getSepolicy
|
import me.weishu.kernelsu.ui.util.getSepolicy
|
||||||
@@ -73,7 +78,7 @@ import me.weishu.kernelsu.ui.viewmodel.getTemplateInfoById
|
|||||||
* @author weishu
|
* @author weishu
|
||||||
* @date 2023/5/16.
|
* @date 2023/5/16.
|
||||||
*/
|
*/
|
||||||
@Destination
|
@Destination<RootGraph>
|
||||||
@Composable
|
@Composable
|
||||||
fun AppProfileScreen(
|
fun AppProfileScreen(
|
||||||
navigator: DestinationsNavigator,
|
navigator: DestinationsNavigator,
|
||||||
@@ -82,10 +87,8 @@ fun AppProfileScreen(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val snackbarHost = LocalSnackbarHost.current
|
val snackbarHost = LocalSnackbarHost.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val failToUpdateAppProfile =
|
val failToUpdateAppProfile = stringResource(R.string.failed_to_update_app_profile).format(appInfo.label)
|
||||||
stringResource(R.string.failed_to_update_app_profile).format(appInfo.label)
|
val failToUpdateSepolicy = stringResource(R.string.failed_to_update_sepolicy).format(appInfo.label)
|
||||||
val failToUpdateSepolicy =
|
|
||||||
stringResource(R.string.failed_to_update_sepolicy).format(appInfo.label)
|
|
||||||
|
|
||||||
val packageName = appInfo.packageName
|
val packageName = appInfo.packageName
|
||||||
val initialProfile = Natives.getAppProfile(packageName, appInfo.uid)
|
val initialProfile = Natives.getAppProfile(packageName, appInfo.uid)
|
||||||
@@ -98,6 +101,7 @@ fun AppProfileScreen(
|
|||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { TopBar { navigator.popBackStack() } },
|
topBar = { TopBar { navigator.popBackStack() } },
|
||||||
|
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
AppProfileInner(
|
AppProfileInner(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -248,6 +252,7 @@ private fun TopBar(onBack: () -> Unit) {
|
|||||||
onClick = onBack
|
onClick = onBack
|
||||||
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
|
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
|
||||||
},
|
},
|
||||||
|
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import androidx.compose.material.icons.Icons
|
|||||||
import androidx.compose.material.icons.filled.*
|
import androidx.compose.material.icons.filled.*
|
||||||
import androidx.compose.material.icons.outlined.*
|
import androidx.compose.material.icons.outlined.*
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.HomeScreenDestination
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.ModuleScreenDestination
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.SuperUserScreenDestination
|
||||||
import com.ramcosta.composedestinations.spec.DirectionDestinationSpec
|
import com.ramcosta.composedestinations.spec.DirectionDestinationSpec
|
||||||
import me.weishu.kernelsu.R
|
import me.weishu.kernelsu.R
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.HomeScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.SuperUserScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.ModuleScreenDestination
|
|
||||||
|
|
||||||
enum class BottomBarDestination(
|
enum class BottomBarDestination(
|
||||||
val direction: DirectionDestinationSpec,
|
val direction: DirectionDestinationSpec,
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import android.net.Uri
|
|||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawing
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
@@ -35,6 +39,7 @@ import androidx.compose.ui.text.font.FontFamily
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -66,7 +71,7 @@ enum class FlashingStatus {
|
|||||||
* @date 2023/1/1.
|
* @date 2023/1/1.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
@Destination
|
@Destination<RootGraph>
|
||||||
fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
||||||
|
|
||||||
var text by rememberSaveable { mutableStateOf("") }
|
var text by rememberSaveable { mutableStateOf("") }
|
||||||
@@ -139,8 +144,8 @@ fun FlashScreen(navigator: DestinationsNavigator, flashIt: FlashIt) {
|
|||||||
text = { Text(text = reboot) },
|
text = { Text(text = reboot) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
}
|
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
KeyEventBlocker {
|
KeyEventBlocker {
|
||||||
it.key == Key.VolumeDown || it.key == Key.VolumeUp
|
it.key == Key.VolumeDown || it.key == Key.VolumeUp
|
||||||
@@ -227,7 +232,8 @@ private fun TopBar(status: FlashingStatus, onBack: () -> Unit = {}, onSave: () -
|
|||||||
contentDescription = "Localized description"
|
contentDescription = "Localized description"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,32 +27,35 @@ import androidx.compose.ui.platform.LocalUriHandler
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.annotation.RootNavGraph
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.InstallScreenDestination
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.SettingScreenDestination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import me.weishu.kernelsu.*
|
import me.weishu.kernelsu.*
|
||||||
import me.weishu.kernelsu.R
|
import me.weishu.kernelsu.R
|
||||||
import me.weishu.kernelsu.ui.component.rememberConfirmDialog
|
import me.weishu.kernelsu.ui.component.rememberConfirmDialog
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.InstallScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.SettingScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.util.*
|
import me.weishu.kernelsu.ui.util.*
|
||||||
import me.weishu.kernelsu.ui.util.module.LatestVersionInfo
|
import me.weishu.kernelsu.ui.util.module.LatestVersionInfo
|
||||||
|
|
||||||
@RootNavGraph(start = true)
|
@Destination<RootGraph>(start = true)
|
||||||
@Destination
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HomeScreen(navigator: DestinationsNavigator) {
|
fun HomeScreen(navigator: DestinationsNavigator) {
|
||||||
val kernelVersion = getKernelVersion()
|
val kernelVersion = getKernelVersion()
|
||||||
|
|
||||||
Scaffold(topBar = {
|
Scaffold(
|
||||||
TopBar(kernelVersion, onSettingsClick = {
|
topBar = {
|
||||||
navigator.navigate(SettingScreenDestination)
|
TopBar(kernelVersion, onSettingsClick = {
|
||||||
}, onInstallClick = {
|
navigator.navigate(SettingScreenDestination)
|
||||||
navigator.navigate(InstallScreenDestination)
|
}, onInstallClick = {
|
||||||
})
|
navigator.navigate(InstallScreenDestination)
|
||||||
}) { innerPadding ->
|
})
|
||||||
|
},
|
||||||
|
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
|
) { innerPadding ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(innerPadding)
|
.padding(innerPadding)
|
||||||
@@ -103,12 +106,11 @@ fun UpdateCard() {
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val latestVersionInfo = LatestVersionInfo()
|
val latestVersionInfo = LatestVersionInfo()
|
||||||
val newVersion by produceState(initialValue = latestVersionInfo) {
|
val newVersion by produceState(initialValue = latestVersionInfo) {
|
||||||
value = withContext(Dispatchers.IO){
|
value = withContext(Dispatchers.IO) {
|
||||||
checkNewVersion()
|
checkNewVersion()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val currentVersionCode = getManagerVersion(context).second
|
val currentVersionCode = getManagerVersion(context).second
|
||||||
val newVersionCode = newVersion.versionCode
|
val newVersionCode = newVersion.versionCode
|
||||||
val newVersionUrl = newVersion.downloadUrl
|
val newVersionUrl = newVersion.downloadUrl
|
||||||
@@ -158,50 +160,54 @@ private fun TopBar(
|
|||||||
onInstallClick: () -> Unit,
|
onInstallClick: () -> Unit,
|
||||||
onSettingsClick: () -> Unit
|
onSettingsClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
TopAppBar(title = { Text(stringResource(R.string.app_name)) }, actions = {
|
TopAppBar(
|
||||||
if (kernelVersion.isGKI()) {
|
title = { Text(stringResource(R.string.app_name)) },
|
||||||
IconButton(onClick = onInstallClick) {
|
actions = {
|
||||||
|
if (kernelVersion.isGKI()) {
|
||||||
|
IconButton(onClick = onInstallClick) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.Archive,
|
||||||
|
contentDescription = stringResource(id = R.string.install)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var showDropdown by remember { mutableStateOf(false) }
|
||||||
|
IconButton(onClick = {
|
||||||
|
showDropdown = true
|
||||||
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.Archive,
|
imageVector = Icons.Filled.Refresh,
|
||||||
contentDescription = stringResource(id = R.string.install)
|
contentDescription = stringResource(id = R.string.reboot)
|
||||||
|
)
|
||||||
|
|
||||||
|
DropdownMenu(expanded = showDropdown, onDismissRequest = {
|
||||||
|
showDropdown = false
|
||||||
|
}) {
|
||||||
|
|
||||||
|
RebootDropdownItem(id = R.string.reboot)
|
||||||
|
|
||||||
|
val pm =
|
||||||
|
LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
|
||||||
|
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_recovery, reason = "recovery")
|
||||||
|
RebootDropdownItem(id = R.string.reboot_bootloader, reason = "bootloader")
|
||||||
|
RebootDropdownItem(id = R.string.reboot_download, reason = "download")
|
||||||
|
RebootDropdownItem(id = R.string.reboot_edl, reason = "edl")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IconButton(onClick = onSettingsClick) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.Settings,
|
||||||
|
contentDescription = stringResource(id = R.string.settings)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
var showDropdown by remember { mutableStateOf(false) }
|
)
|
||||||
IconButton(onClick = {
|
|
||||||
showDropdown = true
|
|
||||||
}) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Filled.Refresh,
|
|
||||||
contentDescription = stringResource(id = R.string.reboot)
|
|
||||||
)
|
|
||||||
|
|
||||||
DropdownMenu(expanded = showDropdown, onDismissRequest = {
|
|
||||||
showDropdown = false
|
|
||||||
}) {
|
|
||||||
|
|
||||||
RebootDropdownItem(id = R.string.reboot)
|
|
||||||
|
|
||||||
val pm =
|
|
||||||
LocalContext.current.getSystemService(Context.POWER_SERVICE) as PowerManager?
|
|
||||||
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_recovery, reason = "recovery")
|
|
||||||
RebootDropdownItem(id = R.string.reboot_bootloader, reason = "bootloader")
|
|
||||||
RebootDropdownItem(id = R.string.reboot_download, reason = "download")
|
|
||||||
RebootDropdownItem(id = R.string.reboot_edl, reason = "edl")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IconButton(onClick = onSettingsClick) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Filled.Settings,
|
|
||||||
contentDescription = stringResource(id = R.string.settings)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -415,9 +421,10 @@ private fun InfoCard() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getManagerVersion(context: Context): Pair<String, Int> {
|
fun getManagerVersion(context: Context): Pair<String, Long> {
|
||||||
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)!!
|
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)!!
|
||||||
return Pair(packageInfo.versionName!!, packageInfo.versionCode)
|
val versionCode = PackageInfoCompat.getLongVersionCode(packageInfo)
|
||||||
|
return Pair(packageInfo.versionName!!, versionCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
|
|||||||
@@ -9,8 +9,12 @@ import androidx.annotation.StringRes
|
|||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawing
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.FileUpload
|
import androidx.compose.material.icons.filled.FileUpload
|
||||||
@@ -40,13 +44,14 @@ import com.maxkeppeler.sheets.list.ListDialog
|
|||||||
import com.maxkeppeler.sheets.list.models.ListOption
|
import com.maxkeppeler.sheets.list.models.ListOption
|
||||||
import com.maxkeppeler.sheets.list.models.ListSelection
|
import com.maxkeppeler.sheets.list.models.ListSelection
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
||||||
import me.weishu.kernelsu.R
|
import me.weishu.kernelsu.R
|
||||||
import me.weishu.kernelsu.ui.component.DialogHandle
|
import me.weishu.kernelsu.ui.component.DialogHandle
|
||||||
import me.weishu.kernelsu.ui.component.rememberConfirmDialog
|
import me.weishu.kernelsu.ui.component.rememberConfirmDialog
|
||||||
import me.weishu.kernelsu.ui.component.rememberCustomDialog
|
import me.weishu.kernelsu.ui.component.rememberCustomDialog
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.FlashScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.util.LkmSelection
|
import me.weishu.kernelsu.ui.util.LkmSelection
|
||||||
import me.weishu.kernelsu.ui.util.getCurrentKmi
|
import me.weishu.kernelsu.ui.util.getCurrentKmi
|
||||||
import me.weishu.kernelsu.ui.util.getSupportedKmis
|
import me.weishu.kernelsu.ui.util.getSupportedKmis
|
||||||
@@ -58,7 +63,7 @@ import me.weishu.kernelsu.ui.util.rootAvailable
|
|||||||
* @author weishu
|
* @author weishu
|
||||||
* @date 2024/3/12.
|
* @date 2024/3/12.
|
||||||
*/
|
*/
|
||||||
@Destination
|
@Destination<RootGraph>
|
||||||
@Composable
|
@Composable
|
||||||
fun InstallScreen(navigator: DestinationsNavigator) {
|
fun InstallScreen(navigator: DestinationsNavigator) {
|
||||||
var installMethod by remember {
|
var installMethod by remember {
|
||||||
@@ -113,11 +118,14 @@ fun InstallScreen(navigator: DestinationsNavigator) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(topBar = {
|
Scaffold(
|
||||||
TopBar(
|
topBar = {
|
||||||
onBack = { navigator.popBackStack() }, onLkmUpload = onLkmUpload
|
TopBar(
|
||||||
)
|
onBack = { navigator.popBackStack() }, onLkmUpload = onLkmUpload
|
||||||
}) {
|
)
|
||||||
|
},
|
||||||
|
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
|
) {
|
||||||
Column(modifier = Modifier.padding(it)) {
|
Column(modifier = Modifier.padding(it)) {
|
||||||
SelectInstallMethod { method ->
|
SelectInstallMethod { method ->
|
||||||
installMethod = method
|
installMethod = method
|
||||||
@@ -293,15 +301,18 @@ fun rememberSelectKmiDialog(onSelected: (String?) -> Unit): DialogHandle {
|
|||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun TopBar(onBack: () -> Unit = {}, onLkmUpload: () -> Unit = {}) {
|
private fun TopBar(onBack: () -> Unit = {}, onLkmUpload: () -> Unit = {}) {
|
||||||
TopAppBar(title = { Text(stringResource(R.string.install)) }, navigationIcon = {
|
TopAppBar(
|
||||||
IconButton(
|
title = { Text(stringResource(R.string.install)) }, navigationIcon = {
|
||||||
onClick = onBack
|
IconButton(
|
||||||
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
|
onClick = onBack
|
||||||
}, actions = {
|
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
|
||||||
IconButton(onClick = onLkmUpload) {
|
}, actions = {
|
||||||
Icon(Icons.Filled.FileUpload, contentDescription = null)
|
IconButton(onClick = onLkmUpload) {
|
||||||
}
|
Icon(Icons.Filled.FileUpload, contentDescription = null)
|
||||||
})
|
}
|
||||||
|
},
|
||||||
|
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -14,11 +14,15 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
import androidx.compose.foundation.layout.defaultMinSize
|
import androidx.compose.foundation.layout.defaultMinSize
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawing
|
||||||
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.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
@@ -29,7 +33,6 @@ import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
|||||||
import androidx.compose.material.pullrefresh.pullRefresh
|
import androidx.compose.material.pullrefresh.pullRefresh
|
||||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CardDefaults
|
|
||||||
import androidx.compose.material3.ElevatedCard
|
import androidx.compose.material3.ElevatedCard
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||||
@@ -64,6 +67,8 @@ import androidx.compose.ui.unit.Dp
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -73,7 +78,6 @@ import me.weishu.kernelsu.R
|
|||||||
import me.weishu.kernelsu.ui.component.ConfirmResult
|
import me.weishu.kernelsu.ui.component.ConfirmResult
|
||||||
import me.weishu.kernelsu.ui.component.rememberConfirmDialog
|
import me.weishu.kernelsu.ui.component.rememberConfirmDialog
|
||||||
import me.weishu.kernelsu.ui.component.rememberLoadingDialog
|
import me.weishu.kernelsu.ui.component.rememberLoadingDialog
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.FlashScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.util.DownloadListener
|
import me.weishu.kernelsu.ui.util.DownloadListener
|
||||||
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
import me.weishu.kernelsu.ui.util.LocalSnackbarHost
|
||||||
import me.weishu.kernelsu.ui.util.download
|
import me.weishu.kernelsu.ui.util.download
|
||||||
@@ -85,7 +89,7 @@ import me.weishu.kernelsu.ui.viewmodel.ModuleViewModel
|
|||||||
import me.weishu.kernelsu.ui.webui.WebUIActivity
|
import me.weishu.kernelsu.ui.webui.WebUIActivity
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
|
||||||
@Destination
|
@Destination<RootGraph>
|
||||||
@Composable
|
@Composable
|
||||||
fun ModuleScreen(navigator: DestinationsNavigator) {
|
fun ModuleScreen(navigator: DestinationsNavigator) {
|
||||||
val viewModel = viewModel<ModuleViewModel>()
|
val viewModel = viewModel<ModuleViewModel>()
|
||||||
@@ -102,41 +106,46 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
|||||||
|
|
||||||
val hideInstallButton = isSafeMode || hasMagisk
|
val hideInstallButton = isSafeMode || hasMagisk
|
||||||
|
|
||||||
Scaffold(topBar = {
|
Scaffold(
|
||||||
TopBar()
|
topBar = {
|
||||||
}, floatingActionButton = if (hideInstallButton) {
|
TopBar()
|
||||||
{ /* Empty */ }
|
},
|
||||||
} else {
|
floatingActionButton = {
|
||||||
{
|
if (hideInstallButton) {
|
||||||
val moduleInstall = stringResource(id = R.string.module_install)
|
/* Empty */
|
||||||
val selectZipLauncher = rememberLauncherForActivityResult(
|
} else {
|
||||||
contract = ActivityResultContracts.StartActivityForResult()
|
val moduleInstall = stringResource(id = R.string.module_install)
|
||||||
) {
|
val selectZipLauncher = rememberLauncherForActivityResult(
|
||||||
if (it.resultCode != RESULT_OK) {
|
contract = ActivityResultContracts.StartActivityForResult()
|
||||||
return@rememberLauncherForActivityResult
|
) {
|
||||||
|
if (it.resultCode != RESULT_OK) {
|
||||||
|
return@rememberLauncherForActivityResult
|
||||||
|
}
|
||||||
|
val data = it.data ?: return@rememberLauncherForActivityResult
|
||||||
|
val uri = data.data ?: return@rememberLauncherForActivityResult
|
||||||
|
|
||||||
|
navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(uri)))
|
||||||
|
|
||||||
|
viewModel.markNeedRefresh()
|
||||||
|
|
||||||
|
Log.i("ModuleScreen", "select zip result: ${it.data}")
|
||||||
}
|
}
|
||||||
val data = it.data ?: return@rememberLauncherForActivityResult
|
|
||||||
val uri = data.data ?: return@rememberLauncherForActivityResult
|
|
||||||
|
|
||||||
navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(uri)))
|
ExtendedFloatingActionButton(
|
||||||
|
onClick = {
|
||||||
|
// select the zip file to install
|
||||||
|
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
||||||
|
intent.type = "application/zip"
|
||||||
|
selectZipLauncher.launch(intent)
|
||||||
|
},
|
||||||
|
icon = { Icon(Icons.Filled.Add, moduleInstall) },
|
||||||
|
text = { Text(text = moduleInstall) },
|
||||||
|
)
|
||||||
|
|
||||||
viewModel.markNeedRefresh()
|
|
||||||
|
|
||||||
Log.i("ModuleScreen", "select zip result: ${it.data}")
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
ExtendedFloatingActionButton(
|
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
onClick = {
|
) { innerPadding ->
|
||||||
// select the zip file to install
|
|
||||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
|
||||||
intent.type = "application/zip"
|
|
||||||
selectZipLauncher.launch(intent)
|
|
||||||
},
|
|
||||||
icon = { Icon(Icons.Filled.Add, moduleInstall) },
|
|
||||||
text = { Text(text = moduleInstall) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}) { innerPadding ->
|
|
||||||
|
|
||||||
when {
|
when {
|
||||||
hasMagisk -> {
|
hasMagisk -> {
|
||||||
@@ -163,10 +172,11 @@ fun ModuleScreen(navigator: DestinationsNavigator) {
|
|||||||
navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(it)))
|
navigator.navigate(FlashScreenDestination(FlashIt.FlashModule(it)))
|
||||||
}, onClickModule = { id, name, hasWebUi ->
|
}, onClickModule = { id, name, hasWebUi ->
|
||||||
if (hasWebUi) {
|
if (hasWebUi) {
|
||||||
context.startActivity(Intent(context, WebUIActivity::class.java)
|
context.startActivity(
|
||||||
.setData(Uri.parse("kernelsu://webui/$id"))
|
Intent(context, WebUIActivity::class.java)
|
||||||
.putExtra("id", id)
|
.setData(Uri.parse("kernelsu://webui/$id"))
|
||||||
.putExtra("name", name)
|
.putExtra("id", id)
|
||||||
|
.putExtra("name", name)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -419,7 +429,10 @@ private fun ModuleList(
|
|||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun TopBar() {
|
private fun TopBar() {
|
||||||
TopAppBar(title = { Text(stringResource(R.string.module)) })
|
TopAppBar(
|
||||||
|
title = { Text(stringResource(R.string.module)) },
|
||||||
|
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -433,13 +446,16 @@ private fun ModuleItem(
|
|||||||
onClick: (ModuleViewModel.ModuleInfo) -> Unit
|
onClick: (ModuleViewModel.ModuleInfo) -> Unit
|
||||||
) {
|
) {
|
||||||
ElevatedCard(
|
ElevatedCard(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth()
|
||||||
colors = CardDefaults.elevatedCardColors(containerColor = MaterialTheme.colorScheme.surface)
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val textDecoration = if (!module.remove) null else TextDecoration.LineThrough
|
val textDecoration = if (!module.remove) null else TextDecoration.LineThrough
|
||||||
|
|
||||||
Column(modifier = Modifier.clickable { onClick(module) }.padding(24.dp, 16.dp, 24.dp, 0.dp)) {
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.clickable { onClick(module) }
|
||||||
|
.padding(24.dp, 16.dp, 24.dp, 0.dp)
|
||||||
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
package me.weishu.kernelsu.ui.screen
|
package me.weishu.kernelsu.ui.screen
|
||||||
|
|
||||||
import android.content.ContentResolver
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.database.Cursor
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.provider.OpenableColumns
|
|
||||||
import android.util.Log
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawing
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
@@ -29,7 +29,6 @@ import androidx.compose.material.icons.filled.RemoveModerator
|
|||||||
import androidx.compose.material.icons.filled.Save
|
import androidx.compose.material.icons.filled.Save
|
||||||
import androidx.compose.material.icons.filled.Share
|
import androidx.compose.material.icons.filled.Share
|
||||||
import androidx.compose.material.icons.filled.Update
|
import androidx.compose.material.icons.filled.Update
|
||||||
import androidx.compose.material3.BottomSheetScaffold
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
@@ -62,6 +61,9 @@ import com.maxkeppeler.sheets.list.ListDialog
|
|||||||
import com.maxkeppeler.sheets.list.models.ListOption
|
import com.maxkeppeler.sheets.list.models.ListOption
|
||||||
import com.maxkeppeler.sheets.list.models.ListSelection
|
import com.maxkeppeler.sheets.list.models.ListSelection
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.AppProfileTemplateScreenDestination
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.FlashScreenDestination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -77,20 +79,16 @@ import me.weishu.kernelsu.ui.component.SwitchItem
|
|||||||
import me.weishu.kernelsu.ui.component.rememberConfirmDialog
|
import me.weishu.kernelsu.ui.component.rememberConfirmDialog
|
||||||
import me.weishu.kernelsu.ui.component.rememberCustomDialog
|
import me.weishu.kernelsu.ui.component.rememberCustomDialog
|
||||||
import me.weishu.kernelsu.ui.component.rememberLoadingDialog
|
import me.weishu.kernelsu.ui.component.rememberLoadingDialog
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.AppProfileTemplateScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.FlashScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.util.getBugreportFile
|
import me.weishu.kernelsu.ui.util.getBugreportFile
|
||||||
import me.weishu.kernelsu.ui.util.getFileNameFromUri
|
import me.weishu.kernelsu.ui.util.getFileNameFromUri
|
||||||
import me.weishu.kernelsu.ui.util.shrinkModules
|
import me.weishu.kernelsu.ui.util.shrinkModules
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.format.DateTimeFormatter
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author weishu
|
* @author weishu
|
||||||
* @date 2023/1/1.
|
* @date 2023/1/1.
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Destination
|
@Destination<RootGraph>
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingScreen(navigator: DestinationsNavigator) {
|
fun SettingScreen(navigator: DestinationsNavigator) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@@ -98,7 +96,8 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
TopBar(onBack = {
|
TopBar(onBack = {
|
||||||
navigator.popBackStack()
|
navigator.popBackStack()
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
|
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
val aboutDialog = rememberCustomDialog {
|
val aboutDialog = rememberCustomDialog {
|
||||||
AboutDialog(it)
|
AboutDialog(it)
|
||||||
@@ -184,17 +183,20 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
showBottomsheet = true
|
showBottomsheet = true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (showBottomsheet){
|
if (showBottomsheet) {
|
||||||
ModalBottomSheet(
|
ModalBottomSheet(
|
||||||
onDismissRequest = { showBottomsheet = false },
|
onDismissRequest = { showBottomsheet = false },
|
||||||
content = {
|
content = {
|
||||||
Row(modifier = Modifier.padding(10.dp)
|
Row(
|
||||||
.align(Alignment.CenterHorizontally)
|
modifier = Modifier
|
||||||
|
.padding(10.dp)
|
||||||
|
.align(Alignment.CenterHorizontally)
|
||||||
|
|
||||||
) {
|
) {
|
||||||
Box{
|
Box {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(16.dp)
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
.clickable {
|
.clickable {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val bugreport = loadingDialog.withLoading {
|
val bugreport = loadingDialog.withLoading {
|
||||||
@@ -209,14 +211,15 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
"${BuildConfig.APPLICATION_ID}.fileprovider",
|
"${BuildConfig.APPLICATION_ID}.fileprovider",
|
||||||
bugreport
|
bugreport
|
||||||
)
|
)
|
||||||
val filename = getFileNameFromUri(context , uri)
|
val filename = getFileNameFromUri(context, uri)
|
||||||
val savefile = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
val savefile =
|
||||||
addCategory(Intent.CATEGORY_OPENABLE)
|
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||||
type = "application/zip"
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
putExtra(Intent.EXTRA_STREAM, uri)
|
type = "application/zip"
|
||||||
putExtra(Intent.EXTRA_TITLE, filename)
|
putExtra(Intent.EXTRA_STREAM, uri)
|
||||||
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
putExtra(Intent.EXTRA_TITLE, filename)
|
||||||
}
|
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
}
|
||||||
context.startActivity(
|
context.startActivity(
|
||||||
Intent.createChooser(
|
Intent.createChooser(
|
||||||
savefile,
|
savefile,
|
||||||
@@ -245,9 +248,10 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Box{
|
Box {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(16.dp)
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
.clickable {
|
.clickable {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val bugreport = loadingDialog.withLoading {
|
val bugreport = loadingDialog.withLoading {
|
||||||
@@ -350,6 +354,7 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UninstallItem(
|
fun UninstallItem(
|
||||||
navigator: DestinationsNavigator,
|
navigator: DestinationsNavigator,
|
||||||
@@ -374,11 +379,9 @@ fun UninstallItem(
|
|||||||
UninstallType.PERMANENT -> navigator.navigate(
|
UninstallType.PERMANENT -> navigator.navigate(
|
||||||
FlashScreenDestination(FlashIt.FlashUninstall)
|
FlashScreenDestination(FlashIt.FlashUninstall)
|
||||||
)
|
)
|
||||||
|
|
||||||
UninstallType.RESTORE_STOCK_IMAGE -> navigator.navigate(
|
UninstallType.RESTORE_STOCK_IMAGE -> navigator.navigate(
|
||||||
FlashScreenDestination(FlashIt.FlashRestore)
|
FlashScreenDestination(FlashIt.FlashRestore)
|
||||||
)
|
)
|
||||||
|
|
||||||
UninstallType.NONE -> Unit
|
UninstallType.NONE -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -464,6 +467,7 @@ private fun TopBar(onBack: () -> Unit = {}) {
|
|||||||
onClick = onBack
|
onClick = onBack
|
||||||
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
|
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
|
||||||
},
|
},
|
||||||
|
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,16 +26,17 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
|||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.AppProfileScreenDestination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.weishu.kernelsu.Natives
|
import me.weishu.kernelsu.Natives
|
||||||
import me.weishu.kernelsu.R
|
import me.weishu.kernelsu.R
|
||||||
import me.weishu.kernelsu.ui.component.SearchAppBar
|
import me.weishu.kernelsu.ui.component.SearchAppBar
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.AppProfileScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel
|
import me.weishu.kernelsu.ui.viewmodel.SuperUserViewModel
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Destination
|
@Destination<RootGraph>
|
||||||
@Composable
|
@Composable
|
||||||
fun SuperUserScreen(navigator: DestinationsNavigator) {
|
fun SuperUserScreen(navigator: DestinationsNavigator) {
|
||||||
val viewModel = viewModel<SuperUserViewModel>()
|
val viewModel = viewModel<SuperUserViewModel>()
|
||||||
@@ -92,7 +93,8 @@ fun SuperUserScreen(navigator: DestinationsNavigator) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
val refreshState = rememberPullRefreshState(
|
val refreshState = rememberPullRefreshState(
|
||||||
refreshing = viewModel.isRefreshing,
|
refreshing = viewModel.isRefreshing,
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||||
import androidx.compose.foundation.layout.FlowRow
|
import androidx.compose.foundation.layout.FlowRow
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawing
|
||||||
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.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
@@ -47,13 +51,14 @@ import androidx.compose.ui.text.AnnotatedString
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
|
import com.ramcosta.composedestinations.generated.destinations.TemplateEditorScreenDestination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import com.ramcosta.composedestinations.result.ResultRecipient
|
import com.ramcosta.composedestinations.result.ResultRecipient
|
||||||
import com.ramcosta.composedestinations.result.getOr
|
import com.ramcosta.composedestinations.result.getOr
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.weishu.kernelsu.R
|
import me.weishu.kernelsu.R
|
||||||
import me.weishu.kernelsu.ui.screen.destinations.TemplateEditorScreenDestination
|
|
||||||
import me.weishu.kernelsu.ui.viewmodel.TemplateViewModel
|
import me.weishu.kernelsu.ui.viewmodel.TemplateViewModel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,7 +67,7 @@ import me.weishu.kernelsu.ui.viewmodel.TemplateViewModel
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Destination
|
@Destination<RootGraph>
|
||||||
@Composable
|
@Composable
|
||||||
fun AppProfileTemplateScreen(
|
fun AppProfileTemplateScreen(
|
||||||
navigator: DestinationsNavigator,
|
navigator: DestinationsNavigator,
|
||||||
@@ -141,6 +146,7 @@ fun AppProfileTemplateScreen(
|
|||||||
text = { Text(stringResource(id = R.string.app_profile_template_create)) },
|
text = { Text(stringResource(id = R.string.app_profile_template_create)) },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
val refreshState = rememberPullRefreshState(
|
val refreshState = rememberPullRefreshState(
|
||||||
refreshing = viewModel.isRefreshing,
|
refreshing = viewModel.isRefreshing,
|
||||||
@@ -254,6 +260,7 @@ private fun TopBar(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3,8 +3,12 @@ package me.weishu.kernelsu.ui.screen
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.safeDrawing
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
@@ -37,6 +41,7 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
import com.ramcosta.composedestinations.result.ResultBackNavigator
|
import com.ramcosta.composedestinations.result.ResultBackNavigator
|
||||||
import me.weishu.kernelsu.Natives
|
import me.weishu.kernelsu.Natives
|
||||||
import me.weishu.kernelsu.R
|
import me.weishu.kernelsu.R
|
||||||
@@ -52,7 +57,7 @@ import me.weishu.kernelsu.ui.viewmodel.toJSON
|
|||||||
* @date 2023/10/20.
|
* @date 2023/10/20.
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalComposeUiApi::class)
|
@OptIn(ExperimentalComposeUiApi::class)
|
||||||
@Destination
|
@Destination<RootGraph>
|
||||||
@Composable
|
@Composable
|
||||||
fun TemplateEditorScreen(
|
fun TemplateEditorScreen(
|
||||||
navigator: ResultBackNavigator<Boolean>,
|
navigator: ResultBackNavigator<Boolean>,
|
||||||
@@ -108,6 +113,7 @@ fun TemplateEditorScreen(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -242,37 +248,40 @@ private fun TopBar(
|
|||||||
onDelete: () -> Unit = {},
|
onDelete: () -> Unit = {},
|
||||||
onSave: () -> Unit = {}
|
onSave: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
TopAppBar(title = {
|
TopAppBar(
|
||||||
Column {
|
title = {
|
||||||
Text(title)
|
Column {
|
||||||
if (summary.isNotBlank()) {
|
Text(title)
|
||||||
Text(
|
if (summary.isNotBlank()) {
|
||||||
text = summary,
|
Text(
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
text = summary,
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, navigationIcon = {
|
||||||
|
IconButton(
|
||||||
|
onClick = onBack
|
||||||
|
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
|
||||||
|
}, actions = {
|
||||||
|
if (readOnly) {
|
||||||
|
return@TopAppBar
|
||||||
|
}
|
||||||
|
IconButton(onClick = onDelete) {
|
||||||
|
Icon(
|
||||||
|
Icons.Filled.DeleteForever,
|
||||||
|
contentDescription = stringResource(id = R.string.app_profile_template_delete)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
IconButton(onClick = onSave) {
|
||||||
}, navigationIcon = {
|
Icon(
|
||||||
IconButton(
|
imageVector = Icons.Filled.Save,
|
||||||
onClick = onBack
|
contentDescription = stringResource(id = R.string.app_profile_template_save)
|
||||||
) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) }
|
)
|
||||||
}, actions = {
|
}
|
||||||
if (readOnly) {
|
},
|
||||||
return@TopAppBar
|
windowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal)
|
||||||
}
|
)
|
||||||
IconButton(onClick = onDelete) {
|
|
||||||
Icon(
|
|
||||||
Icons.Filled.DeleteForever,
|
|
||||||
contentDescription = stringResource(id = R.string.app_profile_template_delete)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
IconButton(onClick = onSave) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Filled.Save,
|
|
||||||
contentDescription = stringResource(id = R.string.app_profile_template_save)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -289,17 +298,16 @@ private fun TextEdit(
|
|||||||
value = text,
|
value = text,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
label = { Text(label) },
|
label = { Text(label) },
|
||||||
suffix =
|
suffix = {
|
||||||
if (errorHint.isNotBlank()) {
|
if (errorHint.isNotBlank()) {
|
||||||
{
|
|
||||||
Text(
|
Text(
|
||||||
text = if (isError) errorHint else "",
|
text = if (isError) errorHint else "",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.error
|
color = MaterialTheme.colorScheme.error
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
null
|
|
||||||
},
|
},
|
||||||
isError = isError,
|
isError = isError,
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
|
|||||||
@@ -7,12 +7,8 @@ import androidx.compose.material3.darkColorScheme
|
|||||||
import androidx.compose.material3.dynamicDarkColorScheme
|
import androidx.compose.material3.dynamicDarkColorScheme
|
||||||
import androidx.compose.material3.dynamicLightColorScheme
|
import androidx.compose.material3.dynamicLightColorScheme
|
||||||
import androidx.compose.material3.lightColorScheme
|
import androidx.compose.material3.lightColorScheme
|
||||||
import androidx.compose.material3.surfaceColorAtElevation
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.SideEffect
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
|
||||||
|
|
||||||
private val DarkColorScheme = darkColorScheme(
|
private val DarkColorScheme = darkColorScheme(
|
||||||
primary = YELLOW,
|
primary = YELLOW,
|
||||||
@@ -42,20 +38,6 @@ fun KernelSUTheme(
|
|||||||
else -> LightColorScheme
|
else -> LightColorScheme
|
||||||
}
|
}
|
||||||
|
|
||||||
val systemUiController = rememberSystemUiController()
|
|
||||||
SideEffect {
|
|
||||||
systemUiController.setStatusBarColor(
|
|
||||||
color = colorScheme.surface,
|
|
||||||
darkIcons = !darkTheme
|
|
||||||
)
|
|
||||||
|
|
||||||
// To match the App Navbar color
|
|
||||||
systemUiController.setNavigationBarColor(
|
|
||||||
color = colorScheme.surfaceColorAtElevation(8.dp),
|
|
||||||
darkIcons = !darkTheme,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme,
|
colorScheme = colorScheme,
|
||||||
typography = Typography,
|
typography = Typography,
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
package me.weishu.kernelsu.ui.util
|
package me.weishu.kernelsu.ui.util
|
||||||
|
|
||||||
import android.content.ContentResolver
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.ParcelFileDescriptor
|
|
||||||
import android.system.Os
|
import android.system.Os
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
import me.weishu.kernelsu.Natives
|
import me.weishu.kernelsu.Natives
|
||||||
import me.weishu.kernelsu.ui.screen.getManagerVersion
|
import me.weishu.kernelsu.ui.screen.getManagerVersion
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.io.FileWriter
|
import java.io.FileWriter
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package me.weishu.kernelsu.ui.util
|
package me.weishu.kernelsu.ui.util
|
||||||
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import me.weishu.kernelsu.R
|
import me.weishu.kernelsu.R
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,18 @@ package me.weishu.kernelsu.ui.webui
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.content.Context
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.ViewGroup.MarginLayoutParams
|
||||||
import android.webkit.WebResourceRequest
|
import android.webkit.WebResourceRequest
|
||||||
import android.webkit.WebResourceResponse
|
import android.webkit.WebResourceResponse
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.enableEdgeToEdge
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.webkit.WebViewAssetLoader
|
import androidx.webkit.WebViewAssetLoader
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import me.weishu.kernelsu.ui.util.createRootShell
|
import me.weishu.kernelsu.ui.util.createRootShell
|
||||||
@@ -21,12 +26,26 @@ class WebUIActivity : ComponentActivity() {
|
|||||||
private var rootShell: Shell? = null
|
private var rootShell: Shell? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
||||||
|
// Enable edge to edge
|
||||||
|
enableEdgeToEdge()
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
window.isNavigationBarContrastEnforced = false
|
||||||
|
}
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
val moduleId = intent.getStringExtra("id")!!
|
val moduleId = intent.getStringExtra("id")!!
|
||||||
val name = intent.getStringExtra("name")!!
|
val name = intent.getStringExtra("name")!!
|
||||||
setTaskDescription(ActivityManager.TaskDescription("KernelSU - $name"))
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
setTaskDescription(ActivityManager.TaskDescription("KernelSU - $name"))
|
||||||
|
} else {
|
||||||
|
val taskDescription = ActivityManager.TaskDescription.Builder().setLabel("KernelSU - $name").build()
|
||||||
|
setTaskDescription(taskDescription)
|
||||||
|
}
|
||||||
|
|
||||||
val prefs = getSharedPreferences("settings", Context.MODE_PRIVATE)
|
val prefs = getSharedPreferences("settings", MODE_PRIVATE)
|
||||||
WebView.setWebContentsDebuggingEnabled(prefs.getBoolean("enable_web_debugging", false))
|
WebView.setWebContentsDebuggingEnabled(prefs.getBoolean("enable_web_debugging", false))
|
||||||
|
|
||||||
val moduleDir = "/data/adb/modules/${moduleId}"
|
val moduleDir = "/data/adb/modules/${moduleId}"
|
||||||
@@ -50,6 +69,16 @@ class WebUIActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val webView = WebView(this).apply {
|
val webView = WebView(this).apply {
|
||||||
|
ViewCompat.setOnApplyWindowInsetsListener(this) { view, insets ->
|
||||||
|
val inset = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
|
view.updateLayoutParams<MarginLayoutParams> {
|
||||||
|
leftMargin = inset.left
|
||||||
|
rightMargin = inset.right
|
||||||
|
topMargin = inset.top
|
||||||
|
bottomMargin = inset.bottom
|
||||||
|
}
|
||||||
|
return@setOnApplyWindowInsetsListener insets
|
||||||
|
}
|
||||||
settings.javaScriptEnabled = true
|
settings.javaScriptEnabled = true
|
||||||
settings.domStorageEnabled = true
|
settings.domStorageEnabled = true
|
||||||
settings.allowFileAccess = false
|
settings.allowFileAccess = false
|
||||||
|
|||||||
@@ -9,21 +9,24 @@ import android.view.Window
|
|||||||
import android.webkit.JavascriptInterface
|
import android.webkit.JavascriptInterface
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.view.WindowCompat
|
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
import com.topjohnwu.superuser.CallbackList
|
import com.topjohnwu.superuser.CallbackList
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
import me.weishu.kernelsu.ui.util.listModules
|
|
||||||
import me.weishu.kernelsu.ui.util.createRootShell
|
import me.weishu.kernelsu.ui.util.createRootShell
|
||||||
|
import me.weishu.kernelsu.ui.util.listModules
|
||||||
import me.weishu.kernelsu.ui.util.withNewRootShell
|
import me.weishu.kernelsu.ui.util.withNewRootShell
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.util.concurrent.CompletableFuture
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
class WebViewInterface(val context: Context, private val webView: WebView, private val modDir: String) {
|
class WebViewInterface(
|
||||||
|
val context: Context,
|
||||||
|
private val webView: WebView,
|
||||||
|
private val modDir: String
|
||||||
|
) {
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
fun exec(cmd: String): String {
|
fun exec(cmd: String): String {
|
||||||
@@ -187,28 +190,20 @@ class WebViewInterface(val context: Context, private val webView: WebView, priva
|
|||||||
}
|
}
|
||||||
|
|
||||||
var keys = currentInfo.keys()
|
var keys = currentInfo.keys()
|
||||||
for(key in keys) {
|
for (key in keys) {
|
||||||
currentModuleInfo.put(key, currentInfo.get(key));
|
currentModuleInfo.put(key, currentInfo.get(key))
|
||||||
}
|
}
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
return currentModuleInfo.toString();
|
return currentModuleInfo.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideSystemUI(window: Window) {
|
fun hideSystemUI(window: Window) =
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
|
||||||
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
|
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
|
||||||
controller.hide(WindowInsetsCompat.Type.systemBars())
|
controller.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
controller.systemBarsBehavior =
|
controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun showSystemUI(window: Window) {
|
fun showSystemUI(window: Window) =
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, true)
|
WindowInsetsControllerCompat(window, window.decorView).show(WindowInsetsCompat.Type.systemBars())
|
||||||
WindowInsetsControllerCompat(
|
|
||||||
window,
|
|
||||||
window.decorView
|
|
||||||
).show(WindowInsetsCompat.Type.systemBars())
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<style name="Theme.KernelSU" parent="android:Theme.Material.NoActionBar">
|
|
||||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<style name="Theme.KernelSU" parent="android:Theme.Material.NoActionBar" />
|
<style name="Theme.KernelSU" parent="android:Theme.Material.NoActionBar">
|
||||||
|
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges</item>
|
||||||
<style name="Theme.KernelSU.WebUI" parent="Theme.KernelSU">
|
|
||||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
|
||||||
<item name="android:windowLightStatusBar">false</item>
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="Theme.KernelSU.WebUI" parent="Theme.KernelSU" />
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<style name="Theme.KernelSU" parent="android:Theme.Material.Light.NoActionBar">
|
|
||||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<style name="Theme.KernelSU" parent="android:Theme.Material.Light.NoActionBar" />
|
<style name="Theme.KernelSU" parent="android:Theme.Material.Light.NoActionBar">
|
||||||
|
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">shortEdges</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="Theme.KernelSU.WebUI" parent="Theme.KernelSU">
|
<style name="Theme.KernelSU.WebUI" parent="Theme.KernelSU">
|
||||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
|
||||||
<item name="android:windowLightStatusBar">true</item>
|
<item name="android:windowLightStatusBar">true</item>
|
||||||
|
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "8.5.2"
|
agp = "8.6.1"
|
||||||
kotlin = "2.0.20"
|
kotlin = "2.0.20"
|
||||||
ksp = "2.0.20-1.0.24"
|
ksp = "2.0.20-1.0.25"
|
||||||
compose-bom = "2024.08.00"
|
compose-bom = "2024.09.02"
|
||||||
lifecycle = "2.8.4"
|
lifecycle = "2.8.6"
|
||||||
accompanist = "0.34.0"
|
accompanist = "0.36.0"
|
||||||
navigation = "2.7.7"
|
navigation = "2.8.1"
|
||||||
activity-compose = "1.9.1"
|
activity-compose = "1.9.2"
|
||||||
kotlinx-coroutines = "1.8.1"
|
kotlinx-coroutines = "1.9.0"
|
||||||
coil-compose = "2.7.0"
|
coil-compose = "2.7.0"
|
||||||
compose-destination = "1.10.2"
|
compose-destination = "2.1.0-beta12"
|
||||||
sheets-compose-dialogs = "1.3.0"
|
sheets-compose-dialogs = "1.3.0"
|
||||||
markdown = "4.6.2"
|
markdown = "4.6.2"
|
||||||
webkit = "1.11.0"
|
webkit = "1.12.0"
|
||||||
appiconloader-coil = "1.5.0"
|
appiconloader-coil = "1.5.0"
|
||||||
parcelablelist = "2.0.1"
|
parcelablelist = "2.0.1"
|
||||||
libsu = "6.0.0"
|
libsu = "6.0.0"
|
||||||
@@ -53,7 +53,6 @@ androidx-webkit = { module = "androidx.webkit:webkit", version.ref = "webkit" }
|
|||||||
|
|
||||||
com-google-accompanist-drawablepainter = { group = "com.google.accompanist", name = "accompanist-drawablepainter", version.ref = "accompanist" }
|
com-google-accompanist-drawablepainter = { group = "com.google.accompanist", name = "accompanist-drawablepainter", version.ref = "accompanist" }
|
||||||
com-google-accompanist-navigation-animation = { group = "com.google.accompanist", name = "accompanist-navigation-animation", version.ref = "accompanist" }
|
com-google-accompanist-navigation-animation = { group = "com.google.accompanist", name = "accompanist-navigation-animation", version.ref = "accompanist" }
|
||||||
com-google-accompanist-systemuicontroller = { group = "com.google.accompanist", name = "accompanist-systemuicontroller", version.ref = "accompanist" }
|
|
||||||
com-google-accompanist-webview = { group = "com.google.accompanist", name = "accompanist-webview", version.ref = "accompanist" }
|
com-google-accompanist-webview = { group = "com.google.accompanist", name = "accompanist-webview", version.ref = "accompanist" }
|
||||||
|
|
||||||
com-github-topjohnwu-libsu-core = { group = "com.github.topjohnwu.libsu", name = "core", version.ref = "libsu" }
|
com-github-topjohnwu-libsu-core = { group = "com.github.topjohnwu.libsu", name = "core", version.ref = "libsu" }
|
||||||
@@ -68,7 +67,7 @@ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-c
|
|||||||
|
|
||||||
me-zhanghai-android-appiconloader-coil = { group = "me.zhanghai.android.appiconloader", name = "appiconloader-coil", version.ref = "appiconloader-coil" }
|
me-zhanghai-android-appiconloader-coil = { group = "me.zhanghai.android.appiconloader", name = "appiconloader-coil", version.ref = "appiconloader-coil" }
|
||||||
|
|
||||||
compose-destinations-animations-core = { group = "io.github.raamcosta.compose-destinations", name = "animations-core", version.ref = "compose-destination" }
|
compose-destinations-core = { group = "io.github.raamcosta.compose-destinations", name = "core", version.ref = "compose-destination" }
|
||||||
compose-destinations-ksp = { group = "io.github.raamcosta.compose-destinations", name = "ksp", version.ref = "compose-destination" }
|
compose-destinations-ksp = { group = "io.github.raamcosta.compose-destinations", name = "ksp", version.ref = "compose-destination" }
|
||||||
|
|
||||||
sheet-compose-dialogs-core = { group = "com.maxkeppeler.sheets-compose-dialogs", name = "core", version.ref = "sheets-compose-dialogs" }
|
sheet-compose-dialogs-core = { group = "com.maxkeppeler.sheets-compose-dialogs", name = "core", version.ref = "sheets-compose-dialogs" }
|
||||||
|
|||||||
Reference in New Issue
Block a user