From da6ed20bc66f83566a58cc092498da70124228b1 Mon Sep 17 00:00:00 2001 From: Kiran Niranjan Date: Fri, 8 Jan 2021 13:09:02 +0530 Subject: [PATCH] fix: SDA-2806, SDA-2822 & SDA-2831 (Reposition notifications when on input) (#1168) * fix: SDA-2806 - Reposition notifications when on input * fix: SDA-2822 - Fix rendering issue on SFE --- src/renderer/components/notification-comp.tsx | 2 +- src/renderer/notification-handler.ts | 115 ++++++++++++++---- src/renderer/notification.ts | 28 ++--- 3 files changed, 101 insertions(+), 44 deletions(-) diff --git a/src/renderer/components/notification-comp.tsx b/src/renderer/components/notification-comp.tsx index cf6b44cc..1e8c0a7e 100644 --- a/src/renderer/components/notification-comp.tsx +++ b/src/renderer/components/notification-comp.tsx @@ -275,7 +275,7 @@ export default class NotificationComp extends React.Component<{}, IState> { let replyText = this.getInputValue(); if (replyText) { // need to replace 👍 with :thumbsup: to make sure client displays the correct emoji - replyText = replyText.replace(/👍/g, replyText.length <= 2 ? ':thumbsup: ' : ':thumbsup:'); + replyText = replyText.replace(/👍/g, ':thumbsup: '); ipcRenderer.send('notification-on-reply', id, replyText); } } diff --git a/src/renderer/notification-handler.ts b/src/renderer/notification-handler.ts index 960fbbc8..d7f3dff6 100644 --- a/src/renderer/notification-handler.ts +++ b/src/renderer/notification-handler.ts @@ -17,6 +17,8 @@ interface ISettings { maxVisibleNotifications: number; animationSteps: number; animationStepMs: number; + spacing: number; + differentialHeight: number; } interface ICorner { @@ -114,18 +116,25 @@ export default class NotificationHandler { /** * Find next possible insert position (on top) */ - public calcNextInsertPos(activeNotificationLength) { - if (activeNotificationLength < this.settings.maxVisibleNotifications) { + public calcNextInsertPos(activeNotifications) { + let nextNotificationY: number = 0; + activeNotifications.forEach((notification) => { + if (notification && windowExists(notification)) { + const [, height] = notification.getSize(); + nextNotificationY += height > this.settings.height ? 112 : 72; + } + }); + if (activeNotifications.length < this.settings.maxVisibleNotifications) { switch (this.settings.startCorner) { case 'upper-right': case 'upper-left': - this.nextInsertPos.y = this.settings.corner.y + (this.settings.totalHeight * activeNotificationLength); + this.nextInsertPos.y = this.settings.corner.y + nextNotificationY; break; default: case 'lower-right': case 'lower-left': - this.nextInsertPos.y = this.settings.corner.y - (this.settings.totalHeight * (activeNotificationLength + 1)); + this.nextInsertPos.y = this.settings.corner.y - (nextNotificationY + 72); break; } } @@ -136,8 +145,10 @@ export default class NotificationHandler { * * @param startPos {number} * @param activeNotifications {ICustomBrowserWindow[]} + * @param height {number} height of the closed notification + * @param isReset {boolean} whether to reset all notification position */ - public moveNotificationDown(startPos, activeNotifications) { + public moveNotificationDown(startPos, activeNotifications, height: number = 0, isReset: boolean = false) { if (startPos >= activeNotifications || startPos === -1) { return; } @@ -149,44 +160,102 @@ export default class NotificationHandler { asyncMap(notificationPosArray, (i, done) => { // Get notification to move const notificationWindow = activeNotifications[i]; + if (!windowExists(notificationWindow)) { + return; + } + const [, y] = notificationWindow.getPosition(); // Calc new y position let newY; switch (this.settings.startCorner) { case 'upper-right': case 'upper-left': - newY = this.settings.corner.y + (this.settings.totalHeight * i); + newY = isReset + ? this.settings.corner.y + (this.settings.totalHeight * i) + : (y - height - this.settings.spacing); break; default: case 'lower-right': case 'lower-left': - newY = this.settings.corner.y - (this.settings.totalHeight * (i + 1)); + newY = isReset + ? this.settings.corner.y - (this.settings.totalHeight * (i + 1)) + : (y + height + this.settings.spacing); break; } + this.animateNotificationPosition(notificationWindow, newY, done); + }); + } + + /** + * Moves the notification by one step + * + * @param startPos {number} + * @param activeNotifications {ICustomBrowserWindow[]} + */ + public moveNotificationUp(startPos, activeNotifications) { + if (startPos >= activeNotifications || startPos === -1) { + return; + } + if (this.settings.startCorner === 'lower-right' || this.settings.startCorner === 'lower-left') { + 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 + const notificationWindow = activeNotifications[i]; if (!windowExists(notificationWindow)) { return; } + const [, y] = notificationWindow.getPosition(); - // Get startPos, calc step size and start animationInterval - const startY = notificationWindow.getPosition()[1]; - const step = (newY - startY) / this.settings.animationSteps; - let curStep = 1; - const animationInterval = setInterval(() => { - // Abort condition - if (curStep === this.settings.animationSteps) { - this.setWindowPosition(notificationWindow, this.settings.firstPos.x, newY); - clearInterval(animationInterval); - done(null, 'done'); - return; - } - // Move one step down - this.setWindowPosition(notificationWindow, this.settings.firstPos.x, startY + curStep * step); - curStep++; - }, this.settings.animationStepMs); + // Calc new y position + let newY; + 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; + } + + this.animateNotificationPosition(notificationWindow, newY, done); }); } + /** + * Get startPos, calc step size and start animationInterval + * @param notificationWindow + * @param newY + * @param done + * @private + */ + private animateNotificationPosition(notificationWindow, newY, done) { + const startY = notificationWindow.getPosition()[1]; + const step = (newY - startY) / this.settings.animationSteps; + let curStep = 1; + const animationInterval = setInterval(() => { + // Abort condition + if (curStep === this.settings.animationSteps) { + this.setWindowPosition(notificationWindow, this.settings.firstPos.x, newY); + clearInterval(animationInterval); + done(null, 'done'); + return; + } + // Move one step down + this.setWindowPosition(notificationWindow, this.settings.firstPos.x, startY + curStep * step); + curStep++; + }, this.settings.animationStepMs); + } + /** * Calculates the first and next notification insert position */ diff --git a/src/renderer/notification.ts b/src/renderer/notification.ts index 4468d6fa..eb2edfc7 100644 --- a/src/renderer/notification.ts +++ b/src/renderer/notification.ts @@ -44,6 +44,8 @@ const notificationSettings = { animationSteps: 5, animationStepMs: 5, logging: true, + spacing: 8, + differentialHeight: 40, }; class Notification extends NotificationHandler { @@ -193,8 +195,6 @@ class Notification extends NotificationHandler { notificationWindow.setSize(notificationSettings.width, notificationSettings.height, true); // Move notification to top notificationWindow.moveTop(); - // Reset alwaysOnTop level to normal - notificationWindow.setAlwaysOnTop(true, 'normal'); if (!data.sticky) { timeoutId = setTimeout(async () => { @@ -241,6 +241,7 @@ class Notification extends NotificationHandler { public async hideNotification(clientId: number): Promise { const browserWindow = this.getNotificationWindow(clientId); if (browserWindow && windowExists(browserWindow)) { + const [, height] = browserWindow.getSize(); // send empty to reset the state const pos = this.activeNotifications.indexOf(browserWindow); this.activeNotifications.splice(pos, 1); @@ -252,7 +253,7 @@ class Notification extends NotificationHandler { browserWindow.close(); } - this.moveNotificationDown(pos, this.activeNotifications); + this.moveNotificationDown(pos, this.activeNotifications, height); if (this.notificationQueue.length > 0 && this.activeNotifications.length < this.settings.maxVisibleNotifications) { const notificationData = this.notificationQueue[0]; @@ -345,7 +346,7 @@ class Notification extends NotificationHandler { // recalculate notification position this.setupNotificationPosition(); - this.moveNotificationDown(0, this.activeNotifications); + this.moveNotificationDown(0, this.activeNotifications, 0, true); } /** @@ -415,20 +416,6 @@ class Notification extends NotificationHandler { if (windowExists(window)) { this.renderNotification(window, data); } - // This is a workaround to make sure the notification - // with visible input always stays on top of normal notifications - if (isWindowsOS) { - this.activeNotifications.forEach((activeNotification) => { - if (!activeNotification || !windowExists(activeNotification)) { - return; - } - const [, height] = activeNotification.getSize(); - // Height of notification window with input will be 104 - if (height > notificationSettings.height) { - activeNotification.moveTop(); - } - }); - } return resolve(window); }); }); @@ -441,7 +428,7 @@ class Notification extends NotificationHandler { * @param data {INotificationData} */ private renderNotification(notificationWindow, data): void { - this.calcNextInsertPos(this.activeNotifications.length); + this.calcNextInsertPos(this.activeNotifications); this.setWindowPosition(notificationWindow, this.nextInsertPos.x, this.nextInsertPos.y); this.setNotificationContent(notificationWindow, { ...data, windowId: notificationWindow.id }); this.activeNotifications.push(notificationWindow); @@ -518,8 +505,9 @@ class Notification extends NotificationHandler { return; } clearTimeout(notificationWindow.displayTimer); - notificationWindow.setAlwaysOnTop(true, 'pop-up-menu'); notificationWindow.setSize(344, CONTAINER_HEIGHT_WITH_INPUT, true); + const pos = this.activeNotifications.indexOf(notificationWindow) + 1; + this.moveNotificationUp(pos, this.activeNotifications); } /**