diff --git a/build-logic/src/main/java/com/idle/app/care.android.feature-binding.gradle.kts b/build-logic/src/main/java/com/idle/app/care.android.feature-binding.gradle.kts index fda52d3e..543b199a 100644 --- a/build-logic/src/main/java/com/idle/app/care.android.feature-binding.gradle.kts +++ b/build-logic/src/main/java/com/idle/app/care.android.feature-binding.gradle.kts @@ -21,6 +21,7 @@ dependencies { implementation(project(":core:designresource")) implementation(project(":core:navigation")) implementation(project(":core:analytics")) + implementation(project(":core:common")) implementation(project(":core:common-ui:binding")) val libs = project.extensions.libs @@ -31,4 +32,4 @@ dependencies { implementation(libs.findLibrary("androidx.lifecycle.viewModel").get()) implementation(libs.findLibrary("androidx.lifecycle.runtime").get()) implementation(libs.findLibrary("material").get()) -} \ No newline at end of file +} diff --git a/build-logic/src/main/java/com/idle/app/care.android.feature-compose.gradle.kts b/build-logic/src/main/java/com/idle/app/care.android.feature-compose.gradle.kts index 9b917339..bfc1bf49 100644 --- a/build-logic/src/main/java/com/idle/app/care.android.feature-compose.gradle.kts +++ b/build-logic/src/main/java/com/idle/app/care.android.feature-compose.gradle.kts @@ -21,6 +21,7 @@ dependencies { implementation(project(":core:designresource")) implementation(project(":core:navigation")) implementation(project(":core:analytics")) + implementation(project(":core:common")) implementation(project(":core:common-ui:binding")) implementation(project(":core:common-ui:compose")) @@ -30,4 +31,4 @@ dependencies { implementation(libs.findLibrary("androidx-navigation-fragment").get()) implementation(libs.findLibrary("androidx.lifecycle.viewModelCompose").get()) implementation(libs.findLibrary("androidx.lifecycle.runtimeCompose").get()) -} \ No newline at end of file +} diff --git a/core/common/src/main/java/com/idle/common/ResultUtil.kt b/core/common/src/main/java/com/idle/common/ResultUtil.kt new file mode 100644 index 00000000..d115174b --- /dev/null +++ b/core/common/src/main/java/com/idle/common/ResultUtil.kt @@ -0,0 +1,13 @@ +package com.idle.common + +import kotlin.coroutines.cancellation.CancellationException + +suspend inline fun T.suspendRunCatching(crossinline block: suspend T.() -> R): Result { + return try { + Result.success(block()) + } catch (e: CancellationException) { + throw e + } catch (t: Throwable) { + Result.failure(t) + } +} diff --git a/core/data/src/main/java/com/idle/data/repository/AuthRepositoryImpl.kt b/core/data/src/main/java/com/idle/data/repository/AuthRepositoryImpl.kt index cd7e002b..30dead76 100644 --- a/core/data/src/main/java/com/idle/data/repository/AuthRepositoryImpl.kt +++ b/core/data/src/main/java/com/idle/data/repository/AuthRepositoryImpl.kt @@ -5,8 +5,8 @@ import com.idle.datastore.datasource.UserInfoDataSource import com.idle.domain.model.auth.BusinessRegistrationInfo import com.idle.domain.model.auth.UserType import com.idle.domain.repositorry.AuthRepository -import com.idle.domain.repositorry.TokenRepository import com.idle.domain.repositorry.ProfileRepository +import com.idle.domain.repositorry.TokenRepository import com.idle.network.model.auth.ConfirmAuthCodeRequest import com.idle.network.model.auth.GenerateNewPasswordRequest import com.idle.network.model.auth.SendPhoneRequest @@ -29,18 +29,21 @@ class AuthRepositoryImpl @Inject constructor( private val userInfoDataSource: UserInfoDataSource, private val tokenRepository: TokenRepository, ) : AuthRepository { - override suspend fun sendPhoneNumber(phoneNumber: String): Result = + override suspend fun sendPhoneNumber(phoneNumber: String) { authDataSource.sendPhoneNumber(SendPhoneRequest(phoneNumber)) + } override suspend fun confirmAuthCode( phoneNumber: String, authCode: String, - ): Result = authDataSource.confirmAuthCode( - ConfirmAuthCodeRequest( - phoneNumber = phoneNumber, - authCode = authCode, + ) { + authDataSource.confirmAuthCode( + ConfirmAuthCodeRequest( + phoneNumber = phoneNumber, + authCode = authCode, + ) ) - ) + } override suspend fun signUpCenter( identifier: String, @@ -48,43 +51,38 @@ class AuthRepositoryImpl @Inject constructor( phoneNumber: String, managerName: String, businessRegistrationNumber: String - ): Result = authDataSource.signUpCenter( - SignUpCenterRequest( - identifier = identifier, - password = password, - phoneNumber = phoneNumber, - managerName = managerName, - businessRegistrationNumber = businessRegistrationNumber, + ) { + authDataSource.signUpCenter( + SignUpCenterRequest( + identifier = identifier, + password = password, + phoneNumber = phoneNumber, + managerName = managerName, + businessRegistrationNumber = businessRegistrationNumber, + ) ) - ) + } - override suspend fun signInCenter(identifier: String, password: String): Result = - authDataSource.signInCenter( + override suspend fun signInCenter(identifier: String, password: String) { + val tokenResponse: TokenResponse = authDataSource.signInCenter( SignInCenterRequest(identifier = identifier, password = password) - ).fold( - onSuccess = { tokenResponse -> - coroutineScope { - handleSignInSuccess(tokenResponse, UserType.CENTER.apiValue) - - val profile = profileRepository.getMyCenterProfile().getOrNull() - if (profile != null) { - userInfoDataSource.setUserInfo(profile.toString()) - } - - Result.success(Unit) - } - }, - onFailure = { Result.failure(it) } ) + coroutineScope { + handleSignInSuccess(tokenResponse, UserType.CENTER.apiValue) + val profile = profileRepository.getMyCenterProfile() + userInfoDataSource.setUserInfo(profile.toString()) + } + } - override suspend fun validateIdentifier(identifier: String): Result = + override suspend fun validateIdentifier(identifier: String) { authDataSource.validateIdentifier(identifier) + } override suspend fun validateBusinessRegistrationNumber( businessRegistrationNumber: String, - ): Result = + ): BusinessRegistrationInfo = authDataSource.validateBusinessRegistrationNumber(businessRegistrationNumber) - .mapCatching { it.toVO() } + .toVO() override suspend fun signUpWorker( name: String, @@ -93,93 +91,79 @@ class AuthRepositoryImpl @Inject constructor( phoneNumber: String, roadNameAddress: String, lotNumberAddress: String, - ): Result = authDataSource.signUpWorker( - SignUpWorkerRequest( - name = name, - birthYear = birthYear, - genderType = genderType, - phoneNumber = phoneNumber, - roadNameAddress = roadNameAddress, - lotNumberAddress = lotNumberAddress, + ) { + val tokenResponse: TokenResponse = authDataSource.signUpWorker( + SignUpWorkerRequest( + name = name, + birthYear = birthYear, + genderType = genderType, + phoneNumber = phoneNumber, + roadNameAddress = roadNameAddress, + lotNumberAddress = lotNumberAddress, + ) ) - ).fold( - onSuccess = { tokenResponse -> - coroutineScope { - handleSignInSuccess(tokenResponse, UserType.WORKER.apiValue) - - val profile = profileRepository.getMyWorkerProfile().getOrNull() - if (profile != null) { - userInfoDataSource.setUserInfo(profile.toString()) - } - - Result.success(Unit) - } - }, - onFailure = { Result.failure(it) } - ) + coroutineScope { + handleSignInSuccess(tokenResponse, UserType.WORKER.apiValue) + val profile = profileRepository.getMyWorkerProfile() + userInfoDataSource.setUserInfo(profile.toString()) + } + } override suspend fun signInWorker( phoneNumber: String, authCode: String, - ): Result = authDataSource.signInWorker( - SignInWorkerRequest(phoneNumber = phoneNumber, authCode = authCode) - ).fold( - onSuccess = { tokenResponse -> - coroutineScope { - handleSignInSuccess(tokenResponse, UserType.WORKER.apiValue) - - val updatedProfile = profileRepository.getMyWorkerProfile().getOrNull() - if (updatedProfile != null) { - userInfoDataSource.setUserInfo(updatedProfile.toString()) - } - - Result.success(Unit) - } - }, - onFailure = { Result.failure(it) } - ) - - override suspend fun logoutWorker(): Result { - tokenRepository.deleteDeviceToken(getDeviceToken()) - - return authDataSource.logoutWorker() - .onSuccess { clearUserData() } + ) { + val tokenResponse: TokenResponse = authDataSource.signInWorker( + SignInWorkerRequest(phoneNumber = phoneNumber, authCode = authCode) + ) + coroutineScope { + handleSignInSuccess(tokenResponse, UserType.WORKER.apiValue) + val updatedProfile = profileRepository.getMyWorkerProfile() + userInfoDataSource.setUserInfo(updatedProfile.toString()) + } } - override suspend fun logoutCenter(): Result { + override suspend fun logoutWorker() { tokenRepository.deleteDeviceToken(getDeviceToken()) - - return authDataSource.logoutCenter() - .onSuccess { clearUserData() } + authDataSource.logoutWorker() + clearUserData() } - override suspend fun withdrawalCenter(reason: String, password: String): Result { + override suspend fun logoutCenter() { tokenRepository.deleteDeviceToken(getDeviceToken()) + authDataSource.logoutCenter() + clearUserData() + } - return authDataSource.withdrawalCenter( + override suspend fun withdrawalCenter(reason: String, password: String) { + tokenRepository.deleteDeviceToken(getDeviceToken()) + authDataSource.withdrawalCenter( WithdrawalCenterRequest(reason = reason, password = password) - ).onSuccess { clearUserData() } + ) + clearUserData() } - override suspend fun withdrawalWorker(reason: String): Result { + override suspend fun withdrawalWorker(reason: String) { tokenRepository.deleteDeviceToken(getDeviceToken()) - - return authDataSource.withdrawalWorker(WithdrawalWorkerRequest(reason)) - .onSuccess { clearUserData() } + authDataSource.withdrawalWorker(WithdrawalWorkerRequest(reason)) + clearUserData() } override suspend fun generateNewPassword( newPassword: String, phoneNumber: String - ): Result = authDataSource.generateNewPassword( - GenerateNewPasswordRequest( - newPassword = newPassword, - phoneNumber = phoneNumber + ) { + authDataSource.generateNewPassword( + GenerateNewPasswordRequest( + newPassword = newPassword, + phoneNumber = phoneNumber + ) ) - ) + } - override suspend fun sendCenterVerificationRequest(): Result = + override suspend fun sendCenterVerificationRequest() { authDataSource.sendCenterVerificationRequest() + } private suspend fun handleSignInSuccess( tokenResponse: TokenResponse, diff --git a/core/data/src/main/java/com/idle/data/repository/ChatRepositoryImpl.kt b/core/data/src/main/java/com/idle/data/repository/ChatRepositoryImpl.kt index 4192c9f0..82915c4d 100644 --- a/core/data/src/main/java/com/idle/data/repository/ChatRepositoryImpl.kt +++ b/core/data/src/main/java/com/idle/data/repository/ChatRepositoryImpl.kt @@ -24,27 +24,30 @@ class ChatRepositoryImpl @Inject constructor( private val chatDataSource: ChatDataSource, private val localChatDataSource: LocalChatDataSource, ) : ChatRepository { - override suspend fun connectWebSocket(): Result = chatDataSource.connectWebSocket() + override suspend fun connectWebSocket() { + chatDataSource.connectWebSocket() + } - override suspend fun disconnectWebSocket(): Result = + override suspend fun disconnectWebSocket() { chatDataSource.disconnectWebSocket() + } - override suspend fun retrieveChatRooms(userId: String): Result> = runCatching { - localChatDataSource.getChatRooms(userId) + override suspend fun retrieveChatRooms(userId: String): List { + return localChatDataSource.getChatRooms(userId) } override suspend fun loadChatRooms( userId: String, userType: UserType - ): Result> = runCatching { - val chatRoomsResponse = when (userType) { - UserType.WORKER -> chatDataSource.getWorkerChatRooms() - UserType.CENTER -> chatDataSource.getCenterChatRooms() - }.getOrThrow() - - val chatRooms = chatRoomsResponse.map { - val chatRoom = it.toVO() + ): List { + val response = if (userType == UserType.WORKER) { + chatDataSource.getWorkerChatRooms() + } else { + chatDataSource.getCenterChatRooms() + } + return response.map { dto -> + val chatRoom = dto.toVO() if (!localChatDataSource.isChatRoomExist(chatRoom.id, userId)) { localChatDataSource.insertChatRoom( myId = userId, @@ -53,24 +56,23 @@ class ChatRepositoryImpl @Inject constructor( opponentId = chatRoom.opponentId, lastMessage = chatRoom.lastMessage, lastMessageTime = chatRoom.lastMessageTime, - unReadMessageCount = chatRoom.unReadMessageCount, + unReadMessageCount = chatRoom.unReadMessageCount ) ) } chatRoom } - chatRooms } override suspend fun retrieveChatRoomMessages( roomId: String, myId: String, messageId: String? - ): Result> = runCatching { - localChatDataSource.getMessages( + ): List { + return localChatDataSource.getMessages( roomId = roomId, myId = myId, - lastMessageId = messageId, + lastMessageId = messageId ) } @@ -79,20 +81,21 @@ class ChatRepositoryImpl @Inject constructor( roomId: String, myId: String, messageId: String?, - unReadMessageCount: Int?, - ): Result> = runCatching { + unReadMessageCount: Int? + ): List { if (messageId == null || !localChatDataSource.isMessageExist(roomId, myId, messageId)) { - val response = when (userType) { - UserType.WORKER -> chatDataSource.getWorkerChatRoomMessages(roomId, messageId) - UserType.CENTER -> chatDataSource.getCenterChatRoomMessages(roomId, messageId) - }.getOrThrow() + val response = if (userType == UserType.WORKER) { + chatDataSource.getWorkerChatRoomMessages(roomId, messageId) + } else { + chatDataSource.getCenterChatRoomMessages(roomId, messageId) + } val allMessages = response.chatMessageInfos .sortedBy { it.sequence } .map { it.toVO() } - val messagesToUse = unReadMessageCount?.let { - allMessages.takeLast(it) + val messagesToUse = unReadMessageCount?.let { count -> + allMessages.takeLast(count) } ?: allMessages val maxSeq = localChatDataSource.getMaxLocalSequence(roomId, myId) ?: Int.MIN_VALUE @@ -106,7 +109,7 @@ class ChatRepositoryImpl @Inject constructor( opponentId = if (myId == message.senderId) message.receiverId else message.senderId, lastMessage = message.content, lastMessageTime = message.createdAt, - unReadMessageCount = 1, + unReadMessageCount = 1 ) ) } @@ -116,47 +119,46 @@ class ChatRepositoryImpl @Inject constructor( } } - val readSequence = response.sequence - allMessages.lastOrNull()?.let { - localChatDataSource.readMessages( - roomId = roomId, - myId = myId, - senderId = it.senderId, - sequence = readSequence, - ) + response.sequence.takeIf { it >= 0 }?.let { seq -> + allMessages.lastOrNull()?.let { + localChatDataSource.readMessages( + roomId = roomId, + myId = myId, + senderId = it.senderId, + sequence = seq + ) + } } } - return@runCatching localChatDataSource.getMessages( + return localChatDataSource.getMessages( roomId = roomId, myId = myId, - lastMessageId = messageId, + lastMessageId = messageId ) } override suspend fun generateChatRooms( userType: UserType, - opponentId: String, - ): Result = - runCatching { - when (userType) { - UserType.WORKER -> chatDataSource.generateWorkerChatRoom(opponentId) - UserType.CENTER -> chatDataSource.generateCenterChatRoom(opponentId) - }.mapCatching { - it.toVO() - }.getOrThrow() + opponentId: String + ): String { + val dto = if (userType == UserType.WORKER) { + chatDataSource.generateWorkerChatRoom(opponentId) + } else { + chatDataSource.generateCenterChatRoom(opponentId) } + return dto.toVO() + } - override suspend fun subscribeChatMessage(userId: String, userType: UserType): Flow = - chatDataSource.subscribeChatMessage(userId) - .map { - val message = it.toVO() - + override suspend fun subscribeChatMessage(userId: String, userType: UserType): Flow { + return chatDataSource.subscribeChatMessage(userId) + .map { response -> + val message = response.toVO() when (message) { is ChatMessage -> { if (!localChatDataSource.isChatRoomExist( roomId = message.roomId, - myId = userId, + myId = userId ) ) { localChatDataSource.insertChatRoom( @@ -166,28 +168,26 @@ class ChatRepositoryImpl @Inject constructor( opponentId = if (userId == message.senderId) message.receiverId else message.senderId, lastMessage = message.content, lastMessageTime = message.createdAt, - unReadMessageCount = 1, + unReadMessageCount = 1 ) ) } - localChatDataSource.insertMessage(message, userId) } - is ReadMessage -> { if (message.opponentId != userId) { localChatDataSource.readMessages( roomId = message.chatroomId, myId = userId, senderId = message.opponentId, - sequence = message.sequence, + sequence = message.sequence ) } } } - message - }.retryWhen { cause, attempt -> + } + .retryWhen { cause, attempt -> if (cause is IOException && attempt < MAX_RETRY_ATTEMPTS) { connectWebSocket() delay(calculateBackoffTime(attempt.toInt())) @@ -196,6 +196,7 @@ class ChatRepositoryImpl @Inject constructor( false } } + } override suspend fun sendMessage( chatroomId: String, @@ -203,36 +204,39 @@ class ChatRepositoryImpl @Inject constructor( receiverId: String, senderName: String, content: String, - userType: UserType, - ): Result = chatDataSource.sendMessage( - userType = userType, - sendMessageRequest = SendMessageRequest( - chatroomId = chatroomId, - receiverId = receiverId, - senderName = senderName, - content = content, + userType: UserType + ) { + chatDataSource.sendMessage( + userType = userType, + sendMessageRequest = SendMessageRequest( + chatroomId = chatroomId, + receiverId = receiverId, + senderName = senderName, + content = content + ) ) - ) + } override suspend fun readMessage( chatroomId: String, myId: String, opponentId: String, userType: UserType, - sequence: Int, - ): Result = chatDataSource.readMessage( - userType = userType, - readMessageRequest = ReadMessageRequest( - chatroomId = chatroomId, - opponentId = opponentId, - sequence = sequence, + sequence: Int + ) { + chatDataSource.readMessage( + userType = userType, + readMessageRequest = ReadMessageRequest( + chatroomId = chatroomId, + opponentId = opponentId, + sequence = sequence + ) ) - ).onSuccess { localChatDataSource.readMessages( roomId = chatroomId, myId = myId, senderId = opponentId, - sequence = sequence, + sequence = sequence ) } } diff --git a/core/data/src/main/java/com/idle/data/repository/ConfigRepositoryImpl.kt b/core/data/src/main/java/com/idle/data/repository/ConfigRepositoryImpl.kt index d9bbd202..84872385 100644 --- a/core/data/src/main/java/com/idle/data/repository/ConfigRepositoryImpl.kt +++ b/core/data/src/main/java/com/idle/data/repository/ConfigRepositoryImpl.kt @@ -9,10 +9,8 @@ import javax.inject.Inject class ConfigRepositoryImpl @Inject constructor( private val configDataSource: ConfigDataSource, ) : ConfigRepository { - override suspend fun getForceUpdate(): Result = runCatching { - configDataSource.getReferenceType( - key = ConfigDataSource.FORCE_UPDATE, - defaultValue = ForceUpdateResponse(), - ).toVO() - } + override suspend fun getForceUpdate(): ForceUpdate = configDataSource.getReferenceType( + key = ConfigDataSource.FORCE_UPDATE, + defaultValue = ForceUpdateResponse(), + ).toVO() } diff --git a/core/data/src/main/java/com/idle/data/repository/JobPostingRepositoryImpl.kt b/core/data/src/main/java/com/idle/data/repository/JobPostingRepositoryImpl.kt index 3f0f132e..643435b8 100644 --- a/core/data/src/main/java/com/idle/data/repository/JobPostingRepositoryImpl.kt +++ b/core/data/src/main/java/com/idle/data/repository/JobPostingRepositoryImpl.kt @@ -60,7 +60,7 @@ class JobPostingRepositoryImpl @Inject constructor( applyMethod: List, applyDeadLineType: ApplyDeadlineType, applyDeadline: String?, - ): Result = jobPostingDataSource.postJobPosting( + ) = jobPostingDataSource.postJobPosting( JobPostingRequest( weekdays = weekdays.map { it.name }, startTime = startTime, @@ -113,7 +113,7 @@ class JobPostingRepositoryImpl @Inject constructor( applyMethod: List?, applyDeadLineType: ApplyDeadlineType, applyDeadline: String?, - ): Result = jobPostingDataSource.updateJobPosting( + ) = jobPostingDataSource.updateJobPosting( jobPostingId = jobPostingId, jobPostingRequest = JobPostingRequest( weekdays = weekdays.map { it.name }, @@ -142,83 +142,77 @@ class JobPostingRepositoryImpl @Inject constructor( ) ) - override suspend fun getCenterJobPostingDetail(jobPostingId: String): Result = - jobPostingDataSource.getCenterJobPostingDetail(jobPostingId) - .mapCatching { it.toVO() } + override suspend fun getCenterJobPostingDetail(jobPostingId: String): CenterJobPostingDetail = + jobPostingDataSource.getCenterJobPostingDetail(jobPostingId).toVO() - override suspend fun getWorkerJobPostingDetail(jobPostingId: String): Result = - jobPostingDataSource.getWorkerJobPostingDetail(jobPostingId) - .mapCatching { it.toVO() } + override suspend fun getWorkerJobPostingDetail(jobPostingId: String): WorkerJobPostingDetail = + jobPostingDataSource.getWorkerJobPostingDetail(jobPostingId).toVO() override suspend fun getJobPostings( next: String?, limit: Int - ): Result = jobPostingDataSource.getJobPostings( + ): WorkerJobPostingPage = jobPostingDataSource.getJobPostings( next = next, limit = limit - ).mapCatching { it.toVO() } + ).toVO() override suspend fun getJobPostingsApplied( next: String?, limit: Int - ): Result = jobPostingDataSource.getJobPostingsApplied( + ): WorkerJobPostingPage = jobPostingDataSource.getJobPostingsApplied( next = next, limit = limit - ).mapCatching { it.toVO() } + ).toVO() - override suspend fun getMyFavoritesJobPostings(): Result> = - jobPostingDataSource.getMyFavoriteJobPostings() - .mapCatching { it.toVO() } + override suspend fun getMyFavoritesJobPostings(): List = + jobPostingDataSource.getMyFavoriteJobPostings().toVO() - override suspend fun getMyFavoritesCrawlingJobPostings(): Result> = - jobPostingDataSource.getMyFavoriteCrawlingJobPostings() - .mapCatching { it.toVO() } + override suspend fun getMyFavoritesCrawlingJobPostings(): List = + jobPostingDataSource.getMyFavoriteCrawlingJobPostings().toVO() - override suspend fun getJobPostingsInProgress(): Result> = - jobPostingDataSource.getJobPostingsInProgress().mapCatching { it.toVO() } + override suspend fun getJobPostingsInProgress(): List = + jobPostingDataSource.getJobPostingsInProgress().toVO() - override suspend fun getJobPostingsCompleted(): Result> = - jobPostingDataSource.getJobPostingsCompleted().mapCatching { it.toVO() } + override suspend fun getJobPostingsCompleted(): List = + jobPostingDataSource.getJobPostingsCompleted().toVO() - override suspend fun getApplicantsCount(jobPostingId: String): Result = - jobPostingDataSource.getApplicantCount(jobPostingId).mapCatching { it.applicantCount } + override suspend fun getApplicantsCount(jobPostingId: String) = + jobPostingDataSource.getApplicantCount(jobPostingId).applicantCount override suspend fun applyJobPosting( jobPostingId: String, applyMethod: ApplyMethod, - ): Result = - jobPostingDataSource.applyJobPosting( - ApplyJobPostingRequest(jobPostingId = jobPostingId, applyMethodType = applyMethod.name) - ) + ) = jobPostingDataSource.applyJobPosting( + ApplyJobPostingRequest(jobPostingId = jobPostingId, applyMethodType = applyMethod.name) + ) override suspend fun addFavoriteJobPosting( jobPostingId: String, jobPostingType: JobPostingType, - ): Result = - jobPostingDataSource.addFavoriteJobPosting( - jobPostingId = jobPostingId, - favoriteJobPostingRequest = FavoriteJobPostingRequest(jobPostingType.name), - ) + ) = jobPostingDataSource.addFavoriteJobPosting( + jobPostingId = jobPostingId, + favoriteJobPostingRequest = FavoriteJobPostingRequest(jobPostingType.name), + ) - override suspend fun removeFavoriteJobPosting(jobPostingId: String): Result = + override suspend fun removeFavoriteJobPosting(jobPostingId: String) = jobPostingDataSource.removeFavoriteJobPosting(jobPostingId = jobPostingId) - override suspend fun getApplicants(jobPostingId: String): Result>> = - jobPostingDataSource.getApplicants(jobPostingId).mapCatching { it.toVO() } + override suspend fun getApplicants(jobPostingId: String): Pair> = + jobPostingDataSource.getApplicants(jobPostingId).toVO() - override suspend fun endJobPosting(jobPostingId: String): Result = + override suspend fun endJobPosting(jobPostingId: String) = jobPostingDataSource.endJobPosting(jobPostingId) - override suspend fun deleteJobPosting(jobPostingId: String): Result = + override suspend fun deleteJobPosting(jobPostingId: String) = jobPostingDataSource.deleteJobPosting(jobPostingId) override suspend fun getCrawlingJobPostings( next: String?, limit: Int, distance: Int, - ): Result = - jobPostingDataSource.getCrawlingJobPostings(next, limit, distance).mapCatching { it.toVO() } + ): CrawlingJobPostingPage = + jobPostingDataSource.getCrawlingJobPostings(next, limit, distance).toVO() - override suspend fun getCrawlingJobPostingDetail(jobPostingId: String): Result = - jobPostingDataSource.getCrawlingJobPostingsDetail(jobPostingId).mapCatching { it.toVO() } + override suspend fun getCrawlingJobPostingDetail(jobPostingId: String): CrawlingJobPostingDetail = + jobPostingDataSource.getCrawlingJobPostingsDetail(jobPostingId).toVO() } diff --git a/core/data/src/main/java/com/idle/data/repository/NotificationRepositoryImpl.kt b/core/data/src/main/java/com/idle/data/repository/NotificationRepositoryImpl.kt index 88b96f59..48f542b6 100644 --- a/core/data/src/main/java/com/idle/data/repository/NotificationRepositoryImpl.kt +++ b/core/data/src/main/java/com/idle/data/repository/NotificationRepositoryImpl.kt @@ -11,14 +11,13 @@ class NotificationRepositoryImpl @Inject constructor( override suspend fun getMyNotifications( next: String?, limit: Int - ): Result>> = - notificationDataSource.getMyNotifications(next = next, limit = limit) - .map { it.toVO() } + ): Pair> = + notificationDataSource.getMyNotifications(next = next, limit = limit).toVO() - override suspend fun readNotification(notificationId: String): Result = + override suspend fun readNotification(notificationId: String) = notificationDataSource.readNotification(notificationId) - override suspend fun getUnreadNotificationCount(): Result = + override suspend fun getUnreadNotificationCount(): Int = notificationDataSource.getUnreadNotificationCount() - .mapCatching { it.unreadNotificationCount ?: 0 } + .unreadNotificationCount ?: 0 } diff --git a/core/data/src/main/java/com/idle/data/repository/ProfileRepositoryImpl.kt b/core/data/src/main/java/com/idle/data/repository/ProfileRepositoryImpl.kt index e0bc929c..ca23232d 100644 --- a/core/data/src/main/java/com/idle/data/repository/ProfileRepositoryImpl.kt +++ b/core/data/src/main/java/com/idle/data/repository/ProfileRepositoryImpl.kt @@ -34,51 +34,50 @@ class ProfileRepositoryImpl @Inject constructor( ) : ProfileRepository { override suspend fun getMyUserType() = userInfoDataSource.userType.first() - override suspend fun getMyCenterProfile(): Result = - profileDataSource.getMyCenterProfile() - .mapCatching { it.toVO() } - .onSuccess { - userInfoDataSource.setUserInfo(it.toString()) - Result.success(it) - } + override suspend fun getMyCenterProfile(): CenterProfile { + val centerProfile = profileDataSource.getMyCenterProfile() + .toVO() + + userInfoDataSource.setUserInfo(centerProfile.toString()) + return centerProfile + } - override suspend fun getLocalMyCenterProfile(): Result = + override suspend fun getLocalMyCenterProfile(): CenterProfile = userInfoDataSource.getLocalCenterProfile() - override suspend fun getCenterProfile(centerId: String): Result = - profileDataSource.getCenterProfile(centerId).mapCatching { it.toVO() } + override suspend fun getCenterProfile(centerId: String): CenterProfile = + profileDataSource.getCenterProfile(centerId).toVO() - override suspend fun getMyWorkerProfile(): Result = - profileDataSource.getMyWorkerProfile().mapCatching { it.toVo() } - .onSuccess { - userInfoDataSource.setUserInfo(it.toString()) - Result.success(it) - } + override suspend fun getMyWorkerProfile(): WorkerProfile { + val workerProfile = profileDataSource.getMyWorkerProfile().toVo() - override suspend fun getLocalMyWorkerProfile(): Result = + userInfoDataSource.setUserInfo(workerProfile.toString()) + return workerProfile + } + + override suspend fun getLocalMyWorkerProfile(): WorkerProfile = userInfoDataSource.getLocalWorkerProfile() - override suspend fun getWorkerProfile(workerId: String): Result = - profileDataSource.getWorkerProfile(workerId).mapCatching { it.toVo() } + override suspend fun getWorkerProfile(workerId: String): WorkerProfile = + profileDataSource.getWorkerProfile(workerId).toVo() override suspend fun updateCenterProfile( officeNumber: String, introduce: String?, - ): Result = profileDataSource.updateMyCenterProfile( - UpdateCenterProfileRequest(officeNumber = officeNumber, introduce = introduce) - ).onSuccess { - val updatedProfile = getMyCenterProfile().getOrNull() - if (updatedProfile != null) { - userInfoDataSource.setUserInfo(updatedProfile.toString()) - } + ) { + profileDataSource.updateMyCenterProfile( + UpdateCenterProfileRequest(officeNumber = officeNumber, introduce = introduce) + ) + + val updatedProfile = getMyCenterProfile() + userInfoDataSource.setUserInfo(updatedProfile.toString()) } - override suspend fun getWorkerId(): Result = profileDataSource.getWorkerId() - .mapCatching { it.carerId } + override suspend fun getWorkerId(): String = profileDataSource.getWorkerId() + .carerId - override suspend fun getCenterStatus(): Result = - profileDataSource.getCenterStatus() - .mapCatching { it.toVO() } + override suspend fun getCenterStatus(): CenterRegistrationStatus = + profileDataSource.getCenterStatus().toVO() override suspend fun updateWorkerProfile( experienceYear: Int?, @@ -87,20 +86,20 @@ class ProfileRepositoryImpl @Inject constructor( jobSearchStatus: JobSearchStatus, introduce: String?, speciality: String - ): Result = profileDataSource.updateWorkerProfile( - UpdateWorkerProfileRequest( - experienceYear = experienceYear, - roadNameAddress = roadNameAddress, - lotNumberAddress = lotNumberAddress, - jobSearchStatus = jobSearchStatus.name, - introduce = introduce, - speciality = speciality + ) { + profileDataSource.updateWorkerProfile( + UpdateWorkerProfileRequest( + experienceYear = experienceYear, + roadNameAddress = roadNameAddress, + lotNumberAddress = lotNumberAddress, + jobSearchStatus = jobSearchStatus.name, + introduce = introduce, + speciality = speciality + ) ) - ).onSuccess { - val updatedProfile = getMyWorkerProfile().getOrNull() - if (updatedProfile != null) { - userInfoDataSource.setUserInfo(updatedProfile.toString()) - } + + val updatedProfile = getMyWorkerProfile() + userInfoDataSource.setUserInfo(updatedProfile.toString()) } override suspend fun registerCenterProfile( @@ -110,7 +109,7 @@ class ProfileRepositoryImpl @Inject constructor( lotNumberAddress: String, officeNumber: String, roadNameAddress: String - ): Result = profileDataSource.registerCenterProfile( + ) = profileDataSource.registerCenterProfile( RegisterCenterProfileRequest( centerName = centerName, detailedAddress = detailedAddress, @@ -126,7 +125,7 @@ class ProfileRepositoryImpl @Inject constructor( imageFileUri: String, reqWidth: Int, reqHeight: Int - ): Result = runCatching { + ) { val resizeImage = resizeImage( context = context, uri = imageFileUri.toUri(), @@ -142,30 +141,30 @@ class ProfileRepositoryImpl @Inject constructor( val profileImageUploadUrlResponse = getProfileImageUploadUrl( userType = userType, imageFileExtension = imageFormat.name, - ).getOrThrow() + ) uploadProfileImage( uploadUrl = profileImageUploadUrlResponse.uploadUrl, imageFileExtension = profileImageUploadUrlResponse.imageFileExtension, imageInputStream = inputStream, - ).getOrThrow() + ) callbackImageUpload( userType = userType, imageId = profileImageUploadUrlResponse.imageId, imageFileExtension = profileImageUploadUrlResponse.imageFileExtension - ).getOrThrow() + ) when (userType) { UserType.CENTER.apiValue -> { - val updatedProfile = getMyCenterProfile().getOrThrow() + val updatedProfile = getMyCenterProfile() .copy(profileImageUrl = imageFileUri) userInfoDataSource.setUserInfo(updatedProfile.toString()) } UserType.WORKER.apiValue -> { - val updatedProfile = getMyWorkerProfile().getOrThrow() + val updatedProfile = getMyWorkerProfile() .copy(profileImageUrl = imageFileUri) userInfoDataSource.setUserInfo(updatedProfile.toString()) @@ -237,14 +236,14 @@ class ProfileRepositoryImpl @Inject constructor( private suspend fun getProfileImageUploadUrl( userType: String, imageFileExtension: String - ): Result = + ): UploadProfileImageUrlResponse = profileDataSource.getProfileImageUploadUrl(userType, imageFileExtension) private suspend fun uploadProfileImage( uploadUrl: String, imageFileExtension: String, imageInputStream: InputStream, - ): Result = profileDataSource.uploadProfileImage( + ) = profileDataSource.uploadProfileImage( uploadUrl = uploadUrl, imageFileExtension = imageFileExtension, imageInputStream = imageInputStream, @@ -254,7 +253,7 @@ class ProfileRepositoryImpl @Inject constructor( userType: String, imageId: String, imageFileExtension: String - ): Result = profileDataSource.callbackImageUpload( + ) = profileDataSource.callbackImageUpload( userType = userType, callbackImageUploadRequest = CallbackImageUploadRequest( imageId = imageId, diff --git a/core/data/src/main/java/com/idle/data/repository/TokenRepositoryImpl.kt b/core/data/src/main/java/com/idle/data/repository/TokenRepositoryImpl.kt index ecaa9cf3..c308186e 100644 --- a/core/data/src/main/java/com/idle/data/repository/TokenRepositoryImpl.kt +++ b/core/data/src/main/java/com/idle/data/repository/TokenRepositoryImpl.kt @@ -18,7 +18,7 @@ class TokenRepositoryImpl @Inject constructor( tokenDataSource.accessToken.first() } - override suspend fun postDeviceToken(deviceToken: String, userType: String): Result = + override suspend fun postDeviceToken(deviceToken: String, userType: String) = notificationDataSource.postFCMToken( PostFcmTokenRequest( deviceToken = deviceToken, @@ -26,6 +26,6 @@ class TokenRepositoryImpl @Inject constructor( ) ) - override suspend fun deleteDeviceToken(deviceToken: String): Result = + override suspend fun deleteDeviceToken(deviceToken: String) = notificationDataSource.deleteFCMToken(DeleteFcmTokenRequest(deviceToken)) } diff --git a/core/datastore/src/main/java/com/idle/datastore/datasource/UserInfoDataSource.kt b/core/datastore/src/main/java/com/idle/datastore/datasource/UserInfoDataSource.kt index 5328b23e..11908800 100644 --- a/core/datastore/src/main/java/com/idle/datastore/datasource/UserInfoDataSource.kt +++ b/core/datastore/src/main/java/com/idle/datastore/datasource/UserInfoDataSource.kt @@ -37,7 +37,7 @@ class UserInfoDataSource @Inject constructor( dataStore.clear(USER_INFO) } - suspend fun getLocalCenterProfile(): Result = runCatching { + suspend fun getLocalCenterProfile(): CenterProfile { val userInfoString = userInfo.first().takeIf { it.isNotBlank() } ?: throw NullPointerException("Missing UserInfo") @@ -54,7 +54,7 @@ class UserInfoDataSource @Inject constructor( key to value } - CenterProfile( + return CenterProfile( centerId = properties["centerId"] ?: throw NullPointerException("Missing CenterId"), centerName = properties["centerName"] ?: throw NullPointerException("Missing centerName"), @@ -75,7 +75,7 @@ class UserInfoDataSource @Inject constructor( ) } - suspend fun getLocalWorkerProfile(): Result = runCatching { + suspend fun getLocalWorkerProfile(): WorkerProfile { val userInfoString = userInfo.first().takeIf { it.isNotBlank() } ?: throw NullPointerException("Missing UserInfo") @@ -92,7 +92,7 @@ class UserInfoDataSource @Inject constructor( key to value } - WorkerProfile( + return WorkerProfile( workerId = properties["workerId"] ?: throw NullPointerException("Missing workerId"), workerName = properties["workerName"] ?: throw NullPointerException("Missing workerName"), diff --git a/core/domain/src/main/kotlin/com/idle/domain/repositorry/AuthRepository.kt b/core/domain/src/main/kotlin/com/idle/domain/repositorry/AuthRepository.kt index 9f770a6a..8bcdd791 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/repositorry/AuthRepository.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/repositorry/AuthRepository.kt @@ -3,12 +3,11 @@ package com.idle.domain.repositorry import com.idle.domain.model.auth.BusinessRegistrationInfo interface AuthRepository { - suspend fun sendPhoneNumber(phoneNumber: String): Result - suspend fun confirmAuthCode(phoneNumber: String, authCode: String): Result - - suspend fun validateIdentifier(identifier: String): Result + suspend fun sendPhoneNumber(phoneNumber: String) + suspend fun confirmAuthCode(phoneNumber: String, authCode: String) + suspend fun validateIdentifier(identifier: String) suspend fun validateBusinessRegistrationNumber(businessRegistrationNumber: String): - Result + BusinessRegistrationInfo suspend fun signUpWorker( name: String, @@ -17,7 +16,7 @@ interface AuthRepository { phoneNumber: String, roadNameAddress: String, lotNumberAddress: String, - ): Result + ) suspend fun signUpCenter( identifier: String, @@ -25,17 +24,15 @@ interface AuthRepository { phoneNumber: String, managerName: String, businessRegistrationNumber: String, - ): Result - - suspend fun signInWorker(phoneNumber: String, authCode: String): Result - suspend fun signInCenter(identifier: String, password: String): Result - - suspend fun logoutWorker(): Result - suspend fun logoutCenter(): Result + ) - suspend fun withdrawalCenter(reason: String, password: String): Result - suspend fun withdrawalWorker(reason: String): Result + suspend fun signInWorker(phoneNumber: String, authCode: String) + suspend fun signInCenter(identifier: String, password: String) + suspend fun logoutWorker() + suspend fun logoutCenter() - suspend fun generateNewPassword(newPassword: String, phoneNumber: String): Result - suspend fun sendCenterVerificationRequest(): Result + suspend fun withdrawalCenter(reason: String, password: String) + suspend fun withdrawalWorker(reason: String) + suspend fun generateNewPassword(newPassword: String, phoneNumber: String) + suspend fun sendCenterVerificationRequest() } diff --git a/core/domain/src/main/kotlin/com/idle/domain/repositorry/ChatRepository.kt b/core/domain/src/main/kotlin/com/idle/domain/repositorry/ChatRepository.kt index 5de82b42..f4ec2b3d 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/repositorry/ChatRepository.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/repositorry/ChatRepository.kt @@ -8,20 +8,19 @@ import com.idle.domain.model.chat.Message import kotlinx.coroutines.flow.Flow interface ChatRepository { - suspend fun connectWebSocket(): Result - suspend fun disconnectWebSocket(): Result - - suspend fun retrieveChatRooms(userId: String): Result> + suspend fun connectWebSocket() + suspend fun disconnectWebSocket() + suspend fun retrieveChatRooms(userId: String): List suspend fun loadChatRooms( userId: String, userType: UserType - ): Result> + ): List suspend fun retrieveChatRoomMessages( roomId: String, myId: String, messageId: String?, - ): Result> + ): List suspend fun getChatRoomMessages( userType: UserType, @@ -29,12 +28,12 @@ interface ChatRepository { myId: String, messageId: String?, unReadMessageCount: Int?, - ): Result> + ): List suspend fun generateChatRooms( userType: UserType, opponentId: String, - ): Result + ): String suspend fun subscribeChatMessage( userId: String, @@ -48,7 +47,7 @@ interface ChatRepository { senderName: String, content: String, userType: UserType, - ): Result + ) suspend fun readMessage( chatroomId: String, @@ -56,5 +55,5 @@ interface ChatRepository { opponentId: String, userType: UserType, sequence: Int, - ): Result + ) } diff --git a/core/domain/src/main/kotlin/com/idle/domain/repositorry/ConfigRepository.kt b/core/domain/src/main/kotlin/com/idle/domain/repositorry/ConfigRepository.kt index 060afc38..b35b1ef6 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/repositorry/ConfigRepository.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/repositorry/ConfigRepository.kt @@ -3,5 +3,5 @@ package com.idle.domain.repositorry import com.idle.domain.model.config.ForceUpdate interface ConfigRepository { - suspend fun getForceUpdate(): Result + suspend fun getForceUpdate(): ForceUpdate } diff --git a/core/domain/src/main/kotlin/com/idle/domain/repositorry/JobPostingRepository.kt b/core/domain/src/main/kotlin/com/idle/domain/repositorry/JobPostingRepository.kt index 73b88659..40e5aee3 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/repositorry/JobPostingRepository.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/repositorry/JobPostingRepository.kt @@ -47,7 +47,7 @@ interface JobPostingRepository { applyMethod: List, applyDeadLineType: ApplyDeadlineType, applyDeadline: String?, - ): Result + ) suspend fun updateJobPosting( jobPostingId: String, @@ -74,52 +74,51 @@ interface JobPostingRepository { applyMethod: List?, applyDeadLineType: ApplyDeadlineType, applyDeadline: String?, - ): Result + ) - suspend fun getCenterJobPostingDetail(jobPostingId: String): Result + suspend fun getCenterJobPostingDetail(jobPostingId: String): CenterJobPostingDetail - suspend fun getWorkerJobPostingDetail(jobPostingId: String): Result + suspend fun getWorkerJobPostingDetail(jobPostingId: String): WorkerJobPostingDetail suspend fun getJobPostings( next: String?, limit: Int = 10, - ): Result + ): WorkerJobPostingPage suspend fun getJobPostingsApplied( next: String?, limit: Int = 10, - ): Result + ): WorkerJobPostingPage - suspend fun getMyFavoritesJobPostings(): Result> + suspend fun getMyFavoritesJobPostings(): List - suspend fun getMyFavoritesCrawlingJobPostings(): Result> + suspend fun getMyFavoritesCrawlingJobPostings(): List - suspend fun getJobPostingsInProgress(): Result> + suspend fun getJobPostingsInProgress(): List - suspend fun getJobPostingsCompleted(): Result> + suspend fun getJobPostingsCompleted(): List - suspend fun getApplicantsCount(jobPostingId: String): Result + suspend fun getApplicantsCount(jobPostingId: String): Int - suspend fun applyJobPosting(jobPostingId: String, applyMethod: ApplyMethod): Result + suspend fun applyJobPosting(jobPostingId: String, applyMethod: ApplyMethod) suspend fun addFavoriteJobPosting( jobPostingId: String, jobPostingType: JobPostingType, - ): Result + ) - suspend fun removeFavoriteJobPosting(jobPostingId: String): Result + suspend fun removeFavoriteJobPosting(jobPostingId: String) - suspend fun getApplicants(jobPostingId: String): Result>> + suspend fun getApplicants(jobPostingId: String): Pair> - suspend fun endJobPosting(jobPostingId: String): Result - - suspend fun deleteJobPosting(jobPostingId: String): Result + suspend fun endJobPosting(jobPostingId: String) + suspend fun deleteJobPosting(jobPostingId: String) suspend fun getCrawlingJobPostings( next: String?, limit: Int = 10, distance: Int = 15, - ): Result + ): CrawlingJobPostingPage - suspend fun getCrawlingJobPostingDetail(jobPostingId: String): Result + suspend fun getCrawlingJobPostingDetail(jobPostingId: String): CrawlingJobPostingDetail } diff --git a/core/domain/src/main/kotlin/com/idle/domain/repositorry/NotificationRepository.kt b/core/domain/src/main/kotlin/com/idle/domain/repositorry/NotificationRepository.kt index 1890d778..ee1ab3fd 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/repositorry/NotificationRepository.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/repositorry/NotificationRepository.kt @@ -6,8 +6,8 @@ interface NotificationRepository { suspend fun getMyNotifications( next: String?, limit: Int = 10, - ): Result>> + ): Pair> - suspend fun readNotification(notificationId: String): Result - suspend fun getUnreadNotificationCount(): Result + suspend fun readNotification(notificationId: String) + suspend fun getUnreadNotificationCount(): Int } diff --git a/core/domain/src/main/kotlin/com/idle/domain/repositorry/ProfileRepository.kt b/core/domain/src/main/kotlin/com/idle/domain/repositorry/ProfileRepository.kt index b294edf3..c9a391a4 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/repositorry/ProfileRepository.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/repositorry/ProfileRepository.kt @@ -7,21 +7,15 @@ import com.idle.domain.model.profile.WorkerProfile interface ProfileRepository { suspend fun getMyUserType(): String - - suspend fun getMyCenterProfile(): Result - - suspend fun getLocalMyCenterProfile(): Result - - suspend fun getCenterProfile(centerId: String): Result - - suspend fun getMyWorkerProfile(): Result - - suspend fun getLocalMyWorkerProfile(): Result - - suspend fun getWorkerProfile(workerId: String): Result - - suspend fun updateCenterProfile(officeNumber: String, introduce: String?): Result - + suspend fun getMyCenterProfile(): CenterProfile + suspend fun getLocalMyCenterProfile(): CenterProfile + suspend fun getCenterProfile(centerId: String): CenterProfile + suspend fun getMyWorkerProfile(): WorkerProfile + suspend fun getLocalMyWorkerProfile(): WorkerProfile + suspend fun getWorkerProfile(workerId: String): WorkerProfile + suspend fun updateCenterProfile(officeNumber: String, introduce: String?) + suspend fun getWorkerId(): String + suspend fun getCenterStatus(): CenterRegistrationStatus suspend fun updateWorkerProfile( experienceYear: Int?, roadNameAddress: String, @@ -29,7 +23,7 @@ interface ProfileRepository { jobSearchStatus: JobSearchStatus, introduce: String?, speciality: String, - ): Result + ) suspend fun registerCenterProfile( centerName: String, @@ -38,16 +32,12 @@ interface ProfileRepository { lotNumberAddress: String, officeNumber: String, roadNameAddress: String, - ): Result + ) suspend fun updateProfileImage( userType: String, imageFileUri: String, reqWidth: Int, reqHeight: Int - ): Result - - suspend fun getWorkerId(): Result - - suspend fun getCenterStatus(): Result + ) } diff --git a/core/domain/src/main/kotlin/com/idle/domain/repositorry/TokenRepository.kt b/core/domain/src/main/kotlin/com/idle/domain/repositorry/TokenRepository.kt index 152ad3bf..d5e02cfd 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/repositorry/TokenRepository.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/repositorry/TokenRepository.kt @@ -2,6 +2,6 @@ package com.idle.domain.repositorry interface TokenRepository { suspend fun getAccessToken(): String - suspend fun postDeviceToken(deviceToken: String, userType: String): Result - suspend fun deleteDeviceToken(deviceToken: String): Result + suspend fun postDeviceToken(deviceToken: String, userType: String) + suspend fun deleteDeviceToken(deviceToken: String) } diff --git a/core/domain/src/main/kotlin/com/idle/domain/usecase/chat/GetChatRoomsUseCase.kt b/core/domain/src/main/kotlin/com/idle/domain/usecase/chat/GetChatRoomsUseCase.kt index 7783b9fa..02736b69 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/chat/GetChatRoomsUseCase.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/usecase/chat/GetChatRoomsUseCase.kt @@ -3,9 +3,6 @@ package com.idle.domain.usecase.chat import com.idle.domain.model.auth.UserType import com.idle.domain.model.chat.ChatRoom import com.idle.domain.model.chat.ChatRoomWithOpponentInfo -import com.idle.domain.model.profile.CenterProfile -import com.idle.domain.model.profile.Profile -import com.idle.domain.model.profile.WorkerProfile import com.idle.domain.repositorry.ChatRepository import com.idle.domain.repositorry.ProfileRepository import kotlinx.coroutines.async @@ -20,40 +17,39 @@ class GetChatRoomsUseCase @Inject constructor( suspend operator fun invoke( userType: UserType, userId: String, - ): Result> = runCatching { - val chatRooms = chatRepository.retrieveChatRooms(userId).getOrThrow() + ): List = coroutineScope { + // 로컬 저장소에서 채팅 방 목록 조회 + val chatRooms: List = chatRepository.retrieveChatRooms(userId) - coroutineScope { - val opponentProfiles = chatRooms.map { chatRoom -> - async { - when (userType) { - UserType.CENTER -> - profileRepository.getWorkerProfile(chatRoom.opponentId).getOrThrow() + val opponentProfiles = chatRooms.map { chatRoom -> + async { + when (userType) { + UserType.CENTER -> + profileRepository.getWorkerProfile(chatRoom.opponentId) - UserType.WORKER -> - profileRepository.getCenterProfile(chatRoom.opponentId).getOrThrow() - } + UserType.WORKER -> + profileRepository.getCenterProfile(chatRoom.opponentId) } - }.awaitAll() + } + }.awaitAll() - chatRooms.zip(opponentProfiles) { chatRoom, profile -> - mapToRoomWithOpponentInfo(chatRoom, profile) - }.sortedBy { it.lastMessageTime } + // 채팅 방과 상대 프로필을 결합하여 UI용 모델 생성 + chatRooms.zip(opponentProfiles) { chatRoom, profile -> + mapToRoomWithOpponentInfo(chatRoom, profile) } + .sortedBy { it.lastMessageTime } } private fun mapToRoomWithOpponentInfo( chatRoom: ChatRoom, - profile: Profile, + profile: com.idle.domain.model.profile.Profile, ): ChatRoomWithOpponentInfo { val (opponentName, profileUrl) = when (profile) { - is WorkerProfile -> { + is com.idle.domain.model.profile.WorkerProfile -> profile.workerName to profile.profileImageUrl - } - is CenterProfile -> { + is com.idle.domain.model.profile.CenterProfile -> profile.centerName to profile.profileImageUrl - } } return ChatRoomWithOpponentInfo( diff --git a/core/domain/src/main/kotlin/com/idle/domain/usecase/jobposting/GetJobPostingsInProgressUseCase.kt b/core/domain/src/main/kotlin/com/idle/domain/usecase/jobposting/GetJobPostingsInProgressUseCase.kt index 0ccbff94..87dba94f 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/jobposting/GetJobPostingsInProgressUseCase.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/usecase/jobposting/GetJobPostingsInProgressUseCase.kt @@ -9,16 +9,14 @@ class GetJobPostingsInProgressUseCase @Inject constructor( private val jobPostingRepository: JobPostingRepository, ) { suspend operator fun invoke() = coroutineScope { - val jobPosting = jobPostingRepository.getJobPostingsInProgress() - jobPosting.mapCatching { jobPostings -> - val deferredResults = jobPostings.map { jobPosting -> - async { - val applicantCount = jobPostingRepository.getApplicantsCount(jobPosting.id).getOrThrow() - jobPosting.copy(applicantCount = applicantCount) - } + val jobPostings = jobPostingRepository.getJobPostingsInProgress() + val deferredResults = jobPostings.map { posting -> + async { + val applicantCount = jobPostingRepository.getApplicantsCount(posting.id) + posting.copy(applicantCount = applicantCount) } - - deferredResults.map { it.await() } } + + deferredResults.map { it.await() } } } diff --git a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/GetMyCenterProfileUseCase.kt b/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/GetMyCenterProfileUseCase.kt index cd5e66b2..681023f5 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/GetMyCenterProfileUseCase.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/GetMyCenterProfileUseCase.kt @@ -7,9 +7,9 @@ import javax.inject.Inject class GetMyCenterProfileUseCase @Inject constructor( private val profileRepository: ProfileRepository ) { - suspend operator fun invoke(): Result { - return profileRepository.getLocalMyCenterProfile().recoverCatching { - profileRepository.getMyCenterProfile().getOrThrow() - } + suspend operator fun invoke(): CenterProfile = try { + profileRepository.getLocalMyCenterProfile() + } catch (e: Exception) { + profileRepository.getMyCenterProfile() } } diff --git a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/GetMyWorkerProfileUseCase.kt b/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/GetMyWorkerProfileUseCase.kt index 20da3252..5a2faa38 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/GetMyWorkerProfileUseCase.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/GetMyWorkerProfileUseCase.kt @@ -7,9 +7,9 @@ import javax.inject.Inject class GetMyWorkerProfileUseCase @Inject constructor( private val profileRepository: ProfileRepository ) { - suspend operator fun invoke(): Result { - return profileRepository.getLocalMyWorkerProfile().recoverCatching { - profileRepository.getMyWorkerProfile().getOrThrow() - } + suspend operator fun invoke(): WorkerProfile = try { + profileRepository.getLocalMyWorkerProfile() + } catch (e: Exception) { + profileRepository.getMyWorkerProfile() } } diff --git a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/RegisterCenterProfileUseCase.kt b/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/RegisterCenterProfileUseCase.kt index 956f064b..d996baaf 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/RegisterCenterProfileUseCase.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/RegisterCenterProfileUseCase.kt @@ -17,34 +17,32 @@ class RegisterCenterProfileUseCase @Inject constructor( officeNumber: String, roadNameAddress: String, imageFileUri: String?, - ) = runCatching { - coroutineScope { - val registerProfileJob = launch { - profileRepository.registerCenterProfile( - centerName = centerName, - detailedAddress = detailedAddress, - introduce = introduce, - lotNumberAddress = lotNumberAddress, - officeNumber = officeNumber, - roadNameAddress = roadNameAddress - ).getOrThrow() - } - - val updateProfileImageJob = imageFileUri?.let { uri -> - if (uri.startsWith("content://")) { - launch { - profileRepository.updateProfileImage( - userType = UserType.CENTER.apiValue, - imageFileUri = uri, - reqWidth = 1340, - reqHeight = 1016, - ).getOrThrow() - } - } else null - } + ) = coroutineScope { + val registerProfileJob = launch { + profileRepository.registerCenterProfile( + centerName = centerName, + detailedAddress = detailedAddress, + introduce = introduce, + lotNumberAddress = lotNumberAddress, + officeNumber = officeNumber, + roadNameAddress = roadNameAddress + ) + } - registerProfileJob.join() - updateProfileImageJob?.join() + val updateProfileImageJob = imageFileUri?.let { uri -> + if (uri.startsWith("content://")) { + launch { + profileRepository.updateProfileImage( + userType = UserType.CENTER.apiValue, + imageFileUri = uri, + reqWidth = 1340, + reqHeight = 1016, + ) + } + } else null } + + registerProfileJob.join() + updateProfileImageJob?.join() } } diff --git a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/UpdateCenterProfileUseCase.kt b/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/UpdateCenterProfileUseCase.kt index 6325b910..90b10367 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/UpdateCenterProfileUseCase.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/UpdateCenterProfileUseCase.kt @@ -13,30 +13,28 @@ class UpdateCenterProfileUseCase @Inject constructor( officeNumber: String, introduce: String?, imageFileUri: String?, - ): Result = runCatching { - coroutineScope { - val updateProfileJob = launch { - profileRepository.updateCenterProfile( - officeNumber = officeNumber, - introduce = introduce, - ).getOrThrow() - } - - val updateProfileImageJob = imageFileUri?.let { uri -> - if (uri.startsWith("content://")) { - launch { - profileRepository.updateProfileImage( - userType = UserType.CENTER.apiValue, - imageFileUri = uri, - reqWidth = 1340, - reqHeight = 1016, - ).getOrThrow() - } - } else null - } + ) = coroutineScope { + val updateProfileJob = launch { + profileRepository.updateCenterProfile( + officeNumber = officeNumber, + introduce = introduce, + ) + } - updateProfileJob.join() - updateProfileImageJob?.join() + val updateProfileImageJob = imageFileUri?.let { uri -> + if (uri.startsWith("content://")) { + launch { + profileRepository.updateProfileImage( + userType = UserType.CENTER.apiValue, + imageFileUri = uri, + reqWidth = 1340, + reqHeight = 1016, + ) + } + } else null } + + updateProfileJob.join() + updateProfileImageJob?.join() } } diff --git a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/UpdateWorkerProfileUseCase.kt b/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/UpdateWorkerProfileUseCase.kt index c02f1f33..5f312f27 100644 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/UpdateWorkerProfileUseCase.kt +++ b/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/UpdateWorkerProfileUseCase.kt @@ -18,34 +18,32 @@ class UpdateWorkerProfileUseCase @Inject constructor( speciality: String, jobSearchStatus: JobSearchStatus, imageFileUri: String?, - ) = runCatching { - coroutineScope { - val updateProfileJob = launch { - profileRepository.updateWorkerProfile( - experienceYear = experienceYear, - roadNameAddress = roadNameAddress, - lotNumberAddress = lotNumberAddress, - jobSearchStatus = jobSearchStatus, - introduce = introduce, - speciality = speciality - ).getOrThrow() - } - - val updateProfileImageJob = imageFileUri?.let { uri -> - if (uri.startsWith("content://")) { - launch { - profileRepository.updateProfileImage( - userType = UserType.WORKER.apiValue, - imageFileUri = uri, - reqWidth = 384, - reqHeight = 384, - ).getOrThrow() - } - } else null - } + ) = coroutineScope { + val updateProfileJob = launch { + profileRepository.updateWorkerProfile( + experienceYear = experienceYear, + roadNameAddress = roadNameAddress, + lotNumberAddress = lotNumberAddress, + jobSearchStatus = jobSearchStatus, + introduce = introduce, + speciality = speciality + ) + } - updateProfileJob.join() - updateProfileImageJob?.join() + val updateProfileImageJob = imageFileUri?.let { uri -> + if (uri.startsWith("content://")) { + launch { + profileRepository.updateProfileImage( + userType = UserType.WORKER.apiValue, + imageFileUri = uri, + reqWidth = 384, + reqHeight = 384, + ) + } + } else null } + + updateProfileJob.join() + updateProfileImageJob?.join() } } diff --git a/core/network/src/main/java/com/idle/network/authenticator/CareAuthenticator.kt b/core/network/src/main/java/com/idle/network/authenticator/CareAuthenticator.kt index 1ede0560..168121fb 100644 --- a/core/network/src/main/java/com/idle/network/authenticator/CareAuthenticator.kt +++ b/core/network/src/main/java/com/idle/network/authenticator/CareAuthenticator.kt @@ -46,12 +46,16 @@ class CareAuthenticator @Inject constructor( return null } - val token = runBlocking { - lock.withLock { - authApi.get().refreshToken(RefreshTokenRequest(tokenManager.getRefreshToken())) - .onResponse() + val token = try { + runBlocking { + lock.withLock { + authApi.get().refreshToken(RefreshTokenRequest(tokenManager.getRefreshToken())) + .onResponse() + } } - }.getOrNull() ?: return null + } catch (e: Exception) { + return null + } runBlocking { val job = launch { tokenManager.setRefreshToken(token.refreshToken) } diff --git a/core/network/src/main/java/com/idle/network/source/AuthDataSource.kt b/core/network/src/main/java/com/idle/network/source/AuthDataSource.kt index 1c91c92b..26c82449 100644 --- a/core/network/src/main/java/com/idle/network/source/AuthDataSource.kt +++ b/core/network/src/main/java/com/idle/network/source/AuthDataSource.kt @@ -13,7 +13,7 @@ import com.idle.network.model.auth.SignUpWorkerRequest import com.idle.network.model.auth.WithdrawalCenterRequest import com.idle.network.model.auth.WithdrawalWorkerRequest import com.idle.network.model.token.TokenResponse -import com.idle.network.util.safeApiCall +import com.idle.network.util.onResponse import kotlinx.coroutines.suspendCancellableCoroutine import javax.inject.Inject import javax.inject.Singleton @@ -25,48 +25,48 @@ class AuthDataSource @Inject constructor( private val authApi: AuthApi, private val firebaseMessaging: FirebaseMessaging, ) { - suspend fun sendPhoneNumber(sendPhoneRequest: SendPhoneRequest): Result = - safeApiCall { authApi.sendPhoneNumber(sendPhoneRequest) } + suspend fun sendPhoneNumber(sendPhoneRequest: SendPhoneRequest): Unit = + authApi.sendPhoneNumber(sendPhoneRequest).onResponse() - suspend fun confirmAuthCode(confirmAuthCodeRequest: ConfirmAuthCodeRequest): Result = - safeApiCall { authApi.confirmAuthCode(confirmAuthCodeRequest) } + suspend fun confirmAuthCode(confirmAuthCodeRequest: ConfirmAuthCodeRequest): Unit = + authApi.confirmAuthCode(confirmAuthCodeRequest).onResponse() - suspend fun signUpCenter(signUpCenterRequest: SignUpCenterRequest): Result = - safeApiCall { authApi.signUpCenter(signUpCenterRequest) } + suspend fun signUpCenter(signUpCenterRequest: SignUpCenterRequest): Unit = + authApi.signUpCenter(signUpCenterRequest).onResponse() - suspend fun signInCenter(signInCenterRequest: SignInCenterRequest): Result = - safeApiCall { authApi.signInCenter(signInCenterRequest) } + suspend fun signInCenter(signInCenterRequest: SignInCenterRequest): TokenResponse = + authApi.signInCenter(signInCenterRequest).onResponse() - suspend fun signUpWorker(signUpWorkerRequest: SignUpWorkerRequest): Result = - safeApiCall { authApi.signUpWorker(signUpWorkerRequest) } + suspend fun signUpWorker(signUpWorkerRequest: SignUpWorkerRequest): TokenResponse = + authApi.signUpWorker(signUpWorkerRequest).onResponse() - suspend fun signInWorker(signInWorkerRequest: SignInWorkerRequest): Result = - safeApiCall { authApi.signInWorker(signInWorkerRequest) } + suspend fun signInWorker(signInWorkerRequest: SignInWorkerRequest): TokenResponse = + authApi.signInWorker(signInWorkerRequest).onResponse() - suspend fun logoutWorker(): Result = safeApiCall { authApi.logoutWorker() } + suspend fun logoutWorker(): Unit = authApi.logoutWorker().onResponse() - suspend fun logoutCenter(): Result = safeApiCall { authApi.logoutCenter() } + suspend fun logoutCenter(): Unit = authApi.logoutCenter().onResponse() - suspend fun withdrawalCenter(withdrawalCenterRequest: WithdrawalCenterRequest): Result = - safeApiCall { authApi.withdrawalCenter(withdrawalCenterRequest) } + suspend fun withdrawalCenter(withdrawalCenterRequest: WithdrawalCenterRequest): Unit = + authApi.withdrawalCenter(withdrawalCenterRequest).onResponse() - suspend fun withdrawalWorker(withdrawalWorkerRequest: WithdrawalWorkerRequest): Result = - safeApiCall { authApi.withdrawalWorker(withdrawalWorkerRequest) } + suspend fun withdrawalWorker(withdrawalWorkerRequest: WithdrawalWorkerRequest): Unit = + authApi.withdrawalWorker(withdrawalWorkerRequest).onResponse() - suspend fun validateIdentifier(identifier: String): Result = - safeApiCall { authApi.validateIdentifier(identifier) } + suspend fun validateIdentifier(identifier: String): Unit = + authApi.validateIdentifier(identifier).onResponse() suspend fun validateBusinessRegistrationNumber( businessRegistrationNumber: String - ): Result = - safeApiCall { authApi.validateBusinessRegistrationNumber(businessRegistrationNumber) } + ): BusinessRegistrationResponse = + authApi.validateBusinessRegistrationNumber(businessRegistrationNumber).onResponse() suspend fun generateNewPassword( generateNewPasswordRequest: GenerateNewPasswordRequest - ): Result = safeApiCall { authApi.generateNewPassword(generateNewPasswordRequest) } + ): Unit = authApi.generateNewPassword(generateNewPasswordRequest).onResponse() - suspend fun sendCenterVerificationRequest(): Result = - safeApiCall { authApi.sendCenterVerificationRequest() } + suspend fun sendCenterVerificationRequest(): Unit = + authApi.sendCenterVerificationRequest().onResponse() suspend fun getDeviceToken(): String = suspendCancellableCoroutine { continuation -> firebaseMessaging.token.addOnCompleteListener { task -> diff --git a/core/network/src/main/java/com/idle/network/source/ChatDataSource.kt b/core/network/src/main/java/com/idle/network/source/ChatDataSource.kt index d40f815b..839205bd 100644 --- a/core/network/src/main/java/com/idle/network/source/ChatDataSource.kt +++ b/core/network/src/main/java/com/idle/network/source/ChatDataSource.kt @@ -1,7 +1,6 @@ package com.idle.network.source import com.idle.domain.model.auth.UserType -import com.idle.network.BuildConfig import com.idle.network.api.ChatApi import com.idle.network.di.TokenManager import com.idle.network.model.chat.ChatResponse @@ -14,7 +13,7 @@ import com.idle.network.serializer.ChatResponseSerializer import com.idle.network.util.MAX_RETRY_ATTEMPTS import com.idle.network.util.MAX_WAIT_TIME import com.idle.network.util.calculateBackoffTime -import com.idle.network.util.safeApiCall +import com.idle.network.util.onResponse import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow @@ -36,95 +35,87 @@ class ChatDataSource @Inject constructor( private val chatResponseSerializer: ChatResponseSerializer, private val json: Json, ) { - suspend fun getWorkerChatRooms(): Result> = - safeApiCall { chatApi.getWorkerChatRooms() } + suspend fun getWorkerChatRooms(): List = + chatApi.getWorkerChatRooms().onResponse() - suspend fun getCenterChatRooms(): Result> = - safeApiCall { chatApi.getCenterChatRooms() } + suspend fun getCenterChatRooms(): List = + chatApi.getCenterChatRooms().onResponse() suspend fun getWorkerChatRoomMessages( roomId: String, messageId: String?, - ): Result = - safeApiCall { - chatApi.getWorkerChatRoomMessages( - chatRoomId = roomId, - messageId = messageId - ) - } + ): GetChatMessageResponse = + chatApi.getWorkerChatRoomMessages( + chatRoomId = roomId, + messageId = messageId + ).onResponse() suspend fun getCenterChatRoomMessages( roomId: String, messageId: String?, - ): Result = - safeApiCall { - chatApi.getCenterChatRoomMessages( - chatRoomId = roomId, - messageId = messageId - ) - } + ): GetChatMessageResponse = + chatApi.getCenterChatRoomMessages( + chatRoomId = roomId, + messageId = messageId + ).onResponse() - suspend fun generateWorkerChatRoom(opponentId: String): Result = - safeApiCall { chatApi.generateWorkerChatRoom(opponentId) } + suspend fun generateWorkerChatRoom(opponentId: String): GenerateChatRoomResponse = + chatApi.generateWorkerChatRoom(opponentId).onResponse() - suspend fun generateCenterChatRoom(opponentId: String): Result = - safeApiCall { chatApi.generateCenterChatRoom(opponentId) } + suspend fun generateCenterChatRoom(opponentId: String): GenerateChatRoomResponse = + chatApi.generateCenterChatRoom(opponentId).onResponse() private var session: StompSessionWithKxSerialization? = null private var connectionAttempts = 0 - suspend fun connectWebSocket(): Result = runCatching { + suspend fun connectWebSocket() { val accessToken = tokenManager.getAccessToken() - - session = client.connect( - url = "${BuildConfig.CARE_WEBSOCKET_URL}/ws", - headers = mapOf("Authorization" to accessToken) - ).stomp(StompConfig()) - .withJsonConversions(json) - - connectionAttempts = 0 - }.recoverCatching { throwable -> - if (connectionAttempts < MAX_RETRY_ATTEMPTS) { - val waitTime = minOf(calculateBackoffTime(connectionAttempts), MAX_WAIT_TIME) - delay(waitTime) - connectionAttempts++ - connectWebSocket().getOrThrow() - } else { - throw throwable + try { + session = client.connect( + url = "${'$'}{BuildConfig.CARE_WEBSOCKET_URL}/ws", + headers = mapOf("Authorization" to accessToken) + ).stomp(StompConfig()) + .withJsonConversions(json) + connectionAttempts = 0 + } catch (e: Throwable) { + if (connectionAttempts < MAX_RETRY_ATTEMPTS) { + val waitTime = minOf(calculateBackoffTime(connectionAttempts), MAX_WAIT_TIME) + delay(waitTime) + connectionAttempts++ + connectWebSocket() + } else { + throw e + } } } - suspend fun disconnectWebSocket(reason: String? = null): Result = try { + suspend fun disconnectWebSocket() { session?.disconnect() - Result.success(Unit) - } catch (e: Exception) { - Result.failure(e) } suspend fun subscribeChatMessage(userId: String): Flow = session?.subscribe( - StompSubscribeHeaders(destination = "/sub/${userId}"), + StompSubscribeHeaders(destination = "/sub/${'$'}{userId}"), chatResponseSerializer, ) ?: flow { throw IOException("웹소켓을 먼저 연결해주세요.") } suspend fun sendMessage( userType: UserType, sendMessageRequest: SendMessageRequest - ): Result = - runCatching { - val result = session?.convertAndSend( - headers = StompSendHeaders(destination = "/pub/send/${userType.apiValue.lowercase()}"), - body = sendMessageRequest, - serializer = SendMessageRequest.serializer(), - ) - } + ) { + session?.convertAndSend( + headers = StompSendHeaders(destination = "/pub/send/${'$'}{userType.apiValue.lowercase()}"), + body = sendMessageRequest, + serializer = SendMessageRequest.serializer(), + ) + } suspend fun readMessage( userType: UserType, readMessageRequest: ReadMessageRequest - ): Result = runCatching { + ) { session?.convertAndSend( - headers = StompSendHeaders(destination = "/pub/read/${userType.apiValue.lowercase()}"), + headers = StompSendHeaders(destination = "/pub/read/${'$'}{userType.apiValue.lowercase()}"), body = readMessageRequest, serializer = ReadMessageRequest.serializer(), ) diff --git a/core/network/src/main/java/com/idle/network/source/JobPostingDataSource.kt b/core/network/src/main/java/com/idle/network/source/JobPostingDataSource.kt index 5b7c03c3..2ac50e1d 100644 --- a/core/network/src/main/java/com/idle/network/source/JobPostingDataSource.kt +++ b/core/network/src/main/java/com/idle/network/source/JobPostingDataSource.kt @@ -14,7 +14,7 @@ import com.idle.network.model.jobposting.GetJobPostingsCenterResponse import com.idle.network.model.jobposting.GetJobPostingsResponse import com.idle.network.model.jobposting.GetWorkerJobPostingDetailResponse import com.idle.network.model.jobposting.JobPostingRequest -import com.idle.network.util.safeApiCall +import com.idle.network.util.onResponse import javax.inject.Inject import javax.inject.Singleton @@ -22,84 +22,79 @@ import javax.inject.Singleton class JobPostingDataSource @Inject constructor( private val jobPostingApi: JobPostingApi ) { - suspend fun postJobPosting(jobPostingRequest: JobPostingRequest): Result = - safeApiCall { jobPostingApi.postJobPosting(jobPostingRequest) } + suspend fun postJobPosting(jobPostingRequest: JobPostingRequest): Unit = + jobPostingApi.postJobPosting(jobPostingRequest).onResponse() suspend fun updateJobPosting( jobPostingId: String, jobPostingRequest: JobPostingRequest - ): Result = safeApiCall { + ): Unit = jobPostingApi.updateJobPosting( jobPostingId = jobPostingId, jobPostingRequest = jobPostingRequest - ) - } + ).onResponse() - suspend fun getCenterJobPostingDetail(jobPostingId: String): - Result = safeApiCall { - jobPostingApi.getJobPostingDetailCenter(jobPostingId) - } + suspend fun getCenterJobPostingDetail(jobPostingId: String): GetCenterJobPostingDetailResponse = + jobPostingApi.getJobPostingDetailCenter(jobPostingId).onResponse() - suspend fun getWorkerJobPostingDetail(jobPostingId: String): - Result = safeApiCall { - jobPostingApi.getJobPostingDetailWorker(jobPostingId) - } + suspend fun getWorkerJobPostingDetail(jobPostingId: String): GetWorkerJobPostingDetailResponse = + jobPostingApi.getJobPostingDetailWorker(jobPostingId).onResponse() - suspend fun getJobPostings(next: String?, limit: Int): Result = - safeApiCall { jobPostingApi.getJobPostings(next = next, limit = limit) } + suspend fun getJobPostings(next: String?, limit: Int): GetJobPostingsResponse = + jobPostingApi.getJobPostings(next = next, limit = limit).onResponse() - suspend fun getJobPostingsApplied(next: String?, limit: Int): Result = - safeApiCall { jobPostingApi.getJobPostingsApplied(next = next, limit = limit) } + suspend fun getJobPostingsApplied(next: String?, limit: Int): GetJobPostingsResponse = + jobPostingApi.getJobPostingsApplied(next = next, limit = limit).onResponse() - suspend fun getMyFavoriteJobPostings(): Result = - safeApiCall { jobPostingApi.getMyFavoriteJobPostings() } + suspend fun getMyFavoriteJobPostings(): GetFavoriteJobPostingsResponse = + jobPostingApi.getMyFavoriteJobPostings().onResponse() - suspend fun getMyFavoriteCrawlingJobPostings(): Result = - safeApiCall { jobPostingApi.getMyFavoriteCrawlingJobPostings() } + suspend fun getMyFavoriteCrawlingJobPostings(): GetFavoriteCrawlingJobPostingsResponse = + jobPostingApi.getMyFavoriteCrawlingJobPostings().onResponse() - suspend fun getJobPostingsInProgress(): Result = - safeApiCall { jobPostingApi.getJobPostingsInProgress() } + suspend fun getJobPostingsInProgress(): GetJobPostingsCenterResponse = + jobPostingApi.getJobPostingsInProgress().onResponse() - suspend fun getJobPostingsCompleted(): Result = - safeApiCall { jobPostingApi.getJobPostingsCompleted() } + suspend fun getJobPostingsCompleted(): GetJobPostingsCenterResponse = + jobPostingApi.getJobPostingsCompleted().onResponse() - suspend fun getApplicantCount(jobPostingId: String): Result = - safeApiCall { jobPostingApi.getApplicantCount(jobPostingId) } + suspend fun getApplicantCount(jobPostingId: String): GetApplicantCountResponse = + jobPostingApi.getApplicantCount(jobPostingId).onResponse() - suspend fun applyJobPosting(applyJobPostingRequest: ApplyJobPostingRequest): Result = - safeApiCall { jobPostingApi.applyJobPosting(applyJobPostingRequest) } + suspend fun applyJobPosting(applyJobPostingRequest: ApplyJobPostingRequest): Unit = + jobPostingApi.applyJobPosting(applyJobPostingRequest).onResponse() suspend fun addFavoriteJobPosting( jobPostingId: String, favoriteJobPostingRequest: FavoriteJobPostingRequest, - ): Result = safeApiCall { + ): Unit = jobPostingApi.addFavoriteJobPosting( jobPostingId = jobPostingId, favoriteJobPostingRequest = favoriteJobPostingRequest - ) - } + ).onResponse() - suspend fun removeFavoriteJobPosting(jobPostingId: String): Result = - safeApiCall { jobPostingApi.removeFavoriteJobPosting(jobPostingId) } + suspend fun removeFavoriteJobPosting(jobPostingId: String): Unit = + jobPostingApi.removeFavoriteJobPosting(jobPostingId).onResponse() - suspend fun getApplicants(jobPostingId: String): Result = - safeApiCall { jobPostingApi.getApplicants(jobPostingId) } + suspend fun getApplicants(jobPostingId: String): GetApplicantsResponse = + jobPostingApi.getApplicants(jobPostingId).onResponse() - suspend fun endJobPosting(jobPostingId: String): Result = - safeApiCall { jobPostingApi.endJobPosting(jobPostingId) } + suspend fun endJobPosting(jobPostingId: String): Unit = + jobPostingApi.endJobPosting(jobPostingId).onResponse() - suspend fun deleteJobPosting(jobPostingId: String): Result = - safeApiCall { jobPostingApi.deleteJobPosting(jobPostingId) } + suspend fun deleteJobPosting(jobPostingId: String): Unit = + jobPostingApi.deleteJobPosting(jobPostingId).onResponse() suspend fun getCrawlingJobPostings( next: String?, limit: Int, distance: Int, - ): Result = - safeApiCall { jobPostingApi.getCrawlingJobPostings(next = next, limit = limit, distance = distance) } + ): GetCrawlingJobPostingsResponse = + jobPostingApi.getCrawlingJobPostings(next = next, limit = limit, distance = distance) + .onResponse() suspend fun getCrawlingJobPostingsDetail( jobPostingId: String - ): Result = - safeApiCall { jobPostingApi.getCrawlingJobPostingsDetail(jobPostingId) } + ): GetCrawlingJobPostingDetailResponse = + jobPostingApi.getCrawlingJobPostingsDetail(jobPostingId).onResponse() } diff --git a/core/network/src/main/java/com/idle/network/source/NotificationDataSource.kt b/core/network/src/main/java/com/idle/network/source/NotificationDataSource.kt index 85d06306..f2815f76 100644 --- a/core/network/src/main/java/com/idle/network/source/NotificationDataSource.kt +++ b/core/network/src/main/java/com/idle/network/source/NotificationDataSource.kt @@ -2,10 +2,10 @@ package com.idle.network.source import com.idle.network.api.NotificationApi import com.idle.network.model.notification.DeleteFcmTokenRequest -import com.idle.network.model.notification.PostFcmTokenRequest import com.idle.network.model.notification.GetMyNotificationResponse import com.idle.network.model.notification.GetUnreadNotificationCountResponse -import com.idle.network.util.safeApiCall +import com.idle.network.model.notification.PostFcmTokenRequest +import com.idle.network.util.onResponse import javax.inject.Inject import javax.inject.Singleton @@ -13,21 +13,21 @@ import javax.inject.Singleton class NotificationDataSource @Inject constructor( private val notificationApi: NotificationApi ) { - suspend fun postFCMToken(postFcmTokenRequest: PostFcmTokenRequest): Result = - safeApiCall { notificationApi.postFCMToken(postFcmTokenRequest) } + suspend fun postFCMToken(postFcmTokenRequest: PostFcmTokenRequest): Unit = + notificationApi.postFCMToken(postFcmTokenRequest).onResponse() - suspend fun deleteFCMToken(deleteFcmTokenRequest: DeleteFcmTokenRequest): Result = - safeApiCall { notificationApi.deleteFCMToken(deleteFcmTokenRequest) } + suspend fun deleteFCMToken(deleteFcmTokenRequest: DeleteFcmTokenRequest): Unit = + notificationApi.deleteFCMToken(deleteFcmTokenRequest).onResponse() suspend fun getMyNotifications( next: String?, limit: Int - ): Result = - safeApiCall { notificationApi.getMyNotifications(next = next, limit = limit) } + ): GetMyNotificationResponse = + notificationApi.getMyNotifications(next = next, limit = limit).onResponse() - suspend fun readNotification(notificationId: String): Result = - safeApiCall { notificationApi.readNotification(notificationId) } + suspend fun readNotification(notificationId: String): Unit = + notificationApi.readNotification(notificationId).onResponse() - suspend fun getUnreadNotificationCount(): Result = - safeApiCall { notificationApi.getUnreadNotificationCount() } + suspend fun getUnreadNotificationCount(): GetUnreadNotificationCountResponse = + notificationApi.getUnreadNotificationCount().onResponse() } diff --git a/core/network/src/main/java/com/idle/network/source/ProfileDataSource.kt b/core/network/src/main/java/com/idle/network/source/ProfileDataSource.kt index 59ab9bbe..fcc02b98 100644 --- a/core/network/src/main/java/com/idle/network/source/ProfileDataSource.kt +++ b/core/network/src/main/java/com/idle/network/source/ProfileDataSource.kt @@ -10,7 +10,7 @@ import com.idle.network.model.profile.RegisterCenterProfileRequest import com.idle.network.model.profile.UpdateCenterProfileRequest import com.idle.network.model.profile.UpdateWorkerProfileRequest import com.idle.network.model.profile.UploadProfileImageUrlResponse -import com.idle.network.util.safeApiCall +import com.idle.network.util.onResponse import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody.Companion.toRequestBody import java.io.InputStream @@ -21,60 +21,54 @@ import javax.inject.Singleton class ProfileDataSource @Inject constructor( private val userApi: UserApi, ) { - suspend fun getMyCenterProfile(): Result = - safeApiCall { userApi.getMyCenterProfile() } + suspend fun getMyCenterProfile(): GetCenterProfileResponse = + userApi.getMyCenterProfile().onResponse() - suspend fun updateMyCenterProfile(updateCenterProfileRequest: UpdateCenterProfileRequest): Result = - safeApiCall { userApi.updateMyCenterProfile(updateCenterProfileRequest) } + suspend fun updateMyCenterProfile(updateCenterProfileRequest: UpdateCenterProfileRequest): Unit = + userApi.updateMyCenterProfile(updateCenterProfileRequest).onResponse() - suspend fun getCenterProfile(centerId: String): Result = - safeApiCall { userApi.getCenterProfile(centerId) } + suspend fun getCenterProfile(centerId: String): GetCenterProfileResponse = + userApi.getCenterProfile(centerId).onResponse() suspend fun getProfileImageUploadUrl( userType: String, imageFileExtension: String - ): Result = safeApiCall { - userApi.getImageUploadUrl(userType, imageFileExtension) - } + ): UploadProfileImageUrlResponse = + userApi.getImageUploadUrl(userType, imageFileExtension).onResponse() suspend fun uploadProfileImage( uploadUrl: String, imageFileExtension: String, imageInputStream: InputStream, - ): Result { + ) { val requestImage = imageInputStream.readBytes() .toRequestBody(imageFileExtension.toMediaTypeOrNull()) - return safeApiCall { - userApi.uploadProfileImage(uploadUrl = uploadUrl, requestImage = requestImage) - } + userApi.uploadProfileImage(uploadUrl = uploadUrl, requestImage = requestImage) + .onResponse() } suspend fun callbackImageUpload( userType: String, callbackImageUploadRequest: CallbackImageUploadRequest, - ): Result = safeApiCall { - userApi.callbackImageUpload( - userType = userType, - callbackImageUploadRequest = callbackImageUploadRequest - ) - } + ): Unit = userApi.callbackImageUpload( + userType = userType, + callbackImageUploadRequest = callbackImageUploadRequest + ).onResponse() - suspend fun getMyWorkerProfile(): Result = - safeApiCall { userApi.getMyWorkerProfile() } + suspend fun getMyWorkerProfile(): GetWorkerProfileResponse = + userApi.getMyWorkerProfile().onResponse() - suspend fun getWorkerProfile(workerId: String): Result = - safeApiCall { userApi.getWorkerProfile(workerId) } + suspend fun getWorkerProfile(workerId: String): GetWorkerProfileResponse = + userApi.getWorkerProfile(workerId).onResponse() - suspend fun updateWorkerProfile(updateWorkerProfileRequest: UpdateWorkerProfileRequest): Result = - safeApiCall { userApi.updateWorkerProfile(updateWorkerProfileRequest) } + suspend fun updateWorkerProfile(updateWorkerProfileRequest: UpdateWorkerProfileRequest): Unit = + userApi.updateWorkerProfile(updateWorkerProfileRequest).onResponse() - suspend fun registerCenterProfile(registerCenterProfileRequest: RegisterCenterProfileRequest): Result = - safeApiCall { userApi.registerCenterProfile(registerCenterProfileRequest) } + suspend fun registerCenterProfile(registerCenterProfileRequest: RegisterCenterProfileRequest): Unit = + userApi.registerCenterProfile(registerCenterProfileRequest).onResponse() - suspend fun getWorkerId(): Result = - safeApiCall { userApi.getWorkerId() } + suspend fun getWorkerId(): GetWorkerIdResponse = userApi.getWorkerId().onResponse() - suspend fun getCenterStatus(): Result = - safeApiCall { userApi.getCenterStatus() } + suspend fun getCenterStatus(): GetCenterStatusResponse = userApi.getCenterStatus().onResponse() } diff --git a/core/network/src/main/java/com/idle/network/util/ResponseExtensions.kt b/core/network/src/main/java/com/idle/network/util/ResponseExtensions.kt new file mode 100644 index 00000000..f838e02d --- /dev/null +++ b/core/network/src/main/java/com/idle/network/util/ResponseExtensions.kt @@ -0,0 +1,30 @@ +package com.idle.network.util + +import com.idle.domain.model.error.ApiErrorCode +import com.idle.domain.model.error.HttpResponseException +import com.idle.domain.model.error.HttpResponseStatus +import com.idle.network.model.error.ErrorResponse +import kotlinx.serialization.json.Json +import retrofit2.Response + +private val json = Json { ignoreUnknownKeys = true } + +internal fun Response.onResponse(): T { + if (isSuccessful) { + return body() ?: Unit as T + } else { + errorBody()?.let { + val errorResponse = json.decodeFromString(it.string()) + + throw HttpResponseException( + status = HttpResponseStatus.create(code()), + apiErrorCode = ApiErrorCode.create(errorResponse.code), + msg = errorResponse.message, + ) + } ?: throw HttpResponseException( + status = HttpResponseStatus.create(-1), + apiErrorCode = ApiErrorCode.UnknownError, + msg = "알 수 없는 에러입니다." + ) + } +} diff --git a/core/network/src/main/java/com/idle/network/util/safeApiCall.kt b/core/network/src/main/java/com/idle/network/util/safeApiCall.kt deleted file mode 100644 index 1c0c7714..00000000 --- a/core/network/src/main/java/com/idle/network/util/safeApiCall.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.idle.network.util - -import com.idle.domain.model.error.ApiErrorCode -import com.idle.domain.model.error.HttpResponseException -import com.idle.domain.model.error.HttpResponseStatus -import com.idle.network.model.error.ErrorResponse -import kotlinx.serialization.json.Json -import retrofit2.Response - -internal inline fun safeApiCall(apiCall: () -> Response): Result { - return try { - val response = apiCall() - response.onResponse() - } catch (e: Exception) { - Result.failure(e) - } -} - -private val json = Json { ignoreUnknownKeys = true } - -internal fun Response.onResponse(): Result { - if (isSuccessful) { - body()?.let { - return Result.success(it) - } ?: return Result.success(Unit as T) - } else { - errorBody()?.let { - val errorResponse = json.decodeFromString(it.string()) - - return Result.failure( - HttpResponseException( - status = HttpResponseStatus.create(code()), - apiErrorCode = ApiErrorCode.create(errorResponse.code), - msg = errorResponse.message, - ) - ) - } ?: return Result.failure( - HttpResponseException( - status = HttpResponseStatus.create(-1), - apiErrorCode = ApiErrorCode.UnknownError, - msg = "알 수 없는 에러입니다." - ) - ) - } -} diff --git a/feature/center-applicant-inquiry/src/main/java/com/idle/applicant/inquiry/ApplicantInquiryViewModel.kt b/feature/center-applicant-inquiry/src/main/java/com/idle/applicant/inquiry/ApplicantInquiryViewModel.kt index 7ad468ff..9cdc9ecd 100644 --- a/feature/center-applicant-inquiry/src/main/java/com/idle/applicant/inquiry/ApplicantInquiryViewModel.kt +++ b/feature/center-applicant-inquiry/src/main/java/com/idle/applicant/inquiry/ApplicantInquiryViewModel.kt @@ -2,6 +2,7 @@ package com.idle.applicant.inquiry import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.jobposting.Applicant import com.idle.domain.model.jobposting.JobPostingSummary @@ -25,10 +26,11 @@ class ApplicantInquiryViewModel @Inject constructor( val applicants = _applicants.asStateFlow() suspend fun getApplicantsInfo(jobPostingId: String) = viewModelScope.launch { - jobPostingRepository.getApplicants(jobPostingId) - .onSuccess { (jobPostingSummary, applicants) -> - _jobPostingSummary.value = jobPostingSummary - _applicants.value = applicants - }.onFailure { errorHelper.sendError(it) } + suspendRunCatching { + jobPostingRepository.getApplicants(jobPostingId) + }.onSuccess { (jobPostingSummary, applicants) -> + _jobPostingSummary.value = jobPostingSummary + _applicants.value = applicants + }.onFailure { errorHelper.sendError(it) } } } diff --git a/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingViewModel.kt b/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingViewModel.kt index 88417278..7b24ee9b 100644 --- a/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingViewModel.kt +++ b/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingViewModel.kt @@ -2,6 +2,7 @@ package com.idle.center.chatting import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.idle.common.suspendRunCatching import com.idle.domain.model.auth.UserType import com.idle.domain.model.chat.ChatMessage import com.idle.domain.model.chat.ChatRoomWithOpponentInfo @@ -16,6 +17,7 @@ import com.idle.navigation.NavigationHelper import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.catch import kotlinx.coroutines.launch import javax.inject.Inject @@ -38,26 +40,34 @@ class CenterChattingViewModel @Inject constructor( val chatRoomList = _chatRoomList.asStateFlow() internal suspend fun initCenterChatting() { - getMyCenterProfileUseCase().onSuccess { + suspendRunCatching { + getMyCenterProfileUseCase() + }.onSuccess { _myProfile.value = it }.onFailure { errorHelper.sendError(it) } } internal fun connectWebsocket() = viewModelScope.launch { - chatRepository.connectWebSocket().onSuccess { + suspendRunCatching { + chatRepository.connectWebSocket() + }.onSuccess { subscribeChatMessage() } } internal fun disconnectWebsocket() = viewModelScope.launch { - chatRepository.disconnectWebSocket() + suspendRunCatching { + chatRepository.disconnectWebSocket() + } } private fun subscribeChatMessage() = viewModelScope.launch { chatRepository.subscribeChatMessage( userId = _myProfile.value?.centerId ?: return@launch, userType = UserType.CENTER, - ).collect { message -> + ).catch { + errorHelper.sendError(it) + }.collect { message -> when (message) { is ChatMessage -> handleChatMessage(message) is ReadMessage -> Unit @@ -79,8 +89,9 @@ class CenterChattingViewModel @Inject constructor( ) } else { // 새로운 방이면 새로 생성 후 최상단에 추가 - val opponentProfile = profileRepository.getWorkerProfile(message.senderId) - .getOrNull() ?: return + val opponentProfile = suspendRunCatching { + profileRepository.getWorkerProfile(message.senderId) + }.getOrNull() ?: return val newChatRoom = ChatRoomWithOpponentInfo( id = roomId, @@ -99,10 +110,14 @@ class CenterChattingViewModel @Inject constructor( } internal suspend fun retrieveChatRoomList() { - getChatRoomsUseCase( - userType = UserType.CENTER, - userId = _myProfile.value?.centerId ?: return - ).onSuccess { + val centerId = _myProfile.value?.centerId ?: return + + suspendRunCatching { + getChatRoomsUseCase( + userType = UserType.CENTER, + userId = centerId, + ) + }.onSuccess { val newMap = LinkedHashMap().apply { putAll(_chatRoomMap.value) it.forEach { chatRoom -> this[chatRoom.id] = chatRoom } @@ -113,13 +128,17 @@ class CenterChattingViewModel @Inject constructor( } internal suspend fun loadChatRoomList() { - chatRepository.loadChatRooms( - userId = _myProfile.value?.centerId ?: return, - userType = UserType.CENTER - ).onSuccess { + val centerId = _myProfile.value?.centerId ?: return + + suspendRunCatching { + chatRepository.loadChatRooms( + userId = centerId, + userType = UserType.CENTER + ) + }.onSuccess { response -> val newMap = LinkedHashMap().apply { putAll(_chatRoomMap.value) - it.forEach { chatRoom -> this[chatRoom.id] = chatRoom } + response.forEach { chatRoom -> this[chatRoom.id] = chatRoom } } _chatRoomMap.value = newMap _chatRoomList.value = _chatRoomMap.value.values.toList() diff --git a/feature/center-home/src/main/java/com/idle/center/home/CenterHomeViewModel.kt b/feature/center-home/src/main/java/com/idle/center/home/CenterHomeViewModel.kt index 0d6ed6d8..152fe668 100644 --- a/feature/center-home/src/main/java/com/idle/center/home/CenterHomeViewModel.kt +++ b/feature/center-home/src/main/java/com/idle/center/home/CenterHomeViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.idle.binding.EventHelper import com.idle.binding.MainEvent import com.idle.binding.ToastType.SUCCESS +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.jobposting.CenterJobPosting import com.idle.domain.repositorry.JobPostingRepository @@ -38,7 +39,9 @@ class CenterHomeViewModel @Inject constructor( val unreadNotificationCount = _unreadNotificationCount.asStateFlow() internal fun getUnreadNotificationCount() = viewModelScope.launch { - notificationRepository.getUnreadNotificationCount().onSuccess { + suspendRunCatching { + notificationRepository.getUnreadNotificationCount() + }.onSuccess { _unreadNotificationCount.value = it }.onFailure { errorHelper.sendError(it) } } @@ -53,19 +56,25 @@ class CenterHomeViewModel @Inject constructor( } internal fun getJobPostingsInProgress() = viewModelScope.launch { - getJobPostingsInProgressUseCase().onSuccess { + suspendRunCatching { + getJobPostingsInProgressUseCase() + }.onSuccess { _jobPostingsInProgress.value = it }.onFailure { errorHelper.sendError(it) } } internal fun getJobPostingsCompleted() = viewModelScope.launch { - jobPostingRepository.getJobPostingsCompleted().onSuccess { + suspendRunCatching { + jobPostingRepository.getJobPostingsCompleted() + }.onSuccess { _jobPostingsCompleted.value = it }.onFailure { errorHelper.sendError(it) } } internal fun endJobPosting(jobPostingId: String) = viewModelScope.launch { - jobPostingRepository.endJobPosting(jobPostingId).onSuccess { + suspendRunCatching { + jobPostingRepository.endJobPosting(jobPostingId) + }.onSuccess { val jobPostingsInProgress = _jobPostingsInProgress.value ?: emptyList() val jobPostingsCompleted = _jobPostingsCompleted.value ?: emptyList() diff --git a/feature/center-job-posting-post/src/main/java/com/idle/center/jobposting/JobPostingViewModel.kt b/feature/center-job-posting-post/src/main/java/com/idle/center/jobposting/JobPostingViewModel.kt index e053cffc..55175fe8 100644 --- a/feature/center-job-posting-post/src/main/java/com/idle/center/jobposting/JobPostingViewModel.kt +++ b/feature/center-job-posting-post/src/main/java/com/idle/center/jobposting/JobPostingViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope import com.idle.binding.EventHelper import com.idle.binding.MainEvent import com.idle.center.job.posting.post.R +import com.idle.common.suspendRunCatching import com.idle.compose.ui.JobPostingBottomSheetType import com.idle.domain.model.auth.Gender import com.idle.domain.model.error.ErrorHelper @@ -310,55 +311,57 @@ class JobPostingViewModel @Inject constructor( internal fun postJobPosting() { viewModelScope.launch { - jobPostingRepository.postJobPosting( - weekdays = _weekDays.value.toList() - .sortedBy { it.ordinal }, - startTime = _workStartTime.value, - endTime = _workEndTime.value, - payType = _payType.value ?: PayType.UNKNOWN, - payAmount = _payAmount.value.toIntOrNull() ?: let { - eventHelper.sendEvent(MainEvent.ShowToast("급여 형식이 잘못되었습니다. 숫자로 입력해주세요.")) - return@launch - }, - roadNameAddress = _roadNameAddress.value, - lotNumberAddress = _lotNumberAddress.value, - clientName = _clientName.value, - gender = _gender.value, - birthYear = _birthYear.value.toIntOrNull() ?: let { - eventHelper.sendEvent(MainEvent.ShowToast("올바른 출생년도를 입력해주세요.")) - return@launch - }, - weight = _weight.value.toIntOrNull(), - careLevel = _careLevel.value.toIntOrNull() ?: let { - eventHelper.sendEvent(MainEvent.ShowToast("올바른 요양 등급을 입력해주세요.")) - return@launch - }, - mentalStatus = _mentalStatus.value, - disease = _disease.value.ifBlank { null }, - isMealAssistance = _isMealAssistance.value ?: let { - eventHelper.sendEvent(MainEvent.ShowToast("식사 보조 여부를 선택해주세요.")) - return@launch - }, - isBowelAssistance = _isBowelAssistance.value ?: let { - eventHelper.sendEvent(MainEvent.ShowToast("배변 보조 여부를 선택해주세요.")) - return@launch - }, - isWalkingAssistance = _isWalkingAssistance.value ?: let { - eventHelper.sendEvent(MainEvent.ShowToast("이동 보조 여부를 선택해주세요.")) - return@launch - }, - lifeAssistance = _lifeAssistance.value.toList().sortedBy { it.ordinal } - .takeIf { it.isNotEmpty() } ?: listOf(LifeAssistance.NONE), - extraRequirement = _extraRequirement.value.ifBlank { null }, - isExperiencePreferred = _isExperiencePreferred.value ?: let { - eventHelper.sendEvent(MainEvent.ShowToast("경력 우대 여부를 선택해주세요.")) - return@launch - }, - applyMethod = _applyMethod.value.toList() - .sortedBy { it.ordinal }, - applyDeadLineType = _applyDeadlineType.value ?: ApplyDeadlineType.UNLIMITED, - applyDeadline = _applyDeadline.value?.toString(), - ).onSuccess { + suspendRunCatching { + jobPostingRepository.postJobPosting( + weekdays = _weekDays.value.toList() + .sortedBy { it.ordinal }, + startTime = _workStartTime.value, + endTime = _workEndTime.value, + payType = _payType.value ?: PayType.UNKNOWN, + payAmount = _payAmount.value.toIntOrNull() ?: let { + eventHelper.sendEvent(MainEvent.ShowToast("급여 형식이 잘못되었습니다. 숫자로 입력해주세요.")) + return@suspendRunCatching + }, + roadNameAddress = _roadNameAddress.value, + lotNumberAddress = _lotNumberAddress.value, + clientName = _clientName.value, + gender = _gender.value, + birthYear = _birthYear.value.toIntOrNull() ?: let { + eventHelper.sendEvent(MainEvent.ShowToast("올바른 출생년도를 입력해주세요.")) + return@suspendRunCatching + }, + weight = _weight.value.toIntOrNull(), + careLevel = _careLevel.value.toIntOrNull() ?: let { + eventHelper.sendEvent(MainEvent.ShowToast("올바른 요양 등급을 입력해주세요.")) + return@suspendRunCatching + }, + mentalStatus = _mentalStatus.value, + disease = _disease.value.ifBlank { null }, + isMealAssistance = _isMealAssistance.value ?: let { + eventHelper.sendEvent(MainEvent.ShowToast("식사 보조 여부를 선택해주세요.")) + return@suspendRunCatching + }, + isBowelAssistance = _isBowelAssistance.value ?: let { + eventHelper.sendEvent(MainEvent.ShowToast("배변 보조 여부를 선택해주세요.")) + return@suspendRunCatching + }, + isWalkingAssistance = _isWalkingAssistance.value ?: let { + eventHelper.sendEvent(MainEvent.ShowToast("이동 보조 여부를 선택해주세요.")) + return@suspendRunCatching + }, + lifeAssistance = _lifeAssistance.value.toList().sortedBy { it.ordinal } + .takeIf { it.isNotEmpty() } ?: listOf(LifeAssistance.NONE), + extraRequirement = _extraRequirement.value.ifBlank { null }, + isExperiencePreferred = _isExperiencePreferred.value ?: let { + eventHelper.sendEvent(MainEvent.ShowToast("경력 우대 여부를 선택해주세요.")) + return@suspendRunCatching + }, + applyMethod = _applyMethod.value.toList() + .sortedBy { it.ordinal }, + applyDeadLineType = _applyDeadlineType.value ?: ApplyDeadlineType.UNLIMITED, + applyDeadline = _applyDeadline.value?.toString(), + ) + }.onSuccess { navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.To( destination = CenterJobPostingPostComplete, @@ -370,7 +373,9 @@ class JobPostingViewModel @Inject constructor( } private fun getMyCenterProfile() = viewModelScope.launch { - getMyCenterProfileUseCase().onSuccess { + suspendRunCatching { + getMyCenterProfileUseCase() + }.onSuccess { _profile.value = it }.onFailure { errorHelper.sendError(it) } } diff --git a/feature/center-pending/src/main/java/com/idle/pending/CenterPendingViewModel.kt b/feature/center-pending/src/main/java/com/idle/pending/CenterPendingViewModel.kt index e153fa57..2a20d70f 100644 --- a/feature/center-pending/src/main/java/com/idle/pending/CenterPendingViewModel.kt +++ b/feature/center-pending/src/main/java/com/idle/pending/CenterPendingViewModel.kt @@ -6,6 +6,7 @@ import com.idle.binding.EventHelper import com.idle.binding.MainEvent import com.idle.binding.ToastType.SUCCESS import com.idle.center.pending.R +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ApiErrorCode import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.error.HttpResponseException @@ -46,7 +47,9 @@ class CenterPendingViewModel @Inject constructor( } internal fun logout() = viewModelScope.launch { - authRepository.logoutCenter().onSuccess { + suspendRunCatching { + authRepository.logoutCenter() + }.onSuccess { navigationHelper.navigateTo( NavigationEvent.ToAuthWithClearBackStack( toastMsg = "로그아웃이 완료되었습니다.", @@ -57,7 +60,9 @@ class CenterPendingViewModel @Inject constructor( } internal fun sendVerificationRequest() = viewModelScope.launch { - authRepository.sendCenterVerificationRequest().onSuccess { + suspendRunCatching { + authRepository.sendCenterVerificationRequest() + }.onSuccess { _status.value = CenterManagerAccountStatus.PENDING eventHelper.sendEvent(MainEvent.ShowToast("센터 인증 요청이 완료되었습니다.", SUCCESS)) }.onFailure { errorHelper.sendError(it) } @@ -74,7 +79,9 @@ class CenterPendingViewModel @Inject constructor( } private fun getCenterStatus() = viewModelScope.launch { - profileRepository.getCenterStatus().onSuccess { + suspendRunCatching { + profileRepository.getCenterStatus() + }.onSuccess { when (it.centerManagerAccountStatus) { CenterManagerAccountStatus.APPROVED -> { handleApprovedCenterStatus() @@ -87,7 +94,9 @@ class CenterPendingViewModel @Inject constructor( } private fun handleApprovedCenterStatus() = viewModelScope.launch { - profileRepository.getMyCenterProfile().onSuccess { + suspendRunCatching { + profileRepository.getMyCenterProfile() + }.onSuccess { navigationHelper.navigateTo( NavigationEvent.To(CenterHome, R.id.centerPendingFragment) ) diff --git a/feature/center-profile/src/main/java/com/idle/center/profile/CenterProfileViewModel.kt b/feature/center-profile/src/main/java/com/idle/center/profile/CenterProfileViewModel.kt index 4ab57885..dfd92f90 100644 --- a/feature/center-profile/src/main/java/com/idle/center/profile/CenterProfileViewModel.kt +++ b/feature/center-profile/src/main/java/com/idle/center/profile/CenterProfileViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope import com.idle.binding.EventHelper import com.idle.binding.MainEvent import com.idle.binding.ToastType.SUCCESS +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.profile.CenterProfile import com.idle.domain.repositorry.ProfileRepository @@ -63,7 +64,9 @@ class CenterProfileViewModel @Inject constructor( } internal fun getMyCenterProfile() = viewModelScope.launch { - getMyCenterProfileUseCase().onSuccess { + suspendRunCatching { + getMyCenterProfileUseCase() + }.onSuccess { _centerProfile.value = it _centerIntroduce.value = it.introduce ?: "" _centerOfficeNumber.value = it.officeNumber @@ -71,7 +74,9 @@ class CenterProfileViewModel @Inject constructor( } internal fun getCenterProfile(centerId: String) = viewModelScope.launch { - profileRepository.getCenterProfile(centerId).onSuccess { + suspendRunCatching { + profileRepository.getCenterProfile(centerId) + }.onSuccess { _centerProfile.value = it _centerIntroduce.value = it.introduce ?: "" _centerOfficeNumber.value = it.officeNumber @@ -90,11 +95,13 @@ class CenterProfileViewModel @Inject constructor( _isUpdateLoading.value = true - updateCenterProfileUseCase( - officeNumber = _centerOfficeNumber.value, - introduce = _centerIntroduce.value.ifBlank { null }, - imageFileUri = _profileImageUri.value?.toString(), - ).onSuccess { + suspendRunCatching { + updateCenterProfileUseCase( + officeNumber = _centerOfficeNumber.value, + introduce = _centerIntroduce.value.ifBlank { null }, + imageFileUri = _profileImageUri.value?.toString(), + ) + }.onSuccess { eventHelper.sendEvent(MainEvent.ShowToast("정보 수정이 완료되었어요.", SUCCESS)) setEditState(false) }.onFailure { diff --git a/feature/center-register-info/src/main/java/com/idle/center/register/RegisterCenterInfoViewModel.kt b/feature/center-register-info/src/main/java/com/idle/center/register/RegisterCenterInfoViewModel.kt index d8e2ad8e..803bff01 100644 --- a/feature/center-register-info/src/main/java/com/idle/center/register/RegisterCenterInfoViewModel.kt +++ b/feature/center-register-info/src/main/java/com/idle/center/register/RegisterCenterInfoViewModel.kt @@ -5,6 +5,7 @@ import androidx.core.text.isDigitsOnly import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.idle.center.register.info.R +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ErrorHelper import com.idle.domain.usecase.profile.RegisterCenterProfileUseCase import com.idle.navigation.DeepLinkDestination.CenterRegisterComplete @@ -45,15 +46,17 @@ class RegisterCenterInfoViewModel @Inject constructor( val centerProfileImageUri = _centerProfileImageUri.asStateFlow() internal fun registerCenterProfile() = viewModelScope.launch { - registerCenterProfileUseCase( - centerName = _centerName.value, - detailedAddress = _centerDetailAddress.value, - introduce = _centerIntroduce.value, - lotNumberAddress = _lotNumberAddress.value, - officeNumber = _centerNumber.value, - roadNameAddress = _roadNameAddress.value, - imageFileUri = _centerProfileImageUri.value.toString(), - ).onSuccess { + suspendRunCatching { + registerCenterProfileUseCase( + centerName = _centerName.value, + detailedAddress = _centerDetailAddress.value, + introduce = _centerIntroduce.value, + lotNumberAddress = _lotNumberAddress.value, + officeNumber = _centerNumber.value, + roadNameAddress = _roadNameAddress.value, + imageFileUri = _centerProfileImageUri.value.toString(), + ) + }.onSuccess { navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.To( CenterRegisterComplete, diff --git a/feature/center-register-info/src/main/java/com/idle/center/register/complete/RegisterCenterInfoCompleteViewModel.kt b/feature/center-register-info/src/main/java/com/idle/center/register/complete/RegisterCenterInfoCompleteViewModel.kt index ba57e21d..6053cc00 100644 --- a/feature/center-register-info/src/main/java/com/idle/center/register/complete/RegisterCenterInfoCompleteViewModel.kt +++ b/feature/center-register-info/src/main/java/com/idle/center/register/complete/RegisterCenterInfoCompleteViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.idle.binding.EventHelper import com.idle.binding.MainEvent +import com.idle.common.suspendRunCatching import com.idle.domain.model.profile.CenterProfile import com.idle.domain.usecase.profile.GetMyCenterProfileUseCase import dagger.hilt.android.lifecycle.HiltViewModel @@ -23,11 +24,13 @@ class RegisterCenterInfoCompleteViewModel @Inject constructor( init { viewModelScope.launch { - getMyCenterProfileUseCase() - .onSuccess { _centerProfile.value = it } - .onFailure { - eventHelper.sendEvent(MainEvent.ShowToast(it.toString())) - } + suspendRunCatching { + getMyCenterProfileUseCase() + }.onSuccess { + _centerProfile.value = it + }.onFailure { + eventHelper.sendEvent(MainEvent.ShowToast(it.toString())) + } } } } diff --git a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailViewModel.kt b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailViewModel.kt index 8dd41d4c..1ed71995 100644 --- a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailViewModel.kt +++ b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailViewModel.kt @@ -3,6 +3,7 @@ package com.idle.chatting_detail import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.idle.common.suspendRunCatching import com.idle.domain.model.auth.UserType import com.idle.domain.model.chat.ChatMessage import com.idle.domain.model.chat.ReadMessage @@ -73,14 +74,18 @@ class ChattingDetailViewModel @Inject constructor( when (myUserType) { UserType.CENTER -> { launch { - profileRepository.getWorkerProfile(opponentId).onSuccess { + suspendRunCatching { + profileRepository.getWorkerProfile(opponentId) + }.onSuccess { _workerProfile.value = it }.onFailure { errorHelper.sendError(it) } } - getMyCenterProfileUseCase().onSuccess { + suspendRunCatching { + getMyCenterProfileUseCase() + }.onSuccess { _centerProfile.value = it }.onFailure { errorHelper.sendError(it) @@ -89,14 +94,18 @@ class ChattingDetailViewModel @Inject constructor( UserType.WORKER -> { launch { - profileRepository.getCenterProfile(opponentId).onSuccess { + suspendRunCatching { + profileRepository.getCenterProfile(opponentId) + }.onSuccess { _centerProfile.value = it }.onFailure { errorHelper.sendError(it) } } - getMyWorkerProfileUseCase().onSuccess { + suspendRunCatching { + getMyWorkerProfileUseCase() + }.onSuccess { _workerProfile.value = it }.onFailure { errorHelper.sendError(it) @@ -109,11 +118,13 @@ class ChattingDetailViewModel @Inject constructor( if (_callType.value == MessageCallType.END) return if (fromJobPosting) { - chatRepository.retrieveChatRoomMessages( - roomId = chatroomId, - myId = myId, - messageId = _chatMessages.value?.first()?.id, - ).onSuccess { messages -> + suspendRunCatching { + chatRepository.retrieveChatRoomMessages( + roomId = chatroomId, + myId = myId, + messageId = _chatMessages.value?.first()?.id, + ) + }.onSuccess { messages -> if (messages.isEmpty()) _callType.value = MessageCallType.END _chatMessages.value = messages.plus(_chatMessages.value ?: emptyList()) @@ -121,13 +132,15 @@ class ChattingDetailViewModel @Inject constructor( errorHelper.sendError(it) } } else { - chatRepository.getChatRoomMessages( - roomId = chatroomId, - messageId = _chatMessages.value?.first()?.id, - userType = myUserType, - myId = myId, - unReadMessageCount = if (unReadMessageCount >= 0) unReadMessageCount else null, - ).onSuccess { messages -> + suspendRunCatching { + chatRepository.getChatRoomMessages( + roomId = chatroomId, + messageId = _chatMessages.value?.first()?.id, + userType = myUserType, + myId = myId, + unReadMessageCount = if (unReadMessageCount >= 0) unReadMessageCount else null, + ) + }.onSuccess { messages -> if (messages.isEmpty()) _callType.value = MessageCallType.END unReadMessageCount -= messages.size @@ -139,7 +152,9 @@ class ChattingDetailViewModel @Inject constructor( } internal fun connectWebsocket() = viewModelScope.launch { - chatRepository.connectWebSocket().onSuccess { + suspendRunCatching { + chatRepository.connectWebSocket() + }.onSuccess { subscribeChatMessage() } } @@ -173,14 +188,16 @@ class ChattingDetailViewModel @Inject constructor( val senderName = if (myUserType == UserType.CENTER) _centerProfile.value!!.centerName else _workerProfile.value!!.workerName - chatRepository.sendMessage( - chatroomId = chatroomId, - myId = myId, - userType = myUserType, - receiverId = opponentId, - senderName = senderName, - content = _writingText.value, - ).onSuccess { + suspendRunCatching { + chatRepository.sendMessage( + chatroomId = chatroomId, + myId = myId, + userType = myUserType, + receiverId = opponentId, + senderName = senderName, + content = _writingText.value, + ) + }.onSuccess { _writingText.value = "" }.onFailure { errorHelper.sendError(it) } } @@ -188,13 +205,15 @@ class ChattingDetailViewModel @Inject constructor( internal suspend fun readMessage() { val lastOpponentMessageSequence = _chatMessages.value?.lastOrNull()?.sequence ?: return - chatRepository.readMessage( - chatroomId = chatroomId, - myId = myId, - opponentId = opponentId, - userType = myUserType, - sequence = lastOpponentMessageSequence - ).onSuccess { + suspendRunCatching { + chatRepository.readMessage( + chatroomId = chatroomId, + myId = myId, + opponentId = opponentId, + userType = myUserType, + sequence = lastOpponentMessageSequence + ) + }.onSuccess { _chatMessages.value = _chatMessages.value?.map { if (it.receiverId == myId) it.copy(isRead = true) else it } diff --git a/feature/job-posting-detail/src/main/java/com/idle/worker/job/posting/detail/center/CenterJobPostingDetailViewModel.kt b/feature/job-posting-detail/src/main/java/com/idle/worker/job/posting/detail/center/CenterJobPostingDetailViewModel.kt index c411e0f3..ba036c9b 100644 --- a/feature/job-posting-detail/src/main/java/com/idle/worker/job/posting/detail/center/CenterJobPostingDetailViewModel.kt +++ b/feature/job-posting-detail/src/main/java/com/idle/worker/job/posting/detail/center/CenterJobPostingDetailViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.idle.binding.EventHelper import com.idle.binding.MainEvent import com.idle.binding.ToastType +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.jobposting.CenterJobPostingDetail import com.idle.domain.model.jobposting.EditJobPostingDetail @@ -45,19 +46,24 @@ class CenterJobPostingDetailViewModel @Inject constructor( } private fun getMyCenterProfile() = viewModelScope.launch { - getMyCenterProfileUseCase().onSuccess { + suspendRunCatching { + getMyCenterProfileUseCase() + }.onSuccess { _profile.value = it }.onFailure { errorHelper.sendError(it) } } internal fun getCenterJobPostingDetail(jobPostingId: String) = viewModelScope.launch { - jobPostingRepository.getCenterJobPostingDetail(jobPostingId) - .onSuccess { _jobPostingDetail.value = it } + suspendRunCatching { + jobPostingRepository.getCenterJobPostingDetail(jobPostingId) + }.onSuccess { _jobPostingDetail.value = it } .onFailure { errorHelper.sendError(it) } } internal fun getApplicantsCount(jobPostingId: String) = viewModelScope.launch { - jobPostingRepository.getApplicantsCount(jobPostingId).onSuccess { + suspendRunCatching { + jobPostingRepository.getApplicantsCount(jobPostingId) + }.onSuccess { _applicantsCount.value = it }.onFailure { errorHelper.sendError(it) } } @@ -75,37 +81,39 @@ class CenterJobPostingDetailViewModel @Inject constructor( return@launch } - jobPostingRepository.updateJobPosting( - jobPostingId = _jobPostingDetail.value?.id ?: return@launch, - weekdays = editJobPostingDetail.weekdays.toList() - .sortedBy { it.ordinal }, - startTime = editJobPostingDetail.startTime, - endTime = editJobPostingDetail.endTime, - payType = editJobPostingDetail.payType, - payAmount = editJobPostingDetail.payAmount.toIntOrNull() ?: return@launch, - roadNameAddress = editJobPostingDetail.roadNameAddress, - lotNumberAddress = editJobPostingDetail.lotNumberAddress, - clientName = editJobPostingDetail.clientName, - gender = editJobPostingDetail.gender, - birthYear = editJobPostingDetail.birthYear.toIntOrNull() ?: return@launch, - weight = editJobPostingDetail.weight?.toIntOrNull(), - careLevel = editJobPostingDetail.careLevel.toIntOrNull() ?: return@launch, - mentalStatus = editJobPostingDetail.mentalStatus, - disease = editJobPostingDetail.disease.ifBlank { null }, - isMealAssistance = editJobPostingDetail.isMealAssistance, - isBowelAssistance = editJobPostingDetail.isBowelAssistance, - isWalkingAssistance = editJobPostingDetail.isWalkingAssistance, - lifeAssistance = editJobPostingDetail.lifeAssistance.toList() - .sortedBy { it.ordinal } - .ifEmpty { listOf(LifeAssistance.NONE) }, - extraRequirement = editJobPostingDetail.extraRequirement, - isExperiencePreferred = editJobPostingDetail.isExperiencePreferred, - applyMethod = editJobPostingDetail.applyMethod.toList() - .sortedBy { it.ordinal }, - applyDeadLineType = editJobPostingDetail.applyDeadlineType, - applyDeadline = editJobPostingDetail.applyDeadline.toString() - .ifBlank { null }, - ).onSuccess { + suspendRunCatching { + jobPostingRepository.updateJobPosting( + jobPostingId = _jobPostingDetail.value?.id ?: return@suspendRunCatching, + weekdays = editJobPostingDetail.weekdays.toList() + .sortedBy { it.ordinal }, + startTime = editJobPostingDetail.startTime, + endTime = editJobPostingDetail.endTime, + payType = editJobPostingDetail.payType, + payAmount = editJobPostingDetail.payAmount.toIntOrNull() ?: return@suspendRunCatching, + roadNameAddress = editJobPostingDetail.roadNameAddress, + lotNumberAddress = editJobPostingDetail.lotNumberAddress, + clientName = editJobPostingDetail.clientName, + gender = editJobPostingDetail.gender, + birthYear = editJobPostingDetail.birthYear.toIntOrNull() ?: return@suspendRunCatching, + weight = editJobPostingDetail.weight?.toIntOrNull(), + careLevel = editJobPostingDetail.careLevel.toIntOrNull() ?: return@suspendRunCatching, + mentalStatus = editJobPostingDetail.mentalStatus, + disease = editJobPostingDetail.disease.ifBlank { null }, + isMealAssistance = editJobPostingDetail.isMealAssistance, + isBowelAssistance = editJobPostingDetail.isBowelAssistance, + isWalkingAssistance = editJobPostingDetail.isWalkingAssistance, + lifeAssistance = editJobPostingDetail.lifeAssistance.toList() + .sortedBy { it.ordinal } + .ifEmpty { listOf(LifeAssistance.NONE) }, + extraRequirement = editJobPostingDetail.extraRequirement, + isExperiencePreferred = editJobPostingDetail.isExperiencePreferred, + applyMethod = editJobPostingDetail.applyMethod.toList() + .sortedBy { it.ordinal }, + applyDeadLineType = editJobPostingDetail.applyDeadlineType, + applyDeadline = editJobPostingDetail.applyDeadline.toString() + .ifBlank { null }, + ) + }.onSuccess { getCenterJobPostingDetail(_jobPostingDetail.value?.id ?: return@launch) eventHelper.sendEvent( MainEvent.ShowToast("수정이 완료되었어요.", ToastType.SUCCESS) @@ -115,7 +123,9 @@ class CenterJobPostingDetailViewModel @Inject constructor( } internal fun endJobPosting(jobPostingId: String) = viewModelScope.launch { - jobPostingRepository.endJobPosting(jobPostingId).onSuccess { + suspendRunCatching { + jobPostingRepository.endJobPosting(jobPostingId) + }.onSuccess { _jobPostingDetail.value = _jobPostingDetail.value?.copy(jobPostingStatus = JobPostingStatus.COMPLETED) eventHelper.sendEvent( @@ -125,7 +135,9 @@ class CenterJobPostingDetailViewModel @Inject constructor( } internal fun deleteJobPosting(jobPostingId: String) = viewModelScope.launch { - jobPostingRepository.deleteJobPosting(jobPostingId).onSuccess { + suspendRunCatching { + jobPostingRepository.deleteJobPosting(jobPostingId) + }.onSuccess { navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.To( com.idle.navigation.DeepLinkDestination.CenterHome, diff --git a/feature/job-posting-detail/src/main/java/com/idle/worker/job/posting/detail/worker/WorkerJobPostingDetailViewModel.kt b/feature/job-posting-detail/src/main/java/com/idle/worker/job/posting/detail/worker/WorkerJobPostingDetailViewModel.kt index f9cc682d..8ecd10d1 100644 --- a/feature/job-posting-detail/src/main/java/com/idle/worker/job/posting/detail/worker/WorkerJobPostingDetailViewModel.kt +++ b/feature/job-posting-detail/src/main/java/com/idle/worker/job/posting/detail/worker/WorkerJobPostingDetailViewModel.kt @@ -10,6 +10,7 @@ import com.idle.analytics.AnalyticsHelper import com.idle.binding.EventHelper import com.idle.binding.MainEvent import com.idle.binding.ToastType.SUCCESS +import com.idle.common.suspendRunCatching import com.idle.domain.model.auth.UserType import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.jobposting.ApplyMethod @@ -47,7 +48,9 @@ class WorkerJobPostingDetailViewModel @Inject constructor( val workerJobPostingDetail = _workerJobPostingDetail.asStateFlow() internal fun getMyProfile() = viewModelScope.launch { - getMyWorkerProfileUseCase().onSuccess { + suspendRunCatching { + getMyWorkerProfileUseCase() + }.onSuccess { _profile.value = it }.onFailure { errorHelper.sendError(it) } } @@ -57,15 +60,15 @@ class WorkerJobPostingDetailViewModel @Inject constructor( jobPostingType: String, ) = viewModelScope.launch { when (jobPostingType) { - JobPostingType.CAREMEET.name -> jobPostingRepository.getWorkerJobPostingDetail( - jobPostingId - ).onSuccess { + JobPostingType.CAREMEET.name -> suspendRunCatching { + jobPostingRepository.getWorkerJobPostingDetail(jobPostingId) + }.onSuccess { _workerJobPostingDetail.value = it }.onFailure { errorHelper.sendError(it) } - JobPostingType.WORKNET.name -> jobPostingRepository.getCrawlingJobPostingDetail( - jobPostingId - ).onSuccess { + JobPostingType.WORKNET.name -> suspendRunCatching { + jobPostingRepository.getCrawlingJobPostingDetail(jobPostingId) + }.onSuccess { _workerJobPostingDetail.value = it }.onFailure { errorHelper.sendError(it) } } @@ -73,10 +76,12 @@ class WorkerJobPostingDetailViewModel @Inject constructor( internal fun applyJobPosting(jobPostingId: String, applyMethod: ApplyMethod) = viewModelScope.launch { - jobPostingRepository.applyJobPosting( - jobPostingId = jobPostingId, - applyMethod = applyMethod, - ).onSuccess { + suspendRunCatching { + jobPostingRepository.applyJobPosting( + jobPostingId = jobPostingId, + applyMethod = applyMethod, + ) + }.onSuccess { eventHelper.sendEvent(MainEvent.ShowToast("지원이 완료되었어요.", SUCCESS)) if (_workerJobPostingDetail.value?.jobPostingType == JobPostingType.CAREMEET) { @@ -101,10 +106,12 @@ class WorkerJobPostingDetailViewModel @Inject constructor( jobPostingId: String, jobPostingType: JobPostingType, ) = viewModelScope.launch { - jobPostingRepository.addFavoriteJobPosting( - jobPostingId = jobPostingId, - jobPostingType = jobPostingType, - ).onSuccess { + suspendRunCatching { + jobPostingRepository.addFavoriteJobPosting( + jobPostingId = jobPostingId, + jobPostingType = jobPostingType, + ) + }.onSuccess { eventHelper.sendEvent( MainEvent.ShowToast("즐겨찾기에 추가되었어요.", SUCCESS) ) @@ -127,7 +134,9 @@ class WorkerJobPostingDetailViewModel @Inject constructor( jobPostingId: String, jobPostingType: JobPostingType, ) = viewModelScope.launch { - jobPostingRepository.removeFavoriteJobPosting(jobPostingId = jobPostingId).onSuccess { + suspendRunCatching { + jobPostingRepository.removeFavoriteJobPosting(jobPostingId = jobPostingId) + }.onSuccess { eventHelper.sendEvent( MainEvent.ShowToast("즐겨찾기에서 제거되었어요.", SUCCESS) ) @@ -147,10 +156,12 @@ class WorkerJobPostingDetailViewModel @Inject constructor( } internal fun generateChatRoom(opponentId: String) = viewModelScope.launch { - chatRepository.generateChatRooms( - userType = UserType.WORKER, - opponentId = opponentId, - ).onSuccess { + suspendRunCatching { + chatRepository.generateChatRooms( + userType = UserType.WORKER, + opponentId = opponentId, + ) + }.onSuccess { navigationHelper.navigateTo( NavigationEvent.To( DeepLinkDestination.ChattingDetail( diff --git a/feature/notification/src/main/java/com/idle/notification/NotificationViewModel.kt b/feature/notification/src/main/java/com/idle/notification/NotificationViewModel.kt index 8c074449..2e07418f 100644 --- a/feature/notification/src/main/java/com/idle/notification/NotificationViewModel.kt +++ b/feature/notification/src/main/java/com/idle/notification/NotificationViewModel.kt @@ -2,6 +2,7 @@ package com.idle.notification import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.jobposting.JobPostingType import com.idle.domain.model.notification.Notification @@ -35,7 +36,9 @@ class NotificationViewModel @Inject constructor( return@launch } - notificationRepository.getMyNotifications(next.value).onSuccess { (nextId, notifications) -> + suspendRunCatching { + notificationRepository.getMyNotifications(next.value) + }.onSuccess { (nextId, notifications) -> _myNotifications.value = _myNotifications.value?.plus(notifications) ?: notifications next.value = nextId @@ -47,7 +50,9 @@ class NotificationViewModel @Inject constructor( internal fun onNotificationClick(notification: Notification) = viewModelScope.launch { launch { - notificationRepository.readNotification(notification.id).onSuccess { + suspendRunCatching { + notificationRepository.readNotification(notification.id) + }.onSuccess { _myNotifications.value = _myNotifications.value?.map { if (it.id == notification.id) { notification.copy(isRead = true) diff --git a/feature/setting/src/main/java/com/idle/setting/center/CenterSettingViewModel.kt b/feature/setting/src/main/java/com/idle/setting/center/CenterSettingViewModel.kt index 613a9ab1..a9b0c082 100644 --- a/feature/setting/src/main/java/com/idle/setting/center/CenterSettingViewModel.kt +++ b/feature/setting/src/main/java/com/idle/setting/center/CenterSettingViewModel.kt @@ -3,6 +3,7 @@ package com.idle.setting.center import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.idle.analytics.AnalyticsHelper +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.profile.CenterProfile import com.idle.domain.repositorry.AuthRepository @@ -37,13 +38,17 @@ class CenterSettingViewModel @Inject constructor( } private fun getMyProfile() = viewModelScope.launch { - getMyCenterProfileUseCase().onSuccess { + suspendRunCatching { + getMyCenterProfileUseCase() + }.onSuccess { _centerProfile.value = it }.onFailure { errorHelper.sendError(it) } } fun logout() = viewModelScope.launch { - authRepository.logoutCenter().onSuccess { + suspendRunCatching { + authRepository.logoutCenter() + }.onSuccess { analyticsHelper.setUserId(null) navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( diff --git a/feature/setting/src/main/java/com/idle/setting/worker/WorkerSettingViewModel.kt b/feature/setting/src/main/java/com/idle/setting/worker/WorkerSettingViewModel.kt index 94121bee..05ebc07f 100644 --- a/feature/setting/src/main/java/com/idle/setting/worker/WorkerSettingViewModel.kt +++ b/feature/setting/src/main/java/com/idle/setting/worker/WorkerSettingViewModel.kt @@ -3,6 +3,7 @@ package com.idle.setting.worker import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.idle.analytics.AnalyticsHelper +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.profile.WorkerProfile import com.idle.domain.repositorry.AuthRepository @@ -33,13 +34,17 @@ class WorkerSettingViewModel @Inject constructor( } private fun getMyProfile() = viewModelScope.launch { - getMyWorkerProfileUseCase().onSuccess { + suspendRunCatching { + getMyWorkerProfileUseCase() + }.onSuccess { _workerProfile.value = it }.onFailure { errorHelper.sendError(it) } } fun logout() = viewModelScope.launch { - authRepository.logoutWorker().onSuccess { + suspendRunCatching { + authRepository.logoutWorker() + }.onSuccess { analyticsHelper.setUserId(null) navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( diff --git a/feature/signin/src/main/java/com/idle/signin/center/CenterSignInViewModel.kt b/feature/signin/src/main/java/com/idle/signin/center/CenterSignInViewModel.kt index 5af940bf..55acb8bc 100644 --- a/feature/signin/src/main/java/com/idle/signin/center/CenterSignInViewModel.kt +++ b/feature/signin/src/main/java/com/idle/signin/center/CenterSignInViewModel.kt @@ -7,6 +7,7 @@ import com.idle.analytics.AnalyticsEvent.PropertiesKeys.ACTION_NAME import com.idle.analytics.AnalyticsEvent.PropertiesKeys.ACTION_RESULT import com.idle.analytics.AnalyticsHelper import com.idle.binding.EventHelper +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ApiErrorCode import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.error.HttpResponseException @@ -62,33 +63,38 @@ class CenterSignInViewModel @Inject constructor( } internal fun signInCenter() = viewModelScope.launch { - authRepository.signInCenter(identifier = _centerId.value, password = _centerPassword.value) - .onSuccess { - analyticsHelper.setUserId(_centerId.value) - handleCenterLoginSuccess() + suspendRunCatching { + authRepository.signInCenter( + identifier = _centerId.value, + password = _centerPassword.value + ) + }.onSuccess { + analyticsHelper.setUserId(_centerId.value) + handleCenterLoginSuccess() + }.onFailure { + if (it is HttpResponseException && it.status == HttpResponseStatus.Unauthorized) { + _isLoginError.value = true + return@launch } - .onFailure { - if (it is HttpResponseException && it.status == HttpResponseStatus.Unauthorized) { - _isLoginError.value = true - return@launch - } - errorHelper.sendError(it) + errorHelper.sendError(it) - analyticsHelper.logEvent( - AnalyticsEvent( - type = AnalyticsEvent.Types.ACTION, - properties = mutableMapOf( - ACTION_NAME to "center_login", - ACTION_RESULT to false, - ) + analyticsHelper.logEvent( + AnalyticsEvent( + type = AnalyticsEvent.Types.ACTION, + properties = mutableMapOf( + ACTION_NAME to "center_login", + ACTION_RESULT to false, ) ) - } + ) + } } private fun handleCenterLoginSuccess() = viewModelScope.launch { - profileRepository.getCenterStatus().onSuccess { centerStatusResponse -> + suspendRunCatching { + profileRepository.getCenterStatus() + }.onSuccess { centerStatusResponse -> navigateBasedOnCenterStatus(centerStatusResponse.centerManagerAccountStatus) }.onFailure { errorHelper.sendError(it) } } @@ -106,7 +112,9 @@ class CenterSignInViewModel @Inject constructor( } private fun fetchAndNavigateToProfile() = viewModelScope.launch { - profileRepository.getMyCenterProfile().onSuccess { + suspendRunCatching { + profileRepository.getMyCenterProfile() + }.onSuccess { navigationHelper.navigateTo(To(CenterHome, R.id.centerSignInFragment)) }.onFailure { val error = it as HttpResponseException diff --git a/feature/signin/src/main/java/com/idle/signin/center/newpassword/NewPasswordViewModel.kt b/feature/signin/src/main/java/com/idle/signin/center/newpassword/NewPasswordViewModel.kt index 1893bcd6..e278d235 100644 --- a/feature/signin/src/main/java/com/idle/signin/center/newpassword/NewPasswordViewModel.kt +++ b/feature/signin/src/main/java/com/idle/signin/center/newpassword/NewPasswordViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.idle.binding.EventHelper import com.idle.binding.MainEvent +import com.idle.common.suspendRunCatching import com.idle.domain.model.CountDownTimer import com.idle.domain.model.CountDownTimer.Companion.SECONDS_PER_MINUTE import com.idle.domain.model.CountDownTimer.Companion.TICK_INTERVAL @@ -149,16 +150,20 @@ class NewPasswordViewModel @Inject constructor( } internal fun sendPhoneNumber() = viewModelScope.launch { - authRepository.sendPhoneNumber(formatPhoneNumber(_phoneNumber.value)) - .onSuccess { startTimer() } - .onFailure { eventHelper.sendEvent(MainEvent.ShowToast(it.message.toString())) } + suspendRunCatching { + authRepository.sendPhoneNumber(formatPhoneNumber(_phoneNumber.value)) + }.onSuccess { + startTimer() + }.onFailure { eventHelper.sendEvent(MainEvent.ShowToast(it.message.toString())) } } internal fun confirmAuthCode() = viewModelScope.launch { - authRepository.confirmAuthCode( - formatPhoneNumber(_phoneNumber.value), - this@NewPasswordViewModel._authCode.value - ).onSuccess { + suspendRunCatching { + authRepository.confirmAuthCode( + formatPhoneNumber(_phoneNumber.value), + this@NewPasswordViewModel._authCode.value + ) + }.onSuccess { cancelTimer() _isConfirmAuthCode.value = true _newPasswordProcess.value = GENERATE_NEW_PASSWORD @@ -180,10 +185,12 @@ class NewPasswordViewModel @Inject constructor( return@launch } - authRepository.generateNewPassword( - newPassword = _newPassword.value, - phoneNumber = formatPhoneNumber(_phoneNumber.value), - ).onSuccess { + suspendRunCatching { + authRepository.generateNewPassword( + newPassword = _newPassword.value, + phoneNumber = formatPhoneNumber(_phoneNumber.value), + ) + }.onSuccess { navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.To( destination = com.idle.navigation.DeepLinkDestination.CenterSignIn("새 비밀번호를 발급하였습니다."), diff --git a/feature/signup/src/main/java/com/idle/signup/center/CenterSignUpViewModel.kt b/feature/signup/src/main/java/com/idle/signup/center/CenterSignUpViewModel.kt index 89b68ef4..68bb04e0 100644 --- a/feature/signup/src/main/java/com/idle/signup/center/CenterSignUpViewModel.kt +++ b/feature/signup/src/main/java/com/idle/signup/center/CenterSignUpViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.idle.binding.EventHelper import com.idle.binding.MainEvent +import com.idle.common.suspendRunCatching import com.idle.domain.model.CountDownTimer import com.idle.domain.model.CountDownTimer.Companion.SECONDS_PER_MINUTE import com.idle.domain.model.CountDownTimer.Companion.TICK_INTERVAL @@ -208,29 +209,32 @@ class CenterSignUpViewModel @Inject constructor( } internal fun sendPhoneNumber() = viewModelScope.launch { - authRepository.sendPhoneNumber(formatPhoneNumber(_centerPhoneNumber.value)) - .onSuccess { startTimer() } - .onFailure { errorHelper.sendError(it) } + suspendRunCatching { + authRepository.sendPhoneNumber(formatPhoneNumber(_centerPhoneNumber.value)) + }.onSuccess { + startTimer() + }.onFailure { errorHelper.sendError(it) } } internal fun confirmAuthCode() = viewModelScope.launch { - authRepository.confirmAuthCode( - formatPhoneNumber(_centerPhoneNumber.value), - _centerAuthCode.value - ) - .onSuccess { - cancelTimer() - _isConfirmAuthCode.value = true - - setCenterSignUpStep(CenterSignUpStep.BUSINESS_REGISTRATION) - }.onFailure { - if (it is HttpResponseException && it.status == HttpResponseStatus.BadRequest) { - _isAuthCodeError.value = true - return@launch - } - - errorHelper.sendError(it) + suspendRunCatching { + authRepository.confirmAuthCode( + formatPhoneNumber(_centerPhoneNumber.value), + _centerAuthCode.value + ) + }.onSuccess { + cancelTimer() + _isConfirmAuthCode.value = true + + setCenterSignUpStep(CenterSignUpStep.BUSINESS_REGISTRATION) + }.onFailure { + if (it is HttpResponseException && it.status == HttpResponseStatus.BadRequest) { + _isAuthCodeError.value = true + return@launch } + + errorHelper.sendError(it) + } } internal fun signUpCenter() = viewModelScope.launch { @@ -241,44 +245,49 @@ class CenterSignUpViewModel @Inject constructor( return@launch } - authRepository.signUpCenter( - identifier = _centerId.value, - password = _centerPassword.value, - phoneNumber = formatPhoneNumber(_centerPhoneNumber.value), - managerName = _centerName.value, - businessRegistrationNumber = formatBusinessRegistrationNumber( - _businessRegistrationNumber.value - ), - ).onSuccess { + suspendRunCatching { + authRepository.signUpCenter( + identifier = _centerId.value, + password = _centerPassword.value, + phoneNumber = formatPhoneNumber(_centerPhoneNumber.value), + managerName = _centerName.value, + businessRegistrationNumber = formatBusinessRegistrationNumber( + _businessRegistrationNumber.value + ), + ) + }.onSuccess { navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.To( com.idle.navigation.DeepLinkDestination.CenterSignIn("회원가입을 성공하였습니다."), R.id.centerSignUpFragment ) ) - } - .onFailure { errorHelper.sendError(it) } + }.onFailure { errorHelper.sendError(it) } } internal fun validateIdentifier() = viewModelScope.launch { eventHelper.sendEvent(MainEvent.DismissToast) - authRepository.validateIdentifier(_centerId.value) - .onSuccess { _centerIdResult.value = true } - .onFailure { - if (it is HttpResponseException && it.apiErrorCode == ApiErrorCode.DuplicateIdentifier) { - _centerIdResult.value = false - return@onFailure - } - - errorHelper.sendError(it) + suspendRunCatching { + authRepository.validateIdentifier(_centerId.value) + }.onSuccess { + _centerIdResult.value = true + }.onFailure { + if (it is HttpResponseException && it.apiErrorCode == ApiErrorCode.DuplicateIdentifier) { + _centerIdResult.value = false + return@onFailure } + + errorHelper.sendError(it) + } } internal fun validateBusinessRegistrationNumber() = viewModelScope.launch { - authRepository.validateBusinessRegistrationNumber( - formatBusinessRegistrationNumber(_businessRegistrationNumber.value) - ).onSuccess { + suspendRunCatching { + authRepository.validateBusinessRegistrationNumber( + formatBusinessRegistrationNumber(_businessRegistrationNumber.value) + ) + }.onSuccess { _businessRegistrationInfo.value = it }.onFailure { errorHelper.sendError(it) } } diff --git a/feature/signup/src/main/java/com/idle/signup/worker/WorkerSignUpViewModel.kt b/feature/signup/src/main/java/com/idle/signup/worker/WorkerSignUpViewModel.kt index f7414074..b79f2484 100644 --- a/feature/signup/src/main/java/com/idle/signup/worker/WorkerSignUpViewModel.kt +++ b/feature/signup/src/main/java/com/idle/signup/worker/WorkerSignUpViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.idle.analytics.AnalyticsHelper import com.idle.binding.EventHelper +import com.idle.common.suspendRunCatching import com.idle.domain.model.CountDownTimer import com.idle.domain.model.CountDownTimer.Companion.SECONDS_PER_MINUTE import com.idle.domain.model.CountDownTimer.Companion.TICK_INTERVAL @@ -113,9 +114,11 @@ class WorkerSignUpViewModel @Inject constructor( } internal fun sendPhoneNumber() = viewModelScope.launch { - authRepository.sendPhoneNumber(formatPhoneNumber(_workerPhoneNumber.value)) - .onSuccess { startTimer() } - .onFailure { errorHelper.sendError(it) } + suspendRunCatching { + authRepository.sendPhoneNumber(formatPhoneNumber(_workerPhoneNumber.value)) + }.onSuccess { + startTimer() + }.onFailure { errorHelper.sendError(it) } } private fun startTimer() { @@ -146,11 +149,15 @@ class WorkerSignUpViewModel @Inject constructor( } internal fun confirmAuthCode() = viewModelScope.launch { - authRepository.signInWorker( - phoneNumber = formatPhoneNumber(_workerPhoneNumber.value), - authCode = _workerAuthCode.value, - ).onSuccess { - profileRepository.getWorkerId().onSuccess { analyticsHelper.setUserId(it) } + suspendRunCatching { + authRepository.signInWorker( + phoneNumber = formatPhoneNumber(_workerPhoneNumber.value), + authCode = _workerAuthCode.value, + ) + }.onSuccess { + suspendRunCatching { + profileRepository.getWorkerId() + }.onSuccess { analyticsHelper.setUserId(it) } navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.To( WorkerHome, @@ -158,10 +165,12 @@ class WorkerSignUpViewModel @Inject constructor( ) ) }.onFailure { - authRepository.confirmAuthCode( - formatPhoneNumber(_workerPhoneNumber.value), - _workerAuthCode.value - ).onSuccess { + suspendRunCatching { + authRepository.confirmAuthCode( + formatPhoneNumber(_workerPhoneNumber.value), + _workerAuthCode.value + ) + }.onSuccess { cancelTimer() _isConfirmAuthCode.value = true _signUpStep.value = WorkerSignUpStep.findStep(PHONE_NUMBER.step + 1) @@ -177,15 +186,19 @@ class WorkerSignUpViewModel @Inject constructor( } internal fun signUpWorker() = viewModelScope.launch { - authRepository.signUpWorker( - name = _workerName.value, - birthYear = _birthYear.value.toIntOrNull() ?: return@launch, - genderType = _gender.value.name, - phoneNumber = formatPhoneNumber(_workerPhoneNumber.value), - roadNameAddress = _roadNameAddress.value, - lotNumberAddress = _lotNumberAddress.value, - ).onSuccess { - profileRepository.getWorkerId().onSuccess { analyticsHelper.setUserId(it) } + suspendRunCatching { + authRepository.signUpWorker( + name = _workerName.value, + birthYear = _birthYear.value.toIntOrNull() ?: return@suspendRunCatching, + genderType = _gender.value.name, + phoneNumber = formatPhoneNumber(_workerPhoneNumber.value), + roadNameAddress = _roadNameAddress.value, + lotNumberAddress = _lotNumberAddress.value, + ) + }.onSuccess { + suspendRunCatching { + profileRepository.getWorkerId() + }.onSuccess { analyticsHelper.setUserId(it) } navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.To( SignUpComplete, diff --git a/feature/withdrawal/src/main/java/com/idle/withdrawal/WithdrawalViewModel.kt b/feature/withdrawal/src/main/java/com/idle/withdrawal/WithdrawalViewModel.kt index 50d71a2d..85300b5d 100644 --- a/feature/withdrawal/src/main/java/com/idle/withdrawal/WithdrawalViewModel.kt +++ b/feature/withdrawal/src/main/java/com/idle/withdrawal/WithdrawalViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.idle.analytics.AnalyticsHelper import com.idle.binding.EventHelper import com.idle.binding.MainEvent +import com.idle.common.suspendRunCatching import com.idle.domain.model.CountDownTimer import com.idle.domain.model.CountDownTimer.Companion.SECONDS_PER_MINUTE import com.idle.domain.model.CountDownTimer.Companion.TICK_INTERVAL @@ -87,9 +88,11 @@ class WithdrawalViewModel @Inject constructor( } internal fun sendPhoneNumber() = viewModelScope.launch { - authRepository.sendPhoneNumber(formatPhoneNumber(_phoneNumber.value)) - .onSuccess { startTimer() } - .onFailure { errorHelper.sendError(it) } + suspendRunCatching { + authRepository.sendPhoneNumber(formatPhoneNumber(_phoneNumber.value)) + }.onSuccess { + startTimer() + }.onFailure { errorHelper.sendError(it) } } internal fun setInconvenientReason(reason: String) { @@ -134,12 +137,12 @@ class WithdrawalViewModel @Inject constructor( } internal fun confirmAuthCode() = viewModelScope.launch { - authRepository.confirmAuthCode(formatPhoneNumber(_phoneNumber.value), _authCode.value) - .onSuccess { - cancelTimer() - _isConfirmAuthCode.value = true - } - .onFailure { errorHelper.sendError(it) } + suspendRunCatching { + authRepository.confirmAuthCode(formatPhoneNumber(_phoneNumber.value), _authCode.value) + }.onSuccess { + cancelTimer() + _isConfirmAuthCode.value = true + }.onFailure { errorHelper.sendError(it) } } internal fun withdrawal(userType: UserType) = viewModelScope.launch { @@ -150,20 +153,22 @@ class WithdrawalViewModel @Inject constructor( } private suspend fun withdrawalCenter() { - authRepository.withdrawalCenter( - reason = _withdrawalReason.value - .sortedBy { it.ordinal } - .map { reason -> - when (reason) { - WithdrawalReason.INCONVENIENT_PLATFORM_USE -> "${reason} : ${_inconvenientReason.value}" - WithdrawalReason.USING_ANOTHER_PLATFORM -> "${reason} : ${_anotherPlatformReason.value}" - WithdrawalReason.LACK_OF_DESIRED_FEATURES -> "${reason} : ${_lackFeaturesReason.value}" - else -> reason + suspendRunCatching { + authRepository.withdrawalCenter( + reason = _withdrawalReason.value + .sortedBy { it.ordinal } + .map { reason -> + when (reason) { + WithdrawalReason.INCONVENIENT_PLATFORM_USE -> "${reason} : ${_inconvenientReason.value}" + WithdrawalReason.USING_ANOTHER_PLATFORM -> "${reason} : ${_anotherPlatformReason.value}" + WithdrawalReason.LACK_OF_DESIRED_FEATURES -> "${reason} : ${_lackFeaturesReason.value}" + else -> reason + } } - } - .joinToString("|"), - password = password.value - ).onSuccess { + .joinToString("|"), + password = password.value + ) + }.onSuccess { analyticsHelper.setUserId(null) navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( @@ -181,11 +186,13 @@ class WithdrawalViewModel @Inject constructor( } private suspend fun withdrawalWorker() { - authRepository.withdrawalWorker( - _withdrawalReason.value - .sortedBy { it.ordinal } - .joinToString("|"), - ).onSuccess { + suspendRunCatching { + authRepository.withdrawalWorker( + _withdrawalReason.value + .sortedBy { it.ordinal } + .joinToString("|"), + ) + }.onSuccess { analyticsHelper.setUserId(null) navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( diff --git a/feature/worker-chatting/src/main/java/com/idle/worker/chatting/WorkerChattingViewModel.kt b/feature/worker-chatting/src/main/java/com/idle/worker/chatting/WorkerChattingViewModel.kt index a05be80c..3668eec2 100644 --- a/feature/worker-chatting/src/main/java/com/idle/worker/chatting/WorkerChattingViewModel.kt +++ b/feature/worker-chatting/src/main/java/com/idle/worker/chatting/WorkerChattingViewModel.kt @@ -2,6 +2,7 @@ package com.idle.worker.chatting import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.idle.common.suspendRunCatching import com.idle.domain.model.auth.UserType import com.idle.domain.model.chat.ChatMessage import com.idle.domain.model.chat.ChatRoomWithOpponentInfo @@ -44,16 +45,22 @@ class WorkerChattingViewModel @Inject constructor( ) internal suspend fun initWorkerChatting() { - getMyWorkerProfileUseCase().onSuccess { profile -> + suspendRunCatching { + getMyWorkerProfileUseCase() + }.onSuccess { profile -> _myProfile.value = profile }.onFailure { errorHelper.sendError(it) } } internal suspend fun retrieveChatRoomList() { - getChatRoomsUseCase( - userType = UserType.WORKER, - userId = _myProfile.value?.workerId ?: return, - ).onSuccess { + val workerId = _myProfile.value?.workerId ?: return + + suspendRunCatching { + getChatRoomsUseCase( + userType = UserType.WORKER, + userId = workerId, + ) + }.onSuccess { val newMap = LinkedHashMap(_chatRoomMap.value) it.forEach { chatRoom -> newMap[chatRoom.id] = chatRoom } _chatRoomMap.value = newMap @@ -61,10 +68,14 @@ class WorkerChattingViewModel @Inject constructor( } internal suspend fun loadChatRoomList() { - chatRepository.loadChatRooms( - userId = _myProfile.value?.workerId ?: return, - userType = UserType.WORKER, - ).onSuccess { + val workerId = _myProfile.value?.workerId ?: return + + suspendRunCatching { + chatRepository.loadChatRooms( + userId = workerId, + userType = UserType.WORKER, + ) + }.onSuccess { val newMap = LinkedHashMap(_chatRoomMap.value) it.forEach { chatRoom -> newMap[chatRoom.id] = chatRoom } _chatRoomMap.value = newMap @@ -72,7 +83,9 @@ class WorkerChattingViewModel @Inject constructor( } internal fun connectWebsocket() = viewModelScope.launch { - chatRepository.connectWebSocket().onSuccess { + suspendRunCatching { + chatRepository.connectWebSocket() + }.onSuccess { subscribeChatMessage() } } @@ -107,8 +120,9 @@ class WorkerChattingViewModel @Inject constructor( ) } else { // 새로운 방이면 새로 생성 후 최상단에 추가 - val opponentProfile = profileRepository.getCenterProfile(chatMessage.senderId) - .getOrNull() ?: return + val opponentProfile = suspendRunCatching { + profileRepository.getCenterProfile(chatMessage.senderId) + }.getOrNull() ?: return val newChatRoom = ChatRoomWithOpponentInfo( id = roomId, diff --git a/feature/worker-home/src/main/java/com/idle/worker/home/WorkerHomeViewModel.kt b/feature/worker-home/src/main/java/com/idle/worker/home/WorkerHomeViewModel.kt index 305027df..1b41ccf3 100644 --- a/feature/worker-home/src/main/java/com/idle/worker/home/WorkerHomeViewModel.kt +++ b/feature/worker-home/src/main/java/com/idle/worker/home/WorkerHomeViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.idle.binding.EventHelper import com.idle.binding.MainEvent import com.idle.binding.ToastType +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.jobposting.ApplyMethod import com.idle.domain.model.jobposting.CrawlingJobPosting @@ -65,16 +66,20 @@ class WorkerHomeViewModel @Inject constructor( } internal fun getUnreadNotificationCount() = viewModelScope.launch { - notificationRepository.getUnreadNotificationCount().onSuccess { + suspendRunCatching { + notificationRepository.getUnreadNotificationCount() + }.onSuccess { _unreadNotificationCount.value = it }.onFailure { errorHelper.sendError(it) } } internal fun applyJobPosting(jobPostingId: String) = viewModelScope.launch { - jobPostingRepository.applyJobPosting( - jobPostingId = jobPostingId, - applyMethod = ApplyMethod.APP - ).onSuccess { + suspendRunCatching { + jobPostingRepository.applyJobPosting( + jobPostingId = jobPostingId, + applyMethod = ApplyMethod.APP + ) + }.onSuccess { eventHelper.sendEvent(MainEvent.ShowToast("지원이 완료되었어요.", ToastType.SUCCESS)) _jobPostings.value = _jobPostings.value?.map { @@ -90,10 +95,12 @@ class WorkerHomeViewModel @Inject constructor( jobPostingId: String, jobPostingType: JobPostingType, ) = viewModelScope.launch { - jobPostingRepository.addFavoriteJobPosting( - jobPostingId = jobPostingId, - jobPostingType = jobPostingType, - ).onSuccess { + suspendRunCatching { + jobPostingRepository.addFavoriteJobPosting( + jobPostingId = jobPostingId, + jobPostingType = jobPostingType, + ) + }.onSuccess { eventHelper.sendEvent(MainEvent.ShowToast("즐겨찾기에 추가되었어요.", ToastType.SUCCESS)) _jobPostings.value = _jobPostings.value?.map { @@ -113,7 +120,9 @@ class WorkerHomeViewModel @Inject constructor( } internal fun removeFavoriteJobPosting(jobPostingId: String) = viewModelScope.launch { - jobPostingRepository.removeFavoriteJobPosting(jobPostingId = jobPostingId).onSuccess { + suspendRunCatching { + jobPostingRepository.removeFavoriteJobPosting(jobPostingId = jobPostingId) + }.onSuccess { eventHelper.sendEvent(MainEvent.ShowToast("즐겨찾기에서 제거되었어요", ToastType.SUCCESS)) _jobPostings.value = _jobPostings.value?.map { @@ -133,7 +142,9 @@ class WorkerHomeViewModel @Inject constructor( } internal fun getMyWorkerProfile() = viewModelScope.launch { - getMyWorkerProfileUseCase().onSuccess { + suspendRunCatching { + getMyWorkerProfileUseCase() + }.onSuccess { _profile.value = it }.onFailure { eventHelper.sendEvent(MainEvent.ShowToast(it.message.toString())) @@ -154,25 +165,28 @@ class WorkerHomeViewModel @Inject constructor( } private suspend fun fetchInAppJobPostings() { - jobPostingRepository.getJobPostings(next = nextCursorId) - .onSuccess { (nextId, postings) -> - nextCursorId = nextId - if (nextId == null) { - _callType.value = JobPostingCallType.CRAWLING - } - _jobPostings.value = _jobPostings.value?.plus(postings) ?: postings + suspendRunCatching { + jobPostingRepository.getJobPostings(next = nextCursorId) + }.onSuccess { (nextId, postings) -> + nextCursorId = nextId + if (nextId == null) { + _callType.value = JobPostingCallType.CRAWLING + } + _jobPostings.value = _jobPostings.value?.plus(postings) ?: postings - if (_jobPostings.value?.isEmpty() != false) { - getJobPostings() - } - }.onFailure { errorHelper.sendError(it) } + if (_jobPostings.value?.isEmpty() != false) { + getJobPostings() + } + }.onFailure { errorHelper.sendError(it) } } private suspend fun fetchCrawlingJobPostings() { - jobPostingRepository.getCrawlingJobPostings( - next = nextCursorId, - distance = nextDistance, - ).onSuccess { pageInfo -> + suspendRunCatching { + jobPostingRepository.getCrawlingJobPostings( + next = nextCursorId, + distance = nextDistance, + ) + }.onSuccess { pageInfo -> nextCursorId = pageInfo.nextCursor nextDistance = pageInfo.nextDistance diff --git a/feature/worker-job-posting/src/main/java/com/idle/worker/job/posting/WorkerJobPostingViewModel.kt b/feature/worker-job-posting/src/main/java/com/idle/worker/job/posting/WorkerJobPostingViewModel.kt index 4214cd04..833c9e06 100644 --- a/feature/worker-job-posting/src/main/java/com/idle/worker/job/posting/WorkerJobPostingViewModel.kt +++ b/feature/worker-job-posting/src/main/java/com/idle/worker/job/posting/WorkerJobPostingViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.idle.binding.EventHelper import com.idle.binding.MainEvent import com.idle.binding.ToastType +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.jobposting.ApplyMethod import com.idle.domain.model.jobposting.CrawlingJobPosting @@ -49,7 +50,9 @@ class WorkerJobPostingViewModel @Inject constructor( init { viewModelScope.launch { - getMyWorkerProfileUseCase().onSuccess { + suspendRunCatching { + getMyWorkerProfileUseCase() + }.onSuccess { _profile.value = it } } @@ -74,17 +77,18 @@ class WorkerJobPostingViewModel @Inject constructor( return@launch } - jobPostingRepository.getJobPostingsApplied(next = nextCursorId) - .onSuccess { nextPage -> - nextCursorId = nextPage.nextCursor + suspendRunCatching { + jobPostingRepository.getJobPostingsApplied(next = nextCursorId) + }.onSuccess { nextPage -> + nextCursorId = nextPage.nextCursor - if (nextPage.nextCursor == null) { - appliedJobPostingCallType = JobPostingCallType.END - } + if (nextPage.nextCursor == null) { + appliedJobPostingCallType = JobPostingCallType.END + } - _appliedJobPostings.value = - _appliedJobPostings.value?.plus(nextPage.items) ?: nextPage.items - }.onFailure { errorHelper.sendError(it) } + _appliedJobPostings.value = + _appliedJobPostings.value?.plus(nextPage.items) ?: nextPage.items + }.onFailure { errorHelper.sendError(it) } } finally { isLoading = false } @@ -96,22 +100,28 @@ class WorkerJobPostingViewModel @Inject constructor( } private suspend fun getFavoriteCareMeetJobPostings() { - jobPostingRepository.getMyFavoritesJobPostings().onSuccess { postings -> + suspendRunCatching { + jobPostingRepository.getMyFavoritesJobPostings() + }.onSuccess { postings -> _favoriteJobPostings.value = _favoriteJobPostings.value?.plus(postings) ?: postings }.onFailure { errorHelper.sendError(it) } } private suspend fun getFavoriteCrawlingJobPostings() { - jobPostingRepository.getMyFavoritesCrawlingJobPostings().onSuccess { postings -> + suspendRunCatching { + jobPostingRepository.getMyFavoritesCrawlingJobPostings() + }.onSuccess { postings -> _favoriteJobPostings.value = _favoriteJobPostings.value?.plus(postings) ?: postings }.onFailure { errorHelper.sendError(it) } } internal fun applyJobPosting(jobPostingId: String) = viewModelScope.launch { - jobPostingRepository.applyJobPosting( - jobPostingId = jobPostingId, - applyMethod = ApplyMethod.APP - ).onSuccess { + suspendRunCatching { + jobPostingRepository.applyJobPosting( + jobPostingId = jobPostingId, + applyMethod = ApplyMethod.APP + ) + }.onSuccess { eventHelper.sendEvent(MainEvent.ShowToast("지원이 완료되었어요.", ToastType.SUCCESS)) _appliedJobPostings.value = _appliedJobPostings.value?.map { @@ -134,10 +144,12 @@ class WorkerJobPostingViewModel @Inject constructor( jobPostingId: String, jobPostingType: JobPostingType, ) = viewModelScope.launch { - jobPostingRepository.addFavoriteJobPosting( - jobPostingId = jobPostingId, - jobPostingType = jobPostingType, - ).onSuccess { + suspendRunCatching { + jobPostingRepository.addFavoriteJobPosting( + jobPostingId = jobPostingId, + jobPostingType = jobPostingType, + ) + }.onSuccess { eventHelper.sendEvent(MainEvent.ShowToast("즐겨찾기에 추가되었어요.", ToastType.SUCCESS)) _appliedJobPostings.value = _appliedJobPostings.value?.map { @@ -171,7 +183,9 @@ class WorkerJobPostingViewModel @Inject constructor( } internal fun removeFavoriteJobPosting(jobPostingId: String) = viewModelScope.launch { - jobPostingRepository.removeFavoriteJobPosting(jobPostingId = jobPostingId).onSuccess { + suspendRunCatching { + jobPostingRepository.removeFavoriteJobPosting(jobPostingId = jobPostingId) + }.onSuccess { eventHelper.sendEvent(MainEvent.ShowToast("즐겨찾기에서 제거했어요.", ToastType.SUCCESS)) _appliedJobPostings.value = _appliedJobPostings.value?.map { diff --git a/feature/worker-profile/src/main/java/com/idle/worker/profile/WorkerProfileViewModel.kt b/feature/worker-profile/src/main/java/com/idle/worker/profile/WorkerProfileViewModel.kt index 71c1d4e3..bfe1982a 100644 --- a/feature/worker-profile/src/main/java/com/idle/worker/profile/WorkerProfileViewModel.kt +++ b/feature/worker-profile/src/main/java/com/idle/worker/profile/WorkerProfileViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope import com.idle.binding.EventHelper import com.idle.binding.MainEvent import com.idle.binding.ToastType +import com.idle.common.suspendRunCatching import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.profile.JobSearchStatus import com.idle.domain.model.profile.WorkerProfile @@ -92,7 +93,9 @@ class WorkerProfileViewModel @Inject constructor( } internal fun getMyWorkerProfile() = viewModelScope.launch { - getMyWorkerProfileUseCase().onSuccess { + suspendRunCatching { + getMyWorkerProfileUseCase() + }.onSuccess { _workerProfile.value = it _workerIntroduce.value = it.introduce ?: "" _specialty.value = it.speciality ?: "" @@ -105,7 +108,9 @@ class WorkerProfileViewModel @Inject constructor( } internal fun getWorkerProfile(workerId: String) = viewModelScope.launch { - profileRepository.getWorkerProfile(workerId).onSuccess { + suspendRunCatching { + profileRepository.getWorkerProfile(workerId) + }.onSuccess { _workerProfile.value = it _workerIntroduce.value = it.introduce ?: "" _specialty.value = it.speciality ?: "" @@ -126,15 +131,17 @@ class WorkerProfileViewModel @Inject constructor( _isUpdateLoading.value = true - updateWorkerProfileUseCase( - experienceYear = _experienceYear.value, - roadNameAddress = _roadNameAddress.value, - lotNumberAddress = _lotNumberAddress.value, - speciality = _specialty.value, - introduce = _workerIntroduce.value.ifBlank { null }, - imageFileUri = _profileImageUri.value?.toString(), - jobSearchStatus = _jobSearchStatus.value, - ).onSuccess { + suspendRunCatching { + updateWorkerProfileUseCase( + experienceYear = _experienceYear.value, + roadNameAddress = _roadNameAddress.value, + lotNumberAddress = _lotNumberAddress.value, + speciality = _specialty.value, + introduce = _workerIntroduce.value.ifBlank { null }, + imageFileUri = _profileImageUri.value?.toString(), + jobSearchStatus = _jobSearchStatus.value, + ) + }.onSuccess { getMyWorkerProfile() eventHelper.sendEvent( MainEvent.ShowToast( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2e540c76..795d6e7e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -60,7 +60,7 @@ okhttp = "4.12.0" retrofit = "2.11.0" # KrossBBow ## https://github.com/joffrey-bion/krossbow -krossbow = "9.0.0" +krossbow = "9.3.0" ## Kotlin # https://github.com/JetBrains/kotlin diff --git a/presentation/src/main/java/com/idle/presentation/MainViewModel.kt b/presentation/src/main/java/com/idle/presentation/MainViewModel.kt index 0cc52733..ddc5c391 100644 --- a/presentation/src/main/java/com/idle/presentation/MainViewModel.kt +++ b/presentation/src/main/java/com/idle/presentation/MainViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.idle.auth.R import com.idle.binding.EventHelper import com.idle.binding.MainEvent.ShowToast +import com.idle.common.suspendRunCatching import com.idle.domain.model.auth.UserType import com.idle.domain.model.config.ForceUpdate import com.idle.domain.model.error.ApiErrorCode @@ -59,7 +60,9 @@ class MainViewModel @Inject constructor( } internal fun getForceUpdateInfo() = viewModelScope.launch { - configRepository.getForceUpdate().onSuccess { + suspendRunCatching { + configRepository.getForceUpdate() + }.onSuccess { _forceUpdate.value = it }.onFailure { errorHelper.sendError(it) } } @@ -72,7 +75,9 @@ class MainViewModel @Inject constructor( } if (userRole == UserType.WORKER.apiValue) { - profileRepository.getMyWorkerProfile().onFailure { + suspendRunCatching { + profileRepository.getMyWorkerProfile() + }.onFailure { return@launch } } @@ -85,8 +90,9 @@ class MainViewModel @Inject constructor( } internal fun readNotification(notificationId: String) = viewModelScope.launch { - notificationRepository.readNotification(notificationId) - .onFailure { errorHelper.sendError(it) } + suspendRunCatching { + notificationRepository.readNotification(notificationId) + }.onFailure { errorHelper.sendError(it) } } private suspend fun getAccessTokenAndUserRole(): Pair = coroutineScope { @@ -109,10 +115,11 @@ class MainViewModel @Inject constructor( } } - private suspend fun getCenterStatus() = - profileRepository.getCenterStatus().onSuccess { centerStatusResponse -> - handleCenterStatus(centerStatusResponse.centerManagerAccountStatus) - } + private suspend fun getCenterStatus() = suspendRunCatching { + profileRepository.getCenterStatus() + }.onSuccess { centerStatusResponse -> + handleCenterStatus(centerStatusResponse.centerManagerAccountStatus) + } private fun handleCenterStatus(status: CenterManagerAccountStatus) { when (status) { @@ -127,7 +134,9 @@ class MainViewModel @Inject constructor( } private fun handleApprovedCenterStatus() = viewModelScope.launch { - profileRepository.getMyCenterProfile().onSuccess { + suspendRunCatching { + profileRepository.getMyCenterProfile() + }.onSuccess { navigationHelper.navigateTo(NavigationEvent.To(CenterHome, R.id.authFragment)) }.onFailure { val error = it as HttpResponseException