From 9f69f458c4e9e2c262d4fb9c32a75782c0ce4ab4 Mon Sep 17 00:00:00 2001 From: tgyuuAn Date: Sat, 10 May 2025 03:39:08 +0900 Subject: [PATCH 1/7] =?UTF-8?q?[PC-000]=20=ED=98=B8=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=A3=BC=EC=86=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/repository/ChatRepositoryImpl.kt | 13 ++++- .../idle/domain/repositorry/ChatRepository.kt | 2 + .../idle/navigation/DeepLinkDestination.kt | 8 +-- .../src/main/res/values/deeplinks.xml | 2 +- .../main/java/com/idle/network/api/AuthApi.kt | 32 +++++------ .../main/java/com/idle/network/api/ChatApi.kt | 12 ++-- .../com/idle/network/api/JobPostingApi.kt | 38 ++++++------- .../com/idle/network/api/NotificationApi.kt | 8 +-- .../main/java/com/idle/network/api/UserApi.kt | 24 ++++---- .../authenticator/CareAuthenticator.kt | 2 +- .../network/interceptor/AuthInterceptor.kt | 7 ++- .../network/model/chat/GetChatRoomResponse.kt | 2 +- .../com/idle/network/source/ChatDataSource.kt | 17 ++++-- .../center/chatting/CenterChattingFragment.kt | 6 +- .../chatting/CenterChattingViewModel.kt | 32 ++++++----- .../chatting_detail/ChattingDetailFragment.kt | 4 +- .../ChattingDetailViewModel.kt | 56 +++++++------------ .../ui/component/CareChatTextBubble.kt | 6 +- .../ui/component/ChattingInput.kt | 8 ++- .../res/navigation/nav_chatting_detail.xml | 6 +- .../worker/WorkerJobPostingDetailViewModel.kt | 2 +- .../worker/chatting/WorkerChattingFragment.kt | 2 +- 22 files changed, 150 insertions(+), 139 deletions(-) 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 2685a0a2e..40f1d6d45 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 @@ -161,8 +161,10 @@ class ChatRepositoryImpl @Inject constructor( receiverId: String, senderName: String, content: String, + userType: UserType, ): Result = chatDataSource.sendMessage( - SendMessageRequest( + userType = userType, + sendMessageRequest = SendMessageRequest( chatroomId = chatroomId, receiverId = receiverId, senderName = senderName, @@ -170,9 +172,14 @@ class ChatRepositoryImpl @Inject constructor( ) ) - override suspend fun readMessage(chatroomId: String, opponentId: String): Result = + override suspend fun readMessage( + chatroomId: String, + opponentId: String, + userType: UserType, + ): Result = chatDataSource.readMessage( - ReadMessageRequest( + userType = userType, + readMessageRequest = ReadMessageRequest( chatroomId = chatroomId, opponentId = opponentId, ) 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 8e8e220e7..acedbec2a 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 @@ -41,10 +41,12 @@ interface ChatRepository { receiverId: String, senderName: String, content: String, + userType: UserType, ): Result suspend fun readMessage( chatroomId: String, opponentId: String, + userType: UserType, ): Result } diff --git a/core/navigation/src/main/java/com/idle/navigation/DeepLinkDestination.kt b/core/navigation/src/main/java/com/idle/navigation/DeepLinkDestination.kt index 9a9541a04..7dda55bff 100644 --- a/core/navigation/src/main/java/com/idle/navigation/DeepLinkDestination.kt +++ b/core/navigation/src/main/java/com/idle/navigation/DeepLinkDestination.kt @@ -46,16 +46,16 @@ sealed class DeepLinkDestination( data class ChattingDetail( val chattingRoomId: String, val myId: String, - val receiverUserType: String, + val myUserType: String, val opponentId: String, val fromJobPosting: Boolean, ) : DeepLinkDestination( addressRes = R.string.chatting_detail_deeplink_url, params = mapOf( "chattingRoomId" to chattingRoomId, - "receiverId" to myId, - "receiverUserType" to receiverUserType, - "senderId" to opponentId, + "myId" to myId, + "myUserType" to myUserType, + "opponentId" to opponentId, "fromJobPosting" to fromJobPosting, ) ) diff --git a/core/navigation/src/main/res/values/deeplinks.xml b/core/navigation/src/main/res/values/deeplinks.xml index f22042df0..828c66b36 100644 --- a/core/navigation/src/main/res/values/deeplinks.xml +++ b/core/navigation/src/main/res/values/deeplinks.xml @@ -6,7 +6,7 @@ care://withdrawal/{userType} care://signup/complete care://newPassword - care://chatting/detail/{chattingRoomId}/{receiverId}/{receiverUserType}/{senderId}/{fromJobPosting} + care://chatting/detail/{chattingRoomId}/{myId}/{myUserType}/{opponentId}/{fromJobPosting} care://chatting/seeallchat/{allChatContents} care://signup/worker diff --git a/core/network/src/main/java/com/idle/network/api/AuthApi.kt b/core/network/src/main/java/com/idle/network/api/AuthApi.kt index 421c4a341..cb1e1f9f1 100644 --- a/core/network/src/main/java/com/idle/network/api/AuthApi.kt +++ b/core/network/src/main/java/com/idle/network/api/AuthApi.kt @@ -20,56 +20,56 @@ import retrofit2.http.POST import retrofit2.http.Path interface AuthApi { - @POST("/api/v1/auth/common/refresh") + @POST("api/v1/auth/common/refresh") suspend fun refreshToken(@Body refreshTokenRequest: RefreshTokenRequest): Response - @POST("/api/v1/auth/common/send") + @POST("api/v1/auth/common/send") suspend fun sendPhoneNumber(@Body sendPhoneRequest: SendPhoneRequest): Response - @POST("/api/v1/auth/common/confirm") + @POST("api/v1/auth/common/confirm") suspend fun confirmAuthCode(@Body confirmAuthCodeRequest: ConfirmAuthCodeRequest): Response - @POST("/api/v1/auth/center/join") + @POST("api/v1/auth/center/join") suspend fun signUpCenter(@Body signUpCenterRequest: SignUpCenterRequest): Response - @POST("/api/v1/auth/center/login") + @POST("api/v1/auth/center/login") suspend fun signInCenter(@Body signInCenterRequest: SignInCenterRequest): Response - @POST("/api/v1/auth/carer/join") + @POST("api/v1/auth/carer/join") suspend fun signUpWorker(@Body signUpWorkerRequest: SignUpWorkerRequest): Response - @POST("/api/v1/auth/carer/login") + @POST("api/v1/auth/carer/login") suspend fun signInWorker(@Body signInWorkerRequest: SignInWorkerRequest): Response - @POST("/api/v1/auth/center/logout") + @POST("api/v1/auth/center/logout") suspend fun logoutCenter(): Response - @POST("/api/v1/auth/carer/logout") + @POST("api/v1/auth/carer/logout") suspend fun logoutWorker(): Response - @POST("/api/v1/auth/center/withdraw") + @POST("api/v1/auth/center/withdraw") suspend fun withdrawalCenter( @Body withdrawalCenterRequest: WithdrawalCenterRequest ): Response - @POST("/api/v1/auth/carer/withdraw") + @POST("api/v1/auth/carer/withdraw") suspend fun withdrawalWorker( @Body withdrawalWorkerRequest: WithdrawalWorkerRequest ): Response - @GET("/api/v1/auth/center/validation/{identifier}") + @GET("api/v1/auth/center/validation/{identifier}") suspend fun validateIdentifier(@Path("identifier") identifier: String): Response - @GET("/api/v1/auth/center/authentication/{businessRegistrationNumber}") + @GET("api/v1/auth/center/authentication/{businessRegistrationNumber}") suspend fun validateBusinessRegistrationNumber( @Path("businessRegistrationNumber") businessRegistrationNumber: String ): Response - @PATCH("/api/v1/auth/center/password/new") + @PATCH("api/v1/auth/center/password/new") suspend fun generateNewPassword( @Body generateNewPasswordRequest: GenerateNewPasswordRequest ): Response - @PATCH("/api/v1/auth/center/join/verify") + @PATCH("api/v1/auth/center/join/verify") suspend fun sendCenterVerificationRequest(): Response -} \ No newline at end of file +} diff --git a/core/network/src/main/java/com/idle/network/api/ChatApi.kt b/core/network/src/main/java/com/idle/network/api/ChatApi.kt index 2711bdc98..222a5d94e 100644 --- a/core/network/src/main/java/com/idle/network/api/ChatApi.kt +++ b/core/network/src/main/java/com/idle/network/api/ChatApi.kt @@ -10,25 +10,25 @@ import retrofit2.http.Path import retrofit2.http.Query interface ChatApi { - @GET("/api/v2/chat/carer/chatrooms") + @GET("api/v2/chat/carer/chatrooms") suspend fun getWorkerChatRooms(): Response> - @GET("/api/v2/chat/center/chatrooms") + @GET("api/v2/chat/center/chatrooms") suspend fun getCenterChatRooms(): Response> - @POST("/api/v2/chat/carer/chatrooms") + @POST("api/v2/chat/carer/chatrooms") suspend fun generateWorkerChatRoom(@Query("opponentId") opponentId: String): Response - @POST("/api/v2/chat/carer/chatrooms") + @POST("api/v2/chat/carer/chatrooms") suspend fun generateCenterChatRoom(@Query("opponentId") opponentId: String): Response - @GET("/api/v2/chat/carer/chatrooms/{chatroom-id}/messages") + @GET("api/v2/chat/carer/chatrooms/{chatroom-id}/messages") suspend fun getWorkerChatRoomMessages( @Path("chatroom-id") chatRoomId: String, @Query("message-id") messageId: String?, ): Response> - @GET("/api/v2/chat/center/chatrooms/{chatroom-id}/messages") + @GET("api/v2/chat/center/chatrooms/{chatroom-id}/messages") suspend fun getCenterChatRoomMessages( @Path("chatroom-id") chatRoomId: String, @Query("message-id") messageId: String?, diff --git a/core/network/src/main/java/com/idle/network/api/JobPostingApi.kt b/core/network/src/main/java/com/idle/network/api/JobPostingApi.kt index 5ce6f9d68..746111644 100644 --- a/core/network/src/main/java/com/idle/network/api/JobPostingApi.kt +++ b/core/network/src/main/java/com/idle/network/api/JobPostingApi.kt @@ -23,84 +23,84 @@ import retrofit2.http.Path import retrofit2.http.Query interface JobPostingApi { - @POST("/api/v1/job-postings") + @POST("api/v1/job-postings") suspend fun postJobPosting(@Body jobPostingRequest: JobPostingRequest): Response - @PATCH("/api/v1/job-postings/{job-posting-id}") + @PATCH("api/v1/job-postings/{job-posting-id}") suspend fun updateJobPosting( @Path("job-posting-id") jobPostingId: String, @Body jobPostingRequest: JobPostingRequest, ): Response - @GET("/api/v1/job-postings/{job-posting-id}/center") + @GET("api/v1/job-postings/{job-posting-id}/center") suspend fun getJobPostingDetailCenter( @Path("job-posting-id") jobPostingId: String ): Response - @GET("/api/v1/job-postings") + @GET("api/v1/job-postings") suspend fun getJobPostings( @Query("next") next: String?, @Query("limit") limit: Int, ): Response - @GET("/api/v1/job-postings/carer/my/applied") + @GET("api/v1/job-postings/carer/my/applied") suspend fun getJobPostingsApplied( @Query("next") next: String?, @Query("limit") limit: Int, ): Response - @GET("/api/v1/job-postings/my/favorites") + @GET("api/v1/job-postings/my/favorites") suspend fun getMyFavoriteJobPostings(): Response - @GET("/api/v1/crawling-job-postings/my/favorites") + @GET("api/v1/crawling-job-postings/my/favorites") suspend fun getMyFavoriteCrawlingJobPostings(): Response - @GET("/api/v1/job-postings/status/in-progress") + @GET("api/v1/job-postings/status/in-progress") suspend fun getJobPostingsInProgress(): Response - @GET("/api/v1/job-postings/status/completed") + @GET("api/v1/job-postings/status/completed") suspend fun getJobPostingsCompleted(): Response - @GET("/api/v1/job-postings/{job-posting-id}/applicant-count") + @GET("api/v1/job-postings/{job-posting-id}/applicant-count") suspend fun getApplicantCount( @Path("job-posting-id") jobPostingId: String ): Response - @GET("/api/v1/job-postings/{job-posting-id}/carer") + @GET("api/v1/job-postings/{job-posting-id}/carer") suspend fun getJobPostingDetailWorker( @Path("job-posting-id") jobPostingId: String ): Response - @GET("/api/v1/job-postings/{job-posting-id}/applicants") + @GET("api/v1/job-postings/{job-posting-id}/applicants") suspend fun getApplicants( @Path("job-posting-id") jobPostingId: String ): Response - @POST("/api/v1/applys") + @POST("api/v1/applys") suspend fun applyJobPosting(@Body applyJobPostingRequest: ApplyJobPostingRequest): Response - @POST("/api/v1/job-postings/{job-posting-id}/favorites") + @POST("api/v1/job-postings/{job-posting-id}/favorites") suspend fun addFavoriteJobPosting( @Path("job-posting-id") jobPostingId: String, @Body favoriteJobPostingRequest: FavoriteJobPostingRequest, ): Response - @DELETE("/api/v1/job-postings/{job-posting-id}/remove-favorites") + @DELETE("api/v1/job-postings/{job-posting-id}/remove-favorites") suspend fun removeFavoriteJobPosting(@Path("job-posting-id") jobPostingId: String): Response - @PATCH("/api/v1/job-postings/{job-posting-id}/end") + @PATCH("api/v1/job-postings/{job-posting-id}/end") suspend fun endJobPosting(@Path("job-posting-id") jobPostingId: String): Response - @DELETE("/api/v1/job-postings/{job-posting-id}") + @DELETE("api/v1/job-postings/{job-posting-id}") suspend fun deleteJobPosting(@Path("job-posting-id") jobPostingId: String): Response - @GET("/api/v1/crawling-job-postings") + @GET("api/v1/crawling-job-postings") suspend fun getCrawlingJobPostings( @Query("next") next: String?, @Query("limit") limit: Int, ): Response - @GET("/api/v1/crawling-job-postings/{crawling-job-posting-id}") + @GET("api/v1/crawling-job-postings/{crawling-job-posting-id}") suspend fun getCrawlingJobPostingsDetail( @Path("crawling-job-posting-id") jobPostingId: String ): Response diff --git a/core/network/src/main/java/com/idle/network/api/NotificationApi.kt b/core/network/src/main/java/com/idle/network/api/NotificationApi.kt index 9d0ed9f8c..dd2ef609e 100644 --- a/core/network/src/main/java/com/idle/network/api/NotificationApi.kt +++ b/core/network/src/main/java/com/idle/network/api/NotificationApi.kt @@ -14,21 +14,21 @@ import retrofit2.http.Path import retrofit2.http.Query interface NotificationApi { - @POST("/api/v1/fcm/token") + @POST("api/v1/fcm/token") suspend fun postFCMToken(@Body postFcmTokenRequest: PostFcmTokenRequest): Response @HTTP(method = "DELETE", path = "/api/v1/fcm/token", hasBody = true) suspend fun deleteFCMToken(@Body deleteFcmTokenRequest: DeleteFcmTokenRequest): Response - @GET("/api/v1/notifications/my") + @GET("api/v1/notifications/my") suspend fun getMyNotifications( @Query("next") next: String?, @Query("limit") limit: Int, ): Response - @PATCH("/api/v1/notifications/{notification-id}") + @PATCH("api/v1/notifications/{notification-id}") suspend fun readNotification(@Path("notification-id") notificationId: String): Response - @GET("/api/v1/notifications/count") + @GET("api/v1/notifications/count") suspend fun getUnreadNotificationCount(): Response } diff --git a/core/network/src/main/java/com/idle/network/api/UserApi.kt b/core/network/src/main/java/com/idle/network/api/UserApi.kt index 368e769d7..1928f34f2 100644 --- a/core/network/src/main/java/com/idle/network/api/UserApi.kt +++ b/core/network/src/main/java/com/idle/network/api/UserApi.kt @@ -21,20 +21,20 @@ import retrofit2.http.Query import retrofit2.http.Url interface UserApi { - @GET("/api/v1/users/center/my/profile") + @GET("api/v1/users/center/my/profile") suspend fun getMyCenterProfile(): Response - @PATCH("/api/v1/users/center/my/profile") + @PATCH("api/v1/users/center/my/profile") suspend fun updateMyCenterProfile( @Body updateCenterProfileRequest: UpdateCenterProfileRequest ): Response - @GET("/api/v1/users/center/profile/{center-id}") + @GET("api/v1/users/center/profile/{center-id}") suspend fun getCenterProfile( @Path("center-id") centerId: String, ): Response - @GET("/api/v1/users/{user-type}/my/profile-image/upload-url") + @GET("api/v1/users/{user-type}/my/profile-image/upload-url") suspend fun getImageUploadUrl( @Path("user-type") userType: String, @Query("imageFileExtension") imageFileExtension: String, @@ -46,33 +46,33 @@ interface UserApi { @Body requestImage: RequestBody, ): Response - @POST("/api/v1/users/{user-type}/my/profile-image/upload-callback") + @POST("api/v1/users/{user-type}/my/profile-image/upload-callback") suspend fun callbackImageUpload( @Path("user-type") userType: String, @Body callbackImageUploadRequest: CallbackImageUploadRequest, ): Response - @GET("/api/v1/users/carer/my/profile") + @GET("api/v1/users/carer/my/profile") suspend fun getMyWorkerProfile(): Response - @GET("/api/v1/users/carer/profile/{carer-id}") + @GET("api/v1/users/carer/profile/{carer-id}") suspend fun getWorkerProfile( @Path("carer-id") workerId: String, ): Response - @PATCH("/api/v1/users/carer/my/profile") + @PATCH("api/v1/users/carer/my/profile") suspend fun updateWorkerProfile( @Body updateWorkerProfileRequest: UpdateWorkerProfileRequest ): Response - @POST("/api/v1/users/center/my/profile") + @POST("api/v1/users/center/my/profile") suspend fun registerCenterProfile( @Body registerCenterProfileRequest: RegisterCenterProfileRequest ): Response - @GET("/api/v1/logs/users/carer/my") + @GET("api/v1/logs/users/carer/my") suspend fun getWorkerId(): Response - @GET("/api/v1/auth/center/join/status") + @GET("api/v1/auth/center/join/status") suspend fun getCenterStatus(): Response -} \ No newline at end of file +} 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 909807ee3..1ede05608 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 @@ -72,4 +72,4 @@ class CareAuthenticator @Inject constructor( private const val MAX_RETRY_COUNT = 3 private const val RETRY_HEADER = "Retry-Count" } -} \ No newline at end of file +} diff --git a/core/network/src/main/java/com/idle/network/interceptor/AuthInterceptor.kt b/core/network/src/main/java/com/idle/network/interceptor/AuthInterceptor.kt index 03afec222..7e98a9053 100644 --- a/core/network/src/main/java/com/idle/network/interceptor/AuthInterceptor.kt +++ b/core/network/src/main/java/com/idle/network/interceptor/AuthInterceptor.kt @@ -33,7 +33,11 @@ class AuthInterceptor @Inject constructor( return false } - if (request.url.host.contains("aws-caremeet-upload.s3.ap-northeast-2.amazonaws.com")) { + if (request.url.host.contains("/aws-caremeet-upload.s3.ap-northeast-2.amazonaws.com")) { + return false + } + + if (request.url.host.contains("/api/v1/auth/common/refresh")) { return false } @@ -42,7 +46,6 @@ class AuthInterceptor @Inject constructor( "/api/v1/auth/common/confirm" -> false "/api/v1/auth/center/join" -> false "/api/v1/auth/center/login" -> false - "/api/v1/auth/common/refresh" -> false "/api/v1/auth/carer/login" -> false "/api/v1/auth/carer/join" -> false "/api/v1/auth/center/password/new" -> false diff --git a/core/network/src/main/java/com/idle/network/model/chat/GetChatRoomResponse.kt b/core/network/src/main/java/com/idle/network/model/chat/GetChatRoomResponse.kt index 12db6d208..dc19ede54 100644 --- a/core/network/src/main/java/com/idle/network/model/chat/GetChatRoomResponse.kt +++ b/core/network/src/main/java/com/idle/network/model/chat/GetChatRoomResponse.kt @@ -13,7 +13,7 @@ data class GetChatRoomResponse( val count: Int = 0, val opponentId: String = "", val opponentName: String = "", - val opponentProfileImageUrl: String = "", + val opponentProfileImageUrl: String? = null, ) { fun toVO() = ChatRoomWithOpponentInfo( id = chatRoomId, 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 cf25d24db..b9cebd520 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 android.util.Log +import com.idle.domain.model.auth.UserType import com.idle.network.BuildConfig import com.idle.network.api.ChatApi import com.idle.network.di.TokenManager @@ -111,18 +112,26 @@ class ChatDataSource @Inject constructor( it } ?: flow { throw IOException("웹소켓을 먼저 연결해주세요.") } - suspend fun sendMessage(sendMessageRequest: SendMessageRequest): Result = + suspend fun sendMessage( + userType: UserType, + sendMessageRequest: SendMessageRequest + ): Result = runCatching { + Log.d("test", "/pub/send/${userType.apiValue.lowercase()}") + session?.convertAndSend( - headers = StompSendHeaders(destination = "/pub/send"), + headers = StompSendHeaders(destination = "/pub/send/${userType.apiValue.lowercase()}"), body = sendMessageRequest, serializer = SendMessageRequest.serializer(), ) } - suspend fun readMessage(readMessageRequest: ReadMessageRequest): Result = runCatching { + suspend fun readMessage( + userType: UserType, + readMessageRequest: ReadMessageRequest + ): Result = runCatching { session?.convertAndSend( - headers = StompSendHeaders(destination = "/pub/read"), + headers = StompSendHeaders(destination = "/pub/read/${userType.apiValue.lowercase()}"), body = readMessageRequest, serializer = ReadMessageRequest.serializer(), ) diff --git a/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt b/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt index b6e8d2375..34ceaaf51 100644 --- a/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt +++ b/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt @@ -71,9 +71,7 @@ internal class CenterChattingFragment : BaseComposeFragment() { CenterChattingScreen( chatRoomList = chatRoomList, myProfile = myProfile, - navigateTo = { - navigationHelper.navigateTo(NavigationEvent.To(it)) - }, + navigateTo = { navigationHelper.navigateTo(NavigationEvent.To(it)) }, ) } } @@ -183,7 +181,7 @@ internal fun ChatRoomItem( chattingRoomId = chatRoom.id, myId = myProfile!!.centerId, opponentId = chatRoom.opponentId, - receiverUserType = UserType.WORKER.apiValue, + myUserType = UserType.CENTER.apiValue, fromJobPosting = false, ) ) 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 5ca9bc4a6..a91ca619e 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 @@ -15,10 +15,7 @@ import com.idle.domain.usecase.profile.GetMyCenterProfileUseCase import com.idle.navigation.NavigationHelper import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import javax.inject.Inject @@ -36,13 +33,9 @@ class CenterChattingViewModel @Inject constructor( private val _chatRoomMap = MutableStateFlow>(LinkedHashMap()) - val chatRoomList = _chatRoomMap - .map { it.values.toList() } - .stateIn( - scope = viewModelScope, - started = SharingStarted.Lazily, - initialValue = null, - ) + + private val _chatRoomList = MutableStateFlow?>(null) + val chatRoomList = _chatRoomList.asStateFlow() internal suspend fun initCenterChatting() { getMyCenterProfileUseCase().onSuccess { @@ -90,6 +83,7 @@ class CenterChattingViewModel @Inject constructor( } _chatRoomMap.value = updatedMap + updateChatRoomListFromMap() } internal suspend fun retrieveChatRoomList() { @@ -97,9 +91,12 @@ class CenterChattingViewModel @Inject constructor( userType = UserType.CENTER, userId = _myProfile.value?.centerId ?: return ).onSuccess { - val newMap = LinkedHashMap(_chatRoomMap.value) - it.forEach { chatRoom -> newMap[chatRoom.id] = chatRoom } + val newMap = LinkedHashMap().apply { + putAll(_chatRoomMap.value) + it.forEach { chatRoom -> this[chatRoom.id] = chatRoom } + } _chatRoomMap.value = newMap + updateChatRoomListFromMap() }.onFailure { errorHelper.sendError(it) } } @@ -108,9 +105,16 @@ class CenterChattingViewModel @Inject constructor( userId = _myProfile.value?.centerId ?: return, userType = UserType.CENTER ).onSuccess { - val newMap = LinkedHashMap(_chatRoomMap.value) - it.forEach { chatRoom -> newMap[chatRoom.id] = chatRoom } + val newMap = LinkedHashMap().apply { + putAll(_chatRoomMap.value) + it.forEach { chatRoom -> this[chatRoom.id] = chatRoom } + } _chatRoomMap.value = newMap + updateChatRoomListFromMap() } } + + private fun updateChatRoomListFromMap() { + _chatRoomList.value = _chatRoomMap.value.values.toList() + } } diff --git a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailFragment.kt b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailFragment.kt index a93f2eef1..fc9d24fea 100644 --- a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailFragment.kt +++ b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailFragment.kt @@ -23,8 +23,8 @@ internal class ChattingDetailFragment : BaseComposeFragment() { val scope = rememberCoroutineScope() fragmentViewModel.apply { - val receiverUserType = receiverUserType - val receiverId = receiverId + val receiverUserType = myUserType + val receiverId = myId val writingText by writingText.collectAsStateWithLifecycle() val chatMessages by chatMessages.collectAsStateWithLifecycle() 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 f00a58562..039c43772 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 @@ -1,5 +1,6 @@ package com.idle.chatting_detail +import android.util.Log import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -35,14 +36,15 @@ class ChattingDetailViewModel @Inject constructor( private val chattingRoomId: String = requireNotNull(savedStateHandle["chattingRoomId"]) { "chattingRoomId is missing in savedStateHandle" } - private val senderId: String = requireNotNull(savedStateHandle["senderId"]) { - "senderId is missing in savedStateHandle" + private val opponentId: String = requireNotNull(savedStateHandle["opponentId"]) { + "opponentId is missing in savedStateHandle" } - val receiverUserType: UserType = UserType.create( - requireNotNull(savedStateHandle["receiverUserType"]) { "receiverUserType is missing" } - ) - val receiverId: String = requireNotNull(savedStateHandle["receiverId"]) { - "receiverId is missing in savedStateHandle" + val myUserType: UserType = + UserType.create( + requireNotNull(savedStateHandle["myUserType"]) { "myUserType is missing" } + ) + val myId: String = requireNotNull(savedStateHandle["myId"]) { + "myId is missing in savedStateHandle" } private val fromJobPosting: Boolean = requireNotNull(savedStateHandle["fromJobPosting"]) { "fromJobPosting is missing in savedStateHandle" @@ -67,10 +69,10 @@ class ChattingDetailViewModel @Inject constructor( } internal suspend fun getUserProfile() = coroutineScope { - when (receiverUserType) { + when (myUserType) { UserType.CENTER -> { launch { - profileRepository.getWorkerProfile(senderId).onSuccess { + profileRepository.getWorkerProfile(opponentId).onSuccess { _workerProfile.value = it }.onFailure { errorHelper.sendError(it) @@ -86,7 +88,7 @@ class ChattingDetailViewModel @Inject constructor( UserType.WORKER -> { launch { - profileRepository.getCenterProfile(senderId).onSuccess { + profileRepository.getCenterProfile(opponentId).onSuccess { _centerProfile.value = it }.onFailure { errorHelper.sendError(it) @@ -105,11 +107,6 @@ class ChattingDetailViewModel @Inject constructor( internal suspend fun getChatMessages() { if (_callType.value == MessageCallType.END) return - val myId = when (receiverUserType) { - UserType.WORKER -> _workerProfile.value?.workerId ?: return - UserType.CENTER -> _centerProfile.value?.centerId ?: return - } - if (fromJobPosting) { chatRepository.retrieveChatRoomMessages( roomId = chattingRoomId, @@ -125,7 +122,7 @@ class ChattingDetailViewModel @Inject constructor( chatRepository.getChatRoomMessages( roomId = chattingRoomId, messageId = _chatMessages.value?.first()?.id, - userType = receiverUserType, + userType = myUserType, myId = myId, ).onSuccess { messages -> if (messages.isEmpty()) _callType.value = MessageCallType.END @@ -138,11 +135,6 @@ class ChattingDetailViewModel @Inject constructor( } internal suspend fun subscribeChatMessage() { - val myId = when (receiverUserType) { - UserType.WORKER -> _workerProfile.value?.workerId ?: return - UserType.CENTER -> _centerProfile.value?.centerId ?: return - } - chatRepository.subscribeChatMessage(myId) .catch { errorHelper.sendError(it) @@ -150,7 +142,6 @@ class ChattingDetailViewModel @Inject constructor( when (message) { is ChatMessage -> { if (message.senderId != myId) readMessage() - _chatMessages.value = (_chatMessages.value ?: emptyList()) + message } @@ -164,37 +155,30 @@ class ChattingDetailViewModel @Inject constructor( } internal fun sendMessage() = viewModelScope.launch { - val receiverId = if (receiverUserType == UserType.CENTER) _workerProfile.value!!.workerId - else _centerProfile.value!!.centerId - - val myId = if (receiverUserType == UserType.CENTER) _centerProfile.value!!.centerId - else _workerProfile.value!!.workerId + val senderName = if (myUserType == UserType.CENTER) _centerProfile.value!!.centerName + else _workerProfile.value!!.workerName - val senderName = - if (receiverUserType == UserType.CENTER) _centerProfile.value!!.centerName - else _workerProfile.value!!.workerName + Log.d("test", "$myId $myUserType $chattingRoomId") chatRepository.sendMessage( chatroomId = chattingRoomId, myId = myId, - receiverId = receiverId, + receiverId = opponentId, senderName = senderName, content = _writingText.value, + userType = myUserType, ).onSuccess { _writingText.value = "" }.onFailure { errorHelper.sendError(it) } } internal suspend fun readMessage() { - val opponentId = if (receiverUserType == UserType.CENTER) _workerProfile.value!!.workerId - else _centerProfile.value!!.centerId - - val myId = if (receiverUserType == UserType.CENTER) _centerProfile.value!!.centerId - else _workerProfile.value!!.workerId + Log.d("test", "$opponentId $myUserType $chattingRoomId") chatRepository.readMessage( chatroomId = chattingRoomId, opponentId = opponentId, + userType = myUserType, ).onSuccess { _chatMessages.value = _chatMessages.value?.map { if (it.receiverId == myId) it.copy(isRead = true) else it diff --git a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ui/component/CareChatTextBubble.kt b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ui/component/CareChatTextBubble.kt index 0dea0a8b9..64e93b5f4 100644 --- a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ui/component/CareChatTextBubble.kt +++ b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ui/component/CareChatTextBubble.kt @@ -50,10 +50,8 @@ fun CareChatSenderTextBubbleWithImage( modifier = modifier.fillMaxWidth() ) { AsyncImage( - model = imageUrl - ?: painterResource(com.idle.designresource.R.drawable.ic_notification_placeholder), - placeholder = - painterResource(com.idle.designresource.R.drawable.ic_notification_placeholder), + model = imageUrl ?: com.idle.designresource.R.drawable.ic_notification_placeholder, + placeholder = painterResource(com.idle.designresource.R.drawable.ic_notification_placeholder), error = painterResource(com.idle.designresource.R.drawable.ic_notification_placeholder), onError = { Log.d("test", imageUrl.toString()) }, contentDescription = null, diff --git a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ui/component/ChattingInput.kt b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ui/component/ChattingInput.kt index 83c3ac8c5..7c50714c2 100644 --- a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ui/component/ChattingInput.kt +++ b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ui/component/ChattingInput.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import com.idle.compose.ui.clickable @@ -20,6 +21,8 @@ fun ChattingInput( sendMessage: () -> Unit, modifier: Modifier = Modifier, ) { + val focusManager = LocalFocusManager.current + Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(16.dp), @@ -39,7 +42,10 @@ fun ChattingInput( contentDescription = "", modifier = Modifier .size(32.dp) - .clickable(throttleTime = 1000L) { sendMessage() }, + .clickable(throttleTime = 1000L) { + sendMessage() + focusManager.clearFocus() + }, ) } } diff --git a/feature/chatting-detail/src/main/res/navigation/nav_chatting_detail.xml b/feature/chatting-detail/src/main/res/navigation/nav_chatting_detail.xml index c073585d7..3fec3e5ad 100644 --- a/feature/chatting-detail/src/main/res/navigation/nav_chatting_detail.xml +++ b/feature/chatting-detail/src/main/res/navigation/nav_chatting_detail.xml @@ -13,13 +13,13 @@ android:name="chattingRoomId" app:argType="string" /> Date: Sat, 10 May 2025 03:43:42 +0900 Subject: [PATCH 2/7] =?UTF-8?q?[PC-000]=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83,=20=ED=9A=8C=EC=9B=90=ED=83=88=ED=87=B4=20=EC=8B=9C?= =?UTF-8?q?=20=EC=9B=B9=EC=86=8C=EC=BC=93=20=EC=97=B0=EA=B2=B0=EC=9D=84=20?= =?UTF-8?q?=EB=81=8A=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/idle/setting/center/CenterSettingViewModel.kt | 3 +++ .../java/com/idle/setting/worker/WorkerSettingViewModel.kt | 3 +++ .../src/main/java/com/idle/withdrawal/WithdrawalViewModel.kt | 4 ++++ 3 files changed, 10 insertions(+) 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 2885be88d..dfe1d3441 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 @@ -6,6 +6,7 @@ import com.idle.analytics.AnalyticsHelper import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.profile.CenterProfile import com.idle.domain.repositorry.AuthRepository +import com.idle.domain.repositorry.ChatRepository import com.idle.domain.usecase.profile.GetMyCenterProfileUseCase import com.idle.setting.SettingEvent import dagger.hilt.android.lifecycle.HiltViewModel @@ -20,6 +21,7 @@ import javax.inject.Inject class CenterSettingViewModel @Inject constructor( private val getMyCenterProfileUseCase: GetMyCenterProfileUseCase, private val authRepository: AuthRepository, + private val chatRepository: ChatRepository, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, val navigationHelper: com.idle.navigation.NavigationHelper, @@ -46,6 +48,7 @@ class CenterSettingViewModel @Inject constructor( fun logout() = viewModelScope.launch { authRepository.logoutCenter().onSuccess { analyticsHelper.setUserId(null) + chatRepository.disconnectWebSocket() navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( toastMsg = "로그아웃이 완료되었습니다.", 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 94121beed..8837f3812 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 @@ -6,6 +6,7 @@ import com.idle.analytics.AnalyticsHelper import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.profile.WorkerProfile import com.idle.domain.repositorry.AuthRepository +import com.idle.domain.repositorry.ChatRepository import com.idle.domain.usecase.profile.GetMyWorkerProfileUseCase import com.idle.setting.SettingEvent import dagger.hilt.android.lifecycle.HiltViewModel @@ -19,6 +20,7 @@ import javax.inject.Inject class WorkerSettingViewModel @Inject constructor( private val getMyWorkerProfileUseCase: GetMyWorkerProfileUseCase, private val authRepository: AuthRepository, + private val chatRepository: ChatRepository, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, val navigationHelper: com.idle.navigation.NavigationHelper, @@ -41,6 +43,7 @@ class WorkerSettingViewModel @Inject constructor( fun logout() = viewModelScope.launch { authRepository.logoutWorker().onSuccess { analyticsHelper.setUserId(null) + chatRepository.disconnectWebSocket() navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( toastMsg = "로그아웃이 완료되었습니다.", 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 50d71a2de..717fb92fc 100644 --- a/feature/withdrawal/src/main/java/com/idle/withdrawal/WithdrawalViewModel.kt +++ b/feature/withdrawal/src/main/java/com/idle/withdrawal/WithdrawalViewModel.kt @@ -13,6 +13,7 @@ import com.idle.domain.model.error.ApiErrorCode import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.error.HttpResponseException import com.idle.domain.repositorry.AuthRepository +import com.idle.domain.repositorry.ChatRepository import com.idle.domain.util.formatPhoneNumber import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Job @@ -24,6 +25,7 @@ import javax.inject.Inject @HiltViewModel class WithdrawalViewModel @Inject constructor( private val authRepository: AuthRepository, + privaate val chatRepository: ChatRepository, private val countDownTimer: CountDownTimer, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, @@ -165,6 +167,7 @@ class WithdrawalViewModel @Inject constructor( password = password.value ).onSuccess { analyticsHelper.setUserId(null) + chatRepository.disconnectWebSocket() navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( "회원탈퇴가 완료되었어요." @@ -187,6 +190,7 @@ class WithdrawalViewModel @Inject constructor( .joinToString("|"), ).onSuccess { analyticsHelper.setUserId(null) + chatRepository.disconnectWebSocket() navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( "회원탈퇴가 완료되었어요." From 162b15c5c87f3d209b96893865ba3cd20d77d376 Mon Sep 17 00:00:00 2001 From: tgyuuAn Date: Sat, 10 May 2025 03:44:31 +0900 Subject: [PATCH 3/7] =?UTF-8?q?[PC-000]=20=ED=86=A0=ED=81=B0=EC=9D=B4=20?= =?UTF-8?q?=EC=97=86=EC=9D=84=20=EA=B2=BD=EC=9A=B0=20=EC=9B=B9=EC=86=8C?= =?UTF-8?q?=EC=BC=93=20=EC=97=B0=EA=B2=B0=EC=9D=84=20=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/idle/presentation/MainViewModel.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/presentation/src/main/java/com/idle/presentation/MainViewModel.kt b/presentation/src/main/java/com/idle/presentation/MainViewModel.kt index 7f2e7cfe5..c9113d193 100644 --- a/presentation/src/main/java/com/idle/presentation/MainViewModel.kt +++ b/presentation/src/main/java/com/idle/presentation/MainViewModel.kt @@ -56,6 +56,12 @@ class MainViewModel @Inject constructor( } internal fun connectWebSocket() = viewModelScope.launch { + val (accessToken, userRole) = getAccessTokenAndUserRole() + + if (accessToken.isBlank() || userRole.isBlank()) { + return@launch + } + chatRepository.connectWebSocket() } From 535296c05083c646eec135b15cdc0898603761c4 Mon Sep 17 00:00:00 2001 From: tgyuuAn Date: Sat, 10 May 2025 03:45:16 +0900 Subject: [PATCH 4/7] =?UTF-8?q?[PC-000]=20=EB=A6=AC=ED=94=84=EB=A0=88?= =?UTF-8?q?=EC=8B=9C=20=ED=86=A0=ED=81=B0=EC=9D=B4=20=EB=A7=8C=EB=A3=8C?= =?UTF-8?q?=EB=90=98=EC=97=88=EC=9D=84=20=EA=B2=BD=EC=9A=B0=20=EC=9B=B9?= =?UTF-8?q?=EC=86=8C=EC=BC=93=20=EC=97=B0=EA=B2=B0=EC=9D=84=20=EB=81=8A?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/idle/presentation/MainViewModel.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/presentation/src/main/java/com/idle/presentation/MainViewModel.kt b/presentation/src/main/java/com/idle/presentation/MainViewModel.kt index c9113d193..0180a2b95 100644 --- a/presentation/src/main/java/com/idle/presentation/MainViewModel.kt +++ b/presentation/src/main/java/com/idle/presentation/MainViewModel.kt @@ -165,12 +165,15 @@ class MainViewModel @Inject constructor( ApiErrorCode.TokenNotValid, ApiErrorCode.TokenExpiredException, ApiErrorCode.TokenNotFound, - ApiErrorCode.NotSupportUserTokenType -> + ApiErrorCode.NotSupportUserTokenType -> { + disconnectWebSocket() + navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( exception.print() ) ) + } else -> eventHelper.sendEvent(ShowToast(exception.print())) } From ad8b70c93cce78d0b347f4af821a450d50da5f28 Mon Sep 17 00:00:00 2001 From: tgyuuAn Date: Sat, 10 May 2025 03:58:17 +0900 Subject: [PATCH 5/7] =?UTF-8?q?[PC-000]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/idle/network/source/ChatDataSource.kt | 2 ++ .../idle/signin/center/CenterSignInViewModel.kt | 7 ++++--- .../idle/signup/worker/WorkerSignUpViewModel.kt | 4 ++++ .../com/idle/withdrawal/WithdrawalViewModel.kt | 2 +- .../java/com/idle/presentation/MainViewModel.kt | 15 ++++++--------- 5 files changed, 17 insertions(+), 13 deletions(-) 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 b9cebd520..d1a471caf 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 @@ -92,6 +92,7 @@ class ChatDataSource @Inject constructor( connectionAttempts++ connectWebSocket().getOrThrow() } else { + Log.d("test connect", throwable.stackTraceToString()) throw throwable } } @@ -100,6 +101,7 @@ class ChatDataSource @Inject constructor( session?.disconnect() Result.success(Unit) } catch (e: Exception) { + Log.d("test disconnect", e.stackTraceToString()) Result.failure(e) } 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 81f7db295..ae146316b 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 @@ -13,6 +13,7 @@ import com.idle.domain.model.error.HttpResponseException import com.idle.domain.model.error.HttpResponseStatus import com.idle.domain.model.profile.CenterManagerAccountStatus import com.idle.domain.repositorry.AuthRepository +import com.idle.domain.repositorry.ChatRepository import com.idle.domain.repositorry.ProfileRepository import com.idle.navigation.DeepLinkDestination.CenterHome import com.idle.navigation.DeepLinkDestination.CenterPending @@ -28,6 +29,7 @@ import javax.inject.Inject @HiltViewModel class CenterSignInViewModel @Inject constructor( private val authRepository: AuthRepository, + private val chatRepository: ChatRepository, private val profileRepository: ProfileRepository, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, @@ -107,9 +109,8 @@ class CenterSignInViewModel @Inject constructor( private fun fetchAndNavigateToProfile() = viewModelScope.launch { profileRepository.getMyCenterProfile().onSuccess { - navigationHelper.navigateTo( - To(CenterHome, R.id.centerSignInFragment) - ) + chatRepository.connectWebSocket() + navigationHelper.navigateTo(To(CenterHome, R.id.centerSignInFragment)) }.onFailure { val error = it as HttpResponseException if (error.apiErrorCode == ApiErrorCode.CenterNotFound) { 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 f74140747..ceff766c0 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 @@ -13,6 +13,7 @@ import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.error.HttpResponseException import com.idle.domain.model.error.HttpResponseStatus import com.idle.domain.repositorry.AuthRepository +import com.idle.domain.repositorry.ChatRepository import com.idle.domain.repositorry.ProfileRepository import com.idle.domain.util.formatPhoneNumber import com.idle.navigation.DeepLinkDestination.SignUpComplete @@ -31,6 +32,7 @@ import javax.inject.Inject class WorkerSignUpViewModel @Inject constructor( private val profileRepository: ProfileRepository, private val authRepository: AuthRepository, + private val chatRepository: ChatRepository, private val countDownTimer: CountDownTimer, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, @@ -151,6 +153,7 @@ class WorkerSignUpViewModel @Inject constructor( authCode = _workerAuthCode.value, ).onSuccess { profileRepository.getWorkerId().onSuccess { analyticsHelper.setUserId(it) } + chatRepository.connectWebSocket() navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.To( WorkerHome, @@ -186,6 +189,7 @@ class WorkerSignUpViewModel @Inject constructor( lotNumberAddress = _lotNumberAddress.value, ).onSuccess { profileRepository.getWorkerId().onSuccess { analyticsHelper.setUserId(it) } + chatRepository.connectWebSocket() 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 717fb92fc..2a1c5924e 100644 --- a/feature/withdrawal/src/main/java/com/idle/withdrawal/WithdrawalViewModel.kt +++ b/feature/withdrawal/src/main/java/com/idle/withdrawal/WithdrawalViewModel.kt @@ -25,7 +25,7 @@ import javax.inject.Inject @HiltViewModel class WithdrawalViewModel @Inject constructor( private val authRepository: AuthRepository, - privaate val chatRepository: ChatRepository, + private val chatRepository: ChatRepository, private val countDownTimer: CountDownTimer, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, diff --git a/presentation/src/main/java/com/idle/presentation/MainViewModel.kt b/presentation/src/main/java/com/idle/presentation/MainViewModel.kt index 0180a2b95..55a5fd581 100644 --- a/presentation/src/main/java/com/idle/presentation/MainViewModel.kt +++ b/presentation/src/main/java/com/idle/presentation/MainViewModel.kt @@ -22,6 +22,7 @@ import com.idle.navigation.DeepLinkDestination.CenterHome import com.idle.navigation.DeepLinkDestination.CenterPending import com.idle.navigation.DeepLinkDestination.CenterRegister import com.idle.navigation.DeepLinkDestination.WorkerHome +import com.idle.navigation.NavigationEvent import com.idle.navigation.NavigationHelper import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.async @@ -112,9 +113,7 @@ class MainViewModel @Inject constructor( private suspend fun navigateToDestination(userRole: String) { when (userRole) { - UserType.WORKER.apiValue -> navigationHelper.navigateTo( - com.idle.navigation.NavigationEvent.To(WorkerHome, R.id.authFragment) - ) + UserType.WORKER.apiValue -> navigationHelper.navigateTo(NavigationEvent.To(WorkerHome, R.id.authFragment)) UserType.CENTER.apiValue -> getCenterStatus() else -> Unit @@ -130,7 +129,7 @@ class MainViewModel @Inject constructor( when (status) { CenterManagerAccountStatus.APPROVED -> handleApprovedCenterStatus() else -> navigationHelper.navigateTo( - com.idle.navigation.NavigationEvent.To( + NavigationEvent.To( CenterPending(status.name), R.id.authFragment ) @@ -140,14 +139,12 @@ class MainViewModel @Inject constructor( private fun handleApprovedCenterStatus() = viewModelScope.launch { profileRepository.getMyCenterProfile().onSuccess { - navigationHelper.navigateTo( - com.idle.navigation.NavigationEvent.To(CenterHome, R.id.authFragment) - ) + navigationHelper.navigateTo(NavigationEvent.To(CenterHome, R.id.authFragment)) }.onFailure { val error = it as HttpResponseException if (error.apiErrorCode == ApiErrorCode.CenterNotFound) { navigationHelper.navigateTo( - com.idle.navigation.NavigationEvent.To( + NavigationEvent.To( CenterRegister, R.id.authFragment ) @@ -169,7 +166,7 @@ class MainViewModel @Inject constructor( disconnectWebSocket() navigationHelper.navigateTo( - com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( + NavigationEvent.ToAuthWithClearBackStack( exception.print() ) ) From f3e720aa67f22511169a4b5fe88960f57fd92f92 Mon Sep 17 00:00:00 2001 From: tgyuuAn Date: Sat, 10 May 2025 04:05:21 +0900 Subject: [PATCH 6/7] =?UTF-8?q?feat=20:=20ci/cd=EC=97=90=20websocket=20url?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/android_cd.yml | 2 ++ .github/workflows/android_ci.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/android_cd.yml b/.github/workflows/android_cd.yml index cd64aef1b..57156db54 100644 --- a/.github/workflows/android_cd.yml +++ b/.github/workflows/android_cd.yml @@ -34,6 +34,8 @@ jobs: run: | echo "CARE_DEV_BASE_URL=${{ secrets.CARE_DEV_BASE_URL }}" >> local.properties echo "CARE_PROD_BASE_URL=${{ secrets.CARE_PROD_BASE_URL }}" >> local.properties + echo "CARE_DEV_WEBSOCKET_URL=${{ secrets.CARE_DEV_WEBSOCKET_URL }}" >> local.properties + echo "CARE_PROD_WEBSOCKET_URL=${{ secrets.CARE_PROD_WEBSOCKET_URL }}" >> local.properties echo "NAVER_BASE_URL=${{ secrets.NAVER_BASE_URL }}" >> local.properties echo "NAVER_CLIENT_ID=${{ secrets.NAVER_CLIENT_ID }}" >> local.properties echo "NAVER_CLIENT_SECRET=${{ secrets.NAVER_CLIENT_SECRET }}" >> local.properties diff --git a/.github/workflows/android_ci.yml b/.github/workflows/android_ci.yml index 800138e13..739094f12 100644 --- a/.github/workflows/android_ci.yml +++ b/.github/workflows/android_ci.yml @@ -37,6 +37,8 @@ jobs: run: | echo "CARE_DEV_BASE_URL=${{ secrets.CARE_DEV_BASE_URL }}" >> local.properties echo "CARE_PROD_BASE_URL=${{ secrets.CARE_PROD_BASE_URL }}" >> local.properties + echo "CARE_DEV_WEBSOCKET_URL=${{ secrets.CARE_DEV_WEBSOCKET_URL }}" >> local.properties + echo "CARE_PROD_WEBSOCKET_URL=${{ secrets.CARE_PROD_WEBSOCKET_URL }}" >> local.properties echo "NAVER_BASE_URL=${{ secrets.NAVER_BASE_URL }}" >> local.properties echo "NAVER_CLIENT_ID=${{ secrets.NAVER_CLIENT_ID }}" >> local.properties echo "NAVER_CLIENT_SECRET=${{ secrets.NAVER_CLIENT_SECRET }}" >> local.properties From 70326f5392caebad0f5f30c913caffaf348589b8 Mon Sep 17 00:00:00 2001 From: tgyuuAn Date: Sat, 10 May 2025 17:39:27 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat=20:=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D,=20=EC=B1=84=ED=8C=85=EB=B0=A9=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=ED=99=94=EB=A9=B4=EC=97=90=EC=84=9C=EB=A7=8C=20?= =?UTF-8?q?=EC=9B=B9=EC=86=8C=EC=BC=93=EC=9D=84=20=EC=97=B0=EA=B2=B0?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B2=83=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../center/chatting/CenterChattingFragment.kt | 7 +++++- .../chatting/CenterChattingViewModel.kt | 12 ++++++++- .../chatting_detail/ChattingDetailFragment.kt | 8 +++++- .../ChattingDetailViewModel.kt | 12 ++++++++- .../setting/center/CenterSettingViewModel.kt | 10 +++----- .../setting/worker/WorkerSettingViewModel.kt | 3 --- .../signin/center/CenterSignInViewModel.kt | 3 --- .../signup/worker/WorkerSignUpViewModel.kt | 4 --- .../idle/withdrawal/WithdrawalViewModel.kt | 4 --- .../worker/chatting/WorkerChattingFragment.kt | 14 ++++++----- .../chatting/WorkerChattingViewModel.kt | 13 +++++++++- .../com/idle/presentation/MainActivity.kt | 12 --------- .../com/idle/presentation/MainViewModel.kt | 25 +++++-------------- 13 files changed, 64 insertions(+), 63 deletions(-) diff --git a/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt b/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt index 34ceaaf51..799c166a0 100644 --- a/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt +++ b/feature/center-chatting/src/main/java/com/idle/center/chatting/CenterChattingFragment.kt @@ -35,6 +35,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.fragment.app.viewModels +import androidx.lifecycle.compose.LifecycleStartEffect import androidx.lifecycle.compose.collectAsStateWithLifecycle import coil.compose.AsyncImage import com.idle.compose.base.BaseComposeFragment @@ -65,7 +66,11 @@ internal class CenterChattingFragment : BaseComposeFragment() { initCenterChatting() retrieveChatRoomList() loadChatRoomList() - subscribeChatMessage() + } + + LifecycleStartEffect(fragmentViewModel) { + connectWebsocket() + onStopOrDispose { disconnectWebsocket() } } CenterChattingScreen( 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 a91ca619e..25fc60b76 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 @@ -43,7 +43,17 @@ class CenterChattingViewModel @Inject constructor( }.onFailure { errorHelper.sendError(it) } } - internal fun subscribeChatMessage() = viewModelScope.launch { + internal fun connectWebsocket() = viewModelScope.launch { + chatRepository.connectWebSocket().onSuccess { + subscribeChatMessage() + } + } + + internal fun disconnectWebsocket() = viewModelScope.launch { + chatRepository.disconnectWebSocket() + } + + private fun subscribeChatMessage() = viewModelScope.launch { chatRepository.subscribeChatMessage(_myProfile.value?.centerId ?: return@launch) .collect { message -> when (message) { diff --git a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailFragment.kt b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailFragment.kt index fc9d24fea..ab65c18f1 100644 --- a/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailFragment.kt +++ b/feature/chatting-detail/src/main/java/com/idle/chatting_detail/ChattingDetailFragment.kt @@ -5,6 +5,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import androidx.fragment.app.viewModels +import androidx.lifecycle.compose.LifecycleStartEffect import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.fragment.findNavController import com.idle.chatting_detail.ui.ChattingDetailLoadingScreen @@ -34,10 +35,15 @@ internal class ChattingDetailFragment : BaseComposeFragment() { LaunchedEffect(Unit) { getUserProfile() getChatMessages() - subscribeChatMessage() readMessage() } + LifecycleStartEffect(fragmentViewModel) { + connectWebsocket() + onStopOrDispose { disconnectWebsocket() } + } + + if (chatMessages != null && workerProfile != null && centerProfile != null) { ChattingDetailScreen( receiverId = receiverId, 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 039c43772..6aa5f05e5 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 @@ -134,7 +134,17 @@ class ChattingDetailViewModel @Inject constructor( } } - internal suspend fun subscribeChatMessage() { + internal fun connectWebsocket() = viewModelScope.launch { + chatRepository.connectWebSocket().onSuccess { + subscribeChatMessage() + } + } + + internal fun disconnectWebsocket() = viewModelScope.launch { + chatRepository.disconnectWebSocket() + } + + private suspend fun subscribeChatMessage() { chatRepository.subscribeChatMessage(myId) .catch { 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 dfe1d3441..613a9ab1b 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 @@ -6,7 +6,6 @@ import com.idle.analytics.AnalyticsHelper import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.profile.CenterProfile import com.idle.domain.repositorry.AuthRepository -import com.idle.domain.repositorry.ChatRepository import com.idle.domain.usecase.profile.GetMyCenterProfileUseCase import com.idle.setting.SettingEvent import dagger.hilt.android.lifecycle.HiltViewModel @@ -21,15 +20,13 @@ import javax.inject.Inject class CenterSettingViewModel @Inject constructor( private val getMyCenterProfileUseCase: GetMyCenterProfileUseCase, private val authRepository: AuthRepository, - private val chatRepository: ChatRepository, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, val navigationHelper: com.idle.navigation.NavigationHelper, ) : ViewModel() { - private val _centerProfile = - MutableStateFlow( - CenterProfile("", "", "", "", "", "", 0.0, 0.0, "", "") - ) + private val _centerProfile = MutableStateFlow( + CenterProfile("", "", "", "", "", "", 0.0, 0.0, "", "") + ) val centerProfile = _centerProfile.asStateFlow() private val _centerSettingEvent = MutableSharedFlow() @@ -48,7 +45,6 @@ class CenterSettingViewModel @Inject constructor( fun logout() = viewModelScope.launch { authRepository.logoutCenter().onSuccess { analyticsHelper.setUserId(null) - chatRepository.disconnectWebSocket() navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( toastMsg = "로그아웃이 완료되었습니다.", 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 8837f3812..94121beed 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 @@ -6,7 +6,6 @@ import com.idle.analytics.AnalyticsHelper import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.profile.WorkerProfile import com.idle.domain.repositorry.AuthRepository -import com.idle.domain.repositorry.ChatRepository import com.idle.domain.usecase.profile.GetMyWorkerProfileUseCase import com.idle.setting.SettingEvent import dagger.hilt.android.lifecycle.HiltViewModel @@ -20,7 +19,6 @@ import javax.inject.Inject class WorkerSettingViewModel @Inject constructor( private val getMyWorkerProfileUseCase: GetMyWorkerProfileUseCase, private val authRepository: AuthRepository, - private val chatRepository: ChatRepository, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, val navigationHelper: com.idle.navigation.NavigationHelper, @@ -43,7 +41,6 @@ class WorkerSettingViewModel @Inject constructor( fun logout() = viewModelScope.launch { authRepository.logoutWorker().onSuccess { analyticsHelper.setUserId(null) - chatRepository.disconnectWebSocket() navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( toastMsg = "로그아웃이 완료되었습니다.", 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 ae146316b..5af940bfe 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 @@ -13,7 +13,6 @@ import com.idle.domain.model.error.HttpResponseException import com.idle.domain.model.error.HttpResponseStatus import com.idle.domain.model.profile.CenterManagerAccountStatus import com.idle.domain.repositorry.AuthRepository -import com.idle.domain.repositorry.ChatRepository import com.idle.domain.repositorry.ProfileRepository import com.idle.navigation.DeepLinkDestination.CenterHome import com.idle.navigation.DeepLinkDestination.CenterPending @@ -29,7 +28,6 @@ import javax.inject.Inject @HiltViewModel class CenterSignInViewModel @Inject constructor( private val authRepository: AuthRepository, - private val chatRepository: ChatRepository, private val profileRepository: ProfileRepository, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, @@ -109,7 +107,6 @@ class CenterSignInViewModel @Inject constructor( private fun fetchAndNavigateToProfile() = viewModelScope.launch { profileRepository.getMyCenterProfile().onSuccess { - chatRepository.connectWebSocket() navigationHelper.navigateTo(To(CenterHome, R.id.centerSignInFragment)) }.onFailure { val error = it as HttpResponseException 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 ceff766c0..f74140747 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 @@ -13,7 +13,6 @@ import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.error.HttpResponseException import com.idle.domain.model.error.HttpResponseStatus import com.idle.domain.repositorry.AuthRepository -import com.idle.domain.repositorry.ChatRepository import com.idle.domain.repositorry.ProfileRepository import com.idle.domain.util.formatPhoneNumber import com.idle.navigation.DeepLinkDestination.SignUpComplete @@ -32,7 +31,6 @@ import javax.inject.Inject class WorkerSignUpViewModel @Inject constructor( private val profileRepository: ProfileRepository, private val authRepository: AuthRepository, - private val chatRepository: ChatRepository, private val countDownTimer: CountDownTimer, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, @@ -153,7 +151,6 @@ class WorkerSignUpViewModel @Inject constructor( authCode = _workerAuthCode.value, ).onSuccess { profileRepository.getWorkerId().onSuccess { analyticsHelper.setUserId(it) } - chatRepository.connectWebSocket() navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.To( WorkerHome, @@ -189,7 +186,6 @@ class WorkerSignUpViewModel @Inject constructor( lotNumberAddress = _lotNumberAddress.value, ).onSuccess { profileRepository.getWorkerId().onSuccess { analyticsHelper.setUserId(it) } - chatRepository.connectWebSocket() 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 2a1c5924e..50d71a2de 100644 --- a/feature/withdrawal/src/main/java/com/idle/withdrawal/WithdrawalViewModel.kt +++ b/feature/withdrawal/src/main/java/com/idle/withdrawal/WithdrawalViewModel.kt @@ -13,7 +13,6 @@ import com.idle.domain.model.error.ApiErrorCode import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.error.HttpResponseException import com.idle.domain.repositorry.AuthRepository -import com.idle.domain.repositorry.ChatRepository import com.idle.domain.util.formatPhoneNumber import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Job @@ -25,7 +24,6 @@ import javax.inject.Inject @HiltViewModel class WithdrawalViewModel @Inject constructor( private val authRepository: AuthRepository, - private val chatRepository: ChatRepository, private val countDownTimer: CountDownTimer, private val analyticsHelper: AnalyticsHelper, private val errorHelper: ErrorHelper, @@ -167,7 +165,6 @@ class WithdrawalViewModel @Inject constructor( password = password.value ).onSuccess { analyticsHelper.setUserId(null) - chatRepository.disconnectWebSocket() navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( "회원탈퇴가 완료되었어요." @@ -190,7 +187,6 @@ class WithdrawalViewModel @Inject constructor( .joinToString("|"), ).onSuccess { analyticsHelper.setUserId(null) - chatRepository.disconnectWebSocket() navigationHelper.navigateTo( com.idle.navigation.NavigationEvent.ToAuthWithClearBackStack( "회원탈퇴가 완료되었어요." diff --git a/feature/worker-chatting/src/main/java/com/idle/worker/chatting/WorkerChattingFragment.kt b/feature/worker-chatting/src/main/java/com/idle/worker/chatting/WorkerChattingFragment.kt index 1f991fc9b..02cc21a35 100644 --- a/feature/worker-chatting/src/main/java/com/idle/worker/chatting/WorkerChattingFragment.kt +++ b/feature/worker-chatting/src/main/java/com/idle/worker/chatting/WorkerChattingFragment.kt @@ -35,6 +35,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.fragment.app.viewModels +import androidx.lifecycle.compose.LifecycleStartEffect import androidx.lifecycle.compose.collectAsStateWithLifecycle import coil.compose.AsyncImage import com.idle.compose.base.BaseComposeFragment @@ -50,7 +51,6 @@ import com.idle.domain.util.formatUnReadNumber import com.idle.navigation.DeepLinkDestination import com.idle.navigation.NavigationEvent import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.launch @AndroidEntryPoint internal class WorkerChattingFragment : BaseComposeFragment() { @@ -64,11 +64,13 @@ internal class WorkerChattingFragment : BaseComposeFragment() { LaunchedEffect(Unit) { initWorkerChatting() - launch { - retrieveChatRoomList() - loadChatRoomList() - } - launch { subscribeChatMessage() } + retrieveChatRoomList() + loadChatRoomList() + } + + LifecycleStartEffect(fragmentViewModel) { + connectWebsocket() + onStopOrDispose { disconnectWebsocket() } } if (chatRoomList != null) { 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 dd731748c..cf8912d54 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 @@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel @@ -71,7 +72,17 @@ class WorkerChattingViewModel @Inject constructor( } } - internal suspend fun subscribeChatMessage() { + internal fun connectWebsocket() = viewModelScope.launch { + chatRepository.connectWebSocket().onSuccess { + subscribeChatMessage() + } + } + + internal fun disconnectWebsocket() = viewModelScope.launch { + chatRepository.disconnectWebSocket() + } + + private suspend fun subscribeChatMessage() { chatRepository.subscribeChatMessage(_myProfile.value?.workerId ?: return) .collect { message -> when (message) { diff --git a/presentation/src/main/java/com/idle/presentation/MainActivity.kt b/presentation/src/main/java/com/idle/presentation/MainActivity.kt index e88f33094..98c954c15 100644 --- a/presentation/src/main/java/com/idle/presentation/MainActivity.kt +++ b/presentation/src/main/java/com/idle/presentation/MainActivity.kt @@ -129,18 +129,6 @@ class MainActivity : AppCompatActivity() { } } - override fun onStart() { - super.onStart() - if (networkMonitor.networkState.value != NetworkState.NotConnected) { - viewModel.connectWebSocket() - } - } - - override fun onStop() { - super.onStop() - viewModel.disconnectWebSocket() - } - override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) diff --git a/presentation/src/main/java/com/idle/presentation/MainViewModel.kt b/presentation/src/main/java/com/idle/presentation/MainViewModel.kt index 55a5fd581..0cc527337 100644 --- a/presentation/src/main/java/com/idle/presentation/MainViewModel.kt +++ b/presentation/src/main/java/com/idle/presentation/MainViewModel.kt @@ -12,7 +12,6 @@ import com.idle.domain.model.error.ErrorHelper import com.idle.domain.model.error.HttpResponseException import com.idle.domain.model.jobposting.SharedJobPostingInfo import com.idle.domain.model.profile.CenterManagerAccountStatus -import com.idle.domain.repositorry.ChatRepository import com.idle.domain.repositorry.ConfigRepository import com.idle.domain.repositorry.JobPostingRepository import com.idle.domain.repositorry.NotificationRepository @@ -41,7 +40,6 @@ class MainViewModel @Inject constructor( private val profileRepository: ProfileRepository, private val notificationRepository: NotificationRepository, private val jobPostingRepository: JobPostingRepository, - private val chatRepository: ChatRepository, private val errorHelper: ErrorHelper, internal val eventHelper: EventHelper, internal val navigationHelper: NavigationHelper, @@ -56,20 +54,6 @@ class MainViewModel @Inject constructor( handleError() } - internal fun connectWebSocket() = viewModelScope.launch { - val (accessToken, userRole) = getAccessTokenAndUserRole() - - if (accessToken.isBlank() || userRole.isBlank()) { - return@launch - } - - chatRepository.connectWebSocket() - } - - internal fun disconnectWebSocket() = viewModelScope.launch { - chatRepository.connectWebSocket() - } - internal fun setNavigationMenuType(navigationMenuType: NavigationMenuType) { _navigationMenuType.value = navigationMenuType } @@ -113,7 +97,12 @@ class MainViewModel @Inject constructor( private suspend fun navigateToDestination(userRole: String) { when (userRole) { - UserType.WORKER.apiValue -> navigationHelper.navigateTo(NavigationEvent.To(WorkerHome, R.id.authFragment)) + UserType.WORKER.apiValue -> navigationHelper.navigateTo( + NavigationEvent.To( + WorkerHome, + R.id.authFragment + ) + ) UserType.CENTER.apiValue -> getCenterStatus() else -> Unit @@ -163,8 +152,6 @@ class MainViewModel @Inject constructor( ApiErrorCode.TokenExpiredException, ApiErrorCode.TokenNotFound, ApiErrorCode.NotSupportUserTokenType -> { - disconnectWebSocket() - navigationHelper.navigateTo( NavigationEvent.ToAuthWithClearBackStack( exception.print()