Switch camera menus in one tap and toggle the current menu
This commit is contained in:
1 parent
217a4bb27b
commit
067a6bd801
1 file changed
+23
-11
+23
-11
@@ -17,6 +17,7 @@ import androidx.camera.lifecycle.ProcessCameraProvider
|
||||
import androidx.camera.video.*
|
||||
import androidx.camera.view.PreviewView
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.detectTapGestures
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
@@ -30,6 +31,7 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
@@ -39,6 +41,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.compose.ui.window.PopupProperties
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.utun.chat.R
|
||||
import com.utun.chat.data.*
|
||||
@@ -326,9 +329,12 @@ fun CameraRecordScreen(initialMode: CaptureMode, onSend: (String, CaptureMode) -
|
||||
|
||||
val idle = phase == CapturePhase.IDLE
|
||||
var menu by remember(mode, lens?.cameraId) { mutableStateOf<CameraOption?>(null) }
|
||||
// Кнопки сами переключают меню; фон и Back закрывают его без перехвата нажатий на соседние кнопки.
|
||||
val menuProperties = remember { PopupProperties(focusable = false, dismissOnClickOutside = false) }
|
||||
BackHandler(menu != null) { menu = null }
|
||||
LaunchedEffect(idle) { if (!idle) menu = null }
|
||||
LaunchedEffect(menu) { LogManager.addLog("DEBUG", "Capture", "Toolbar menu=$menu mode=$mode camera=${lens?.cameraId}") }
|
||||
Scaffold(topBar = {
|
||||
Scaffold(modifier = Modifier.pointerInput(menu) { if (menu != null) detectTapGestures { menu = null } }, topBar = {
|
||||
TopAppBar(title = {
|
||||
Row(Modifier.horizontalScroll(rememberScrollState()), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
CaptureMode.values().forEach { item ->
|
||||
@@ -360,13 +366,14 @@ fun CameraRecordScreen(initialMode: CaptureMode, onSend: (String, CaptureMode) -
|
||||
Box {
|
||||
val name = lens?.let { "${it.label} ${it.mm}".trim() } ?: "—"
|
||||
CaptureControlButton(stringResource(R.string.stream_camera, name), enabled = lenses.isNotEmpty(),
|
||||
onClick = { menu = CameraOption.CAMERA }) {
|
||||
onClick = { menu = if (menu == CameraOption.CAMERA) null else 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 }) {
|
||||
DropdownMenu(expanded = menu == CameraOption.CAMERA, properties = menuProperties,
|
||||
onDismissRequest = { if (menu == CameraOption.CAMERA) menu = null }) {
|
||||
CaptureMenuHeader(stringResource(R.string.camera))
|
||||
lenses.forEach { item ->
|
||||
CaptureOptionItem("${item.label} ${item.mm}".trim(), lens == item, onClick = {
|
||||
@@ -379,10 +386,12 @@ fun CameraRecordScreen(initialMode: CaptureMode, onSend: (String, CaptureMode) -
|
||||
Box {
|
||||
if (mode == CaptureMode.VIDEO) {
|
||||
CaptureControlButton(stringResource(R.string.stream_video_codec, codec.label),
|
||||
enabled = !videoOptions.isNullOrEmpty(), onClick = { menu = CameraOption.CODEC }) {
|
||||
enabled = !videoOptions.isNullOrEmpty(),
|
||||
onClick = { menu = if (menu == CameraOption.CODEC) null else CameraOption.CODEC }) {
|
||||
CaptureValueIcon(CaptureIconShape.CHIP, codec.name)
|
||||
}
|
||||
DropdownMenu(expanded = menu == CameraOption.CODEC, onDismissRequest = { menu = null }) {
|
||||
DropdownMenu(expanded = menu == CameraOption.CODEC, properties = menuProperties,
|
||||
onDismissRequest = { if (menu == CameraOption.CODEC) menu = null }) {
|
||||
CaptureMenuHeader(stringResource(R.string.call_video_codec))
|
||||
videoOptions?.forEach { (item, supported) ->
|
||||
CaptureOptionItem(item.label, codec == item, onClick = {
|
||||
@@ -401,12 +410,13 @@ fun CameraRecordScreen(initialMode: CaptureMode, onSend: (String, CaptureMode) -
|
||||
val label = if (mode == CaptureMode.PHOTO) resolution?.label ?: "—" else quality.label
|
||||
CaptureControlButton(stringResource(R.string.stream_resolution, label),
|
||||
enabled = if (mode == CaptureMode.PHOTO) resolutions.isNotEmpty() else !videoOptions?.get(codec).isNullOrEmpty(),
|
||||
onClick = { menu = CameraOption.RESOLUTION }) {
|
||||
onClick = { menu = if (menu == CameraOption.RESOLUTION) null else CameraOption.RESOLUTION }) {
|
||||
val value = if (mode == CaptureMode.PHOTO) resolution?.let { "${minOf(it.width, it.height)}p" } ?: "—"
|
||||
else quality.label
|
||||
CaptureValueIcon(CaptureIconShape.SCREEN, value)
|
||||
}
|
||||
DropdownMenu(expanded = menu == CameraOption.RESOLUTION, onDismissRequest = { menu = null }) {
|
||||
DropdownMenu(expanded = menu == CameraOption.RESOLUTION, properties = menuProperties,
|
||||
onDismissRequest = { if (menu == CameraOption.RESOLUTION) menu = null }) {
|
||||
CaptureMenuHeader(stringResource(R.string.call_video_resolution))
|
||||
if (mode == CaptureMode.PHOTO) resolutions.forEach { item ->
|
||||
CaptureOptionItem(item.label, resolution == item, onClick = {
|
||||
@@ -425,10 +435,11 @@ fun CameraRecordScreen(initialMode: CaptureMode, onSend: (String, CaptureMode) -
|
||||
if (mode == CaptureMode.VIDEO) {
|
||||
val description = stringResource(R.string.stream_bitrate_value, bitrate / 1_000_000.0)
|
||||
CaptureControlButton(stringResource(R.string.stream_bitrate, description),
|
||||
onClick = { menu = CameraOption.BITRATE }) {
|
||||
onClick = { menu = if (menu == CameraOption.BITRATE) null else CameraOption.BITRATE }) {
|
||||
CaptureValueIcon(CaptureIconShape.GAUGE, captureBitrateLabel(bitrate))
|
||||
}
|
||||
DropdownMenu(expanded = menu == CameraOption.BITRATE, onDismissRequest = { menu = null }) {
|
||||
DropdownMenu(expanded = menu == CameraOption.BITRATE, properties = menuProperties,
|
||||
onDismissRequest = { if (menu == CameraOption.BITRATE) menu = null }) {
|
||||
CaptureMenuHeader(stringResource(R.string.capture_bitrate_title))
|
||||
VIDEO_BITRATES.forEach { item ->
|
||||
CaptureOptionItem(stringResource(R.string.stream_bitrate_value, item / 1_000_000.0), bitrate == item,
|
||||
@@ -440,10 +451,11 @@ fun CameraRecordScreen(initialMode: CaptureMode, onSend: (String, CaptureMode) -
|
||||
}
|
||||
} else {
|
||||
CaptureControlButton(stringResource(R.string.capture_jpeg_quality, jpegQuality),
|
||||
onClick = { menu = CameraOption.JPEG_QUALITY }) {
|
||||
onClick = { menu = if (menu == CameraOption.JPEG_QUALITY) null else CameraOption.JPEG_QUALITY }) {
|
||||
CaptureValueIcon(CaptureIconShape.GAUGE, jpegQuality.toString(), detail = "JPEG")
|
||||
}
|
||||
DropdownMenu(expanded = menu == CameraOption.JPEG_QUALITY, onDismissRequest = { menu = null }) {
|
||||
DropdownMenu(expanded = menu == CameraOption.JPEG_QUALITY, properties = menuProperties,
|
||||
onDismissRequest = { if (menu == CameraOption.JPEG_QUALITY) menu = null }) {
|
||||
CaptureMenuHeader(stringResource(R.string.capture_jpeg_quality_title))
|
||||
JPEG_QUALITIES.forEach { item ->
|
||||
CaptureOptionItem(item.toString(), jpegQuality == item, onClick = {
|
||||
|
||||
Reference in new issue
Block a user