fix(media): properly constrain video height within NoteCard

Replace aspectRatio modifier with BoxWithConstraints that manually
calculates height from aspect ratio and clamps it to the max height
constraint. Video now stays within its allocated space in the card,
so controls are accessible and content below is not overlapped.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
nrobi144
2026-03-17 17:09:40 +02:00
parent fbde0052a8
commit d70b13ef33
@@ -23,9 +23,10 @@ package com.vitorpamplona.amethyst.desktop.ui.media
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.BoxWithConstraints
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.height
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
@@ -248,77 +249,84 @@ fun DesktopVideoPlayer(
return return
} }
Box( BoxWithConstraints(modifier = modifier) {
modifier = // Calculate height from aspect ratio, clamped to max constraints
modifier val desiredHeight = maxWidth / aspectRatio
.aspectRatio(aspectRatio) val constrainedHeight = if (constraints.hasBoundedHeight) minOf(desiredHeight, maxHeight) else desiredHeight
.background(
MaterialTheme.colorScheme.surfaceContainerHigh, Box(
RoundedCornerShape(8.dp), modifier =
), Modifier
contentAlignment = Alignment.Center, .fillMaxWidth()
) { .height(constrainedHeight)
val displayBitmap = frame ?: thumbnail .background(
displayBitmap?.let { bitmap -> MaterialTheme.colorScheme.surfaceContainerHigh,
Image( RoundedCornerShape(8.dp),
bitmap = bitmap, ),
contentDescription = "Video", contentAlignment = Alignment.Center,
modifier = ) {
Modifier val displayBitmap = frame ?: thumbnail
.fillMaxSize() displayBitmap?.let { bitmap ->
.clip(RoundedCornerShape(8.dp)), Image(
contentScale = ContentScale.Fit, bitmap = bitmap,
contentDescription = "Video",
modifier =
Modifier
.fillMaxSize()
.clip(RoundedCornerShape(8.dp)),
contentScale = ContentScale.Fit,
)
}
VideoControls(
isPlaying = isPlaying,
isBuffering = isBuffering,
position = position,
duration = duration,
currentTime = currentTime,
volume = volume,
isMuted = isMuted,
viewMode = viewMode,
onPlayPause = {
val p = player
if (p != null) {
if (isPlaying) {
p.controls().pause()
} else {
ActiveMediaManager.activate(playerId)
if (position <= 0f && !p.status().isPlaying) {
p.media().play(url)
isBuffering = true
} else {
p.controls().play()
}
}
} else {
// First play — activate lazy init
activated = true
}
},
onSeek = { pos ->
player?.controls()?.setPosition(pos)
},
onVolumeChange = { vol ->
volume = vol
player?.audio()?.setVolume(vol)
},
onMuteToggle = {
isMuted = !isMuted
player?.audio()?.isMute = isMuted
},
onFullscreen =
if (onFullscreen != null) {
{ onFullscreen(position) }
} else {
null
},
onViewModeChange = onViewModeChange,
trailingControls = trailingControls,
) )
} }
VideoControls(
isPlaying = isPlaying,
isBuffering = isBuffering,
position = position,
duration = duration,
currentTime = currentTime,
volume = volume,
isMuted = isMuted,
viewMode = viewMode,
onPlayPause = {
val p = player
if (p != null) {
if (isPlaying) {
p.controls().pause()
} else {
ActiveMediaManager.activate(playerId)
if (position <= 0f && !p.status().isPlaying) {
p.media().play(url)
isBuffering = true
} else {
p.controls().play()
}
}
} else {
// First play — activate lazy init
activated = true
}
},
onSeek = { pos ->
player?.controls()?.setPosition(pos)
},
onVolumeChange = { vol ->
volume = vol
player?.audio()?.setVolume(vol)
},
onMuteToggle = {
isMuted = !isMuted
player?.audio()?.isMute = isMuted
},
onFullscreen =
if (onFullscreen != null) {
{ onFullscreen(position) }
} else {
null
},
onViewModeChange = onViewModeChange,
trailingControls = trailingControls,
)
} }
} }