Trigger desktop notifications
Notifications show the conversation name, avatar, and new message text. Clicking the notification opens the conversation.
This commit is contained in:
parent
f8e69fa8e7
commit
fa3699cdd3
7 changed files with 115 additions and 4 deletions
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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
36
js/notifications.js
Normal 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);
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue