diff --git a/app/src/main/java/com/project200/undabang/di/RepositoryModule.kt b/app/src/main/java/com/project200/undabang/di/RepositoryModule.kt new file mode 100644 index 00000000..a1fbadac --- /dev/null +++ b/app/src/main/java/com/project200/undabang/di/RepositoryModule.kt @@ -0,0 +1,17 @@ +package com.project200.undabang.di + +import com.project200.common.utils.ChatRoomStateRepository +import com.project200.undabang.fcm.ChatRoomStateRepositoryImpl +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class RepositoryModule { + @Binds + @Singleton + abstract fun bindChatRoomStateRepository(impl: ChatRoomStateRepositoryImpl): ChatRoomStateRepository +} diff --git a/app/src/main/java/com/project200/undabang/fcm/ChatRoomStateRepositoryImpl.kt b/app/src/main/java/com/project200/undabang/fcm/ChatRoomStateRepositoryImpl.kt new file mode 100644 index 00000000..25710cdc --- /dev/null +++ b/app/src/main/java/com/project200/undabang/fcm/ChatRoomStateRepositoryImpl.kt @@ -0,0 +1,19 @@ +package com.project200.undabang.fcm + +import com.project200.common.utils.ChatRoomStateRepository +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class ChatRoomStateRepositoryImpl + @Inject + constructor() : ChatRoomStateRepository { + private val _activeChatRoomId = MutableStateFlow(null) + override val activeChatRoomId = _activeChatRoomId.asStateFlow() + + override fun setActiveChatRoomId(roomId: Long?) { + _activeChatRoomId.value = roomId + } + } diff --git a/app/src/main/java/com/project200/undabang/fcm/FcmService.kt b/app/src/main/java/com/project200/undabang/fcm/FcmService.kt index fe811ba9..664f208a 100644 --- a/app/src/main/java/com/project200/undabang/fcm/FcmService.kt +++ b/app/src/main/java/com/project200/undabang/fcm/FcmService.kt @@ -11,6 +11,7 @@ import androidx.core.net.toUri import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import com.project200.common.constants.FcmConstants.KEY_FCM_TOKEN +import com.project200.common.utils.ChatRoomStateRepository import com.project200.common.utils.EncryptedPrefs import com.project200.undabang.fcm.FcmConstant.CHAT_NOTI_CHANNEL_ID import com.project200.undabang.fcm.FcmConstant.CHAT_NOTI_CHANNEL_NAME @@ -24,6 +25,9 @@ class FcmService : FirebaseMessagingService() { @EncryptedPrefs lateinit var sharedPreferences: SharedPreferences + @Inject + lateinit var chatRoomStateRepository: ChatRoomStateRepository + /** * 새로운 FCM 토큰이 발급되거나 갱신될 때 호출됩니다. * 이 토큰은 백엔드 서버로 전송되어 특정 기기에 알림을 보내는 데 사용됩니다. @@ -62,6 +66,9 @@ class FcmService : FirebaseMessagingService() { if (chatRoomId == null || nickname == null || memberId == null) return + // 현재 활성화된 채팅방과 동일한 채팅방에서 온 알림이면 무시 + if (chatRoomId.toLong() == chatRoomStateRepository.activeChatRoomId.value) return + // 알림 식별을 위한 고유 ID val uniqueId = chatRoomId.hashCode() diff --git a/common/src/main/java/com/project200/common/utils/ChatRoomStateRepository.kt b/common/src/main/java/com/project200/common/utils/ChatRoomStateRepository.kt new file mode 100644 index 00000000..b988d0df --- /dev/null +++ b/common/src/main/java/com/project200/common/utils/ChatRoomStateRepository.kt @@ -0,0 +1,20 @@ +package com.project200.common.utils + +import kotlinx.coroutines.flow.StateFlow + +/** + * 앱 전체에서 현재 활성화된 채팅방의 상태를 관리하는 리포지토리 인터페이스 + */ +interface ChatRoomStateRepository { + /** + * 현재 활성화된 채팅방의 ID를 StateFlow 형태로 제공합니다. + * 활성화된 채팅방이 없으면 null입니다. + */ + val activeChatRoomId: StateFlow + + /** + * 현재 활성화된 채팅방의 ID를 설정합니다. + * @param roomId 채팅방에서 나갈 때는 null을 전달합니다. + */ + fun setActiveChatRoomId(roomId: Long?) +} diff --git a/feature/chatting/src/main/java/com/project200/feature/chatting/chattingRoom/ChattingRoomFragment.kt b/feature/chatting/src/main/java/com/project200/feature/chatting/chattingRoom/ChattingRoomFragment.kt index 298faefd..cb29cfbe 100644 --- a/feature/chatting/src/main/java/com/project200/feature/chatting/chattingRoom/ChattingRoomFragment.kt +++ b/feature/chatting/src/main/java/com/project200/feature/chatting/chattingRoom/ChattingRoomFragment.kt @@ -22,6 +22,7 @@ import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.google.android.material.snackbar.Snackbar +import com.project200.common.utils.ChatRoomStateRepository import com.project200.common.utils.CommonDateTimeFormatters.YYYY_MM_DD_KR import com.project200.feature.chatting.chattingRoom.adapter.ChatRVAdapter import com.project200.feature.chatting.utils.KeyboardVisibilityHelper @@ -38,6 +39,7 @@ import kotlinx.coroutines.flow.collect import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import java.time.LocalDate +import javax.inject.Inject @AndroidEntryPoint class ChattingRoomFragment : BindingFragment(R.layout.fragment_chatting_room), KeyboardControlInterface { @@ -45,6 +47,9 @@ class ChattingRoomFragment : BindingFragment(R.layo private lateinit var chatAdapter: ChatRVAdapter private val args: ChattingRoomFragmentArgs by navArgs() + @Inject + lateinit var chatRoomStateRepository: ChatRoomStateRepository + // 이전 메시지 로드 상태를 추적하는 플래그 private var isPaging = false @@ -383,6 +388,20 @@ class ChattingRoomFragment : BindingFragment(R.layo super.onDestroyView() } + override fun onResume() { + super.onResume() + // 현재 채팅방을 활성 채팅방으로 설정 + chatRoomStateRepository.setActiveChatRoomId(args.roomId) + } + + override fun onPause() { + super.onPause() + // 채팅방을 나갈 때 활성 채팅방 ID를 null로 설정 + if (chatRoomStateRepository.activeChatRoomId.value == args.roomId) { + chatRoomStateRepository.setActiveChatRoomId(null) + } + } + companion object { const val POLLING_PERIOD = 2000L }