Skip to content
Open
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 @@ -34,6 +34,7 @@ import com.google.jetpackcamera.feature.postcapture.ui.PostCaptureLayout
import com.google.jetpackcamera.feature.postcapture.ui.SaveCurrentMediaButton
import com.google.jetpackcamera.feature.postcapture.ui.ShareCurrentMediaButton
import com.google.jetpackcamera.feature.postcapture.utils.MediaSharing
import com.google.jetpackcamera.ui.components.capture.SnackBarController
import com.google.jetpackcamera.ui.components.capture.TestableSnackbar
import com.google.jetpackcamera.ui.uistate.SnackBarUiState
import com.google.jetpackcamera.ui.uistate.postcapture.DeleteButtonUiState
Expand Down Expand Up @@ -73,8 +74,8 @@ fun PostCaptureScreen(
onSaveMedia = viewModel::saveCurrentMedia,
onShareCurrentMedia = viewModel::onShareCurrentMedia,
onLoadVideo = viewModel::loadCurrentVideo,
onSnackBarResult = viewModel::onSnackBarResult,
snackBarUiState = snackBarUiState
snackBarUiState = snackBarUiState,
snackBarController = viewModel.snackBarController
)
}

Expand All @@ -87,8 +88,8 @@ fun PostCaptureComponent(
onShareCurrentMedia: () -> Unit,
onDeleteMedia: (onSuccessCallback: () -> Unit) -> Unit,
onLoadVideo: () -> Unit,
onSnackBarResult: (String) -> Unit,
snackBarUiState: SnackBarUiState = SnackBarUiState.Disabled
snackBarUiState: SnackBarUiState = SnackBarUiState.Disabled,
snackBarController: SnackBarController? = null
) {
when (uiState) {
PostCaptureUiState.Loading -> {
Expand Down Expand Up @@ -139,12 +140,14 @@ fun PostCaptureComponent(
if (snackBarUiState is SnackBarUiState.Enabled) {
val snackBarData = snackBarUiState.snackBarQueue.peek()
if (snackBarData != null) {
TestableSnackbar(
modifier = modifier.testTag(snackBarData.testTag),
snackbarToShow = snackBarData,
snackbarHostState = snackbarHostState,
onSnackbarResult = onSnackBarResult
)
snackBarController?.let {
TestableSnackbar(
modifier = modifier.testTag(snackBarData.testTag),
snackbarToShow = snackBarData,
snackbarHostState = snackbarHostState,
snackBarController = snackBarController
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,18 @@ import com.google.jetpackcamera.feature.postcapture.ui.SNACKBAR_POST_CAPTURE_IMA
import com.google.jetpackcamera.feature.postcapture.ui.SNACKBAR_POST_CAPTURE_VIDEO_DELETE_FAILURE
import com.google.jetpackcamera.feature.postcapture.ui.SNACKBAR_POST_CAPTURE_VIDEO_SAVE_FAILURE
import com.google.jetpackcamera.feature.postcapture.ui.SNACKBAR_POST_CAPTURE_VIDEO_SAVE_SUCCESS
import com.google.jetpackcamera.ui.components.capture.SnackBarController
import com.google.jetpackcamera.ui.components.capture.SnackBarControllerImpl
import com.google.jetpackcamera.ui.uistate.SnackBarUiState
import com.google.jetpackcamera.ui.uistate.SnackbarData
import com.google.jetpackcamera.ui.uistate.postcapture.DeleteButtonUiState
import com.google.jetpackcamera.ui.uistate.postcapture.MediaViewerUiState
import com.google.jetpackcamera.ui.uistate.postcapture.PostCaptureUiState
import com.google.jetpackcamera.ui.uistate.postcapture.ShareButtonUiState
import com.google.jetpackcamera.ui.uistateadapter.from
import com.google.jetpackcamera.ui.uistateadapter.postcapture.from
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import java.util.LinkedList
import javax.inject.Inject
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.async
import kotlinx.coroutines.channels.Channel
Expand Down Expand Up @@ -111,8 +110,10 @@ class PostCaptureViewModel @Inject constructor(
MutableStateFlow(SnackBarUiState.Enabled())
val snackBarUiState: StateFlow<SnackBarUiState.Enabled> =
_snackBarUiState.asStateFlow()
private val snackBarCount = atomic(0)

val snackBarController: SnackBarController = SnackBarControllerImpl(
viewModelScope = viewModelScope,
snackBarUiState = _snackBarUiState
)
private var player: ExoPlayer? = null

private val playerState = MutableStateFlow<PlayerState>(PlayerState.Unavailable)
Expand Down Expand Up @@ -302,7 +303,7 @@ class PostCaptureViewModel @Inject constructor(
*/

private suspend fun saveMedia(mediaDescriptor: MediaDescriptor.Content) {
val cookieInt = snackBarCount.incrementAndGet()
val cookieInt = snackBarController.incrementAndGetSnackBarCount()
val cookie = "MediaSave-$cookieInt"
val result: Uri?
try {
Expand All @@ -321,7 +322,7 @@ class PostCaptureViewModel @Inject constructor(
SNACKBAR_POST_CAPTURE_VIDEO_SAVE_SUCCESS
}

addSnackBarData(
snackBarController.addSnackBarData(
SnackbarData(
cookie = cookie,
stringResource = stringResource,
Expand All @@ -343,7 +344,7 @@ class PostCaptureViewModel @Inject constructor(
SNACKBAR_POST_CAPTURE_VIDEO_SAVE_FAILURE
}

addSnackBarData(
snackBarController.addSnackBarData(
SnackbarData(
cookie = cookie,
stringResource = stringResource,
Expand All @@ -364,7 +365,7 @@ class PostCaptureViewModel @Inject constructor(
SNACKBAR_POST_CAPTURE_VIDEO_SAVE_FAILURE
}

addSnackBarData(
snackBarController.addSnackBarData(
SnackbarData(
cookie = cookie,
stringResource = stringResource,
Expand All @@ -388,9 +389,9 @@ class PostCaptureViewModel @Inject constructor(
false
}
if (!result) {
val cookieInt = snackBarCount.incrementAndGet()
val cookieInt = snackBarController.incrementAndGetSnackBarCount()
val cookie = "MediaDelete-$cookieInt"
addSnackBarData(
snackBarController.addSnackBarData(
SnackbarData(
cookie = cookie,
stringResource = when (mediaDescriptor) {
Expand Down Expand Up @@ -426,39 +427,6 @@ class PostCaptureViewModel @Inject constructor(
}
}
}

// snackbar interaction
private fun addSnackBarData(snackBarData: SnackbarData) {
viewModelScope.launch {
_snackBarUiState.update { old ->
val newQueue = LinkedList(old.snackBarQueue)

newQueue.add(snackBarData)
Log.d(TAG, "SnackBar added. Queue size: ${newQueue.size}")
old.copy(
snackBarQueue = newQueue
)
}
}
}

fun onSnackBarResult(cookie: String) {
viewModelScope.launch {
_snackBarUiState.update { state ->
val newQueue = LinkedList(state.snackBarQueue)
val snackBarData = newQueue.poll()
if (snackBarData != null && snackBarData.cookie == cookie) {
// If the latest snackBar had a result, then clear snackBarToShow
Log.d(TAG, "SnackBar removed. Queue size: ${newQueue.size}")
state.copy(
snackBarQueue = newQueue
)
} else {
state
}
}
}
}
}

sealed interface PlayerState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ internal class PostCaptureViewModelTest {
val cookie = snackBarUiState.snackBarQueue.first().cookie

// When
viewModel.onSnackBarResult(cookie)
viewModel.snackBarController.onSnackBarResult(cookie)
advanceUntilIdle()

// Then
Expand All @@ -367,7 +367,7 @@ internal class PostCaptureViewModelTest {
advanceUntilIdle()

// When
viewModel.onSnackBarResult("incorrect_cookie")
viewModel.snackBarController.onSnackBarResult("incorrect_cookie")
advanceUntilIdle()

// Then
Expand All @@ -382,7 +382,7 @@ internal class PostCaptureViewModelTest {
assertThat(snackBarUiState.snackBarQueue).isEmpty()

// When
viewModel.onSnackBarResult("any_cookie")
viewModel.snackBarController.onSnackBarResult("any_cookie")
advanceUntilIdle()

// Then
Expand Down
Loading
Loading