adding connection status

This commit is contained in:
2025-07-03 20:38:49 -04:00
parent 4719344ae8
commit ccf26b80e8
6 changed files with 168 additions and 8 deletions

View File

@@ -3,6 +3,7 @@ package com.mattintech.lchat.repository
import android.content.Context
import com.mattintech.lchat.data.Message
import com.mattintech.lchat.network.WifiAwareManager
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -35,6 +36,10 @@ class ChatRepository private constructor(context: Context) {
private var messageCallback: ((String, String, String) -> Unit)? = null
private var connectionCallback: ((String, Boolean) -> Unit)? = null
private var lastActivityTime = System.currentTimeMillis()
private var connectionCheckJob: Job? = null
private val connectionTimeout = 30000L // 30 seconds
init {
wifiAwareManager.initialize()
setupWifiAwareCallbacks()
@@ -51,6 +56,19 @@ class ChatRepository private constructor(context: Context) {
isOwnMessage = false
)
addMessage(message)
// Update last activity time
lastActivityTime = System.currentTimeMillis()
// If we're receiving messages, we must be connected
if (_connectionState.value !is ConnectionState.Connected &&
_connectionState.value !is ConnectionState.Hosting) {
when (_connectionState.value) {
is ConnectionState.Hosting -> {} // Keep hosting state
else -> _connectionState.value = ConnectionState.Connected("Active")
}
}
messageCallback?.invoke(userId, userName, content)
}
}
@@ -58,11 +76,13 @@ class ChatRepository private constructor(context: Context) {
fun startHostMode(roomName: String) {
wifiAwareManager.startHostMode(roomName)
_connectionState.value = ConnectionState.Hosting(roomName)
startConnectionMonitoring()
}
fun startClientMode() {
wifiAwareManager.startClientMode()
_connectionState.value = ConnectionState.Searching
startConnectionMonitoring()
}
fun sendMessage(userId: String, userName: String, content: String) {
@@ -76,6 +96,15 @@ class ChatRepository private constructor(context: Context) {
)
addMessage(message)
wifiAwareManager.sendMessage(userId, userName, content)
// Update last activity time
lastActivityTime = System.currentTimeMillis()
// If we can send messages, update connection state if needed
if (_connectionState.value is ConnectionState.Disconnected ||
_connectionState.value is ConnectionState.Error) {
_connectionState.value = ConnectionState.Connected("Active")
}
}
private fun addMessage(message: Message) {
@@ -92,15 +121,49 @@ class ChatRepository private constructor(context: Context) {
fun setConnectionCallback(callback: (String, Boolean) -> Unit) {
connectionCallback = callback
wifiAwareManager.setConnectionCallback(callback)
wifiAwareManager.setConnectionCallback { roomName, isConnected ->
if (isConnected) {
_connectionState.value = ConnectionState.Connected(roomName)
} else {
_connectionState.value = ConnectionState.Disconnected
}
callback(roomName, isConnected)
}
}
fun stop() {
stopConnectionMonitoring()
wifiAwareManager.stop()
_connectionState.value = ConnectionState.Disconnected
_connectedUsers.value = emptyList()
}
private fun startConnectionMonitoring() {
connectionCheckJob?.cancel()
connectionCheckJob = GlobalScope.launch {
while (isActive) {
delay(5000) // Check every 5 seconds
val timeSinceLastActivity = System.currentTimeMillis() - lastActivityTime
// If no activity for 30 seconds and we think we're connected, mark as disconnected
if (timeSinceLastActivity > connectionTimeout) {
when (_connectionState.value) {
is ConnectionState.Connected,
is ConnectionState.Hosting -> {
_connectionState.value = ConnectionState.Disconnected
}
else -> {} // Keep current state
}
}
}
}
}
private fun stopConnectionMonitoring() {
connectionCheckJob?.cancel()
connectionCheckJob = null
}
sealed class ConnectionState {
object Disconnected : ConnectionState()
object Searching : ConnectionState()

View File

@@ -9,8 +9,11 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.navArgs
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.mattintech.lchat.R
import com.mattintech.lchat.databinding.FragmentChatBinding
import com.mattintech.lchat.repository.ChatRepository
import com.mattintech.lchat.ui.adapters.MessageAdapter
import com.mattintech.lchat.utils.LOG_PREFIX
import com.mattintech.lchat.viewmodel.ChatViewModel
@@ -50,6 +53,7 @@ class ChatFragment : Fragment() {
setupUI()
observeViewModel()
updateRoomInfo()
}
private fun setupUI() {
@@ -84,7 +88,7 @@ class ChatFragment : Fragment() {
lifecycleScope.launch {
viewModel.connectionState.collect { state ->
Log.d(TAG, "Connection state: $state")
// Handle connection state changes if needed
updateConnectionStatus(state)
}
}
}
@@ -97,6 +101,41 @@ class ChatFragment : Fragment() {
binding.messageInput.text?.clear()
}
private fun updateRoomInfo() {
val (roomName, _, isHost) = viewModel.getRoomInfo()
binding.roomNameText.text = if (isHost) "Hosting: $roomName" else "Room: $roomName"
}
private fun updateConnectionStatus(state: ChatRepository.ConnectionState) {
when (state) {
is ChatRepository.ConnectionState.Disconnected -> {
binding.connectionStatusText.text = "Disconnected"
binding.connectionIndicator.backgroundTintList =
ContextCompat.getColorStateList(requireContext(), R.color.disconnected_color)
}
is ChatRepository.ConnectionState.Searching -> {
binding.connectionStatusText.text = "Searching..."
binding.connectionIndicator.backgroundTintList =
ContextCompat.getColorStateList(requireContext(), R.color.connecting_color)
}
is ChatRepository.ConnectionState.Hosting -> {
binding.connectionStatusText.text = "Hosting"
binding.connectionIndicator.backgroundTintList =
ContextCompat.getColorStateList(requireContext(), R.color.hosting_color)
}
is ChatRepository.ConnectionState.Connected -> {
binding.connectionStatusText.text = "Connected"
binding.connectionIndicator.backgroundTintList =
ContextCompat.getColorStateList(requireContext(), R.color.connected_color)
}
is ChatRepository.ConnectionState.Error -> {
binding.connectionStatusText.text = "Error: ${state.message}"
binding.connectionIndicator.backgroundTintList =
ContextCompat.getColorStateList(requireContext(), R.color.disconnected_color)
}
}
}
override fun onDestroyView() {
super.onDestroyView()
Log.d(TAG, "onDestroyView")