diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureButtonComponents.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureButtonComponents.kt index da3b27e55..1e3914842 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureButtonComponents.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureButtonComponents.kt @@ -155,6 +155,18 @@ private fun CaptureKeyHandler( } } +/** + * A capture button that can be used for both image and video capture. + * + * @param modifier the modifier for this component + * @param onImageCapture the callback for an image capture event + * @param onStartRecording the callback for a start recording event + * @param onStopRecording the callback for a stop recording event + * @param onLockVideoRecording The callback for a lock video recording event. The boolean parameter indicates if the recording should be locked. + * @param onIncrementZoom The callback for a zoom increment event, providing the zoom increment value. + * @param captureButtonUiState the [CaptureButtonUiState] for this component + * @param captureButtonSize the size of the capture button + */ @Composable internal fun CaptureButton( modifier: Modifier = Modifier, diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureLayout.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureLayout.kt index 72a0933d2..3084eec0c 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureLayout.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureLayout.kt @@ -41,7 +41,25 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -// these layouts are only concerned with placement. nothing else. no state handling +/** + * The base layout for the camera capture screen. + * + * @param modifier the modifier for this component + * @param viewfinder the viewfinder composable + * @param captureButton the capture button composable + * @param imageWell the image well composable + * @param flipCameraButton the flip camera button composable + * @param zoomLevelDisplay the zoom level display composable + * @param elapsedTimeDisplay the elapsed time display composable + * @param quickSettingsButton the quick settings button composable + * @param indicatorRow the indicator row composable + * @param captureModeToggle the capture mode toggle composable + * @param quickSettingsOverlay the quick settings overlay composable + * @param debugOverlay the debug overlay composable + * @param debugVisibilityWrapper A wrapper that conditionally hides its contents based on debug settings + * @param screenFlashOverlay the screen flash overlay composable + * @param snackBar the snack bar composable for showing messages + */ @Composable fun PreviewLayout( modifier: Modifier = Modifier, diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureScreenComponents.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureScreenComponents.kt index ef96e1174..3e3a803f1 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureScreenComponents.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/CaptureScreenComponents.kt @@ -134,6 +134,11 @@ private const val BLINK_TIME = 100L private val TAP_TO_FOCUS_INDICATOR_SIZE = 56.dp private const val FOCUS_INDICATOR_RESULT_DELAY = 100L +/** + * A composable that displays the elapsed time since the start of a video recording. + * + * @param elapsedTimeUiState the [ElapsedTimeUiState] for this component + */ @Composable fun ElapsedTimeText(modifier: Modifier = Modifier, elapsedTimeUiState: ElapsedTimeUiState) { if (elapsedTimeUiState is ElapsedTimeUiState.Enabled) { @@ -146,6 +151,14 @@ fun ElapsedTimeText(modifier: Modifier = Modifier, elapsedTimeUiState: ElapsedTi } } +/** + * A composable that displays a toggle button for pausing and resuming video recording. + * + * @param modifier the modifier for this component + * @param onSetPause the callback for setting the pause state + * @param size the size of the button + * @param currentRecordingState the current recording state + */ @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun PauseResumeToggleButton( @@ -177,6 +190,14 @@ fun PauseResumeToggleButton( } } +/** + * A composable that displays a toggle button for enabling and disabling audio. + * + * @param modifier the modifier for this component + * @param buttonSize the size of the button + * @param audioUiState the [AudioUiState] for this component + * @param onToggleAudio the callback for toggling audio + */ @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun AmplitudeToggleButton( @@ -235,6 +256,14 @@ fun AmplitudeToggleButton( } } +/** + * A composable that displays a toggle button for switching between image and video capture. + * + * @param uiState the [CaptureModeToggleUiState.Available] for this component + * @param onChangeCaptureMode the callback for changing the capture mode + * @param onToggleWhenDisabled the callback for when the toggle is disabled + * @param modifier the modifier for this component + */ @Composable fun CaptureModeToggleButton( uiState: CaptureModeToggleUiState.Available, @@ -304,6 +333,14 @@ fun CaptureModeToggleButton( ) } +/** + * A composable that displays a snackbar with a test tag. + * + * @param modifier the modifier for this component + * @param snackbarToShow the [SnackbarData] to show + * @param snackbarHostState the [SnackbarHostState] for this component + * @param onSnackbarResult the callback for the snackbar result + */ @Composable fun TestableSnackbar( modifier: Modifier = Modifier, @@ -510,6 +547,19 @@ fun PreviewDisplay( } } +/** + * A composable that displays the capture button. + * + * @param modifier the modifier for this component + * @param captureButtonUiState the [CaptureButtonUiState] for this component + * @param isQuickSettingsOpen true if the quick settings are open + * @param onToggleQuickSettings the callback for toggling the quick settings + * @param onIncrementZoom A callback to increment the zoom, providing the zoom increment value. + * @param onCaptureImage A callback to capture an image, providing the `ContentResolver` for saving. + * @param onStartVideoRecording The callback for starting a video recording. + * @param onStopVideoRecording The callback for stopping a video recording. + * @param onLockVideoRecording A callback to lock video recording. The boolean parameter indicates if the recording should be locked. + */ @Composable fun CaptureButton( modifier: Modifier = Modifier, @@ -548,6 +598,12 @@ fun CaptureButton( ) } +/** + * A composable that displays the stabilization icon. + * + * @param stabilizationUiState the [StabilizationUiState] for this component + * @param modifier the modifier for this component + */ @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun StabilizationIcon(stabilizationUiState: StabilizationUiState, modifier: Modifier = Modifier) { @@ -625,6 +681,12 @@ fun StabilizationIcon(stabilizationUiState: StabilizationUiState, modifier: Modi } } +/** + * A composable that displays the video quality icon. + * + * @param videoQuality the [VideoQuality] for this component + * @param modifier the modifier for this component + */ @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun VideoQualityIcon(videoQuality: VideoQuality, modifier: Modifier = Modifier) { @@ -671,6 +733,14 @@ fun VideoQualityIcon(videoQuality: VideoQuality, modifier: Modifier = Modifier) } } +/** + * A composable that displays the flip camera button. + * + * @param enabledCondition the enabled condition for this component + * @param flipLensUiState the [FlipLensUiState] for this component + * @param onClick the callback for when the button is clicked + * @param modifier the modifier for this component + */ @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun FlipCameraButton( diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/DebouncedOrientationFlow.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/DebouncedOrientationFlow.kt index e8555dd30..ffe34280c 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/DebouncedOrientationFlow.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/DebouncedOrientationFlow.kt @@ -31,6 +31,11 @@ import kotlinx.coroutines.flow.runningFold /** Orientation hysteresis amount used in rounding, in degrees. */ private const val ORIENTATION_HYSTERESIS = 5 +/** + * A flow that emits the device's orientation, debounced to avoid rapid changes. + * + * @param context the application context + */ fun debouncedOrientationFlow(context: Context) = callbackFlow { val orientationListener = object : OrientationEventListener(context) { override fun onOrientationChanged(orientation: Int) { diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/DisabledReason.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/DisabledReason.kt index dba0ee2a4..50c33e06b 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/DisabledReason.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/DisabledReason.kt @@ -17,6 +17,10 @@ package com.google.jetpackcamera.ui.components.capture import com.google.jetpackcamera.ui.uistate.DisableRationale +/** + * Represents reasons why a UI component or functionality might be disabled, providing a test tag + * and a string resource ID for user-facing explanation. + */ enum class DisabledReason( // 'override' is required override val testTag: String, diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/MultipleEventsCutter.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/EventDebouncer.kt similarity index 73% rename from ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/MultipleEventsCutter.kt rename to ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/EventDebouncer.kt index 93fea248b..54023d287 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/MultipleEventsCutter.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/EventDebouncer.kt @@ -16,14 +16,20 @@ package com.google.jetpackcamera.ui.components.capture /** - * A helper class that prevents multiple clicks. + * A helper class that debounces events, preventing multiple rapid-fire executions. */ -internal class MultipleEventsCutter { +internal class EventDebouncer { private val now: Long get() = System.currentTimeMillis() private var lastEventTimeMs: Long = 0 + /** + * Processes an event, executing it only if a specified duration has passed since the last + * event. This prevents multiple rapid-fire executions of the same event. + * + * @param event The lambda function representing the event to be executed. + */ fun processEvent(event: () -> Unit) { if (now - lastEventTimeMs >= DURATION_BETWEEN_CLICKS_MS) { event.invoke() diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ImageWell.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ImageWell.kt index 98e2e856c..ec4234c72 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ImageWell.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ImageWell.kt @@ -48,6 +48,15 @@ import androidx.core.graphics.createBitmap import com.google.jetpackcamera.data.media.MediaDescriptor import com.google.jetpackcamera.ui.uistate.capture.ImageWellUiState +/** + * A composable that displays the last captured image. + * + * @param imageWellUiState the [ImageWellUiState.LastCapture] for this component + * @param onClick the callback for when the image well is clicked + * @param modifier the modifier for this component + * @param shape the shape of the image well + * @param enabled true if the image well is enabled + */ @OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalAnimationApi::class) @Composable fun ImageWell( diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ScreenFlashComponents.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ScreenFlashComponents.kt index c4ceccd7d..52961063c 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ScreenFlashComponents.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ScreenFlashComponents.kt @@ -36,6 +36,12 @@ import com.google.jetpackcamera.ui.uistate.capture.ScreenFlashUiState private const val TAG = "ScreenFlashComponents" +/** + * A composable that manages the screen flash UI and brightness. + * + * @param screenFlashUiState The [ScreenFlashUiState] that controls the screen flash behavior. + * @param onInitialBrightnessCalculated Callback to provide the initial screen brightness when it's first calculated. + */ @Composable fun ScreenFlashScreen( screenFlashUiState: ScreenFlashUiState, @@ -55,6 +61,12 @@ fun ScreenFlashScreen( } } +/** + * A composable that displays a white overlay to simulate a screen flash. + * + * @param screenFlashUiState The [ScreenFlashUiState] that controls the overlay's visibility and behavior. + * @param modifier The modifier for this composable. + */ @Composable private fun ScreenFlashOverlay( screenFlashUiState: ScreenFlashUiState, diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ZoomBarComponents.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ZoomBarComponents.kt index f1b6b7ab8..781957a10 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ZoomBarComponents.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ZoomBarComponents.kt @@ -51,6 +51,15 @@ import com.google.jetpackcamera.ui.uistate.capture.ZoomControlUiState import java.math.RoundingMode import java.text.DecimalFormat +/** + * A composable that displays a row of zoom buttons. + * + * @param onChangeZoom the callback for when the zoom changes + * @param modifier the modifier for this component + * @param zoomControlUiState the [ZoomControlUiState] for this component + * @param buttonSize the size of the buttons + * @param spacing the spacing between the buttons + */ @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun ZoomButtonRow( diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ZoomState.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ZoomState.kt index 38cb3380a..a9640fa26 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ZoomState.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/ZoomState.kt @@ -69,23 +69,31 @@ class ZoomState( } /** - * Scale the current zoom level. + * Scales the current zoom level by the given [scalingFactor]. + * + * @param scalingFactor The factor by which to scale the current zoom level. + * @param lensToZoom Specifies which lens's zoom to modify (primary or secondary). */ suspend fun scaleZoom(scalingFactor: Float, lensToZoom: LensToZoom) { absoluteZoom(scalingFactor * functionalZoom, lensToZoom) } /** - * Increment the current zoom level. + * Increments the current zoom level by the given [increment]. + * + * @param increment The amount to increment the current zoom level by. + * @param lensToZoom Specifies which lens's zoom to modify (primary or secondary). */ suspend fun incrementZoom(increment: Float, lensToZoom: LensToZoom) { absoluteZoom(increment + functionalZoom, lensToZoom) } /** - * Ease towards a specific zoom level + * Animates the zoom level to the specified [targetZoomLevel]. * - * @param animationSpec [androidx.compose.animation.core.AnimationSpec] used for the animation, default to tween over 500ms + * @param targetZoomLevel The target zoom level to animate to. + * @param animationSpec The [AnimationSpec] to use for the animation. + * @param lensToZoom Specifies which lens's zoom to modify (primary or secondary). */ suspend fun animatedZoom( targetZoomLevel: Float, @@ -113,6 +121,12 @@ class ZoomState( } } + /** + * Updates the zoom state when the camera lens changes. + * + * @param newInitialZoomLevel The new initial zoom level. + * @param newZoomRange The new zoom range. + */ suspend fun onChangeLens(newInitialZoomLevel: Float, newZoomRange: Range) { mutatorMutex.mutate(MutatePriority.PreventUserInput) { functionalZoom = newInitialZoomLevel diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/quicksettings/ui/QuickSettingsComponents.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/quicksettings/ui/QuickSettingsComponents.kt index aa03ac926..77b625933 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/quicksettings/ui/QuickSettingsComponents.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/quicksettings/ui/QuickSettingsComponents.kt @@ -530,6 +530,15 @@ private fun QuickSettingToggleButton( ) } +/** + * A modal bottom sheet composable used to display a collection of quick setting buttons. + * + * @param modifier The [Modifier] to be applied to this composable. + * @param onDismiss The lambda function to be invoked when the bottom sheet is dismissed. + * @param sheetState The [SheetState] controlling the visibility and behavior of the bottom sheet. + * @param quickSettingButtons A variable number of composable functions that represent the buttons + * to be displayed within the quick settings bottom sheet. + */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun QuickSettingsBottomSheet( @@ -684,11 +693,17 @@ private fun QuickSettingsBottomSheetRow( } /** - * @param isHighlighted true if the button is currently checked; false otherwise. - * @param onClick will be called when the user clicks the button. - * @param text The text label to display below the icon. - * @param painter The icon to display inside the button. - * @param modifier The Modifier to be applied to the button. + * A customizable toggle button used within the quick settings menu. This button displays an icon + * and a text label, and can be highlighted to indicate a selected state. It serves as a generic + * component for various quick settings options. + * + * @param onClick The lambda function to be invoked when the button is clicked. + * @param text The text label displayed below the icon. + * @param accessibilityText The content description for accessibility purposes. + * @param painter The [Painter] for the icon displayed inside the button. + * @param modifier The [Modifier] to be applied to this composable. + * @param isHighlighted A boolean indicating whether the button is currently in a highlighted (selected) state. + * @param enabled A boolean indicating whether the button is interactive. */ @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable diff --git a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/theme/Theme.kt b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/theme/Theme.kt index 29efaecf2..d64b02b0d 100644 --- a/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/theme/Theme.kt +++ b/ui/components/capture/src/main/java/com/google/jetpackcamera/ui/components/capture/theme/Theme.kt @@ -25,6 +25,15 @@ import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext +/** + * A composable that provides a Material Design theme for previews within the Jetpack Camera App. + * + * This theme adapts to system dark mode settings and supports dynamic colors on Android 12+. + * + * @param darkTheme Whether the theme should be in dark mode. Defaults to `isSystemInDarkTheme()`. + * @param dynamicColor Whether dynamic color should be enabled. Defaults to `true`. + * @param content The composable content to which the theme will be applied. + */ @Composable fun PreviewPreviewTheme( darkTheme: Boolean = isSystemInDarkTheme(),