diff --git a/app/src/main/java/com/techlads/composetv/features/home/leftmenu/MenuHeader.kt b/app/src/main/java/com/techlads/composetv/features/home/leftmenu/MenuHeader.kt deleted file mode 100644 index b40edbc..0000000 --- a/app/src/main/java/com/techlads/composetv/features/home/leftmenu/MenuHeader.kt +++ /dev/null @@ -1,61 +0,0 @@ -@file:OptIn(ExperimentalTvMaterial3Api::class) - -package com.techlads.composetv.features.home.leftmenu - -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.keyframes -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.material3.Icon -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.tv.material3.ExperimentalTvMaterial3Api -import androidx.tv.material3.LocalContentColor -import androidx.tv.material3.Text -import com.techlads.composetv.theme.ComposeTvTheme -import compose.icons.LineAwesomeIcons -import compose.icons.lineawesomeicons.TvSolid - -@Composable -fun MenuHeader(expanded: Boolean = true) { - val animatedAlpha = animateFloatAsState( - animationSpec = keyframes { - this.delayMillis = 100 - this.durationMillis = 100 - }, - targetValue = if (expanded) 1f else 0f, label = "animatedAlpha", - ) - Column( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.width(if (expanded) 180.dp else 20.dp), - ) { - Icon( - modifier = Modifier.size(50.dp), - imageVector = LineAwesomeIcons.TvSolid, - contentDescription = "App icon", - tint = LocalContentColor.current, - ) - Text( - text = "Compose Tv", - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - modifier = Modifier.alpha(animatedAlpha.value), - maxLines = 1, - ) - } -} - -@Preview -@Composable -fun MenuHeaderPrev() { - ComposeTvTheme { - MenuHeader() - } -} diff --git a/app/src/main/java/com/techlads/composetv/features/home/leftmenu/data/MenuData.kt b/app/src/main/java/com/techlads/composetv/features/home/leftmenu/data/MenuData.kt index cdaed2e..418f65d 100644 --- a/app/src/main/java/com/techlads/composetv/features/home/leftmenu/data/MenuData.kt +++ b/app/src/main/java/com/techlads/composetv/features/home/leftmenu/data/MenuData.kt @@ -13,6 +13,7 @@ import compose.icons.lineawesomeicons.HeartSolid import compose.icons.lineawesomeicons.HomeSolid import compose.icons.lineawesomeicons.MusicSolid import compose.icons.lineawesomeicons.SearchSolid +import compose.icons.lineawesomeicons.UserCircle import compose.icons.lineawesomeicons.VideoSolid object MenuData { @@ -29,4 +30,10 @@ object MenuData { "Settings", LineAwesomeIcons.CogSolid, ) + + val profile = MenuItem( + Home.title, + "My Profile", + LineAwesomeIcons.UserCircle, + ) } diff --git a/app/src/main/java/com/techlads/composetv/features/home/navigation/drawer/HomeDrawer.kt b/app/src/main/java/com/techlads/composetv/features/home/navigation/drawer/HomeDrawer.kt index 1dd4c30..1072300 100644 --- a/app/src/main/java/com/techlads/composetv/features/home/navigation/drawer/HomeDrawer.kt +++ b/app/src/main/java/com/techlads/composetv/features/home/navigation/drawer/HomeDrawer.kt @@ -2,85 +2,37 @@ package com.techlads.composetv.features.home.navigation.drawer -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.core.animateDpAsState -import androidx.compose.animation.core.keyframes import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.selection.selectableGroup import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.tv.material3.ClickableSurfaceDefaults import androidx.tv.material3.DrawerValue import androidx.tv.material3.ExperimentalTvMaterial3Api import androidx.tv.material3.Icon import androidx.tv.material3.MaterialTheme import androidx.tv.material3.ModalNavigationDrawer -import androidx.tv.material3.Surface +import androidx.tv.material3.NavigationDrawerItem +import androidx.tv.material3.NavigationDrawerItemDefaults +import androidx.tv.material3.NavigationDrawerScope import androidx.tv.material3.Text import androidx.tv.material3.rememberDrawerState -import com.techlads.composetv.features.home.leftmenu.MenuHeader import com.techlads.composetv.features.home.leftmenu.data.MenuData import com.techlads.composetv.features.home.leftmenu.model.MenuItem -val navigationRow: @Composable ( - drawerValue: DrawerValue, - menu: MenuItem, - modifier: Modifier, - isSelected: Boolean, - onMenuSelected: ((menuItem: MenuItem) -> Unit)?, -) -> Unit = { drawerValue, menu, modifier, isSelected, onMenuSelected -> - - val padding = animateDpAsState( - animationSpec = keyframes { - this.delayMillis = 100 - }, - targetValue = if (drawerValue == DrawerValue.Open) 4.dp else 0.dp, label = "", - ) - - Surface( - onClick = { onMenuSelected?.invoke(menu) }, - colors = ClickableSurfaceDefaults.colors( - containerColor = if (isSelected) MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f) else MaterialTheme.colorScheme.surface, - ), - modifier = modifier - .padding(vertical = 4.dp) - .then(if (drawerValue == DrawerValue.Open) modifier.width(170.dp) else modifier) - ) { - Row( - Modifier.padding(horizontal = 12.dp, vertical = 8.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - menu.icon?.let { - Icon( - imageVector = it, - contentDescription = menu.text, - modifier = Modifier.size(20.dp), - ) - Spacer(modifier = Modifier.padding(horizontal = padding.value)) - } - AnimatedVisibility( - visible = drawerValue == DrawerValue.Open, - modifier = Modifier.height(20.dp), - ) { - Text( - text = menu.text, - maxLines = 1, - style = MaterialTheme.typography.bodyMedium, - ) - } - } - } -} @Composable fun HomeDrawer( @@ -88,40 +40,100 @@ fun HomeDrawer( selectedId: String = MenuData.menuItems.first().id, onMenuSelected: ((menuItem: MenuItem) -> Unit)? ) { + val closeDrawerWidth = 80.dp val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) ModalNavigationDrawer( - drawerState = drawerState, - drawerContent = { drawer -> + drawerState = drawerState, drawerContent = { drawer -> Column( Modifier .background(MaterialTheme.colorScheme.surface) .fillMaxHeight() - .padding(horizontal = 12.dp, vertical = 12.dp), - horizontalAlignment = Alignment.CenterHorizontally, + .padding(12.dp) + .selectableGroup(), + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.spacedBy( + 8.dp, alignment = Alignment.CenterVertically + ), ) { Spacer(modifier = Modifier.height(8.dp)) - MenuHeader(expanded = drawer == DrawerValue.Open) - Spacer(modifier = Modifier.height(16.dp)) - - MenuData.menuItems.forEach { - navigationRow(drawer, it, Modifier, selectedId == it.id) { - onMenuSelected?.invoke(it) - drawerState.setValue(DrawerValue.Closed) - } - } - - Spacer(modifier = Modifier.weight(1f)) - navigationRow( - drawer, MenuData.settingsItem, Modifier, MenuData.settingsItem.id == selectedId - ) { - onMenuSelected?.invoke(it) + Header(item = MenuData.profile, onMenuSelected = { drawerState.setValue(DrawerValue.Closed) + }) + MenuData.menuItems.forEachIndexed { index, item -> + NavigationRow(item = item, + isSelected = selectedId == item.id, + onMenuSelected = { + drawerState.setValue(DrawerValue.Closed) + onMenuSelected?.invoke(item) + }) } + Spacer(modifier = Modifier.weight(1f)) + NavigationRow(item = MenuData.settingsItem, + isSelected = selectedId == MenuData.settingsItem.id, + onMenuSelected = { + drawerState.setValue(DrawerValue.Closed) + onMenuSelected?.invoke(MenuData.settingsItem) + }) } - }, - content = content, - ) + }, scrimBrush = Brush.horizontalGradient( + listOf( + MaterialTheme.colorScheme.surface, Color.Transparent + ) + ) + ) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(start = closeDrawerWidth) + ) { + content() + } + } +} + +@Composable +fun NavigationDrawerScope.NavigationRow( + item: MenuItem, + isSelected: Boolean, + enabled: Boolean = true, + onMenuSelected: ((menuItem: MenuItem) -> Unit)? +) { + NavigationDrawerItem(selected = isSelected, enabled = enabled, + colors = NavigationDrawerItemDefaults.colors( + selectedContainerColor = MaterialTheme.colorScheme.surfaceVariant.copy( + alpha = 0.5f + ), + selectedContentColor = MaterialTheme.colorScheme.onSurface, + ), + onClick = { + onMenuSelected?.invoke(item) + }, leadingContent = { + Icon( + imageVector = item.icon ?: return@NavigationDrawerItem, + contentDescription = item.text, + modifier = Modifier.size(20.dp), + ) + }) { + Text(item.text) + } +} + +@Composable +fun NavigationDrawerScope.Header( + item: MenuItem, onMenuSelected: ((menuItem: MenuItem) -> Unit)? +) { + NavigationDrawerItem(selected = false, onClick = { + onMenuSelected?.invoke(item) + }, leadingContent = { + Icon( + imageVector = item.icon ?: return@NavigationDrawerItem, + contentDescription = item.text, + modifier = Modifier.size(40.dp), + ) + }) { + Text(item.text) + } } @Preview diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a1c1599..d1d153c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ qr_code = "1.5.3" timber = "5.0.1" hilt = "2.45" datastore-preferences = "1.0.0" -tv-compose = "1.0.0-alpha09" +tv-compose = "1.0.0-alpha10" line_awesome = "1.0.0" compose_bom = "2023.09.00" media3 = "1.1.1"