diff --git a/app/src/main/java/com/easyhz/picly/data/repository/user/UserRepositoryImpl.kt b/app/src/main/java/com/easyhz/picly/data/repository/user/UserRepositoryImpl.kt index a2ec555..96f1dcc 100644 --- a/app/src/main/java/com/easyhz/picly/data/repository/user/UserRepositoryImpl.kt +++ b/app/src/main/java/com/easyhz/picly/data/repository/user/UserRepositoryImpl.kt @@ -55,7 +55,7 @@ class UserRepositoryImpl onSuccess.invoke() } - override suspend fun signUp(user: UserForm, onSuccess: () -> Unit, onError: (String?) -> Unit) { + override suspend fun signUp(user: UserForm) { try { var uid = user.uid var email = user.email @@ -66,12 +66,11 @@ class UserRepositoryImpl } saveUser(uid, email, user.authProvider) - onSuccess.invoke() } catch (e: FirebaseAuthException) { - onError(e.errorCode) + throw e } catch (e: Exception) { Log.e(this.javaClass.simpleName, "Sign Up Error: ${e.message}") - onError(e.unknownErrorCode()) + throw e } } diff --git a/app/src/main/java/com/easyhz/picly/domain/repository/user/UserRepository.kt b/app/src/main/java/com/easyhz/picly/domain/repository/user/UserRepository.kt index e784bff..2dde4fe 100644 --- a/app/src/main/java/com/easyhz/picly/domain/repository/user/UserRepository.kt +++ b/app/src/main/java/com/easyhz/picly/domain/repository/user/UserRepository.kt @@ -13,7 +13,7 @@ interface UserRepository { fun fetchLoginInfo(id: String) : Flow fun logout(onSuccess: () -> Unit) - suspend fun signUp(user: UserForm, onSuccess: () -> Unit, onError: (String?) -> Unit) + suspend fun signUp(user: UserForm) suspend fun deleteUser(id: String, onSuccess: () -> Unit) } \ No newline at end of file diff --git a/app/src/main/java/com/easyhz/picly/domain/usecase/album/upload/UploadUseCase.kt b/app/src/main/java/com/easyhz/picly/domain/usecase/album/upload/UploadUseCase.kt index 83b2547..ab6ed32 100644 --- a/app/src/main/java/com/easyhz/picly/domain/usecase/album/upload/UploadUseCase.kt +++ b/app/src/main/java/com/easyhz/picly/domain/usecase/album/upload/UploadUseCase.kt @@ -7,45 +7,38 @@ import com.easyhz.picly.domain.repository.album.AlbumRepository import com.easyhz.picly.util.getImageSizes import com.easyhz.picly.util.getImageUri import com.google.firebase.Timestamp -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.FlowCollector -import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.withContext import javax.inject.Inject class UploadUseCase @Inject constructor( private val repository: AlbumRepository ) { - - fun writeAlbums( + sealed class UploadAlbumResult{ + data class Success(val message: String): UploadAlbumResult() + data class Error(val errorMessage: String): UploadAlbumResult() + } + suspend fun writeAlbums( ownerId: String, tags: List, selectedImageList: List, expireTime: Timestamp - ): Flow = flow { + ): UploadAlbumResult = withContext(Dispatchers.IO) { val album = createAlbum(ownerId, tags, selectedImageList, expireTime) try { - var documentId = "" - repository.writeAlbums(album).collectLatest { - documentId = it.id - } - if (documentId.isBlank()) throw Exception() + val documentId = repository.writeAlbums(album).first().id + if (documentId.isBlank()) return@withContext UploadAlbumResult.Error("잠시 후 다시 시도해주세요.") val imageUrls = repository.writeAlbumImages(documentId, selectedImageList.getImageUri()).first() - updateAlbum(documentId, album.copy(imageUrls = imageUrls.imageUrls, thumbnailUrl = imageUrls.thumbnailUrl)) - + val result = repository.updateAlbums(documentId, album.copy(imageUrls = imageUrls.imageUrls, thumbnailUrl = imageUrls.thumbnailUrl)).first() + return@withContext UploadAlbumResult.Success(result) } catch (e: Exception) { Log.e(this.javaClass.simpleName, "Error writing albums and images: ${e.message}") - throw e + UploadAlbumResult.Error("알 수 없는 오류가 발생하였습니다.") } } - private suspend fun FlowCollector.updateAlbum(documentId: String, album: Album) { - val result = repository.updateAlbums(documentId, album).first() - emit(result) - } - private fun createAlbum( ownerId: String, tags: List, diff --git a/app/src/main/java/com/easyhz/picly/domain/usecase/user/SignUpUseCase.kt b/app/src/main/java/com/easyhz/picly/domain/usecase/user/SignUpUseCase.kt index 3804d04..400aff1 100644 --- a/app/src/main/java/com/easyhz/picly/domain/usecase/user/SignUpUseCase.kt +++ b/app/src/main/java/com/easyhz/picly/domain/usecase/user/SignUpUseCase.kt @@ -1,12 +1,31 @@ package com.easyhz.picly.domain.usecase.user +import android.util.Log import com.easyhz.picly.domain.model.user.UserForm import com.easyhz.picly.domain.repository.user.UserRepository +import com.easyhz.picly.util.unknownErrorCode +import com.google.firebase.auth.FirebaseAuthException +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import javax.inject.Inject class SignUpUseCase @Inject constructor( private val repository: UserRepository ){ - suspend fun signUp(user: UserForm, onSuccess: () -> Unit, onError: (String?) -> Unit) = repository.signUp(user, onSuccess, onError) + sealed class SignUpResult { + data object Success: SignUpResult() + data class Error(val errorMessage: String): SignUpResult() + } + suspend fun signUp(user: UserForm): SignUpResult = withContext(Dispatchers.IO) { + try { + val result = repository.signUp(user) + return@withContext SignUpResult.Success + } catch (e: FirebaseAuthException) { + return@withContext SignUpResult.Error(e.errorCode) + } catch (e: Exception) { + Log.e(this.javaClass.simpleName, "SingUpUseCase Sign Up Error: ${e.message}") + return@withContext SignUpResult.Error(e.unknownErrorCode()) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/easyhz/picly/view/album/upload/UploadFragment.kt b/app/src/main/java/com/easyhz/picly/view/album/upload/UploadFragment.kt index 7f8f52b..58252ca 100644 --- a/app/src/main/java/com/easyhz/picly/view/album/upload/UploadFragment.kt +++ b/app/src/main/java/com/easyhz/picly/view/album/upload/UploadFragment.kt @@ -29,6 +29,7 @@ import com.easyhz.picly.R import com.easyhz.picly.databinding.FragmentUploadBinding import com.easyhz.picly.domain.model.album.upload.gallery.GalleryImageItem import com.easyhz.picly.domain.model.album.upload.gallery.GalleryImageItem.Companion.toGalleryImageItem +import com.easyhz.picly.domain.usecase.album.upload.UploadUseCase.UploadAlbumResult import com.easyhz.picly.util.BlueSnackBar import com.easyhz.picly.util.PICLY import com.easyhz.picly.util.animateGrow @@ -53,6 +54,9 @@ import com.easyhz.picly.view.dialog.Orientation import com.easyhz.picly.view.navigation.NavControllerManager import com.google.android.material.textfield.TextInputLayout import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch @AndroidEntryPoint @@ -232,7 +236,6 @@ class UploadFragment: Fragment() { } for (i in 0 until clipData.itemCount) { val item = clipData.getItemAt(i).uri.toGalleryImageItem(requireActivity()) - println("item> $item") item?.let { selectedImages.add(it) } @@ -354,13 +357,16 @@ class UploadFragment: Fragment() { } viewModel.selectedImageList.value?.let { imageList -> loading.show(true) - viewModel.writeAlbums( - imageList, - binding.expireDateButton.text.toString(), - binding.expireTimeButton.text.toString(), - { onFailure(it) } - ) { - onSuccess(it) + CoroutineScope(Dispatchers.Main).launch { + val result = viewModel.writeAlbums( + imageList, + binding.expireDateButton.text.toString(), + binding.expireTimeButton.text.toString(), + ) + when(result) { + is UploadAlbumResult.Success -> onSuccess(result.message) + is UploadAlbumResult.Error -> onFailure(result.errorMessage) + } } } } diff --git a/app/src/main/java/com/easyhz/picly/view/album/upload/UploadViewModel.kt b/app/src/main/java/com/easyhz/picly/view/album/upload/UploadViewModel.kt index 165cdc8..306eb13 100644 --- a/app/src/main/java/com/easyhz/picly/view/album/upload/UploadViewModel.kt +++ b/app/src/main/java/com/easyhz/picly/view/album/upload/UploadViewModel.kt @@ -3,17 +3,11 @@ package com.easyhz.picly.view.album.upload import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope import com.easyhz.picly.data.repository.user.UserManager import com.easyhz.picly.domain.model.album.upload.gallery.GalleryImageItem import com.easyhz.picly.domain.usecase.album.upload.UploadUseCase import com.easyhz.picly.util.toFirebaseTimestamp import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import javax.inject.Inject @HiltViewModel @@ -34,29 +28,18 @@ class UploadViewModel _tags.value = emptyList() } - fun writeAlbums( + suspend fun writeAlbums( selectedImageList: List, expiredDate: String, - expiredTime: String, - onFailure: (String) -> Unit, - onSuccess: (String) -> Unit, - ) = viewModelScope.launch(Dispatchers.IO) { - val ownerId = UserManager.currentUser?.uid ?: run { - return@launch - } - uploadUseCase.writeAlbums( + expiredTime: String + ): UploadUseCase.UploadAlbumResult { + val ownerId = UserManager.currentUser?.uid ?: return UploadUseCase.UploadAlbumResult.Error("") + return uploadUseCase.writeAlbums( ownerId = ownerId, tags = tags.value.orEmpty(), selectedImageList = selectedImageList, expireTime = "$expiredDate $expiredTime".toFirebaseTimestamp() - ).catch { e -> - e.localizedMessage?.let { onFailure(it) } - }.collectLatest { - withContext(Dispatchers.Main) { - onSuccess(it) - } - } - + ) } fun addTag(tag: String) { diff --git a/app/src/main/java/com/easyhz/picly/view/user/LoginFragment.kt b/app/src/main/java/com/easyhz/picly/view/user/LoginFragment.kt index b79210c..969844f 100644 --- a/app/src/main/java/com/easyhz/picly/view/user/LoginFragment.kt +++ b/app/src/main/java/com/easyhz/picly/view/user/LoginFragment.kt @@ -20,6 +20,7 @@ import com.easyhz.picly.data.firebase.Constants.AUTH_PROVIDER_GOOGLE import com.easyhz.picly.data.repository.user.UserManager.initGoogle import com.easyhz.picly.data.repository.user.UserManager.onGoogleSignInAccount import com.easyhz.picly.databinding.FragmentLoginBinding +import com.easyhz.picly.domain.usecase.user.SignUpUseCase import com.easyhz.picly.helper.PRIVACY_POLICY_URL import com.easyhz.picly.helper.TERMS_OF_SERVICE_URL import com.easyhz.picly.util.BlueSnackBar @@ -29,9 +30,11 @@ import com.easyhz.picly.view.user.email.SignUpViewModel import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignInClient import com.google.android.gms.common.api.ApiException -import com.google.android.gms.oss.licenses.OssLicensesMenuActivity import com.google.android.gms.tasks.Task import com.google.firebase.auth.AuthResult +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch class LoginFragment : Fragment() { private lateinit var binding: FragmentLoginBinding @@ -127,24 +130,24 @@ class LoginFragment : Fragment() { onFailure("${task.exception?.localizedMessage}") return } - if (task.result?.additionalUserInfo?.isNewUser == true) { - val user = task.result.user - user?.let { u -> - u.email?.let { - signUpViewModel.signUp( - requireActivity(), - email = it, - password = u.uid, - uid = u.uid, - authProvider = AUTH_PROVIDER_GOOGLE, - onSuccess = { onSuccess() } - ) { - onFailure(it) - } - } - } - } else { + if (task.result?.additionalUserInfo?.isNewUser == false) { onSuccess() + return + } + val user = task.result?.user ?: return + val email = user.email ?: return + CoroutineScope(Dispatchers.Main).launch { + val result = signUpViewModel.signUp( + requireActivity(), + email = email, + password = user.uid, + uid = user.uid, + authProvider = AUTH_PROVIDER_GOOGLE + ) + when(result) { + is SignUpUseCase.SignUpResult.Success -> onSuccess() + is SignUpUseCase.SignUpResult.Error -> onFailure(result.errorMessage) + } } } diff --git a/app/src/main/java/com/easyhz/picly/view/user/email/SignUpFragment.kt b/app/src/main/java/com/easyhz/picly/view/user/email/SignUpFragment.kt index 86eb485..fd01ec1 100644 --- a/app/src/main/java/com/easyhz/picly/view/user/email/SignUpFragment.kt +++ b/app/src/main/java/com/easyhz/picly/view/user/email/SignUpFragment.kt @@ -11,12 +11,16 @@ import com.easyhz.picly.R import com.easyhz.picly.data.firebase.AuthError import com.easyhz.picly.data.firebase.Constants.AUTH_PROVIDER_EMAIL import com.easyhz.picly.databinding.FragmentEmailLoginBinding +import com.easyhz.picly.domain.usecase.user.SignUpUseCase import com.easyhz.picly.util.BlueSnackBar import com.easyhz.picly.util.user.setEmailField import com.easyhz.picly.util.user.setPasswordField import com.easyhz.picly.view.dialog.LoadingDialog import com.easyhz.picly.view.navigation.NavControllerManager import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch @AndroidEntryPoint class SignUpFragment :Fragment() { @@ -63,14 +67,17 @@ class SignUpFragment :Fragment() { text = getString(R.string.sign_up) setOnClickListener { loading.show(true) - viewModel.signUp( - requireContext(), - email = binding.userField.emailField.editText.text.toString(), - password = binding.userField.passwordField.editText.text.toString(), - authProvider = AUTH_PROVIDER_EMAIL, - onSuccess ={onSuccess()} - ) { - onFailure(it) + CoroutineScope(Dispatchers.Main).launch { + val result = viewModel.signUp( + requireContext(), + email = binding.userField.emailField.editText.text.toString(), + password = binding.userField.passwordField.editText.text.toString(), + authProvider = AUTH_PROVIDER_EMAIL, + ) + when(result) { + is SignUpUseCase.SignUpResult.Success -> onSuccess() + is SignUpUseCase.SignUpResult.Error -> onFailure(result.errorMessage) + } } } } diff --git a/app/src/main/java/com/easyhz/picly/view/user/email/SignUpViewModel.kt b/app/src/main/java/com/easyhz/picly/view/user/email/SignUpViewModel.kt index 5f3b874..60908d6 100644 --- a/app/src/main/java/com/easyhz/picly/view/user/email/SignUpViewModel.kt +++ b/app/src/main/java/com/easyhz/picly/view/user/email/SignUpViewModel.kt @@ -3,7 +3,6 @@ package com.easyhz.picly.view.user.email import android.content.Context import androidx.core.net.toUri import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope import com.easyhz.picly.data.firebase.AuthError import com.easyhz.picly.data.repository.user.UserManager import com.easyhz.picly.domain.model.album.upload.gallery.GalleryImageItem @@ -13,9 +12,6 @@ import com.easyhz.picly.domain.usecase.user.SignUpUseCase import com.easyhz.picly.util.getDefaultImage import com.google.firebase.Timestamp import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.launch import java.util.Calendar import javax.inject.Inject @@ -26,43 +22,38 @@ class SignUpViewModel private val uploadUseCase: UploadUseCase ): ViewModel() { - fun signUp( + suspend fun signUp( context: Context, email: String, password: String, authProvider: String, - uid: String = "", - onSuccess: (String) -> Unit, - onFailure: (String) -> Unit - ) = viewModelScope.launch { + uid: String = "" + ): SignUpUseCase.SignUpResult { isEmptyEmailAndPassword(email, password)?.let { - onFailure(it) - return@launch + return SignUpUseCase.SignUpResult.Error(it) } - signUpUseCase.signUp( - UserForm(email, password, authProvider, uid), - onSuccess = { initAlbum(context, onSuccess, onFailure) } - ) { - if (it != null) { - onFailure(it) - } + val signUpResult = signUpUseCase.signUp(UserForm(email, password, authProvider, uid)) + if (signUpResult is SignUpUseCase.SignUpResult.Error) { + return SignUpUseCase.SignUpResult.Error(signUpResult.errorMessage) } + + val initAlbumResult = initAlbum(context) + if (initAlbumResult is UploadUseCase.UploadAlbumResult.Error) { + return SignUpUseCase.SignUpResult.Error(initAlbumResult.errorMessage) + } + return SignUpUseCase.SignUpResult.Success } - private fun initAlbum(context: Context, onSuccess: (String) -> Unit, onFailure: (String) -> Unit) = viewModelScope.launch { + private suspend fun initAlbum(context: Context): UploadUseCase.UploadAlbumResult { UserManager.currentUser?.uid?.let { id -> val defaultGalleryItem = getDefaultGalleryItem(context) - uploadUseCase.writeAlbums( + return uploadUseCase.writeAlbums( ownerId = id, tags = TAGS, selectedImageList = listOf(defaultGalleryItem!!), expireTime = getExpireTime() - ).catch { e -> - e.localizedMessage?.let { onFailure(it) } - }.collectLatest { - onSuccess(it) - } - } + ) + } ?: return UploadUseCase.UploadAlbumResult.Error("알 수 없는 오류가 발생했습니다") } private fun getDefaultGalleryItem(context: Context): GalleryImageItem? {