Trigger desktop notifications

Notifications show the conversation name, avatar, and new message text.
Clicking the notification opens the conversation.
This commit is contained in:
lilia 2015-03-17 15:06:21 -07:00
parent f8e69fa8e7
commit fa3699cdd3
7 changed files with 115 additions and 4 deletions

View file

@ -202,6 +202,7 @@
<script type="text/javascript" src="js/components.js"></script>
<script type="text/javascript" src="js/libtextsecure.js"></script>
<script type="text/javascript" src="js/notifications.js"></script>
<script type="text/javascript" src="js/database.js"></script>
<script type="text/javascript" src="js/libphonenumber-util.js"></script>
<script type="text/javascript" src="js/models/messages.js"></script>

View file

@ -115,12 +115,12 @@
e.args.push(message.id);
message.save({ errors : [e] }).then(function() {
extension.trigger('message', message);
openConversation(conversation.id);
notifyConversation(message);
});
} else if (e.message === 'Bad MAC') {
message.save({ errors : [ _.pick(e, ['name', 'message'])]}).then(function() {
extension.trigger('message', message);
openConversation(conversation.id);
notifyConversation(message);
});
} else {
console.log(e);
@ -220,7 +220,7 @@
conversation.save().then(function() {
message.save().then(function() {
extension.trigger('message', message); // notify frontend listeners
openConversation(conversation.id);
notifyConversation(message);
});
});
});

View file

@ -36,6 +36,8 @@
this.messageCollection = new Whisper.MessageCollection([], {
conversation: this
});
this.on('change:avatar', this.updateAvatarUrl);
},
validate: function(attributes, options) {
@ -190,6 +192,28 @@
},
isPrivate: function() {
return this.get('type') === 'private';
},
updateAvatarUrl: function() {
if (this.avatarUrl) {
URL.revokeObjectURL(this.avatarUrl);
this.avatarUrl = null;
}
var avatar = this.get('avatar');
if (avatar) {
this.avatarUrl = URL.createObjectURL(
new Blob([avatar.data], {type: avatar.contentType})
);
} else {
this.avatarUrl = null;
}
},
getAvatarUrl: function() {
if (this.avatarUrl === undefined) {
this.updateAvatarUrl();
}
return this.avatarUrl || '/images/default.png';
}
});

36
js/notifications.js Normal file
View file

@ -0,0 +1,36 @@
/* vim: ts=4:sw=4
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
;(function() {
'use strict';
window.Whisper = window.Whisper || {};
Whisper.Notifications = {
isEnabled: function(callback) {
return Notification.permission === 'granted' &&
!localStorage.getItem('disable-notifications');
},
enable: function(callback) {
localStorage.removeItem('disable-notifications');
Notification.requestPermission(function(status) {
callback(status);
});
},
disable: function() {
localStorage.setItem('disable-notifications', true);
}
};
})();

View file

@ -15,6 +15,26 @@
*/
;(function() {
'use strict';
$('.notifications .on button').click(function() {
Whisper.Notifications.disable();
initOptions();
});
$('.notifications .off button').click(function() {
Whisper.Notifications.enable(initOptions);
initOptions();
});
function initOptions() {
if (Whisper.Notifications.isEnabled()) {
$('.notifications .on').show();
$('.notifications .off').hide();
} else {
$('.notifications .on').hide();
$('.notifications .off').show();
}
}
$(function() {
if (textsecure.registration.isDone()) {
$('#complete-number').text(
@ -23,6 +43,7 @@
)[0]
);//TODO: no
$('#setup-complete').show().addClass('in');
initOptions();
} else {
$('#init-setup').show().addClass('in');
$('#status').text("Connecting...");
@ -55,6 +76,7 @@
textsecure.registration.done();
$('#init-setup').hide();
$('#setup-complete').show().addClass('in');
initOptions();
}
});
} else

View file

@ -41,9 +41,32 @@
windowMap.remove('windowId', windowId);
}
window.openConversation = function openConversation (modelId) {
function getConversation(modelId) {
var conversation = window.inbox.get(modelId) || {id: modelId};
conversation = conversations.add(conversation);
return conversation;
}
window.notifyConversation = function(message) {
if (Whisper.Notifications.isEnabled()) {
var conversation = getConversation(message.get('conversationId'));
conversation.fetch().then(function() {
var notification = new Notification(conversation.getTitle(), {
body: message.get('body'),
icon: conversation.getAvatarUrl(),
tag: conversation.id
});
notification.onclick = function() {
openConversation(conversation.id);
};
});
} else {
openConversation(message.get('conversationId'));
}
};
window.openConversation = function openConversation (modelId) {
var conversation = getConversation(modelId);
conversation.fetch().then(function() {
conversation.fetchContacts();
});

View file

@ -93,12 +93,17 @@
</header>
<div class='container'>
<h3>You are registered on TextSecure with number <span id="complete-number"></span></h3>
<div class='notifications'>
<span class='on'>Desktop notifcations are enabled. <button class='disable'>Turn off Notifications</button></span>
<span class='off'>Desktop notifcations are not enabled. <button class='enable'>Turn on Notifications</button></span>
</div>
</div>
</div>
<script type="text/javascript" src="js/components.js"></script>
<script type="text/javascript" src="js/libtextsecure.js"></script>
<script type="text/javascript" src="js/notifications.js"></script>
<script type="text/javascript" src="js/database.js"></script>
<script type="text/javascript" src="js/libphonenumber-util.js"></script>
<script type="text/javascript" src="js/models/messages.js"></script>