✨ Live updates of chat messages with websocket on watchOS
This commit is contained in:
@@ -26,7 +26,7 @@ struct AppInfoHeaderView : View {
|
||||
|
||||
// Display WebSocket connection status
|
||||
Text(webSocketStatusMessage)
|
||||
.font(.caption2)
|
||||
.font(.system(size: 10))
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,18 +259,22 @@ struct ChatRoomView: View {
|
||||
@State private var messages: [SnChatMessage] = []
|
||||
@State private var isLoading = false
|
||||
@State private var error: Error?
|
||||
@State private var webSocketConnectionState: WebSocketState = .disconnected // New state for WebSocket status
|
||||
@State private var wsState: WebSocketState = .disconnected // New state for WebSocket status
|
||||
|
||||
@State private var cancellables = Set<AnyCancellable>() // For managing subscriptions
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
// Display WebSocket connection status
|
||||
if (wsState != .connected)
|
||||
{
|
||||
Text(webSocketStatusMessage)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
.padding(.vertical, 2)
|
||||
.animation(.easeInOut, value: webSocketConnectionState) // Animate status changes
|
||||
.animation(.easeInOut, value: wsState) // Animate status changes
|
||||
.transition(.opacity)
|
||||
}
|
||||
|
||||
if isLoading {
|
||||
ProgressView()
|
||||
@@ -336,7 +340,7 @@ struct ChatRoomView: View {
|
||||
}
|
||||
|
||||
private var webSocketStatusMessage: String {
|
||||
switch webSocketConnectionState {
|
||||
switch wsState {
|
||||
case .connected: return "Connected"
|
||||
case .connecting: return "Connecting..."
|
||||
case .disconnected: return "Disconnected"
|
||||
@@ -368,6 +372,15 @@ struct ChatRoomView: View {
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
private func sendReadReceipt() {
|
||||
let data: [String: Any] = ["chat_room_id": room.id]
|
||||
let packet: [String: Any] = ["type": "messages.read", "data": data, "endpoint": "sphere"]
|
||||
if let jsonData = try? JSONSerialization.data(withJSONObject: packet, options: []),
|
||||
let jsonString = String(data: jsonData, encoding: .utf8) {
|
||||
appState.networkService.sendWebSocketMessage(message: jsonString)
|
||||
}
|
||||
}
|
||||
|
||||
private func setupWebSocketListeners() {
|
||||
// Listen for WebSocket packets (new messages)
|
||||
appState.networkService.packetStream
|
||||
@@ -377,20 +390,33 @@ struct ChatRoomView: View {
|
||||
print("[ChatRoomView] WebSocket packet stream error: \(err.localizedDescription)")
|
||||
}
|
||||
}, receiveValue: { packet in
|
||||
// Assuming 'message.created' is the type for new messages
|
||||
if packet.type == "message.created",
|
||||
if ["messages.new", "messages.update", "messages.delete"].contains(packet.type),
|
||||
let messageData = packet.data {
|
||||
do {
|
||||
let jsonData = try JSONSerialization.data(withJSONObject: messageData, options: [])
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .iso8601
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
let newMessage = try decoder.decode(SnChatMessage.self, from: jsonData)
|
||||
let message = try decoder.decode(SnChatMessage.self, from: jsonData)
|
||||
|
||||
if newMessage.chatRoomId == room.id {
|
||||
// Avoid adding duplicates
|
||||
if !messages.contains(where: { $0.id == newMessage.id }) {
|
||||
messages.append(newMessage)
|
||||
if message.chatRoomId == room.id {
|
||||
switch packet.type {
|
||||
case "messages.new":
|
||||
if message.type.hasPrefix("call") {
|
||||
// TODO: Handle ongoing call
|
||||
}
|
||||
if !messages.contains(where: { $0.id == message.id }) {
|
||||
messages.append(message)
|
||||
}
|
||||
sendReadReceipt()
|
||||
case "messages.update":
|
||||
if let index = messages.firstIndex(where: { $0.id == message.id }) {
|
||||
messages[index] = message
|
||||
}
|
||||
case "messages.delete":
|
||||
messages.removeAll(where: { $0.id == message.id })
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
@@ -404,7 +430,7 @@ struct ChatRoomView: View {
|
||||
appState.networkService.stateStream
|
||||
.receive(on: DispatchQueue.main) // Ensure UI updates on main thread
|
||||
.sink { state in
|
||||
webSocketConnectionState = state
|
||||
wsState = state
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
Reference in New Issue
Block a user