manager: support full screen for webui

This commit is contained in:
weishu
2024-02-20 23:25:57 +08:00
parent 65bff7bf03
commit 55f8f2da90
3 changed files with 57 additions and 15 deletions

View File

@@ -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(

View File

@@ -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 {
@@ -94,4 +114,21 @@ private suspend fun stopServer(port: Int) {
.execute() .execute()
} }
} }
}
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())
} }

View File

@@ -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>