manager: support full screen for webui
This commit is contained in:
@@ -20,6 +20,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||||
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
|
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
|
||||||
import com.ramcosta.composedestinations.DestinationsNavHost
|
import com.ramcosta.composedestinations.DestinationsNavHost
|
||||||
import com.ramcosta.composedestinations.navigation.popBackStack
|
import com.ramcosta.composedestinations.navigation.popBackStack
|
||||||
@@ -44,8 +45,11 @@ class MainActivity : ComponentActivity() {
|
|||||||
KernelSUTheme {
|
KernelSUTheme {
|
||||||
val navController = rememberAnimatedNavController()
|
val navController = rememberAnimatedNavController()
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||||
|
val route = navBackStackEntry?.destination?.route
|
||||||
|
val showBottomBar = route == null || !route.startsWith("web_screen")
|
||||||
Scaffold(
|
Scaffold(
|
||||||
bottomBar = { BottomBar(navController) },
|
bottomBar = { if (showBottomBar) BottomBar(navController) },
|
||||||
snackbarHost = { SnackbarHost(snackbarHostState) }
|
snackbarHost = { SnackbarHost(snackbarHostState) }
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
package me.weishu.kernelsu.ui.screen
|
package me.weishu.kernelsu.ui.screen
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.Window
|
||||||
import android.webkit.JavascriptInterface
|
import android.webkit.JavascriptInterface
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.accompanist.web.WebView
|
import com.google.accompanist.web.WebView
|
||||||
import com.google.accompanist.web.rememberWebViewState
|
import com.google.accompanist.web.rememberWebViewState
|
||||||
@@ -26,7 +32,6 @@ import me.weishu.kernelsu.ui.util.createRootShell
|
|||||||
import me.weishu.kernelsu.ui.util.serveModule
|
import me.weishu.kernelsu.ui.util.serveModule
|
||||||
import java.net.ServerSocket
|
import java.net.ServerSocket
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
@Destination
|
@Destination
|
||||||
@Composable
|
@Composable
|
||||||
@@ -38,18 +43,20 @@ fun WebScreen(navigator: DestinationsNavigator, moduleId: String, moduleName: St
|
|||||||
}
|
}
|
||||||
|
|
||||||
val lifecycleOwner = LocalLifecycleOwner.current
|
val lifecycleOwner = LocalLifecycleOwner.current
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
DisposableEffect(Unit) {
|
DisposableEffect(Unit) {
|
||||||
onDispose {
|
onDispose {
|
||||||
|
if (WebViewInterface.isHideSystemUI && context is Activity) {
|
||||||
|
showSystemUI(context.window)
|
||||||
|
}
|
||||||
lifecycleOwner.lifecycleScope.launch {
|
lifecycleOwner.lifecycleScope.launch {
|
||||||
stopServer(port)
|
stopServer(port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(topBar = {
|
Scaffold { innerPadding ->
|
||||||
TopBar(moduleName)
|
|
||||||
}) { innerPadding ->
|
|
||||||
WebView(
|
WebView(
|
||||||
state = rememberWebViewState(url = "http://localhost:$port"),
|
state = rememberWebViewState(url = "http://localhost:$port"),
|
||||||
Modifier
|
Modifier
|
||||||
@@ -59,25 +66,38 @@ fun WebScreen(navigator: DestinationsNavigator, moduleId: String, moduleName: St
|
|||||||
android.webkit.WebView(context).apply {
|
android.webkit.WebView(context).apply {
|
||||||
settings.javaScriptEnabled = true
|
settings.javaScriptEnabled = true
|
||||||
settings.domStorageEnabled = true
|
settings.domStorageEnabled = true
|
||||||
addJavascriptInterface(WebViewInterface(), "ksu")
|
addJavascriptInterface(WebViewInterface(context), "ksu")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WebViewInterface {
|
class WebViewInterface(val context: Context) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
var isHideSystemUI: Boolean = false
|
||||||
|
}
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
fun exec(cmd: String): String {
|
fun exec(cmd: String): String {
|
||||||
val shell = createRootShell()
|
val shell = createRootShell()
|
||||||
return ShellUtils.fastCmd(shell, cmd)
|
return ShellUtils.fastCmd(shell, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
@JavascriptInterface
|
||||||
|
fun fullScreen(enable: Boolean) {
|
||||||
|
if (context is Activity) {
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
if (enable) {
|
||||||
|
hideSystemUI(context.window)
|
||||||
|
} else {
|
||||||
|
showSystemUI(context.window)
|
||||||
|
}
|
||||||
|
isHideSystemUI = enable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
private fun TopBar(title: String) {
|
|
||||||
TopAppBar(title = { Text(title) })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getFreePort(): Int {
|
private suspend fun getFreePort(): Int {
|
||||||
@@ -95,3 +115,20 @@ private suspend fun stopServer(port: Int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun hideSystemUI(window: Window) {
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
WindowInsetsControllerCompat(window, window.decorView).let { controller ->
|
||||||
|
controller.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
|
controller.systemBarsBehavior =
|
||||||
|
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showSystemUI(window: Window) {
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, true)
|
||||||
|
WindowInsetsControllerCompat(
|
||||||
|
window,
|
||||||
|
window.decorView
|
||||||
|
).show(WindowInsetsCompat.Type.systemBars())
|
||||||
|
}
|
||||||
@@ -2,5 +2,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="Theme.KernelSU" parent="android:Theme.Material.Light.NoActionBar">
|
<style name="Theme.KernelSU" parent="android:Theme.Material.Light.NoActionBar">
|
||||||
|
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user