Feat(App): Support full screen
This commit is contained in:
@@ -10,6 +10,8 @@ import androidx.compose.material.icons.filled.Close
|
|||||||
import androidx.compose.material.icons.filled.Code
|
import androidx.compose.material.icons.filled.Code
|
||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.material.icons.filled.Download
|
import androidx.compose.material.icons.filled.Download
|
||||||
|
import androidx.compose.material.icons.filled.Fullscreen
|
||||||
|
import androidx.compose.material.icons.filled.FullscreenExit
|
||||||
import androidx.compose.material.icons.filled.Inbox
|
import androidx.compose.material.icons.filled.Inbox
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
import androidx.compose.material.icons.filled.Reorder
|
import androidx.compose.material.icons.filled.Reorder
|
||||||
@@ -43,6 +45,8 @@ object OxygenIcons {
|
|||||||
val Delete = Icons.Default.Delete
|
val Delete = Icons.Default.Delete
|
||||||
val Download = Icons.Default.Download
|
val Download = Icons.Default.Download
|
||||||
val Error = Icons.Default.Cancel
|
val Error = Icons.Default.Cancel
|
||||||
|
val FullScreen = Icons.Default.Fullscreen
|
||||||
|
val FullScreenExit = Icons.Default.FullscreenExit
|
||||||
val Home = Icons.Rounded.Home
|
val Home = Icons.Rounded.Home
|
||||||
val HomeBorder = Icons.Outlined.Home
|
val HomeBorder = Icons.Outlined.Home
|
||||||
val Info = Icons.Outlined.Info
|
val Info = Icons.Outlined.Info
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
package top.fatweb.oxygen.toolbox.navigation
|
package top.fatweb.oxygen.toolbox.navigation
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.NavDestination
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import top.fatweb.oxygen.toolbox.ui.OxygenAppState
|
import top.fatweb.oxygen.toolbox.ui.OxygenAppState
|
||||||
|
import top.fatweb.oxygen.toolbox.ui.util.LocalFullScreen
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun OxygenNavHost(
|
fun OxygenNavHost(
|
||||||
@@ -16,6 +21,21 @@ fun OxygenNavHost(
|
|||||||
onShowSnackbar: suspend (message: String, action: String?) -> Boolean
|
onShowSnackbar: suspend (message: String, action: String?) -> Boolean
|
||||||
) {
|
) {
|
||||||
val navController = appState.navController
|
val navController = appState.navController
|
||||||
|
val fullScreen = LocalFullScreen.current
|
||||||
|
|
||||||
|
LaunchedEffect(navController) {
|
||||||
|
navController.addOnDestinationChangedListener(object :
|
||||||
|
NavController.OnDestinationChangedListener {
|
||||||
|
override fun onDestinationChanged(
|
||||||
|
controller: NavController,
|
||||||
|
destination: NavDestination,
|
||||||
|
arguments: Bundle?
|
||||||
|
) {
|
||||||
|
fullScreen.onStateChange.invoke(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
NavHost(
|
NavHost(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
navController = navController,
|
navController = navController,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package top.fatweb.oxygen.toolbox.ui
|
package top.fatweb.oxygen.toolbox.ui
|
||||||
|
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
@@ -7,7 +8,6 @@ import androidx.compose.foundation.layout.WindowInsets
|
|||||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.only
|
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.safeDrawing
|
||||||
@@ -24,6 +24,7 @@ import androidx.compose.material3.SnackbarResult
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
@@ -34,9 +35,11 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.navigation.NavDestination
|
import androidx.navigation.NavDestination
|
||||||
import androidx.navigation.NavDestination.Companion.hierarchy
|
import androidx.navigation.NavDestination.Companion.hierarchy
|
||||||
@@ -59,6 +62,8 @@ import top.fatweb.oxygen.toolbox.ui.component.SearchButtonPosition
|
|||||||
import top.fatweb.oxygen.toolbox.ui.settings.SettingsDialog
|
import top.fatweb.oxygen.toolbox.ui.settings.SettingsDialog
|
||||||
import top.fatweb.oxygen.toolbox.ui.theme.GradientColors
|
import top.fatweb.oxygen.toolbox.ui.theme.GradientColors
|
||||||
import top.fatweb.oxygen.toolbox.ui.theme.LocalGradientColors
|
import top.fatweb.oxygen.toolbox.ui.theme.LocalGradientColors
|
||||||
|
import top.fatweb.oxygen.toolbox.ui.util.FullScreen
|
||||||
|
import top.fatweb.oxygen.toolbox.ui.util.LocalFullScreen
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -69,159 +74,186 @@ fun OxygenApp(appState: OxygenAppState) {
|
|||||||
mutableStateOf(false)
|
mutableStateOf(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
OxygenBackground {
|
val context = LocalContext.current
|
||||||
OxygenGradientBackground(
|
val window = (context as ComponentActivity).window
|
||||||
gradientColors = if (shouldShowGradientBackground) LocalGradientColors.current else GradientColors()
|
val windowInsetsController = WindowInsetsControllerCompat(window, window.decorView)
|
||||||
) {
|
var isFullScreen by remember { mutableStateOf(false) }
|
||||||
val destination = appState.currentTopLevelDestination
|
|
||||||
|
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val fullScreen = FullScreen(
|
||||||
|
enable = isFullScreen,
|
||||||
|
onStateChange = {
|
||||||
|
isFullScreen = it
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
val isOffline by appState.isOffline.collectAsStateWithLifecycle()
|
LaunchedEffect(Unit) {
|
||||||
|
windowInsetsController.systemBarsBehavior =
|
||||||
|
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||||
|
}
|
||||||
|
|
||||||
val noConnectMessage = stringResource(R.string.core_no_connect)
|
LaunchedEffect(isFullScreen) {
|
||||||
|
if (isFullScreen) {
|
||||||
|
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||||
|
} else {
|
||||||
|
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var canScroll by remember { mutableStateOf(true) }
|
CompositionLocalProvider(LocalFullScreen provides fullScreen) {
|
||||||
val topAppBarScrollBehavior =
|
OxygenBackground {
|
||||||
if (canScroll) TopAppBarDefaults.enterAlwaysScrollBehavior() else TopAppBarDefaults.pinnedScrollBehavior()
|
OxygenGradientBackground(
|
||||||
|
gradientColors = if (shouldShowGradientBackground) LocalGradientColors.current else GradientColors()
|
||||||
|
) {
|
||||||
|
val destination = appState.currentTopLevelDestination
|
||||||
|
|
||||||
var activeSearch by remember { mutableStateOf(false) }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
var searchValue by remember { mutableStateOf("") }
|
|
||||||
var searchCount by remember { mutableIntStateOf(0) }
|
|
||||||
|
|
||||||
LaunchedEffect(activeSearch) {
|
val isOffline by appState.isOffline.collectAsStateWithLifecycle()
|
||||||
canScroll = !activeSearch
|
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(destination) {
|
val noConnectMessage = stringResource(R.string.core_no_connect)
|
||||||
activeSearch = false
|
|
||||||
searchValue = ""
|
var canScroll by remember { mutableStateOf(true) }
|
||||||
if (searchCount == 0) {
|
val topAppBarScrollBehavior =
|
||||||
searchCount++
|
if (canScroll) TopAppBarDefaults.enterAlwaysScrollBehavior() else TopAppBarDefaults.pinnedScrollBehavior()
|
||||||
} else {
|
|
||||||
searchCount = 0
|
var activeSearch by remember { mutableStateOf(false) }
|
||||||
|
var searchValue by remember { mutableStateOf("") }
|
||||||
|
var searchCount by remember { mutableIntStateOf(0) }
|
||||||
|
|
||||||
|
LaunchedEffect(activeSearch) {
|
||||||
|
canScroll = !activeSearch
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(isOffline) {
|
LaunchedEffect(destination) {
|
||||||
if (isOffline) {
|
activeSearch = false
|
||||||
snackbarHostState.showSnackbar(
|
searchValue = ""
|
||||||
message = noConnectMessage,
|
if (searchCount == 0) {
|
||||||
duration = SnackbarDuration.Indefinite
|
searchCount++
|
||||||
|
} else {
|
||||||
|
searchCount = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(isOffline) {
|
||||||
|
if (isOffline) {
|
||||||
|
snackbarHostState.showSnackbar(
|
||||||
|
message = noConnectMessage,
|
||||||
|
duration = SnackbarDuration.Indefinite
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showSettingsDialog) {
|
||||||
|
SettingsDialog(
|
||||||
|
onDismiss = { showSettingsDialog = false },
|
||||||
|
onNavigateToLibraries = appState::navigateToLibraries,
|
||||||
|
onNavigateToAbout = appState::navigateToAbout
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (showSettingsDialog) {
|
Scaffold(
|
||||||
SettingsDialog(
|
modifier = Modifier
|
||||||
onDismiss = { showSettingsDialog = false },
|
.nestedScroll(connection = topAppBarScrollBehavior.nestedScrollConnection),
|
||||||
onNavigateToLibraries = appState::navigateToLibraries,
|
containerColor = Color.Transparent,
|
||||||
onNavigateToAbout = appState::navigateToAbout
|
contentColor = MaterialTheme.colorScheme.onBackground,
|
||||||
)
|
contentWindowInsets = WindowInsets(left = 0, top = 0, right = 0, bottom = 0),
|
||||||
}
|
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
||||||
|
bottomBar = {
|
||||||
Scaffold(
|
AnimatedVisibility(
|
||||||
modifier = Modifier
|
visible = appState.shouldShowBottomBar && destination != null
|
||||||
.nestedScroll(connection = topAppBarScrollBehavior.nestedScrollConnection),
|
) {
|
||||||
containerColor = Color.Transparent,
|
OxygenBottomBar(
|
||||||
contentColor = MaterialTheme.colorScheme.onBackground,
|
destinations = appState.topLevelDestinations,
|
||||||
contentWindowInsets = WindowInsets(left = 0, top = 0, right = 0, bottom = 0),
|
currentDestination = appState.currentDestination,
|
||||||
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
onNavigateToDestination = appState::navigateToTopLevelDestination
|
||||||
bottomBar = {
|
|
||||||
AnimatedVisibility(
|
|
||||||
visible = appState.shouldShowBottomBar && destination != null
|
|
||||||
) {
|
|
||||||
OxygenBottomBar(
|
|
||||||
destinations = appState.topLevelDestinations,
|
|
||||||
currentDestination = appState.currentDestination,
|
|
||||||
onNavigateToDestination = appState::navigateToTopLevelDestination
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
) { padding ->
|
|
||||||
Row(
|
|
||||||
Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(padding)
|
|
||||||
.consumeWindowInsets(padding)
|
|
||||||
.windowInsetsPadding(
|
|
||||||
WindowInsets.safeDrawing.only(
|
|
||||||
WindowInsetsSides.Horizontal
|
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
) {
|
|
||||||
AnimatedVisibility(
|
|
||||||
visible = appState.shouldShowNavRail && destination != null
|
|
||||||
) {
|
|
||||||
OxygenNavRail(
|
|
||||||
modifier = Modifier.safeDrawingPadding(),
|
|
||||||
destinations = appState.topLevelDestinations,
|
|
||||||
currentDestination = appState.currentDestination,
|
|
||||||
onNavigateToDestination = appState::navigateToTopLevelDestination
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
) { padding ->
|
||||||
Column(
|
Row(
|
||||||
Modifier.fillMaxSize()
|
Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(padding)
|
||||||
|
.consumeWindowInsets(padding)
|
||||||
|
.windowInsetsPadding(
|
||||||
|
WindowInsets.safeDrawing.only(
|
||||||
|
WindowInsetsSides.Horizontal
|
||||||
|
)
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = destination != null
|
visible = appState.shouldShowNavRail && destination != null
|
||||||
) {
|
) {
|
||||||
OxygenTopAppBar(
|
OxygenNavRail(
|
||||||
scrollBehavior = topAppBarScrollBehavior,
|
modifier = Modifier.safeDrawingPadding(),
|
||||||
title = {
|
destinations = appState.topLevelDestinations,
|
||||||
destination?.let {
|
currentDestination = appState.currentDestination,
|
||||||
Text(
|
onNavigateToDestination = appState::navigateToTopLevelDestination
|
||||||
text = stringResource(destination.titleTextId),
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
navigationIcon = OxygenIcons.Search,
|
|
||||||
navigationIconContentDescription = stringResource(R.string.feature_settings_top_app_bar_navigation_icon_description),
|
|
||||||
actionIcon = OxygenIcons.MoreVert,
|
|
||||||
actionIconContentDescription = stringResource(R.string.feature_settings_top_app_bar_action_icon_description),
|
|
||||||
activeSearch = activeSearch,
|
|
||||||
searchButtonPosition = SearchButtonPosition.Navigation,
|
|
||||||
query = searchValue,
|
|
||||||
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
|
|
||||||
containerColor = Color.Transparent,
|
|
||||||
scrolledContainerColor = Color.Transparent
|
|
||||||
),
|
|
||||||
onNavigationClick = { activeSearch = true },
|
|
||||||
onActionClick = { showSettingsDialog = true },
|
|
||||||
onQueryChange = {
|
|
||||||
searchValue = it
|
|
||||||
},
|
|
||||||
onSearch = {
|
|
||||||
searchCount++
|
|
||||||
},
|
|
||||||
onCancelSearch = {
|
|
||||||
searchValue = ""
|
|
||||||
activeSearch = false
|
|
||||||
searchCount = 0
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
OxygenNavHost(
|
Column(
|
||||||
appState = appState,
|
Modifier.fillMaxSize()
|
||||||
startDestination = when (appState.launchPageConfig) {
|
) {
|
||||||
LaunchPageConfig.Tools -> TOOLS_ROUTE
|
AnimatedVisibility(
|
||||||
LaunchPageConfig.Star -> STAR_ROUTE
|
visible = destination != null
|
||||||
},
|
) {
|
||||||
isVertical = appState.shouldShowBottomBar,
|
OxygenTopAppBar(
|
||||||
searchValue = searchValue,
|
scrollBehavior = topAppBarScrollBehavior,
|
||||||
searchCount = searchCount,
|
title = {
|
||||||
onShowSnackbar = { message, action ->
|
destination?.let {
|
||||||
snackbarHostState.showSnackbar(
|
Text(
|
||||||
message = message,
|
text = stringResource(destination.titleTextId),
|
||||||
actionLabel = action,
|
maxLines = 1,
|
||||||
duration = SnackbarDuration.Short
|
overflow = TextOverflow.Ellipsis
|
||||||
) == SnackbarResult.ActionPerformed
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
navigationIcon = OxygenIcons.Search,
|
||||||
|
navigationIconContentDescription = stringResource(R.string.feature_settings_top_app_bar_navigation_icon_description),
|
||||||
|
actionIcon = OxygenIcons.MoreVert,
|
||||||
|
actionIconContentDescription = stringResource(R.string.feature_settings_top_app_bar_action_icon_description),
|
||||||
|
activeSearch = activeSearch,
|
||||||
|
searchButtonPosition = SearchButtonPosition.Navigation,
|
||||||
|
query = searchValue,
|
||||||
|
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
|
||||||
|
containerColor = Color.Transparent,
|
||||||
|
scrolledContainerColor = Color.Transparent
|
||||||
|
),
|
||||||
|
onNavigationClick = { activeSearch = true },
|
||||||
|
onActionClick = { showSettingsDialog = true },
|
||||||
|
onQueryChange = {
|
||||||
|
searchValue = it
|
||||||
|
},
|
||||||
|
onSearch = {
|
||||||
|
searchCount++
|
||||||
|
},
|
||||||
|
onCancelSearch = {
|
||||||
|
searchValue = ""
|
||||||
|
activeSearch = false
|
||||||
|
searchCount = 0
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
OxygenNavHost(
|
||||||
|
appState = appState,
|
||||||
|
startDestination = when (appState.launchPageConfig) {
|
||||||
|
LaunchPageConfig.Tools -> TOOLS_ROUTE
|
||||||
|
LaunchPageConfig.Star -> STAR_ROUTE
|
||||||
|
},
|
||||||
|
isVertical = appState.shouldShowBottomBar,
|
||||||
|
searchValue = searchValue,
|
||||||
|
searchCount = searchCount,
|
||||||
|
onShowSnackbar = { message, action ->
|
||||||
|
snackbarHostState.showSnackbar(
|
||||||
|
message = message,
|
||||||
|
actionLabel = action,
|
||||||
|
duration = SnackbarDuration.Short
|
||||||
|
) == SnackbarResult.ActionPerformed
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package top.fatweb.oxygen.toolbox.ui.util
|
||||||
|
|
||||||
|
import androidx.compose.runtime.compositionLocalOf
|
||||||
|
|
||||||
|
data class FullScreen(
|
||||||
|
val enable: Boolean = false,
|
||||||
|
val onStateChange: (Boolean) -> Unit = {}
|
||||||
|
)
|
||||||
|
|
||||||
|
val LocalFullScreen = compositionLocalOf { FullScreen() }
|
||||||
@@ -64,6 +64,7 @@ import top.fatweb.oxygen.toolbox.R
|
|||||||
import top.fatweb.oxygen.toolbox.icon.OxygenIcons
|
import top.fatweb.oxygen.toolbox.icon.OxygenIcons
|
||||||
import top.fatweb.oxygen.toolbox.ui.component.Indicator
|
import top.fatweb.oxygen.toolbox.ui.component.Indicator
|
||||||
import top.fatweb.oxygen.toolbox.ui.component.OxygenTopAppBar
|
import top.fatweb.oxygen.toolbox.ui.component.OxygenTopAppBar
|
||||||
|
import top.fatweb.oxygen.toolbox.ui.util.LocalFullScreen
|
||||||
import top.fatweb.oxygen.toolbox.ui.util.ResourcesUtils
|
import top.fatweb.oxygen.toolbox.ui.util.ResourcesUtils
|
||||||
import top.fatweb.oxygen.toolbox.util.NativeWebApi
|
import top.fatweb.oxygen.toolbox.util.NativeWebApi
|
||||||
import top.fatweb.oxygen.toolbox.util.Permissions
|
import top.fatweb.oxygen.toolbox.util.Permissions
|
||||||
@@ -98,6 +99,7 @@ internal fun ToolViewScreen(
|
|||||||
isPreview: Boolean,
|
isPreview: Boolean,
|
||||||
onBackClick: () -> Unit
|
onBackClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
val (isFullScreen, onFullScreenStateChange) = LocalFullScreen.current
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier
|
modifier
|
||||||
@@ -111,7 +113,9 @@ internal fun ToolViewScreen(
|
|||||||
TopBar(
|
TopBar(
|
||||||
toolViewUiState = toolViewUiState,
|
toolViewUiState = toolViewUiState,
|
||||||
isPreview = isPreview,
|
isPreview = isPreview,
|
||||||
onBackClick = onBackClick
|
isFullScreen = isFullScreen,
|
||||||
|
onBackClick = onBackClick,
|
||||||
|
onFullScreenChange = onFullScreenStateChange
|
||||||
)
|
)
|
||||||
Content(
|
Content(
|
||||||
toolViewUiState = toolViewUiState,
|
toolViewUiState = toolViewUiState,
|
||||||
@@ -125,7 +129,9 @@ internal fun ToolViewScreen(
|
|||||||
private fun TopBar(
|
private fun TopBar(
|
||||||
toolViewUiState: ToolViewUiState,
|
toolViewUiState: ToolViewUiState,
|
||||||
isPreview: Boolean,
|
isPreview: Boolean,
|
||||||
onBackClick: () -> Unit
|
isFullScreen: Boolean,
|
||||||
|
onBackClick: () -> Unit,
|
||||||
|
onFullScreenChange: (Boolean) -> Unit
|
||||||
) = OxygenTopAppBar(
|
) = OxygenTopAppBar(
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
@@ -143,11 +149,16 @@ private fun TopBar(
|
|||||||
},
|
},
|
||||||
navigationIcon = OxygenIcons.Back,
|
navigationIcon = OxygenIcons.Back,
|
||||||
navigationIconContentDescription = stringResource(R.string.core_back),
|
navigationIconContentDescription = stringResource(R.string.core_back),
|
||||||
|
actionIcon = if (isFullScreen) OxygenIcons.FullScreenExit else OxygenIcons.FullScreen,
|
||||||
|
actionIconContentDescription = stringResource(if (isFullScreen) R.string.core_exit_full_screen else R.string.core_full_screen),
|
||||||
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
|
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
|
||||||
containerColor = Color.Transparent,
|
containerColor = Color.Transparent,
|
||||||
scrolledContainerColor = Color.Transparent
|
scrolledContainerColor = Color.Transparent
|
||||||
),
|
),
|
||||||
onNavigationClick = onBackClick
|
onNavigationClick = onBackClick,
|
||||||
|
onActionClick = {
|
||||||
|
onFullScreenChange(!isFullScreen)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
<string name="core_search">搜索</string>
|
<string name="core_search">搜索</string>
|
||||||
<string name="core_loading">加载中…</string>
|
<string name="core_loading">加载中…</string>
|
||||||
<string name="core_no_connect">⚠️ 无法连接至互联网</string>
|
<string name="core_no_connect">⚠️ 无法连接至互联网</string>
|
||||||
|
<string name="core_full_screen">全屏</string>
|
||||||
|
<string name="core_exit_full_screen">退出全屏</string>
|
||||||
<string name="core_install">安装</string>
|
<string name="core_install">安装</string>
|
||||||
<string name="core_installing">安装中……</string>
|
<string name="core_installing">安装中……</string>
|
||||||
<string name="core_upgrade">更新</string>
|
<string name="core_upgrade">更新</string>
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
<string name="core_search">Search</string>
|
<string name="core_search">Search</string>
|
||||||
<string name="core_loading">Loading…</string>
|
<string name="core_loading">Loading…</string>
|
||||||
<string name="core_no_connect">⚠️ Unable to connect to the internet</string>
|
<string name="core_no_connect">⚠️ Unable to connect to the internet</string>
|
||||||
|
<string name="core_full_screen">Full Screen</string>
|
||||||
|
<string name="core_exit_full_screen">Exit Full Screen</string>
|
||||||
<string name="core_install">Install</string>
|
<string name="core_install">Install</string>
|
||||||
<string name="core_installing">Installing…</string>
|
<string name="core_installing">Installing…</string>
|
||||||
<string name="core_upgrade">Upgrade</string>
|
<string name="core_upgrade">Upgrade</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user