diff --git a/Extensions.js b/Extensions.js index 0914efe..743ba43 100644 --- a/Extensions.js +++ b/Extensions.js @@ -2,15 +2,21 @@ const arrConstructor = ([]).constructor; const methods = { callDestroyEvents(notify) { - if(notify.destroyed) return; - if(!notify.destroyEvents) return; - if(notify.destroyEvents.constructor != arrConstructor) return; + if (notify.destroyed) { + return; + } + if (!notify.destroyEvents) { + return; + } + if (notify.destroyEvents.constructor != arrConstructor) { + return; + } for (let i = 0; i < notify.destroyEvents.length; i++) { const event = notify.destroyEvents[i]; - if(typeof event == 'function'){ + if (typeof event == 'function') { try { event(); } - catch(e) { + catch (e) { console.error('Execute onDestroy error:\n' + e); } } @@ -21,24 +27,24 @@ const methods = { }, destroyNotify(notify, manager) { - try { methods.callDestroyEvents(notify); } catch(e) { console.error(e); } - - if(manager.activeNotifications && manager.activeNotifications.constructor == arrConstructor){ + try { methods.callDestroyEvents(notify); } catch (e) { console.error(e); } + + if (manager.activeNotifications && manager.activeNotifications.constructor == arrConstructor) { const index = manager.activeNotifications.indexOf(notify); - if(index > -1){ + if (index > -1) { manager.activeNotifications.splice(index, 1); } setTimeout(() => { - if(manager.activeNotifications.length == 0){ + if (manager.activeNotifications.length == 0) { manager.win.hide(); manager.win.webContents.session.clearCache(); } }, 1000); } - if(manager.onclickEvents && manager.onclickEvents.constructor == arrConstructor){ + if (manager.onclickEvents && manager.onclickEvents.constructor == arrConstructor) { const index = manager.onclickEvents.findIndex(x => x.id == notify.id); - if(index > -1){ + if (index > -1) { manager.onclickEvents.splice(index, 1); } } diff --git a/LICENSE b/LICENSE index 7edc1c2..5b765c9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 fydne +Copyright (c) 2024 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Notify.js b/Notify.js index 9d1371b..21d9283 100644 --- a/Notify.js +++ b/Notify.js @@ -10,7 +10,7 @@ module.exports = class Notify { * @param {string} imageUrl Link to image of notification (file:// or http(s):// or another protocol) * @param {NotifySound} sound Sound to play when a notification is shown */ - constructor(title, body, time = 10, imageUrl = null, sound = null){ + constructor(title, body, time = 10, imageUrl = null, sound = null) { this.id = id++; this.title = title; this.body = body; @@ -27,10 +27,11 @@ module.exports = class Notify { } onDestroy(func) { - if(typeof func != 'function'){ + if (typeof func != 'function') { console.error('func is not a function'); return; } + this.destroyEvents.push(func); } }; \ No newline at end of file diff --git a/NotifyManager.js b/NotifyManager.js index 283471e..66660a4 100644 --- a/NotifyManager.js +++ b/NotifyManager.js @@ -13,7 +13,7 @@ module.exports = class NotifyManager { * 4 - bottom-left; * @param {string} customStyle Your personal style for notifications */ - constructor(position = 1, customStyle = ''){ + constructor(position = 1, customStyle = '') { this.loaded = false; this.position = position; this.onclickEvents = []; @@ -36,49 +36,71 @@ module.exports = class NotifyManager { hasShadow: false, x: (this.position == 1 || this.position == 2) ? display.workAreaSize.width + display.workArea.x - 320 : 0, y: 0, - webPreferences:{ + webPreferences: { devTools: false, preload: __dirname + '/files/preload.js' } }); this.win.setVisibleOnAllWorkspaces(true); - this.win.setIgnoreMouseEvents(true, {forward:true}); + this.win.setIgnoreMouseEvents(true, { forward: true }); this.win.setFocusable(false); - (async() => { + (async () => { await this.win.loadURL('file://' + __dirname + '/files/render.html'); + this.win.webContents.setWindowOpenHandler(({ url }) => { shell.openExternal(url); return { action: 'deny' }; }); + this.win.send('load-position', this.position); this.win.send('custom-style', customStyle); this.loaded = true; //this.win.webContents.openDevTools({mode: 'detach'}); ipcMain.on('notify-manager-set-visibly', (ev, boolean, focus) => { - if(ev.sender != this.win.webContents) return; - this.win.setIgnoreMouseEvents(!boolean, {forward:true}); - if(boolean && focus) this.win.setFocusable(boolean); - else this.win.setFocusable(false); + if (ev.sender != this.win.webContents) { + return; + } + + this.win.setIgnoreMouseEvents(!boolean, { forward: true }); + if (boolean && focus) { + this.win.setFocusable(boolean); + } else { + this.win.setFocusable(false); + } }); + ipcMain.on('notify-manager-onclick', (ev, id) => { - if(ev.sender != this.win.webContents) return; + if (ev.sender != this.win.webContents) { + return; + } + const element = this.onclickEvents.find(x => x.id == id); - if(!element) return; - try{ - if(typeof element.event == 'function'){ + if (!element) { + return; + } + + try { + if (typeof element.event == 'function') { element.event(); } - }catch(e){ + } catch (e) { console.error(e); } }); + ipcMain.on('notify-manager-destory', (ev, id) => { - if(ev.sender != this.win.webContents) return; + if (ev.sender != this.win.webContents) { + return; + } + const notify = this.activeNotifications.find(x => x.id == id); - if(!notify) return; + if (!notify) { + return; + } + Extensions.destroyNotify(notify, this); }); })(); @@ -87,7 +109,7 @@ module.exports = class NotifyManager { isLoaded() { return this.loaded; } - + getWindow() { return this.win; } @@ -95,9 +117,11 @@ module.exports = class NotifyManager { /** * @param {Notify} notify Notification to show */ - async show(notify, onclick = null){ - while(!this.loaded) await delay(1000); - + async show(notify, onclick = null) { + while (!this.loaded) { + await delay(100); + } + this.win.showInactive(); this.win.send('show', { id: notify.id, @@ -110,12 +134,8 @@ module.exports = class NotifyManager { this.activeNotifications.push(notify); - setTimeout(() => { - Extensions.destroyNotify(notify, this); - }, notify.time * 1000); - - if(onclick){ - if(typeof onclick != 'function'){ + if (onclick) { + if (typeof onclick != 'function') { console.error('onclick is not a function'); return notify; } @@ -128,12 +148,15 @@ module.exports = class NotifyManager { return notify; } - + /** * @param {Notify} notify Notification to destroy */ - destroy(notify){ - if(!this.loaded) throw new Error('window not initialized yet'); + destroy(notify) { + if (!this.loaded) { + throw new Error('window not initialized yet'); + } + this.win.send('destroy', { id: notify.id, sound: notify.sound diff --git a/NotifySound.js b/NotifySound.js index 4b62d95..e1240c8 100644 --- a/NotifySound.js +++ b/NotifySound.js @@ -3,7 +3,7 @@ module.exports = class NotifySound { * @param {string} url URL to sound (file:// or http(s):// or another protocol) * @param {number} volume Volume set during playback (0 to 100) */ - constructor(url, volume = 100){ + constructor(url, volume = 100) { this.url = url; this.volume = volume; } diff --git a/README.md b/README.md index 2439044..07c901d 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,11 @@ Create beautiful and functional notifications on electron
# Info -You can test the library with `npm run test` or `npm run test.reply`. And also see the source code of [examples](https://github.com/fydne/Notify-Manager-electron/tree/main/examples) +You can test the library with `npm run test` or `npm run test.reply`. And also see the source code of [examples](https://github.com/zxcnoname666/Notify-Manager-electron/tree/main/examples) #### Approximate result: - + > You can change the appearance of the notification by adding your style when creating the NotifyManager @@ -22,14 +22,14 @@ You can use your own sounds when showing a notification. # Demo ## Standart notify -Example: [Click](https://github.com/fydne/Notify-Manager-electron/tree/main/examples/small.js) +Example: [Click](https://github.com/zxcnoname666/Notify-Manager-electron/tree/main/examples/small.js) Demo: https://user-images.githubusercontent.com/121295212/219909789-5f343998-814b-4c2a-814b-d290ea1fe3a2.mp4 ## Reply notify -Example: [Click](https://github.com/fydne/Notify-Manager-electron/tree/main/examples/reply) +Example: [Click](https://github.com/zxcnoname666/Notify-Manager-electron/tree/main/examples/reply) Demo: @@ -78,7 +78,7 @@ const { shell } = require('electron'); const notify = new Notify('Click hook', 'Click to open link'); -_manager.show(notify, () => shell.openExternal('https://github.com/fydne/notify-manager-electron')); +_manager.show(notify, () => shell.openExternal('https://github.com/zxcnoname666/notify-manager-electron')); ``` #### Notification with image & custom duration Recommended image size - 55x55px @@ -90,18 +90,15 @@ const notify = new Notify('Your App', 'Your beautiful message', duration, 'https _manager.show(notify); ``` #### Notify with sound -##### Attention: It is not recommended to use music playing for a long time. Instead, use sounds up to 10 seconds long. The example below uses music for demonstration purposes only. +##### Attention: It is not recommended to use music playing for a long time. Instead, use sounds up to 10 seconds long. ```javascript // url, volume -const sound = new NotifySound('https://cdn.fydne.dev/another/rgq05ekp8k4k/sneg.mp3', 50); +const sound = new NotifySound('https://github.com/zxcnoname666/repo-files/raw/main/notify-manager-electron/meow1.mp3', 50); -const body = 'notify with sound & html'+ -''; -const image = 'https://github.com/fydne/SoundCloud-Desktop/raw/main/icons/appLogo.png'; +const body = 'text'; +const image = 'https://github.com/zxcnoname666/SoundCloud-Desktop/raw/main/icons/appLogo.png'; -const notify = new Notify('Notify', body, 60, image, sound); +const notify = new Notify('notify with sound & html', body, 60, image, sound); // show notify _manager.show(notify); diff --git a/examples/reply/script.js b/examples/reply/script.js index cb0dfde..d477d18 100644 --- a/examples/reply/script.js +++ b/examples/reply/script.js @@ -6,31 +6,36 @@ const fs = require('original-fs'); const text = fs.readFileSync(__dirname + '/body.html', 'utf-8'); -const init = async() => { +const init = async () => { const _manager = new Manager(2); const uid = GenerateRandom(); - const _notify = new Notify('New message', '', 10, null, new Sound('https://cdn.fydne.dev/another/sdb1c4qrbpt5/meow1.mp3', 50)); + const _notify = new Notify('New message', '', 10, null, new Sound('https://github.com/zxcnoname666/repo-files/raw/main/notify-manager-electron/meow1.mp3', 50)); _notify.body = text - .replaceAll('{message}', GenerateMessage()) - .replaceAll('{uid}', uid) - .replaceAll('{notify.id}', _notify.id); + .replaceAll('{message}', GenerateMessage()) + .replaceAll('{uid}', uid) + .replaceAll('{notify.id}', _notify.id); ipcMain.on('reply.message', (ev, id, message) => { - if(ev.sender != _manager.win.webContents) return; + if (ev.sender != _manager.win.webContents) { + return; + } + console.log(`received reply from notify (id: ${id} / current notify: ${id == uid}):\n${message}\n------------------------`); _manager.destroy(_notify); }); - + _manager.show(_notify); }; app.whenReady().then(() => { init(); app.on('activate', function () { - if (BrowserWindow.getAllWindows().length === 0) init(); + if (BrowserWindow.getAllWindows().length === 0) { + init(); + } }); }); @@ -41,10 +46,15 @@ function GenerateMessage() { 'Hi. Do you even go for a walk sometimes?', 'There will be an event today at 12 a.m. Will you come with us?' ]; + const rand = Math.round(Math.random() * messages.length); - if(0 >= rand) return 'Hello. How are you?'; + if (0 >= rand) { + return 'Hello. How are you?'; + } + return messages[rand - 1]; } + function GenerateRandom() { - return 'xxxxxxxxxxxx'.replace(/[x]/g, () => (Math.random()*32|0).toString(32)); + return 'xxxxxxxxxxxx'.replace(/[x]/g, () => (Math.random() * 32 | 0).toString(32)); } \ No newline at end of file diff --git a/examples/small.js b/examples/small.js index e7efa04..b301525 100644 --- a/examples/small.js +++ b/examples/small.js @@ -6,30 +6,38 @@ const Sound = require('../files/index').NotifySound; app.whenReady().then(() => { init(); app.on('activate', function () { - if (BrowserWindow.getAllWindows().length === 0) init(); + if (BrowserWindow.getAllWindows().length === 0) { + init(); + } }); }); async function init() { const _manager = new Manager(1); + const _notify = new Notify('hello', 'this is test'); _notify.onDestroy(() => console.log('first notify has been destroyed')); _manager.show(_notify); + _manager.show(new Notify('test', 'something text')); + const _t = await _manager.show(new Notify('yea?', 'hide it in one second')); setTimeout(() => _manager.destroy(_t), 1000); - setTimeout(() => _manager.show(new Notify('notify', 'text after 10 seconds')), 10000); + + setTimeout(() => { + _manager.show(new Notify('notify', 'text after 10 seconds')); + }, 10000); + setTimeout(() => { // Open by click - _manager.show(new Notify('notify', 'click to open link', 20), () => shell.openExternal('https://github.com/fydne/notify-manager-electron')); + _manager.show(new Notify('notify', 'click to open link', 20), () => shell.openExternal('https://github.com/zxcnoname666/notify-manager-electron')); }, 11000); + setTimeout(() => { - // Play and open music on soundcloud - _manager.show(new Notify('notify', 'notify with sound & html'+ - '', - 45, 'https://github.com/fydne/SoundCloud-Desktop/raw/main/icons/appLogo.png', - new Sound('https://cdn.fydne.dev/another/rgq05ekp8k4k/sneg.mp3', 50))); + // Play notify and open music on soundcloud + _manager.show(new Notify('notify with sound & html', 'meow', + 10, 'https://github.com/favicon.ico', + new Sound('https://github.com/zxcnoname666/repo-files/raw/main/notify-manager-electron/meow1.mp3', 50) + )); }, 20000); }; \ No newline at end of file diff --git a/files/index.d.ts b/files/index.d.ts index 86926cb..34c9980 100644 --- a/files/index.d.ts +++ b/files/index.d.ts @@ -61,7 +61,7 @@ export class Notify { * changing it afterwards will not affect to the notification. */ sound?: NotifySound; - + /** * Returns a boolean variable indicating whether the * notification was destroyed in any way. @@ -73,7 +73,7 @@ export class Notify { * * @param func The function that will be called when the notification is destroyed. */ - onDestroy(func: void) : void; + onDestroy(func: void): void; }; export class NotifySound { @@ -106,22 +106,22 @@ export class NotifyManager { * @param notify Notification to show * @param onclick onClick callback */ - async show(notify: Notify, onclick: void = null) : Notify; - + async show(notify: Notify, onclick: void = null): Promise