Use shared capture icons and menus for camera and resolution selection

This commit is contained in:
evgeny committed 2026-10-28 12:08:06 +01:00
1 parent 379e7731df
commit b84561dba5
1 file changed
+46 -9
@@ -41,9 +41,11 @@ import com.utun.chat.ui.components.ZoomableImage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import kotlin.math.roundToInt
enum class CaptureMode { PHOTO, VIDEO }
private enum class CapturePhase { IDLE, CAPTURING, RECORDING, PAUSED, FINALIZING, CAPTURED, SENDING }
private enum class CameraOption { CAMERA, RESOLUTION }
private enum class CaptureQuality(val label: String, val quality: Quality, val bitrate: Int) {
SD_LOW("480p 512k", Quality.SD, 512_000), SD("480p 1M", Quality.SD, 1_000_000),
HD("720p 2M", Quality.HD, 2_000_000), FHD("1080p 4.5M", Quality.FHD, 4_500_000)
@@ -254,6 +256,9 @@ fun CameraRecordScreen(initialMode: CaptureMode, onSend: (String, CaptureMode) -
}
val idle = phase == CapturePhase.IDLE
var menu by remember(mode, lens?.cameraId) { mutableStateOf<CameraOption?>(null) }
LaunchedEffect(idle) { if (!idle) menu = null }
LaunchedEffect(menu) { LogManager.addLog("DEBUG", "Capture", "Toolbar menu=$menu mode=$mode camera=${lens?.cameraId}") }
Scaffold(topBar = {
TopAppBar(title = {
Row(Modifier.horizontalScroll(rememberScrollState()), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
@@ -282,15 +287,47 @@ fun CameraRecordScreen(initialMode: CaptureMode, onSend: (String, CaptureMode) -
horizontalAlignment = Alignment.CenterHorizontally) {
if (idle) {
Row(Modifier.fillMaxWidth().horizontalScroll(rememberScrollState()).padding(horizontal = 12.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)) {
lenses.forEach { item -> FilterChip(selected = lens == item, onClick = { lens = item }, label = { Text(item.label) }) }
}
Row(Modifier.fillMaxWidth().horizontalScroll(rememberScrollState()).padding(horizontal = 12.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)) {
if (mode == CaptureMode.PHOTO) resolutions.forEach { item ->
FilterChip(selected = resolution == item, onClick = { resolution = item }, label = { Text(item.label) })
} else CaptureQuality.values().forEach { item ->
FilterChip(selected = quality == item, onClick = { quality = item }, label = { Text(item.label) })
horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.CenterVertically) {
Box {
val name = lens?.let { "${it.label} ${it.mm}".trim() } ?: "—"
CaptureControlButton(stringResource(R.string.stream_camera, name), enabled = lenses.isNotEmpty(),
onClick = { menu = CameraOption.CAMERA }) {
val focal = lens?.eqFocal?.takeIf { it > 0 }?.let {
stringResource(R.string.stream_camera_focal_short, it.roundToInt())
} ?: "—"
CaptureValueIcon(CaptureIconShape.CAMERA, focal, front = lens?.type == LensType.SELFIE)
}
DropdownMenu(expanded = menu == CameraOption.CAMERA, onDismissRequest = { menu = null }) {
lenses.forEach { item ->
CaptureOptionItem("${item.label} ${item.mm}".trim(), lens == item, onClick = {
menu = null; lens = item
LogManager.addLog("INFO", "Capture", "Camera selected id=${item.cameraId} mode=$mode")
})
}
}
}
Box {
val label = if (mode == CaptureMode.PHOTO) resolution?.label ?: "—" else quality.label
CaptureControlButton(stringResource(R.string.stream_resolution, label),
enabled = mode == CaptureMode.VIDEO || resolutions.isNotEmpty(), onClick = { menu = CameraOption.RESOLUTION }) {
val value = if (mode == CaptureMode.PHOTO) resolution?.let { "${minOf(it.width, it.height)}p" } ?: "—"
else quality.label.substringBefore(' ')
CaptureValueIcon(CaptureIconShape.SCREEN, value,
detail = if (mode == CaptureMode.VIDEO) quality.label.substringAfter(' ') else null)
}
DropdownMenu(expanded = menu == CameraOption.RESOLUTION, onDismissRequest = { menu = null }) {
if (mode == CaptureMode.PHOTO) resolutions.forEach { item ->
CaptureOptionItem(item.label, resolution == item, onClick = {
menu = null; resolution = item
LogManager.addLog("INFO", "Capture", "Photo resolution selected ${item.label}")
})
} else CaptureQuality.values().forEach { item ->
CaptureOptionItem(item.label, quality == item, onClick = {
menu = null; quality = item
LogManager.addLog("INFO", "Capture", "Video quality selected ${item.label}")
})
}
}
}
}
}