Skip to content

Commit 651ca00

Browse files
committed
Move Toast invocations out of Camera/VideoEdit ViewModels.
1 parent f81a4bd commit 651ca00

File tree

4 files changed

+70
-7
lines changed

4 files changed

+70
-7
lines changed

Diff for: app/src/main/java/com/google/android/samples/socialite/ui/camera/Camera.kt

+17
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.google.android.samples.socialite.ui.camera
1919
import android.Manifest
2020
import android.annotation.SuppressLint
2121
import android.view.Surface
22+
import android.widget.Toast
2223
import androidx.camera.core.CameraSelector
2324
import androidx.camera.core.Preview
2425
import androidx.camera.view.RotationProvider
@@ -64,6 +65,7 @@ import androidx.window.layout.FoldingFeature
6465
import androidx.window.layout.WindowInfoTracker
6566
import com.google.accompanist.permissions.ExperimentalPermissionsApi
6667
import com.google.accompanist.permissions.rememberMultiplePermissionsState
68+
import kotlin.coroutines.coroutineContext
6769
import kotlin.reflect.KFunction1
6870
import kotlinx.coroutines.Dispatchers
6971
import kotlinx.coroutines.asExecutor
@@ -91,6 +93,21 @@ fun Camera(
9193
val lifecycleOwner = LocalLifecycleOwner.current
9294
val context = LocalContext.current
9395

96+
LaunchedEffect(lifecycleOwner, context) {
97+
viewModel.imageCaptureState.collect { state ->
98+
when (state) {
99+
ImageCaptureState.IMAGE_CAPTURE_SUCCESS ->
100+
Toast.makeText(context, "Photo saved.", Toast.LENGTH_SHORT).show()
101+
ImageCaptureState.IMAGE_CAPTURE_FAIL ->
102+
Toast.makeText(context, "Photo capture failed.", Toast.LENGTH_SHORT).show()
103+
else -> {
104+
/* no-op */
105+
}
106+
}
107+
108+
}
109+
}
110+
94111
var isLayoutUnfolded by remember { mutableStateOf<Boolean?>(null) }
95112

96113
LaunchedEffect(lifecycleOwner, context) {

Diff for: app/src/main/java/com/google/android/samples/socialite/ui/camera/CameraViewModel.kt

+18-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import android.content.Context
2222
import android.os.Build
2323
import android.provider.MediaStore
2424
import android.view.Display
25-
import android.widget.Toast
2625
import androidx.annotation.RequiresPermission
2726
import androidx.camera.core.AspectRatio
2827
import androidx.camera.core.Camera
@@ -58,6 +57,7 @@ import java.text.SimpleDateFormat
5857
import java.util.Locale
5958
import javax.inject.Inject
6059
import kotlinx.coroutines.flow.MutableStateFlow
60+
import kotlinx.coroutines.flow.SharedFlow
6161
import kotlinx.coroutines.launch
6262

6363
@HiltViewModel
@@ -72,6 +72,8 @@ class CameraViewModel @Inject constructor(
7272

7373
val chatId: Long? = savedStateHandle.get("chatId")
7474
var viewFinderState = MutableStateFlow(ViewFinderState())
75+
private var _imageCaptureState = MutableStateFlow(ImageCaptureState.PENDING)
76+
val imageCaptureState: SharedFlow<ImageCaptureState> = _imageCaptureState
7577

7678
val aspectRatioStrategy =
7779
AspectRatioStrategy(AspectRatio.RATIO_16_9, AspectRatioStrategy.FALLBACK_RULE_NONE)
@@ -189,18 +191,23 @@ class CameraViewModel @Inject constructor(
189191
ContextCompat.getMainExecutor(context),
190192
object : ImageCapture.OnImageSavedCallback {
191193
override fun onError(exc: ImageCaptureException) {
192-
val msg = "Photo capture failed."
193-
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
194+
viewModelScope.launch {
195+
_imageCaptureState.emit(ImageCaptureState.IMAGE_CAPTURE_FAIL)
196+
}
194197
}
195198

196199
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
200+
var state = ImageCaptureState.PENDING
197201
val savedUri = output.savedUri
198202
if (savedUri != null) {
203+
state = ImageCaptureState.IMAGE_CAPTURE_SUCCESS
199204
sendPhotoMessage(savedUri.toString())
200205
onMediaCaptured(Media(savedUri, MediaType.PHOTO))
201206
} else {
202-
val msg = "Photo capture failed."
203-
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
207+
state = ImageCaptureState.IMAGE_CAPTURE_FAIL
208+
}
209+
viewModelScope.launch {
210+
_imageCaptureState.emit(state)
204211
}
205212
}
206213
},
@@ -310,6 +317,12 @@ data class ViewFinderState(
310317
val lensFacing: Int = CameraSelector.LENS_FACING_BACK,
311318
)
312319

320+
enum class ImageCaptureState {
321+
PENDING,
322+
IMAGE_CAPTURE_SUCCESS,
323+
IMAGE_CAPTURE_FAIL
324+
}
325+
313326
/**
314327
* Defines the current state of the camera.
315328
*/

Diff for: app/src/main/java/com/google/android/samples/socialite/ui/videoedit/VideoEditScreen.kt

+19
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.google.android.samples.socialite.ui.videoedit
1919
import android.media.MediaMetadataRetriever
2020
import android.net.Uri
2121
import android.util.Log
22+
import android.widget.Toast
2223
import androidx.compose.foundation.Image
2324
import androidx.compose.foundation.background
2425
import androidx.compose.foundation.layout.Arrangement
@@ -59,6 +60,7 @@ import androidx.compose.material3.TextFieldDefaults
5960
import androidx.compose.material3.TopAppBar
6061
import androidx.compose.material3.TopAppBarDefaults
6162
import androidx.compose.runtime.Composable
63+
import androidx.compose.runtime.LaunchedEffect
6264
import androidx.compose.runtime.collectAsState
6365
import androidx.compose.runtime.getValue
6466
import androidx.compose.runtime.mutableStateOf
@@ -71,6 +73,7 @@ import androidx.compose.ui.graphics.asImageBitmap
7173
import androidx.compose.ui.graphics.vector.ImageVector
7274
import androidx.compose.ui.platform.LocalContext
7375
import androidx.compose.ui.platform.LocalInspectionMode
76+
import androidx.compose.ui.platform.LocalLifecycleOwner
7477
import androidx.compose.ui.res.colorResource
7578
import androidx.compose.ui.res.stringResource
7679
import androidx.compose.ui.tooling.preview.Preview
@@ -92,6 +95,7 @@ fun VideoEditScreen(
9295
onCloseButtonClicked: () -> Unit,
9396
navController: NavController,
9497
) {
98+
val lifecycleOwner = LocalLifecycleOwner.current
9599
val context = LocalContext.current
96100

97101
val viewModel: VideoEditScreenViewModel = hiltViewModel()
@@ -104,6 +108,21 @@ fun VideoEditScreen(
104108

105109
val isProcessing = viewModel.isProcessing.collectAsState()
106110

111+
LaunchedEffect(lifecycleOwner, context) {
112+
viewModel.videoSaveState.collect { state ->
113+
when (state) {
114+
VideoSaveState.VIDEO_SAVE_SUCCESS ->
115+
Toast.makeText(context, "Edited video saved", Toast.LENGTH_LONG).show()
116+
VideoSaveState.VIDEO_SAVE_FAIL ->
117+
Toast.makeText(context, "Error applying edits on video", Toast.LENGTH_LONG)
118+
.show()
119+
else -> {
120+
/* no-op */
121+
}
122+
}
123+
}
124+
}
125+
107126
var removeAudioEnabled by rememberSaveable { mutableStateOf(false) }
108127
var overlayText by rememberSaveable { mutableStateOf("") }
109128
var redOverlayTextEnabled by rememberSaveable { mutableStateOf(false) }

Diff for: app/src/main/java/com/google/android/samples/socialite/ui/videoedit/VideoEditScreenViewModel.kt

+16-2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import java.text.SimpleDateFormat
4949
import java.util.Locale
5050
import javax.inject.Inject
5151
import kotlinx.coroutines.flow.MutableStateFlow
52+
import kotlinx.coroutines.flow.SharedFlow
5253
import kotlinx.coroutines.flow.StateFlow
5354
import kotlinx.coroutines.launch
5455

@@ -67,13 +68,19 @@ class VideoEditScreenViewModel @Inject constructor(
6768
private val _isProcessing = MutableStateFlow(false)
6869
val isProcessing: StateFlow<Boolean> = _isProcessing
6970

71+
private var _videoSaveState = MutableStateFlow(VideoSaveState.PENDING)
72+
val videoSaveState: SharedFlow<VideoSaveState> = _videoSaveState
73+
7074
fun setChatId(chatId: Long) {
7175
this.chatId.value = chatId
7276
}
7377

7478
private val transformerListener: Transformer.Listener =
7579
@UnstableApi object : Transformer.Listener {
7680
override fun onCompleted(composition: Composition, exportResult: ExportResult) {
81+
viewModelScope.launch {
82+
_videoSaveState.emit(VideoSaveState.VIDEO_SAVE_SUCCESS)
83+
}
7784
Toast.makeText(application, "Edited video saved", Toast.LENGTH_LONG).show()
7885

7986
sendVideo()
@@ -88,8 +95,9 @@ class VideoEditScreenViewModel @Inject constructor(
8895
exportException: ExportException,
8996
) {
9097
exportException.printStackTrace()
91-
Toast.makeText(application, "Error applying edits on video", Toast.LENGTH_LONG)
92-
.show()
98+
viewModelScope.launch {
99+
_videoSaveState.emit(VideoSaveState.VIDEO_SAVE_FAIL)
100+
}
93101
_isProcessing.value = false
94102
}
95103
}
@@ -183,3 +191,9 @@ class VideoEditScreenViewModel @Inject constructor(
183191
}
184192
}
185193
}
194+
195+
enum class VideoSaveState {
196+
PENDING,
197+
VIDEO_SAVE_SUCCESS,
198+
VIDEO_SAVE_FAIL
199+
}

0 commit comments

Comments
 (0)