diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4804b9608..16569147d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -14,7 +14,7 @@ android { defaultConfig { versionCode = 21 - versionName = "1.2.6" + versionName = "1.2.7" targetSdk = 35 testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/com/idle/care/CareApplication.kt b/app/src/main/java/com/idle/care/CareApplication.kt index 8de3a496f..7109a244c 100644 --- a/app/src/main/java/com/idle/care/CareApplication.kt +++ b/app/src/main/java/com/idle/care/CareApplication.kt @@ -1,12 +1,9 @@ package com.idle.care import android.app.Application -import android.app.NotificationChannel -import android.app.NotificationManager import com.appsflyer.AppsFlyerLib import com.appsflyer.attribution.AppsFlyerRequestListener -import com.idle.care.notification.NotificationHandler.Companion.BACKGROUND_CHANNEL -import com.idle.care.notification.NotificationHandler.Companion.BACKGROUND_DESCRIPTION +import com.idle.care.notification.NotificationService.Companion.initNotification import com.idle.domain.model.error.ErrorHelper import com.kakao.sdk.common.KakaoSdk import dagger.hilt.android.HiltAndroidApp @@ -22,24 +19,11 @@ class CareApplication : Application() { override fun onCreate() { super.onCreate() - initNotification() + initNotification(this) initKakao() initAppsFlyer() } - private fun initNotification() { - val channel = - NotificationChannel( - BACKGROUND_CHANNEL, - BACKGROUND_CHANNEL, - NotificationManager.IMPORTANCE_DEFAULT - ) - channel.description = BACKGROUND_DESCRIPTION - - val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager - notificationManager.createNotificationChannel(channel) - } - private fun initKakao() { KakaoSdk.init(this, BuildConfig.KAKAO_APP_KEY) } diff --git a/app/src/main/java/com/idle/care/di/AppModule.kt b/app/src/main/java/com/idle/care/di/AppModule.kt deleted file mode 100644 index 7f60936a5..000000000 --- a/app/src/main/java/com/idle/care/di/AppModule.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.idle.care.di - -import android.content.Context -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@InstallIn(SingletonComponent::class) -@Module -object AppModule { - - @Provides - @Singleton - fun provideNotificationHandler( - @ApplicationContext context: Context - ): com.idle.care.notification.NotificationHandler = - com.idle.care.notification.NotificationHandler(context) -} \ No newline at end of file diff --git a/app/src/main/java/com/idle/care/notification/NotificationHandler.kt b/app/src/main/java/com/idle/care/notification/NotificationHandler.kt deleted file mode 100644 index e1d461482..000000000 --- a/app/src/main/java/com/idle/care/notification/NotificationHandler.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.idle.care.notification - -import android.app.NotificationManager -import android.app.PendingIntent -import android.content.Context -import android.content.Intent -import androidx.core.app.NotificationCompat -import androidx.core.content.ContextCompat -import com.idle.designsystem.binding.R -import com.idle.presentation.MainActivity -import javax.inject.Inject - -class NotificationHandler @Inject constructor(private val context: Context) { - private val notificationManager: NotificationManager = - context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - - internal fun deliverNotification( - title: String, - body: String, - data: Map - ) { - val intent = Intent(context, MainActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP - } - - if (data.isNotEmpty()) { - data.forEach { (key, value) -> - intent.putExtra(key, value) - } - } - - val pendingIntent = PendingIntent.getActivity( - context, - 0, - intent, - PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE, - ) - - val builder = NotificationCompat.Builder(context, BACKGROUND_CHANNEL) - .setSmallIcon(com.idle.care.R.drawable.ic_notification_icon) - .setColor(ContextCompat.getColor(context, R.color.orange_500)) - .setContentTitle(title) - .setContentText(body) - .setContentIntent(pendingIntent) - .setAutoCancel(true) - - notificationManager.notify(System.currentTimeMillis().toInt(), builder.build()) - } - - companion object { - const val BACKGROUND_CHANNEL = "백그라운드 알림" - const val BACKGROUND_DESCRIPTION = - "센터장 : 공고 지원자 확인, 요양보호사 : 희망 공고가 게시되었을 때의 알림을 받을 수 있는 채널입니다." - } -} \ No newline at end of file diff --git a/app/src/main/java/com/idle/care/notification/NotificationService.kt b/app/src/main/java/com/idle/care/notification/NotificationService.kt index cfd2c78e4..8a28123ea 100644 --- a/app/src/main/java/com/idle/care/notification/NotificationService.kt +++ b/app/src/main/java/com/idle/care/notification/NotificationService.kt @@ -1,10 +1,19 @@ package com.idle.care.notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import androidx.core.app.NotificationCompat +import androidx.core.content.ContextCompat import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage +import com.idle.designsystem.binding.R import com.idle.domain.model.error.ErrorHelper import com.idle.domain.repositorry.ProfileRepository import com.idle.domain.repositorry.TokenRepository +import com.idle.presentation.MainActivity import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope @@ -23,12 +32,13 @@ class NotificationService : FirebaseMessagingService() { @Inject lateinit var profileRepository: ProfileRepository - @Inject - lateinit var notificationHandler: NotificationHandler - @Inject lateinit var errorHelper: ErrorHelper + private val notificationManager: NotificationManager = + getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + private val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable -> errorHelper.logError(throwable) } @@ -56,15 +66,68 @@ class NotificationService : FirebaseMessagingService() { val body = message.notification?.body ?: "" val data = message.data - notificationHandler.deliverNotification( + deliverNotification( title = title, body = body, data = data, ) } + internal fun deliverNotification( + title: String, + body: String, + data: Map + ) { + val intent = Intent(this, MainActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP + } + + if (data.isNotEmpty()) { + data.forEach { (key, value) -> + intent.putExtra(key, value) + } + } + + val pendingIntent = PendingIntent.getActivity( + this, + 0, + intent, + PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE, + ) + + val builder = NotificationCompat.Builder(this, BACKGROUND_CHANNEL) + .setSmallIcon(com.idle.care.R.drawable.ic_notification_icon) + .setColor(ContextCompat.getColor(this, R.color.orange_500)) + .setContentTitle(title) + .setContentText(body) + .setContentIntent(pendingIntent) + .setAutoCancel(true) + + notificationManager.notify(System.currentTimeMillis().toInt(), builder.build()) + } + override fun onDestroy() { super.onDestroy() scope.cancel() } + + companion object { + private const val BACKGROUND_CHANNEL = "백그라운드 알림" + private const val BACKGROUND_DESCRIPTION = + "센터장 : 공고 지원자 확인, 요양보호사 : 희망 공고가 게시되었을 때의 알림을 받을 수 있는 채널입니다." + + fun initNotification(context: Context) { + val channel = + NotificationChannel( + BACKGROUND_CHANNEL, + BACKGROUND_CHANNEL, + NotificationManager.IMPORTANCE_DEFAULT + ) + channel.description = BACKGROUND_DESCRIPTION + + val notificationManager = + context.getSystemService(NOTIFICATION_SERVICE) as NotificationManager + notificationManager.createNotificationChannel(channel) + } + } } 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 82915c4d0..e2c1f94a1 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 @@ -12,7 +12,7 @@ import com.idle.network.model.chat.ReadMessageRequest import com.idle.network.model.chat.SendMessageRequest import com.idle.network.source.ChatDataSource import com.idle.network.util.MAX_RETRY_ATTEMPTS -import com.idle.network.util.calculateBackoffTime +import com.idle.network.util.calculateRetryTime import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -174,6 +174,7 @@ class ChatRepositoryImpl @Inject constructor( } localChatDataSource.insertMessage(message, userId) } + is ReadMessage -> { if (message.opponentId != userId) { localChatDataSource.readMessages( @@ -190,7 +191,7 @@ class ChatRepositoryImpl @Inject constructor( .retryWhen { cause, attempt -> if (cause is IOException && attempt < MAX_RETRY_ATTEMPTS) { connectWebSocket() - delay(calculateBackoffTime(attempt.toInt())) + delay(calculateRetryTime(attempt.toInt())) true } else { false 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 ca23232dd..c9e925cfa 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 @@ -21,7 +21,9 @@ import com.idle.network.model.profile.UpdateWorkerProfileRequest import com.idle.network.model.profile.UploadProfileImageUrlResponse import com.idle.network.source.ProfileDataSource import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.InputStream @@ -35,49 +37,66 @@ class ProfileRepositoryImpl @Inject constructor( override suspend fun getMyUserType() = userInfoDataSource.userType.first() override suspend fun getMyCenterProfile(): CenterProfile { - val centerProfile = profileDataSource.getMyCenterProfile() - .toVO() + val localProfile = userInfoDataSource.getLocalCenterProfile() + if (localProfile != null) return localProfile + val centerProfile = profileDataSource.getMyCenterProfile().toVO() userInfoDataSource.setUserInfo(centerProfile.toString()) return centerProfile } - override suspend fun getLocalMyCenterProfile(): CenterProfile = - userInfoDataSource.getLocalCenterProfile() - override suspend fun getCenterProfile(centerId: String): CenterProfile = profileDataSource.getCenterProfile(centerId).toVO() override suspend fun getMyWorkerProfile(): WorkerProfile { - val workerProfile = profileDataSource.getMyWorkerProfile().toVo() + val localProfile = userInfoDataSource.getLocalWorkerProfile() + if (localProfile != null) return localProfile + val workerProfile = profileDataSource.getMyWorkerProfile().toVo() userInfoDataSource.setUserInfo(workerProfile.toString()) return workerProfile } - override suspend fun getLocalMyWorkerProfile(): WorkerProfile = - userInfoDataSource.getLocalWorkerProfile() - override suspend fun getWorkerProfile(workerId: String): WorkerProfile = profileDataSource.getWorkerProfile(workerId).toVo() + override suspend fun getWorkerId(): String = profileDataSource.getWorkerId() + .carerId + + override suspend fun getCenterStatus(): CenterRegistrationStatus = + profileDataSource.getCenterStatus().toVO() + override suspend fun updateCenterProfile( officeNumber: String, introduce: String?, + imageFileUri: String?, ) { - profileDataSource.updateMyCenterProfile( - UpdateCenterProfileRequest(officeNumber = officeNumber, introduce = introduce) - ) - - val updatedProfile = getMyCenterProfile() - userInfoDataSource.setUserInfo(updatedProfile.toString()) - } + coroutineScope { + val updateProfileJob = launch { + profileDataSource.updateMyCenterProfile( + UpdateCenterProfileRequest(officeNumber = officeNumber, introduce = introduce) + ) + } - override suspend fun getWorkerId(): String = profileDataSource.getWorkerId() - .carerId + val profileImageJob = imageFileUri?.let { uri -> + launch { + if (uri.isContentUri()) { + updateProfileImage( + userType = UserType.CENTER.apiValue, + imageFileUri = imageFileUri, + reqWidth = 1340, + reqHeight = 1016, + ) + } + } + } - override suspend fun getCenterStatus(): CenterRegistrationStatus = - profileDataSource.getCenterStatus().toVO() + updateProfileJob.join() + profileImageJob?.join() + val updatedProfile = getMyCenterProfile() + userInfoDataSource.setUserInfo(updatedProfile.toString()) + } + } override suspend fun updateWorkerProfile( experienceYear: Int?, @@ -85,21 +104,41 @@ class ProfileRepositoryImpl @Inject constructor( lotNumberAddress: String, jobSearchStatus: JobSearchStatus, introduce: String?, - speciality: String + speciality: String, + imageFileUri: String?, ) { - profileDataSource.updateWorkerProfile( - UpdateWorkerProfileRequest( - experienceYear = experienceYear, - roadNameAddress = roadNameAddress, - lotNumberAddress = lotNumberAddress, - jobSearchStatus = jobSearchStatus.name, - introduce = introduce, - speciality = speciality - ) - ) + coroutineScope { + val updateProfileJob = launch { + profileDataSource.updateWorkerProfile( + UpdateWorkerProfileRequest( + experienceYear = experienceYear, + roadNameAddress = roadNameAddress, + lotNumberAddress = lotNumberAddress, + jobSearchStatus = jobSearchStatus.name, + introduce = introduce, + speciality = speciality + ) + ) + } - val updatedProfile = getMyWorkerProfile() - userInfoDataSource.setUserInfo(updatedProfile.toString()) + val updateProfileImageJob = imageFileUri?.let { uri -> + if (uri.isContentUri()) { + launch { + updateProfileImage( + userType = UserType.WORKER.apiValue, + imageFileUri = uri, + reqWidth = 384, + reqHeight = 384, + ) + } + } else null + } + + updateProfileJob.join() + updateProfileImageJob?.join() + val updatedProfile = getMyWorkerProfile() + userInfoDataSource.setUserInfo(updatedProfile.toString()) + } } override suspend fun registerCenterProfile( @@ -108,19 +147,42 @@ class ProfileRepositoryImpl @Inject constructor( introduce: String, lotNumberAddress: String, officeNumber: String, - roadNameAddress: String - ) = profileDataSource.registerCenterProfile( - RegisterCenterProfileRequest( - centerName = centerName, - detailedAddress = detailedAddress, - introduce = introduce, - lotNumberAddress = lotNumberAddress, - officeNumber = officeNumber, - roadNameAddress = roadNameAddress, - ) - ) + roadNameAddress: String, + imageFileUri: String? + ) { + coroutineScope { + val registerProfileJob = launch { + profileDataSource.registerCenterProfile( + RegisterCenterProfileRequest( + centerName = centerName, + detailedAddress = detailedAddress, + introduce = introduce, + lotNumberAddress = lotNumberAddress, + officeNumber = officeNumber, + roadNameAddress = roadNameAddress, + ) + ) + } + + val profileImageJob = imageFileUri?.let { uri -> + launch { + if (uri.isContentUri()) { + updateProfileImage( + userType = UserType.CENTER.apiValue, + imageFileUri = imageFileUri, + reqWidth = 1340, + reqHeight = 1016, + ) + } + } + } - override suspend fun updateProfileImage( + registerProfileJob.join() + profileImageJob?.join() + } + } + + private suspend fun updateProfileImage( userType: String, imageFileUri: String, reqWidth: Int, @@ -260,4 +322,6 @@ class ProfileRepositoryImpl @Inject constructor( imageFileExtension = imageFileExtension, ) ) + + private fun String?.isContentUri(): Boolean = this?.startsWith("content://") == true } 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 11908800b..829c0fdc8 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 @@ -19,7 +19,7 @@ class UserInfoDataSource @Inject constructor( @Named("userInfo") private val dataStore: DataStore ) { val userType: Flow = dataStore.getValue(USER_TYPE, "") - val userInfo: Flow = dataStore.getValue(USER_INFO, "") + private val userInfo: Flow = dataStore.getValue(USER_INFO, "") suspend fun setUserType(userRole: String) { dataStore.setValue(USER_TYPE, userRole) @@ -37,81 +37,76 @@ class UserInfoDataSource @Inject constructor( dataStore.clear(USER_INFO) } - suspend fun getLocalCenterProfile(): CenterProfile { - val userInfoString = userInfo.first().takeIf { it.isNotBlank() } - ?: throw NullPointerException("Missing UserInfo") + suspend fun getLocalCenterProfile(): CenterProfile? { + try { + val userInfoString = userInfo.first().takeIf { it.isNotBlank() } + ?: return null - if (!userInfoString.startsWith("CenterProfile(")) { - throw NullPointerException("Stored UserInfo is not a CenterProfile") - } - - val properties = userInfoString - .removePrefix("CenterProfile(") - .removeSuffix(")") - .split(", ") - .associate { - val (key, value) = it.split("=") - key to value + if (!userInfoString.startsWith("CenterProfile(")) { + return null } - return CenterProfile( - centerId = properties["centerId"] ?: throw NullPointerException("Missing CenterId"), - centerName = properties["centerName"] - ?: throw NullPointerException("Missing centerName"), - officeNumber = properties["officeNumber"] - ?: throw NullPointerException("Missing officeNumber"), - roadNameAddress = properties["roadNameAddress"] - ?: throw NullPointerException("Missing roadNameAddress"), - lotNumberAddress = properties["lotNumberAddress"] - ?: throw NullPointerException("Missing lotNumberAddress"), - detailedAddress = properties["detailedAddress"] - ?: throw NullPointerException("Missing detailedAddress"), - longitude = properties["longitude"]?.toDoubleOrNull() - ?: throw NullPointerException("Invalid longitude format"), - latitude = properties["latitude"]?.toDoubleOrNull() - ?: throw NullPointerException("Invalid latitude format"), - introduce = properties["introduce"].takeIf { it != "null" }, - profileImageUrl = properties["profileImageUrl"].takeIf { it != "null" }, - ) + val properties = userInfoString + .removePrefix("CenterProfile(") + .removeSuffix(")") + .split(", ") + .associate { + val (key, value) = it.split("=") + key to value + } + + return CenterProfile( + centerId = properties["centerId"] ?: return null, + centerName = properties["centerName"] ?: return null, + officeNumber = properties["officeNumber"] ?: return null, + roadNameAddress = properties["roadNameAddress"] ?: return null, + lotNumberAddress = properties["lotNumberAddress"] ?: return null, + detailedAddress = properties["detailedAddress"] ?: return null, + longitude = properties["longitude"]?.toDoubleOrNull() ?: return null, + latitude = properties["latitude"]?.toDoubleOrNull() ?: return null, + introduce = properties["introduce"].takeIf { it != "null" }, + profileImageUrl = properties["profileImageUrl"].takeIf { it != "null" }, + ) + } catch (e: Exception) { + return null + } } - suspend fun getLocalWorkerProfile(): WorkerProfile { - val userInfoString = userInfo.first().takeIf { it.isNotBlank() } - ?: throw NullPointerException("Missing UserInfo") + suspend fun getLocalWorkerProfile(): WorkerProfile? { + return try { + val userInfoString = userInfo.first() + .takeIf { it.isNotBlank() } ?: return null - if (!userInfoString.startsWith("WorkerProfile(")) { - throw NullPointerException("Stored UserInfo is not a WorkerProfile") - } + if (!userInfoString.startsWith("WorkerProfile(")) return null - val properties = userInfoString - .removePrefix("WorkerProfile(") - .removeSuffix(")") - .split(", ") - .associate { - val (key, value) = it.split("=") - key to value - } + val properties = userInfoString + .removePrefix("WorkerProfile(") + .removeSuffix(")") + .split(", ") + .associate { + val (key, value) = it.split("=") + key to value + } - return WorkerProfile( - workerId = properties["workerId"] ?: throw NullPointerException("Missing workerId"), - workerName = properties["workerName"] - ?: throw NullPointerException("Missing workerName"), - age = properties["age"]?.toInt() ?: throw NullPointerException("Invalid age format"), - gender = Gender.create(properties["gender"]), - experienceYear = properties["experienceYear"]?.toIntOrNull(), - phoneNumber = properties["phoneNumber"] - ?: throw NullPointerException("Missing phoneNumber"), - roadNameAddress = properties["roadNameAddress"] - ?: throw NullPointerException("Missing roadNameAddress"), - lotNumberAddress = properties["lotNumberAddress"] - ?: throw NullPointerException("Missing lotNumberAddress"), - longitude = properties["longitude"] ?: throw NullPointerException("Missing longitude"), - latitude = properties["latitude"] ?: throw NullPointerException("Missing latitude"), - jobSearchStatus = JobSearchStatus.create(properties["jobSearchStatus"]), - introduce = properties["introduce"].takeIf { it != "null" }, - speciality = properties["speciality"].takeIf { it != "null" }, - profileImageUrl = properties["profileImageUrl"].takeIf { it != "null" } - ) + WorkerProfile( + workerId = properties["workerId"] ?: return null, + workerName = properties["workerName"] ?: return null, + age = properties["age"]?.toIntOrNull() ?: return null, + gender = Gender.create(properties["gender"]), + experienceYear = properties["experienceYear"]?.toIntOrNull(), + phoneNumber = properties["phoneNumber"] ?: return null, + roadNameAddress = properties["roadNameAddress"] ?: return null, + lotNumberAddress = properties["lotNumberAddress"] ?: return null, + longitude = properties["longitude"] ?: return null, + latitude = properties["latitude"] ?: return null, + jobSearchStatus = JobSearchStatus.create(properties["jobSearchStatus"]), + introduce = properties["introduce"].takeIf { it != "null" }, + speciality = properties["speciality"].takeIf { it != "null" }, + profileImageUrl = properties["profileImageUrl"].takeIf { it != "null" } + ) + } catch (e: Exception) { + null + } } companion object { 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 c9a391a46..ebfe78c7a 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 @@ -8,14 +8,17 @@ import com.idle.domain.model.profile.WorkerProfile interface ProfileRepository { suspend fun getMyUserType(): String 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 updateCenterProfile( + officeNumber: String, + introduce: String?, + imageFileUri: String?, + ) + suspend fun updateWorkerProfile( experienceYear: Int?, roadNameAddress: String, @@ -23,6 +26,7 @@ interface ProfileRepository { jobSearchStatus: JobSearchStatus, introduce: String?, speciality: String, + imageFileUri: String?, ) suspend fun registerCenterProfile( @@ -32,12 +36,6 @@ interface ProfileRepository { lotNumberAddress: String, officeNumber: String, roadNameAddress: String, - ) - - suspend fun updateProfileImage( - userType: String, - imageFileUri: String, - reqWidth: Int, - reqHeight: Int + imageFileUri: 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 02736b698..68b26f8a2 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,6 +3,9 @@ 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 @@ -42,14 +45,11 @@ class GetChatRoomsUseCase @Inject constructor( private fun mapToRoomWithOpponentInfo( chatRoom: ChatRoom, - profile: com.idle.domain.model.profile.Profile, + profile: Profile, ): ChatRoomWithOpponentInfo { val (opponentName, profileUrl) = when (profile) { - is com.idle.domain.model.profile.WorkerProfile -> - profile.workerName to profile.profileImageUrl - - is com.idle.domain.model.profile.CenterProfile -> - profile.centerName to profile.profileImageUrl + is WorkerProfile -> profile.workerName to profile.profileImageUrl + is CenterProfile -> profile.centerName to profile.profileImageUrl } return ChatRoomWithOpponentInfo( 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 deleted file mode 100644 index 681023f56..000000000 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/GetMyCenterProfileUseCase.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.idle.domain.usecase.profile - -import com.idle.domain.model.profile.CenterProfile -import com.idle.domain.repositorry.ProfileRepository -import javax.inject.Inject - -class GetMyCenterProfileUseCase @Inject constructor( - private val profileRepository: ProfileRepository -) { - 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 deleted file mode 100644 index 5a2faa386..000000000 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/GetMyWorkerProfileUseCase.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.idle.domain.usecase.profile - -import com.idle.domain.model.profile.WorkerProfile -import com.idle.domain.repositorry.ProfileRepository -import javax.inject.Inject - -class GetMyWorkerProfileUseCase @Inject constructor( - private val profileRepository: ProfileRepository -) { - 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 deleted file mode 100644 index d996baaf9..000000000 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/RegisterCenterProfileUseCase.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.idle.domain.usecase.profile - -import com.idle.domain.model.auth.UserType -import com.idle.domain.repositorry.ProfileRepository -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import javax.inject.Inject - -class RegisterCenterProfileUseCase @Inject constructor( - private val profileRepository: ProfileRepository, -) { - suspend operator fun invoke( - centerName: String, - detailedAddress: String, - introduce: String, - lotNumberAddress: String, - officeNumber: String, - roadNameAddress: String, - imageFileUri: String?, - ) = coroutineScope { - val registerProfileJob = launch { - profileRepository.registerCenterProfile( - centerName = centerName, - detailedAddress = detailedAddress, - introduce = introduce, - lotNumberAddress = lotNumberAddress, - officeNumber = officeNumber, - roadNameAddress = roadNameAddress - ) - } - - 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 deleted file mode 100644 index 90b10367b..000000000 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/UpdateCenterProfileUseCase.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.idle.domain.usecase.profile - -import com.idle.domain.model.auth.UserType -import com.idle.domain.repositorry.ProfileRepository -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import javax.inject.Inject - -class UpdateCenterProfileUseCase @Inject constructor( - private val profileRepository: ProfileRepository -) { - suspend operator fun invoke( - officeNumber: String, - introduce: String?, - imageFileUri: String?, - ) = coroutineScope { - val updateProfileJob = launch { - profileRepository.updateCenterProfile( - officeNumber = officeNumber, - introduce = introduce, - ) - } - - 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 deleted file mode 100644 index 5f312f278..000000000 --- a/core/domain/src/main/kotlin/com/idle/domain/usecase/profile/UpdateWorkerProfileUseCase.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.idle.domain.usecase.profile - -import com.idle.domain.model.auth.UserType -import com.idle.domain.model.profile.JobSearchStatus -import com.idle.domain.repositorry.ProfileRepository -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import javax.inject.Inject - -class UpdateWorkerProfileUseCase @Inject constructor( - private val profileRepository: ProfileRepository, -) { - suspend operator fun invoke( - experienceYear: Int?, - roadNameAddress: String, - lotNumberAddress: String, - introduce: String?, - speciality: String, - jobSearchStatus: JobSearchStatus, - imageFileUri: String?, - ) = coroutineScope { - val updateProfileJob = launch { - profileRepository.updateWorkerProfile( - experienceYear = experienceYear, - roadNameAddress = roadNameAddress, - lotNumberAddress = lotNumberAddress, - jobSearchStatus = jobSearchStatus, - introduce = introduce, - speciality = speciality - ) - } - - 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/source/ChatDataSource.kt b/core/network/src/main/java/com/idle/network/source/ChatDataSource.kt index 839205bdf..2a1605b80 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,6 +1,7 @@ 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 @@ -11,8 +12,7 @@ import com.idle.network.model.chat.ReadMessageRequest import com.idle.network.model.chat.SendMessageRequest 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.calculateRetryTime import com.idle.network.util.onResponse import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow @@ -44,20 +44,18 @@ class ChatDataSource @Inject constructor( suspend fun getWorkerChatRoomMessages( roomId: String, messageId: String?, - ): GetChatMessageResponse = - chatApi.getWorkerChatRoomMessages( - chatRoomId = roomId, - messageId = messageId - ).onResponse() + ): GetChatMessageResponse = chatApi.getWorkerChatRoomMessages( + chatRoomId = roomId, + messageId = messageId + ).onResponse() suspend fun getCenterChatRoomMessages( roomId: String, messageId: String?, - ): GetChatMessageResponse = - chatApi.getCenterChatRoomMessages( - chatRoomId = roomId, - messageId = messageId - ).onResponse() + ): GetChatMessageResponse = chatApi.getCenterChatRoomMessages( + chatRoomId = roomId, + messageId = messageId + ).onResponse() suspend fun generateWorkerChatRoom(opponentId: String): GenerateChatRoomResponse = chatApi.generateWorkerChatRoom(opponentId).onResponse() @@ -72,14 +70,14 @@ class ChatDataSource @Inject constructor( val accessToken = tokenManager.getAccessToken() try { session = client.connect( - url = "${'$'}{BuildConfig.CARE_WEBSOCKET_URL}/ws", + 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) + val waitTime = calculateRetryTime(connectionAttempts) delay(waitTime) connectionAttempts++ connectWebSocket() @@ -95,16 +93,17 @@ class ChatDataSource @Inject constructor( 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 ) { session?.convertAndSend( - headers = StompSendHeaders(destination = "/pub/send/${'$'}{userType.apiValue.lowercase()}"), + headers = StompSendHeaders(destination = "/pub/send/$${userType.apiValue.lowercase()}"), body = sendMessageRequest, serializer = SendMessageRequest.serializer(), ) @@ -115,7 +114,7 @@ class ChatDataSource @Inject constructor( readMessageRequest: ReadMessageRequest ) { 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/util/BackOff.kt b/core/network/src/main/java/com/idle/network/util/BackOff.kt index 579a82864..84ec1f725 100644 --- a/core/network/src/main/java/com/idle/network/util/BackOff.kt +++ b/core/network/src/main/java/com/idle/network/util/BackOff.kt @@ -1,9 +1,21 @@ package com.idle.network.util import com.idle.domain.model.CountDownTimer.Companion.TICK_INTERVAL +import kotlin.math.min import kotlin.math.pow +import kotlin.random.Random const val MAX_RETRY_ATTEMPTS = 5 -const val MAX_WAIT_TIME = 10_000L +private const val MAX_WAIT_TIME = 10_000L -fun calculateBackoffTime(attempt: Int): Long = (2.0.pow(attempt) * TICK_INTERVAL).toLong() +fun calculateRetryTime(attempt: Int): Long { + return min(MAX_WAIT_TIME, calculateEqualJitter(attempt)) +} + +private fun calculateEqualJitter(attempt: Int): Long { + val baseDelay = calculateBackoffTime(attempt) + val randomJitter = Random.nextLong(0, baseDelay / 2 + 1) + return baseDelay / 2 + randomJitter +} + +private fun calculateBackoffTime(attempt: Int): Long = (2.0.pow(attempt) * TICK_INTERVAL).toLong() 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 7b24ee9b3..766061fd8 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 @@ -12,7 +12,6 @@ import com.idle.domain.model.profile.CenterProfile import com.idle.domain.repositorry.ChatRepository import com.idle.domain.repositorry.ProfileRepository import com.idle.domain.usecase.chat.GetChatRoomsUseCase -import com.idle.domain.usecase.profile.GetMyCenterProfileUseCase import com.idle.navigation.NavigationHelper import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -23,7 +22,6 @@ import javax.inject.Inject @HiltViewModel class CenterChattingViewModel @Inject constructor( - private val getMyCenterProfileUseCase: GetMyCenterProfileUseCase, private val getChatRoomsUseCase: GetChatRoomsUseCase, private val profileRepository: ProfileRepository, private val chatRepository: ChatRepository, @@ -41,7 +39,7 @@ class CenterChattingViewModel @Inject constructor( internal suspend fun initCenterChatting() { suspendRunCatching { - getMyCenterProfileUseCase() + profileRepository.getMyCenterProfile() }.onSuccess { _myProfile.value = it }.onFailure { errorHelper.sendError(it) } 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 55175fe87..e30004494 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 @@ -18,7 +18,7 @@ import com.idle.domain.model.jobposting.MentalStatus import com.idle.domain.model.jobposting.PayType import com.idle.domain.model.profile.CenterProfile import com.idle.domain.repositorry.JobPostingRepository -import com.idle.domain.usecase.profile.GetMyCenterProfileUseCase +import com.idle.domain.repositorry.ProfileRepository import com.idle.navigation.DeepLinkDestination.CenterJobPostingPostComplete import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -36,7 +36,7 @@ import javax.inject.Inject @HiltViewModel class JobPostingViewModel @Inject constructor( - private val getMyCenterProfileUseCase: GetMyCenterProfileUseCase, + private val profileRepository: ProfileRepository, private val jobPostingRepository: JobPostingRepository, private val errorHelper: ErrorHelper, val eventHelper: EventHelper, @@ -374,7 +374,7 @@ class JobPostingViewModel @Inject constructor( private fun getMyCenterProfile() = viewModelScope.launch { suspendRunCatching { - getMyCenterProfileUseCase() + profileRepository.getMyCenterProfile() }.onSuccess { _profile.value = it }.onFailure { errorHelper.sendError(it) } 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 dfd92f905..1040b3d6c 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 @@ -10,8 +10,6 @@ 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 -import com.idle.domain.usecase.profile.GetMyCenterProfileUseCase -import com.idle.domain.usecase.profile.UpdateCenterProfileUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -21,8 +19,6 @@ import javax.inject.Inject @HiltViewModel class CenterProfileViewModel @Inject constructor( private val profileRepository: ProfileRepository, - private val getMyCenterProfileUseCase: GetMyCenterProfileUseCase, - private val updateCenterProfileUseCase: UpdateCenterProfileUseCase, private val errorHelper: ErrorHelper, private val eventHelper: EventHelper, ) : ViewModel() { @@ -65,7 +61,7 @@ class CenterProfileViewModel @Inject constructor( internal fun getMyCenterProfile() = viewModelScope.launch { suspendRunCatching { - getMyCenterProfileUseCase() + profileRepository.getMyCenterProfile() }.onSuccess { _centerProfile.value = it _centerIntroduce.value = it.introduce ?: "" @@ -96,7 +92,7 @@ class CenterProfileViewModel @Inject constructor( _isUpdateLoading.value = true suspendRunCatching { - updateCenterProfileUseCase( + profileRepository.updateCenterProfile( officeNumber = _centerOfficeNumber.value, introduce = _centerIntroduce.value.ifBlank { null }, imageFileUri = _profileImageUri.value?.toString(), 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 803bff01a..5f6259c09 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 @@ -7,8 +7,9 @@ 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.domain.repositorry.ProfileRepository import com.idle.navigation.DeepLinkDestination.CenterRegisterComplete +import com.idle.navigation.NavigationHelper import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -17,11 +18,10 @@ import javax.inject.Inject @HiltViewModel class RegisterCenterInfoViewModel @Inject constructor( - private val registerCenterProfileUseCase: RegisterCenterProfileUseCase, + private val profileRepository: ProfileRepository, private val errorHelper: ErrorHelper, - private val navigationHelper: com.idle.navigation.NavigationHelper, + private val navigationHelper: NavigationHelper, ) : ViewModel() { - private val _registrationStep = MutableStateFlow(RegistrationStep.INFO) val registrationStep = _registrationStep.asStateFlow() @@ -47,7 +47,7 @@ class RegisterCenterInfoViewModel @Inject constructor( internal fun registerCenterProfile() = viewModelScope.launch { suspendRunCatching { - registerCenterProfileUseCase( + profileRepository.registerCenterProfile( centerName = _centerName.value, detailedAddress = _centerDetailAddress.value, introduce = _centerIntroduce.value, 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 6053cc005..67c107fa9 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 @@ -6,7 +6,7 @@ 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 com.idle.domain.repositorry.ProfileRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -15,7 +15,7 @@ import javax.inject.Inject @HiltViewModel class RegisterCenterInfoCompleteViewModel @Inject constructor( - private val getMyCenterProfileUseCase: GetMyCenterProfileUseCase, + private val profileRepository: ProfileRepository, private val eventHelper: EventHelper, val navigationHelper: com.idle.navigation.NavigationHelper, ) : ViewModel() { @@ -25,7 +25,7 @@ class RegisterCenterInfoCompleteViewModel @Inject constructor( init { viewModelScope.launch { suspendRunCatching { - getMyCenterProfileUseCase() + profileRepository.getMyCenterProfile() }.onSuccess { _centerProfile.value = it }.onFailure { 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 1ed719950..415e79570 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 @@ -12,8 +12,6 @@ import com.idle.domain.model.profile.CenterProfile import com.idle.domain.model.profile.WorkerProfile import com.idle.domain.repositorry.ChatRepository import com.idle.domain.repositorry.ProfileRepository -import com.idle.domain.usecase.profile.GetMyCenterProfileUseCase -import com.idle.domain.usecase.profile.GetMyWorkerProfileUseCase import com.idle.navigation.NavigationHelper import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.coroutineScope @@ -27,8 +25,6 @@ import javax.inject.Inject class ChattingDetailViewModel @Inject constructor( private val profileRepository: ProfileRepository, private val chatRepository: ChatRepository, - private val getMyWorkerProfileUseCase: GetMyWorkerProfileUseCase, - private val getMyCenterProfileUseCase: GetMyCenterProfileUseCase, private val errorHelper: ErrorHelper, val navigationHelper: NavigationHelper, private val savedStateHandle: SavedStateHandle, @@ -84,7 +80,7 @@ class ChattingDetailViewModel @Inject constructor( } suspendRunCatching { - getMyCenterProfileUseCase() + profileRepository.getMyCenterProfile() }.onSuccess { _centerProfile.value = it }.onFailure { @@ -104,7 +100,7 @@ class ChattingDetailViewModel @Inject constructor( } suspendRunCatching { - getMyWorkerProfileUseCase() + profileRepository.getMyWorkerProfile() }.onSuccess { _workerProfile.value = it }.onFailure { 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 ba036c9b4..78dfe672c 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 @@ -13,7 +13,7 @@ import com.idle.domain.model.jobposting.JobPostingStatus import com.idle.domain.model.jobposting.LifeAssistance import com.idle.domain.model.profile.CenterProfile import com.idle.domain.repositorry.JobPostingRepository -import com.idle.domain.usecase.profile.GetMyCenterProfileUseCase +import com.idle.domain.repositorry.ProfileRepository import com.idle.job.posting.detail.R import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -23,7 +23,7 @@ import javax.inject.Inject @HiltViewModel class CenterJobPostingDetailViewModel @Inject constructor( - private val getMyCenterProfileUseCase: GetMyCenterProfileUseCase, + private val profileRepository: ProfileRepository, private val jobPostingRepository: JobPostingRepository, private val errorHelper: ErrorHelper, val eventHelper: EventHelper, @@ -47,7 +47,7 @@ class CenterJobPostingDetailViewModel @Inject constructor( private fun getMyCenterProfile() = viewModelScope.launch { suspendRunCatching { - getMyCenterProfileUseCase() + profileRepository.getMyCenterProfile() }.onSuccess { _profile.value = it }.onFailure { errorHelper.sendError(it) } @@ -89,14 +89,17 @@ class CenterJobPostingDetailViewModel @Inject constructor( startTime = editJobPostingDetail.startTime, endTime = editJobPostingDetail.endTime, payType = editJobPostingDetail.payType, - payAmount = editJobPostingDetail.payAmount.toIntOrNull() ?: return@suspendRunCatching, + payAmount = editJobPostingDetail.payAmount.toIntOrNull() + ?: return@suspendRunCatching, roadNameAddress = editJobPostingDetail.roadNameAddress, lotNumberAddress = editJobPostingDetail.lotNumberAddress, clientName = editJobPostingDetail.clientName, gender = editJobPostingDetail.gender, - birthYear = editJobPostingDetail.birthYear.toIntOrNull() ?: return@suspendRunCatching, + birthYear = editJobPostingDetail.birthYear.toIntOrNull() + ?: return@suspendRunCatching, weight = editJobPostingDetail.weight?.toIntOrNull(), - careLevel = editJobPostingDetail.careLevel.toIntOrNull() ?: return@suspendRunCatching, + careLevel = editJobPostingDetail.careLevel.toIntOrNull() + ?: return@suspendRunCatching, mentalStatus = editJobPostingDetail.mentalStatus, disease = editJobPostingDetail.disease.ifBlank { null }, isMealAssistance = editJobPostingDetail.isMealAssistance, 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 8ecd10d17..8e31dc41a 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 @@ -21,7 +21,7 @@ import com.idle.domain.model.jobposting.WorkerJobPostingDetail import com.idle.domain.model.profile.WorkerProfile import com.idle.domain.repositorry.ChatRepository import com.idle.domain.repositorry.JobPostingRepository -import com.idle.domain.usecase.profile.GetMyWorkerProfileUseCase +import com.idle.domain.repositorry.ProfileRepository import com.idle.navigation.DeepLinkDestination import com.idle.navigation.NavigationEvent import dagger.hilt.android.lifecycle.HiltViewModel @@ -33,7 +33,7 @@ import javax.inject.Inject @HiltViewModel class WorkerJobPostingDetailViewModel @Inject constructor( - private val getMyWorkerProfileUseCase: GetMyWorkerProfileUseCase, + private val profileRepository: ProfileRepository, private val jobPostingRepository: JobPostingRepository, private val chatRepository: ChatRepository, private val analyticsHelper: AnalyticsHelper, @@ -49,7 +49,7 @@ class WorkerJobPostingDetailViewModel @Inject constructor( internal fun getMyProfile() = viewModelScope.launch { suspendRunCatching { - getMyWorkerProfileUseCase() + profileRepository.getMyWorkerProfile() }.onSuccess { _profile.value = it }.onFailure { errorHelper.sendError(it) } 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 a9b0c0821..357c238b4 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 @@ -7,7 +7,7 @@ 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 -import com.idle.domain.usecase.profile.GetMyCenterProfileUseCase +import com.idle.domain.repositorry.ProfileRepository import com.idle.setting.SettingEvent import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow @@ -19,7 +19,7 @@ import javax.inject.Inject @HiltViewModel class CenterSettingViewModel @Inject constructor( - private val getMyCenterProfileUseCase: GetMyCenterProfileUseCase, + private val profileRepository: ProfileRepository, private val authRepository: AuthRepository, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, @@ -39,7 +39,7 @@ class CenterSettingViewModel @Inject constructor( private fun getMyProfile() = viewModelScope.launch { suspendRunCatching { - getMyCenterProfileUseCase() + profileRepository.getMyCenterProfile() }.onSuccess { _centerProfile.value = it }.onFailure { errorHelper.sendError(it) } 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 05ebc07f9..a621838e1 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 @@ -7,7 +7,7 @@ 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 -import com.idle.domain.usecase.profile.GetMyWorkerProfileUseCase +import com.idle.domain.repositorry.ProfileRepository import com.idle.setting.SettingEvent import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow @@ -18,7 +18,7 @@ import javax.inject.Inject @HiltViewModel class WorkerSettingViewModel @Inject constructor( - private val getMyWorkerProfileUseCase: GetMyWorkerProfileUseCase, + private val profileRepository: ProfileRepository, private val authRepository: AuthRepository, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, @@ -35,7 +35,7 @@ class WorkerSettingViewModel @Inject constructor( private fun getMyProfile() = viewModelScope.launch { suspendRunCatching { - getMyWorkerProfileUseCase() + profileRepository.getMyWorkerProfile() }.onSuccess { _workerProfile.value = it }.onFailure { errorHelper.sendError(it) } 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 3668eec2d..4a00cff4b 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 @@ -12,7 +12,6 @@ import com.idle.domain.model.profile.WorkerProfile import com.idle.domain.repositorry.ChatRepository import com.idle.domain.repositorry.ProfileRepository import com.idle.domain.usecase.chat.GetChatRoomsUseCase -import com.idle.domain.usecase.profile.GetMyWorkerProfileUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -26,7 +25,6 @@ import javax.inject.Inject class WorkerChattingViewModel @Inject constructor( private val profileRepository: ProfileRepository, private val getChatRoomsUseCase: GetChatRoomsUseCase, - private val getMyWorkerProfileUseCase: GetMyWorkerProfileUseCase, private val chatRepository: ChatRepository, private val errorHelper: ErrorHelper, val navigationHelper: com.idle.navigation.NavigationHelper, @@ -46,7 +44,7 @@ class WorkerChattingViewModel @Inject constructor( internal suspend fun initWorkerChatting() { suspendRunCatching { - getMyWorkerProfileUseCase() + profileRepository.getMyWorkerProfile() }.onSuccess { profile -> _myProfile.value = profile }.onFailure { errorHelper.sendError(it) } 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 1b41ccf38..f2316ba50 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 @@ -15,7 +15,7 @@ import com.idle.domain.model.jobposting.WorkerJobPosting import com.idle.domain.model.profile.WorkerProfile import com.idle.domain.repositorry.JobPostingRepository import com.idle.domain.repositorry.NotificationRepository -import com.idle.domain.usecase.profile.GetMyWorkerProfileUseCase +import com.idle.domain.repositorry.ProfileRepository import com.idle.navigation.DeepLinkDestination import com.idle.navigation.NavigationEvent import com.idle.navigation.NavigationHelper @@ -28,7 +28,7 @@ import javax.inject.Inject @HiltViewModel class WorkerHomeViewModel @Inject constructor( - private val getMyWorkerProfileUseCase: GetMyWorkerProfileUseCase, + private val profileRepository: ProfileRepository, private val notificationRepository: NotificationRepository, private val jobPostingRepository: JobPostingRepository, private val errorHelper: ErrorHelper, @@ -143,7 +143,7 @@ class WorkerHomeViewModel @Inject constructor( internal fun getMyWorkerProfile() = viewModelScope.launch { suspendRunCatching { - getMyWorkerProfileUseCase() + profileRepository.getMyWorkerProfile() }.onSuccess { _profile.value = it }.onFailure { 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 833c9e06d..2855f0686 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 @@ -14,7 +14,7 @@ import com.idle.domain.model.jobposting.JobPostingType import com.idle.domain.model.jobposting.WorkerJobPosting import com.idle.domain.model.profile.WorkerProfile import com.idle.domain.repositorry.JobPostingRepository -import com.idle.domain.usecase.profile.GetMyWorkerProfileUseCase +import com.idle.domain.repositorry.ProfileRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -24,7 +24,7 @@ import javax.inject.Inject @HiltViewModel class WorkerJobPostingViewModel @Inject constructor( - private val getMyWorkerProfileUseCase: GetMyWorkerProfileUseCase, + private val profileRepository: ProfileRepository, private val jobPostingRepository: JobPostingRepository, private val errorHelper: ErrorHelper, private val eventHelper: EventHelper, @@ -51,7 +51,7 @@ class WorkerJobPostingViewModel @Inject constructor( init { viewModelScope.launch { suspendRunCatching { - getMyWorkerProfileUseCase() + profileRepository.getMyWorkerProfile() }.onSuccess { _profile.value = it } 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 bfe1982ad..fa99b8ecf 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 @@ -12,8 +12,6 @@ import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.profile.JobSearchStatus import com.idle.domain.model.profile.WorkerProfile import com.idle.domain.repositorry.ProfileRepository -import com.idle.domain.usecase.profile.GetMyWorkerProfileUseCase -import com.idle.domain.usecase.profile.UpdateWorkerProfileUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -23,8 +21,6 @@ import javax.inject.Inject @HiltViewModel class WorkerProfileViewModel @Inject constructor( private val profileRepository: ProfileRepository, - private val getMyWorkerProfileUseCase: GetMyWorkerProfileUseCase, - private val updateWorkerProfileUseCase: UpdateWorkerProfileUseCase, private val errorHelper: ErrorHelper, private val eventHelper: EventHelper, ) : ViewModel() { @@ -94,7 +90,7 @@ class WorkerProfileViewModel @Inject constructor( internal fun getMyWorkerProfile() = viewModelScope.launch { suspendRunCatching { - getMyWorkerProfileUseCase() + profileRepository.getMyWorkerProfile() }.onSuccess { _workerProfile.value = it _workerIntroduce.value = it.introduce ?: "" @@ -132,7 +128,7 @@ class WorkerProfileViewModel @Inject constructor( _isUpdateLoading.value = true suspendRunCatching { - updateWorkerProfileUseCase( + profileRepository.updateWorkerProfile( experienceYear = _experienceYear.value, roadNameAddress = _roadNameAddress.value, lotNumberAddress = _lotNumberAddress.value,