fix: soften realtime connection status in chat subtitle
Some checks failed
Android CI / android (push) Failing after 4m40s
Android Release / release (push) Failing after 5m1s
CI / test (push) Failing after 2m35s

- show Connecting immediately when opening realtime

- delay Reconnecting subtitle updates to avoid noisy transient states

- keep normal chat presence text during short reconnects
This commit is contained in:
2026-04-06 00:07:13 +03:00
parent 4a28d3d495
commit 662d624452

View File

@@ -93,6 +93,8 @@ class ChatViewModel @Inject constructor(
private var membersLoadKey: String? = null
private var privateChatRelationKey: Long? = null
private var typingResetJob: Job? = null
private var reconnectSubtitleJob: Job? = null
private var latestRealtimeConnectionState: RealtimeConnectionState = RealtimeConnectionState.Disconnected
init {
activeChatTracker.setActiveChat(chatId)
@@ -918,17 +920,63 @@ class ChatViewModel @Inject constructor(
private fun observeRealtimeState() {
viewModelScope.launch {
realtimeManager.connectionState.collectLatest { connectionState ->
_uiState.update {
val isConnecting = connectionState == RealtimeConnectionState.Connecting ||
connectionState == RealtimeConnectionState.Reconnecting
it.copy(
isRealtimeConnecting = isConnecting,
chatSubtitle = resolveDisplayedSubtitle(
baseSubtitle = it.baseChatSubtitle,
isRealtimeConnecting = isConnecting,
isTyping = it.isTyping,
),
)
latestRealtimeConnectionState = connectionState
reconnectSubtitleJob?.cancel()
when (connectionState) {
RealtimeConnectionState.Connecting -> {
_uiState.update {
it.copy(
isRealtimeConnecting = true,
chatSubtitle = resolveDisplayedSubtitle(
baseSubtitle = it.baseChatSubtitle,
isRealtimeConnecting = true,
isTyping = it.isTyping,
),
)
}
}
RealtimeConnectionState.Reconnecting -> {
_uiState.update {
it.copy(
isRealtimeConnecting = false,
chatSubtitle = resolveDisplayedSubtitle(
baseSubtitle = it.baseChatSubtitle,
isRealtimeConnecting = false,
isTyping = it.isTyping,
),
)
}
reconnectSubtitleJob = viewModelScope.launch {
delay(RECONNECT_SUBTITLE_DELAY_MS)
if (latestRealtimeConnectionState != RealtimeConnectionState.Reconnecting) return@launch
_uiState.update {
it.copy(
isRealtimeConnecting = true,
chatSubtitle = resolveDisplayedSubtitle(
baseSubtitle = it.baseChatSubtitle,
isRealtimeConnecting = true,
isTyping = it.isTyping,
),
)
}
}
}
RealtimeConnectionState.Connected,
RealtimeConnectionState.Disconnected,
-> {
_uiState.update {
it.copy(
isRealtimeConnecting = false,
chatSubtitle = resolveDisplayedSubtitle(
baseSubtitle = it.baseChatSubtitle,
isRealtimeConnecting = false,
isTyping = it.isTyping,
),
)
}
}
}
}
}
@@ -1232,6 +1280,8 @@ class ChatViewModel @Inject constructor(
}
override fun onCleared() {
typingResetJob?.cancel()
reconnectSubtitleJob?.cancel()
activeChatTracker.clearActiveChat(chatId)
super.onCleared()
}
@@ -1239,5 +1289,6 @@ class ChatViewModel @Inject constructor(
private companion object {
const val MESSAGES_PAGE_SIZE = 50
const val MIN_VOICE_DURATION_MS = 1_000L
const val RECONNECT_SUBTITLE_DELAY_MS = 2_500L
}
}