SpacedeckWebsockets = { data: { users_online: {} }, methods: { handle_live_updates: function(msg) { if (msg.model == "Space" && msg.object) { if (msg.object.space_type == "space") { if (this.active_space) { if (this.active_space._id == msg.object._id) { this.active_space = _.merge(this.active_space, msg.object); } } } } if (msg.model == "Message") { if (msg.action == "create" && msg.object) { var new_message = msg.object; if(this.active_space && this.active_space._id == new_message.space._id) { this.active_space_messages.push(new_message); this.refresh_space_comments(); } else console.log("message created in another space."); } } if (msg.model == "Artifact") { if (msg.action == "create" && msg.object) { var new_artifact = msg.object; if (this.active_space && this.active_space._id == new_artifact.space_id) { var o = new_artifact; if (o._id && !this.find_artifact_by_id(o._id)) { this.update_board_artifact_viewmodel(new_artifact); this.active_space_artifacts.push(new_artifact) } else { console.log("warning: got create on existing artifact."); msg.action = "update"; // hackety hack! } } else console.log("artifact created in another space."); } else if (msg.action == "update" && msg.object) { if (this.active_space) { var o = msg.object; if (o && o._id) { var existing_artifact = this.find_artifact_by_id(o._id); if (!existing_artifact) { existing_artifact = o; } else { for (key in o) { existing_artifact[key] = o[key]; this.update_board_artifact_viewmodel(existing_artifact); } } } } } else if (msg.action == "delete" && msg.object) { if (this.active_space) { var o = msg.object; if (o._id){ var existing_artifact = this.find_artifact_by_id(o._id); if (existing_artifact) { var idx = this.active_space_artifacts.indexOf(existing_artifact); this.active_space_artifacts.splice(idx, 1); } else console.log("existing artifact to delete not found"); } else console.error("object without _id"); } } } }, subscribe: function(space) { if (this.websocket && this.websocket.readyState==1) { this.websocket.send(JSON.stringify({action: "subscribe", space_id: space._id})); } else { console.error("socket not ready yet. (subscribe)"); } }, is_member_online: function(space, member) { if (!member.user) { return false; } if (!this.users_online[space._id]) { return false; } var isOnline = _.find(this.users_online[space._id], function(u) { return (u._id == member.user._id); }); return isOnline; }, auth_websocket: function(space){ if (!this.websocket) { this.init_websocket(); } if (this.websocket && this.websocket.readyState==1) { var token = ""; if (this.user) token = this.user.token; var auth_params = { action: "auth", editor_auth: space_auth, editor_name: this.guest_nickname, auth_token: token, space_id: space._id }; console.log("[websocket] auth space"); this.websocket.send(JSON.stringify(auth_params)); } }, websocket_send: function(msg) { if (!this.websocket) return; if (this.websocket.readyState!=1) return; try { this.websocket.send(JSON.stringify(msg)); } catch (e) { // catch NS problems } }, init_websocket: function() { if (this.websocket) this.websocket = null; if (this.current_timeout) { clearTimeout(this.current_timeout); this.current_timeout = null; } try { this.websocket = new WebSocket(ENV.websocketsEndpoint + "/socket"); } catch (e) { console.log("[websocket] cannot establish websocket connection: ",e); this.current_timeout = setTimeout(function() { console.log("[websocket] reconnecting", e); this.init_websocket(); }.bind(this),5000); } if (!this.websocket) { console.log("[websocket] no websocket support?"); return; } this.websocket.onopen = function(evt) { if (this.current_timeout) { clearTimeout(this.current_timeout); this.current_timeout = null; } if (this.active_space_loaded) { this.auth_websocket(this.active_space); } this.online = true; }.bind(this); this.websocket.onclose = function(evt) { if (!window._spacedeck_location_change) { this.online = false; } if (!this.current_timeout) { this.current_timeout = setTimeout(function() { console.log("[websocket] onclose: reconnecting", evt); this.init_websocket(); }.bind(this),5000); } }.bind(this); this.websocket.onmessage = function(evt) { this.online = true; try { var msg = JSON.parse(evt.data); } catch (e) { console.log("[websocket] malformed message: ",evt.data); return; } if (msg.channel_id == channel_id) { return; } if (msg.action == "cursor") { this.handle_user_cursor_update(msg); } else if (msg.action == "viewport") { this.handle_presenter_viewport_update(msg); } else if (msg.action == "media") { this.handle_presenter_media_update(msg); } if (msg.action == "update" || msg.action == "create" || msg.action == "delete"){ this.handle_live_updates(msg); } if (msg.action == "init") { channel_id = msg.channel_id; } if (msg.action == "auth_valid") { if (this.active_space) { this.subscribe(this.active_space); if (this.unsaved_transactions()) { console.log("[websockets-saver] found unsaved transactions, triggering save."); this.process_artifact_save_queue(); } } } if (msg.action == "subscription_valid") { console.log("subscription_valid"); } if (msg.action == "status_update") { var spaceId = msg.space_id; var users = msg.users; // filter ourselves if (this.user && this.user._id) { users = _.filter(users, function(u) { return (u && (u._id != this.user._id)); }.bind(this)); } users = _.filter(users, function(u) { return (u && (u._id || u.nickname)); }); this.users_online[spaceId] = users; if (this.active_space) { if (this.active_space._id == spaceId) { this.active_space_users = users; } } } }.bind(this); this.websocket.onerror = function(evt) { console.log("websocket.onerror:", evt); if (!window._spacedeck_location_change) { this.online = false; this.was_offline = true; } if (!this.current_timeout) { this.current_timeout = setTimeout(function() { console.log("websocket.onerror: reconnecting", evt); this.init_websocket(); }.bind(this),5000); } }.bind(this); } } }