* VRFS-1473 - Notification Highlighter - make obvious to user that they have new notifications complete
* VRFS-1523 - USER: Make "enter" key send message in new user-to-user messaging feature
This commit is contained in:
parent
526f6fe577
commit
53a6941ceb
|
|
@ -472,8 +472,8 @@ message TestClientMessage {
|
||||||
// sent from client to server periodically to let server track if the client is truly alive and avoid TCP timeout scenarios
|
// sent from client to server periodically to let server track if the client is truly alive and avoid TCP timeout scenarios
|
||||||
// the server will send a HeartbeatAck in response to this
|
// the server will send a HeartbeatAck in response to this
|
||||||
message Heartbeat {
|
message Heartbeat {
|
||||||
optional string notification_seen_at = 1;
|
optional string notification_seen = 1;
|
||||||
|
optional string notification_seen_at = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// target: client
|
// target: client
|
||||||
|
|
|
||||||
|
|
@ -294,7 +294,28 @@ module JamRuby
|
||||||
|
|
||||||
# returns the # of new notifications
|
# returns the # of new notifications
|
||||||
def new_notifications
|
def new_notifications
|
||||||
Notification.select('id').where(target_user_id: id).where('created_at > ?', notification_seen_at).count
|
search = Notification.select('id').where(target_user_id: self.id)
|
||||||
|
search = search.where('created_at > ?', self.notification_seen_at) if self.notification_seen_at
|
||||||
|
search.count
|
||||||
|
end
|
||||||
|
|
||||||
|
# the user can pass in a timestamp string, or the keyword 'LATEST'
|
||||||
|
# if LATEST is specified, we'll use the latest_notification as the timestamp
|
||||||
|
# if not, just use seen as-is
|
||||||
|
def update_notification_seen_at seen
|
||||||
|
new_latest_seen = nil
|
||||||
|
if seen == 'LATEST'
|
||||||
|
latest = self.latest_notification
|
||||||
|
new_latest_seen = latest.created_at if latest
|
||||||
|
else
|
||||||
|
new_latest_seen = seen
|
||||||
|
end
|
||||||
|
|
||||||
|
self.notification_seen_at = new_latest_seen
|
||||||
|
end
|
||||||
|
|
||||||
|
def latest_notification
|
||||||
|
Notification.select('created_at').where(target_user_id: id).limit(1).order('created_at DESC').first
|
||||||
end
|
end
|
||||||
|
|
||||||
def confirm_email!
|
def confirm_email!
|
||||||
|
|
|
||||||
|
|
@ -99,9 +99,10 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
// Heartbeat message
|
// Heartbeat message
|
||||||
factory.heartbeat = function(notification_last_seen_at) {
|
factory.heartbeat = function(lastNotificationSeen, lastNotificationSeenAt) {
|
||||||
var data = {};
|
var data = {};
|
||||||
data.notification_last_seen_at = notification_last_seen_at;
|
data.notification_seen = lastNotificationSeen;
|
||||||
|
data.notification_seen_at = lastNotificationSeenAt;
|
||||||
return client_container(msg.HEARTBEAT, route_to.SERVER, data);
|
return client_container(msg.HEARTBEAT, route_to.SERVER, data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
var heartbeatAckCheckInterval = null;
|
var heartbeatAckCheckInterval = null;
|
||||||
var userDeferred = null;
|
var userDeferred = null;
|
||||||
var notificationLastSeenAt = undefined;
|
var notificationLastSeenAt = undefined;
|
||||||
|
var notificationLastSeen = undefined;
|
||||||
|
|
||||||
var opts = {
|
var opts = {
|
||||||
inClient: true, // specify false if you want the app object but none of the client-oriented features
|
inClient: true, // specify false if you want the app object but none of the client-oriented features
|
||||||
|
|
@ -92,9 +93,9 @@
|
||||||
|
|
||||||
function _heartbeat() {
|
function _heartbeat() {
|
||||||
if (app.heartbeatActive) {
|
if (app.heartbeatActive) {
|
||||||
|
var message = context.JK.MessageFactory.heartbeat(notificationLastSeen, notificationLastSeenAt);
|
||||||
var message = context.JK.MessageFactory.heartbeat(notificationLastSeenAt);
|
|
||||||
notificationLastSeenAt = undefined;
|
notificationLastSeenAt = undefined;
|
||||||
|
notificationLastSeen = undefined;
|
||||||
context.JK.JamServer.send(message);
|
context.JK.JamServer.send(message);
|
||||||
lastHeartbeatFound = false;
|
lastHeartbeatFound = false;
|
||||||
}
|
}
|
||||||
|
|
@ -386,7 +387,7 @@
|
||||||
return userDeferred;
|
return userDeferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateNotificationSeen = function(notificationCreatedAt) {
|
this.updateNotificationSeen = function(notificationId, notificationCreatedAt) {
|
||||||
var time = new Date(notificationCreatedAt);
|
var time = new Date(notificationCreatedAt);
|
||||||
|
|
||||||
if(!notificationCreatedAt) {
|
if(!notificationCreatedAt) {
|
||||||
|
|
@ -395,10 +396,12 @@
|
||||||
|
|
||||||
if(!notificationLastSeenAt) {
|
if(!notificationLastSeenAt) {
|
||||||
notificationLastSeenAt = notificationCreatedAt;
|
notificationLastSeenAt = notificationCreatedAt;
|
||||||
|
notificationLastSeen = notificationId;
|
||||||
logger.debug("updated notificationLastSeenAt with: " + notificationCreatedAt);
|
logger.debug("updated notificationLastSeenAt with: " + notificationCreatedAt);
|
||||||
}
|
}
|
||||||
else if(time.getTime() > new Date(notificationLastSeenAt).getTime()) {
|
else if(time.getTime() > new Date(notificationLastSeenAt).getTime()) {
|
||||||
notificationLastSeenAt = notificationCreatedAt;
|
notificationLastSeenAt = notificationCreatedAt;
|
||||||
|
notificationLastSeen = notificationId;
|
||||||
logger.debug("updated notificationLastSeenAt with: " + notificationCreatedAt);
|
logger.debug("updated notificationLastSeenAt with: " + notificationCreatedAt);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,8 @@
|
||||||
if (!sidebarVisible) {
|
if (!sidebarVisible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var $expandedPanelContents = $('[layout-id="' + expandedPanel + '"] [layout-panel="contents"]');
|
var $expandedPanel = $('[layout-id="' + expandedPanel + '"]');
|
||||||
|
var $expandedPanelContents = $expandedPanel.find('[layout-panel="contents"]');
|
||||||
var combinedHeaderHeight = $('[layout-panel="contents"]').length * opts.panelHeaderHeight;
|
var combinedHeaderHeight = $('[layout-panel="contents"]').length * opts.panelHeaderHeight;
|
||||||
var searchHeight = $('.sidebar .search').first().height();
|
var searchHeight = $('.sidebar .search').first().height();
|
||||||
var expanderHeight = $('[layout-sidebar-expander]').height();
|
var expanderHeight = $('[layout-sidebar-expander]').height();
|
||||||
|
|
@ -259,6 +260,7 @@
|
||||||
$('[layout-panel="contents"]').hide();
|
$('[layout-panel="contents"]').hide();
|
||||||
$('[layout-panel="contents"]').css({"height": "1px"});
|
$('[layout-panel="contents"]').css({"height": "1px"});
|
||||||
$expandedPanelContents.show();
|
$expandedPanelContents.show();
|
||||||
|
$expandedPanel.triggerHandler('open')
|
||||||
$expandedPanelContents.animate({"height": expandedPanelHeight + "px"}, opts.animationDuration);
|
$expandedPanelContents.animate({"height": expandedPanelHeight + "px"}, opts.animationDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -531,6 +533,25 @@
|
||||||
return openDialogs.length > 0;
|
return openDialogs.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function currentDialog() {
|
||||||
|
if(openDialogs.length == 0) return null;
|
||||||
|
|
||||||
|
return openDialogs[openDialogs.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// payload is a notification event from websocket gateway
|
||||||
|
function dialogObscuredNotification(payload) {
|
||||||
|
var openDialog = currentDialog();
|
||||||
|
if(!openDialog) return false;
|
||||||
|
|
||||||
|
if(typeof openDialog.handledNotification === 'function') {
|
||||||
|
return !openDialog.handledNotification(payload);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for keeping N dialogs in correct stacked order,
|
* Responsible for keeping N dialogs in correct stacked order,
|
||||||
* also moves the .dialog-overlay such that it hides/obscures all dialogs except the highest one
|
* also moves the .dialog-overlay such that it hides/obscures all dialogs except the highest one
|
||||||
|
|
@ -854,6 +875,10 @@
|
||||||
showDialog(dialog, options);
|
showDialog(dialog, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.dialogObscuredNotification = function() {
|
||||||
|
return dialogObscuredNotification();
|
||||||
|
}
|
||||||
|
|
||||||
this.isDialogShowing = function() {
|
this.isDialogShowing = function() {
|
||||||
return isDialogShowing();
|
return isDialogShowing();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,34 +10,38 @@
|
||||||
var missedNotificationsWhileAway = false;
|
var missedNotificationsWhileAway = false;
|
||||||
var $panel = null;
|
var $panel = null;
|
||||||
var $expanded = null;
|
var $expanded = null;
|
||||||
|
var $contents = null;
|
||||||
var $count = null;
|
var $count = null;
|
||||||
|
var $list = null;
|
||||||
|
var $notificationTemplate = null;
|
||||||
var darkenedColor = '#0D7B89';
|
var darkenedColor = '#0D7B89';
|
||||||
var highlightedColor = 'white'
|
var highlightedColor = 'white'
|
||||||
|
var textMessageDialog = null;
|
||||||
|
var queuedNotification = null;
|
||||||
// one important limitation; if the user is focused on an iframe, this will be false
|
var queuedNotificationCreatedAt = null;
|
||||||
// however, if they are doing something with Facebook or the photo picker, this may actually still be desirable
|
|
||||||
function userCanSeeNotifications() {
|
|
||||||
return document.hasFocus() || app.layout.isDialogShowing();
|
|
||||||
}
|
|
||||||
|
|
||||||
function isNotificationsPanelVisible() {
|
function isNotificationsPanelVisible() {
|
||||||
return $expanded.is(':visible')
|
return $contents.is(':visible')
|
||||||
}
|
}
|
||||||
|
|
||||||
function incrementNotificationCount() {
|
function incrementNotificationCount() {
|
||||||
var count = parseInt($count.text());
|
var count = parseInt($count.text());
|
||||||
$count.text(count + 1);
|
setCount(count + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the element to white, and pulse it down to the un-highlighted value 2x, then set
|
// set the element to white, and pulse it down to the un-highlighted value 2x, then set
|
||||||
function pulseToDark() {
|
function pulseToDark() {
|
||||||
|
logger.debug("pulsing notification badge")
|
||||||
lowlightCount();
|
lowlightCount();
|
||||||
$count.pulse({'background-color' : highlightedColor}, {pulses: 2}, function() {
|
$count.pulse({'background-color' : highlightedColor}, {pulses: 2}, function() {
|
||||||
$count.text('0');
|
$count.removeAttr('style')
|
||||||
|
setCount(0);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setCount(count) {
|
||||||
|
$count.text(count);
|
||||||
|
}
|
||||||
|
|
||||||
function lowlightCount() {
|
function lowlightCount() {
|
||||||
$count.removeClass('highlighted');
|
$count.removeClass('highlighted');
|
||||||
|
|
@ -47,11 +51,35 @@
|
||||||
$count.addClass('highlighted');
|
$count.addClass('highlighted');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function queueNotificationSeen(notificationId, notificationCreatedAt) {
|
||||||
|
|
||||||
|
var time = new Date(notificationCreatedAt);
|
||||||
|
|
||||||
|
if(!notificationCreatedAt) {
|
||||||
|
throw 'invalid value passed to queuedNotificationCreatedAt'
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!queuedNotificationCreatedAt) {
|
||||||
|
queuedNotification = notificationId;
|
||||||
|
queuedNotificationCreatedAt = notificationCreatedAt;
|
||||||
|
logger.debug("updated queuedNotificationCreatedAt with: " + notificationCreatedAt);
|
||||||
|
}
|
||||||
|
else if(time.getTime() > new Date(queuedNotificationCreatedAt).getTime()) {
|
||||||
|
queuedNotification = notificationId;
|
||||||
|
queuedNotificationCreatedAt = notificationCreatedAt;
|
||||||
|
logger.debug("updated queuedNotificationCreatedAt with: " + notificationCreatedAt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.debug("ignored queuedNotificationCreatedAt for: " + notificationCreatedAt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onNotificationOccurred(payload) {
|
function onNotificationOccurred(payload) {
|
||||||
if(userCanSeeNotifications()) {
|
if(userCanSeeNotifications(payload)) {
|
||||||
app.updateNotificationSeen(payload.created_at);
|
app.updateNotificationSeen(payload.notification_id, payload.created_at);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
queueNotificationSeen(payload.notification_id, payload.created_at);
|
||||||
highlightCount();
|
highlightCount();
|
||||||
incrementNotificationCount();
|
incrementNotificationCount();
|
||||||
missedNotificationsWhileAway = true;
|
missedNotificationsWhileAway = true;
|
||||||
|
|
@ -63,12 +91,28 @@
|
||||||
if(missedNotificationsWhileAway) {
|
if(missedNotificationsWhileAway) {
|
||||||
// catch user's eye, then put count to 0
|
// catch user's eye, then put count to 0
|
||||||
pulseToDark();
|
pulseToDark();
|
||||||
|
if(queuedNotificationCreatedAt) {
|
||||||
|
app.updateNotificationSeen(queuedNotification, queuedNotificationCreatedAt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
queuedNotification = null;
|
||||||
|
queuedNotificationCreatedAt = null;
|
||||||
missedNotificationsWhileAway = false;
|
missedNotificationsWhileAway = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function opened() {
|
||||||
|
queuedNotification = null;
|
||||||
|
queuedNotificationCreatedAt = null;
|
||||||
|
rest.updateUser({notification_seen_at: 'LATEST'})
|
||||||
|
.done(function(response) {
|
||||||
|
lowlightCount();
|
||||||
|
setCount(0);
|
||||||
|
})
|
||||||
|
.fail(app.ajaxError)
|
||||||
|
}
|
||||||
|
|
||||||
function windowBlurred() {
|
function windowBlurred() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -77,6 +121,42 @@
|
||||||
$(app.layout).on('dialog_closed', function(e, data) {if(data.dialogCount == 0) userCameBack(); });
|
$(app.layout).on('dialog_closed', function(e, data) {if(data.dialogCount == 0) userCameBack(); });
|
||||||
$(window).focus(userCameBack);
|
$(window).focus(userCameBack);
|
||||||
$(window).blur(windowBlurred);
|
$(window).blur(windowBlurred);
|
||||||
|
app.user()
|
||||||
|
.done(function(user) {
|
||||||
|
setCount(user.new_notifications);
|
||||||
|
if(user.new_notifications > 0) {
|
||||||
|
highlightCount();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$panel.on('open', opened);
|
||||||
|
|
||||||
|
// friend notifications
|
||||||
|
registerFriendRequest();
|
||||||
|
registerFriendRequestAccepted();
|
||||||
|
registerNewUserFollower();
|
||||||
|
registerNewBandFollower();
|
||||||
|
|
||||||
|
// session notifications
|
||||||
|
registerSessionInvitation();
|
||||||
|
registerSessionEnded();
|
||||||
|
registerJoinRequest();
|
||||||
|
registerJoinRequestApproved();
|
||||||
|
registerJoinRequestRejected();
|
||||||
|
registerMusicianSessionJoin();
|
||||||
|
registerBandSessionJoin();
|
||||||
|
|
||||||
|
// recording notifications
|
||||||
|
registerMusicianRecordingSaved();
|
||||||
|
registerBandRecordingSaved();
|
||||||
|
registerRecordingMasterMixComplete();
|
||||||
|
|
||||||
|
// band notifications
|
||||||
|
registerBandInvitation();
|
||||||
|
registerBandInvitationAccepted();
|
||||||
|
|
||||||
|
// register text messages
|
||||||
|
registerTextMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
function populate() {
|
function populate() {
|
||||||
|
|
@ -88,20 +168,736 @@
|
||||||
.fail(app.ajaxError)
|
.fail(app.ajaxError)
|
||||||
}
|
}
|
||||||
|
|
||||||
function initialize(sidebar) {
|
function updateNotificationList(response) {
|
||||||
|
$list.empty();
|
||||||
|
|
||||||
|
$.each(response, function(index, val) {
|
||||||
|
|
||||||
|
if(val.description == 'TEXT_MESSAGE') {
|
||||||
|
val.formatted_msg = textMessageDialog.formatTextMessage(val.message.substring(0, 200), val.source_user_id, val.source_user.name, val.message.length > 200).html();
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill in template for Connect pre-click
|
||||||
|
var template = $notificationTemplate.html();
|
||||||
|
var notificationHtml = context.JK.fillTemplate(template, {
|
||||||
|
notificationId: val.notification_id,
|
||||||
|
sessionId: val.session_id,
|
||||||
|
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
|
||||||
|
text: val.formatted_msg,
|
||||||
|
date: $.timeago(val.created_at)
|
||||||
|
});
|
||||||
|
|
||||||
|
$list.append(notificationHtml);
|
||||||
|
|
||||||
|
// val.description contains the notification record's description value from the DB (i.e., type)
|
||||||
|
initializeActions(val, val.description);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function initializeActions(payload, type) {
|
||||||
|
|
||||||
|
var $notification = $('li[notification-id=' + payload.notification_id + ']');
|
||||||
|
var $btnNotificationAction = '#btn-notification-action';
|
||||||
|
|
||||||
|
// wire up "x" button to delete notification
|
||||||
|
$notification.find('#img-delete-notification').click(deleteNotificationHandler);
|
||||||
|
|
||||||
|
// customize action buttons based on notification type
|
||||||
|
if (type === context.JK.MessageType.FRIEND_REQUEST) {
|
||||||
|
var $action_btn = $notification.find($btnNotificationAction);
|
||||||
|
$action_btn.text('ACCEPT');
|
||||||
|
$action_btn.click(function() {
|
||||||
|
acceptFriendRequest(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type === context.JK.MessageType.FRIEND_REQUEST_ACCEPTED) {
|
||||||
|
$notification.find('#div-actions').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type === context.JK.MessageType.NEW_USER_FOLLOWER || type === context.JK.MessageType.NEW_BAND_FOLLOWER) {
|
||||||
|
$notification.find('#div-actions').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type === context.JK.MessageType.SESSION_INVITATION) {
|
||||||
|
var $action_btn = $notification.find($btnNotificationAction);
|
||||||
|
$action_btn.text('JOIN');
|
||||||
|
$action_btn.click(function() {
|
||||||
|
openTerms(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type === context.JK.MessageType.JOIN_REQUEST) {
|
||||||
|
var $action_btn = $notification.find($btnNotificationAction);
|
||||||
|
$action_btn.text('APPROVE');
|
||||||
|
$action_btn.click(function() {
|
||||||
|
approveJoinRequest(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type === context.JK.MessageType.JOIN_REQUEST_APPROVED) {
|
||||||
|
var $action_btn = $notification.find($btnNotificationAction);
|
||||||
|
$action_btn.text('JOIN');
|
||||||
|
$action_btn.click(function() {
|
||||||
|
openTerms(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type === context.JK.MessageType.JOIN_REQUEST_REJECTED) {
|
||||||
|
$notification.find('#div-actions').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type === context.JK.MessageType.MUSICIAN_SESSION_JOIN || type === context.JK.MessageType.BAND_SESSION_JOIN) {
|
||||||
|
|
||||||
|
var actionText = '';
|
||||||
|
var callback;
|
||||||
|
if (context.JK.currentUserMusician) {
|
||||||
|
// user is MUSICIAN; musician_access = TRUE
|
||||||
|
if (payload.musician_access) {
|
||||||
|
actionText = "JOIN";
|
||||||
|
callback = joinSession;
|
||||||
|
}
|
||||||
|
// user is MUSICIAN; fan_access = TRUE
|
||||||
|
else if (payload.fan_access) {
|
||||||
|
actionText = "LISTEN";
|
||||||
|
callback = listenToSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// user is FAN; fan_access = TRUE
|
||||||
|
if (payload.fan_access) {
|
||||||
|
actionText = "LISTEN";
|
||||||
|
callback = listenToSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var $action_btn = $notification.find($btnNotificationAction);
|
||||||
|
$action_btn.text(actionText);
|
||||||
|
$action_btn.click(function() {
|
||||||
|
callback(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type === context.JK.MessageType.MUSICIAN_RECORDING_SAVED || type === context.JK.MessageType.BAND_RECORDING_SAVED) {
|
||||||
|
var $action_btn = $notification.find($btnNotificationAction);
|
||||||
|
$action_btn.text('LISTEN');
|
||||||
|
$action_btn.click(function() {
|
||||||
|
listenToRecording(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type === context.JK.MessageType.RECORDING_MASTER_MIX_COMPLETE) {
|
||||||
|
$notification.find('#div-actions').hide();
|
||||||
|
context.jamClient.OnDownloadAvailable(); // poke backend, letting it know a download is available
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (type === context.JK.MessageType.BAND_INVITATION) {
|
||||||
|
var $action_btn = $notification.find($btnNotificationAction);
|
||||||
|
$action_btn.text('ACCEPT');
|
||||||
|
$action_btn.click(function() {
|
||||||
|
acceptBandInvitation(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (type === context.JK.MessageType.BAND_INVITATION_ACCEPTED) {
|
||||||
|
$notification.find('#div-actions').hide();
|
||||||
|
}
|
||||||
|
else if (type === context.JK.MessageType.TEXT_MESSAGE) {
|
||||||
|
var $action_btn = $notification.find($btnNotificationAction);
|
||||||
|
$action_btn.text('REPLY');
|
||||||
|
$action_btn.click(function() {
|
||||||
|
var userId = $notification.find('.more-text-available').attr('data-sender-id');
|
||||||
|
app.layout.showDialog('text-message', { d1: userId });
|
||||||
|
});
|
||||||
|
|
||||||
|
var moreTextLink = $notification.find('.more-text-available');
|
||||||
|
var textMessage = $notification.find('.text-message');
|
||||||
|
var clipped_msg = textMessage.attr('data-is-clipped') === 'true';
|
||||||
|
|
||||||
|
if(clipped_msg) {
|
||||||
|
moreTextLink.text('more').show();
|
||||||
|
moreTextLink.click(function(e) {
|
||||||
|
var userId = $(this).attr('data-sender-id');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
moreTextLink.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function acceptBandInvitation(args) {
|
||||||
|
rest.updateBandInvitation(
|
||||||
|
args.band_id,
|
||||||
|
args.band_invitation_id,
|
||||||
|
true
|
||||||
|
).done(function(response) {
|
||||||
|
deleteNotification(args.notification_id); // delete notification corresponding to this friend request
|
||||||
|
}).error(app.ajaxError);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function deleteNotification(notificationId) {
|
||||||
|
var url = "/api/users/" + context.JK.currentUserId + "/notifications/" + notificationId;
|
||||||
|
$.ajax({
|
||||||
|
type: "DELETE",
|
||||||
|
dataType: "json",
|
||||||
|
contentType: 'application/json',
|
||||||
|
url: url,
|
||||||
|
processData: false,
|
||||||
|
success: function(response) {
|
||||||
|
$('li[notification-id=' + notificationId + ']').hide();
|
||||||
|
//decrementNotificationCount();
|
||||||
|
},
|
||||||
|
error: app.ajaxError
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function listenToSession(args) {
|
||||||
|
deleteNotification(args.notification_id);
|
||||||
|
context.JK.popExternalLink('/sessions/' + args.session_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********** TODO: THE NEXT 3 FUNCTIONS ARE COPIED FROM sessionList.js. REFACTOR TO COMMON PLACE. *************/
|
||||||
|
function joinSession(args) {
|
||||||
|
// NOTE: invited musicians get their own notification, so no need to check if user has invitation here
|
||||||
|
// like other places because an invited user would never get this notification
|
||||||
|
if (args.musician_access) {
|
||||||
|
if (args.approval_required) {
|
||||||
|
openAlert(args.session_id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
openTerms(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deleteNotification(args.notification_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function registerJoinRequestApproved() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST_APPROVED, function(header, payload) {
|
||||||
|
logger.debug("Handling JOIN_REQUEST_APPROVED msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "Join Request Approved",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
}, {
|
||||||
|
"ok_text": "JOIN SESSION",
|
||||||
|
"ok_callback": openTerms,
|
||||||
|
"ok_callback_args": { "session_id": payload.session_id, "notification_id": payload.notification_id }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerJoinRequestRejected() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST_REJECTED, function(header, payload) {
|
||||||
|
logger.debug("Handling JOIN_REQUEST_REJECTED msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "Join Request Rejected",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function registerJoinRequest() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST, function(header, payload) {
|
||||||
|
logger.debug("Handling JOIN_REQUEST msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "New Join Request",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
}, {
|
||||||
|
"ok_text": "APPROVE",
|
||||||
|
"ok_callback": approveJoinRequest,
|
||||||
|
"ok_callback_args": { "join_request_id": payload.join_request_id, "notification_id": payload.notification_id },
|
||||||
|
"cancel_text": "REJECT",
|
||||||
|
"cancel_callback": rejectJoinRequest,
|
||||||
|
"cancel_callback_args": { "join_request_id": payload.join_request_id, "notification_id": payload.notification_id }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function registerFriendRequestAccepted() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_REQUEST_ACCEPTED, function(header, payload) {
|
||||||
|
logger.debug("Handling FRIEND_REQUEST_ACCEPTED msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
initializeFriendsPanel();
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "Friend Request Accepted",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerNewUserFollower() {
|
||||||
|
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.NEW_USER_FOLLOWER, function(header, payload) {
|
||||||
|
logger.debug("Handling NEW_USER_FOLLOWER msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "New Follower",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function registerNewBandFollower() {
|
||||||
|
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.NEW_BAND_FOLLOWER, function(header, payload) {
|
||||||
|
logger.debug("Handling NEW_BAND_FOLLOWER msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "New Band Follower",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function registerFriendRequest() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_REQUEST, function(header, payload) {
|
||||||
|
logger.debug("Handling FRIEND_REQUEST msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "New Friend Request",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
}, {
|
||||||
|
"ok_text": "ACCEPT",
|
||||||
|
"ok_callback": acceptFriendRequest,
|
||||||
|
"ok_callback_args": { "friend_request_id": payload.friend_request_id, "notification_id": payload.notification_id }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function acceptFriendRequest(args) {
|
||||||
|
|
||||||
|
rest.acceptFriendRequest({
|
||||||
|
status: 'accept',
|
||||||
|
friend_request_id: args.friend_request_id
|
||||||
|
}).done(function(response) {
|
||||||
|
deleteNotification(args.notification_id); // delete notification corresponding to this friend request
|
||||||
|
initializeFriendsPanel(); // refresh friends panel when request is accepted
|
||||||
|
}).error(app.ajaxError);
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerSessionEnded() {
|
||||||
|
// TODO: this should clean up all notifications related to this session
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_ENDED, function(header, payload) {
|
||||||
|
logger.debug("Handling SESSION_ENDED msg " + JSON.stringify(payload));
|
||||||
|
deleteSessionNotifications(payload.session_id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove all notifications for this session
|
||||||
|
function deleteSessionNotifications(sessionId) {
|
||||||
|
$('li[session-id=' + sessionId + ']').hide();
|
||||||
|
//decrementNotificationCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerSessionInvitation() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_INVITATION, function(header, payload) {
|
||||||
|
logger.debug("Handling SESSION_INVITATION msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
var participants = [];
|
||||||
|
rest.getSession(payload.session_id).done(function(response) {
|
||||||
|
$.each(response.participants, function(index, val) {
|
||||||
|
participants.push({"photo_url": context.JK.resolveAvatarUrl(val.user.photo_url), "name": val.user.name});
|
||||||
|
});
|
||||||
|
|
||||||
|
var participantHtml = "You have been invited to join a session with: <br/><br/>";
|
||||||
|
participantHtml += "<table><tbody>";
|
||||||
|
|
||||||
|
$.each(participants, function(index, val) {
|
||||||
|
if (index < 4) {
|
||||||
|
participantHtml += "<tr><td><img class='avatar-small' src='" + context.JK.resolveAvatarUrl(val.photo_url) + "' /></td><td>" + val.name + "</td></tr>";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
participantHtml += "</tbody></table>";
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "Session Invitation",
|
||||||
|
"text": participantHtml
|
||||||
|
}, {
|
||||||
|
"ok_text": "JOIN SESSION",
|
||||||
|
"ok_callback": openTerms,
|
||||||
|
"ok_callback_args": { "session_id": payload.session_id, "notification_id": payload.notification_id }
|
||||||
|
});
|
||||||
|
}).error(app.ajaxError);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function registerMusicianSessionJoin() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, function(header, payload) {
|
||||||
|
logger.debug("Handling MUSICIAN_SESSION_JOIN msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
var okText = '';
|
||||||
|
var showNotification = false;
|
||||||
|
var callback;
|
||||||
|
if (context.JK.currentUserMusician) {
|
||||||
|
// user is MUSICIAN; musician_access = TRUE
|
||||||
|
if (payload.musician_access) {
|
||||||
|
showNotification = true;
|
||||||
|
okText = "JOIN";
|
||||||
|
callback = joinSession;
|
||||||
|
}
|
||||||
|
// user is MUSICIAN; fan_access = TRUE
|
||||||
|
else if (payload.fan_access) {
|
||||||
|
showNotification = true;
|
||||||
|
okText = "LISTEN";
|
||||||
|
callback = listenToSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// user is FAN; fan_access = TRUE
|
||||||
|
if (payload.fan_access) {
|
||||||
|
showNotification = true;
|
||||||
|
okText = "LISTEN";
|
||||||
|
callback = listenToSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showNotification) {
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "Musician Joined Session",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
}, {
|
||||||
|
"ok_text": okText,
|
||||||
|
"ok_callback": callback,
|
||||||
|
"ok_callback_args": {
|
||||||
|
"session_id": payload.session_id,
|
||||||
|
"fan_access": payload.fan_access,
|
||||||
|
"musician_access": payload.musician_access,
|
||||||
|
"approval_required": payload.approval_required,
|
||||||
|
"notification_id": payload.notification_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function registerBandSessionJoin() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_SESSION_JOIN, function(header, payload) {
|
||||||
|
logger.debug("Handling BAND_SESSION_JOIN msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
var okText = '';
|
||||||
|
var showNotification = false;
|
||||||
|
var callback;
|
||||||
|
if (context.JK.currentUserMusician) {
|
||||||
|
// user is MUSICIAN; musician_access = TRUE
|
||||||
|
if (payload.musician_access) {
|
||||||
|
showNotification = true;
|
||||||
|
okText = "JOIN";
|
||||||
|
callback = joinSession;
|
||||||
|
}
|
||||||
|
// user is MUSICIAN; fan_access = TRUE
|
||||||
|
else if (payload.fan_access) {
|
||||||
|
showNotification = true;
|
||||||
|
okText = "LISTEN";
|
||||||
|
callback = listenToSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// user is FAN; fan_access = TRUE
|
||||||
|
if (payload.fan_access) {
|
||||||
|
showNotification = true;
|
||||||
|
okText = "LISTEN";
|
||||||
|
callback = listenToSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showNotification) {
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "Band Joined Session",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
}, {
|
||||||
|
"ok_text": "LISTEN",
|
||||||
|
"ok_callback": callback,
|
||||||
|
"ok_callback_args": {
|
||||||
|
"session_id": payload.session_id,
|
||||||
|
"fan_access": payload.fan_access,
|
||||||
|
"musician_access": payload.musician_access,
|
||||||
|
"approval_required": payload.approval_required,
|
||||||
|
"notification_id": payload.notification_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function registerMusicianRecordingSaved() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_RECORDING_SAVED, function(header, payload) {
|
||||||
|
logger.debug("Handling MUSICIAN_RECORDING_SAVED msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "Musician Recording Saved",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
}, {
|
||||||
|
"ok_text": "LISTEN",
|
||||||
|
"ok_callback": listenToRecording,
|
||||||
|
"ok_callback_args": {
|
||||||
|
"recording_id": payload.recording_id,
|
||||||
|
"notification_id": payload.notification_id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerBandRecordingSaved() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_RECORDING_SAVED, function(header, payload) {
|
||||||
|
logger.debug("Handling BAND_RECORDING_SAVED msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "Band Recording Saved",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
}, {
|
||||||
|
"ok_text": "LISTEN",
|
||||||
|
"ok_callback": listenToRecording,
|
||||||
|
"ok_callback_args": {
|
||||||
|
"recording_id": payload.recording_id,
|
||||||
|
"notification_id": payload.notification_id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function registerRecordingMasterMixComplete() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.RECORDING_MASTER_MIX_COMPLETE, function(header, payload) {
|
||||||
|
logger.debug("Handling RECORDING_MASTER_MIX_COMPLETE msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "Recording Master Mix Complete",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
}, {
|
||||||
|
"ok_text": "SHARE",
|
||||||
|
"ok_callback": shareRecording,
|
||||||
|
"ok_callback_args": {
|
||||||
|
"recording_id": payload.recording_id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function shareRecording(args) {
|
||||||
|
var recordingId = args.recording_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerBandInvitation() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_INVITATION, function(header, payload) {
|
||||||
|
logger.debug("Handling BAND_INVITATION msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "Band Invitation",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
}, {
|
||||||
|
"ok_text": "ACCEPT",
|
||||||
|
"ok_callback": acceptBandInvitation,
|
||||||
|
"ok_callback_args": {
|
||||||
|
"band_invitation_id": payload.band_invitation_id,
|
||||||
|
"band_id": payload.band_id,
|
||||||
|
"notification_id": payload.notification_id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function registerTextMessage() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.TEXT_MESSAGE, function(header, payload) {
|
||||||
|
logger.debug("Handling TEXT_MESSAGE msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
textMessageDialog.messageReceived(payload);
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerBandInvitationAccepted() {
|
||||||
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_INVITATION_ACCEPTED, function(header, payload) {
|
||||||
|
logger.debug("Handling BAND_INVITATION_ACCEPTED msg " + JSON.stringify(payload));
|
||||||
|
|
||||||
|
handleNotification(payload, header.type);
|
||||||
|
|
||||||
|
app.notify({
|
||||||
|
"title": "Band Invitation Accepted",
|
||||||
|
"text": payload.msg,
|
||||||
|
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// one important limitation; if the user is focused on an iframe, this will be false
|
||||||
|
// however, if they are doing something with Facebook or the photo picker, this may actually still be desirable
|
||||||
|
function userCanSeeNotifications(payload) {
|
||||||
|
return document.hasFocus() && !app.layout.dialogObscuredNotification(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
// default handler for incoming notification
|
||||||
|
function handleNotification(payload, type) {
|
||||||
|
|
||||||
|
// on a load of notifications, it is possible to load a very new notification,
|
||||||
|
// and get a websocket notification right after for that same notification,
|
||||||
|
// so we need to protect against such duplicates
|
||||||
|
if($list.find('li[notification-id="' + payload.notification_id + '"]').length > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add notification to sidebar
|
||||||
|
var template = $notificationTemplate.html();
|
||||||
|
var notificationHtml = context.JK.fillTemplate(template, {
|
||||||
|
notificationId: payload.notification_id,
|
||||||
|
sessionId: payload.session_id,
|
||||||
|
avatar_url: context.JK.resolveAvatarUrl(payload.photo_url),
|
||||||
|
text: payload.msg instanceof jQuery ? payload.msg.html() : payload.msg ,
|
||||||
|
date: $.timeago(payload.created_at)
|
||||||
|
});
|
||||||
|
|
||||||
|
$list.prepend(notificationHtml);
|
||||||
|
|
||||||
|
onNotificationOccurred(payload);
|
||||||
|
|
||||||
|
initializeActions(payload, type);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function onCreateJoinRequest(sessionId) {
|
||||||
|
var joinRequest = {};
|
||||||
|
joinRequest.music_session = sessionId;
|
||||||
|
joinRequest.user = context.JK.currentUserId;
|
||||||
|
rest.createJoinRequest(joinRequest)
|
||||||
|
.done(function(response) {
|
||||||
|
|
||||||
|
}).error(context.JK.app.ajaxError);
|
||||||
|
|
||||||
|
context.JK.app.layout.closeDialog('alert');
|
||||||
|
}
|
||||||
|
|
||||||
|
function approveJoinRequest(args) {
|
||||||
|
rest.updateJoinRequest(args.join_request_id, true)
|
||||||
|
.done(function(response) {
|
||||||
|
deleteNotification(args.notification_id);
|
||||||
|
}).error(app.ajaxError);
|
||||||
|
}
|
||||||
|
|
||||||
|
function rejectJoinRequest(args) {
|
||||||
|
rest.updateJoinRequest(args.join_request_id, false)
|
||||||
|
.done(function(response) {
|
||||||
|
deleteNotification(args.notification_id);
|
||||||
|
}).error(app.ajaxError);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openTerms(args) {
|
||||||
|
var termsDialog = new context.JK.TermsDialog(app, args, onTermsAccepted);
|
||||||
|
termsDialog.initialize();
|
||||||
|
app.layout.showDialog('terms');
|
||||||
|
}
|
||||||
|
|
||||||
|
function onTermsAccepted(args) {
|
||||||
|
deleteNotification(args.notification_id);
|
||||||
|
context.location = '/client#/session/' + args.session_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function openAlert(sessionId) {
|
||||||
|
var alertDialog = new context.JK.AlertDialog(context.JK.app, "YES",
|
||||||
|
"You must be approved to join this session. Would you like to send a request to join?",
|
||||||
|
sessionId, onCreateJoinRequest);
|
||||||
|
|
||||||
|
alertDialog.initialize();
|
||||||
|
context.JK.app.layout.showDialog('alert');
|
||||||
|
}
|
||||||
|
|
||||||
|
function listenToRecording(args) {
|
||||||
|
deleteNotification(args.notification_id);
|
||||||
|
context.JK.popExternalLink('/recordings/' + args.recording_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteNotificationHandler(evt) {
|
||||||
|
evt.stopPropagation();
|
||||||
|
var notificationId = $(this).attr('notification-id');
|
||||||
|
deleteNotification(notificationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize(sidebar, textMessageDialogInstance) {
|
||||||
|
textMessageDialog = textMessageDialogInstance;
|
||||||
$panel = $('[layout-id="panelNotifications"]');
|
$panel = $('[layout-id="panelNotifications"]');
|
||||||
$expanded = $panel.find('.panel.expanded');
|
$expanded = $panel.find('.panel.expanded');
|
||||||
|
$contents = $panel.find('.panelcontents');
|
||||||
$count = $panel.find('#sidebar-notification-count');
|
$count = $panel.find('#sidebar-notification-count');
|
||||||
|
$list = $panel.find('#sidebar-notification-list');
|
||||||
|
$notificationTemplate = $('#template-notification-panel');
|
||||||
if($panel.length == 0) throw "notifications panel not found"
|
if($panel.length == 0) throw "notifications panel not found"
|
||||||
if($expanded.length == 0) throw "notifications expanded content not found"
|
if($expanded.length == 0) throw "notifications expanded content not found"
|
||||||
|
if($contents.length == 0) throw "notifications contents not found"
|
||||||
if($count.length == 0) throw "notifications count element not found";
|
if($count.length == 0) throw "notifications count element not found";
|
||||||
|
if($list.length == 0) throw "notification list element not found";
|
||||||
|
if($notificationTemplate.length == 0) throw "notification template not found";
|
||||||
|
|
||||||
events();
|
events();
|
||||||
|
|
||||||
populate();
|
populate();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.initiliaze = initialize;
|
this.initialize = initialize;
|
||||||
this.onNotificationOccurred = onNotificationOccurred;
|
this.onNotificationOccurred = onNotificationOccurred;
|
||||||
};
|
};
|
||||||
})(window, jQuery);
|
})(window, jQuery);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
var invitationDialog = null;
|
var invitationDialog = null;
|
||||||
var textMessageDialog = null;
|
var textMessageDialog = null;
|
||||||
var notificationPanel = null;
|
var notificationPanel = null;
|
||||||
|
var me = null;
|
||||||
|
|
||||||
function initializeSearchPanel() {
|
function initializeSearchPanel() {
|
||||||
$('#search_text_type').change(function() {
|
$('#search_text_type').change(function() {
|
||||||
|
|
@ -118,188 +119,7 @@
|
||||||
|
|
||||||
function initializeNotificationsPanel() {
|
function initializeNotificationsPanel() {
|
||||||
notificationPanel = new context.JK.NotificationPanel(app);
|
notificationPanel = new context.JK.NotificationPanel(app);
|
||||||
notificationPanel.initialize();
|
notificationPanel.initialize(me, textMessageDialog);
|
||||||
}
|
|
||||||
|
|
||||||
function updateNotificationList(response) {
|
|
||||||
$('#sidebar-notification-list').empty();
|
|
||||||
|
|
||||||
$.each(response, function(index, val) {
|
|
||||||
|
|
||||||
if(val.description == 'TEXT_MESSAGE') {
|
|
||||||
val.formatted_msg = textMessageDialog.formatTextMessage(val.message.substring(0, 200), val.source_user_id, val.source_user.name, val.message.length > 200).html();
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill in template for Connect pre-click
|
|
||||||
var template = $('#template-notification-panel').html();
|
|
||||||
var notificationHtml = context.JK.fillTemplate(template, {
|
|
||||||
notificationId: val.notification_id,
|
|
||||||
sessionId: val.session_id,
|
|
||||||
avatar_url: context.JK.resolveAvatarUrl(val.photo_url),
|
|
||||||
text: val.formatted_msg,
|
|
||||||
date: $.timeago(val.created_at)
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#sidebar-notification-list').append(notificationHtml);
|
|
||||||
|
|
||||||
// val.description contains the notification record's description value from the DB (i.e., type)
|
|
||||||
initializeActions(val, val.description);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function initializeActions(payload, type) {
|
|
||||||
|
|
||||||
var $notification = $('li[notification-id=' + payload.notification_id + ']');
|
|
||||||
var $btnNotificationAction = '#btn-notification-action';
|
|
||||||
|
|
||||||
// wire up "x" button to delete notification
|
|
||||||
$notification.find('#img-delete-notification').click(deleteNotificationHandler);
|
|
||||||
|
|
||||||
// customize action buttons based on notification type
|
|
||||||
if (type === context.JK.MessageType.FRIEND_REQUEST) {
|
|
||||||
var $action_btn = $notification.find($btnNotificationAction);
|
|
||||||
$action_btn.text('ACCEPT');
|
|
||||||
$action_btn.click(function() {
|
|
||||||
acceptFriendRequest(payload);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (type === context.JK.MessageType.FRIEND_REQUEST_ACCEPTED) {
|
|
||||||
$notification.find('#div-actions').hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (type === context.JK.MessageType.NEW_USER_FOLLOWER || type === context.JK.MessageType.NEW_BAND_FOLLOWER) {
|
|
||||||
$notification.find('#div-actions').hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (type === context.JK.MessageType.SESSION_INVITATION) {
|
|
||||||
var $action_btn = $notification.find($btnNotificationAction);
|
|
||||||
$action_btn.text('JOIN');
|
|
||||||
$action_btn.click(function() {
|
|
||||||
openTerms(payload);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (type === context.JK.MessageType.JOIN_REQUEST) {
|
|
||||||
var $action_btn = $notification.find($btnNotificationAction);
|
|
||||||
$action_btn.text('APPROVE');
|
|
||||||
$action_btn.click(function() {
|
|
||||||
approveJoinRequest(payload);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (type === context.JK.MessageType.JOIN_REQUEST_APPROVED) {
|
|
||||||
var $action_btn = $notification.find($btnNotificationAction);
|
|
||||||
$action_btn.text('JOIN');
|
|
||||||
$action_btn.click(function() {
|
|
||||||
openTerms(payload);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (type === context.JK.MessageType.JOIN_REQUEST_REJECTED) {
|
|
||||||
$notification.find('#div-actions').hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (type === context.JK.MessageType.MUSICIAN_SESSION_JOIN || type === context.JK.MessageType.BAND_SESSION_JOIN) {
|
|
||||||
|
|
||||||
var actionText = '';
|
|
||||||
var callback;
|
|
||||||
if (context.JK.currentUserMusician) {
|
|
||||||
// user is MUSICIAN; musician_access = TRUE
|
|
||||||
if (payload.musician_access) {
|
|
||||||
actionText = "JOIN";
|
|
||||||
callback = joinSession;
|
|
||||||
}
|
|
||||||
// user is MUSICIAN; fan_access = TRUE
|
|
||||||
else if (payload.fan_access) {
|
|
||||||
actionText = "LISTEN";
|
|
||||||
callback = listenToSession;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// user is FAN; fan_access = TRUE
|
|
||||||
if (payload.fan_access) {
|
|
||||||
actionText = "LISTEN";
|
|
||||||
callback = listenToSession;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var $action_btn = $notification.find($btnNotificationAction);
|
|
||||||
$action_btn.text(actionText);
|
|
||||||
$action_btn.click(function() {
|
|
||||||
callback(payload);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (type === context.JK.MessageType.MUSICIAN_RECORDING_SAVED || type === context.JK.MessageType.BAND_RECORDING_SAVED) {
|
|
||||||
var $action_btn = $notification.find($btnNotificationAction);
|
|
||||||
$action_btn.text('LISTEN');
|
|
||||||
$action_btn.click(function() {
|
|
||||||
listenToRecording(payload);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (type === context.JK.MessageType.RECORDING_MASTER_MIX_COMPLETE) {
|
|
||||||
$notification.find('#div-actions').hide();
|
|
||||||
context.jamClient.OnDownloadAvailable(); // poke backend, letting it know a download is available
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (type === context.JK.MessageType.BAND_INVITATION) {
|
|
||||||
var $action_btn = $notification.find($btnNotificationAction);
|
|
||||||
$action_btn.text('ACCEPT');
|
|
||||||
$action_btn.click(function() {
|
|
||||||
acceptBandInvitation(payload);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (type === context.JK.MessageType.BAND_INVITATION_ACCEPTED) {
|
|
||||||
$notification.find('#div-actions').hide();
|
|
||||||
}
|
|
||||||
else if (type === context.JK.MessageType.TEXT_MESSAGE) {
|
|
||||||
var $action_btn = $notification.find($btnNotificationAction);
|
|
||||||
$action_btn.text('REPLY');
|
|
||||||
$action_btn.click(function() {
|
|
||||||
var userId = $notification.find('.more-text-available').attr('data-sender-id');
|
|
||||||
app.layout.showDialog('text-message', { d1: userId });
|
|
||||||
});
|
|
||||||
|
|
||||||
var moreTextLink = $notification.find('.more-text-available');
|
|
||||||
var textMessage = $notification.find('.text-message');
|
|
||||||
var clipped_msg = textMessage.attr('data-is-clipped') === 'true';
|
|
||||||
|
|
||||||
if(clipped_msg) {
|
|
||||||
moreTextLink.text('more').show();
|
|
||||||
moreTextLink.click(function(e) {
|
|
||||||
var userId = $(this).attr('data-sender-id');
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
moreTextLink.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteNotificationHandler(evt) {
|
|
||||||
evt.stopPropagation();
|
|
||||||
var notificationId = $(this).attr('notification-id');
|
|
||||||
deleteNotification(notificationId);
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteNotification(notificationId) {
|
|
||||||
var url = "/api/users/" + context.JK.currentUserId + "/notifications/" + notificationId;
|
|
||||||
$.ajax({
|
|
||||||
type: "DELETE",
|
|
||||||
dataType: "json",
|
|
||||||
contentType: 'application/json',
|
|
||||||
url: url,
|
|
||||||
processData: false,
|
|
||||||
success: function(response) {
|
|
||||||
$('li[notification-id=' + notificationId + ']').hide();
|
|
||||||
decrementNotificationCount();
|
|
||||||
},
|
|
||||||
error: app.ajaxError
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeChatPanel() {
|
function initializeChatPanel() {
|
||||||
|
|
@ -348,61 +168,6 @@
|
||||||
$('#sidebar-search-results').height('0px');
|
$('#sidebar-search-results').height('0px');
|
||||||
}
|
}
|
||||||
|
|
||||||
function decrementNotificationCount() {
|
|
||||||
/**
|
|
||||||
var count = parseInt($('#sidebar-notification-count').html());
|
|
||||||
if (count === 0) {
|
|
||||||
$('#sidebar-notification-count').html(0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$('#sidebar-notification-count').html(count - 1);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// one important limitation; if the user is focused on an iframe, this will be false
|
|
||||||
// however, if they are doing something with Facebook or the photo picker, this may actually still be desirable
|
|
||||||
function userCanSeeNotifications() {
|
|
||||||
return document.hasFocus() || app.layout.isDialogShowing();
|
|
||||||
}
|
|
||||||
|
|
||||||
// default handler for incoming notification
|
|
||||||
function handleNotification(payload, type) {
|
|
||||||
|
|
||||||
// on a load of notifications, it is possible to load a very new notification,
|
|
||||||
// and get a websocket notification right after for that same notification,
|
|
||||||
// so we need to protect against such duplicates
|
|
||||||
if($('#sidebar-notification-list').find('li[notification-id="' + payload.notification_id + '"]').length > 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// increment displayed notification count
|
|
||||||
incrementNotificationCount();
|
|
||||||
|
|
||||||
// add notification to sidebar
|
|
||||||
var template = $("#template-notification-panel").html();
|
|
||||||
var notificationHtml = context.JK.fillTemplate(template, {
|
|
||||||
notificationId: payload.notification_id,
|
|
||||||
sessionId: payload.session_id,
|
|
||||||
avatar_url: context.JK.resolveAvatarUrl(payload.photo_url),
|
|
||||||
text: payload.msg instanceof jQuery ? payload.msg.html() : payload.msg ,
|
|
||||||
date: $.timeago(payload.created_at)
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#sidebar-notification-list').prepend(notificationHtml);
|
|
||||||
|
|
||||||
if(userCanSeeNotifications()) {
|
|
||||||
app.updateNotificationSeen(payload.created_at);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
initializeActions(payload, type);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var delay = (function(){
|
var delay = (function(){
|
||||||
var timer = 0;
|
var timer = 0;
|
||||||
return function(callback, ms) {
|
return function(callback, ms) {
|
||||||
|
|
@ -460,32 +225,14 @@
|
||||||
|
|
||||||
// friend notifications
|
// friend notifications
|
||||||
registerFriendUpdate();
|
registerFriendUpdate();
|
||||||
registerFriendRequest();
|
|
||||||
registerFriendRequestAccepted();
|
|
||||||
registerNewUserFollower();
|
|
||||||
registerNewBandFollower();
|
|
||||||
|
|
||||||
// session invitations
|
// session invitations
|
||||||
registerSessionInvitation();
|
|
||||||
registerSessionEnded();
|
|
||||||
registerJoinRequest();
|
|
||||||
registerJoinRequestApproved();
|
|
||||||
registerJoinRequestRejected();
|
|
||||||
registerSessionJoin();
|
registerSessionJoin();
|
||||||
registerSessionDepart();
|
registerSessionDepart();
|
||||||
registerMusicianSessionJoin();
|
|
||||||
registerBandSessionJoin();
|
|
||||||
|
|
||||||
// recording notifications
|
// recording notifications
|
||||||
registerMusicianRecordingSaved();
|
|
||||||
registerBandRecordingSaved();
|
|
||||||
registerRecordingStarted();
|
registerRecordingStarted();
|
||||||
registerRecordingEnded();
|
registerRecordingEnded();
|
||||||
registerRecordingMasterMixComplete();
|
|
||||||
|
|
||||||
// band notifications
|
|
||||||
registerBandInvitation();
|
|
||||||
registerBandInvitationAccepted();
|
|
||||||
|
|
||||||
// broadcast notifications
|
// broadcast notifications
|
||||||
registerSourceUpRequested();
|
registerSourceUpRequested();
|
||||||
|
|
@ -493,9 +240,6 @@
|
||||||
registerSourceUp();
|
registerSourceUp();
|
||||||
registerSourceDown();
|
registerSourceDown();
|
||||||
|
|
||||||
// register text messages
|
|
||||||
registerTextMessage();
|
|
||||||
|
|
||||||
// watch for Invite More Users events
|
// watch for Invite More Users events
|
||||||
$('#sidebar-div .btn-email-invitation').click(function() {
|
$('#sidebar-div .btn-email-invitation').click(function() {
|
||||||
invitationDialog.showEmailDialog();
|
invitationDialog.showEmailDialog();
|
||||||
|
|
@ -529,210 +273,6 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerFriendRequest() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_REQUEST, function(header, payload) {
|
|
||||||
logger.debug("Handling FRIEND_REQUEST msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "New Friend Request",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
}, {
|
|
||||||
"ok_text": "ACCEPT",
|
|
||||||
"ok_callback": acceptFriendRequest,
|
|
||||||
"ok_callback_args": { "friend_request_id": payload.friend_request_id, "notification_id": payload.notification_id }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function acceptFriendRequest(args) {
|
|
||||||
|
|
||||||
rest.acceptFriendRequest({
|
|
||||||
status: 'accept',
|
|
||||||
friend_request_id: args.friend_request_id
|
|
||||||
}).done(function(response) {
|
|
||||||
deleteNotification(args.notification_id); // delete notification corresponding to this friend request
|
|
||||||
initializeFriendsPanel(); // refresh friends panel when request is accepted
|
|
||||||
}).error(app.ajaxError);
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerFriendRequestAccepted() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.FRIEND_REQUEST_ACCEPTED, function(header, payload) {
|
|
||||||
logger.debug("Handling FRIEND_REQUEST_ACCEPTED msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
initializeFriendsPanel();
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "Friend Request Accepted",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerNewUserFollower() {
|
|
||||||
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.NEW_USER_FOLLOWER, function(header, payload) {
|
|
||||||
logger.debug("Handling NEW_USER_FOLLOWER msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "New Follower",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerNewBandFollower() {
|
|
||||||
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.NEW_BAND_FOLLOWER, function(header, payload) {
|
|
||||||
logger.debug("Handling NEW_BAND_FOLLOWER msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "New Band Follower",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerSessionInvitation() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_INVITATION, function(header, payload) {
|
|
||||||
logger.debug("Handling SESSION_INVITATION msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
var participants = [];
|
|
||||||
rest.getSession(payload.session_id).done(function(response) {
|
|
||||||
$.each(response.participants, function(index, val) {
|
|
||||||
participants.push({"photo_url": context.JK.resolveAvatarUrl(val.user.photo_url), "name": val.user.name});
|
|
||||||
});
|
|
||||||
|
|
||||||
var participantHtml = "You have been invited to join a session with: <br/><br/>";
|
|
||||||
participantHtml += "<table><tbody>";
|
|
||||||
|
|
||||||
$.each(participants, function(index, val) {
|
|
||||||
if (index < 4) {
|
|
||||||
participantHtml += "<tr><td><img class='avatar-small' src='" + context.JK.resolveAvatarUrl(val.photo_url) + "' /></td><td>" + val.name + "</td></tr>";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
participantHtml += "</tbody></table>";
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "Session Invitation",
|
|
||||||
"text": participantHtml
|
|
||||||
}, {
|
|
||||||
"ok_text": "JOIN SESSION",
|
|
||||||
"ok_callback": openTerms,
|
|
||||||
"ok_callback_args": { "session_id": payload.session_id, "notification_id": payload.notification_id }
|
|
||||||
});
|
|
||||||
}).error(app.ajaxError);
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function openTerms(args) {
|
|
||||||
var termsDialog = new context.JK.TermsDialog(app, args, onTermsAccepted);
|
|
||||||
termsDialog.initialize();
|
|
||||||
app.layout.showDialog('terms');
|
|
||||||
}
|
|
||||||
|
|
||||||
function onTermsAccepted(args) {
|
|
||||||
deleteNotification(args.notification_id);
|
|
||||||
context.location = '/client#/session/' + args.session_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerSessionEnded() {
|
|
||||||
// TODO: this should clean up all notifications related to this session
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_ENDED, function(header, payload) {
|
|
||||||
logger.debug("Handling SESSION_ENDED msg " + JSON.stringify(payload));
|
|
||||||
deleteSessionNotifications(payload.session_id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove all notifications for this session
|
|
||||||
function deleteSessionNotifications(sessionId) {
|
|
||||||
$('li[session-id=' + sessionId + ']').hide();
|
|
||||||
decrementNotificationCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerJoinRequest() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST, function(header, payload) {
|
|
||||||
logger.debug("Handling JOIN_REQUEST msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "New Join Request",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
}, {
|
|
||||||
"ok_text": "APPROVE",
|
|
||||||
"ok_callback": approveJoinRequest,
|
|
||||||
"ok_callback_args": { "join_request_id": payload.join_request_id, "notification_id": payload.notification_id },
|
|
||||||
"cancel_text": "REJECT",
|
|
||||||
"cancel_callback": rejectJoinRequest,
|
|
||||||
"cancel_callback_args": { "join_request_id": payload.join_request_id, "notification_id": payload.notification_id }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function approveJoinRequest(args) {
|
|
||||||
rest.updateJoinRequest(args.join_request_id, true)
|
|
||||||
.done(function(response) {
|
|
||||||
deleteNotification(args.notification_id);
|
|
||||||
}).error(app.ajaxError);
|
|
||||||
}
|
|
||||||
|
|
||||||
function rejectJoinRequest(args) {
|
|
||||||
rest.updateJoinRequest(args.join_request_id, false)
|
|
||||||
.done(function(response) {
|
|
||||||
deleteNotification(args.notification_id);
|
|
||||||
}).error(app.ajaxError);
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerJoinRequestApproved() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST_APPROVED, function(header, payload) {
|
|
||||||
logger.debug("Handling JOIN_REQUEST_APPROVED msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "Join Request Approved",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
}, {
|
|
||||||
"ok_text": "JOIN SESSION",
|
|
||||||
"ok_callback": openTerms,
|
|
||||||
"ok_callback_args": { "session_id": payload.session_id, "notification_id": payload.notification_id }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerJoinRequestRejected() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.JOIN_REQUEST_REJECTED, function(header, payload) {
|
|
||||||
logger.debug("Handling JOIN_REQUEST_REJECTED msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "Join Request Rejected",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerSessionJoin() {
|
function registerSessionJoin() {
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_JOIN, function(header, payload) {
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SESSION_JOIN, function(header, payload) {
|
||||||
logger.debug("Handling SESSION_JOIN msg " + JSON.stringify(payload));
|
logger.debug("Handling SESSION_JOIN msg " + JSON.stringify(payload));
|
||||||
|
|
@ -765,201 +305,6 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerMusicianSessionJoin() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_SESSION_JOIN, function(header, payload) {
|
|
||||||
logger.debug("Handling MUSICIAN_SESSION_JOIN msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
var okText = '';
|
|
||||||
var showNotification = false;
|
|
||||||
var callback;
|
|
||||||
if (context.JK.currentUserMusician) {
|
|
||||||
// user is MUSICIAN; musician_access = TRUE
|
|
||||||
if (payload.musician_access) {
|
|
||||||
showNotification = true;
|
|
||||||
okText = "JOIN";
|
|
||||||
callback = joinSession;
|
|
||||||
}
|
|
||||||
// user is MUSICIAN; fan_access = TRUE
|
|
||||||
else if (payload.fan_access) {
|
|
||||||
showNotification = true;
|
|
||||||
okText = "LISTEN";
|
|
||||||
callback = listenToSession;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// user is FAN; fan_access = TRUE
|
|
||||||
if (payload.fan_access) {
|
|
||||||
showNotification = true;
|
|
||||||
okText = "LISTEN";
|
|
||||||
callback = listenToSession;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showNotification) {
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "Musician Joined Session",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
}, {
|
|
||||||
"ok_text": okText,
|
|
||||||
"ok_callback": callback,
|
|
||||||
"ok_callback_args": {
|
|
||||||
"session_id": payload.session_id,
|
|
||||||
"fan_access": payload.fan_access,
|
|
||||||
"musician_access": payload.musician_access,
|
|
||||||
"approval_required": payload.approval_required,
|
|
||||||
"notification_id": payload.notification_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerBandSessionJoin() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_SESSION_JOIN, function(header, payload) {
|
|
||||||
logger.debug("Handling BAND_SESSION_JOIN msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
var okText = '';
|
|
||||||
var showNotification = false;
|
|
||||||
var callback;
|
|
||||||
if (context.JK.currentUserMusician) {
|
|
||||||
// user is MUSICIAN; musician_access = TRUE
|
|
||||||
if (payload.musician_access) {
|
|
||||||
showNotification = true;
|
|
||||||
okText = "JOIN";
|
|
||||||
callback = joinSession;
|
|
||||||
}
|
|
||||||
// user is MUSICIAN; fan_access = TRUE
|
|
||||||
else if (payload.fan_access) {
|
|
||||||
showNotification = true;
|
|
||||||
okText = "LISTEN";
|
|
||||||
callback = listenToSession;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// user is FAN; fan_access = TRUE
|
|
||||||
if (payload.fan_access) {
|
|
||||||
showNotification = true;
|
|
||||||
okText = "LISTEN";
|
|
||||||
callback = listenToSession;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showNotification) {
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "Band Joined Session",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
}, {
|
|
||||||
"ok_text": "LISTEN",
|
|
||||||
"ok_callback": callback,
|
|
||||||
"ok_callback_args": {
|
|
||||||
"session_id": payload.session_id,
|
|
||||||
"fan_access": payload.fan_access,
|
|
||||||
"musician_access": payload.musician_access,
|
|
||||||
"approval_required": payload.approval_required,
|
|
||||||
"notification_id": payload.notification_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function listenToSession(args) {
|
|
||||||
deleteNotification(args.notification_id);
|
|
||||||
context.JK.popExternalLink('/sessions/' + args.session_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********** TODO: THE NEXT 3 FUNCTIONS ARE COPIED FROM sessionList.js. REFACTOR TO COMMON PLACE. *************/
|
|
||||||
function joinSession(args) {
|
|
||||||
// NOTE: invited musicians get their own notification, so no need to check if user has invitation here
|
|
||||||
// like other places because an invited user would never get this notification
|
|
||||||
if (args.musician_access) {
|
|
||||||
if (args.approval_required) {
|
|
||||||
openAlert(args.session_id);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
openTerms(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deleteNotification(args.notification_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
function openAlert(sessionId) {
|
|
||||||
var alertDialog = new context.JK.AlertDialog(context.JK.app, "YES",
|
|
||||||
"You must be approved to join this session. Would you like to send a request to join?",
|
|
||||||
sessionId, onCreateJoinRequest);
|
|
||||||
|
|
||||||
alertDialog.initialize();
|
|
||||||
context.JK.app.layout.showDialog('alert');
|
|
||||||
}
|
|
||||||
|
|
||||||
function onCreateJoinRequest(sessionId) {
|
|
||||||
var joinRequest = {};
|
|
||||||
joinRequest.music_session = sessionId;
|
|
||||||
joinRequest.user = context.JK.currentUserId;
|
|
||||||
rest.createJoinRequest(joinRequest)
|
|
||||||
.done(function(response) {
|
|
||||||
|
|
||||||
}).error(context.JK.app.ajaxError);
|
|
||||||
|
|
||||||
context.JK.app.layout.closeDialog('alert');
|
|
||||||
}
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
function registerMusicianRecordingSaved() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.MUSICIAN_RECORDING_SAVED, function(header, payload) {
|
|
||||||
logger.debug("Handling MUSICIAN_RECORDING_SAVED msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "Musician Recording Saved",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
}, {
|
|
||||||
"ok_text": "LISTEN",
|
|
||||||
"ok_callback": listenToRecording,
|
|
||||||
"ok_callback_args": {
|
|
||||||
"recording_id": payload.recording_id,
|
|
||||||
"notification_id": payload.notification_id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerBandRecordingSaved() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_RECORDING_SAVED, function(header, payload) {
|
|
||||||
logger.debug("Handling BAND_RECORDING_SAVED msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "Band Recording Saved",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
}, {
|
|
||||||
"ok_text": "LISTEN",
|
|
||||||
"ok_callback": listenToRecording,
|
|
||||||
"ok_callback_args": {
|
|
||||||
"recording_id": payload.recording_id,
|
|
||||||
"notification_id": payload.notification_id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function listenToRecording(args) {
|
|
||||||
deleteNotification(args.notification_id);
|
|
||||||
context.JK.popExternalLink('/recordings/' + args.recording_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerRecordingStarted() {
|
function registerRecordingStarted() {
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.RECORDING_STARTED, function(header, payload) {
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.RECORDING_STARTED, function(header, payload) {
|
||||||
logger.debug("Handling RECORDING_STARTED msg " + JSON.stringify(payload));
|
logger.debug("Handling RECORDING_STARTED msg " + JSON.stringify(payload));
|
||||||
|
|
@ -984,86 +329,6 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerRecordingMasterMixComplete() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.RECORDING_MASTER_MIX_COMPLETE, function(header, payload) {
|
|
||||||
logger.debug("Handling RECORDING_MASTER_MIX_COMPLETE msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "Recording Master Mix Complete",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
}, {
|
|
||||||
"ok_text": "SHARE",
|
|
||||||
"ok_callback": shareRecording,
|
|
||||||
"ok_callback_args": {
|
|
||||||
"recording_id": payload.recording_id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function shareRecording(args) {
|
|
||||||
var recordingId = args.recording_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerBandInvitation() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_INVITATION, function(header, payload) {
|
|
||||||
logger.debug("Handling BAND_INVITATION msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "Band Invitation",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
}, {
|
|
||||||
"ok_text": "ACCEPT",
|
|
||||||
"ok_callback": acceptBandInvitation,
|
|
||||||
"ok_callback_args": {
|
|
||||||
"band_invitation_id": payload.band_invitation_id,
|
|
||||||
"band_id": payload.band_id,
|
|
||||||
"notification_id": payload.notification_id
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function acceptBandInvitation(args) {
|
|
||||||
rest.updateBandInvitation(
|
|
||||||
args.band_id,
|
|
||||||
args.band_invitation_id,
|
|
||||||
true
|
|
||||||
).done(function(response) {
|
|
||||||
deleteNotification(args.notification_id); // delete notification corresponding to this friend request
|
|
||||||
}).error(app.ajaxError);
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerTextMessage() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.TEXT_MESSAGE, function(header, payload) {
|
|
||||||
logger.debug("Handling TEXT_MESSAGE msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
textMessageDialog.messageReceived(payload);
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerBandInvitationAccepted() {
|
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_INVITATION_ACCEPTED, function(header, payload) {
|
|
||||||
logger.debug("Handling BAND_INVITATION_ACCEPTED msg " + JSON.stringify(payload));
|
|
||||||
|
|
||||||
handleNotification(payload, header.type);
|
|
||||||
|
|
||||||
app.notify({
|
|
||||||
"title": "Band Invitation Accepted",
|
|
||||||
"text": payload.msg,
|
|
||||||
"icon_url": context.JK.resolveAvatarUrl(payload.photo_url)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerSourceUpRequested() {
|
function registerSourceUpRequested() {
|
||||||
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SOURCE_UP_REQUESTED, function(header, payload) {
|
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SOURCE_UP_REQUESTED, function(header, payload) {
|
||||||
|
|
||||||
|
|
@ -1170,13 +435,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
this.initialize = function(invitationDialogInstance, textMessageDialogInstance) {
|
this.initialize = function(invitationDialogInstance, textMessageDialogInstance) {
|
||||||
|
invitationDialog = invitationDialogInstance;
|
||||||
|
textMessageDialog = textMessageDialogInstance;
|
||||||
events();
|
events();
|
||||||
initializeSearchPanel();
|
initializeSearchPanel();
|
||||||
initializeFriendsPanel();
|
initializeFriendsPanel();
|
||||||
initializeChatPanel();
|
initializeChatPanel();
|
||||||
initializeNotificationsPanel();
|
initializeNotificationsPanel();
|
||||||
invitationDialog = invitationDialogInstance;
|
|
||||||
textMessageDialog = textMessageDialogInstance;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
})(window,jQuery);
|
})(window,jQuery);
|
||||||
|
|
@ -47,8 +47,7 @@
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendMessage(e) {
|
function sendMessage() {
|
||||||
|
|
||||||
var msg = $textBox.val();
|
var msg = $textBox.val();
|
||||||
if(!msg || msg == '') {
|
if(!msg || msg == '') {
|
||||||
// don't bother the server with empty messages
|
// don't bother the server with empty messages
|
||||||
|
|
@ -124,6 +123,15 @@
|
||||||
return markedUpMsg;
|
return markedUpMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we handled the notification, meaning the dialog showed this message as a chat message
|
||||||
|
function handledNotification(payload) {
|
||||||
|
return showing && payload.description == "TEXT_MESSAGE" && payload.sender_id == otherId;
|
||||||
|
}
|
||||||
|
|
||||||
|
function afterShow(args) {
|
||||||
|
$textBox.focus();
|
||||||
|
}
|
||||||
|
|
||||||
function beforeShow(args) {
|
function beforeShow(args) {
|
||||||
|
|
||||||
app.layout.closeDialog('text-message') // ensure no others are showing. this is a singleton dialog
|
app.layout.closeDialog('text-message') // ensure no others are showing. this is a singleton dialog
|
||||||
|
|
@ -175,13 +183,38 @@
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
function postMessage(e) {
|
function pasteIntoInput(el, text) {
|
||||||
|
el.focus();
|
||||||
|
if (typeof el.selectionStart == "number"
|
||||||
|
&& typeof el.selectionEnd == "number") {
|
||||||
|
var val = el.value;
|
||||||
|
var selStart = el.selectionStart;
|
||||||
|
el.value = val.slice(0, selStart) + text + val.slice(el.selectionEnd);
|
||||||
|
el.selectionEnd = el.selectionStart = selStart + text.length;
|
||||||
|
} else if (typeof document.selection != "undefined") {
|
||||||
|
var textRange = document.selection.createRange();
|
||||||
|
textRange.text = text;
|
||||||
|
textRange.collapse(false);
|
||||||
|
textRange.select();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
function handleEnter(evt) {
|
||||||
|
if (evt.keyCode == 13 && evt.shiftKey) {
|
||||||
|
pasteIntoInput(this, "\n");
|
||||||
|
evt.preventDefault();
|
||||||
|
}
|
||||||
|
else if(evt.keyCode == 13 && !evt.shiftKey){
|
||||||
|
sendMessage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function events() {
|
function events() {
|
||||||
$form.submit(postMessage)
|
$form.submit(sendMessage)
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/6014702/how-do-i-detect-shiftenter-and-generate-a-new-line-in-textarea
|
||||||
|
$textBox.keydown(handleEnter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -234,6 +267,7 @@
|
||||||
function initialize() {
|
function initialize() {
|
||||||
var dialogBindings = {
|
var dialogBindings = {
|
||||||
'beforeShow' : beforeShow,
|
'beforeShow' : beforeShow,
|
||||||
|
'afterShow' : afterShow,
|
||||||
'afterHide': afterHide
|
'afterHide': afterHide
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -253,6 +287,7 @@
|
||||||
this.initialize = initialize;
|
this.initialize = initialize;
|
||||||
this.messageReceived = messageReceived;
|
this.messageReceived = messageReceived;
|
||||||
this.formatTextMessage = formatTextMessage;
|
this.formatTextMessage = formatTextMessage;
|
||||||
|
this.handledNotification = handledNotification;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
.previous-message-text {
|
.previous-message-text {
|
||||||
line-height:18px;
|
line-height:18px;
|
||||||
|
white-space:pre-line;
|
||||||
}
|
}
|
||||||
|
|
||||||
.previous-message-timestamp {
|
.previous-message-timestamp {
|
||||||
|
|
@ -52,4 +53,9 @@
|
||||||
width:100%;
|
width:100%;
|
||||||
height:40px;
|
height:40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-send-text-message {
|
||||||
|
text-align:center;
|
||||||
|
width:50px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -44,6 +44,12 @@ class ApiUsersController < ApiController
|
||||||
@user.show_whats_next = params[:show_whats_next] if params.has_key?(:show_whats_next)
|
@user.show_whats_next = params[:show_whats_next] if params.has_key?(:show_whats_next)
|
||||||
@user.subscribe_email = params[:subscribe_email] if params.has_key?(:subscribe_email)
|
@user.subscribe_email = params[:subscribe_email] if params.has_key?(:subscribe_email)
|
||||||
@user.biography = params[:biography] if params.has_key?(:biography)
|
@user.biography = params[:biography] if params.has_key?(:biography)
|
||||||
|
|
||||||
|
# allow keyword of 'LATEST' to mean set the notification_seen_at to the most recent notification for this user
|
||||||
|
if params.has_key?(:notification_seen_at)
|
||||||
|
@user.update_notification_seen_at params[:notification_seen_at]
|
||||||
|
end
|
||||||
|
|
||||||
@user.save
|
@user.save
|
||||||
|
|
||||||
if @user.errors.any?
|
if @user.errors.any?
|
||||||
|
|
|
||||||
|
|
@ -214,11 +214,6 @@ class UsersController < ApplicationController
|
||||||
@promo_latest, start = Feed.index(nil, limit: 10)
|
@promo_latest, start = Feed.index(nil, limit: 10)
|
||||||
end
|
end
|
||||||
|
|
||||||
# temporary--will go away soon
|
|
||||||
@jamfest_2014 = Event.find_by_id('80bb6acf-3ddc-4305-9442-75e6ec047c27')
|
|
||||||
@jamfest_2014 = Event.find_by_id('a2dfbd26-9b17-4446-8c61-b67a542ea6ee') unless @jamfest_2014
|
|
||||||
# temporary--end
|
|
||||||
|
|
||||||
@welcome_page = true
|
@welcome_page = true
|
||||||
render :layout => "web"
|
render :layout => "web"
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
object @music_session
|
object @music_session
|
||||||
|
|
||||||
if !current_user
|
if !current_user
|
||||||
# there should be more data returned, but we need to think very carefully about what data is public for a music session
|
# there should be more data returned, but we need to think very carefully about what data is public for a music session
|
||||||
|
|
|
||||||
|
|
@ -311,10 +311,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
JK.bindHoverEvents();
|
JK.bindHoverEvents();
|
||||||
|
|
||||||
setInterval(function() {
|
|
||||||
console.log("IN FOCUS: " + document.hasFocus());
|
|
||||||
}, 1000)
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,6 @@
|
||||||
= link_to "Already have an account?", signin_path, class: "signin", id: "signin"
|
= link_to "Already have an account?", signin_path, class: "signin", id: "signin"
|
||||||
|
|
||||||
- content_for :after_black_bar do
|
- content_for :after_black_bar do
|
||||||
- if @jamfest_2014
|
|
||||||
.jamfest{style: 'top:-70px;position:relative'}
|
|
||||||
%a{ href: event_path(@jamfest_2014.slug), style: 'font-size:24px' }
|
|
||||||
Join us online March 12 for Virtual Jam Fest!
|
|
||||||
%div{style: "padding-top:20px;"}
|
%div{style: "padding-top:20px;"}
|
||||||
.right
|
.right
|
||||||
= render :partial => "buzz"
|
= render :partial => "buzz"
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ describe "Home Screen", :js => true, :type => :feature, :capybara_feature => tru
|
||||||
Capybara.javascript_driver = :poltergeist
|
Capybara.javascript_driver = :poltergeist
|
||||||
Capybara.current_driver = Capybara.javascript_driver
|
Capybara.current_driver = Capybara.javascript_driver
|
||||||
Capybara.default_wait_time = 10
|
Capybara.default_wait_time = 10
|
||||||
|
MusicSession.delete_all
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:user) { FactoryGirl.create(:user) }
|
let(:user) { FactoryGirl.create(:user) }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,168 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe "Notification Highlighter", :js => true, :type => :feature, :capybara_feature => true do
|
||||||
|
|
||||||
|
subject { page }
|
||||||
|
|
||||||
|
before(:all) do
|
||||||
|
Capybara.javascript_driver = :poltergeist
|
||||||
|
Capybara.current_driver = Capybara.javascript_driver
|
||||||
|
Capybara.default_wait_time = 10
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:user) { FactoryGirl.create(:user) }
|
||||||
|
let(:user2) { FactoryGirl.create(:user) }
|
||||||
|
|
||||||
|
|
||||||
|
shared_examples_for :notification_badge do |options|
|
||||||
|
it "in correct state" do
|
||||||
|
sign_in_poltergeist(user) unless page.has_selector?('h2', 'musicians')
|
||||||
|
badge = find("#{NOTIFICATION_PANEL} .badge", text:options[:count])
|
||||||
|
badge['class'].include?('highlighted').should == options[:highlighted]
|
||||||
|
|
||||||
|
if options[:action] == :click
|
||||||
|
badge.trigger(:click)
|
||||||
|
badge = find("#{NOTIFICATION_PANEL} .badge", text:0)
|
||||||
|
badge['class'].include?('highlighted').should == false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
describe "user with no notifications" do
|
||||||
|
|
||||||
|
it_behaves_like :notification_badge, highlighted: false, count:0
|
||||||
|
|
||||||
|
describe "and realtime notifications with sidebar closed" do
|
||||||
|
before(:each) do
|
||||||
|
sign_in_poltergeist(user)
|
||||||
|
document_focus
|
||||||
|
user.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like :notification_badge, highlighted: false, count:0
|
||||||
|
|
||||||
|
describe "sees notification" do
|
||||||
|
before(:each) do
|
||||||
|
notification = Notification.send_text_message("text message", user2, user)
|
||||||
|
notification.errors.any?.should be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like :notification_badge, highlighted: false, count:0, action: :click
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "document out of focus" do
|
||||||
|
before(:each) do
|
||||||
|
document_blur
|
||||||
|
notification = Notification.send_text_message("text message", user2, user)
|
||||||
|
notification.errors.any?.should be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like :notification_badge, highlighted: true, count:1, action: :click
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
describe "and realtime notifications with sidebar open" do
|
||||||
|
before(:each) do
|
||||||
|
# generate one message so that count = 1 to start
|
||||||
|
notification = Notification.send_text_message("text message", user2, user)
|
||||||
|
notification.errors.any?.should be_false
|
||||||
|
sign_in_poltergeist(user)
|
||||||
|
document_focus
|
||||||
|
open_notifications
|
||||||
|
badge = find("#{NOTIFICATION_PANEL} .badge", text:'0') # wait for the opening of the sidebar to bring count to 0
|
||||||
|
user.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like :notification_badge, highlighted: false, count:0
|
||||||
|
|
||||||
|
describe "sees notification" do
|
||||||
|
before(:each) do
|
||||||
|
notification = Notification.send_text_message("text message", user2, user)
|
||||||
|
notification.errors.any?.should be_false
|
||||||
|
find('#notification #ok-button') # wait for notification to show, so that we know the sidebar had a chance to update
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like :notification_badge, highlighted: false, count:0
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "document out of focus" do
|
||||||
|
before(:each) do
|
||||||
|
document_blur
|
||||||
|
notification = Notification.send_text_message("text message 2", user2, user)
|
||||||
|
notification.errors.any?.should be_false
|
||||||
|
find('#notification #ok-button')
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like :notification_badge, highlighted: true, count:1
|
||||||
|
|
||||||
|
describe "user comes back" do
|
||||||
|
before(:each) do
|
||||||
|
window_focus
|
||||||
|
|
||||||
|
it_behaves_like :notification_badge, highlighted: false, count:1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "user with new notifications" do
|
||||||
|
before(:each) do
|
||||||
|
# create a notification
|
||||||
|
notification = Notification.send_text_message("text message", user2, user)
|
||||||
|
notification.errors.any?.should be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like :notification_badge, highlighted:true, count:1, action: :click
|
||||||
|
|
||||||
|
describe "user has previously seen notifications" do
|
||||||
|
before(:each) do
|
||||||
|
user.update_notification_seen_at 'LATEST'
|
||||||
|
user.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like :notification_badge, highlighted: false, count:0, action: :click
|
||||||
|
|
||||||
|
describe "user again has unseen notifications" do
|
||||||
|
before(:each) do
|
||||||
|
# create a notification
|
||||||
|
notification = Notification.send_text_message("text message", user2, user)
|
||||||
|
notification.errors.any?.should be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like :notification_badge, highlighted:true, count:1, action: :click
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
describe "user no unseen notifications" do
|
||||||
|
describe "notification occurs in realtime" do
|
||||||
|
|
||||||
|
describe "sidebar is open" do
|
||||||
|
describe "user can see notifications" do
|
||||||
|
it "stays deactivated" do
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "user can not see notifications" do
|
||||||
|
describe "with dialog open" do
|
||||||
|
it "temporarily activates" do
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with document blurred" do
|
||||||
|
it "temporarily activates" do
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -42,7 +42,7 @@ describe "Text Message", :js => true, :type => :feature, :capybara_feature => tr
|
||||||
notification = Notification.send_text_message("bibbity bobbity boo", @user2, @user1)
|
notification = Notification.send_text_message("bibbity bobbity boo", @user2, @user1)
|
||||||
notification.errors.any?.should be_false
|
notification.errors.any?.should be_false
|
||||||
|
|
||||||
open_sidebar
|
open_notifications
|
||||||
|
|
||||||
# find the notification and click REPLY
|
# find the notification and click REPLY
|
||||||
find("[layout-id='panelNotifications'] [notification-id='#{notification.id}'] .button-orange", text:'REPLY').trigger(:click)
|
find("[layout-id='panelNotifications'] [notification-id='#{notification.id}'] .button-orange", text:'REPLY').trigger(:click)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
# methods here all assume you are in /client
|
# methods here all assume you are in /client
|
||||||
|
|
||||||
|
NOTIFICATION_PANEL = '[layout-id="panelNotifications"]'
|
||||||
|
|
||||||
# enters text into the search sidebar
|
# enters text into the search sidebar
|
||||||
def site_search(text, options = {})
|
def site_search(text, options = {})
|
||||||
within('#searchForm') do
|
within('#searchForm') do
|
||||||
|
|
@ -56,11 +58,41 @@ def send_text_message(msg, options={})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def open_sidebar
|
def open_notifications
|
||||||
find('[layout-id="panelNotifications"] .panel-header').trigger(:click)
|
find("#{NOTIFICATION_PANEL} .panel-header").trigger(:click)
|
||||||
end
|
end
|
||||||
|
|
||||||
def hover_intent(element)
|
def hover_intent(element)
|
||||||
element.hover
|
element.hover
|
||||||
element.hover
|
element.hover
|
||||||
|
end
|
||||||
|
|
||||||
|
# forces document.hasFocus() to return false
|
||||||
|
def document_blur
|
||||||
|
page.evaluate_script(%{(function() {
|
||||||
|
// save original
|
||||||
|
if(!window.documentFocus) { window.documentFocus = window.document.hasFocus; }
|
||||||
|
|
||||||
|
window.document.hasFocus = function() {
|
||||||
|
console.log("document.hasFocus() returns false");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})()})
|
||||||
|
end
|
||||||
|
|
||||||
|
def document_focus
|
||||||
|
page.evaluate_script(%{(function() {
|
||||||
|
// save original
|
||||||
|
if(!window.documentFocus) { window.documentFocus = window.document.hasFocus; }
|
||||||
|
|
||||||
|
window.document.hasFocus = function() {
|
||||||
|
console.log("document.hasFocus() returns true");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
})()})
|
||||||
|
end
|
||||||
|
|
||||||
|
# simulates focus event on window
|
||||||
|
def window_focus
|
||||||
|
page.evaluate_script(%{window.jQuery(window).trigger('focus');})
|
||||||
end
|
end
|
||||||
|
|
@ -575,20 +575,9 @@ module JamWebsockets
|
||||||
connection.touch
|
connection.touch
|
||||||
|
|
||||||
# update user's notification_seen_at field if the heartbeat indicates it saw one
|
# update user's notification_seen_at field if the heartbeat indicates it saw one
|
||||||
notification_seen_at_parsed = nil
|
# first we try to use the notification id, which should usually exist.
|
||||||
notification_seen_at = heartbeat.notification_seen_at if heartbeat.value_for_tag(1)
|
# if not, then fallback to notification_seen_at, which is approximately the last time we saw a notification
|
||||||
begin
|
update_notification_seen_at(connection, context, heartbeat)
|
||||||
notification_seen_at_parsed = Time.parse(notification_seen_at)
|
|
||||||
rescue Exception => e
|
|
||||||
@log.error "unable to parse notification_seen_at in heartbeat from #{context}. notification_seen_at: #{notification_seen_at}"
|
|
||||||
end
|
|
||||||
|
|
||||||
if notification_seen_at_parsed
|
|
||||||
connection.user.notification_seen_at = notification_seen_at
|
|
||||||
unless connection.user.save(validate: false)
|
|
||||||
@log.error "unable to update notification_seen_at for client #{context}. errors: #{connection.user.errors.inspect}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
ConnectionManager.active_record_transaction do |connection_manager|
|
ConnectionManager.active_record_transaction do |connection_manager|
|
||||||
|
|
@ -614,6 +603,34 @@ module JamWebsockets
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_notification_seen_at(connection, context, heartbeat)
|
||||||
|
notification_id_field = heartbeat.notification_seen if heartbeat.value_for_tag(1)
|
||||||
|
if notification_id_field
|
||||||
|
notification = Notification.find_by_id(notification_id_field)
|
||||||
|
if notification
|
||||||
|
connection.user.notification_seen_at = notification.created_at
|
||||||
|
unless connection.user.save(validate: false)
|
||||||
|
@log.error "unable to update notification_seen_at via id field for client #{context}. errors: #{connection.user.errors.inspect}"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
notification_seen_at_parsed = nil
|
||||||
|
notification_seen_at = heartbeat.notification_seen_at if heartbeat.value_for_tag(2)
|
||||||
|
begin
|
||||||
|
notification_seen_at_parsed = Time.parse(notification_seen_at) if notification_seen_at && notification_seen_at.length > 0
|
||||||
|
rescue Exception => e
|
||||||
|
@log.error "unable to parse notification_seen_at in heartbeat from #{context}. notification_seen_at: #{notification_seen_at}"
|
||||||
|
end
|
||||||
|
|
||||||
|
if notification_seen_at_parsed
|
||||||
|
connection.user.notification_seen_at = notification_seen_at
|
||||||
|
unless connection.user.save(validate: false)
|
||||||
|
@log.error "unable to update notification_seen_at via time field for client #{context}. errors: #{connection.user.errors.inspect}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def valid_login(username, password, token, client_id)
|
def valid_login(username, password, token, client_id)
|
||||||
|
|
||||||
if !token.nil? && token != ''
|
if !token.nil? && token != ''
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue