Live updates of chat messages with websocket on watchOS

This commit is contained in:
2025-10-31 00:11:24 +08:00
parent 3edcdd72af
commit 0ca801d963
2 changed files with 42 additions and 16 deletions

View File

@@ -26,7 +26,7 @@ struct AppInfoHeaderView : View {
// Display WebSocket connection status
Text(webSocketStatusMessage)
.font(.caption2)
.font(.system(size: 10))
.foregroundColor(.secondary)
}
}

View File

@@ -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
Text(webSocketStatusMessage)
.font(.caption2)
.foregroundColor(.secondary)
.padding(.vertical, 2)
.animation(.easeInOut, value: webSocketConnectionState) // Animate status changes
if (wsState != .connected)
{
Text(webSocketStatusMessage)
.font(.caption2)
.foregroundColor(.secondary)
.padding(.vertical, 2)
.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)
}