| 97 | |
| 98 | // Function to create and set up WebSocket with auto-reconnect |
| 99 | const setupWebSocket = () => { |
| 100 | // Close any existing connection |
| 101 | if (socket) { |
| 102 | socket.close() |
| 103 | } |
| 104 | |
| 105 | setConnectionStatus(["connecting"]) |
| 106 | |
| 107 | // Always use secure WebSocket protocol (wss) |
| 108 | const wsBaseUrl = apiUrl.replace(/^https?:\/\//, "wss://") |
| 109 | const wsUrl = `${wsBaseUrl}/share_poll?id=${props.id}` |
| 110 | // Create WebSocket connection |
| 111 | socket = new WebSocket(wsUrl) |
| 112 | |
| 113 | // Handle connection opening |
| 114 | socket.onopen = () => { |
| 115 | setConnectionStatus(["connected"]) |
| 116 | } |
| 117 | |
| 118 | // Handle incoming messages |
| 119 | socket.onmessage = (event) => { |
| 120 | try { |
| 121 | const d = JSON.parse(event.data) |
| 122 | const [root, type, ...splits] = d.key.split("/") |
| 123 | if (root !== "session") return |
| 124 | if (type === "info") { |
| 125 | setStore("info", reconcile(d.content)) |
| 126 | return |
| 127 | } |
| 128 | if (type === "message") { |
| 129 | const [, messageID] = splits |
| 130 | if ("metadata" in d.content) { |
| 131 | d.content = fromV1(d.content) |
| 132 | } |
| 133 | d.content.parts = d.content.parts ?? store.messages[messageID]?.parts ?? [] |
| 134 | setStore("messages", messageID, reconcile(d.content)) |
| 135 | } |
| 136 | if (type === "part") { |
| 137 | setStore("messages", d.content.messageID, "parts", (arr) => { |
| 138 | const index = arr.findIndex((x) => x.id === d.content.id) |
| 139 | if (index === -1) arr.push(d.content) |
| 140 | if (index > -1) arr[index] = d.content |
| 141 | return [...arr] |
| 142 | }) |
| 143 | } |
| 144 | } catch (error) { |
| 145 | console.error("Error parsing WebSocket message:", error) |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | // Handle errors |
| 150 | socket.onerror = (error) => { |
| 151 | console.error("WebSocket error:", error) |
| 152 | setConnectionStatus(["error", props.messages.error_connection_failed]) |
| 153 | } |
| 154 | |
| 155 | // Handle connection close and reconnection |
| 156 | socket.onclose = () => { |