Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: changes to capture button #302

Draft
wants to merge 6 commits into
base: kim/refactor/captureModes/captureMode_Ui
Choose a base branch
from
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -567,8 +567,12 @@ constructor(
if (constraints.supportedImageFormatsMap[streamConfig]
?.contains(ImageOutputFormat.JPEG_ULTRA_HDR) == true
) {
// if both image/video are supported, we don't need to change our current capture mode
this.captureMode
// if both image/video are supported, only change capture mode if default is the current
if (this.captureMode != CaptureMode.DEFAULT) {
this.captureMode
} else {
CaptureMode.VIDEO_ONLY
}
} else {
// if only video is supported, change to video only
CaptureMode.VIDEO_ONLY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,35 @@
*/
package com.google.jetpackcamera.settings.model

/**
* Class representing the app's configuration to capture an image
*/
enum class CaptureMode {

/**
* Both Image and Video use cases will be bound.
*
* Tap the Capture Button to take an image.
*
* Hold the Capture button to start recording, and release to complete the recording.
*/
DEFAULT,

/**
* Video use case will be bound. Image use case will not be bound.
*
* Tap the Capture Button to start recording.
* Hold the Capture button to start recording; releasing will not stop the recording.
*
* Tap the capture button again after recording has started to complete the recording.
*/
VIDEO_ONLY,

/**
* Image use case will be bound. Video use case will not be bound.
*
* Tap the Capture Button to capture an Image.
* Holding the Capture Button will do nothing. Subsequent release of the Capture button will also do nothing.
*/
IMAGE_ONLY
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.google.jetpackcamera.feature.preview.ui.HDR_IMAGE_UNSUPPORTED_ON_DEVI
import com.google.jetpackcamera.feature.preview.ui.HDR_IMAGE_UNSUPPORTED_ON_LENS_TAG
import com.google.jetpackcamera.feature.preview.ui.HDR_IMAGE_UNSUPPORTED_ON_MULTI_STREAM_TAG
import com.google.jetpackcamera.feature.preview.ui.HDR_IMAGE_UNSUPPORTED_ON_SINGLE_STREAM_TAG
import com.google.jetpackcamera.feature.preview.ui.HDR_SIMULTANEOUS_IMAGE_VIDEO_UNSUPPORTED_TAG
import com.google.jetpackcamera.feature.preview.ui.HDR_VIDEO_UNSUPPORTED_ON_DEVICE_TAG
import com.google.jetpackcamera.feature.preview.ui.HDR_VIDEO_UNSUPPORTED_ON_LENS_TAG
import com.google.jetpackcamera.feature.preview.ui.IMAGE_CAPTURE_EXTERNAL_UNSUPPORTED_TAG
Expand Down Expand Up @@ -73,6 +74,10 @@ enum class DisabledReason(val testTag: String, val reasonTextResId: Int) {
HDR_IMAGE_UNSUPPORTED_ON_MULTI_STREAM(
HDR_IMAGE_UNSUPPORTED_ON_MULTI_STREAM_TAG,
R.string.toast_hdr_photo_unsupported_on_lens_multi_stream
),
HDR_SIMULTANEOUS_IMAGE_VIDEO_UNSUPPORTED(
HDR_SIMULTANEOUS_IMAGE_VIDEO_UNSUPPORTED_TAG,
R.string.toast_hdr_simultaneous_image_video_unsupported
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.LifecycleStartEffect
import androidx.tracing.Trace
import com.google.jetpackcamera.core.camera.VideoRecordingState
import com.google.jetpackcamera.feature.preview.quicksettings.QuickSettingsScreenOverlay
import com.google.jetpackcamera.feature.preview.ui.CameraControlsOverlay
import com.google.jetpackcamera.feature.preview.ui.PreviewDisplay
Expand Down Expand Up @@ -145,7 +144,7 @@ fun PreviewScreen(
onSetCaptureMode = viewModel::setCaptureMode,
onChangeFlash = viewModel::setFlash,
onChangeAspectRatio = viewModel::setAspectRatio,
onChangeCaptureMode = viewModel::setCaptureMode,
onChangeCaptureMode = viewModel::setStreamConfig,
onChangeDynamicRange = viewModel::setDynamicRange,
onChangeConcurrentCameraMode = viewModel::setConcurrentCameraMode,
onChangeImageFormat = viewModel::setImageFormat,
Expand Down Expand Up @@ -347,7 +346,6 @@ private fun ContentScreen_WhileRecording() {

private val FAKE_PREVIEW_UI_STATE_READY = PreviewUiState.Ready(
currentCameraSettings = DEFAULT_CAMERA_APP_SETTINGS,
videoRecordingState = VideoRecordingState.Inactive(),
systemConstraints = TYPICAL_SYSTEM_CONSTRAINTS,
previewMode = PreviewMode.StandardMode {}
// captureModeToggleUiState = CaptureModeToggleUiState.Invisible
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.google.jetpackcamera.core.camera.VideoRecordingState
import com.google.jetpackcamera.feature.preview.ui.SnackbarData
import com.google.jetpackcamera.feature.preview.ui.ToastMessage
import com.google.jetpackcamera.settings.model.CameraAppSettings
import com.google.jetpackcamera.settings.model.CaptureMode
import com.google.jetpackcamera.settings.model.FlashMode
import com.google.jetpackcamera.settings.model.StabilizationMode
import com.google.jetpackcamera.settings.model.SystemConstraints
Expand Down Expand Up @@ -50,7 +51,8 @@ sealed interface PreviewUiState {
val debugUiState: DebugUiState = DebugUiState(),
val stabilizationUiState: StabilizationUiState = StabilizationUiState.Disabled,
val flashModeUiState: FlashModeUiState = FlashModeUiState.Unavailable,
val captureModeUiState: CaptureModeUiState = CaptureModeUiState.Unavailable
val captureModeUiState: CaptureModeUiState = CaptureModeUiState.Unavailable,
val captureButtonUiState: CaptureButtonUiState = CaptureButtonUiState.Unavailable
) : PreviewUiState
}

Expand All @@ -61,7 +63,20 @@ data class DebugUiState(
val isDebugMode: Boolean = false,
val isDebugOverlayOpen: Boolean = false
)

val DEFAULT_CAPTURE_BUTTON_UISTATE = CaptureButtonUiState.Enabled(
captureMode = CaptureMode.DEFAULT,
previewMode = PreviewMode.StandardMode {},
videoRecordingState = VideoRecordingState.Inactive()
)
sealed interface CaptureButtonUiState {

data object Unavailable : CaptureButtonUiState
data class Enabled(
val captureMode: CaptureMode,
val previewMode: PreviewMode,
val videoRecordingState: VideoRecordingState
) : CaptureButtonUiState
}
sealed interface StabilizationUiState {
data object Disabled : StabilizationUiState

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ class PreviewViewModel @AssistedInject constructor(
}.copy(
// Update or initialize PreviewUiState.Ready
previewMode = previewMode,
currentCameraSettings = cameraAppSettings,
currentCameraSettings = cameraAppSettings.applyPreviewMode(previewMode),
systemConstraints = systemConstraints,
zoomScale = cameraState.zoomScale,
videoRecordingState = cameraState.videoRecordingState,
Expand All @@ -211,6 +211,10 @@ class PreviewViewModel @AssistedInject constructor(
captureModeUiState = getCaptureModeUiState(
systemConstraints,
cameraAppSettings
),
captureButtonUiState = getCaptureButtonUiState(
cameraAppSettings,
cameraState
)
// TODO(kc): set elapsed time UI state once VideoRecordingState
// refactor is complete.
Expand Down Expand Up @@ -364,6 +368,8 @@ class PreviewViewModel @AssistedInject constructor(
systemConstraints: SystemConstraints,
cameraAppSettings: CameraAppSettings
): CaptureModeUiState {
Log.d(TAG, "new capture mode state ${cameraAppSettings.captureMode}")

val cameraConstraints: CameraConstraints? = systemConstraints.forCurrentLens(
cameraAppSettings
)
Expand All @@ -386,6 +392,7 @@ class PreviewViewModel @AssistedInject constructor(
}
val supportedCaptureModes = getSupportedCaptureModes(
cameraAppSettings,
isHdrOn,
currentHdrDynamicRangeSupported,
currentHdrImageFormatSupported
)
Expand Down Expand Up @@ -421,7 +428,7 @@ class PreviewViewModel @AssistedInject constructor(
videoCaptureState = SingleSelectableState.Disabled(disabledReason = disabledReason)
defaultCaptureState =
SingleSelectableState.Disabled(disabledReason = disabledReason)
} else {
} else if (!supportedCaptureModes.contains(CaptureMode.IMAGE_ONLY)) {
val disabledReason =
getCaptureModeDisabledReason(
disabledCaptureMode = CaptureMode.IMAGE_ONLY,
Expand All @@ -437,6 +444,13 @@ class PreviewViewModel @AssistedInject constructor(
imageCaptureState = SingleSelectableState.Disabled(disabledReason = disabledReason)
defaultCaptureState =
SingleSelectableState.Disabled(disabledReason = disabledReason)
} else {
videoCaptureState = SingleSelectableState.Selectable
imageCaptureState = SingleSelectableState.Selectable
defaultCaptureState =
SingleSelectableState.Disabled(
disabledReason = DisabledReason.HDR_SIMULTANEOUS_IMAGE_VIDEO_UNSUPPORTED
)
}
return CaptureModeUiState.Enabled(
currentSelection = cameraAppSettings.captureMode,
Expand All @@ -449,6 +463,7 @@ class PreviewViewModel @AssistedInject constructor(

private fun getSupportedCaptureModes(
cameraAppSettings: CameraAppSettings,
isHdrOn: Boolean,
currentHdrDynamicRangeSupported: Boolean,
currentHdrImageFormatSupported: Boolean
): List<CaptureMode> = if (
Expand All @@ -458,7 +473,12 @@ class PreviewViewModel @AssistedInject constructor(
currentHdrImageFormatSupported &&
cameraAppSettings.concurrentCameraMode == ConcurrentCameraMode.OFF
) {
listOf(CaptureMode.DEFAULT, CaptureMode.IMAGE_ONLY, CaptureMode.VIDEO_ONLY)
// do not allow both use cases to be bound if hdr is on
if (isHdrOn) {
listOf(CaptureMode.IMAGE_ONLY, CaptureMode.VIDEO_ONLY)
} else {
listOf(CaptureMode.DEFAULT, CaptureMode.IMAGE_ONLY, CaptureMode.VIDEO_ONLY)
}
} else if (
cameraAppSettings.concurrentCameraMode == ConcurrentCameraMode.OFF &&
previewMode is PreviewMode.ExternalImageCaptureMode ||
Expand Down Expand Up @@ -541,6 +561,14 @@ class PreviewViewModel @AssistedInject constructor(
}
}

fun getCaptureButtonUiState(
cameraAppSettings: CameraAppSettings,
cameraState: CameraState
): CaptureButtonUiState = CaptureButtonUiState.Enabled(
captureMode = cameraAppSettings.captureMode,
previewMode = previewMode,
videoRecordingState = cameraState.videoRecordingState
)
/*
private fun getCaptureToggleUiState(
systemConstraints: SystemConstraints,
Expand Down Expand Up @@ -742,7 +770,7 @@ class PreviewViewModel @AssistedInject constructor(
}
}

fun setCaptureMode(streamConfig: StreamConfig) {
fun setStreamConfig(streamConfig: StreamConfig) {
viewModelScope.launch {
cameraUseCase.setStreamConfig(streamConfig)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.tooling.preview.Preview
import com.google.jetpackcamera.core.camera.VideoRecordingState
import com.google.jetpackcamera.feature.preview.CaptureButtonUiState
import com.google.jetpackcamera.feature.preview.DEFAULT_CAPTURE_BUTTON_UISTATE
import com.google.jetpackcamera.feature.preview.FlashModeUiState
import com.google.jetpackcamera.feature.preview.PreviewMode
import com.google.jetpackcamera.feature.preview.PreviewUiState
Expand All @@ -60,6 +62,7 @@ import com.google.jetpackcamera.feature.preview.quicksettings.ui.QuickSettingsGr
import com.google.jetpackcamera.settings.model.AspectRatio
import com.google.jetpackcamera.settings.model.CameraAppSettings
import com.google.jetpackcamera.settings.model.CameraConstraints
import com.google.jetpackcamera.settings.model.CaptureMode
import com.google.jetpackcamera.settings.model.ConcurrentCameraMode
import com.google.jetpackcamera.settings.model.DynamicRange
import com.google.jetpackcamera.settings.model.FlashMode
Expand Down Expand Up @@ -251,7 +254,7 @@ private fun ExpandedQuickSettingsUi(
selectedDynamicRange = currentCameraSettings.dynamicRange,
selectedImageOutputFormat = currentCameraSettings.imageFormat,
hdrDynamicRangeSupported =
cameraConstraints?.hdrDynamicRangeSupported() ?: false,
cameraConstraints?.hdrDynamicRangeSupported() == true,
previewMode = previewUiState.previewMode,
enabled = shouldEnable()
)
Expand Down Expand Up @@ -292,16 +295,13 @@ fun ExpandedQuickSettingsUiPreview() {
MaterialTheme {
ExpandedQuickSettingsUi(
previewUiState = PreviewUiState.Ready(
currentCameraSettings = CameraAppSettings(),
systemConstraints = TYPICAL_SYSTEM_CONSTRAINTS,
previewMode = PreviewMode.StandardMode {},
videoRecordingState = VideoRecordingState.Inactive(),
// captureModeToggleUiState = CaptureModeToggleUiState.Invisible,
flashModeUiState = FlashModeUiState.Available(
selectedFlashMode = FlashMode.OFF,
availableFlashModes = listOf(FlashMode.OFF, FlashMode.ON),
isActive = false
)
),
captureButtonUiState = DEFAULT_CAPTURE_BUTTON_UISTATE
),
currentCameraSettings = CameraAppSettings(),
onLensFaceClick = { },
Expand All @@ -323,11 +323,8 @@ fun ExpandedQuickSettingsUiPreview_WithHdr() {
MaterialTheme {
ExpandedQuickSettingsUi(
previewUiState = PreviewUiState.Ready(
currentCameraSettings = CameraAppSettings(),
systemConstraints = TYPICAL_SYSTEM_CONSTRAINTS,
previewMode = PreviewMode.StandardMode {},
// captureModeToggleUiState = CaptureModeToggleUiState.Invisible,
videoRecordingState = VideoRecordingState.Inactive()
captureButtonUiState = DEFAULT_CAPTURE_BUTTON_UISTATE
),
currentCameraSettings = CameraAppSettings(dynamicRange = DynamicRange.HLG10),
onLensFaceClick = { },
Expand All @@ -345,9 +342,7 @@ fun ExpandedQuickSettingsUiPreview_WithHdr() {

private val TYPICAL_SYSTEM_CONSTRAINTS_WITH_HDR =
TYPICAL_SYSTEM_CONSTRAINTS.copy(
perLensConstraints = TYPICAL_SYSTEM_CONSTRAINTS.perLensConstraints.entries.associate {
(lensFacing, constraints)
->
perLensConstraints = TYPICAL_SYSTEM_CONSTRAINTS.perLensConstraints.entries.associate { (lensFacing, constraints) ->
lensFacing to constraints.copy(
supportedDynamicRanges = setOf(DynamicRange.SDR, DynamicRange.HLG10)
)
Expand Down
Loading
Loading