From e8edbe53bcb1723de7b2bb51b04caa267756ba6b Mon Sep 17 00:00:00 2001 From: lilia Date: Sun, 13 Sep 2015 20:25:04 -0700 Subject: [PATCH] Improve notification behavior Only allow one notification at a time. Use a basic notification for normal messages, and image notification for image messages, and a list notification when there are multiple unread messages. // FREEBIE --- js/chromium.js | 43 +++++++++++++++++++++ js/models/messages.js | 13 ++++++- js/notifications.js | 85 ++++++++++++++++++++++++++++++++++-------- js/panel_controller.js | 19 +++++----- 4 files changed, 133 insertions(+), 27 deletions(-) diff --git a/js/chromium.js b/js/chromium.js index 34d896212b..e719bb959e 100644 --- a/js/chromium.js +++ b/js/chromium.js @@ -170,6 +170,49 @@ } }; + if (chrome) { + chrome.notifications.onClicked.addListener(function() { + chrome.notifications.clear('signal'); + Whisper.Notifications.onclick(); + }); + chrome.notifications.onButtonClicked.addListener(function() { + chrome.notifications.clear('signal'); + Whisper.Notifications.clear(); + getInboxCollection().each(function(model) { + if (model.get('unreadCount') > 0) { + model.markRead(); + } + }); + }); + chrome.notifications.onClosed.addListener(function(id, byUser) { + if (byUser) { + Whisper.Notifications.clear(); + } + }); + } + extension.notify = function(options) { + if (chrome) { + chrome.notifications.clear('signal'); + chrome.notifications.create('signal', { + type : options.type, + title : options.title, + message : options.message || '', // required + iconUrl : options.iconUrl, + items : options.items, + buttons : options.buttons + }); + } else { + var notification = new Notification(options.title, { + body : options.message, + icon : options.iconUrl, + tag : 'signal' + }); + notification.onclick = function() { + Whisper.Notifications.onclick(); + }; + } + }; + if (chrome.runtime.onInstalled) { chrome.runtime.onInstalled.addListener(function(options) { if (options.reason === 'install') { diff --git a/js/models/messages.js b/js/models/messages.js index dead330976..4087aeaea0 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -61,9 +61,20 @@ return this.get('body'); }, + getNotificationText: function() { + var description = this.getDescription(); + if (description) { + return description; + } + if (this.get('attachments').length > 0) { + return 'Media message'; + } + + return ''; + }, updateImageUrl: function() { this.revokeImageUrl(); - var attachment = message.get('attachments')[0]; + var attachment = this.get('attachments')[0]; if (attachment) { var blob = new Blob([attachment.data], { type: attachment.contentType diff --git a/js/notifications.js b/js/notifications.js index a87543c829..b431f43331 100644 --- a/js/notifications.js +++ b/js/notifications.js @@ -5,20 +5,73 @@ 'use strict'; window.Whisper = window.Whisper || {}; - Whisper.Notifications = { - isEnabled: function(callback) { - return Notification.permission === 'granted' && - !storage.get('disable-notifications'); - }, - enable: function(callback) { - storage.remove('disable-notifications'); - Notification.requestPermission(function(status) { - callback(status); - }); - }, - disable: function() { - storage.put('disable-notifications', true); - } - }; - + Whisper.Notifications = new (Backbone.Collection.extend({ + initialize: function() { + this.on('add', this.update); + }, + isEnabled: function(callback) { + return Notification.permission === 'granted' && + !storage.get('disable-notifications'); + }, + enable: function(callback) { + storage.remove('disable-notifications'); + Notification.requestPermission(function(status) { + callback(status); + }); + }, + disable: function() { + storage.put('disable-notifications', true); + }, + onclick: function() { + var last = this.last(); + if (!last) { + openInbox(); + return; + } + var conversation = ConversationController.create({ + id: last.get('conversationId') + }); + openConversation(conversation); + this.clear(); + }, + update: function(options) { + if (this.length > 1) { + var iconUrl = 'images/icon_128.png'; + var conversationIds = _.uniq(this.map(function(m) { + return m.get('conversationId'); + })); + if (conversationIds.length === 1) { + iconUrl = this.at(0).get('iconUrl'); + } + extension.notify({ + type : 'list', + iconUrl : iconUrl, + title : '' + this.length + ' new messages', + message : 'Most recent from ' + this.last().get('title'), + items : this.map(function(m) { + return { + title : m.get('title'), + message : m.get('message') + }; + }), + buttons : [{ + title : 'Mark all as read', + iconUrl : 'images/check.png' + }] + }); + } else { + var m = this.at(0); + extension.notify({ + type : 'basic', + title : m.get('title'), + message : m.get('message'), + iconUrl : m.get('iconUrl'), + imageUrl : m.get('imageUrl') + }); + } + }, + clear: function() { + this.reset([]); + } + }))(); })(); diff --git a/js/panel_controller.js b/js/panel_controller.js index e9f245fb29..40f405c48f 100644 --- a/js/panel_controller.js +++ b/js/panel_controller.js @@ -93,15 +93,14 @@ var sender = ConversationController.create({id: message.get('source')}); conversation.fetch().then(function() { sender.fetch().then(function() { - sender.getNotificationIcon().then(function(icon) { - var notification = new Notification(sender.getTitle(), { - body: message.getDescription(), - icon: icon, - tag: conversation.id + sender.getNotificationIcon().then(function(iconUrl) { + Whisper.Notifications.add({ + title : sender.getTitle(), + message : message.getNotificationText(), + iconUrl : iconUrl, + imageUrl : message.getImageUrl(), + conversationId: conversation.id }); - notification.onclick = function() { - openConversation(conversation); - }; }); }); }); @@ -152,7 +151,7 @@ }; var open; - function openConversation(conversation) { + window.openConversation = function(conversation) { if (inboxOpened === true) { var appWindow = chrome.app.window.get(inboxWindowId); appWindow.contentWindow.openConversation(conversation); @@ -160,7 +159,7 @@ open = conversation; openInbox(); } - } + }; window.getOpenConversation = function() { var o = open; open = null;