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/components.js"></script>
|
||||||
<script type="text/javascript" src="js/libtextsecure.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/database.js"></script>
|
||||||
<script type="text/javascript" src="js/libphonenumber-util.js"></script>
|
<script type="text/javascript" src="js/libphonenumber-util.js"></script>
|
||||||
<script type="text/javascript" src="js/models/messages.js"></script>
|
<script type="text/javascript" src="js/models/messages.js"></script>
|
||||||
|
|
|
@ -115,12 +115,12 @@
|
||||||
e.args.push(message.id);
|
e.args.push(message.id);
|
||||||
message.save({ errors : [e] }).then(function() {
|
message.save({ errors : [e] }).then(function() {
|
||||||
extension.trigger('message', message);
|
extension.trigger('message', message);
|
||||||
openConversation(conversation.id);
|
notifyConversation(message);
|
||||||
});
|
});
|
||||||
} else if (e.message === 'Bad MAC') {
|
} else if (e.message === 'Bad MAC') {
|
||||||
message.save({ errors : [ _.pick(e, ['name', 'message'])]}).then(function() {
|
message.save({ errors : [ _.pick(e, ['name', 'message'])]}).then(function() {
|
||||||
extension.trigger('message', message);
|
extension.trigger('message', message);
|
||||||
openConversation(conversation.id);
|
notifyConversation(message);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
@ -220,7 +220,7 @@
|
||||||
conversation.save().then(function() {
|
conversation.save().then(function() {
|
||||||
message.save().then(function() {
|
message.save().then(function() {
|
||||||
extension.trigger('message', message); // notify frontend listeners
|
extension.trigger('message', message); // notify frontend listeners
|
||||||
openConversation(conversation.id);
|
notifyConversation(message);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
this.messageCollection = new Whisper.MessageCollection([], {
|
this.messageCollection = new Whisper.MessageCollection([], {
|
||||||
conversation: this
|
conversation: this
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.on('change:avatar', this.updateAvatarUrl);
|
||||||
},
|
},
|
||||||
|
|
||||||
validate: function(attributes, options) {
|
validate: function(attributes, options) {
|
||||||
|
@ -190,6 +192,28 @@
|
||||||
},
|
},
|
||||||
isPrivate: function() {
|
isPrivate: function() {
|
||||||
return this.get('type') === 'private';
|
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() {
|
;(function() {
|
||||||
'use strict';
|
'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() {
|
$(function() {
|
||||||
if (textsecure.registration.isDone()) {
|
if (textsecure.registration.isDone()) {
|
||||||
$('#complete-number').text(
|
$('#complete-number').text(
|
||||||
|
@ -23,6 +43,7 @@
|
||||||
)[0]
|
)[0]
|
||||||
);//TODO: no
|
);//TODO: no
|
||||||
$('#setup-complete').show().addClass('in');
|
$('#setup-complete').show().addClass('in');
|
||||||
|
initOptions();
|
||||||
} else {
|
} else {
|
||||||
$('#init-setup').show().addClass('in');
|
$('#init-setup').show().addClass('in');
|
||||||
$('#status').text("Connecting...");
|
$('#status').text("Connecting...");
|
||||||
|
@ -55,6 +76,7 @@
|
||||||
textsecure.registration.done();
|
textsecure.registration.done();
|
||||||
$('#init-setup').hide();
|
$('#init-setup').hide();
|
||||||
$('#setup-complete').show().addClass('in');
|
$('#setup-complete').show().addClass('in');
|
||||||
|
initOptions();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -41,9 +41,32 @@
|
||||||
windowMap.remove('windowId', windowId);
|
windowMap.remove('windowId', windowId);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.openConversation = function openConversation (modelId) {
|
function getConversation(modelId) {
|
||||||
var conversation = window.inbox.get(modelId) || {id: modelId};
|
var conversation = window.inbox.get(modelId) || {id: modelId};
|
||||||
conversation = conversations.add(conversation);
|
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.fetch().then(function() {
|
||||||
conversation.fetchContacts();
|
conversation.fetchContacts();
|
||||||
});
|
});
|
||||||
|
|
|
@ -93,12 +93,17 @@
|
||||||
</header>
|
</header>
|
||||||
<div class='container'>
|
<div class='container'>
|
||||||
<h3>You are registered on TextSecure with number <span id="complete-number"></span></h3>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="js/components.js"></script>
|
<script type="text/javascript" src="js/components.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/libtextsecure.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/database.js"></script>
|
||||||
<script type="text/javascript" src="js/libphonenumber-util.js"></script>
|
<script type="text/javascript" src="js/libphonenumber-util.js"></script>
|
||||||
<script type="text/javascript" src="js/models/messages.js"></script>
|
<script type="text/javascript" src="js/models/messages.js"></script>
|
||||||
|
|
Loading…
Reference in a new issue