summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimberly Crevecoeur <kcrevecoeur@google.com>2024-01-22 17:42:40 -0800
committerGitHub <noreply@github.com>2024-01-22 17:42:40 -0800
commit28ea0e1eb0fcb5c05e6c6ed604f7a97ec9b79ca4 (patch)
treea26f38e31efea7b804b6159e590503516f427e8e
parent42fad7995f353de3587ffe233b423fc54122a492 (diff)
downloadjetpack-camera-app-28ea0e1eb0fcb5c05e6c6ed604f7a97ec9b79ca4.tar.gz
Fix issue where UiAutomator cannot find components (#100)
* Fix issue where UiAutomator cannot find components * spotless
-rw-r--r--app/build.gradle.kts1
-rw-r--r--feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt374
-rw-r--r--feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/QuickSettingsScreen.kt7
3 files changed, 192 insertions, 190 deletions
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 274e616..1c27e4d 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -73,7 +73,6 @@ android {
}
dependencies {
- implementation("androidx.test.ext:junit-ktx:1.1.5")
// Compose
val composeBom = platform(libs.compose.bom)
implementation(composeBom)
diff --git a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt
index 5aeb5c0..d8d90b2 100644
--- a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt
+++ b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewScreen.kt
@@ -22,6 +22,7 @@ import android.util.Log
import androidx.camera.core.Preview.SurfaceProvider
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
@@ -128,217 +129,224 @@ fun PreviewScreen(
Text(text = stringResource(R.string.camera_not_ready), color = Color.White)
}
} else if (previewUiState.cameraState == CameraState.READY) {
- // display camera feed. this stays behind everything else
- PreviewDisplay(
- onFlipCamera = viewModel::flipCamera,
- onTapToFocus = viewModel::tapToFocus,
- onZoomChange = { zoomChange: Float ->
- viewModel.setZoomScale(zoomChange)
- zoomScaleShow = true
- zoomHandler.postDelayed({ zoomScaleShow = false }, ZOOM_SCALE_SHOW_TIMEOUT_MS)
- },
- aspectRatio = previewUiState.currentCameraSettings.aspectRatio,
- deferredSurfaceProvider = deferredSurfaceProvider
- )
-
- QuickSettingsScreenOverlay(
- modifier = Modifier,
- isOpen = previewUiState.quickSettingsIsOpen,
- toggleIsOpen = { viewModel.toggleQuickSettings() },
- currentCameraSettings = previewUiState.currentCameraSettings,
- onLensFaceClick = viewModel::flipCamera,
- onFlashModeClick = viewModel::setFlash,
- onAspectRatioClick = {
- viewModel.setAspectRatio(it)
+ Box(
+ modifier = Modifier.semantics {
+ testTagsAsResourceId = true
}
- // onTimerClick = {}/*TODO*/
- )
- // relative-grid style overlay on top of preview display
- Column(
- modifier = Modifier
- .semantics {
- testTagsAsResourceId = true
- }
- .fillMaxSize()
) {
- // hide settings, quickSettings, and quick capture mode button
- when (previewUiState.videoRecordingState) {
- VideoRecordingState.ACTIVE -> {}
- VideoRecordingState.INACTIVE -> {
- // 3-segmented row to keep quick settings button centered
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .height(IntrinsicSize.Min)
- ) {
- // row to left of quick settings button
+ // display camera feed. this stays behind everything else
+ PreviewDisplay(
+ onFlipCamera = viewModel::flipCamera,
+ onTapToFocus = viewModel::tapToFocus,
+ onZoomChange = { zoomChange: Float ->
+ viewModel.setZoomScale(zoomChange)
+ zoomScaleShow = true
+ zoomHandler.postDelayed({ zoomScaleShow = false }, ZOOM_SCALE_SHOW_TIMEOUT_MS)
+ },
+ aspectRatio = previewUiState.currentCameraSettings.aspectRatio,
+ deferredSurfaceProvider = deferredSurfaceProvider
+ )
+
+ QuickSettingsScreenOverlay(
+ modifier = Modifier,
+ isOpen = previewUiState.quickSettingsIsOpen,
+ toggleIsOpen = { viewModel.toggleQuickSettings() },
+ currentCameraSettings = previewUiState.currentCameraSettings,
+ onLensFaceClick = viewModel::flipCamera,
+ onFlashModeClick = viewModel::setFlash,
+ onAspectRatioClick = {
+ viewModel.setAspectRatio(it)
+ }
+ // onTimerClick = {}/*TODO*/
+ )
+ // relative-grid style overlay on top of preview display
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ ) {
+ // hide settings, quickSettings, and quick capture mode button
+ when (previewUiState.videoRecordingState) {
+ VideoRecordingState.ACTIVE -> {}
+ VideoRecordingState.INACTIVE -> {
+ // 3-segmented row to keep quick settings button centered
Row(
modifier = Modifier
- .weight(1f),
- horizontalArrangement = Arrangement.Start,
- verticalAlignment = Alignment.CenterVertically
+ .fillMaxWidth()
+ .height(IntrinsicSize.Min)
) {
- // button to open default settings page
- SettingsNavButton(
+ // row to left of quick settings button
+ Row(
modifier = Modifier
- .padding(12.dp),
- onNavigateToSettings = onNavigateToSettings
- )
- if (!previewUiState.quickSettingsIsOpen) {
- QuickSettingsIndicators(
- currentCameraSettings = previewUiState.currentCameraSettings,
- onFlashModeClick = viewModel::setFlash
+ .weight(1f),
+ horizontalArrangement = Arrangement.Start,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ // button to open default settings page
+ SettingsNavButton(
+ modifier = Modifier
+ .padding(12.dp),
+ onNavigateToSettings = onNavigateToSettings
)
+ if (!previewUiState.quickSettingsIsOpen) {
+ QuickSettingsIndicators(
+ currentCameraSettings = previewUiState
+ .currentCameraSettings,
+ onFlashModeClick = viewModel::setFlash
+ )
+ }
}
- }
- // quick settings button
- ToggleQuickSettingsButton(
- toggleDropDown = { viewModel.toggleQuickSettings() },
- isOpen = previewUiState.quickSettingsIsOpen
- )
+ // quick settings button
+ ToggleQuickSettingsButton(
+ toggleDropDown = { viewModel.toggleQuickSettings() },
+ isOpen = previewUiState.quickSettingsIsOpen
+ )
- // Row to right of quick settings
- Row(
- modifier = Modifier
- .weight(1f)
- .fillMaxHeight(),
- horizontalArrangement = Arrangement.Center,
- verticalAlignment = Alignment.CenterVertically
- ) {
- TestingButton(
+ // Row to right of quick settings
+ Row(
modifier = Modifier
- .testTag("ToggleCaptureMode"),
- onClick = { viewModel.toggleCaptureMode() },
- text = stringResource(
- when (previewUiState.currentCameraSettings.captureMode) {
- CaptureMode.SINGLE_STREAM ->
- R.string.capture_mode_single_stream
+ .weight(1f)
+ .fillMaxHeight(),
+ horizontalArrangement = Arrangement.Center,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ TestingButton(
+ modifier = Modifier
+ .testTag("ToggleCaptureMode"),
+ onClick = { viewModel.toggleCaptureMode() },
+ text = stringResource(
+ when (previewUiState.currentCameraSettings.captureMode) {
+ CaptureMode.SINGLE_STREAM ->
+ R.string.capture_mode_single_stream
- CaptureMode.MULTI_STREAM ->
- R.string.capture_mode_multi_stream
- }
+ CaptureMode.MULTI_STREAM ->
+ R.string.capture_mode_multi_stream
+ }
+ )
)
- )
+ }
}
}
}
- }
- // this component places a gap in the center of the column that will push out the top
- // and bottom edges. This will also allow the addition of vertical button bars on the
- // sides of the screen
- Row(
- modifier = Modifier
- .weight(1f)
- .fillMaxWidth()
- ) {}
+ // this component places a gap in the center of the column that will push out the top
+ // and bottom edges. This will also allow the addition of vertical button bars on the
+ // sides of the screen
+ Row(
+ modifier = Modifier
+ .weight(1f)
+ .fillMaxWidth()
+ ) {}
- if (zoomScaleShow) {
- ZoomScaleText(zoomScale = zoomScale)
- }
+ if (zoomScaleShow) {
+ ZoomScaleText(zoomScale = zoomScale)
+ }
- // 3-segmented row to keep capture button centered
- Row(
- modifier =
- Modifier
- .fillMaxWidth()
- .height(IntrinsicSize.Min)
- ) {
- when (previewUiState.videoRecordingState) {
- // hide first segment while recording in progress
- VideoRecordingState.ACTIVE -> {
- Spacer(
- modifier = Modifier
- .fillMaxHeight()
- .weight(1f)
- )
- }
- // show first segment when not recording
- VideoRecordingState.INACTIVE -> {
- Row(
- modifier = Modifier
- .weight(1f)
- .fillMaxHeight(),
- horizontalArrangement = Arrangement.Center,
- verticalAlignment = Alignment.CenterVertically
- ) {
- if (!previewUiState.quickSettingsIsOpen) {
- FlipCameraButton(
- onClick = { viewModel.flipCamera() },
- // enable only when phone has front and rear camera
- enabledCondition =
- previewUiState.currentCameraSettings.isBackCameraAvailable &&
- previewUiState.currentCameraSettings
- .isFrontCameraAvailable
- )
+ // 3-segmented row to keep capture button centered
+ Row(
+ modifier =
+ Modifier
+ .fillMaxWidth()
+ .height(IntrinsicSize.Min)
+ ) {
+ when (previewUiState.videoRecordingState) {
+ // hide first segment while recording in progress
+ VideoRecordingState.ACTIVE -> {
+ Spacer(
+ modifier = Modifier
+ .fillMaxHeight()
+ .weight(1f)
+ )
+ }
+ // show first segment when not recording
+ VideoRecordingState.INACTIVE -> {
+ Row(
+ modifier = Modifier
+ .weight(1f)
+ .fillMaxHeight(),
+ horizontalArrangement = Arrangement.Center,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ if (!previewUiState.quickSettingsIsOpen) {
+ FlipCameraButton(
+ onClick = { viewModel.flipCamera() },
+ // enable only when phone has front and rear camera
+ enabledCondition =
+ previewUiState
+ .currentCameraSettings
+ .isBackCameraAvailable &&
+ previewUiState
+ .currentCameraSettings
+ .isFrontCameraAvailable
+ )
+ }
}
}
}
- }
- val multipleEventsCutter = remember { MultipleEventsCutter() }
- val context = LocalContext.current
- CaptureButton(
- modifier = Modifier
- .testTag(CAPTURE_BUTTON),
- onClick = {
- multipleEventsCutter.processEvent {
- when (previewMode) {
- is PreviewMode.StandardMode -> {
- viewModel.captureImage()
- }
+ val multipleEventsCutter = remember { MultipleEventsCutter() }
+ val context = LocalContext.current
+ CaptureButton(
+ modifier = Modifier
+ .testTag(CAPTURE_BUTTON),
+ onClick = {
+ multipleEventsCutter.processEvent {
+ when (previewMode) {
+ is PreviewMode.StandardMode -> {
+ viewModel.captureImage()
+ }
- is PreviewMode.ExternalImageCaptureMode -> {
- viewModel.captureImage(
- context.contentResolver,
- previewMode.imageCaptureUri,
- previewMode.onImageCapture
- )
+ is PreviewMode.ExternalImageCaptureMode -> {
+ viewModel.captureImage(
+ context.contentResolver,
+ previewMode.imageCaptureUri,
+ previewMode.onImageCapture
+ )
+ }
}
}
- }
- if (previewUiState.quickSettingsIsOpen) {
- viewModel.toggleQuickSettings()
- }
- },
- onLongPress = {
- viewModel.startVideoRecording()
- if (previewUiState.quickSettingsIsOpen) {
- viewModel.toggleQuickSettings()
- }
- },
- onRelease = { viewModel.stopVideoRecording() },
- videoRecordingState = previewUiState.videoRecordingState
- )
- // You can replace this row so long as the weight of the component is 1f to
- // ensure the capture button remains centered.
- Row(
- modifier = Modifier
- .fillMaxHeight()
- .weight(1f)
- ) {
- /*TODO("Place other components here") */
+ if (previewUiState.quickSettingsIsOpen) {
+ viewModel.toggleQuickSettings()
+ }
+ },
+ onLongPress = {
+ viewModel.startVideoRecording()
+ if (previewUiState.quickSettingsIsOpen) {
+ viewModel.toggleQuickSettings()
+ }
+ },
+ onRelease = { viewModel.stopVideoRecording() },
+ videoRecordingState = previewUiState.videoRecordingState
+ )
+ // You can replace this row so long as the weight of the component is 1f to
+ // ensure the capture button remains centered.
+ Row(
+ modifier = Modifier
+ .fillMaxHeight()
+ .weight(1f)
+ ) {
+ /*TODO("Place other components here") */
+ }
}
}
- }
- // displays toast when there is a message to show
- if (previewUiState.toastMessageToShow != null) {
- ShowTestableToast(
- modifier = Modifier
- .testTag(previewUiState.toastMessageToShow!!.testTag),
- toastMessage = previewUiState.toastMessageToShow!!,
- onToastShown = viewModel::onToastShown
+ // displays toast when there is a message to show
+ if (previewUiState.toastMessageToShow != null) {
+ ShowTestableToast(
+ modifier = Modifier
+ .testTag(previewUiState.toastMessageToShow!!.testTag),
+ toastMessage = previewUiState.toastMessageToShow!!,
+ onToastShown = viewModel::onToastShown
+ )
+ }
+
+ // Screen flash overlay that stays on top of everything but invisible normally. This should
+ // not be enabled based on whether screen flash is enabled because a previous image capture
+ // may still be running after flash mode change and clear actions (e.g. brightness restore)
+ // may need to be handled later. Compose smart recomposition should be able to optimize this
+ // if the relevant states are no longer changing.
+ ScreenFlashScreen(
+ screenFlashUiState = screenFlashUiState,
+ onInitialBrightnessCalculated = viewModel.screenFlash::setClearUiScreenBrightness
)
}
-
- // Screen flash overlay that stays on top of everything but invisible normally. This should
- // not be enabled based on whether screen flash is enabled because a previous image capture
- // may still be running after flash mode change and clear actions (e.g. brightness restore)
- // may need to be handled later. Compose smart recomposition should be able to optimize this
- // if the relevant states are no longer changing.
- ScreenFlashScreen(
- screenFlashUiState = screenFlashUiState,
- onInitialBrightnessCalculated = viewModel.screenFlash::setClearUiScreenBrightness
- )
}
}
diff --git a/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/QuickSettingsScreen.kt b/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/QuickSettingsScreen.kt
index e6b2ff9..8a8a60f 100644
--- a/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/QuickSettingsScreen.kt
+++ b/feature/quicksettings/src/main/java/com/google/jetpackcamera/feature/quicksettings/QuickSettingsScreen.kt
@@ -36,8 +36,6 @@ import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.dimensionResource
-import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.semantics.testTagsAsResourceId
import com.google.jetpackcamera.feature.quicksettings.ui.ExpandedQuickSetRatio
import com.google.jetpackcamera.feature.quicksettings.ui.QuickFlipCamera
import com.google.jetpackcamera.feature.quicksettings.ui.QuickSetFlash
@@ -82,13 +80,10 @@ fun QuickSettingsScreenOverlay(
if (isOpen) {
Column(
modifier =
- Modifier
+ modifier
.fillMaxSize()
.background(color = backgroundColor.value)
.alpha(alpha = contentAlpha.value)
- .semantics {
- testTagsAsResourceId = true
- }
.clickable {
// if a setting is expanded, click on the background to close it.
// if no other settings are expanded, then close the popup