src: bring back LKM patching

This commit is contained in:
rifsxd
2025-05-26 02:38:51 +06:00
parent 39617497ca
commit 5fa1050e1b
18 changed files with 325 additions and 330 deletions

View File

@@ -40,7 +40,7 @@ import com.dergoogler.mmrl.ui.component.LabelItemDefaults
import com.dergoogler.mmrl.ui.component.text.TextRow
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
// import com.ramcosta.composedestinations.generated.destinations.InstallScreenDestination // DISBAND LKM MODE
import com.ramcosta.composedestinations.generated.destinations.InstallScreenDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -66,9 +66,9 @@ fun HomeScreen(navigator: DestinationsNavigator) {
TopBar(
kernelVersion,
ksuVersion,
// onInstallClick = {
// navigator.navigate(InstallScreenDestination)
// }, // DISBAND LKM MODE
onInstallClick = {
navigator.navigate(InstallScreenDestination)
},
scrollBehavior = scrollBehavior
)
},
@@ -87,7 +87,7 @@ fun HomeScreen(navigator: DestinationsNavigator) {
}
StatusCard(kernelVersion, ksuVersion, lkmMode) {
// navigator.navigate(InstallScreenDestination) // DISBAND LKM MODE
navigator.navigate(InstallScreenDestination)
}
if (isManager && Natives.requireNewKernel()) {
WarningCard(
@@ -173,20 +173,22 @@ fun RebootDropdownItem(@StringRes id: Int, reason: String = "") {
private fun TopBar(
kernelVersion: KernelVersion,
ksuVersion: Int?,
// onInstallClick: () -> Unit, // DISBAND LKM MODE
onInstallClick: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = { Text(stringResource(R.string.app_name)) },
actions = {
// if (kernelVersion.isGKI()) {
// IconButton(onClick = onInstallClick) {
// Icon(
// imageVector = Icons.Filled.Archive,
// contentDescription = stringResource(id = R.string.install)
// )
// }
// } // DISBAND LKM MODE
if (ksuVersion != null) {
if (kernelVersion.isGKI()) {
IconButton(onClick = onInstallClick) {
Icon(
imageVector = Icons.Filled.Archive,
contentDescription = stringResource(id = R.string.install)
)
}
}
}
if (ksuVersion != null) {
var showDropdown by remember { mutableStateOf(false) }
@@ -257,16 +259,17 @@ private fun StatusCard(
tapCount++
if (tapCount == 10) {
Toast.makeText(context, "Never gonna give you up! 💜", Toast.LENGTH_SHORT).show()
// tapCount = 0
val url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
val intent = android.content.Intent(android.content.Intent.ACTION_VIEW, android.net.Uri.parse(url))
intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
if (ksuVersion != null) {
context.startActivity(intent)
} else {
onClickInstall()
}
} else if (ksuVersion == null && kernelVersion.isGKI()) {
onClickInstall()
}
// if (kernelVersion.isGKI()) {
// onClickInstall()
// }
}
.padding(24.dp), verticalAlignment = Alignment.CenterVertically) {
when {
@@ -344,20 +347,20 @@ private fun StatusCard(
}
}
// kernelVersion.isGKI() -> {
// Icon(Icons.Filled.Report, stringResource(R.string.lkm_mode_deprecated))
// Column(Modifier.padding(start = 20.dp)) {
// Text(
// text = stringResource(R.string.lkm_mode_deprecated),
// style = MaterialTheme.typography.titleMedium
// )
// Spacer(Modifier.height(4.dp))
// Text(
// text = stringResource(R.string.lkm_alternative_suggestion),
// style = MaterialTheme.typography.bodyMedium
// )
// }
// }
kernelVersion.isGKI() -> {
Icon(Icons.Filled.Report, stringResource(R.string.home_not_installed))
Column(Modifier.padding(start = 20.dp)) {
Text(
text = stringResource(R.string.home_not_installed),
style = MaterialTheme.typography.titleMedium
)
Spacer(Modifier.height(4.dp))
Text(
text = stringResource(R.string.home_click_to_install),
style = MaterialTheme.typography.bodyMedium
)
}
}
else -> {
Icon(Icons.Filled.Dangerous, stringResource(R.string.home_failure))

View File

@@ -22,6 +22,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.FileUpload
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
@@ -30,6 +31,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
@@ -77,6 +79,32 @@ import com.rifsxd.ksunext.ui.util.rootAvailable
@Destination<RootGraph>
@Composable
fun InstallScreen(navigator: DestinationsNavigator) {
var showLkmWarning by remember { mutableStateOf(true) }
if (showLkmWarning) {
AlertDialog(
onDismissRequest = {
showLkmWarning = false
navigator.popBackStack()
},
title = { Text(stringResource(R.string.warning)) },
text = { Text(stringResource(R.string.lkm_warning_message)) },
confirmButton = {
TextButton(onClick = { showLkmWarning = false }) {
Text(stringResource(R.string.proceed))
}
},
dismissButton = {
TextButton(onClick = {
showLkmWarning = false
navigator.popBackStack()
}) {
Text(stringResource(R.string.cancel))
}
}
)
}
var installMethod by remember {
mutableStateOf<InstallMethod?>(null)
}

View File

@@ -399,12 +399,12 @@ fun SettingScreen(navigator: DestinationsNavigator) {
)
}
// val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode
// if (lkmMode) {
// UninstallItem(navigator) {
// loadingDialog.withLoading(it)
// }
// } // DISBAND LKM MODE
val lkmMode = Natives.version >= Natives.MINIMAL_SUPPORTED_KERNEL_LKM && Natives.isLkmMode
if (lkmMode) {
UninstallItem(navigator) {
loadingDialog.withLoading(it)
}
}
var showBottomsheet by remember { mutableStateOf(false) }
@@ -532,107 +532,107 @@ fun SettingScreen(navigator: DestinationsNavigator) {
}
}
// @Composable
// fun UninstallItem(
// navigator: DestinationsNavigator,
// withLoading: suspend (suspend () -> Unit) -> Unit,
// ) {
// val context = LocalContext.current
// val scope = rememberCoroutineScope()
// val uninstallConfirmDialog = rememberConfirmDialog()
// val showTodo = {
// Toast.makeText(context, "TODO", Toast.LENGTH_SHORT).show()
// }
// val uninstallDialog = rememberUninstallDialog { uninstallType ->
// scope.launch {
// val result = uninstallConfirmDialog.awaitConfirm(
// title = context.getString(uninstallType.title),
// content = context.getString(uninstallType.message)
// )
// if (result == ConfirmResult.Confirmed) {
// withLoading {
// when (uninstallType) {
// UninstallType.TEMPORARY -> showTodo()
// UninstallType.PERMANENT -> navigator.navigate(
// FlashScreenDestination(FlashIt.FlashUninstall)
// )
// UninstallType.RESTORE_STOCK_IMAGE -> navigator.navigate(
// FlashScreenDestination(FlashIt.FlashRestore)
// )
// UninstallType.NONE -> Unit
// }
// }
// }
// }
// }
// val uninstall = stringResource(id = R.string.settings_uninstall)
// ListItem(
// leadingContent = {
// Icon(
// Icons.Filled.Delete,
// uninstall
// )
// },
// headlineContent = { Text(uninstall) },
// modifier = Modifier.clickable {
// uninstallDialog.show()
// }
// )
// }
@Composable
fun UninstallItem(
navigator: DestinationsNavigator,
withLoading: suspend (suspend () -> Unit) -> Unit,
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val uninstallConfirmDialog = rememberConfirmDialog()
val showTodo = {
Toast.makeText(context, "TODO", Toast.LENGTH_SHORT).show()
}
val uninstallDialog = rememberUninstallDialog { uninstallType ->
scope.launch {
val result = uninstallConfirmDialog.awaitConfirm(
title = context.getString(uninstallType.title),
content = context.getString(uninstallType.message)
)
if (result == ConfirmResult.Confirmed) {
withLoading {
when (uninstallType) {
UninstallType.TEMPORARY -> showTodo()
UninstallType.PERMANENT -> navigator.navigate(
FlashScreenDestination(FlashIt.FlashUninstall)
)
UninstallType.RESTORE_STOCK_IMAGE -> navigator.navigate(
FlashScreenDestination(FlashIt.FlashRestore)
)
UninstallType.NONE -> Unit
}
}
}
}
}
val uninstall = stringResource(id = R.string.settings_uninstall)
ListItem(
leadingContent = {
Icon(
Icons.Filled.Delete,
uninstall
)
},
headlineContent = { Text(uninstall) },
modifier = Modifier.clickable {
uninstallDialog.show()
}
)
}
// enum class UninstallType(val title: Int, val message: Int, val icon: ImageVector) {
// TEMPORARY(
// R.string.settings_uninstall_temporary,
// R.string.settings_uninstall_temporary_message,
// Icons.Filled.Delete
// ),
// PERMANENT(
// R.string.settings_uninstall_permanent,
// R.string.settings_uninstall_permanent_message,
// Icons.Filled.DeleteForever
// ),
// RESTORE_STOCK_IMAGE(
// R.string.settings_restore_stock_image,
// R.string.settings_restore_stock_image_message,
// Icons.AutoMirrored.Filled.Undo
// ),
// NONE(0, 0, Icons.Filled.Delete)
// }
enum class UninstallType(val title: Int, val message: Int, val icon: ImageVector) {
TEMPORARY(
R.string.settings_uninstall_temporary,
R.string.settings_uninstall_temporary_message,
Icons.Filled.Delete
),
PERMANENT(
R.string.settings_uninstall_permanent,
R.string.settings_uninstall_permanent_message,
Icons.Filled.DeleteForever
),
RESTORE_STOCK_IMAGE(
R.string.settings_restore_stock_image,
R.string.settings_restore_stock_image_message,
Icons.AutoMirrored.Filled.Undo
),
NONE(0, 0, Icons.Filled.Delete)
}
// @OptIn(ExperimentalMaterial3Api::class)
// @Composable
// fun rememberUninstallDialog(onSelected: (UninstallType) -> Unit): DialogHandle {
// return rememberCustomDialog { dismiss ->
// val options = listOf(
// // UninstallType.TEMPORARY,
// UninstallType.PERMANENT,
// UninstallType.RESTORE_STOCK_IMAGE
// )
// val listOptions = options.map {
// ListOption(
// titleText = stringResource(it.title),
// subtitleText = if (it.message != 0) stringResource(it.message) else null,
// icon = IconSource(it.icon)
// )
// }
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun rememberUninstallDialog(onSelected: (UninstallType) -> Unit): DialogHandle {
return rememberCustomDialog { dismiss ->
val options = listOf(
// UninstallType.TEMPORARY,
UninstallType.PERMANENT,
UninstallType.RESTORE_STOCK_IMAGE
)
val listOptions = options.map {
ListOption(
titleText = stringResource(it.title),
subtitleText = if (it.message != 0) stringResource(it.message) else null,
icon = IconSource(it.icon)
)
}
// var selection = UninstallType.NONE
// ListDialog(state = rememberUseCaseState(visible = true, onFinishedRequest = {
// if (selection != UninstallType.NONE) {
// onSelected(selection)
// }
// }, onCloseRequest = {
// dismiss()
// }), header = Header.Default(
// title = stringResource(R.string.settings_uninstall),
// ), selection = ListSelection.Single(
// showRadioButtons = false,
// options = listOptions,
// ) { index, _ ->
// selection = options[index]
// })
// }
// } // DISBAND LKM MODE
var selection = UninstallType.NONE
ListDialog(state = rememberUseCaseState(visible = true, onFinishedRequest = {
if (selection != UninstallType.NONE) {
onSelected(selection)
}
}, onCloseRequest = {
dismiss()
}), header = Header.Default(
title = stringResource(R.string.settings_uninstall),
), selection = ListSelection.Single(
showRadioButtons = false,
options = listOptions,
) { index, _ ->
selection = options[index]
})
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable

Binary file not shown.

View File

@@ -100,6 +100,7 @@
<string name="proceed">Proceed</string>
<string name="cancel">Cancel</string>
<string name="later">Later</string>
<string name="lkm_warning_message">The LKM patch relies on closed source components. Do you want to continue?</string>
<string name="home_next_kernelsu">🔥 Next build</string>
<string name="home_next_kernelsu_repo">https://github.com/KernelSU-Next/KernelSU-Next</string>
<string name="home_next_kernelsu_body">Next experimental branch. Check it out on GitHub!</string>