Skip to content
This repository has been archived by the owner on Aug 7, 2024. It is now read-only.

Commit

Permalink
feat: support for large screen adaptive layouts (fix #43)
Browse files Browse the repository at this point in the history
  • Loading branch information
SuhasDissa committed May 7, 2024
1 parent 35fd345 commit a5d9046
Show file tree
Hide file tree
Showing 8 changed files with 466 additions and 35 deletions.
45 changes: 45 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ dependencies {

implementation("io.coil-kt:coil-compose:2.6.0")
implementation("com.google.android.material:material:1.11.0")
implementation("androidx.compose.material3.adaptive:adaptive-android:1.0.0-alpha12")

val media3Version = "1.1.1"

Expand All @@ -99,6 +100,7 @@ dependencies {

implementation("org.burnoutcrew.composereorderable:reorderable:0.9.6")
implementation("com.github.nanihadesuka:LazyColumnScrollbar:1.8.0")
implementation("androidx.window:window:1.2.0")

implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
Expand Down
171 changes: 168 additions & 3 deletions app/src/main/java/app/suhasdissa/vibeyou/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,21 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.PermanentNavigationDrawer
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
Expand All @@ -26,18 +34,26 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import androidx.window.core.layout.WindowHeightSizeClass
import androidx.window.core.layout.WindowSizeClass
import androidx.window.core.layout.WindowWidthSizeClass
import app.suhasdissa.vibeyou.navigation.AppNavHost
import app.suhasdissa.vibeyou.navigation.Destination
import app.suhasdissa.vibeyou.navigation.HomeDestination
import app.suhasdissa.vibeyou.presentation.components.MiniPlayerScaffold
import app.suhasdissa.vibeyou.presentation.components.NavDrawerContent
import app.suhasdissa.vibeyou.presentation.components.ModalNavDrawerContent
import app.suhasdissa.vibeyou.presentation.components.PermanentNavDrawerContent
import app.suhasdissa.vibeyou.presentation.screens.player.FullScreenPlayer
import app.suhasdissa.vibeyou.presentation.screens.player.model.PlayerViewModel
import app.suhasdissa.vibeyou.presentation.screens.settings.model.SettingsModel
import app.suhasdissa.vibeyou.ui.theme.VibeYouTheme
import app.suhasdissa.vibeyou.utils.ThemeUtil
import app.suhasdissa.vibeyou.utils.mediaItemState
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
Expand Down Expand Up @@ -137,11 +153,58 @@ class MainActivity : ComponentActivity() {
@Composable
private fun MainAppContent(
playerViewModel: PlayerViewModel,
settingsModel: SettingsModel
settingsModel: SettingsModel,
windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
) {
val navHostController = rememberNavController()
val homeNavHostController = rememberNavController()
if (windowSizeClass.windowHeightSizeClass != WindowHeightSizeClass.COMPACT) {
when (windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> {
ModelNavDrawerLayout(
navHostController,
homeNavHostController,
playerViewModel,
settingsModel
)
}

WindowWidthSizeClass.MEDIUM -> {
PermanentNavDrawerLayout(
navHostController,
homeNavHostController,
playerViewModel,
settingsModel
)
}

WindowWidthSizeClass.EXPANDED -> {
PermanentNavDrawerWithPlayerLayout(
navHostController,
homeNavHostController,
playerViewModel,
settingsModel
)
}
}
} else {
PermanentNavDrawerLayout(
navHostController,
homeNavHostController,
playerViewModel,
settingsModel,
horizontalPlayer = true
)
}
}

@Composable
private fun ModelNavDrawerLayout(
navHostController: NavHostController,
homeNavHostController: NavHostController,
playerViewModel: PlayerViewModel,
settingsModel: SettingsModel
) {
val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()
var currentDestination by remember {
Expand All @@ -152,7 +215,7 @@ private fun MainAppContent(
drawerState = drawerState,
gesturesEnabled = drawerState.isOpen,
drawerContent = {
NavDrawerContent(
ModalNavDrawerContent(
currentDestination = currentDestination,
onDestinationSelected = {
scope.launch {
Expand Down Expand Up @@ -190,3 +253,105 @@ private fun MainAppContent(

}
}

@Composable
private fun PermanentNavDrawerLayout(
navHostController: NavHostController,
homeNavHostController: NavHostController,
playerViewModel: PlayerViewModel,
settingsModel: SettingsModel,
horizontalPlayer: Boolean = false
) {
var currentDestination by remember {
mutableStateOf<Any>(HomeDestination.LocalMusic)
}

PermanentNavigationDrawer(drawerContent = {
PermanentNavDrawerContent(
currentDestination = currentDestination,
onDestinationSelected = {
currentDestination = it
when (it) {
is Destination -> navHostController.navigate(it)
is HomeDestination -> {
homeNavHostController.popBackStack()
homeNavHostController.navigate(it)
}
}
}
)
}) {
MiniPlayerScaffold(playerViewModel, horizontalPlayer = horizontalPlayer) { pV ->
AppNavHost(
modifier = Modifier
.fillMaxSize()
.consumeWindowInsets(pV)
.padding(pV),
navHostController = navHostController,
homeNavHostController = homeNavHostController,
onDrawerOpen = null,
playerViewModel,
settingsModel
)
}
}
}

@Composable
private fun PermanentNavDrawerWithPlayerLayout(
navHostController: NavHostController,
homeNavHostController: NavHostController,
playerViewModel: PlayerViewModel,
settingsModel: SettingsModel
) {
var currentDestination by remember {
mutableStateOf<Any>(HomeDestination.LocalMusic)
}

PermanentNavigationDrawer(drawerContent = {
PermanentNavDrawerContent(
currentDestination = currentDestination,
onDestinationSelected = {
currentDestination = it
when (it) {
is Destination -> navHostController.navigate(it)
is HomeDestination -> {
homeNavHostController.popBackStack()
homeNavHostController.navigate(it)
}
}
}
)
}) {
Row(Modifier.fillMaxSize()) {
AppNavHost(
modifier = Modifier
.fillMaxHeight()
.weight(1f),
navHostController = navHostController,
homeNavHostController = homeNavHostController,
onDrawerOpen = null,
playerViewModel,
settingsModel
)

playerViewModel.controller?.let { controller ->
val mediaItem by controller.mediaItemState()
AnimatedVisibility(visible = mediaItem != null) {
Column(
Modifier
.fillMaxHeight()
.width(400.dp)
.background(MaterialTheme.colorScheme.surface)
) {
FullScreenPlayer(
controller,
onCollapse = null,
playerViewModel
)
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fun AppNavHost(
modifier: Modifier = Modifier,
navHostController: NavHostController,
homeNavHostController: NavHostController,
onDrawerOpen: () -> Unit,
onDrawerOpen: (() -> Unit)?,
playerViewModel: PlayerViewModel,
settingsModel: SettingsModel
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package app.suhasdissa.vibeyou.presentation.components

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.BottomSheetDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold
Expand All @@ -16,8 +18,10 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import app.suhasdissa.vibeyou.presentation.screens.player.FullScreenPlayer
import app.suhasdissa.vibeyou.presentation.screens.player.FullScreenPlayerHorizontal
import app.suhasdissa.vibeyou.presentation.screens.player.MiniPlayer
import app.suhasdissa.vibeyou.presentation.screens.player.model.PlayerViewModel
import app.suhasdissa.vibeyou.utils.mediaItemState
Expand All @@ -27,6 +31,7 @@ import kotlinx.coroutines.launch
@Composable
fun MiniPlayerScaffold(
playerViewModel: PlayerViewModel,
horizontalPlayer: Boolean = false,
content: @Composable (PaddingValues) -> Unit
) {
var isPlayerSheetVisible by remember { mutableStateOf(false) }
Expand All @@ -39,20 +44,43 @@ fun MiniPlayerScaffold(
onDismissRequest = { isPlayerSheetVisible = false },
sheetState = playerSheetState,
shape = RoundedCornerShape(8.dp),
dragHandle = null
dragHandle = null,
sheetMaxWidth = Dp.Unspecified,
windowInsets = if (horizontalPlayer) WindowInsets(
0,
0,
0,
0
) else BottomSheetDefaults.windowInsets
) {
playerViewModel.controller?.let { controller ->
FullScreenPlayer(
controller,
onCollapse = {
scope.launch { playerSheetState.hide() }.invokeOnCompletion {
if (!playerSheetState.isVisible) {
isPlayerSheetVisible = false
if (horizontalPlayer) {
Row(Modifier.fillMaxSize()) {
FullScreenPlayerHorizontal(
controller,
onCollapse = {
scope.launch { playerSheetState.hide() }.invokeOnCompletion {
if (!playerSheetState.isVisible) {
isPlayerSheetVisible = false
}
}
},
playerViewModel
)
}
} else {
FullScreenPlayer(
controller,
onCollapse = {
scope.launch { playerSheetState.hide() }.invokeOnCompletion {
if (!playerSheetState.isVisible) {
isPlayerSheetVisible = false
}
}
}
},
playerViewModel
)
},
playerViewModel
)
}
}
}
}
Expand Down
Loading

0 comments on commit a5d9046

Please sign in to comment.