diff options
Diffstat (limited to 'feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt')
-rw-r--r-- | feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt | 118 |
1 files changed, 107 insertions, 11 deletions
diff --git a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt index e7b1544..5a43e60 100644 --- a/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt +++ b/feature/preview/src/main/java/com/google/jetpackcamera/feature/preview/PreviewViewModel.kt @@ -15,26 +15,37 @@ */ package com.google.jetpackcamera.feature.preview +import android.content.ContentResolver +import android.net.Uri import android.util.Log import android.view.Display -import androidx.camera.core.ImageCaptureException import androidx.camera.core.Preview.SurfaceProvider import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import androidx.tracing.traceAsync import com.google.jetpackcamera.domain.camera.CameraUseCase +import com.google.jetpackcamera.feature.preview.ui.ToastMessage import com.google.jetpackcamera.settings.SettingsRepository import com.google.jetpackcamera.settings.model.AspectRatio import com.google.jetpackcamera.settings.model.CaptureMode import com.google.jetpackcamera.settings.model.DEFAULT_CAMERA_APP_SETTINGS import com.google.jetpackcamera.settings.model.FlashMode import dagger.hilt.android.lifecycle.HiltViewModel +import java.lang.Exception import javax.inject.Inject +import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch private const val TAG = "PreviewViewModel" +private const val IMAGE_CAPTURE_TRACE = "JCA Image Capture" + +// toast test descriptions +const val IMAGE_CAPTURE_SUCCESS_TOAST_TAG = "ImageCaptureSuccessToast" +const val IMAGE_CAPTURE_FAIL_TOAST_TAG = "ImageCaptureFailureToast" /** * [ViewModel] for [PreviewScreen]. @@ -45,7 +56,6 @@ class PreviewViewModel @Inject constructor( private val settingsRepository: SettingsRepository // only reads from settingsRepository. do not push changes to repository from here ) : ViewModel() { - private val _previewUiState: MutableStateFlow<PreviewUiState> = MutableStateFlow(PreviewUiState(currentCameraSettings = DEFAULT_CAMERA_APP_SETTINGS)) @@ -54,6 +64,8 @@ class PreviewViewModel @Inject constructor( private var recordingJob: Job? = null + val screenFlash = ScreenFlash(cameraUseCase, viewModelScope) + init { viewModelScope.launch { settingsRepository.cameraAppSettings.collect { @@ -112,7 +124,10 @@ class PreviewViewModel @Inject constructor( ) ) // apply to cameraUseCase - cameraUseCase.setFlashMode(previewUiState.value.currentCameraSettings.flashMode) + cameraUseCase.setFlashMode( + previewUiState.value.currentCameraSettings.flashMode, + previewUiState.value.currentCameraSettings.isFrontCameraFacing + ) } } @@ -181,8 +196,10 @@ class PreviewViewModel @Inject constructor( ) ) // apply to cameraUseCase - cameraUseCase - .flipCamera(previewUiState.value.currentCameraSettings.isFrontCameraFacing) + cameraUseCase.flipCamera( + previewUiState.value.currentCameraSettings.isFrontCameraFacing, + previewUiState.value.currentCameraSettings.flashMode + ) } } } @@ -190,12 +207,71 @@ class PreviewViewModel @Inject constructor( fun captureImage() { Log.d(TAG, "captureImage") viewModelScope.launch { - try { - cameraUseCase.takePicture() - Log.d(TAG, "cameraUseCase.takePicture success") - } catch (exception: ImageCaptureException) { - Log.d(TAG, "cameraUseCase.takePicture error") - Log.d(TAG, exception.toString()) + traceAsync(IMAGE_CAPTURE_TRACE, 0) { + try { + cameraUseCase.takePicture() + // todo: remove toast after postcapture screen implemented + _previewUiState.emit( + previewUiState.value.copy( + toastMessageToShow = ToastMessage( + stringResource = R.string.toast_image_capture_success, + testTag = IMAGE_CAPTURE_SUCCESS_TOAST_TAG + ) + ) + ) + Log.d(TAG, "cameraUseCase.takePicture success") + } catch (exception: Exception) { + // todo: remove toast after postcapture screen implemented + _previewUiState.emit( + previewUiState.value.copy( + toastMessageToShow = ToastMessage( + stringResource = R.string.toast_capture_failure, + testTag = IMAGE_CAPTURE_FAIL_TOAST_TAG + ) + ) + ) + Log.d(TAG, "cameraUseCase.takePicture error") + Log.d(TAG, exception.toString()) + } + } + } + } + + fun captureImage( + contentResolver: ContentResolver, + imageCaptureUri: Uri?, + onImageCapture: (ImageCaptureEvent) -> Unit + ) { + Log.d(TAG, "captureImageWithUri") + viewModelScope.launch { + traceAsync(IMAGE_CAPTURE_TRACE, 0) { + try { + cameraUseCase.takePicture(contentResolver, imageCaptureUri) + // todo: remove toast after postcapture screen implemented + _previewUiState.emit( + previewUiState.value.copy( + toastMessageToShow = ToastMessage( + stringResource = R.string.toast_image_capture_success, + testTag = IMAGE_CAPTURE_SUCCESS_TOAST_TAG + ) + ) + ) + onImageCapture(ImageCaptureEvent.ImageSaved) + Log.d(TAG, "cameraUseCase.takePicture success") + } catch (exception: Exception) { + // todo: remove toast after postcapture screen implemented + _previewUiState.emit( + previewUiState.value.copy( + toastMessageToShow = ToastMessage( + stringResource = R.string.toast_capture_failure, + testTag = IMAGE_CAPTURE_FAIL_TOAST_TAG + ) + ) + ) + Log.d(TAG, "cameraUseCase.takePicture error") + Log.d(TAG, exception.toString()) + onImageCapture(ImageCaptureEvent.ImageCaptureError(exception)) + } } } } @@ -259,4 +335,24 @@ class PreviewViewModel @Inject constructor( y = y ) } + + fun onToastShown() { + viewModelScope.launch { + // keeps the composable up on screen longer to be detected by UiAutomator + delay(2.seconds) + _previewUiState.emit( + previewUiState.value.copy( + toastMessageToShow = null + ) + ) + } + } + + sealed interface ImageCaptureEvent { + object ImageSaved : ImageCaptureEvent + + data class ImageCaptureError( + val exception: Exception + ) : ImageCaptureEvent + } } |