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 = 10709
versionName = "1.7.0-beta.10"
versionCode = 10710
versionName = "1.7.0-beta.11"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
resValue("string", "app_name", "TypeType")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.derivedStateOf
Expand Down Expand Up @@ -189,25 +188,13 @@ fun LoadedPlayer(
onSaveProgress = { onAction(PlayerAction.OnSaveProgress(it)) },
)

val expandedTopPadding = WindowInsets.safeDrawing.asPaddingValues().calculateTopPadding()
val expandedTopPaddingPx = with(LocalDensity.current) { expandedTopPadding.toPx() }
val autoplayVisible by remember(hostTransitionProgress) {
derivedStateOf { hostTransitionProgress() < 0.01f }
}
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.background)
.then(
if (isFullscreen) {
Modifier
} else {
Modifier.playerTopProgressPadding(
maxTopPx = expandedTopPaddingPx,
progress = hostTransitionProgress,
)
}
),
) {
PlayerContentLayout(
isFullscreen = isFullscreen,
Expand Down Expand Up @@ -322,23 +309,3 @@ fun LoadedPlayer(
onAction = onAction,
)
}

private fun Modifier.playerTopProgressPadding(
maxTopPx: Float,
progress: () -> Float,
): Modifier = layout { measurable, constraints ->
val topPx = (maxTopPx * (1f - progress().coerceIn(0f, 1f))).roundToInt()
val maxHeight = if (constraints.hasBoundedHeight) {
(constraints.maxHeight - topPx).coerceAtLeast(0)
} else {
constraints.maxHeight
}
val childConstraints = constraints.copy(
minHeight = constraints.minHeight.coerceAtMost(maxHeight),
maxHeight = maxHeight,
)
val placeable = measurable.measure(childConstraints)
layout(placeable.width, placeable.height + topPx) {
placeable.placeRelative(0, topPx)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,53 +47,59 @@ fun PlayerControls(
chaptersAvailable: Boolean = false,
sponsorBlockSegments: List<SponsorBlockSegment> = emptyList(),
seekPreviewPositionMs: Long? = null,
timelineScrubbing: Boolean = false,
onTimelineScrubbingChange: (Boolean) -> Unit = {},
) {
BoxWithConstraints(modifier = modifier) {
val compactControls = !isFullscreen && maxHeight < COMPACT_CONTROLS_HEIGHT
TopScrim(
compact = compactControls,
modifier = Modifier.align(Alignment.TopCenter),
)
if (!timelineScrubbing) {
TopScrim(
compact = compactControls,
modifier = Modifier.align(Alignment.TopCenter),
)
}
BottomScrim(
compact = compactControls,
isFullscreen = isFullscreen,
modifier = Modifier.align(Alignment.BottomCenter),
)
PlayerTopBar(
title = title,
onNavigateBack = onNavigateBack,
onOpenChapters = onOpenChapters,
onOpenOptions = onOpenOptions,
onEnterPip = onEnterPip,
onCycleResizeMode = onCycleResizeMode,
resizeMode = resizeMode,
isFullscreen = isFullscreen,
isPipAvailable = isPipAvailable,
chaptersAvailable = chaptersAvailable,
compact = compactControls,
modifier = Modifier
.align(Alignment.TopCenter)
.fillMaxWidth()
.testTag(PLAYER_TOP_CONTROLS_TAG)
.then(
if (isFullscreen) {
Modifier.windowInsetsPadding(WindowInsets.statusBars)
} else {
Modifier
},
),
)
PlayerCenterControls(
player = player,
isFullscreen = isFullscreen,
compact = compactControls,
modifier = Modifier.align(Alignment.Center).testTag(PLAYER_CENTER_CONTROLS_TAG),
)
if (!timelineScrubbing) {
PlayerTopBar(
title = title,
onNavigateBack = onNavigateBack,
onOpenChapters = onOpenChapters,
onOpenOptions = onOpenOptions,
onEnterPip = onEnterPip,
onCycleResizeMode = onCycleResizeMode,
resizeMode = resizeMode,
isFullscreen = isFullscreen,
isPipAvailable = isPipAvailable,
chaptersAvailable = chaptersAvailable,
compact = compactControls,
modifier = Modifier
.align(Alignment.TopCenter)
.fillMaxWidth()
.testTag(PLAYER_TOP_CONTROLS_TAG)
.then(
if (isFullscreen) {
Modifier.windowInsetsPadding(WindowInsets.statusBars)
} else {
Modifier
},
),
)
PlayerCenterControls(
player = player,
isFullscreen = isFullscreen,
compact = compactControls,
modifier = Modifier.align(Alignment.Center).testTag(PLAYER_CENTER_CONTROLS_TAG),
)
}
BottomBar(
player = player,
sponsorBlockSegments = sponsorBlockSegments,
seekPreviewPositionMs = seekPreviewPositionMs,
timelineScrubbing = timelineScrubbing,
onTimelineScrubbingChange = onTimelineScrubbingChange,
isFullscreen = isFullscreen,
compact = compactControls,
Expand Down Expand Up @@ -161,12 +167,14 @@ private fun BottomBar(
player: Player,
sponsorBlockSegments: List<SponsorBlockSegment>,
seekPreviewPositionMs: Long?,
timelineScrubbing: Boolean,
onTimelineScrubbingChange: (Boolean) -> Unit,
isFullscreen: Boolean,
compact: Boolean,
onToggleFullscreen: () -> Unit,
modifier: Modifier = Modifier,
) {
// I SPEND 2 HOURS FIGURING OUT HOW TO ALIGN THIS FREAKING SEEKBAR WITH THE BUTTON FULLSCREEN IM SUCH A FAILURE
Row(
modifier = modifier
.height(
Expand All @@ -187,23 +195,25 @@ private fun BottomBar(
onScrubbingChange = onTimelineScrubbingChange,
modifier = Modifier.weight(1f),
)
IconButton(
onClick = onToggleFullscreen,
modifier = Modifier.size(
when {
isFullscreen -> 48.dp
compact -> 36.dp
else -> 40.dp
},
),
) {
Icon(
painter = painterResource(
if (isFullscreen) R.drawable.ic_fullscreen_exit else R.drawable.ic_fullscreen,
if (!timelineScrubbing) {
IconButton(
onClick = onToggleFullscreen,
modifier = Modifier.size(
when {
isFullscreen -> 48.dp
compact -> 36.dp
else -> 40.dp
},
),
contentDescription = stringResource(R.string.player_fullscreen),
tint = Color.White,
)
) {
Icon(
painter = painterResource(
if (isFullscreen) R.drawable.ic_fullscreen_exit else R.drawable.ic_fullscreen,
),
contentDescription = stringResource(R.string.player_fullscreen),
tint = Color.White,
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
Expand All @@ -24,6 +29,7 @@ import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.unit.dp
import androidx.media3.common.util.UnstableApi
import androidx.media3.session.MediaController
import androidx.media3.ui.compose.state.rememberPresentationState
Expand Down Expand Up @@ -262,7 +268,7 @@ internal fun PlayerSurfaceBox(
fraction
},
onGestureFeedback = {
controlsVisible = gestureState.dragMode.value == DragMode.Seek
controlsVisible = false
hapticFeedback.performHapticFeedback(HapticFeedbackType.TextHandleMove)
},
isFullscreen = isFullscreen,
Expand All @@ -278,6 +284,31 @@ internal fun PlayerSurfaceBox(
)
}

AnimatedVisibility(
visible = gestureState.seekDragOverlayActive.value,
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier.align(Alignment.BottomCenter),
) {
PlayerSeekScrubOverlay(
player = player,
positionMs = gestureState.seekDragTargetMs.longValue,
segments = sponsorBlockPolicy.visibleSegments,
isFullscreen = isFullscreen,
modifier = Modifier
.fillMaxWidth()
.then(
if (isFullscreen) {
Modifier.padding(start = 12.dp, end = 8.dp, bottom = 6.dp)
} else {
Modifier
.windowInsetsPadding(WindowInsets.navigationBars)
.padding(start = 4.dp, end = 4.dp)
},
),
)
}

AnimatedVisibility(
visible = controlsAllowedByProgress &&
(controlsVisible || accessibleControls) &&
Expand Down
Loading