mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-02-25 18:55:29 -06:00
SDA-4614 - Add toast stacking and unstacking logic (#2189)
This commit is contained in:
parent
fa515accb7
commit
8d06432c00
254
package-lock.json
generated
254
package-lock.json
generated
@ -1,18 +1,17 @@
|
||||
{
|
||||
"name": "symphony",
|
||||
"version": "24.9.0",
|
||||
"version": "24.10.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "symphony",
|
||||
"version": "24.9.0",
|
||||
"version": "24.10.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/lazy-brush": "^1.0.0",
|
||||
"adm-zip": "^0.5.10",
|
||||
"async.map": "0.5.2",
|
||||
"classnames": "2.2.6",
|
||||
"electron-dl": "3.5.0",
|
||||
"electron-fetch": "1.9.1",
|
||||
@ -38,9 +37,10 @@
|
||||
"@types/react-dom": "16.9.17",
|
||||
"browserify": "17.0.0",
|
||||
"builder-util-runtime": "^9.0.3",
|
||||
"cheerio": "v1.0.0-rc.12",
|
||||
"cross-env": "7.0.3",
|
||||
"del": "3.0.0",
|
||||
"electron": "31.4.0",
|
||||
"electron": "32.0.1",
|
||||
"electron-builder": "^24.13.2",
|
||||
"electron-devtools-installer": "^3.2.0",
|
||||
"electron-icon-maker": "0.0.5",
|
||||
@ -3769,75 +3769,6 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/async.eachof": {
|
||||
"version": "0.5.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"async.util.keyiterator": "0.5.2",
|
||||
"async.util.noop": "0.5.2",
|
||||
"async.util.once": "0.5.2",
|
||||
"async.util.onlyonce": "0.5.2"
|
||||
}
|
||||
},
|
||||
"node_modules/async.map": {
|
||||
"version": "0.5.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"async.util.doparallel": "0.5.2",
|
||||
"async.util.mapasync": "0.5.2"
|
||||
}
|
||||
},
|
||||
"node_modules/async.util.doparallel": {
|
||||
"version": "0.5.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"async.eachof": "0.5.2"
|
||||
}
|
||||
},
|
||||
"node_modules/async.util.isarray": {
|
||||
"version": "0.5.2",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/async.util.isarraylike": {
|
||||
"version": "0.5.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"async.util.isarray": "0.5.2"
|
||||
}
|
||||
},
|
||||
"node_modules/async.util.keyiterator": {
|
||||
"version": "0.5.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"async.util.isarraylike": "0.5.2",
|
||||
"async.util.keys": "0.5.2"
|
||||
}
|
||||
},
|
||||
"node_modules/async.util.keys": {
|
||||
"version": "0.5.2",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/async.util.mapasync": {
|
||||
"version": "0.5.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"async.util.isarraylike": "0.5.2",
|
||||
"async.util.noop": "0.5.2",
|
||||
"async.util.once": "0.5.2"
|
||||
}
|
||||
},
|
||||
"node_modules/async.util.noop": {
|
||||
"version": "0.5.2",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/async.util.once": {
|
||||
"version": "0.5.2",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/async.util.onlyonce": {
|
||||
"version": "0.5.2",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"dev": true,
|
||||
@ -4190,8 +4121,9 @@
|
||||
},
|
||||
"node_modules/boolbase": {
|
||||
"version": "1.0.0",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/boolean": {
|
||||
"version": "3.2.0",
|
||||
@ -4835,35 +4767,35 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cheerio": {
|
||||
"version": "1.0.0-rc.5",
|
||||
"version": "1.0.0-rc.12",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/cheerio/-/cheerio-1.0.0-rc.12.tgz",
|
||||
"integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cheerio-select-tmp": "^0.1.0",
|
||||
"dom-serializer": "~1.2.0",
|
||||
"domhandler": "^4.0.0",
|
||||
"entities": "~2.1.0",
|
||||
"htmlparser2": "^6.0.0",
|
||||
"parse5": "^6.0.0",
|
||||
"parse5-htmlparser2-tree-adapter": "^6.0.0"
|
||||
"cheerio-select": "^2.1.0",
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"htmlparser2": "^8.0.1",
|
||||
"parse5": "^7.0.0",
|
||||
"parse5-htmlparser2-tree-adapter": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.12"
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/cheerio-select-tmp": {
|
||||
"version": "0.1.1",
|
||||
"node_modules/cheerio-select": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/cheerio-select/-/cheerio-select-2.1.0.tgz",
|
||||
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"css-select": "^3.1.2",
|
||||
"css-what": "^4.0.0",
|
||||
"domelementtype": "^2.1.0",
|
||||
"domhandler": "^4.0.0",
|
||||
"domutils": "^2.4.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
"boolbase": "^1.0.0",
|
||||
"css-select": "^5.1.0",
|
||||
"css-what": "^6.1.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/chownr": {
|
||||
@ -5544,29 +5476,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/css-select": {
|
||||
"version": "3.1.2",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/css-select/-/css-select-5.1.0.tgz",
|
||||
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-what": "^4.0.0",
|
||||
"domhandler": "^4.0.0",
|
||||
"domutils": "^2.4.3",
|
||||
"nth-check": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
"css-what": "^6.1.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"domutils": "^3.0.1",
|
||||
"nth-check": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/css-what": {
|
||||
"version": "4.0.0",
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/css-what/-/css-what-6.1.0.tgz",
|
||||
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/css/node_modules/source-map": {
|
||||
@ -6157,16 +6085,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "1.2.0",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.0.0",
|
||||
"entities": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"entities": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-walk": {
|
||||
@ -6184,14 +6110,9 @@
|
||||
},
|
||||
"node_modules/domelementtype": {
|
||||
"version": "2.3.0",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"license": "BSD-2-Clause"
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/domexception": {
|
||||
"version": "1.0.1",
|
||||
@ -6202,30 +6123,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/domhandler": {
|
||||
"version": "4.3.1",
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/domhandler/-/domhandler-5.0.3.tgz",
|
||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.2.0"
|
||||
"domelementtype": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "2.8.0",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/domutils/-/domutils-3.1.0.tgz",
|
||||
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
@ -6330,9 +6247,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron": {
|
||||
"version": "31.4.0",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/electron/-/electron-31.4.0.tgz",
|
||||
"integrity": "sha512-YTwKoAA+nrJMlI1TTHnIXLYWoQLKnhbkz0qxZcI7Hadcy0UaFMFs9xzwvH2MnrRpVJy7RKo49kVGuvSdRl8zMA==",
|
||||
"version": "32.0.1",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/electron/-/electron-32.0.1.tgz",
|
||||
"integrity": "sha512-5Hd5Jaf9niYVR2hZxoRd3gOrcxPOxQV1XPV5WaoSfT9jLJHFadhlKtuSDIk3U6rQZke+aC7GqPPAv55nWFCMsA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
@ -6922,11 +6839,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "2.1.0",
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/env-paths": {
|
||||
@ -9245,21 +9163,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "6.1.0",
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.0.0",
|
||||
"domutils": "^2.5.2",
|
||||
"entities": "^2.0.0"
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"entities": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/http-cache-semantics": {
|
||||
@ -12833,13 +12745,11 @@
|
||||
},
|
||||
"node_modules/nth-check": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/nth-check/-/nth-check-2.1.1.tgz",
|
||||
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/nth-check?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/number-is-nan": {
|
||||
@ -13316,16 +13226,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/parse5": {
|
||||
"version": "6.0.1",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/parse5/-/parse5-7.1.2.tgz",
|
||||
"integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dependencies": {
|
||||
"entities": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5-htmlparser2-tree-adapter": {
|
||||
"version": "6.0.1",
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://repo.symphony.com/artifactory/api/npm/npm-virtual-dev/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
|
||||
"integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"parse5": "^6.0.1"
|
||||
"domhandler": "^5.0.2",
|
||||
"parse5": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pascalcase": {
|
||||
|
@ -216,7 +216,6 @@
|
||||
"dependencies": {
|
||||
"@types/lazy-brush": "^1.0.0",
|
||||
"adm-zip": "^0.5.10",
|
||||
"async.map": "0.5.2",
|
||||
"classnames": "2.2.6",
|
||||
"electron-dl": "3.5.0",
|
||||
"electron-fetch": "1.9.1",
|
||||
|
@ -120,6 +120,7 @@ class CallNotification {
|
||||
this.callNotificationWindow.once('closed', () => {
|
||||
this.callNotificationWindow = undefined;
|
||||
});
|
||||
notification.stack();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -127,7 +128,8 @@ class CallNotification {
|
||||
*
|
||||
* @param clientId {number}
|
||||
*/
|
||||
public notificationClicked(clientId): void {
|
||||
public notificationClicked(clientId: number): void {
|
||||
notification.unstack();
|
||||
const browserWindow = this.callNotificationWindow;
|
||||
if (
|
||||
browserWindow &&
|
||||
@ -148,6 +150,7 @@ class CallNotification {
|
||||
* @param clientId {number}
|
||||
*/
|
||||
public onCallNotificationOnAccept(clientId: number): void {
|
||||
notification.unstack();
|
||||
const browserWindow = this.callNotificationWindow;
|
||||
if (
|
||||
browserWindow &&
|
||||
@ -168,6 +171,7 @@ class CallNotification {
|
||||
* @param clientId {number}
|
||||
*/
|
||||
public onCallNotificationOnReject(clientId: number): void {
|
||||
notification.unstack();
|
||||
const browserWindow = this.callNotificationWindow;
|
||||
if (
|
||||
browserWindow &&
|
||||
@ -187,6 +191,7 @@ class CallNotification {
|
||||
* Close the notification window
|
||||
*/
|
||||
public closeNotification(clientId: number): void {
|
||||
notification.unstack();
|
||||
const browserWindow = this.callNotificationWindow;
|
||||
if (browserWindow && windowExists(browserWindow)) {
|
||||
if (
|
||||
|
@ -1,5 +1,4 @@
|
||||
import * as asyncMap from 'async.map';
|
||||
import { app, screen } from 'electron';
|
||||
import { app, BrowserWindow, screen } from 'electron';
|
||||
|
||||
import { windowExists } from '../app/window-utils';
|
||||
import { isLinux, isMac } from '../common/env';
|
||||
@ -31,7 +30,8 @@ const NEXT_INSERT_POSITION_WITH_INPUT = 142;
|
||||
const NOTIFICATIONS_PADDING_SEPARATION = 12;
|
||||
const CALL_NOTIFICATION_WIDTH = 264;
|
||||
const CALL_NOTIFICATION_HEIGHT = 286;
|
||||
const MAX_VISIBLE_TOAST_FOR_CALL_NOTIFICATION = 3;
|
||||
const MAX_VISIBLE_TOAST_FOR_CALL_NOTIFICATION = 0;
|
||||
const NOTIFICATION_STACK_HEIGHT = 10;
|
||||
export default class NotificationHandler {
|
||||
public settings: ISettings;
|
||||
public callNotificationSettings: ICorner = { x: 0, y: 0 };
|
||||
@ -42,8 +42,9 @@ export default class NotificationHandler {
|
||||
};
|
||||
|
||||
private externalDisplay: Electron.Display | undefined;
|
||||
private isNotificationStacked: boolean = false;
|
||||
|
||||
constructor(opts) {
|
||||
constructor(opts: ISettings) {
|
||||
this.settings = opts as ISettings;
|
||||
this.setupNotificationPosition();
|
||||
|
||||
@ -71,11 +72,7 @@ export default class NotificationHandler {
|
||||
window.setPosition(parseInt(String(x), 10), parseInt(String(y), 10));
|
||||
} catch (err) {
|
||||
console.warn(
|
||||
'Failed to set window position. x: ' +
|
||||
x +
|
||||
' y: ' +
|
||||
y +
|
||||
'. Contact the developers for more details',
|
||||
`Failed to set window position. x: ${x} y: ${y}. Contact the developers for more details`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -92,10 +89,9 @@ export default class NotificationHandler {
|
||||
|
||||
const screens = screen.getAllDisplays();
|
||||
if (screens && screens.length >= 0) {
|
||||
this.externalDisplay = screens.find((screen) => {
|
||||
const screenId = screen.id.toString();
|
||||
return screenId === this.settings.displayId;
|
||||
});
|
||||
this.externalDisplay = screens.find(
|
||||
(screen) => screen.id.toString() === this.settings.displayId,
|
||||
);
|
||||
}
|
||||
|
||||
const display = this.externalDisplay || screen.getPrimaryDisplay();
|
||||
@ -157,9 +153,91 @@ export default class NotificationHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Find next possible insert position (on top)
|
||||
* Stacks all active notifications on top of each other
|
||||
* like cards stacked with a small offset.
|
||||
*
|
||||
* @param activeNotifications {BrowserWindow[]}
|
||||
*/
|
||||
public calcNextInsertPos(activeNotifications) {
|
||||
public stackNotifications(activeNotifications: BrowserWindow[]) {
|
||||
if (!activeNotifications || activeNotifications.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set initial position
|
||||
const posY = this.settings.firstPos.y;
|
||||
|
||||
const stackOffset = 10; // Vertical offset for each stacked notification
|
||||
|
||||
activeNotifications.forEach((notificationWindow, index) => {
|
||||
if (!windowExists(notificationWindow)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate new position for each notification in the stack
|
||||
const newY = posY + stackOffset * index;
|
||||
|
||||
// Keep the x position constant
|
||||
const newX = this.settings.firstPos.x;
|
||||
|
||||
// Set the position of the notification window
|
||||
this.setWindowPosition(notificationWindow, newX, newY);
|
||||
});
|
||||
this.isNotificationStacked = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unstacks all active notifications, restoring them to their original positions.
|
||||
*
|
||||
* @param activeNotifications {BrowserWindow[]}
|
||||
*/
|
||||
public unstackNotifications(activeNotifications: BrowserWindow[]) {
|
||||
if (!activeNotifications || activeNotifications.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let cumulativeHeight = 0;
|
||||
|
||||
activeNotifications.forEach((notificationWindow) => {
|
||||
if (!windowExists(notificationWindow)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get actual height of the notification
|
||||
const height = notificationWindow.getBounds().height;
|
||||
|
||||
let newY;
|
||||
switch (this.settings.startCorner) {
|
||||
case 'upper-right':
|
||||
case 'upper-left':
|
||||
newY = this.settings.corner.y + cumulativeHeight;
|
||||
cumulativeHeight += height + this.settings.spacing;
|
||||
break;
|
||||
case 'lower-right':
|
||||
case 'lower-left':
|
||||
default:
|
||||
cumulativeHeight += height + this.settings.spacing;
|
||||
newY = this.settings.corner.y - cumulativeHeight;
|
||||
break;
|
||||
}
|
||||
|
||||
// The x position should remain the same as the first position
|
||||
const newX = this.settings.firstPos.x;
|
||||
|
||||
// Set the position of the notification window
|
||||
this.setWindowPosition(notificationWindow, newX, newY);
|
||||
});
|
||||
|
||||
this.isNotificationStacked = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the next insert position for new notifications based on the current layout.
|
||||
*
|
||||
* @public
|
||||
* @param {BrowserWindow[]} activeNotifications - An array containing references to all active notification windows.
|
||||
* @returns {void}
|
||||
*/
|
||||
public calcNextInsertPos(activeNotifications: BrowserWindow[]): void {
|
||||
let nextNotificationY: number = 0;
|
||||
activeNotifications.forEach((notification) => {
|
||||
if (notification && windowExists(notification)) {
|
||||
@ -168,8 +246,14 @@ export default class NotificationHandler {
|
||||
height > this.settings.height
|
||||
? NEXT_INSERT_POSITION_WITH_INPUT
|
||||
: NEXT_INSERT_POSITION;
|
||||
if (this.isNotificationStacked) {
|
||||
// When stacked, only consider padding separation for next insert position
|
||||
nextNotificationY += NOTIFICATIONS_PADDING_SEPARATION;
|
||||
} else {
|
||||
// When not stacked, use the standard shift height and padding
|
||||
nextNotificationY += shift + NOTIFICATIONS_PADDING_SEPARATION;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (activeNotifications.length < this.settings.maxVisibleNotifications) {
|
||||
switch (this.settings.startCorner) {
|
||||
@ -177,7 +261,6 @@ export default class NotificationHandler {
|
||||
case 'upper-left':
|
||||
this.nextInsertPos.y = this.settings.corner.y + nextNotificationY;
|
||||
break;
|
||||
|
||||
default:
|
||||
case 'lower-right':
|
||||
case 'lower-left':
|
||||
@ -189,101 +272,128 @@ export default class NotificationHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the notification by one step
|
||||
* Animates the position of notifications when the notification is closed or added.
|
||||
*
|
||||
* @param startPos {number}
|
||||
* @param activeNotifications {ICustomBrowserWindow[]}
|
||||
* @param height {number} height of the closed notification
|
||||
* @param isReset {boolean} whether to reset all notification position
|
||||
* @public
|
||||
* @param {number} startPos - The starting position in the active notifications array from which to begin the animation.
|
||||
* @param {BrowserWindow[]} activeNotifications - An array containing references to all active notification windows.
|
||||
* @param {number} closedNotificationHeight - The height of the closed notification, used for adjusting positions.
|
||||
* @param {boolean} isReset - Indicates whether the notification positions should be reset to their original positions.
|
||||
* @returns {void}
|
||||
*/
|
||||
public moveNotificationDown(
|
||||
startPos,
|
||||
activeNotifications,
|
||||
height: number = 0,
|
||||
public moveNotification(
|
||||
startPos: number,
|
||||
activeNotifications: BrowserWindow[],
|
||||
closedNotificationHeight: number = 0,
|
||||
isReset: boolean = false,
|
||||
) {
|
||||
if (startPos >= activeNotifications || startPos === -1) {
|
||||
): void {
|
||||
if (startPos >= activeNotifications.length || startPos === -1) {
|
||||
return;
|
||||
}
|
||||
// Build array with index of affected notifications
|
||||
|
||||
const notificationPosArray: number[] = [];
|
||||
for (let i = startPos; i < activeNotifications.length; i++) {
|
||||
notificationPosArray.push(i);
|
||||
}
|
||||
asyncMap(notificationPosArray, (i, done) => {
|
||||
// Get notification to move
|
||||
|
||||
notificationPosArray.forEach((i) => {
|
||||
const notificationWindow = activeNotifications[i];
|
||||
if (!windowExists(notificationWindow)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newY;
|
||||
const newX = this.settings.firstPos.x;
|
||||
|
||||
if (this.isNotificationStacked) {
|
||||
newY = this.settings.firstPos.y + NOTIFICATION_STACK_HEIGHT * i;
|
||||
} else {
|
||||
const [, y] = notificationWindow.getPosition();
|
||||
|
||||
// Calc new y position
|
||||
let newY;
|
||||
switch (this.settings.startCorner) {
|
||||
case 'upper-right':
|
||||
case 'upper-left':
|
||||
newY = isReset
|
||||
? this.settings.corner.y + this.settings.totalHeight * i
|
||||
: y - height - this.settings.spacing;
|
||||
if (isReset) {
|
||||
newY = this.settings.corner.y + this.settings.totalHeight * i;
|
||||
} else {
|
||||
const heightAdjustment = closedNotificationHeight
|
||||
? closedNotificationHeight + this.settings.spacing
|
||||
: this.settings.totalHeight + this.settings.spacing;
|
||||
newY = y - heightAdjustment;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case 'lower-right':
|
||||
case 'lower-left':
|
||||
newY = isReset
|
||||
? this.settings.corner.y - this.settings.totalHeight * (i + 1)
|
||||
: y + height + this.settings.spacing;
|
||||
if (isReset) {
|
||||
newY =
|
||||
this.settings.corner.y - this.settings.totalHeight * (i + 1);
|
||||
} else {
|
||||
const heightAdjustment = closedNotificationHeight
|
||||
? closedNotificationHeight + this.settings.spacing
|
||||
: this.settings.totalHeight + this.settings.spacing;
|
||||
newY = y + heightAdjustment;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.animateNotificationPosition(notificationWindow, newY, done);
|
||||
this.animateNotificationPosition(notificationWindow, newY, newX);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the notification by one step
|
||||
* Moves a notification up in the stack.
|
||||
*
|
||||
* @param startPos {number}
|
||||
* @param activeNotifications {ICustomBrowserWindow[]}
|
||||
* @public
|
||||
* @param {number} startPos - The starting position in the active notifications array.
|
||||
* @param {BrowserWindow[]} activeNotifications - An array containing references to all active notification windows.
|
||||
* @returns {void}
|
||||
*/
|
||||
public moveNotificationUp(startPos, activeNotifications) {
|
||||
if (startPos >= activeNotifications || startPos === -1) {
|
||||
public moveNotificationUp(
|
||||
startPos: number,
|
||||
activeNotifications: BrowserWindow[],
|
||||
): void {
|
||||
if (startPos >= activeNotifications.length || startPos === -1) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
this.settings.startCorner === 'lower-right' ||
|
||||
this.settings.startCorner === 'lower-left'
|
||||
) {
|
||||
|
||||
// Adjust startPos for lower corners
|
||||
if (['lower-right', 'lower-left'].includes(this.settings.startCorner)) {
|
||||
startPos -= 1;
|
||||
}
|
||||
// Build array with index of affected notifications
|
||||
|
||||
const notificationPosArray: number[] = [];
|
||||
for (let i = startPos; i < activeNotifications.length; i++) {
|
||||
notificationPosArray.push(i);
|
||||
}
|
||||
asyncMap(notificationPosArray, (i, done) => {
|
||||
// Get notification to move
|
||||
|
||||
notificationPosArray.forEach((i) => {
|
||||
const notificationWindow = activeNotifications[i];
|
||||
if (!windowExists(notificationWindow)) {
|
||||
return;
|
||||
}
|
||||
const [, y] = notificationWindow.getPosition();
|
||||
|
||||
// Calc new y position
|
||||
let newY;
|
||||
const [, y] = notificationWindow.getPosition();
|
||||
let newY: number;
|
||||
const newX = this.settings.firstPos.x;
|
||||
|
||||
// Calculate new Y position based on the start corner
|
||||
switch (this.settings.startCorner) {
|
||||
case 'upper-right':
|
||||
case 'upper-left':
|
||||
newY = y + this.settings.differentialHeight;
|
||||
break;
|
||||
default:
|
||||
case 'lower-right':
|
||||
case 'lower-left':
|
||||
newY = y - this.settings.differentialHeight;
|
||||
break;
|
||||
default:
|
||||
newY = y;
|
||||
}
|
||||
|
||||
this.animateNotificationPosition(notificationWindow, newY, done);
|
||||
// Animate the notification to the new position
|
||||
this.animateNotificationPosition(notificationWindow, newY, newX);
|
||||
});
|
||||
}
|
||||
|
||||
@ -291,30 +401,31 @@ export default class NotificationHandler {
|
||||
* Get startPos, calc step size and start animationInterval
|
||||
* @param notificationWindow
|
||||
* @param newY
|
||||
* @param done
|
||||
* @private
|
||||
* @param newX
|
||||
*/
|
||||
private animateNotificationPosition(notificationWindow, newY, done) {
|
||||
const startY = notificationWindow.getPosition()[1];
|
||||
const step = (newY - startY) / this.settings.animationSteps;
|
||||
private animateNotificationPosition(
|
||||
notificationWindow: Electron.BrowserWindow,
|
||||
newY: number,
|
||||
newX: number,
|
||||
) {
|
||||
const [startX, startY] = notificationWindow.getPosition();
|
||||
const stepY = (newY - startY) / this.settings.animationSteps;
|
||||
const stepX = (newX - startX) / this.settings.animationSteps;
|
||||
|
||||
let curStep = 1;
|
||||
const animationInterval = setInterval(() => {
|
||||
// Abort condition
|
||||
if (curStep === this.settings.animationSteps) {
|
||||
this.setWindowPosition(
|
||||
notificationWindow,
|
||||
this.settings.firstPos.x,
|
||||
newY,
|
||||
);
|
||||
this.setWindowPosition(notificationWindow, newX, newY);
|
||||
clearInterval(animationInterval);
|
||||
done(null, 'done');
|
||||
return;
|
||||
}
|
||||
// Move one step down
|
||||
|
||||
// Move one step in both x and y directions
|
||||
this.setWindowPosition(
|
||||
notificationWindow,
|
||||
this.settings.firstPos.x,
|
||||
startY + curStep * step,
|
||||
startX + curStep * stepX,
|
||||
startY + curStep * stepY,
|
||||
);
|
||||
curStep++;
|
||||
}, this.settings.animationStepMs);
|
||||
|
@ -325,7 +325,7 @@ class Notification extends NotificationHandler {
|
||||
browserWindow.close();
|
||||
}
|
||||
|
||||
this.moveNotificationDown(pos, this.activeNotifications, height);
|
||||
this.moveNotification(pos, this.activeNotifications, height, false);
|
||||
|
||||
if (
|
||||
this.notificationQueue.length > 0 &&
|
||||
@ -452,7 +452,7 @@ class Notification extends NotificationHandler {
|
||||
|
||||
// recalculate notification position
|
||||
this.setupNotificationPosition();
|
||||
this.moveNotificationDown(0, this.activeNotifications, 0, true);
|
||||
this.moveNotification(0, this.activeNotifications, 0, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -506,6 +506,20 @@ class Notification extends NotificationHandler {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Stacks the active notifications
|
||||
*/
|
||||
public stack() {
|
||||
this.stackNotifications(this.activeNotifications);
|
||||
}
|
||||
|
||||
/**
|
||||
* unstacks the active notifications
|
||||
*/
|
||||
public unstack(): void {
|
||||
this.unstackNotifications(this.activeNotifications);
|
||||
}
|
||||
|
||||
/**
|
||||
* SDA-1268 - Workaround to exit window
|
||||
* fullscreen state when notification is clicked
|
||||
|
Loading…
Reference in New Issue
Block a user