fix: add window insets to top bar and bottom navigation bar, queue sheet

This commit is contained in:
Kingkor Roy Tirtho 2026-10-14 19:26:54 +06:00
parent fda5bb8a60
commit d5eaf101eb
9 changed files with 37 additions and 38 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<g id="Alapkör">
<circle id="XMLID_23_" fill="#CD201F" cx="50" cy="50" r="50"/>
</g>
<g id="Elemek">
<path id="XMLID_19_" fill="#FFFFFF" d="M47,28.2c-9-5.3-15.3-9-15.3-9v61.7c0,0,30.4-18,52.3-30.9C72.1,43,57.7,34.5,47,28.2z"/>
</g>
<g id="Fedő">
<path id="XMLID_5_" fill="#CD201F" d="M48.4,40.1c-4.1-2.4-7-4.1-7-4.1V64c0,0,13.9-8.2,23.8-14C59.8,46.8,53.3,42.9,48.4,40.1z"/>
<rect id="XMLID_4_" x="41.4" y="55.6" fill="#CD201F" width="6.2" height="21"/>
</g>
<g id="Vonalak">
</g>
</svg>

Before

Width:  |  Height:  |  Size: 787 B

View File

@ -32,7 +32,6 @@ 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.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
@ -156,7 +155,7 @@ fun PlatformWebViewScreen(webViewController: WebViewController) {
ApplicationMainBar( ApplicationMainBar(
title = { title = {
Row( Row(
modifier = Modifier.fillMaxWidth().statusBarsPadding().height(56.dp), modifier = Modifier.fillMaxWidth().height(56.dp),
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
@ -227,4 +226,4 @@ fun PlatformWebViewScreen(webViewController: WebViewController) {
navigator.evaluateJavaScript(bridgeBootstrapScript) navigator.evaluateJavaScript(bridgeBootstrapScript)
}) })
} }
} }

View File

@ -30,7 +30,6 @@ import androidx.compose.foundation.layout.fillMaxHeight
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.navigationBars import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
@ -128,7 +127,11 @@ fun AppShell(
Box(modifier = Modifier.fillMaxSize()) { Box(modifier = Modifier.fillMaxSize()) {
val useSidebar = viewModel.useSidebar() val useSidebar = viewModel.useSidebar()
val bottomOverlayInset = viewModel.bottomOverlayInset(useSidebar) val density = LocalDensity.current
val navigationBarInset = with(density) {
WindowInsets.navigationBars.getBottom(this).toDp()
}
val bottomOverlayInset = viewModel.bottomOverlayInset(useSidebar) + navigationBarInset
CompositionLocalProvider(LocalAppShellBottomInset provides bottomOverlayInset) { CompositionLocalProvider(LocalAppShellBottomInset provides bottomOverlayInset) {
if (useSidebar) { if (useSidebar) {
@ -278,7 +281,9 @@ private fun CompactPlayerOverlay(
val floatingPlayerHeightPx = with(density) { viewModel.floatingPlayerHeight.toPx() } val floatingPlayerHeightPx = with(density) { viewModel.floatingPlayerHeight.toPx() }
val bottomBarHeightPx = with(density) { viewModel.bottomBarHeight.toPx() } val bottomBarHeightPx = with(density) { viewModel.bottomBarHeight.toPx() }
val navBarInsetPx = WindowInsets.navigationBars.getBottom(density).toFloat() val navBarInsetPx = WindowInsets.navigationBars.getBottom(density).toFloat()
val peekHeightPx = floatingPlayerHeightPx + bottomBarHeightPx + navBarInsetPx val playerBarSpacingPx = with(density) { viewModel.floatingPlayerSpacing.toPx() }
val peekHeightPx =
floatingPlayerHeightPx + bottomBarHeightPx + navBarInsetPx + playerBarSpacingPx
val peekHeight = with(density) { peekHeightPx.toDp() } val peekHeight = with(density) { peekHeightPx.toDp() }
val partialDetent = remember(peekHeight) { val partialDetent = remember(peekHeight) {
@ -318,7 +323,6 @@ private fun CompactPlayerOverlay(
Column(modifier = Modifier.fillMaxWidth()) { Column(modifier = Modifier.fillMaxWidth()) {
AppFloatingPlayer( AppFloatingPlayer(
modifier = Modifier modifier = Modifier
.offset(y = 12.dp)
.graphicsLayer { .graphicsLayer {
alpha = uiState.floatingPlayerAlpha alpha = uiState.floatingPlayerAlpha
}) })
@ -332,9 +336,12 @@ private fun CompactPlayerOverlay(
AppBottombar( AppBottombar(
navigator = navigator, navigator = navigator,
navigationState = navigationState, navigationState = navigationState,
modifier = Modifier.fillMaxWidth().align(Alignment.BottomCenter).graphicsLayer { modifier = Modifier
alpha = uiState.floatingPlayerAlpha .fillMaxWidth()
}) .align(Alignment.BottomCenter)
.graphicsLayer {
alpha = uiState.floatingPlayerAlpha
})
} }
} }
} }

View File

@ -42,9 +42,9 @@ data class LyricsOverlayState(
class AppShellViewModel : ViewModel() { class AppShellViewModel : ViewModel() {
val sidebarMinWidth = 840.dp val sidebarMinWidth = 840.dp
val bottomBarEstimatedHeight = 58.dp
val bottomBarHeight = 80.dp val bottomBarHeight = 80.dp
val floatingPlayerHeight = 74.dp val floatingPlayerHeight = 76.dp
val floatingPlayerSpacing = 12.dp
val largePlayerInset = 100.dp val largePlayerInset = 100.dp
val floatingPlayerDismissProgress = 0.7f val floatingPlayerDismissProgress = 0.7f
val expandedPlayerVisibilityThreshold = 0.001f val expandedPlayerVisibilityThreshold = 0.001f
@ -53,11 +53,8 @@ class AppShellViewModel : ViewModel() {
val isLyricsOverlayVisible: StateFlow<Boolean> = lyricsOverlayVisible.asStateFlow() val isLyricsOverlayVisible: StateFlow<Boolean> = lyricsOverlayVisible.asStateFlow()
val floatingPlayerBottomOffset: Dp
get() = bottomBarEstimatedHeight + 8.dp
val compactChromeInset: Dp val compactChromeInset: Dp
get() = floatingPlayerBottomOffset + floatingPlayerHeight + 10.dp get() = bottomBarHeight + floatingPlayerHeight + floatingPlayerSpacing
@Composable @Composable
fun useSidebar(maxWidth: Dp? = null): Boolean { fun useSidebar(maxWidth: Dp? = null): Boolean {

View File

@ -34,6 +34,9 @@ import org.spotube.millennium.composables.MillenniumModalBottomSheet
import org.spotube.millennium.composables.rememberMillenniumDrawerState import org.spotube.millennium.composables.rememberMillenniumDrawerState
private val SlidingSheetBreakpoint = 840.dp private val SlidingSheetBreakpoint = 840.dp
private val MaxHeightSheetDetent = SheetDetent("max-height-85-percent") { containerHeight, sheetHeight ->
minOf(sheetHeight, containerHeight * 0.85f)
}
@Composable @Composable
fun QueueSheet( fun QueueSheet(
@ -85,7 +88,10 @@ internal fun BottomSheetContent(
content: @Composable () -> Unit content: @Composable () -> Unit
) { ) {
if (!isVisible) return if (!isVisible) return
val sheetState = rememberModalBottomSheetState(initialDetent = SheetDetent.FullyExpanded) val sheetState = rememberModalBottomSheetState(
initialDetent = MaxHeightSheetDetent,
detents = listOf(SheetDetent.Hidden, MaxHeightSheetDetent)
)
LaunchedEffect(sheetState.bottomSheetState.currentDetent) { LaunchedEffect(sheetState.bottomSheetState.currentDetent) {
if (sheetState.bottomSheetState.currentDetent == SheetDetent.Hidden) { if (sheetState.bottomSheetState.currentDetent == SheetDetent.Hidden) {
onDismiss() onDismiss()

View File

@ -18,6 +18,8 @@
package dev.krtirtho.spotube.core.ui.component package dev.krtirtho.spotube.core.ui.component
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.statusBars
import org.spotube.millennium.composables.MillenniumTopAppBar import org.spotube.millennium.composables.MillenniumTopAppBar
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -33,10 +35,11 @@ actual fun ApplicationMainBar(
title = title, title = title,
subtitle = subtitle, subtitle = subtitle,
actions = actions, actions = actions,
windowInsets = WindowInsets.statusBars,
navigationIcon = { navigationIcon = {
if (backButton) { if (backButton) {
ApplicationBackButton() ApplicationBackButton()
} }
} }
) )
} }

View File

@ -27,4 +27,8 @@ org.gradle.caching=true
#Android #Android
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
android.useAndroidX=true android.useAndroidX=true
# Preserve compatibility with this project's current Kotlin Multiplatform Android setup on AGP 9.
android.builtInKotlin=false
android.newDsl=false
android.sourceset.disallowProvider=false

View File

@ -14,7 +14,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
[versions] [versions]
agp = "8.13.2" agp = "9.1.0"
android-compileSdk = "37" android-compileSdk = "37"
android-minSdk = "28" android-minSdk = "28"
android-targetSdk = "36" android-targetSdk = "36"
@ -193,4 +193,4 @@ uniffi = { id = "dev.gobley.uniffi", version.ref = "uniffi" }
cargo = { id = "dev.gobley.cargo", version.ref = "uniffi" } cargo = { id = "dev.gobley.cargo", version.ref = "uniffi" }
mokkery = { id = "dev.mokkery", version.ref = "mokkery" } mokkery = { id = "dev.mokkery", version.ref = "mokkery" }
vanniktechMavenPublish = { id = "com.vanniktech.maven.publish", version.ref = "vanniktechMavenPublish" } vanniktechMavenPublish = { id = "com.vanniktech.maven.publish", version.ref = "vanniktechMavenPublish" }
neucleusFramework = { id = "dev.nucleusframework", version.ref = "nucleusNucleusApplication" } neucleusFramework = { id = "dev.nucleusframework", version.ref = "nucleusNucleusApplication" }