Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ android {
applicationId = "dev.typetype.android"
minSdk = 23
targetSdk = 37
versionCode = 10707
versionName = "1.7.0-beta.8"
versionCode = 10708
versionName = "1.7.0-beta.9"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
resValue("string", "app_name", "TypeType")
}
Expand Down
24 changes: 6 additions & 18 deletions app/src/main/java/dev/typetype/android/AppNavigation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,7 @@ internal fun AppTopBar(

@Composable
internal fun AppBottomBar(
currentDestination: NavDestination?,
fallbackTabRouteQualifiedName: String?,
selectedTabRouteQualifiedName: String?,
onTabClick: (TopLevelTab) -> Unit,
tabs: List<TopLevelTab> = topLevelTabs,
modifier: Modifier = Modifier,
Expand All @@ -155,10 +154,10 @@ internal fun AppBottomBar(
containerColor = MaterialTheme.colorScheme.surface,
) {
tabs.forEach { tab: TopLevelTab ->
val selected = tab.isSelected(currentDestination, fallbackTabRouteQualifiedName, tabs)
val selected = tab.route::class.qualifiedName == selectedTabRouteQualifiedName
NavigationBarItem(
selected = selected,
onClick = { if (!currentDestination.matchesRoute(tab.route)) onTabClick(tab) },
onClick = { onTabClick(tab) },
icon = { Icon(painterResource(tab.iconRes), contentDescription = null) },
label = { Text(stringResource(tab.labelRes)) },
)
Expand All @@ -169,8 +168,7 @@ internal fun AppBottomBar(

@Composable
internal fun AppNavigationRail(
currentDestination: NavDestination?,
fallbackTabRouteQualifiedName: String?,
selectedTabRouteQualifiedName: String?,
onTabClick: (TopLevelTab) -> Unit,
tabs: List<TopLevelTab> = topLevelTabs,
modifier: Modifier = Modifier,
Expand All @@ -184,10 +182,10 @@ internal fun AppNavigationRail(
) {
Spacer(Modifier.weight(1f))
tabs.forEach { tab: TopLevelTab ->
val selected = tab.isSelected(currentDestination, fallbackTabRouteQualifiedName, tabs)
val selected = tab.route::class.qualifiedName == selectedTabRouteQualifiedName
NavigationRailItem(
selected = selected,
onClick = { if (!currentDestination.matchesRoute(tab.route)) onTabClick(tab) },
onClick = { onTabClick(tab) },
icon = { Icon(painterResource(tab.iconRes), contentDescription = null) },
label = { Text(stringResource(tab.labelRes)) },
)
Expand Down Expand Up @@ -220,16 +218,6 @@ private fun ProfileAvatarButton(
}
}

private fun TopLevelTab.isSelected(
destination: NavDestination?,
fallbackRouteName: String?,
tabs: List<TopLevelTab>,
): Boolean {
val direct = destination.matchesRoute(route)
val anyDirect = tabs.any { destination.matchesRoute(it.route) }
return direct || (!anyDirect && route::class.qualifiedName == fallbackRouteName)
}

internal fun NavDestination?.matchesRoute(route: Any): Boolean {
val destination = this ?: return false
return when (route) {
Expand Down
20 changes: 12 additions & 8 deletions app/src/main/java/dev/typetype/android/AppShell.kt
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ fun AppShell(
currentDestination?.hasRoute<SearchRoute>() == true ||
currentDestination?.hasRoute<NotificationsRoute>() == true
)
var activeTabRoute by rememberSaveable { mutableStateOf<String?>(null) }
var selectedTabRoute by rememberSaveable { mutableStateOf<String?>(null) }
var isPlayerFullscreen by remember { mutableStateOf(false) }
var playerTransitionProgress by remember { mutableFloatStateOf(0f) }
val playerHostState by playerHostController.state.collectAsStateWithLifecycle()
Expand All @@ -103,9 +103,13 @@ fun AppShell(
)
LaunchedEffect(currentDestination) {
topLevelTabs.firstOrNull { currentDestination.matchesRoute(it.route) }?.let {
activeTabRoute = it.route::class.qualifiedName
selectedTabRoute = it.route::class.qualifiedName
}
}
val selectedTabRouteQualifiedName = selectedTabRoute
?: topLevelTabs.firstOrNull { currentDestination.matchesRoute(it.route) }
?.route
?.let { it::class.qualifiedName }

val mediaController = rememberMediaController().value
val snackbarHostState = remember { SnackbarHostState() }
Expand All @@ -119,10 +123,10 @@ fun AppShell(
Row(modifier = Modifier.fillMaxSize()) {
if (usesNavigationRail && showsNavigation && appChromeVisible) {
AppNavigationRail(
currentDestination = currentDestination,
fallbackTabRouteQualifiedName = activeTabRoute,
selectedTabRouteQualifiedName = selectedTabRouteQualifiedName,
onTabClick = { tab: TopLevelTab ->
navController.navigateTopLevel(tab.route, activeTabRoute)
selectedTabRoute = tab.route::class.qualifiedName
navController.navigateTopLevel(tab.route, selectedTabRoute)
},
tabs = navigationTabs,
)
Expand Down Expand Up @@ -163,10 +167,10 @@ fun AppShell(
bottomBar = {
if (!usesNavigationRail && showsNavigation) {
AppBottomBar(
currentDestination = currentDestination,
fallbackTabRouteQualifiedName = activeTabRoute,
selectedTabRouteQualifiedName = selectedTabRouteQualifiedName,
onTabClick = { tab: TopLevelTab ->
navController.navigateTopLevel(tab.route, activeTabRoute)
selectedTabRoute = tab.route::class.qualifiedName
navController.navigateTopLevel(tab.route, selectedTabRoute)
},
tabs = navigationTabs,
modifier = Modifier.playerChrome(phoneChromeAlpha),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.navigationBarsIgnoringVisibility
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBars
Expand Down Expand Up @@ -56,6 +56,7 @@ fun PlayerControls(
)
BottomScrim(
compact = compactControls,
isFullscreen = isFullscreen,
modifier = Modifier.align(Alignment.BottomCenter),
)
PlayerTopBar(
Expand Down Expand Up @@ -99,11 +100,17 @@ fun PlayerControls(
.align(Alignment.BottomCenter)
.fillMaxWidth()
.testTag(PLAYER_BOTTOM_CONTROLS_TAG)
.windowInsetsPadding(WindowInsets.navigationBarsIgnoringVisibility)
.then(
if (isFullscreen) {
Modifier
} else {
Modifier.windowInsetsPadding(WindowInsets.navigationBars)
},
)
.padding(
start = if (isFullscreen) 12.dp else 4.dp,
end = if (isFullscreen) 8.dp else 4.dp,
bottom = if (isFullscreen) 12.dp else 0.dp,
bottom = if (isFullscreen) 6.dp else 0.dp,
),
)
}
Expand All @@ -124,11 +131,21 @@ private fun TopScrim(compact: Boolean, modifier: Modifier = Modifier) {
}

@Composable
private fun BottomScrim(compact: Boolean, modifier: Modifier = Modifier) {
private fun BottomScrim(
compact: Boolean,
isFullscreen: Boolean,
modifier: Modifier = Modifier,
) {
Box(
modifier = modifier
.fillMaxWidth()
.height(if (compact) 88.dp else 152.dp)
.height(
when {
isFullscreen -> 116.dp
compact -> 88.dp
else -> 152.dp
},
)
.background(
Brush.verticalGradient(
colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.72f)),
Expand Down Expand Up @@ -157,7 +174,7 @@ private fun BottomBar(
},
)
.padding(start = if (isFullscreen) 8.dp else 2.dp, end = 2.dp),
verticalAlignment = Alignment.CenterVertically,
verticalAlignment = Alignment.Bottom,
) {
PlayerTimeBar(
player = player,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,15 @@ internal fun PlayerSurfaceBox(
LaunchedEffect(accessibleControls) {
if (accessibleControls) controlsVisible = true
}
LaunchedEffect(controlsVisible, playbackStatus.isPlaying, accessibleControls) {
val isSeekDragging = gestureState.dragMode.value == DragMode.Seek
LaunchedEffect(
controlsVisible,
playbackStatus.isPlaying,
accessibleControls,
isSeekDragging,
) {
if (controlsVisible && playbackStatus.isPlaying && !accessibleControls) {
if (isSeekDragging) return@LaunchedEffect
delay(AUTO_HIDE_DELAY_MS)
controlsVisible = false
}
Expand Down