add badge count api (#28)

This commit is contained in:
Lynn 2017-03-06 21:09:10 -08:00 committed by GitHub
parent 71387c1dce
commit 4645f3a21e
4 changed files with 135 additions and 5 deletions

50
js/badgeCount.js Normal file
View File

@ -0,0 +1,50 @@
'use strict';
const electron = require('electron');
const app = electron.app;
const nativeImage = electron.nativeImage;
const { isMac } = require('./utils.js');
const windowMgr = require('./windowMgr.js');
const maxCount = 1e8;
function show(count) {
if (typeof count !== 'number') {
return;
}
if (isMac) {
// too big of a number here and setBadgeCount crashes
app.setBadgeCount(Math.min(maxCount, count));
return;
}
// handle ms windows...
const mainWindow = windowMgr.getMainWindow();
if (mainWindow) {
if (count > 0) {
// get badge img from renderer process, will return
// img dataUrl in setDataUrl func.
mainWindow.send('createBadgeDataUrl', { count: count });
} else {
// clear badge count icon
mainWindow.setOverlayIcon(null, '');
}
}
}
function setDataUrl(dataUrl, count) {
const mainWindow = windowMgr.getMainWindow();
if (mainWindow && dataUrl && count) {
let img = nativeImage.createFromDataURL(dataUrl);
// for accessibility screen readers
const desc = 'Symphony has ' + count + ' unread messages';
mainWindow.setOverlayIcon(img, desc);
}
}
module.exports = {
show: show,
setDataUrl: setDataUrl
}

View File

@ -8,6 +8,7 @@ const electron = require('electron');
const windowMgr = require('./windowMgr.js');
const log = require('./log.js');
const badgeCount = require('./badgeCount.js');
/**
* Ensure events comes from a window that we have created.
@ -78,18 +79,29 @@ electron.ipcMain.on('symphony-api', (event, arg) => {
return;
}
if (arg.cmd === 'isOnline') {
if (arg.cmd === 'isOnline' && typeof arg.isOnline === 'boolean') {
windowMgr.setIsOnline(arg.isOnline);
return;
}
if (arg.cmd === 'setBadgeCount' && typeof arg.count === 'number') {
badgeCount.show(arg.count);
return;
}
if (arg.cmd === 'badgeDataUrl' && typeof arg.dataUrl === 'string' &&
typeof arg.count === 'number') {
badgeCount.setDataUrl(arg.dataUrl, arg.count);
return;
}
if (arg.cmd === 'registerLogger') {
// renderer window that has a registered logger from JS.
log.setLogWindow(event.sender);
return;
}
if (arg.cmd === 'open' && arg.url) {
if (arg.cmd === 'open' && typeof arg.url === 'string') {
let title = arg.title || 'Symphony';
let width = arg.width || 1024;
let height = arg.height || 768;

View File

@ -36,6 +36,21 @@ window.SYM_API = {
});
},
/**
* sets the count on the tray icon to the given number.
* @param {number} count count to be displayed
* note: count of 0 will remove the displayed count.
* note: for mac the number displayed will be 0 to 49 and 50+
* note: for windws the number displayed will be 0 to 9 and 10+ (since imgs
* are used here).
*/
setBadgeCount: function(count) {
local.ipcRenderer.send(api, {
cmd: 'setBadgeCount',
count: count
});
},
/**
* allows JS to register a logger that can be used by electron main process.
* @param {Object} logger function that can be called accepting
@ -59,8 +74,10 @@ window.SYM_API = {
}
};
Object.freeze(window.SYM_API);
// listen for log message from main process
local.ipcRenderer.on('log', (event, arg) => {
local.ipcRenderer.on('log', (arg) => {
if (local.logger && arg && arg.level && arg.msg) {
local.logger({
logLevel: arg.level,
@ -69,6 +86,54 @@ local.ipcRenderer.on('log', (event, arg) => {
}
});
/**
* Use render process to create badge count img and send back to main process.
* If number is greater than 99 then 99+ img is returned.
* note: with sandboxing turned on only get arg and no event passed in, so
* need to use ipcRenderer to callback to main process.
* @type {object} arg.count - number: count to be displayed
*/
local.ipcRenderer.on('createBadgeDataUrl', (arg) => {
const count = arg && arg.count || 0;
// create 32 x 32 img
let radius = 16;
let canvas = document.createElement('canvas');
canvas.height = radius * 2;
canvas.width = radius * 2;
let ctx = canvas.getContext('2d');
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(radius, radius, radius, 0, 2 * Math.PI, false);
ctx.fill();
ctx.textAlign = 'center';
ctx.fillStyle = 'white';
let text = count > 99 ? '99+' : count.toString();
if (text.length > 2) {
ctx.font = 'bold 18px sans-serif';
ctx.fillText(text, radius, 22);
} else if (text.length > 1) {
ctx.font = 'bold 24px sans-serif';
ctx.fillText(text, radius, 24);
} else {
ctx.font = 'bold 26px sans-serif';
ctx.fillText(text, radius, 26);
}
let dataUrl = canvas.toDataURL('image/png', 1.0);
local.ipcRenderer.send(api, {
cmd: 'badgeDataUrl',
dataUrl: dataUrl,
count: count
});
});
function updateOnlineStatus() {
local.ipcRenderer.send(api, {
cmd: 'isOnline',
@ -80,5 +145,3 @@ window.addEventListener('offline', updateOnlineStatus, false);
window.addEventListener('online', updateOnlineStatus, false);
updateOnlineStatus();
Object.freeze(window.SYM_API);

View File

@ -112,6 +112,10 @@ app.on('before-quit', function() {
willQuitApp = true;
});
function getMainWindow() {
return mainWindow;
}
function showMainWindow() {
mainWindow.show();
}
@ -164,6 +168,7 @@ function setIsOnline(status) {
module.exports = {
createMainWindow: createMainWindow,
getMainWindow: getMainWindow,
showMainWindow: showMainWindow,
isMainWindow: isMainWindow,
hasWindow: hasWindow,