Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 61 additions & 67 deletions core/data/src/main/java/com/idle/data/repository/ChatRepositoryImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -79,59 +79,52 @@ class ChatRepositoryImpl @Inject constructor(
roomId: String,
myId: String,
messageId: String?,
unReadMessageCount: Int?,
): Result<List<ChatMessage>> = runCatching {
if (messageId == null ||
!localChatDataSource.isMessageExist(roomId, myId, messageId)
) {
// 웹소켓으로 얻지 못한 메세지가 있을경우 정합성을 위해 서버에서 호출
when (userType) {
UserType.WORKER -> chatDataSource.getWorkerChatRoomMessages(
roomId = roomId,
messageId = messageId,
)
if (messageId == null || !localChatDataSource.isMessageExist(roomId, myId, messageId)) {
val response = when (userType) {
UserType.WORKER -> chatDataSource.getWorkerChatRoomMessages(roomId, messageId)
UserType.CENTER -> chatDataSource.getCenterChatRoomMessages(roomId, messageId)
}.getOrThrow()

UserType.CENTER -> chatDataSource.getCenterChatRoomMessages(
roomId = roomId,
messageId = messageId,
)
}.mapCatching { response ->
val messages = response.chatMessageInfos
val readSequence = response.sequence
val allMessages = response.chatMessageInfos
.sortedBy { it.sequence }
.map { it.toVO() }

val messagesToUse = unReadMessageCount?.let {
allMessages.takeLast(it)
} ?: allMessages

val maxSeq = localChatDataSource.getMaxLocalSequence(roomId, myId) ?: Int.MIN_VALUE

messages.lastOrNull()?.let {
localChatDataSource.readMessages(
roomId = roomId,
messagesToUse.forEach { message ->
if (!localChatDataSource.isChatRoomExist(message.roomId, myId)) {
localChatDataSource.insertChatRoom(
myId = myId,
senderId = it.senderId ?: return@let,
sequence = readSequence,
chatRoom = ChatRoom(
id = message.roomId,
opponentId = if (myId == message.senderId) message.receiverId else message.senderId,
lastMessage = message.content,
lastMessageTime = message.createdAt,
unReadMessageCount = 1,
)
)
}

messages
.sortedBy { it.sequence }
.map {
val message = it.toVO()

if (!localChatDataSource.isChatRoomExist(message.roomId, myId)) {
localChatDataSource.insertChatRoom(
myId = myId,
chatRoom = ChatRoom(
id = message.roomId,
opponentId = if (myId == message.senderId) message.receiverId else message.senderId,
lastMessage = message.content,
lastMessageTime = message.createdAt,
unReadMessageCount = 1,
)
)
}
if (message.sequence > maxSeq) {
localChatDataSource.insertMessage(message, myId)
}
}

val maxSeq =
localChatDataSource.getMaxLocalSequence(roomId, myId) ?: Int.MIN_VALUE
if (message.sequence > maxSeq) {
localChatDataSource.insertMessage(message, myId)
}
}
}.getOrThrow()
val readSequence = response.sequence
allMessages.lastOrNull()?.let {
localChatDataSource.readMessages(
roomId = roomId,
myId = myId,
senderId = it.senderId,
sequence = readSequence,
)
}
}

return@runCatching localChatDataSource.getMessages(
Expand Down Expand Up @@ -182,12 +175,14 @@ class ChatRepositoryImpl @Inject constructor(
}

is ReadMessage -> {
localChatDataSource.readMessages(
roomId = message.chatroomId,
myId = userId,
senderId = message.opponentId,
sequence = message.sequence,
)
if (message.opponentId != userId) {
localChatDataSource.readMessages(
roomId = message.chatroomId,
myId = userId,
senderId = message.opponentId,
sequence = message.sequence,
)
}
}
}

Expand Down Expand Up @@ -225,20 +220,19 @@ class ChatRepositoryImpl @Inject constructor(
opponentId: String,
userType: UserType,
sequence: Int,
): Result<Unit> =
chatDataSource.readMessage(
userType = userType,
readMessageRequest = ReadMessageRequest(
chatroomId = chatroomId,
opponentId = opponentId,
sequence = sequence,
)
).onSuccess {
localChatDataSource.readMessages(
roomId = chatroomId,
myId = myId,
senderId = opponentId,
sequence = sequence,
)
}
): Result<Unit> = chatDataSource.readMessage(
userType = userType,
readMessageRequest = ReadMessageRequest(
chatroomId = chatroomId,
opponentId = opponentId,
sequence = sequence,
)
).onSuccess {
localChatDataSource.readMessages(
roomId = chatroomId,
myId = myId,
senderId = opponentId,
sequence = sequence,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ class LocalChatDataSource @Inject constructor(
roomId: String,
myId: String,
lastMessageId: String?
): List<ChatMessage> =
messagesDao.getMessages(
roomId = roomId,
myId = myId,
lastMessageId = lastMessageId,
).map(MessageEntity::toDomain).reversed()
): List<ChatMessage> = messagesDao.getMessages(
roomId = roomId,
myId = myId,
lastMessageId = lastMessageId,
).map(MessageEntity::toDomain).reversed()

suspend fun readMessages(
roomId: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface ChatRepository {
roomId: String,
myId: String,
messageId: String?,
unReadMessageCount: Int?,
): Result<List<ChatMessage>>

suspend fun generateChatRooms(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ sealed class DeepLinkDestination(
val myUserType: String,
val opponentId: String,
val fromJobPosting: Boolean,
val unReadMessageCount: Int
) : DeepLinkDestination(
addressRes = R.string.chatting_detail_deeplink_url,
params = mapOf(
Expand All @@ -57,6 +58,7 @@ sealed class DeepLinkDestination(
"myUserType" to myUserType,
"opponentId" to opponentId,
"fromJobPosting" to fromJobPosting,
"unReadMessageCount" to unReadMessageCount,
)
)

Expand Down
2 changes: 1 addition & 1 deletion core/navigation/src/main/res/values/deeplinks.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<string name="withdrawal_deeplink_url">care://withdrawal/{userType}</string>
<string name="signup_complete_deeplink_url">care://signup/complete</string>
<string name="new_password_deeplink_url">care://newPassword</string>
<string name="chatting_detail_deeplink_url">care://chatting/detail/{chattingRoomId}/{myId}/{myUserType}/{opponentId}/{fromJobPosting}</string>
<string name="chatting_detail_deeplink_url">care://chatting/detail/{chattingRoomId}/{myId}/{myUserType}/{opponentId}/{fromJobPosting}/{unReadMessageCount}</string>
<string name="chatting_see_all_chat_deeplink_url">care://chatting/seeallchat/{allChatContents}</string>

<string name="worker_signup_deeplink_url">care://signup/worker</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import com.idle.network.util.safeApiCall
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.serialization.json.Json
import okio.IOException
import org.hildan.krossbow.stomp.config.StompConfig
Expand Down Expand Up @@ -106,9 +105,7 @@ class ChatDataSource @Inject constructor(
session?.subscribe(
StompSubscribeHeaders(destination = "/sub/${userId}"),
chatResponseSerializer,
)?.map {
it
} ?: flow { throw IOException("웹소켓을 먼저 연결해주세요.") }
) ?: flow { throw IOException("웹소켓을 먼저 연결해주세요.") }

suspend fun sendMessage(
userType: UserType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ internal fun ChatRoomItem(
myId = myProfile!!.centerId,
opponentId = chatRoom.opponentId,
myUserType = UserType.CENTER.apiValue,
unReadMessageCount = chatRoom.unReadMessageCount,
fromJobPosting = false,
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,12 @@ class CenterChattingViewModel @Inject constructor(
chatRepository.subscribeChatMessage(
userId = _myProfile.value?.centerId ?: return@launch,
userType = UserType.CENTER,
)
.collect { message ->
when (message) {
is ChatMessage -> handleChatMessage(message)
is ReadMessage -> Unit
}
).collect { message ->
when (message) {
is ChatMessage -> handleChatMessage(message)
is ReadMessage -> Unit
}
}
}

private suspend fun handleChatMessage(message: ChatMessage) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ class ChattingDetailViewModel @Inject constructor(
private val opponentId: String = requireNotNull(savedStateHandle["opponentId"]) {
"opponentId is missing in savedStateHandle"
}
val myUserType: UserType =
UserType.create(
requireNotNull(savedStateHandle["myUserType"]) { "myUserType is missing" }
)
val myUserType: UserType = UserType.create(
requireNotNull(savedStateHandle["myUserType"]) { "myUserType is missing" }
)
val myId: String = requireNotNull(savedStateHandle["myId"]) {
"myId is missing in savedStateHandle"
}
private var unReadMessageCount: Int = requireNotNull(savedStateHandle["unReadMessageCount"]) {
"unReadMessageCount is missing in savedStateHandle"
}
private val fromJobPosting: Boolean = requireNotNull(savedStateHandle["fromJobPosting"]) {
"fromJobPosting is missing in savedStateHandle"
}
Expand Down Expand Up @@ -124,8 +126,10 @@ class ChattingDetailViewModel @Inject constructor(
messageId = _chatMessages.value?.first()?.id,
userType = myUserType,
myId = myId,
unReadMessageCount = if (unReadMessageCount >= 0) unReadMessageCount else null,
).onSuccess { messages ->
if (messages.isEmpty()) _callType.value = MessageCallType.END
unReadMessageCount -= messages.size

_chatMessages.value = messages.plus(_chatMessages.value ?: emptyList())
}.onFailure {
Expand All @@ -151,8 +155,8 @@ class ChattingDetailViewModel @Inject constructor(
}.collect { message ->
when (message) {
is ChatMessage -> {
if (message.senderId != myId) readMessage()

if (message.senderId == myId) readMessage()
readMessage()
_chatMessages.value = (_chatMessages.value ?: emptyList()) + message
}

Expand Down Expand Up @@ -182,12 +186,14 @@ class ChattingDetailViewModel @Inject constructor(
}

internal suspend fun readMessage() {
val lastOpponentMessageSequence = _chatMessages.value?.lastOrNull()?.sequence ?: return

chatRepository.readMessage(
chatroomId = chatroomId,
myId = myId,
opponentId = opponentId,
userType = myUserType,
sequence = _chatMessages.value?.lastOrNull()?.sequence ?: return
sequence = lastOpponentMessageSequence
).onSuccess {
_chatMessages.value = _chatMessages.value?.map {
if (it.receiverId == myId) it.copy(isRead = true) else it
Expand Down
Loading