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
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package com.idle.care.notification
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.idle.domain.model.error.ErrorHelper
import com.idle.domain.repositorry.TokenRepository
import com.idle.domain.repositorry.ProfileRepository
import com.idle.domain.repositorry.TokenRepository
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -40,10 +40,12 @@ class NotificationService : FirebaseMessagingService() {
scope.launch {
val userType = profileRepository.getMyUserType()

tokenRepository.postDeviceToken(
deviceToken = token,
userType = userType,
)
if (userType.isNotEmpty()) {
tokenRepository.postDeviceToken(
deviceToken = token,
userType = userType,
)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,22 +95,42 @@ class ChatRepositoryImpl @Inject constructor(
messageId = messageId,
)
}.mapCatching { response ->
response.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,
val messages = response.chatMessageInfos
val readSequence = response.sequence

messages.lastOrNull()?.let {
localChatDataSource.readMessages(
roomId = roomId,
myId = myId,
senderId = it.senderId ?: return@let,
sequence = readSequence,
)
}

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,
)
)
)
}

val maxSeq =
localChatDataSource.getMaxLocalSequence(roomId, myId) ?: Int.MIN_VALUE
if (message.sequence > maxSeq) {
localChatDataSource.insertMessage(message, myId)
}
}
localChatDataSource.insertMessage(message, myId)
}
}.getOrThrow()
}

Expand Down Expand Up @@ -138,6 +158,7 @@ class ChatRepositoryImpl @Inject constructor(
chatDataSource.subscribeChatMessage(userId)
.map {
val message = it.toVO()

when (message) {
is ChatMessage -> {
if (!localChatDataSource.isChatRoomExist(
Expand Down Expand Up @@ -165,9 +186,11 @@ class ChatRepositoryImpl @Inject constructor(
roomId = message.chatroomId,
myId = userId,
senderId = message.opponentId,
sequence = message.sequence,
)
}
}

message
}.retryWhen { cause, attempt ->
if (cause is IOException && attempt < MAX_RETRY_ATTEMPTS) {
Expand Down Expand Up @@ -201,18 +224,21 @@ class ChatRepositoryImpl @Inject constructor(
myId: String,
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,
)
}
}
21 changes: 16 additions & 5 deletions core/database/src/main/java/com/idle/database/dao/MessagesDao.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package com.idle.database.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Upsert
import com.idle.database.model.MessageEntity

@Dao
interface MessagesDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertMessage(messages: MessageEntity)
@Upsert
suspend fun upsertMessage(messages: MessageEntity)

@Query(
"""
Expand All @@ -25,7 +24,7 @@ interface MessagesDao {
roomId: String,
myId: String,
lastMessageId: String?,
limit: Int = 50
limit: Int = 50,
): List<MessageEntity>

@Query(
Expand All @@ -36,12 +35,14 @@ interface MessagesDao {
AND myId = :myId
AND senderId = :opponentId
AND isRead = 0
AND sequence <= :sequence
"""
)
suspend fun readMessages(
roomId: String,
myId: String,
opponentId: String,
sequence: Int,
)

@Query(
Expand All @@ -60,4 +61,14 @@ interface MessagesDao {
roomId: String,
messageId: String,
): Boolean

@Query(
"""
SELECT MAX(sequence)
FROM message
WHERE roomId = :roomId
AND myId = :myId
"""
)
suspend fun getMaxLocalSequence(roomId: String, myId: String): Int?
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,31 @@ package com.idle.database.model
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey
import com.idle.domain.model.chat.ChatMessage
import java.time.LocalDateTime

@Entity(
tableName = "message",
indices = [Index(value = ["roomId", "id"], unique = false)],
foreignKeys = arrayOf(
primaryKeys = ["myId", "id"],
indices = [Index(value = ["roomId", "sequence"])],
foreignKeys = [
ForeignKey(
entity = ChatRoomEntity::class,
parentColumns = ["id", "myId"],
childColumns = ["roomId", "myId"],
)
)
]
)
data class MessageEntity(
@PrimaryKey val id: String,
val id: String,
val roomId: String,
val myId: String,
val senderId: String,
val receiverId: String,
val content: String,
val createdAt: LocalDateTime,
val isRead: Boolean,
val sequence: Int,
) {
internal fun toDomain() = ChatMessage(
id = id,
Expand All @@ -36,6 +37,7 @@ data class MessageEntity(
content = content,
createdAt = createdAt,
isRead = isRead,
sequence = sequence,
)
}

Expand All @@ -48,4 +50,5 @@ internal fun ChatMessage.toMessageEntity(myId: String) = MessageEntity(
content = content,
createdAt = createdAt,
isRead = isRead,
sequence = sequence,
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class LocalChatDataSource @Inject constructor(
private val chatRoomsDao: ChatRoomsDao,
) {
suspend fun insertMessage(message: ChatMessage, myId: String) =
messagesDao.insertMessage(message.toMessageEntity(myId))
messagesDao.upsertMessage(message.toMessageEntity(myId))

suspend fun getMessages(
roomId: String,
Expand All @@ -32,7 +32,8 @@ class LocalChatDataSource @Inject constructor(
roomId: String,
myId: String,
senderId: String,
): Unit = messagesDao.readMessages(roomId, myId, senderId)
sequence: Int,
): Unit = messagesDao.readMessages(roomId, myId, senderId, sequence)

suspend fun isMessageExist(roomId: String, myId: String, messageId: String): Boolean =
messagesDao.isMessageExist(
Expand All @@ -41,6 +42,12 @@ class LocalChatDataSource @Inject constructor(
messageId = messageId,
)

suspend fun getMaxLocalSequence(roomId: String, myId: String): Int? =
messagesDao.getMaxLocalSequence(
roomId = roomId,
myId = myId,
)

suspend fun insertChatRoom(myId: String, chatRoom: ChatRoom) =
chatRoomsDao.insertChatRoom(
ChatRoomEntity(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.idle.domain.model.chat

import java.time.LocalDateTime

sealed class Message
sealed class Message(open val sequence: Int)

data class ChatMessage(
val id: String,
Expand All @@ -12,9 +12,11 @@ data class ChatMessage(
val content: String,
val createdAt: LocalDateTime,
val isRead: Boolean,
) : Message()
override val sequence: Int,
) : Message(sequence)

data class ReadMessage(
val opponentId: String,
val chatroomId: String,
) : Message()
override val sequence: Int,
) : Message(sequence)
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,6 @@ interface ChatRepository {
myId: String,
opponentId: String,
userType: UserType,
sequence: Int,
): Result<Unit>
}
6 changes: 3 additions & 3 deletions core/network/src/main/java/com/idle/network/api/ChatApi.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.idle.network.api

import com.idle.network.model.chat.ChatMessageResponse
import com.idle.network.model.chat.GenerateChatRoomResponse
import com.idle.network.model.chat.GetChatMessageResponse
import com.idle.network.model.chat.GetChatRoomResponse
import retrofit2.Response
import retrofit2.http.GET
Expand All @@ -26,11 +26,11 @@ interface ChatApi {
suspend fun getWorkerChatRoomMessages(
@Path("chatroom-id") chatRoomId: String,
@Query("message-id") messageId: String?,
): Response<List<ChatMessageResponse>>
): Response<GetChatMessageResponse>

@GET("api/v2/chat/center/chatrooms/{chatroom-id}/messages")
suspend fun getCenterChatRoomMessages(
@Path("chatroom-id") chatRoomId: String,
@Query("message-id") messageId: String?,
): Response<List<ChatMessageResponse>>
): Response<GetChatMessageResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ data class ChatMessageResponse(
val receiverId: String?,
val content: String?,
val createdAt: String?,
val sequence: Int?,
override val type: String = MESSAGE_TYPE,
) : ChatResponse() {
override fun toVO() = ChatMessage(
Expand All @@ -24,6 +25,7 @@ data class ChatMessageResponse(
createdAt = createdAt?.let { LocalDateTime.parse(it, DateTimeFormatter.ISO_DATE_TIME) }
?: LocalDateTime.MIN,
isRead = false,
sequence = sequence ?: -1
)
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.idle.network.model.chat

import com.idle.domain.model.chat.ChatMessage
import kotlinx.serialization.Serializable

@Serializable
data class GetChatMessageResponse(
val chatMessageInfos: List<ChatMessageResponse> = emptyList(),
val sequence: Int = 0,
) {
fun toVO(): Pair<List<ChatMessage>, Int> =
chatMessageInfos.map(ChatMessageResponse::toVO) to sequence
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import kotlinx.serialization.Serializable
data class ReadMessageRequest(
val chatroomId: String,
val opponentId: String,
val sequence: Int,
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import kotlinx.serialization.Serializable
data class ReadMessageResponse(
val readByUserId: String?,
val chatroomId: String?,
val sequence: Int?,
override val type: String = READ_TYPE,
) : ChatResponse() {
override fun toVO() = ReadMessage(
opponentId = readByUserId ?: "",
chatroomId = chatroomId ?: "",
sequence = sequence ?: -1
)
}
Loading