package chats.data.remote.signalr import android.content.Context import core.notifications.data.ActiveChatTracker import core.notifications.data.NotificationHelper import core.security.TokenManager import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import javax.inject.Inject import javax.inject.Singleton @Singleton class SignalRNotificationObserver @Inject constructor( private val signalrClient: ChatHubClient, private val activeChatTracker: ActiveChatTracker, private val tokenManager: TokenManager, private val chatRepository: chats.domain.repository.ChatRepository, @ApplicationContext private val context: Context ) { private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main) private var isStarted = false private val processedMessageIds = mutableSetOf() fun refresh() { scope.launch { try { val chats = chatRepository.getChats() val total = chats.sumOf { it.unreadCount } activeChatTracker.setTotalUnreadCount(total) } catch (e: Exception) { // Ignore load error } } } fun start() { if (isStarted) return isStarted = true // Initial count load refresh() signalrClient.events .onEach { event -> when (event) { is ChatEvent.NewMessage -> { val currentUserId = tokenManager.getUserId() val message = event.message // Don't show if it's our message or already processed if (message.senderId == currentUserId) return@onEach if (processedMessageIds.contains(message.id)) return@onEach // Mark as processed processedMessageIds.add(message.id) if (processedMessageIds.size > 200) { processedMessageIds.remove(processedMessageIds.first()) } // Increment immediately for UI feedback activeChatTracker.incrementUnreadCount() // Refresh total count from source of truth in background refresh() // Don't show if this chat is currently open if (activeChatTracker.currentChatId.value == message.chatId) return@onEach NotificationHelper.showNotification( context = context, title = message.sender?.displayName ?: "Новое сообщение", body = message.content ?: "Вам прислали вложение", type = "chat", chatId = message.chatId, notificationId = message.id.hashCode(), totalCount = activeChatTracker.totalUnreadCount.value ) } is ChatEvent.MessagesRead -> { // If anyone read messages, sync our total count refresh() } else -> Unit } } .launchIn(scope) } }