diff --git a/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmViewModel.kt b/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmViewModel.kt index 88b3b21e..1ffb3525 100644 --- a/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmViewModel.kt +++ b/app/src/main/java/com/boostcamp/dailyfilm/presentation/uploadfilm/UploadFilmViewModel.kt @@ -24,6 +24,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import javax.inject.Inject @@ -39,7 +40,7 @@ class UploadFilmViewModel @Inject constructor( val startTime = savedStateHandle.get(KEY_START_TIME) ?: 0L val dateModel = savedStateHandle.get(KEY_DATE_MODEL) val calendarIndex = savedStateHandle.get(KEY_CALENDAR_INDEX) - val editState = savedStateHandle.get(KEY_EDIT_STATE) + val editState = savedStateHandle.getStateFlow(KEY_EDIT_STATE, null) private val _uploadResult = MutableSharedFlow() val uploadResult: SharedFlow get() = _uploadResult @@ -61,12 +62,25 @@ class UploadFilmViewModel @Inject constructor( private val _isWriting = MutableLiveData(false) val isWriting: LiveData get() = _isWriting - private val _clickSound = MutableStateFlow(true) - val clickSound = _clickSound.asStateFlow() - private val _compressProgress = MutableLiveData(0) val compressProgress: LiveData get() = _compressProgress + + private val _uploadUiState = MutableStateFlow(UploadUiState.Idle) + val uploadUiState: StateFlow get() = _uploadUiState + + private val _writingState = MutableStateFlow(false) + val writingState: StateFlow get() = _writingState + + private val _muteState = MutableStateFlow(false) + val muteState = _muteState.asStateFlow() + + private val _contentState = MutableStateFlow("") + + private val _compressState = MutableStateFlow(0) + val compressState: StateFlow get() = _compressState + + init { calcProgress() } @@ -75,10 +89,10 @@ class UploadFilmViewModel @Inject constructor( Config.resetStatistics() Config.enableStatisticsCallback { val percentage = it.videoFrameNumber - _compressProgress.postValue(percentage) + _compressState.value = percentage if (isEnded()) - _compressProgress.postValue(240) + _compressState.value = 240 } } @@ -90,21 +104,22 @@ class UploadFilmViewModel @Inject constructor( fun uploadVideo() { - val text = textContent.value ?: "" - val progress = _compressProgress.value ?: 0 + val text = _contentState.value ?: "" + val progress = _compressState.value when { text.isEmpty() -> { - _uiState.value = UiState.Failure(Throwable("영상에 맞는 문구를 입력해주세요.")) + _uploadUiState.value = UploadUiState.UploadFailed(Throwable("일기가 비어있습니다")) return } - (editState != EditState.EDIT_CONTENT) && progress < 240 -> { - _uiState.value = UiState.Failure(Throwable("영상 처리중입니다. 잠시만 기다려주세요.")) + (editState.value != EditState.EDIT_CONTENT) && progress < 240 -> { + _uploadUiState.value = UploadUiState.UploadFailed(Throwable("영상이 처리중입니다. 잠시만 기다려주세요")) return } } - editState?.let { state -> + _uploadUiState.value = UploadUiState.UploadLoading + editState.value?.let { state -> when (state) { EditState.NEW_UPLOAD -> uploadStorage() EditState.EDIT_CONTENT -> uploadEdit() @@ -115,22 +130,19 @@ class UploadFilmViewModel @Inject constructor( private fun uploadEdit() { - val text = textContent.value ?: "" + val text = _contentState.value ?: "" infoItem?.let { item -> - _uiState.value = UiState.Loading viewModelScope.launch { dateModel ?: return@launch val date = item.uploadDate val dailyFilmItem = DailyFilmItem(dateModel.videoUrl.toString(), text, date) when (val result = uploadFilmRepository.uploadEditVideo(date, dailyFilmItem)) { is Result.Success -> { - _uiState.value = UiState.Success( - dateModel.copy(text = text) - ) + _uploadUiState.value = UploadUiState.UploadSuccess(dateModel.copy(text = text)) } is Result.Error -> { - _uiState.value = UiState.Failure(result.exception) + _uploadUiState.value = UploadUiState.UploadFailed(result.exception) } } } @@ -139,14 +151,13 @@ class UploadFilmViewModel @Inject constructor( private fun uploadStorage() { infoItem?.let { item -> - _uiState.value = UiState.Loading viewModelScope.launch { when (val result = uploadFilmRepository.uploadVideo(item.uploadDate, item.uri)) { is Result.Success -> { uploadRealtime(result.data) } is Result.Error -> { - _uiState.value = UiState.Failure(result.exception) + _uploadUiState.value = UploadUiState.UploadFailed(result.exception) } } } @@ -155,9 +166,9 @@ class UploadFilmViewModel @Inject constructor( private fun uploadRealtime(videoUrl: Uri?) { val uploadDate = infoItem?.uploadDate - val text = textContent.value ?: "" + val text = _contentState.value ?: "" if (dateModel ==null){ - _uiState.value = UiState.Failure(Throwable("dateModel Fail")) + _uploadUiState.value = UploadUiState.UploadFailed(Throwable("dateModel failed")) return } if (videoUrl != null && uploadDate != null) { @@ -166,23 +177,23 @@ class UploadFilmViewModel @Inject constructor( when (val result = uploadFilmRepository.uploadFilmInfo(uploadDate, filmItem)) { is Result.Success -> { uploadFilmRepository.insertFilmEntity(filmItem) - _uiState.value = UiState.Success( + _uploadUiState.value = UploadUiState.UploadSuccess( dateModel.copy(text = text, videoUrl = videoUrl.toString()) ) } is Result.Error -> { - _uiState.value = UiState.Failure(result.exception) + _uploadUiState.value = UploadUiState.UploadFailed(result.exception) } } } } else { - _uiState.value = - UiState.Failure(Throwable("userId == null or videoUrl == null or uploadDate or null ")) + _uploadUiState.value = + UploadUiState.UploadFailed(Throwable("userId or videoUrl or uploadDate is null")) } } fun updateSpannableText() { - textContent.value?.let { text -> + _contentState.value.let { text -> if (text.isNotEmpty()) { _showedTextContent.value = SpannableString(text).apply { setSpan( @@ -198,11 +209,14 @@ class UploadFilmViewModel @Inject constructor( } } + fun updateTextContent(text: String) { + _contentState.value = text + } + private fun deleteVideo() { dateModel ?: return viewModelScope.launch { - _uiState.value = UiState.Loading val updateDate = dateModel.getDate() when (val result = deleteFilmRepository.delete(updateDate)) { @@ -210,29 +224,27 @@ class UploadFilmViewModel @Inject constructor( uploadStorage() } is Result.Error -> { - UiState.Failure(result.exception) + _uploadUiState.value = UploadUiState.UploadFailed(result.exception) } } } } fun changeIsWriting() { - _isWriting.value?.let { - _isWriting.value = it.not() - } + _writingState.value = _writingState.value.not() } fun updateIsWriting(flag: Boolean) { - _isWriting.value = flag + _writingState.value = flag } fun controlSound() { - _clickSound.value = !_clickSound.value + _muteState.value = !_muteState.value } fun cancelUploadVideo() { viewModelScope.launch { - _cancelUploadResult.emit(true) + _uploadUiState.emit(UploadUiState.Canceled) } } @@ -241,3 +253,16 @@ class UploadFilmViewModel @Inject constructor( const val KEY_START_TIME = "start_time" } } + +sealed interface UploadUiState { + + object Idle: UploadUiState + + object Canceled: UploadUiState + object UploadLoading: UploadUiState + + data class UploadSuccess(val dateModel: DateModel): UploadUiState + + data class UploadFailed(val throwable: Throwable): UploadUiState + +}