diff --git a/web/app/assets/javascripts/backend_alerts.js b/web/app/assets/javascripts/backend_alerts.js new file mode 100644 index 000000000..c00693ff3 --- /dev/null +++ b/web/app/assets/javascripts/backend_alerts.js @@ -0,0 +1,100 @@ +(function(context,$) { + + "use strict"; + + context.JK = context.JK || {}; + + // Class to intercept and delegate out all backend alerts as necessary + // better if modules that needed certain events would just register for them. + context.JK.BackendAlerts = function(app) { + + var ALERT_TYPE = context.JK.ALERT_TYPE; + + function onNoValidAudioConfig(type, text) { + app.notify({ + "title": ALERT_TYPE[type].title, + "text": text, + "icon_url": "/assets/content/icon_alert_big.png" + }); + context.location = "/client#"; // leaveSession will be called in beforeHide below + } + + function onStunEvent() { + var testResults = context.jamClient.NetworkTestResult(); + + $.each(testResults, function (index, val) { + if (val.bStunFailed) { + // if true we could not reach a stun server + } + else if (val.bRemoteUdpBocked) { + // if true the user cannot communicate with peer via UDP, although they could do LAN based session + } + }); + } + + function onGenericEvent(type, text) { + context.setTimeout(function() { + var alert = ALERT_TYPE[type]; + + if(alert && alert.title) { + app.notify({ + "title": ALERT_TYPE[type].title, + "text": text, + "icon_url": "/assets/content/icon_alert_big.png" + }); + } + else { + logger.debug("Unknown Backend Event type %o, data %o", type, text) + } + }, 1); + } + + function alertCallback(type, text) { + + function timeCallback() { + var start = new Date(); + setTimeout(function() { + var timed = new Date().getTime() - start.getTime(); + if(timed > 250) { + logger.warn("SLOW AlERT_CALLBACK. type: %o text: %o time: %o", type, text, timed); + } + }, 1); + } + + timeCallback(); + + logger.debug("alert callback", type, text); + + if (type === 2) { // BACKEND_MIXER_CHANGE + context.JK.CurrentSessionModel.onBackendMixerChanged(type, text) + } + else if (type === 19) { // NO_VALID_AUDIO_CONFIG + onNoValidAudioConfig(type, text); + } + else if (type === 24) { + onStunEvent(); + } + else if (type === 26) { // DEAD_USER_REMOVE_EVENT + context.JK.CurrentSessionModel.onDeadUserRemove(type, text); + } + else if (type === 27) { // WINDOW_CLOSE_BACKGROUND_MODE + context.JK.CurrentSessionModel.onWindowBackgrounded(type, text); + } + else if(type != 30 && type != 31 && type != 21){ // these are handled elsewhere + onGenericEvent(type, text); + } + } + + function initialize() { + context.jamClient.SessionSetAlertCallback("JK.AlertCallback"); + } + + this.initialize = initialize; + + + context.JK.AlertCallback = alertCallback; + + return this; + } + +})(window, jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/chatPanel.js b/web/app/assets/javascripts/chatPanel.js index bf5b05eca..45a13014b 100644 --- a/web/app/assets/javascripts/chatPanel.js +++ b/web/app/assets/javascripts/chatPanel.js @@ -274,7 +274,6 @@ if(response.next == null) { // if we less results than asked for, end searching $chatMessagesScroller.infinitescroll('pause'); - logger.debug("end of chatss"); if(currentPage > 0) { // there are bugs with infinitescroll not removing the 'loading'. diff --git a/web/app/assets/javascripts/globals.js b/web/app/assets/javascripts/globals.js index 623670af6..f0c81c1d7 100644 --- a/web/app/assets/javascripts/globals.js +++ b/web/app/assets/javascripts/globals.js @@ -31,6 +31,58 @@ DIALOG_CLOSED : 'dialog_closed' } + // recreate eThresholdType enum from MixerDialog.h + context.JK.ALERT_TYPE = { + 0: {"title": "", "message": ""}, // NO_EVENT, + 1: {"title": "", "message": ""}, // BACKEND_ERROR: generic error - eg P2P message error + 2: {"title": "", "message": ""}, // BACKEND_MIXER_CHANGE, - event that controls have been regenerated + 3: {"title": "High Packet Jitter", "message": "Your network connection is currently experiencing packet jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click here."}, // PACKET_JTR, + 4: {"title": "High Packet Loss", "message": "Your network connection is currently experiencing packet loss at a rate that is too high to deliver good audio quality. For troubleshooting tips, click here." }, // PACKET_LOSS + 5: {"title": "High Packet Late", "message": "Your network connection is currently experiencing packet loss at a rate that is too high to deliver good audio quality. For troubleshooting tips, click here."}, // PACKET_LATE, + 6: {"title": "Large Jitter Queue", "message": "Your network connection is currently experiencing packet jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click here."}, // JTR_QUEUE_DEPTH, + 7: {"title": "High Network Jitter", "message": "Your network connection is currently experiencing network jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click here."}, // NETWORK_JTR, + 8: {"title": "High Session Latency", "message": "The latency of your audio device combined with your Internet connection has become high enough to impact your session quality. For troubleshooting tips, click here." }, // NETWORK_PING, + 9: {"title": "Bandwidth Throttled", "message": "The available bandwidth on your network has diminished, and this may impact your audio quality. For troubleshooting tips, click here."}, // BITRATE_THROTTLE_WARN, + 10:{"title": "Low Bandwidth", "message": "The available bandwidth on your network has become too low, and this may impact your audio quality. For troubleshooting tips, click here." }, // BANDWIDTH_LOW + + // IO related events + 11:{"title": "Variable Input Rate", "message": "The input rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click here." }, // INPUT_IO_RATE + 12:{"title": "High Input Jitter", "message": "The input rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click here."}, // INPUT_IO_JTR, + 13:{"title": "Variable Output Rate", "message": "The output rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click here." }, // OUTPUT_IO_RATE + 14:{"title": "High Output Jitter", "message": "The output rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click here."}, // OUTPUT_IO_JTR, + + // CPU load related + 15: { "title": "CPU Utilization High", "message": "The CPU of your computer is unable to keep up with the current processing load, and this may impact your audio quality. For troubleshooting tips, click here." }, // CPU_LOAD + 16: {"title": "Decode Violations", "message": ""}, // DECODE_VIOLATIONS, + 17: {"title": "", "message": ""}, // LAST_THRESHOLD + 18: {"title": "Wifi Alert", "message": ""}, // WIFI_NETWORK_ALERT, //user or peer is using wifi + 19: {"title": "No Audio Configuration", "message": "You cannot join the session because you do not have a valid audio configuration."}, // NO_VALID_AUDIO_CONFIG, + 20: {"title": "Audio Device Not Present", "message": ""}, // AUDIO_DEVICE_NOT_PRESENT, // the audio device is not connected + 21: {"title": "", "message": ""}, // RECORD_PLAYBACK_STATE, // record/playback events have occurred + 22: {"title": "", "message": ""}, // RUN_UPDATE_CHECK_BACKGROUND, //this is auto check - do + 23: {"title": "", "message": ""}, // RUN_UPDATE_CHECK_INTERACTIVE, //this is initiated by user + 24: {"title": "", "message": ""}, // STUN_EVENT, // system completed stun test... come get the result + 25: {"title": "No Audio", "message": "Your system is no longer transmitting audio. Other session members are unable to hear you."}, // DEAD_USER_WARN_EVENT, //the backend is not receiving audio from this peer + 26: {"title": "No Audio", "message": "Your system is no longer transmitting audio. Other session members are unable to hear you."}, // DEAD_USER_REMOVE_EVENT, //the backend is removing the user from session as no audio is coming from this peer + 27: {"title": "", "message": ""}, // WINDOW_CLOSE_BACKGROUND_MODE, //the user has closed the window and the client is now in background mode + 28: {"title": "", "message": ""}, // WINDOW_OPEN_FOREGROUND_MODE, //the user has opened the window and the client is now in forground mode/ + + 29: {"title": "Failed to Broadcast", "message": ""}, // SESSION_LIVEBROADCAST_FAIL, //error of some sort - so can't broadcast + 30: {"title": "", "message": ""}, // SESSION_LIVEBROADCAST_ACTIVE, //active + 31: {"title": "", "message": ""}, // SESSION_LIVEBROADCAST_STOPPED, //stopped by server/user + 32: {"title": "Client Pinned", "message": "This client will be the source of a broadcast."}, // SESSION_LIVEBROADCAST_PINNED, //node pinned by user + 33: {"title": "Client No Longer Pinned", "message": "This client is no longer designated as the source of the broadcast."}, // SESSION_LIVEBROADCAST_UNPINNED, //node unpinned by user + + 34: {"title": "", "message": ""}, // BACKEND_STATUS_MSG, //status/informational message + 35: {"title": "LAN Unpredictable", "message": "Your local network is adding considerable variance to transmit times. For troubleshooting tips, click here."}, // LOCAL_NETWORK_VARIANCE_HIGH,//the ping time via a hairpin for the user network is unnaturally high or variable. + + //indicates problem with user computer stack or network itself (wifi, antivirus etc) + 36: {"title": "LAN High Latency", "message": "Your local network is adding considerable latency. For troubleshooting tips, click here."}, // LOCAL_NETWORK_LATENCY_HIGH, + 37: {"title": "", "message": ""}, // RECORDING_CLOSE, //update and remove tracks from front-end + 38: {"title": "No Audio Sent", "message": ""}, // PEER_REPORTS_NO_AUDIO_RECV, //update and remove tracks from front-end + 39: {"title": "", "message": ""} // LAST_ALERT + }; + context.JK.MAX_TRACKS = 6; context.JK.MAX_OUTPUTS = 2; diff --git a/web/app/assets/javascripts/session.js b/web/app/assets/javascripts/session.js index 20fae6390..dd6cdf78d 100644 --- a/web/app/assets/javascripts/session.js +++ b/web/app/assets/javascripts/session.js @@ -30,7 +30,6 @@ var claimedRecording = null; var playbackControls = null; var promptLeave = false; - var backendMixerAlertThrottleTimer = null; var rateSessionDialog = null; var rest = context.JK.Rest(); @@ -77,59 +76,6 @@ }; - // recreate eThresholdType enum from MixerDialog.h - var alert_type = { - 0: {"title": "", "message": ""}, // NO_EVENT, - 1: {"title": "", "message": ""}, // BACKEND_ERROR: generic error - eg P2P message error - 2: {"title": "", "message": ""}, // BACKEND_MIXER_CHANGE, - event that controls have been regenerated - 3: {"title": "High Packet Jitter", "message": "Your network connection is currently experiencing packet jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click here."}, // PACKET_JTR, - 4: {"title": "High Packet Loss", "message": "Your network connection is currently experiencing packet loss at a rate that is too high to deliver good audio quality. For troubleshooting tips, click here." }, // PACKET_LOSS - 5: {"title": "High Packet Late", "message": "Your network connection is currently experiencing packet loss at a rate that is too high to deliver good audio quality. For troubleshooting tips, click here."}, // PACKET_LATE, - 6: {"title": "Large Jitter Queue", "message": "Your network connection is currently experiencing packet jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click here."}, // JTR_QUEUE_DEPTH, - 7: {"title": "High Network Jitter", "message": "Your network connection is currently experiencing network jitter at a level that is too high to deliver good audio quality. For troubleshooting tips, click here."}, // NETWORK_JTR, - 8: {"title": "High Session Latency", "message": "The latency of your audio device combined with your Internet connection has become high enough to impact your session quality. For troubleshooting tips, click here." }, // NETWORK_PING, - 9: {"title": "Bandwidth Throttled", "message": "The available bandwidth on your network has diminished, and this may impact your audio quality. For troubleshooting tips, click here."}, // BITRATE_THROTTLE_WARN, - 10:{"title": "Low Bandwidth", "message": "The available bandwidth on your network has become too low, and this may impact your audio quality. For troubleshooting tips, click here." }, // BANDWIDTH_LOW - - // IO related events - 11:{"title": "Variable Input Rate", "message": "The input rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click here." }, // INPUT_IO_RATE - 12:{"title": "High Input Jitter", "message": "The input rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click here."}, // INPUT_IO_JTR, - 13:{"title": "Variable Output Rate", "message": "The output rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click here." }, // OUTPUT_IO_RATE - 14:{"title": "High Output Jitter", "message": "The output rate of your audio device is varying too much to deliver good audio quality. For troubleshooting tips, click here."}, // OUTPUT_IO_JTR, - - // CPU load related - 15: { "title": "CPU Utilization High", "message": "The CPU of your computer is unable to keep up with the current processing load, and this may impact your audio quality. For troubleshooting tips, click here." }, // CPU_LOAD - 16: {"title": "Decode Violations", "message": ""}, // DECODE_VIOLATIONS, - 17: {"title": "", "message": ""}, // LAST_THRESHOLD - 18: {"title": "Wifi Alert", "message": ""}, // WIFI_NETWORK_ALERT, //user or peer is using wifi - 19: {"title": "No Audio Configuration", "message": "You cannot join the session because you do not have a valid audio configuration."}, // NO_VALID_AUDIO_CONFIG, - 20: {"title": "Audio Device Not Present", "message": ""}, // AUDIO_DEVICE_NOT_PRESENT, // the audio device is not connected - 21: {"title": "", "message": ""}, // RECORD_PLAYBACK_STATE, // record/playback events have occurred - 22: {"title": "", "message": ""}, // RUN_UPDATE_CHECK_BACKGROUND, //this is auto check - do - 23: {"title": "", "message": ""}, // RUN_UPDATE_CHECK_INTERACTIVE, //this is initiated by user - 24: {"title": "", "message": ""}, // STUN_EVENT, // system completed stun test... come get the result - 25: {"title": "No Audio", "message": "Your system is no longer transmitting audio. Other session members are unable to hear you."}, // DEAD_USER_WARN_EVENT, //the backend is not receiving audio from this peer - 26: {"title": "No Audio", "message": "Your system is no longer transmitting audio. Other session members are unable to hear you."}, // DEAD_USER_REMOVE_EVENT, //the backend is removing the user from session as no audio is coming from this peer - 27: {"title": "", "message": ""}, // WINDOW_CLOSE_BACKGROUND_MODE, //the user has closed the window and the client is now in background mode - 28: {"title": "", "message": ""}, // WINDOW_OPEN_FOREGROUND_MODE, //the user has opened the window and the client is now in forground mode/ - - 29: {"title": "Failed to Broadcast", "message": ""}, // SESSION_LIVEBROADCAST_FAIL, //error of some sort - so can't broadcast - 30: {"title": "", "message": ""}, // SESSION_LIVEBROADCAST_ACTIVE, //active - 31: {"title": "", "message": ""}, // SESSION_LIVEBROADCAST_STOPPED, //stopped by server/user - 32: {"title": "Client Pinned", "message": "This client will be the source of a broadcast."}, // SESSION_LIVEBROADCAST_PINNED, //node pinned by user - 33: {"title": "Client No Longer Pinned", "message": "This client is no longer designated as the source of the broadcast."}, // SESSION_LIVEBROADCAST_UNPINNED, //node unpinned by user - - 34: {"title": "", "message": ""}, // BACKEND_STATUS_MSG, //status/informational message - 35: {"title": "LAN Unpredictable", "message": "Your local network is adding considerable variance to transmit times. For troubleshooting tips, click here."}, // LOCAL_NETWORK_VARIANCE_HIGH,//the ping time via a hairpin for the user network is unnaturally high or variable. - - //indicates problem with user computer stack or network itself (wifi, antivirus etc) - 36: {"title": "LAN High Latency", "message": "Your local network is adding considerable latency. For troubleshooting tips, click here."}, // LOCAL_NETWORK_LATENCY_HIGH, - 37: {"title": "", "message": ""}, // RECORDING_CLOSE, //update and remove tracks from front-end - 38: {"title": "No Audio Sent", "message": ""}, // PEER_REPORTS_NO_AUDIO_RECV, //update and remove tracks from front-end - 39: {"title": "", "message": ""} // LAST_ALERT - }; - - function beforeShow(data) { sessionId = data.id; promptLeave = true; @@ -144,114 +90,6 @@ return { freezeInteraction: true }; } - function alertCallback(type, text) { - - function timeCallback() { - var start = new Date(); - setTimeout(function() { - var timed = new Date().getTime() - start.getTime(); - if(timed > 250) { - logger.warn("SLOW AlERT_CALLBACK. type: %o text: %o time: %o", type, text, timed); - } - }, 1); - } - - timeCallback(); - - logger.debug("alert callback", type, text); - - if (type === 2) { // BACKEND_MIXER_CHANGE - logger.debug("BACKEND_MIXER_CHANGE alert. reason:" + text); - - if(sessionModel.id() && text == "RebuildAudioIoControl") { - - // the backend will send these events rapid-fire back to back. - // the server can still perform correctly, but it is nicer to wait 100 ms to let them all fall through - if(backendMixerAlertThrottleTimer) {clearTimeout(backendMixerAlertThrottleTimer);} - - backendMixerAlertThrottleTimer = setTimeout(function() { - // this is a local change to our tracks. we need to tell the server about our updated track information - var inputTracks = context.JK.TrackHelpers.getUserTracks(context.jamClient); - - // create a trackSync request based on backend data - var syncTrackRequest = {}; - syncTrackRequest.client_id = app.clientId; - syncTrackRequest.tracks = inputTracks; - syncTrackRequest.id = sessionModel.id(); - - rest.putTrackSyncChange(syncTrackRequest) - .done(function() { - }) - .fail(function() { - app.notify({ - "title": "Can't Sync Local Tracks", - "text": "The client is unable to sync local track information with the server. You should rejoin the session to ensure a good experience.", - "icon_url": "/assets/content/icon_alert_big.png" - }); - }) - }, 100); - } - else if(sessionModel.id() && (text == 'RebuildMediaControl' || text == 'RebuildRemoteUserControl')) { - sessionModel.refreshCurrentSession(true); - } - } - else if (type === 19) { // NO_VALID_AUDIO_CONFIG - app.notify({ - "title": alert_type[type].title, - "text": text, - "icon_url": "/assets/content/icon_alert_big.png" - }); - context.location = "/client#"; // leaveSession will be called in beforeHide below - } - else if (type === 24) { // STUN_EVENT - var testResults = context.jamClient.NetworkTestResult(); - - $.each(testResults, function(index, val) { - if (val.bStunFailed) { - // if true we could not reach a stun server - } - else if (val.bRemoteUdpBocked) { - // if true the user cannot communicate with peer via UDP, although they could do LAN based session - } - }); - } - else if (type === 26) { - var clientId = text; - var participant = sessionModel.getParticipant(clientId); - if(participant) { - app.notify({ - "title": alert_type[type].title, - "text": participant.user.name + " is no longer sending audio.", - "icon_url": context.JK.resolveAvatarUrl(participant.user.photo_url) - }); - var $track = $('div.track[client-id="' + clientId + '"]'); - $('.disabled-track-overlay', $track).show(); - } - } - else if (type === 27) { // WINDOW_CLOSE_BACKGROUND_MODE - // the window was closed; just attempt to nav to home, which will cause all the right REST calls to happen - promptLeave = false; - context.location = '/client#/home' - } - else if(type != 30 && type != 31 && type != 21){ // these are handled elsewhere - context.setTimeout(function() { - var alert = alert_type[type]; - - if(alert && alert.title) { - app.notify({ - "title": alert_type[type].title, - "text": text, - "icon_url": "/assets/content/icon_alert_big.png" - }); - } - else { - logger.debug("Unknown Backend Event type %o, data %o", type, text) - } - }, 1); - - } - } - function initializeSession() { // indicate that the screen is active, so that // body-scoped drag handlers can go active @@ -327,7 +165,8 @@ context.JK.CurrentSessionModel = sessionModel = new context.JK.SessionModel( context.JK.app, context.JK.JamServer, - context.jamClient + context.jamClient, + self ); $(sessionModel.recordingModel) @@ -1567,7 +1406,6 @@ context.JK.HandleVolumeChangeCallback = handleVolumeChangeCallback; context.JK.HandleBridgeCallback = handleBridgeCallback; - context.JK.AlertCallback = alertCallback; }; })(window,jQuery); \ No newline at end of file diff --git a/web/app/assets/javascripts/sessionModel.js b/web/app/assets/javascripts/sessionModel.js index e5b33c2f3..7f359d274 100644 --- a/web/app/assets/javascripts/sessionModel.js +++ b/web/app/assets/javascripts/sessionModel.js @@ -7,7 +7,10 @@ context.JK = context.JK || {}; var logger = context.JK.logger; - context.JK.SessionModel = function(app, server, client) { + // screen can be null + context.JK.SessionModel = function(app, server, client, sessionScreen) { + var ALERT_TYPE = context.JK.ALERT_TYPE; + var clientId = client.clientID; var currentSessionId = null; // Set on join, prior to setting currentSession. var currentSession = null; @@ -19,6 +22,7 @@ var pendingSessionRefresh = false; var recordingModel = new context.JK.RecordingModel(app, this, rest, context.jamClient); var currentTrackChanges = 0; + var backendMixerAlertThrottleTimer = null; // we track all the clientIDs of all the participants ever seen by this session, so that we can reliably convert a clientId from the backend into a username/avatar var participantsEverSeen = {}; var $self = $(this); @@ -29,6 +33,10 @@ return currentSession ? currentSession.id : null; } + function inSession() { + return !!currentSessionId; + } + function participants() { if (currentSession) { return currentSession.participants; @@ -214,6 +222,12 @@ * the provided callback when complete. */ function refreshCurrentSessionRest(callback, force) { + + if(!inSession()) { + logger.debug("refreshCurrentSession skipped: ") + return; + } + var url = "/api/sessions/" + currentSessionId; if(requestingSessionRefresh) { // if someone asks for a refresh while one is going on, we ask for another to queue up @@ -239,7 +253,14 @@ logger.info("ignoring refresh because we already have current: " + currentTrackChanges + ", seen: " + response.track_changes_counter); } }, - error: function(jqXHR) { app.notifyServerError(jqXHR, "Unable to refresh session data") }, + error: function(jqXHR) { + if(jqXHR.status != 404) { + app.notifyServerError(jqXHR, "Unable to refresh session data") + } + else { + logger.debug("refreshCurrentSessionRest: could not refresh data for session because it's gone") + } + }, complete: function() { requestingSessionRefresh = false; if(pendingSessionRefresh) { @@ -411,6 +432,70 @@ return $.Deferred().reject().promise(); } + function onDeadUserRemove(type, text) { + var clientId = text; + var participant = participantsEverSeen[clientId]; + if(participant) { + app.notify({ + "title": ALERT_TYPE[type].title, + "text": participant.user.name + " is no longer sending audio.", + "icon_url": context.JK.resolveAvatarUrl(participant.user.photo_url) + }); + var $track = $('div.track[client-id="' + clientId + '"]'); + $('.disabled-track-overlay', $track).show(); + } + } + + function onWindowBackgrounded(type, text) { + // the window was closed; just attempt to nav to home, which will cause all the right REST calls to happen + if(sessionScreen) { + sessionScreen.setPromptLeave(false); + context.location = '/client#/home' + } + } + + function onBackendMixerChanged(type, text) { + logger.debug("BACKEND_MIXER_CHANGE alert. reason:" + text); + + if(inSession() && text == "RebuildAudioIoControl") { + + // the backend will send these events rapid-fire back to back. + // the server can still perform correctly, but it is nicer to wait 100 ms to let them all fall through + if(backendMixerAlertThrottleTimer) {clearTimeout(backendMixerAlertThrottleTimer);} + + backendMixerAlertThrottleTimer = setTimeout(function() { + // this is a local change to our tracks. we need to tell the server about our updated track information + var inputTracks = context.JK.TrackHelpers.getUserTracks(context.jamClient); + + // create a trackSync request based on backend data + var syncTrackRequest = {}; + syncTrackRequest.client_id = app.clientId; + syncTrackRequest.tracks = inputTracks; + syncTrackRequest.id = id(); + + rest.putTrackSyncChange(syncTrackRequest) + .done(function() { + }) + .fail(function() { + if(jqXHR.status != 404) { + app.notify({ + "title": "Can't Sync Local Tracks", + "text": "The client is unable to sync local track information with the server. You should rejoin the session to ensure a good experience.", + "icon_url": "/assets/content/icon_alert_big.png" + }); + } + else { + logger.debug("Unable to sync local tracks because session is gone.") + } + + }) + }, 100); + } + else if(inSession() && (text == 'RebuildMediaControl' || text == 'RebuildRemoteUserControl')) { + refreshCurrentSession(true); + } + } + // Public interface this.id = id; this.recordedTracks = recordedTracks; @@ -425,6 +510,12 @@ this.onWebsocketDisconnected = onWebsocketDisconnected; this.recordingModel = recordingModel; this.findUserBy = findUserBy; + + // ALERT HANDLERS + this.onBackendMixerChanged = onBackendMixerChanged; + this.onDeadUserRemove = onDeadUserRemove; + this.onWindowBackgrounded = onWindowBackgrounded; + this.getCurrentSession = function() { return currentSession; }; diff --git a/web/app/views/clients/index.html.erb b/web/app/views/clients/index.html.erb index 3c946bcb3..6b4169cbf 100644 --- a/web/app/views/clients/index.html.erb +++ b/web/app/views/clients/index.html.erb @@ -298,8 +298,12 @@ }); // this ensures that there is always a CurrentSessionModel, even if it's for a non-active session - JK.CurrentSessionModel = new JK.SessionModel(JK.app, JK.JamServer, window.jamClient); + JK.CurrentSessionModel = new JK.SessionModel(JK.app, JK.JamServer, window.jamClient, null); } + + // make surethe CurrentSessionModel exists before initializing backend alerts + var backendAlerts = new JK.BackendAlerts(JK.app); + backendAlerts.initialize(); JK.bindHoverEvents(); })