diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/CharacterInfo.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/CharacterInfo.kt similarity index 91% rename from app/src/main/java/kr/co/vividnext/sodalive/chat/room/CharacterInfo.kt rename to app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/CharacterInfo.kt index 68101998..7f08bb8a 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/CharacterInfo.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/CharacterInfo.kt @@ -1,7 +1,7 @@ /* * 보이스온 - 채팅방 캐릭터 정보 모델 */ -package kr.co.vividnext.sodalive.chat.room +package kr.co.vividnext.sodalive.chat.talk.room import androidx.annotation.Keep import com.google.gson.annotations.SerializedName diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatMessage.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessage.kt similarity index 95% rename from app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatMessage.kt rename to app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessage.kt index 2f6d1416..23cca8d1 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatMessage.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessage.kt @@ -1,7 +1,7 @@ /* * 보이스온 - 채팅 메시지 모델 (서버 응답 기반) */ -package kr.co.vividnext.sodalive.chat.room +package kr.co.vividnext.sodalive.chat.talk.room import androidx.annotation.Keep import com.google.gson.annotations.SerializedName diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatMessageMappers.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessageMappers.kt similarity index 91% rename from app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatMessageMappers.kt rename to app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessageMappers.kt index 9f4ea163..75938a98 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatMessageMappers.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessageMappers.kt @@ -1,7 +1,7 @@ /* * 보이스온 - 채팅 메시지 매핑 유틸리티 */ -package kr.co.vividnext.sodalive.chat.room +package kr.co.vividnext.sodalive.chat.talk.room import androidx.annotation.Keep diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatMessagesResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessagesResponse.kt similarity index 88% rename from app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatMessagesResponse.kt rename to app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessagesResponse.kt index 2e7cd6cd..556e6adc 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatMessagesResponse.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatMessagesResponse.kt @@ -1,7 +1,7 @@ /* * 보이스온 - 점진적 메시지 로딩 응답 모델 */ -package kr.co.vividnext.sodalive.chat.room +package kr.co.vividnext.sodalive.chat.talk.room import androidx.annotation.Keep import com.google.gson.annotations.SerializedName diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatRoomEnterResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomEnterResponse.kt similarity index 90% rename from app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatRoomEnterResponse.kt rename to app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomEnterResponse.kt index bc17a19e..b378e244 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/ChatRoomEnterResponse.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomEnterResponse.kt @@ -1,7 +1,7 @@ /* * 보이스온 - 통합 채팅방 입장 응답 모델 */ -package kr.co.vividnext.sodalive.chat.room +package kr.co.vividnext.sodalive.chat.talk.room import androidx.annotation.Keep import com.google.gson.annotations.SerializedName diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatTalkRoomModule.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatTalkRoomModule.kt new file mode 100644 index 00000000..3c6e9bb4 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatTalkRoomModule.kt @@ -0,0 +1,13 @@ +package kr.co.vividnext.sodalive.chat.talk.room + +import kr.co.vividnext.sodalive.chat.talk.room.db.ChatMessageDatabase +import org.koin.android.ext.koin.androidContext +import org.koin.dsl.module + +val chatTalkRoomModule = module { + // Database + single { ChatMessageDatabase.getDatabase(androidContext()) } + + // DAO + single { get().chatMessageDao() } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/MessageStatus.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/MessageStatus.kt similarity index 85% rename from app/src/main/java/kr/co/vividnext/sodalive/chat/room/MessageStatus.kt rename to app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/MessageStatus.kt index 63167f64..a2134426 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/MessageStatus.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/MessageStatus.kt @@ -1,7 +1,7 @@ /* * 보이스온 - 채팅방 메시지 전송 상태 Enum */ -package kr.co.vividnext.sodalive.chat.room +package kr.co.vividnext.sodalive.chat.talk.room import androidx.annotation.Keep diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/MessageType.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/MessageType.kt similarity index 84% rename from app/src/main/java/kr/co/vividnext/sodalive/chat/room/MessageType.kt rename to app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/MessageType.kt index e82e0ab0..042b1cc4 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/MessageType.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/MessageType.kt @@ -1,7 +1,7 @@ /* * 보이스온 - 채팅방 메시지 타입 Enum */ -package kr.co.vividnext.sodalive.chat.room +package kr.co.vividnext.sodalive.chat.talk.room import androidx.annotation.Keep diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/ServerChatMessage.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ServerChatMessage.kt similarity index 92% rename from app/src/main/java/kr/co/vividnext/sodalive/chat/room/ServerChatMessage.kt rename to app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ServerChatMessage.kt index 0520dfe2..04cac086 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/chat/room/ServerChatMessage.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ServerChatMessage.kt @@ -1,7 +1,7 @@ /* * 보이스온 - 채팅 메시지 모델 (서버 응답 전용 DTO) */ -package kr.co.vividnext.sodalive.chat.room +package kr.co.vividnext.sodalive.chat.talk.room import androidx.annotation.Keep import com.google.gson.annotations.SerializedName diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageConverters.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageConverters.kt new file mode 100644 index 00000000..73b7c875 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageConverters.kt @@ -0,0 +1,17 @@ +/* + * 보이스온 - 채팅 메시지 Room TypeConverters + */ +package kr.co.vividnext.sodalive.chat.talk.room.db + +import androidx.room.TypeConverter +import kr.co.vividnext.sodalive.chat.talk.room.MessageStatus + +object ChatMessageConverters { + @TypeConverter + @JvmStatic + fun fromStatus(value: MessageStatus?): String? = value?.name + + @TypeConverter + @JvmStatic + fun toStatus(value: String?): MessageStatus? = value?.let { MessageStatus.valueOf(it) } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageDao.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageDao.kt new file mode 100644 index 00000000..54267951 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageDao.kt @@ -0,0 +1,32 @@ +/* + * 보이스온 - 채팅 메시지 DAO + */ +package kr.co.vividnext.sodalive.chat.talk.room.db + +import androidx.annotation.Keep +import androidx.room.* + +@Keep +@Dao +interface ChatMessageDao { + @Query("SELECT * FROM chat_messages WHERE roomId = :roomId ORDER BY createdAt DESC LIMIT 20") + suspend fun getRecentMessages(roomId: Long): List + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertMessage(message: ChatMessageEntity) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertMessages(messages: List) + + @Update + suspend fun updateMessage(message: ChatMessageEntity) + + @Query("DELETE FROM chat_messages WHERE roomId = :roomId AND createdAt < :cutoffTime") + suspend fun deleteOldMessages(roomId: Long, cutoffTime: Long) + + @Query("DELETE FROM chat_messages") + suspend fun deleteAllMessages() + + @Query("SELECT DISTINCT roomId FROM chat_messages") + suspend fun getAllRoomIds(): List +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageDatabase.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageDatabase.kt new file mode 100644 index 00000000..032ba301 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageDatabase.kt @@ -0,0 +1,37 @@ +/* + * 보이스온 - 채팅방 Room Database (ChatMessage 테이블 포함) + */ +package kr.co.vividnext.sodalive.chat.talk.room.db + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase +import androidx.room.TypeConverters + +@Database( + entities = [ChatMessageEntity::class], + version = 1, + exportSchema = false +) +@TypeConverters(ChatMessageConverters::class) +abstract class ChatMessageDatabase : RoomDatabase() { + abstract fun chatMessageDao(): ChatMessageDao + + companion object { + @Volatile + private var INSTANCE: ChatMessageDatabase? = null + + fun getDatabase(context: Context): ChatMessageDatabase { + return INSTANCE ?: synchronized(this) { + val instance = Room.databaseBuilder( + context.applicationContext, + ChatMessageDatabase::class.java, + "chat_database" + ).build() + INSTANCE = instance + instance + } + } + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageEntity.kt b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageEntity.kt new file mode 100644 index 00000000..705bed8a --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/db/ChatMessageEntity.kt @@ -0,0 +1,22 @@ +/* + * 보이스온 - 채팅 메시지 Room Entity + */ +package kr.co.vividnext.sodalive.chat.talk.room.db + +import androidx.annotation.Keep +import androidx.room.Entity +import androidx.room.PrimaryKey +import kr.co.vividnext.sodalive.chat.talk.room.MessageStatus + +@Keep +@Entity(tableName = "chat_messages") +data class ChatMessageEntity( + @PrimaryKey val messageId: Long, + val roomId: Long, + val message: String, + val profileImageUrl: String, + val mine: Boolean, + val createdAt: Long, + val status: MessageStatus = MessageStatus.SENT, + val localId: String? = null +) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt b/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt index 632af85c..0e95a4e3 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt @@ -146,6 +146,7 @@ import kr.co.vividnext.sodalive.mypage.profile.tag.MemberTagApi import kr.co.vividnext.sodalive.mypage.profile.tag.MemberTagRepository import kr.co.vividnext.sodalive.mypage.profile.tag.MemberTagViewModel import kr.co.vividnext.sodalive.mypage.recent.recentContentModule +import kr.co.vividnext.sodalive.chat.talk.room.chatTalkRoomModule import kr.co.vividnext.sodalive.mypage.service_center.FaqApi import kr.co.vividnext.sodalive.mypage.service_center.FaqRepository import kr.co.vividnext.sodalive.mypage.service_center.ServiceCenterViewModel @@ -410,6 +411,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) { viewModelModule, repositoryModule, recentContentModule, + chatTalkRoomModule, otherModule )