Второй этап выхода из офлайн режима
This commit is contained in:
@@ -45,7 +45,8 @@ enum class ConnectionStatus { CONNECTED, CONNECTING, DISCONNECTED }
|
||||
@Singleton
|
||||
class ChatHubClient @Inject constructor() {
|
||||
private var hubConnection: HubConnection? = null
|
||||
private val _events = MutableSharedFlow<ChatEvent>(extraBufferCapacity = 1024)
|
||||
// extraBufferCapacity=1024 позволяет буферизовать события пока нет подписчиков
|
||||
private val _events = MutableSharedFlow<ChatEvent>(replay = 0, extraBufferCapacity = 1024)
|
||||
val events: SharedFlow<ChatEvent> = _events.asSharedFlow()
|
||||
|
||||
private val _status = MutableStateFlow(ConnectionStatus.DISCONNECTED)
|
||||
@@ -56,32 +57,59 @@ class ChatHubClient @Inject constructor() {
|
||||
private var lastToken: String? = null
|
||||
|
||||
fun connect(baseUrl: String, accessToken: String) {
|
||||
if (hubConnection?.connectionState == HubConnectionState.CONNECTED) return
|
||||
// Проверяем текущее состояние
|
||||
val currentState = hubConnection?.connectionState
|
||||
if (currentState == HubConnectionState.CONNECTED) {
|
||||
Log.d("ChatHubClient", "Already connected, skipping")
|
||||
return
|
||||
}
|
||||
|
||||
// Если соединение в процессе - останавливаем его
|
||||
if (currentState == HubConnectionState.CONNECTING) {
|
||||
Log.d("ChatHubClient", "Connection in progress ($currentState), stopping first...")
|
||||
hubConnection?.stop()
|
||||
}
|
||||
|
||||
// Сохраняем параметры для переподключения
|
||||
lastBaseUrl = baseUrl
|
||||
lastToken = accessToken
|
||||
_status.value = ConnectionStatus.CONNECTING
|
||||
|
||||
hubConnection = HubConnectionBuilder.create("${baseUrl}/hubs/chat")
|
||||
Log.d("ChatHubClient", "Connecting to ${baseUrl}/hubs/chat with token: ${accessToken.take(10)}...")
|
||||
|
||||
// Создаем новое соединение
|
||||
val newHubConnection = HubConnectionBuilder.create("${baseUrl}/hubs/chat")
|
||||
.withAccessTokenProvider(Single.just(accessToken))
|
||||
.build()
|
||||
|
||||
hubConnection = newHubConnection
|
||||
|
||||
setupHandlers()
|
||||
|
||||
hubConnection?.onClosed { exception ->
|
||||
Log.e("ChatHubClient", "Connection closed. Reconnecting...", exception)
|
||||
_status.value = ConnectionStatus.DISCONNECTED
|
||||
scope.launch {
|
||||
delay(5000)
|
||||
connect(baseUrl, accessToken)
|
||||
// Проверяем, есть ли еще актуальные параметры для переподключения
|
||||
val reconnectBaseUrl = lastBaseUrl
|
||||
val reconnectToken = lastToken
|
||||
|
||||
if (reconnectBaseUrl != null && reconnectToken != null) {
|
||||
Log.d("ChatHubClient", "Attempting reconnection with saved parameters...")
|
||||
delay(5000)
|
||||
connect(reconnectBaseUrl, reconnectToken)
|
||||
} else {
|
||||
Log.w("ChatHubClient", "Cannot reconnect: missing baseUrl or token")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
try {
|
||||
Log.d("ChatHubClient", "Starting SignalR connection...")
|
||||
hubConnection?.start()?.blockingAwait()
|
||||
_status.value = ConnectionStatus.CONNECTED
|
||||
Log.d("ChatHubClient", "SignalR Connected")
|
||||
Log.d("ChatHubClient", "SignalR Connected successfully!")
|
||||
} catch (e: Exception) {
|
||||
Log.e("ChatHubClient", "SignalR Connection Error", e)
|
||||
_status.value = ConnectionStatus.DISCONNECTED
|
||||
@@ -91,19 +119,25 @@ class ChatHubClient @Inject constructor() {
|
||||
|
||||
private fun setupHandlers() {
|
||||
hubConnection?.let { conn ->
|
||||
Log.d("ChatHubClient", "Setting up SignalR handlers")
|
||||
|
||||
conn.on("new_message", { message: MessageDto ->
|
||||
Log.d("ChatHubClient", ">>> new_message event received: ${message.id} in chat ${message.chatId}")
|
||||
_events.tryEmit(ChatEvent.NewMessage(message))
|
||||
}, MessageDto::class.java)
|
||||
|
||||
conn.on("message_edited", { messageId: String, chatId: String, content: String ->
|
||||
Log.d("ChatHubClient", ">>> message_edited event: $messageId")
|
||||
_events.tryEmit(ChatEvent.MessageEdited(messageId, chatId, content))
|
||||
}, String::class.java, String::class.java, String::class.java)
|
||||
|
||||
conn.on("message_deleted", { messageId: String, chatId: String ->
|
||||
Log.d("ChatHubClient", ">>> message_deleted event: $messageId")
|
||||
_events.tryEmit(ChatEvent.MessageDeleted(messageId, chatId))
|
||||
}, String::class.java, String::class.java)
|
||||
|
||||
conn.on("messages_read", { data: MessagesReadEvent ->
|
||||
Log.d("ChatHubClient", ">>> messages_read event: ${data.effectiveChatId}")
|
||||
_events.tryEmit(ChatEvent.MessagesRead(
|
||||
data.effectiveChatId,
|
||||
data.effectiveUserId,
|
||||
@@ -124,10 +158,12 @@ class ChatHubClient @Inject constructor() {
|
||||
}, String::class.java)
|
||||
|
||||
conn.on("new_chat", { chat: ChatDto ->
|
||||
Log.d("ChatHubClient", ">>> new_chat event: ${chat.id}")
|
||||
_events.tryEmit(ChatEvent.NewChat(chat))
|
||||
}, ChatDto::class.java)
|
||||
|
||||
conn.on("reaction_added", { data: ReactionEvent ->
|
||||
Log.d("ChatHubClient", ">>> reaction_added event: ${data.emoji} on ${data.messageId}")
|
||||
_events.tryEmit(ChatEvent.ReactionUpdated(
|
||||
data.messageId ?: "",
|
||||
data.chatId ?: "",
|
||||
@@ -138,6 +174,7 @@ class ChatHubClient @Inject constructor() {
|
||||
}, ReactionEvent::class.java)
|
||||
|
||||
conn.on("reaction_removed", { data: ReactionEvent ->
|
||||
Log.d("ChatHubClient", ">>> reaction_removed event: ${data.emoji} on ${data.messageId}")
|
||||
_events.tryEmit(ChatEvent.ReactionUpdated(
|
||||
data.messageId ?: "",
|
||||
data.chatId ?: "",
|
||||
@@ -185,6 +222,26 @@ class ChatHubClient @Inject constructor() {
|
||||
_status.value = ConnectionStatus.DISCONNECTED
|
||||
}
|
||||
|
||||
/**
|
||||
* Принудительное переподключение - останавливает текущее соединение и создает новое
|
||||
*/
|
||||
fun reconnect() {
|
||||
Log.d("ChatHubClient", "Forced reconnect requested")
|
||||
val baseUrl = lastBaseUrl
|
||||
val token = lastToken
|
||||
|
||||
if (baseUrl != null && token != null) {
|
||||
disconnect()
|
||||
// Небольшая задержка перед переподключением
|
||||
scope.launch {
|
||||
delay(1000)
|
||||
connect(baseUrl, token)
|
||||
}
|
||||
} else {
|
||||
Log.w("ChatHubClient", "Cannot reconnect: missing saved credentials")
|
||||
}
|
||||
}
|
||||
|
||||
fun addReaction(messageId: String, chatId: String, emoji: String) {
|
||||
if (hubConnection?.connectionState == HubConnectionState.CONNECTED) {
|
||||
hubConnection?.invoke("add_reaction", mapOf(
|
||||
@@ -250,12 +307,13 @@ class ChatHubClient @Inject constructor() {
|
||||
}
|
||||
|
||||
if (hubConnection?.connectionState == HubConnectionState.CONNECTED) {
|
||||
Log.d("ChatHubClient", "Joining chat room: $chatId")
|
||||
hubConnection?.invoke("join_chat", chatId)
|
||||
?.doOnError { Log.e("ChatHubClient", "join_chat error", it) }
|
||||
?.subscribe()
|
||||
Log.d("ChatHubClient", "Joined chat room: $chatId")
|
||||
} else {
|
||||
Log.e("ChatHubClient", "Failed to join chat room $chatId: Not connected")
|
||||
Log.e("ChatHubClient", "Failed to join chat room $chatId: Not connected (state=${hubConnection?.connectionState})")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user