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
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ private fun ContentScreen(
},
imageWell = { modifier ->
if (captureUiState.externalCaptureMode == ExternalCaptureMode.Standard) {
(captureUiState.imageWellUiState as? ImageWellUiState.LastCapture)?.let {
(captureUiState.imageWellUiState as? ImageWellUiState.Content)?.let {
ImageWell(
modifier = modifier,
imageWellUiState = it,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ class PreviewViewModel @Inject constructor(
*/
fun imageWellToRepository() {
(captureUiState.value as? CaptureUiState.Ready)
?.let { it.imageWellUiState as? ImageWellUiState.LastCapture }
?.let { it.imageWellUiState as? ImageWellUiState.Content }
?.let { postCurrentMediaToMediaRepository(it.mediaDescriptor) }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ import com.google.jetpackcamera.data.media.MediaDescriptor
import com.google.jetpackcamera.ui.uistate.capture.ImageWellUiState

/**
* A composable that displays the last captured image.
* A composable that displays thumbnail image that can be clicked to open the full media in
* post-capture
*
* @param imageWellUiState the [ImageWellUiState.LastCapture] for this component
* @param onClick the callback for when the image well is clicked
Expand All @@ -60,7 +61,7 @@ import com.google.jetpackcamera.ui.uistate.capture.ImageWellUiState
@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalAnimationApi::class)
@Composable
fun ImageWell(
imageWellUiState: ImageWellUiState.LastCapture,
imageWellUiState: ImageWellUiState.Content,
onClick: () -> Unit,
modifier: Modifier = Modifier,
shape: Shape = RoundedCornerShape(16.dp),
Expand Down Expand Up @@ -109,7 +110,7 @@ private fun ImageWellPreview() {
uri = Uri.EMPTY,
thumbnail = previewBitmap
)
val imageWellUiState = ImageWellUiState.LastCapture(
val imageWellUiState = ImageWellUiState.Content(
mediaDescriptor = mediaDescriptor
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,7 @@ sealed interface ImageWellUiState {
*/
data object Unavailable : ImageWellUiState

/**
* The image well is displaying information about the last captured media.
*
* @param mediaDescriptor A [MediaDescriptor.Content] object that contains information about
* the last captured media, such as its URI and whether it is a video.
*/
data class LastCapture(val mediaDescriptor: MediaDescriptor.Content) : ImageWellUiState
data class Content(val mediaDescriptor: MediaDescriptor.Content) : ImageWellUiState

companion object
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ private val ORDERED_UI_SUPPORTED_ASPECT_RATIOS = listOf(
AspectRatio.ONE_ONE
)

/**
* Creates an [AspectRatioUiState] from [CameraAppSettings].
*
* @param cameraAppSettings The current camera application settings.
*
* @return An [AspectRatioUiState] representing the available aspect ratios and the currently
* selected one. If only one or no aspect ratios are supported, it returns
* [AspectRatioUiState.Unavailable].
*/
fun AspectRatioUiState.Companion.from(cameraAppSettings: CameraAppSettings): AspectRatioUiState {
val supportedAspectRatios = ORDERED_UI_SUPPORTED_ASPECT_RATIOS.toSet()
val availableAspectRatios =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ import com.google.jetpackcamera.core.camera.VideoRecordingState
import com.google.jetpackcamera.settings.model.CameraAppSettings
import com.google.jetpackcamera.ui.uistate.capture.AudioUiState

/**
* Creates an [AudioUiState] from the given camera application settings.
*
* @param cameraAppSettings The current settings of the camera application.
* @param cameraState The current state of the camera, used to get the audio amplitude.
* @return [AudioUiState.Enabled.On] if audio is enabled, containing the current amplitude,
* or [AudioUiState.Enabled.Mute] if audio is disabled.
*/
fun AudioUiState.Companion.from(
cameraAppSettings: CameraAppSettings,
cameraState: CameraState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,21 @@ import com.google.jetpackcamera.core.camera.VideoRecordingState
import com.google.jetpackcamera.settings.model.CameraAppSettings
import com.google.jetpackcamera.ui.uistate.capture.CaptureButtonUiState

/**
* Creates a [CaptureButtonUiState] based on the current camera settings and state.
*
* This function determines the UI state for the capture button based on the capture mode, video
* recording status, and whether the recording has been locked.
*
* @param cameraAppSettings The current application settings, used to determine the capture mode.
* @param cameraState The current state of the camera, used to check video recording status.
* @param lockedState A boolean indicating whether the video recording is currently in a locked state.
*
* @return A [CaptureButtonUiState] representing the current state of the capture button.
* - [CaptureButtonUiState.Enabled.Idle] if not recording.
* - [CaptureButtonUiState.Enabled.Recording.PressedRecording] if recording is active but not locked.
* - [CaptureButtonUiState.Enabled.Recording.LockedRecording] if recording is active and locked.
*/
fun CaptureButtonUiState.Companion.from(
cameraAppSettings: CameraAppSettings,
cameraState: CameraState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@ private val ORDERED_UI_SUPPORTED_CAPTURE_MODES = listOf(
CaptureMode.VIDEO_ONLY
)

/**
* Creates a [CaptureModeToggleUiState] based on the current camera and system state.
*
* This adapter determines whether the simplified capture mode toggle (between IMAGE_ONLY and
* VIDEO_ONLY) should be available and what its state should be. The toggle is generally
* unavailable if video is recording or if the current capture mode is STANDARD.
*
* @param systemConstraints The constraints of the entire camera system.
* @param cameraAppSettings The current settings of the camera.
* @param cameraState The real-time state of the camera hardware.
* @param externalCaptureMode The mode influencing UI based on how the camera was launched.
* @return A [CaptureModeToggleUiState] which is either [CaptureModeToggleUiState.Available]
* containing the states for the image and video-only modes, or
* [CaptureModeToggleUiState.Unavailable] if the toggle should not be shown.
*/
fun CaptureModeToggleUiState.Companion.from(
systemConstraints: CameraSystemConstraints,
cameraAppSettings: CameraAppSettings,
Expand Down Expand Up @@ -75,6 +90,19 @@ fun CaptureModeToggleUiState.Companion.from(
)
}

/**
* Creates a [CaptureModeUiState] for the full capture mode selection UI (e.g., in quick settings).
*
* This adapter is responsible for determining the list of all available and selectable capture
* modes ([CaptureMode.STANDARD], [CaptureMode.IMAGE_ONLY], [CaptureMode.VIDEO_ONLY]) based on the
* current system and camera constraints.
*
* @param systemConstraints The constraints of the entire camera system.
* @param cameraAppSettings The current settings of the camera.
* @param externalCaptureMode The mode influencing UI based on how the camera was launched.
* @return A [CaptureModeUiState.Available] object containing the currently selected capture mode
* and a list of all available modes, each represented as a [SingleSelectableUiState].
*/
fun CaptureModeUiState.Companion.from(
systemConstraints: CameraSystemConstraints,
cameraAppSettings: CameraAppSettings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,28 @@ import com.google.jetpackcamera.ui.uistate.capture.CaptureModeUiState
import com.google.jetpackcamera.ui.uistate.capture.ConcurrentCameraUiState
import com.google.jetpackcamera.ui.uistate.capture.StreamConfigUiState

/**
* Creates a [ConcurrentCameraUiState] based on the current camera and system state.
*
* This function determines the availability and current selection of the concurrent camera feature.
* It synthesizes various states and settings to decide if the concurrent camera mode can be
* enabled. The feature is considered disabled if any of the following conditions are true:
* - The device hardware does not support concurrent cameras.
* - The camera was launched with an external intent for single image capture.
* - The selected capture mode is exclusively for single image capture (`IMAGE_ONLY`).
* - An HDR mode (either HLG10 for video or ULTRA_HDR for images) is active.
* - The stream configuration is set to `SINGLE_STREAM`.
* - Low Light Boost flash mode is active.
*
* @param cameraAppSettings The current application-level camera settings.
* @param systemConstraints The capabilities and limitations of the device's camera hardware.
* @param externalCaptureMode The mode indicating if the camera was launched by an external intent.
* @param captureModeUiState The current state of the capture mode selection UI.
* @param streamConfigUiState The current state of the stream configuration UI.
* @return A [ConcurrentCameraUiState.Available] object containing the currently selected
* concurrent camera mode and a boolean indicating if the feature is currently enabled and
* can be interacted with.
*/
fun ConcurrentCameraUiState.Companion.from(
cameraAppSettings: CameraAppSettings,
systemConstraints: CameraSystemConstraints,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,6 @@ fun debugUiState(
/**
* Constructs a [DebugUiState] based on the current camera and application state.
*
* This is a private factory function that determines whether the debug UI should be fully
* enabled and open, enabled but closed, or completely disabled. It gathers and transforms
* the necessary data for the UI.
*
* @param systemConstraints The system-level constraints for the current camera.
* @param cameraAppSettings The current application-level camera settings.
* @param cameraState The real-time state of the camera.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ import com.google.jetpackcamera.core.camera.CameraState
import com.google.jetpackcamera.core.camera.VideoRecordingState
import com.google.jetpackcamera.ui.uistate.capture.ElapsedTimeUiState

/**
* Creates an [ElapsedTimeUiState] based on the current [CameraState].
*
* This function translates the [VideoRecordingState] from the core camera layer into a UI-specific
* state for displaying the elapsed time of a video recording. It handles different recording
* phases: active recording, the final time after recording stops, and the initial state when
* a recording is starting.
*
* @param cameraState The real-time state from the camera, which includes the video recording status.
*
* @return An [ElapsedTimeUiState.Enabled] state containing the elapsed time in nanoseconds.
* - For [VideoRecordingState.Active], it provides the ongoing elapsed time.
* - For [VideoRecordingState.Inactive], it provides the final duration of the last recording.
* - For [VideoRecordingState.Starting], it provides an initial value of 0.
*/
fun ElapsedTimeUiState.Companion.from(cameraState: CameraState): ElapsedTimeUiState {
val videoRecordingState = cameraState.videoRecordingState
return when (videoRecordingState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ private val ORDERED_UI_SUPPORTED_FLASH_MODES = listOf(
FlashMode.LOW_LIGHT_BOOST
)

/**
* Creates the initial [FlashModeUiState] from the given camera settings and system constraints.
*
* This factory function determines the set of available flash modes based on hardware support
* and current camera settings (like HDR or concurrent mode). If only [FlashMode.OFF] is available,
* or no modes are supported, it returns [FlashModeUiState.Unavailable].
*
* @param cameraAppSettings The current settings of the camera, used to determine which flash modes
* might be disabled due to other active settings (e.g., HDR).
* @param systemConstraints The hardware capabilities of the camera system, used to get the list
* of supported flash modes for the current lens.
* @return A [FlashModeUiState] which is either [Available] if multiple flash modes can be shown,
* or [Unavailable] if the flash controls should be hidden.
*/
fun FlashModeUiState.Companion.from(
cameraAppSettings: CameraAppSettings,
systemConstraints: CameraSystemConstraints
Expand Down Expand Up @@ -81,6 +95,20 @@ fun FlashModeUiState.Companion.from(
}
}

/**
* Updates an existing [FlashModeUiState] based on new camera settings and state.
*
* This function efficiently updates the flash UI state without recreating it from scratch if
* possible. It checks for changes in supported modes, selected mode, and the real-time status
* of Low Light Boost.
*
* @param cameraAppSettings The current application settings for the camera.
* @param systemConstraints The hardware capabilities of the camera system.
* @param cameraState The real-time state from the camera, used to check [LowLightBoostState].
* @return An updated [FlashModeUiState]. This may be the same instance if no relevant
* state has changed, a copied instance with minor updates, or a completely new instance if
* supported flash modes have changed.
*/
fun FlashModeUiState.updateFrom(
cameraAppSettings: CameraAppSettings,
systemConstraints: CameraSystemConstraints,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ private val ORDERED_UI_SUPPORTED_LENS_FACINGS = listOf(

)

/**
* Creates a [FlipLensUiState] based on the current camera settings and system constraints.
*
* This function determines the UI state for the lens flipping control (e.g., front/back camera
* button). It gathers the list of all physically available lenses from the system constraints
* and combines it with the currently selected lens from the application settings.
*
* @param cameraAppSettings The current application settings, used to determine the currently
* selected [LensFacing].
* @param systemConstraints The hardware capabilities of the camera system, used to get the list
* of all available lenses on the device.
* @return A [FlipLensUiState.Available] object containing the currently selected lens and a list
* of all available lenses for the UI to display.
*/
fun FlipLensUiState.Companion.from(
cameraAppSettings: CameraAppSettings,
systemConstraints: CameraSystemConstraints
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ import com.google.jetpackcamera.core.camera.CameraState
import com.google.jetpackcamera.core.camera.FocusState
import com.google.jetpackcamera.ui.uistate.capture.FocusMeteringUiState

/**
* Updates an existing [FocusMeteringUiState] based on a new [CameraState].
*
* This factory function translates the [FocusState] into its corresponding UI representation.
*
* @param cameraState The new, real-time state from the camera.
* @return The existing [FocusMeteringUiState] instance if no change is detected, or a new
* [FocusMeteringUiState] reflecting the updated camera focus state.
*/
fun FocusMeteringUiState.updateFrom(cameraState: CameraState): FocusMeteringUiState {
val focusState = cameraState.focusState
return when (this) {
Expand All @@ -45,6 +54,17 @@ fun FocusMeteringUiState.updateFrom(cameraState: CameraState): FocusMeteringUiSt
}
}

/**
* Creates a [FocusMeteringUiState] from the given [CameraState].
*
* This factory function translates the low-level [FocusState] from the core camera layer into its
* corresponding UI representation. It maps the coordinates and status (e.g., RUNNING, SUCCESS)
* to the appropriate [FocusMeteringUiState] subtype, which can be either [FocusMeteringUiState.Unspecified]
* or [FocusMeteringUiState.Specified].
*
* @param cameraState The real-time state from the camera containing the focus information.
* @return A [FocusMeteringUiState] that represents the current focus state for the UI.
*/
fun FocusMeteringUiState.Companion.from(cameraState: CameraState): FocusMeteringUiState {
return when (val focusState = cameraState.focusState) {
is FocusState.Unspecified -> FocusMeteringUiState.Unspecified
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,30 @@ import com.google.jetpackcamera.settings.model.CameraSystemConstraints
import com.google.jetpackcamera.settings.model.forCurrentLens
import com.google.jetpackcamera.ui.uistate.capture.HdrUiState

/**
* Creates an [HdrUiState] based on the current camera settings, system constraints, and capture mode.
*
* This function determines whether the High Dynamic Range (HDR) feature is available for the user
* to interact with. The availability depends on a combination of hardware support for specific
* HDR formats ([DynamicRange.HLG10] for video, [ImageOutputFormat.JPEG_ULTRA_HDR] for images) and
* various other settings that may conflict with HDR, such as flash mode or concurrent camera mode.
*
* The logic is tailored to the [ExternalCaptureMode]:
* - **ImageCapture / MultipleImageCapture**: Checks for `JPEG_ULTRA_HDR` support.
* - **VideoCapture**: Checks for `HLG10` dynamic range support.
* - **Standard**: Checks for support for either `HLG10` or `JPEG_ULTRA_HDR`.
*
* In all cases, HDR is disabled if `LOW_LIGHT_BOOST` flash mode is active. For video and standard
* modes, it is also disabled if concurrent camera mode is active.
*
* @param cameraAppSettings The current application and camera settings.
* @param systemConstraints The capabilities and limitations of the device's camera hardware.
* @param externalCaptureMode The mode indicating how the camera was launched (e.g., via an
* external intent), which influences which HDR formats are relevant.
*
* @return [HdrUiState.Available] if the feature is supported and not blocked by other settings,
* otherwise returns [HdrUiState.Unavailable].
*/
fun HdrUiState.Companion.from(
cameraAppSettings: CameraAppSettings,
systemConstraints: CameraSystemConstraints,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ import com.google.jetpackcamera.core.camera.VideoRecordingState
import com.google.jetpackcamera.data.media.MediaDescriptor
import com.google.jetpackcamera.ui.uistate.capture.ImageWellUiState

/**
* Creates an [ImageWellUiState] for a given [MediaDescriptor] and [VideoRecordingState].
*
* This function determines the state of the image well, a component that displays the
* [MediaDescriptor]'s thumbnail. This state will be unavailable if any of the following are true:
* - mediaDescriptor is not MediaDescriptor.Content
* - mediaDescriptor does not have a thumbnail
*
* @param mediaDescriptor the media's correlating [MediaDescriptor]
* @param videoRecordingState The current state of video recording.
* @return [ImageWellUiState.Content] only if the mediaDescriptor is MediaDescriptor.Content,
* has a non-null thumbnail, and video recording state is inactive.
* otherwise return [ImageWellUiState.Unavailable]
*/
fun ImageWellUiState.Companion.from(
mediaDescriptor: MediaDescriptor,
videoRecordingState: VideoRecordingState
Expand All @@ -27,7 +41,7 @@ fun ImageWellUiState.Companion.from(
mediaDescriptor.thumbnail != null &&
videoRecordingState is VideoRecordingState.Inactive
) {
ImageWellUiState.LastCapture(mediaDescriptor = mediaDescriptor)
ImageWellUiState.Content(mediaDescriptor = mediaDescriptor)
} else {
ImageWellUiState.Unavailable
}
Expand Down

This file was deleted.

Loading
Loading