mirror of
https://github.com/finos/SymphonyElectron.git
synced 2024-12-28 09:51:06 -06:00
add notification grouping (#48)
This commit is contained in:
parent
75d1342b28
commit
27d58a94d7
@ -34,6 +34,9 @@
|
|||||||
</body>
|
</body>
|
||||||
<script>
|
<script>
|
||||||
var notfEl = document.getElementById('notf');
|
var notfEl = document.getElementById('notf');
|
||||||
|
var num = 0;
|
||||||
|
|
||||||
|
// note: notification will close when clicked
|
||||||
notfEl.addEventListener('click', function() {
|
notfEl.addEventListener('click', function() {
|
||||||
var title = document.getElementById('title').value;
|
var title = document.getElementById('title').value;
|
||||||
var body = document.getElementById('body').value;
|
var body = document.getElementById('body').value;
|
||||||
@ -41,26 +44,46 @@
|
|||||||
var shouldFlash = document.getElementById('flash').checked;
|
var shouldFlash = document.getElementById('flash').checked;
|
||||||
var color = document.getElementById('color').value;
|
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, {
|
var notf = new SYM_API.Notification(title, {
|
||||||
body: body,
|
body: (body + ' num=' + num + ' groupId=' + groupId),
|
||||||
image: imageUrl,
|
image: imageUrl,
|
||||||
flash: shouldFlash,
|
flash: shouldFlash,
|
||||||
color: color || 'white',
|
color: color || 'white',
|
||||||
data: {
|
data: {
|
||||||
hello: 'hello word'
|
hello: 'hello word'
|
||||||
}
|
},
|
||||||
|
groupId: groupId
|
||||||
});
|
});
|
||||||
|
|
||||||
notf.addEventListener('click', function(event) {
|
notf.addEventListener('click', onclick);
|
||||||
|
function onclick(event) {
|
||||||
event.target.data.then(function(value) {
|
event.target.data.then(function(value) {
|
||||||
alert('notification clicked: ' + value.hello);
|
alert('notification clicked: ' + value.hello);
|
||||||
})
|
})
|
||||||
});
|
}
|
||||||
|
|
||||||
notf.addEventListener('close', function() {
|
notf.addEventListener('close', onclose);
|
||||||
|
function onclose() {
|
||||||
alert('notification closed');
|
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;
|
var badgeCount = 0;
|
||||||
|
@ -54,11 +54,11 @@ function setContents(notificationObj) {
|
|||||||
audio.play()
|
audio.play()
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} 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');
|
let container = notiDoc.getElementById('container');
|
||||||
|
|
||||||
@ -78,34 +78,35 @@ function setContents(notificationObj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
let titleDoc = notiDoc.getElementById('title')
|
let titleDoc = notiDoc.getElementById('title');
|
||||||
titleDoc.innerHTML = notificationObj.title || ''
|
titleDoc.innerHTML = notificationObj.title || '';
|
||||||
|
|
||||||
// message
|
// message
|
||||||
let messageDoc = notiDoc.getElementById('message')
|
let messageDoc = notiDoc.getElementById('message');
|
||||||
messageDoc.innerHTML = notificationObj.text || ''
|
messageDoc.innerHTML = notificationObj.text || '';
|
||||||
|
|
||||||
// Image
|
// Image
|
||||||
let imageDoc = notiDoc.getElementById('image')
|
let imageDoc = notiDoc.getElementById('image');
|
||||||
if (notificationObj.image) {
|
if (notificationObj.image) {
|
||||||
imageDoc.src = notificationObj.image
|
imageDoc.src = notificationObj.image;
|
||||||
} else {
|
} else {
|
||||||
setStyleOnDomElement({ display: 'none'}, imageDoc)
|
setStyleOnDomElement({ display: 'none'}, imageDoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
const winId = notificationObj.windowId;
|
const winId = notificationObj.windowId;
|
||||||
|
|
||||||
// Close button
|
let closeButton = notiDoc.getElementById('close');
|
||||||
let closeButton = notiDoc.getElementById('close')
|
|
||||||
closeButton.addEventListener('click', function(clickEvent) {
|
// 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()
|
clickEvent.stopPropagation()
|
||||||
ipc.send('electron-notify-close', winId, notificationObj)
|
ipc.send('electron-notify-close', winId, notificationObj)
|
||||||
})
|
}
|
||||||
|
|
||||||
// URL
|
container.onclick = function() {
|
||||||
container.addEventListener('click', function() {
|
ipc.send('electron-notify-click', winId, notificationObj);
|
||||||
ipc.send('electron-notify-click', winId, notificationObj)
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setStyleOnDomElement(styleObj, domElement) {
|
function setStyleOnDomElement(styleObj, domElement) {
|
||||||
|
@ -229,20 +229,6 @@ function setupConfig() {
|
|||||||
|
|
||||||
|
|
||||||
function notify(notification) {
|
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?
|
// Is it an object and only one argument?
|
||||||
if (arguments.length === 1 && typeof notification === 'object') {
|
if (arguments.length === 1 && typeof notification === 'object') {
|
||||||
let notf = Object.assign({}, notification);
|
let notf = Object.assign({}, notification);
|
||||||
@ -265,6 +251,54 @@ function incrementId() {
|
|||||||
|
|
||||||
function showNotification(notificationObj) {
|
function showNotification(notificationObj) {
|
||||||
return new Promise(function(resolve) {
|
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?
|
// Can we show it?
|
||||||
if (activeNotifications.length < config.maxVisibleNotifications) {
|
if (activeNotifications.length < config.maxVisibleNotifications) {
|
||||||
// Get inactiveWindow or create new:
|
// Get inactiveWindow or create new:
|
||||||
@ -273,60 +307,74 @@ function showNotification(notificationObj) {
|
|||||||
calcInsertPos()
|
calcInsertPos()
|
||||||
setWindowPosition(notificationWindow, nextInsertPos.x, nextInsertPos.y)
|
setWindowPosition(notificationWindow, nextInsertPos.x, nextInsertPos.y)
|
||||||
|
|
||||||
// Add to activeNotifications
|
let updatedNotfWindow = setNotificationContents(notificationWindow, notificationObj);
|
||||||
activeNotifications.push(notificationWindow)
|
|
||||||
|
|
||||||
|
activeNotifications.push(updatedNotfWindow);
|
||||||
|
|
||||||
|
resolve(updatedNotfWindow);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Add to notificationQueue
|
||||||
|
notificationQueue.push(notificationObj);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function setNotificationContents(notfWindow, notfObj) {
|
||||||
// Display time per notification basis.
|
// Display time per notification basis.
|
||||||
let displayTime = notificationObj.displayTime ? notificationObj.displayTime : config.displayTime
|
let displayTime = notfObj.displayTime ? notfObj.displayTime : config.displayTime;
|
||||||
|
|
||||||
|
if (notfWindow.displayTimer) {
|
||||||
|
clearTimeout(notfWindow.displayTimer);
|
||||||
|
}
|
||||||
|
|
||||||
// Set timeout to hide notification
|
// Set timeout to hide notification
|
||||||
let timeoutId
|
let timeoutId;
|
||||||
let closeFunc = buildCloseNotification(notificationWindow, notificationObj, function() {
|
let closeFunc = buildCloseNotification(notfWindow, notfObj, function() {
|
||||||
return timeoutId
|
return timeoutId
|
||||||
})
|
});
|
||||||
let closeNotificationSafely = buildCloseNotificationSafely(closeFunc)
|
let closeNotificationSafely = buildCloseNotificationSafely(closeFunc);
|
||||||
timeoutId = setTimeout(function() {
|
timeoutId = setTimeout(function() {
|
||||||
closeNotificationSafely('timeout')
|
closeNotificationSafely('timeout');
|
||||||
}, displayTime)
|
}, displayTime);
|
||||||
|
|
||||||
|
var updatedNotificationWindow = notfWindow;
|
||||||
|
|
||||||
|
updatedNotificationWindow.displayTimer = timeoutId;
|
||||||
|
|
||||||
|
updatedNotificationWindow.groupId = notfObj.groupId;
|
||||||
|
|
||||||
// Trigger onShowFunc if existent
|
// Trigger onShowFunc if existent
|
||||||
if (notificationObj.onShowFunc) {
|
if (notfObj.onShowFunc) {
|
||||||
notificationObj.onShowFunc({
|
notfObj.onShowFunc({
|
||||||
event: 'show',
|
event: 'show',
|
||||||
id: notificationObj.id,
|
id: notfObj.id,
|
||||||
closeNotification: closeNotificationSafely
|
closeNotification: closeNotificationSafely
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var updatedNotificationWindow = notificationWindow;
|
|
||||||
|
|
||||||
// Save onClickFunc in notification window
|
// Save onClickFunc in notification window
|
||||||
if (notificationObj.onClickFunc) {
|
if (notfObj.onClickFunc) {
|
||||||
updatedNotificationWindow.electronNotifyOnClickFunc = notificationObj.onClickFunc
|
updatedNotificationWindow.electronNotifyOnClickFunc = notfObj.onClickFunc
|
||||||
} else {
|
} else {
|
||||||
delete updatedNotificationWindow.electronNotifyOnClickFunc
|
delete updatedNotificationWindow.electronNotifyOnClickFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notificationObj.onCloseFunc) {
|
if (notfObj.onCloseFunc) {
|
||||||
updatedNotificationWindow.electronNotifyOnCloseFunc = notificationObj.onCloseFunc
|
updatedNotificationWindow.electronNotifyOnCloseFunc = notfObj.onCloseFunc
|
||||||
} else {
|
} else {
|
||||||
delete updatedNotificationWindow.electronNotifyOnCloseFunc
|
delete updatedNotificationWindow.electronNotifyOnCloseFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
const windowId = notificationWindow.id;
|
const windowId = notfWindow.id;
|
||||||
// Set contents, ...
|
// Set contents, ...
|
||||||
updatedNotificationWindow.webContents.send('electron-notify-set-contents',
|
updatedNotificationWindow.webContents.send('electron-notify-set-contents',
|
||||||
Object.assign({ windowId: windowId}, notificationObj));
|
Object.assign({ windowId: windowId}, notfObj));
|
||||||
// Show window
|
// Show window
|
||||||
updatedNotificationWindow.showInactive();
|
updatedNotificationWindow.showInactive();
|
||||||
resolve(updatedNotificationWindow)
|
|
||||||
})
|
return updatedNotificationWindow;
|
||||||
} else {
|
|
||||||
// Add to notificationQueue
|
|
||||||
notificationQueue.push(notificationObj)
|
|
||||||
resolve()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close notification function
|
// Close notification function
|
||||||
|
@ -17,6 +17,7 @@ class Notify {
|
|||||||
image: options.image || options.icon,
|
image: options.image || options.icon,
|
||||||
flash: options.flash,
|
flash: options.flash,
|
||||||
color: options.color,
|
color: options.color,
|
||||||
|
groupId: options.groupId,
|
||||||
onShowFunc: onShow.bind(this),
|
onShowFunc: onShow.bind(this),
|
||||||
onClickFunc: onClick.bind(this),
|
onClickFunc: onClick.bind(this),
|
||||||
onCloseFunc: onClose.bind(this),
|
onCloseFunc: onClose.bind(this),
|
||||||
@ -35,6 +36,7 @@ class Notify {
|
|||||||
function onClick(arg) {
|
function onClick(arg) {
|
||||||
if (arg.id === this._id) {
|
if (arg.id === this._id) {
|
||||||
this.emitter.emit('click');
|
this.emitter.emit('click');
|
||||||
|
arg.closeNotification();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +82,7 @@ class Notify {
|
|||||||
|
|
||||||
removeEventListener(event, cb) {
|
removeEventListener(event, cb) {
|
||||||
if (event && typeof cb === 'function') {
|
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
|
* icon {string} url of image to show in notification
|
||||||
* flash {bool} true if notification should flash (default false)
|
* flash {bool} true if notification should flash (default false)
|
||||||
* color {string} background color for notification
|
* 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
|
* data {object} arbitrary object to be stored with notification
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
@ -41,7 +44,8 @@ class Notify {
|
|||||||
static get permission() {}
|
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() {}
|
get data() {}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user