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
This commit is contained in:
Kiran Niranjan 2021-01-08 13:09:02 +05:30 committed by GitHub
parent 3a16b7ef19
commit da6ed20bc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 101 additions and 44 deletions

View File

@ -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);
}
}

View File

@ -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
*/

View File

@ -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<void> {
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);
}
/**