1#ifndef YAZE_APP_PLATFORM_WASM_COLLABORATION_H_
2#define YAZE_APP_PLATFORM_WASM_COLLABORATION_H_
7#include <emscripten/html5.h>
8#include <emscripten/val.h>
17#include "absl/status/status.h"
18#include "absl/status/statusor.h"
32class WasmCollaboration {
42 double last_activity = 0;
76 using UserListCallback = std::function<void(
const std::vector<User>&)>;
77 using ChangeCallback = std::function<void(
const ChangeEvent&)>;
78 using CursorCallback = std::function<void(
const CursorInfo&)>;
79 using StatusCallback = std::function<void(
bool connected,
const std::string& message)>;
80 using ConnectionStateCallback = std::function<void(ConnectionState state,
const std::string& message)>;
99 absl::Status SetWebSocketUrl(
const std::string& url) {
101 websocket_url_.clear();
102 return absl::OkStatus();
104 if (url.find(
"ws://") != 0 && url.find(
"wss://") != 0) {
105 return absl::InvalidArgumentError(
106 "WebSocket URL must start with ws:// or wss://");
109 if (url.length() < 8) {
110 return absl::InvalidArgumentError(
"WebSocket URL is too short");
112 websocket_url_ = url;
113 return absl::OkStatus();
120 std::string GetWebSocketUrl()
const {
return websocket_url_; }
128 void InitializeFromConfig();
134 bool IsConfigured()
const {
return !websocket_url_.empty(); }
142 absl::StatusOr<std::string>
CreateSession(
const std::string& session_name,
143 const std::string& username,
144 const std::string& password =
"");
152 absl::Status
JoinSession(
const std::string& room_code,
153 const std::string& username,
154 const std::string& password =
"");
168 const std::vector<uint8_t>& old_data,
169 const std::vector<uint8_t>& new_data);
178 absl::Status SendCursorPosition(
const std::string& editor_type,
179 int x,
int y,
int map_id = -1);
185 void SetRom(Rom* rom) { rom_ = rom; }
191 void SetChangeCallback(ChangeCallback callback) {
192 change_callback_ = callback;
199 void SetUserListCallback(UserListCallback callback) {
200 user_list_callback_ = callback;
207 void SetCursorCallback(CursorCallback callback) {
208 cursor_callback_ = callback;
215 void SetStatusCallback(StatusCallback callback) {
216 status_callback_ = callback;
223 void SetConnectionStateCallback(ConnectionStateCallback callback) {
224 connection_state_callback_ = callback;
232 return connection_state_;
250 bool IsApplyingRemoteChange()
const {
return applying_remote_change_; }
256 std::string
GetRoomCode()
const {
return room_code_; }
267 std::string GetUserId()
const {
return user_id_; }
273 void SetAutoResolveConflicts(
bool enable) {
274 auto_resolve_conflicts_ = enable;
281 void ProcessPendingChanges();
285 void HandleMessage(
const std::string& message);
286 void HandleCreateResponse(
const emscripten::val& data);
287 void HandleJoinResponse(
const emscripten::val& data);
288 void HandleUserList(
const emscripten::val& data);
289 void HandleChange(
const emscripten::val& data);
290 void HandleCursor(
const emscripten::val& data);
291 void HandleError(
const emscripten::val& data);
294 std::string GenerateUserId();
295 std::string GenerateUserColor();
296 void UpdateUserActivity(
const std::string& user_id);
297 void CheckUserTimeouts();
298 bool IsChangeValid(
const ChangeEvent& change);
299 void ApplyRemoteChange(
const ChangeEvent& change);
302 void InitiateReconnection();
303 void AttemptReconnection();
304 void ResetReconnectionState();
305 void UpdateConnectionState(ConnectionState new_state,
const std::string& message);
306 void QueueMessageWhileDisconnected(
const std::string& message);
309 std::unique_ptr<net::EmscriptenWebSocket> websocket_;
310 bool is_connected_ =
false;
312 std::string websocket_url_;
315 int reconnection_attempts_ = 0;
316 int max_reconnection_attempts_ = 10;
317 double reconnection_delay_seconds_ = 1.0;
318 double max_reconnection_delay_ = 30.0;
319 bool should_reconnect_ =
false;
320 std::string stored_password_;
323 std::string room_code_;
324 std::string session_name_;
325 std::string user_id_;
326 std::string username_;
327 std::string user_color_;
330 std::map<std::string, User> users_;
331 mutable std::mutex users_mutex_;
334 std::map<std::string, CursorInfo> cursors_;
335 mutable std::mutex cursors_mutex_;
338 std::vector<ChangeEvent> pending_changes_;
339 mutable std::mutex changes_mutex_;
342 std::vector<std::string> queued_messages_;
343 mutable std::mutex message_queue_mutex_;
344 size_t max_queued_messages_ = 100;
347 bool auto_resolve_conflicts_ =
true;
350 UserListCallback user_list_callback_;
351 ChangeCallback change_callback_;
352 CursorCallback cursor_callback_;
353 StatusCallback status_callback_;
354 ConnectionStateCallback connection_state_callback_;
360 double last_cursor_send_ = 0;
363 bool applying_remote_change_ =
false;
367WasmCollaboration& GetWasmCollaborationInstance();
376#include "absl/status/status.h"
377#include "absl/status/statusor.h"
411 const std::string&) {
412 return absl::UnimplementedError(
"Collaboration requires WASM build");
415 absl::Status
JoinSession(
const std::string&,
const std::string&) {
416 return absl::UnimplementedError(
"Collaboration requires WASM build");
420 return absl::UnimplementedError(
"Collaboration requires WASM build");
424 const std::vector<uint8_t>&) {
425 return absl::UnimplementedError(
"Collaboration requires WASM build");
ConnectionState
WebSocket connection states.