mirror of
https://github.com/finos/SymphonyElectron.git
synced 2024-12-27 01:11:13 -06:00
add notification grouping (#48)
This commit is contained in:
parent
75d1342b28
commit
27d58a94d7
@ -34,6 +34,9 @@
|
||||
</body>
|
||||
<script>
|
||||
var notfEl = document.getElementById('notf');
|
||||
var num = 0;
|
||||
|
||||
// note: notification will close when clicked
|
||||
notfEl.addEventListener('click', function() {
|
||||
var title = document.getElementById('title').value;
|
||||
var body = document.getElementById('body').value;
|
||||
@ -41,26 +44,46 @@
|
||||
var shouldFlash = document.getElementById('flash').checked;
|
||||
var color = document.getElementById('color').value;
|
||||
|
||||
num++;
|
||||
|
||||
// notfs with same groupId will replace existing notf.
|
||||
var groupId = (num % 2).toString();
|
||||
var notf = new SYM_API.Notification(title, {
|
||||
body: body,
|
||||
body: (body + ' num=' + num + ' groupId=' + groupId),
|
||||
image: imageUrl,
|
||||
flash: shouldFlash,
|
||||
color: color || 'white',
|
||||
data: {
|
||||
hello: 'hello word'
|
||||
}
|
||||
},
|
||||
groupId: groupId
|
||||
});
|
||||
|
||||
notf.addEventListener('click', function(event) {
|
||||
notf.addEventListener('click', onclick);
|
||||
function onclick(event) {
|
||||
event.target.data.then(function(value) {
|
||||
alert('notification clicked: ' + value.hello);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
notf.addEventListener('close', function() {
|
||||
notf.addEventListener('close', onclose);
|
||||
function onclose() {
|
||||
alert('notification closed');
|
||||
});
|
||||
removeEvents();
|
||||
};
|
||||
|
||||
notf.addEventListener('error', onerror);
|
||||
function onerror(event) {
|
||||
alert('error=' + event.result);
|
||||
};
|
||||
|
||||
// be sure to remove all events when closed, otherwise leaks
|
||||
// will occur.
|
||||
function removeEvents() {
|
||||
notf.removeEventListener('click', onclick)
|
||||
notf.removeEventListener('close', onclose)
|
||||
notf.removeEventListener('error', onerror)
|
||||
}
|
||||
});
|
||||
|
||||
var badgeCount = 0;
|
||||
|
@ -54,11 +54,11 @@ function setContents(notificationObj) {
|
||||
audio.play()
|
||||
}
|
||||
} catch (e) {
|
||||
log('electron-notify: ERROR could not find sound file: ' + notificationObj.sound.replace('file://', ''), e, e.stack)
|
||||
log('electron-notify: ERROR could not find sound file: ' + notificationObj.sound.replace('file://', ''), e, e.stack);
|
||||
}
|
||||
}
|
||||
|
||||
let notiDoc = window.document
|
||||
let notiDoc = window.document;
|
||||
|
||||
let container = notiDoc.getElementById('container');
|
||||
|
||||
@ -78,34 +78,35 @@ function setContents(notificationObj) {
|
||||
}
|
||||
|
||||
// Title
|
||||
let titleDoc = notiDoc.getElementById('title')
|
||||
titleDoc.innerHTML = notificationObj.title || ''
|
||||
let titleDoc = notiDoc.getElementById('title');
|
||||
titleDoc.innerHTML = notificationObj.title || '';
|
||||
|
||||
// message
|
||||
let messageDoc = notiDoc.getElementById('message')
|
||||
messageDoc.innerHTML = notificationObj.text || ''
|
||||
let messageDoc = notiDoc.getElementById('message');
|
||||
messageDoc.innerHTML = notificationObj.text || '';
|
||||
|
||||
// Image
|
||||
let imageDoc = notiDoc.getElementById('image')
|
||||
let imageDoc = notiDoc.getElementById('image');
|
||||
if (notificationObj.image) {
|
||||
imageDoc.src = notificationObj.image
|
||||
imageDoc.src = notificationObj.image;
|
||||
} else {
|
||||
setStyleOnDomElement({ display: 'none'}, imageDoc)
|
||||
setStyleOnDomElement({ display: 'none'}, imageDoc);
|
||||
}
|
||||
|
||||
const winId = notificationObj.windowId;
|
||||
|
||||
// Close button
|
||||
let closeButton = notiDoc.getElementById('close')
|
||||
closeButton.addEventListener('click', function(clickEvent) {
|
||||
let closeButton = notiDoc.getElementById('close');
|
||||
|
||||
// note: use onclick because we only want one handler, for case
|
||||
// when content gets overwritten by notf with same groupId
|
||||
closeButton.onclick = function(clickEvent) {
|
||||
clickEvent.stopPropagation()
|
||||
ipc.send('electron-notify-close', winId, notificationObj)
|
||||
})
|
||||
}
|
||||
|
||||
// URL
|
||||
container.addEventListener('click', function() {
|
||||
ipc.send('electron-notify-click', winId, notificationObj)
|
||||
})
|
||||
container.onclick = function() {
|
||||
ipc.send('electron-notify-click', winId, notificationObj);
|
||||
}
|
||||
}
|
||||
|
||||
function setStyleOnDomElement(styleObj, domElement) {
|
||||
|
@ -229,20 +229,6 @@ function setupConfig() {
|
||||
|
||||
|
||||
function notify(notification) {
|
||||
if (notificationQueue.length >= MAX_QUEUE_SIZE) {
|
||||
var id = latestID;
|
||||
incrementId();
|
||||
if (typeof notification.onErrorFunc === 'function') {
|
||||
setTimeout(function() {
|
||||
notification.onErrorFunc({
|
||||
id: id,
|
||||
error: 'max notification queue size reached: ' + MAX_QUEUE_SIZE
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
// Is it an object and only one argument?
|
||||
if (arguments.length === 1 && typeof notification === 'object') {
|
||||
let notf = Object.assign({}, notification);
|
||||
@ -265,6 +251,54 @@ function incrementId() {
|
||||
|
||||
function showNotification(notificationObj) {
|
||||
return new Promise(function(resolve) {
|
||||
|
||||
if (notificationQueue.length >= MAX_QUEUE_SIZE) {
|
||||
if (typeof notificationObj.onErrorFunc === 'function') {
|
||||
setTimeout(function() {
|
||||
notificationObj.onErrorFunc({
|
||||
id: notificationObj.id,
|
||||
error: 'max notification queue size reached: ' + MAX_QUEUE_SIZE
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
// check if group id provided. should replace existing notification
|
||||
// if has same grouping id.
|
||||
let groupId = notificationObj.groupId;
|
||||
if (groupId) {
|
||||
// first check waiting items
|
||||
for(let i = 0; i < notificationQueue.length; i++) {
|
||||
if (groupId === notificationQueue[ i ].groupId) {
|
||||
notificationQueue[ i ] = notificationObj;
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// next check items being shown
|
||||
for(let i = 0; i < activeNotifications.length; i++) {
|
||||
if (groupId === activeNotifications[ i ].groupId) {
|
||||
let notificationWindow = activeNotifications[ i ];
|
||||
|
||||
// be sure to call close event for existing, so it gets
|
||||
// cleaned up.
|
||||
if (notificationWindow.electronNotifyOnCloseFunc) {
|
||||
notificationWindow.electronNotifyOnCloseFunc({
|
||||
event: 'close',
|
||||
id: notificationObj.id
|
||||
});
|
||||
delete notificationWindow.electronNotifyOnCloseFunc;
|
||||
}
|
||||
setNotificationContents(notificationWindow, notificationObj)
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can we show it?
|
||||
if (activeNotifications.length < config.maxVisibleNotifications) {
|
||||
// Get inactiveWindow or create new:
|
||||
@ -273,62 +307,76 @@ function showNotification(notificationObj) {
|
||||
calcInsertPos()
|
||||
setWindowPosition(notificationWindow, nextInsertPos.x, nextInsertPos.y)
|
||||
|
||||
// Add to activeNotifications
|
||||
activeNotifications.push(notificationWindow)
|
||||
let updatedNotfWindow = setNotificationContents(notificationWindow, notificationObj);
|
||||
|
||||
// Display time per notification basis.
|
||||
let displayTime = notificationObj.displayTime ? notificationObj.displayTime : config.displayTime
|
||||
activeNotifications.push(updatedNotfWindow);
|
||||
|
||||
// Set timeout to hide notification
|
||||
let timeoutId
|
||||
let closeFunc = buildCloseNotification(notificationWindow, notificationObj, function() {
|
||||
return timeoutId
|
||||
})
|
||||
let closeNotificationSafely = buildCloseNotificationSafely(closeFunc)
|
||||
timeoutId = setTimeout(function() {
|
||||
closeNotificationSafely('timeout')
|
||||
}, displayTime)
|
||||
|
||||
// Trigger onShowFunc if existent
|
||||
if (notificationObj.onShowFunc) {
|
||||
notificationObj.onShowFunc({
|
||||
event: 'show',
|
||||
id: notificationObj.id,
|
||||
closeNotification: closeNotificationSafely
|
||||
})
|
||||
}
|
||||
|
||||
var updatedNotificationWindow = notificationWindow;
|
||||
|
||||
// Save onClickFunc in notification window
|
||||
if (notificationObj.onClickFunc) {
|
||||
updatedNotificationWindow.electronNotifyOnClickFunc = notificationObj.onClickFunc
|
||||
} else {
|
||||
delete updatedNotificationWindow.electronNotifyOnClickFunc
|
||||
}
|
||||
|
||||
if (notificationObj.onCloseFunc) {
|
||||
updatedNotificationWindow.electronNotifyOnCloseFunc = notificationObj.onCloseFunc
|
||||
} else {
|
||||
delete updatedNotificationWindow.electronNotifyOnCloseFunc
|
||||
}
|
||||
|
||||
const windowId = notificationWindow.id;
|
||||
// Set contents, ...
|
||||
updatedNotificationWindow.webContents.send('electron-notify-set-contents',
|
||||
Object.assign({ windowId: windowId}, notificationObj));
|
||||
// Show window
|
||||
updatedNotificationWindow.showInactive();
|
||||
resolve(updatedNotificationWindow)
|
||||
resolve(updatedNotfWindow);
|
||||
})
|
||||
} else {
|
||||
// Add to notificationQueue
|
||||
notificationQueue.push(notificationObj)
|
||||
resolve()
|
||||
notificationQueue.push(notificationObj);
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function setNotificationContents(notfWindow, notfObj) {
|
||||
// Display time per notification basis.
|
||||
let displayTime = notfObj.displayTime ? notfObj.displayTime : config.displayTime;
|
||||
|
||||
if (notfWindow.displayTimer) {
|
||||
clearTimeout(notfWindow.displayTimer);
|
||||
}
|
||||
|
||||
// Set timeout to hide notification
|
||||
let timeoutId;
|
||||
let closeFunc = buildCloseNotification(notfWindow, notfObj, function() {
|
||||
return timeoutId
|
||||
});
|
||||
let closeNotificationSafely = buildCloseNotificationSafely(closeFunc);
|
||||
timeoutId = setTimeout(function() {
|
||||
closeNotificationSafely('timeout');
|
||||
}, displayTime);
|
||||
|
||||
var updatedNotificationWindow = notfWindow;
|
||||
|
||||
updatedNotificationWindow.displayTimer = timeoutId;
|
||||
|
||||
updatedNotificationWindow.groupId = notfObj.groupId;
|
||||
|
||||
// Trigger onShowFunc if existent
|
||||
if (notfObj.onShowFunc) {
|
||||
notfObj.onShowFunc({
|
||||
event: 'show',
|
||||
id: notfObj.id,
|
||||
closeNotification: closeNotificationSafely
|
||||
})
|
||||
}
|
||||
|
||||
// Save onClickFunc in notification window
|
||||
if (notfObj.onClickFunc) {
|
||||
updatedNotificationWindow.electronNotifyOnClickFunc = notfObj.onClickFunc
|
||||
} else {
|
||||
delete updatedNotificationWindow.electronNotifyOnClickFunc;
|
||||
}
|
||||
|
||||
if (notfObj.onCloseFunc) {
|
||||
updatedNotificationWindow.electronNotifyOnCloseFunc = notfObj.onCloseFunc
|
||||
} else {
|
||||
delete updatedNotificationWindow.electronNotifyOnCloseFunc;
|
||||
}
|
||||
|
||||
const windowId = notfWindow.id;
|
||||
// Set contents, ...
|
||||
updatedNotificationWindow.webContents.send('electron-notify-set-contents',
|
||||
Object.assign({ windowId: windowId}, notfObj));
|
||||
// Show window
|
||||
updatedNotificationWindow.showInactive();
|
||||
|
||||
return updatedNotificationWindow;
|
||||
}
|
||||
|
||||
// Close notification function
|
||||
function buildCloseNotification(notificationWindow, notificationObj, getTimeoutId) {
|
||||
return function(event) {
|
||||
|
@ -17,6 +17,7 @@ class Notify {
|
||||
image: options.image || options.icon,
|
||||
flash: options.flash,
|
||||
color: options.color,
|
||||
groupId: options.groupId,
|
||||
onShowFunc: onShow.bind(this),
|
||||
onClickFunc: onClick.bind(this),
|
||||
onCloseFunc: onClose.bind(this),
|
||||
@ -35,6 +36,7 @@ class Notify {
|
||||
function onClick(arg) {
|
||||
if (arg.id === this._id) {
|
||||
this.emitter.emit('click');
|
||||
arg.closeNotification();
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +82,7 @@ class Notify {
|
||||
|
||||
removeEventListener(event, cb) {
|
||||
if (event && typeof cb === 'function') {
|
||||
this.emitter.removeEventListener(event, cb);
|
||||
this.emitter.removeListener(event, cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,9 @@ class Notify {
|
||||
* icon {string} url of image to show in notification
|
||||
* flash {bool} true if notification should flash (default false)
|
||||
* color {string} background color for notification
|
||||
* groupId {string} non-empty string to unique identify notf, if another
|
||||
* notification arrives with same groupId then it's content will
|
||||
* replace existing notification.
|
||||
* data {object} arbitrary object to be stored with notification
|
||||
* }
|
||||
*/
|
||||
@ -41,7 +44,8 @@ class Notify {
|
||||
static get permission() {}
|
||||
|
||||
/**
|
||||
* returns data object passed in via constructor options
|
||||
* returns data object passed in via constructor options, return a
|
||||
* promise that will be fullfilled with the data.
|
||||
*/
|
||||
get data() {}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user