+
+

+
-
-
-

+
{this.renderImage(icon)}
+
+
+
+ {title}
+ {this.renderExtBadge(isExternal)}
+
+ {this.renderReplyButton(id, themeClassName)}
-
-
-
- {title}
- {this.renderExtBadge(isExternal)}
-
-
{body}
-
-
-
-
+ {body}
-
+ {this.renderRTE(themeClassName)}
+
+ );
+ }
+
+ /**
+ * Renders RTE
+ * @param isInputHidden
+ */
+ private renderRTE(themeClassName: string): JSX.Element | undefined {
+ const { canSendMessage, isInputHidden, id } = this.state;
+ const actionButtonContainer = classNames('rte-button-container', {
+ 'action-container-margin': !isInputHidden,
+ });
+ if (!isInputHidden) {
+ return (
+
-
- );
+ );
+ }
+ return;
}
/**
@@ -242,6 +248,45 @@ export default class NotificationComp extends React.Component<{}, IState> {
);
}
+ /**
+ * Renders image if provided otherwise renders symphony logo
+ * @param imageUrl
+ */
+ private renderImage(imageUrl: string): JSX.Element | undefined {
+ let imgClass = 'default-logo';
+ let url = '../renderer/assets/notification-symphony-logo.svg';
+ let alt = 'Symphony logo';
+ const isDefaultUrl = imageUrl.includes('default.png');
+ const shouldDisplayBadge = !!imageUrl && !isDefaultUrl;
+ if (imageUrl && !isDefaultUrl) {
+ imgClass = 'profile-picture';
+ url = imageUrl;
+ alt = 'Profile picture';
+ }
+ return (
+
+

+ {this.renderSymphonyBadge(shouldDisplayBadge)}
+
+ );
+ }
+
+ /**
+ * Renders profile picture symphpony badge
+ * @param hasImageUrl
+ */
+ private renderSymphonyBadge(hasImageUrl: boolean): JSX.Element | undefined {
+ if (hasImageUrl) {
+ return (
+

+ );
+ }
+ return;
+ }
/**
* Invoked when the notification window is clicked
@@ -250,7 +295,6 @@ export default class NotificationComp extends React.Component<{}, IState> {
*/
private click(id: number): void {
ipcRenderer.send('notification-clicked', id);
- this.clearFlashInterval();
}
/**
@@ -260,7 +304,6 @@ export default class NotificationComp extends React.Component<{}, IState> {
*/
private close(id: number): void {
ipcRenderer.send('close-notification', id);
- this.clearFlashInterval();
}
/**
@@ -318,15 +361,6 @@ export default class NotificationComp extends React.Component<{}, IState> {
}
}
- /**
- * Clears a active notification flash interval
- */
- private clearFlashInterval(): void {
- if (this.flashTimer) {
- clearInterval(this.flashTimer);
- }
- }
-
/**
* Displays an input on the notification
*
@@ -388,30 +422,13 @@ export default class NotificationComp extends React.Component<{}, IState> {
* @param data {Object}
*/
private updateState(_event, data): void {
- const { color, flash } = data;
- data.color = color && !color.startsWith('#') ? '#' + color : color;
+ const { color } = data;
+ data.color = this.isValidColor(color) ? color : '';
data.isInputHidden = true;
data.containerHeight = CONTAINER_HEIGHT;
-
- data.color = this.isValidColor(data.color) ? data.color : '';
-
+ data.theme = data.theme ? data.theme : Themes.LIGHT;
this.resetNotificationData();
- this.setState(data as IState);
-
- if (this.flashTimer) {
- clearInterval(this.flashTimer);
- }
- if (flash) {
- const origColor = data.color;
- this.flashTimer = setInterval(() => {
- const { color: bgColor } = this.state;
- if (bgColor === 'red') {
- this.setState({ color: origColor });
- } else {
- this.setState({ color: 'red' });
- }
- }, 1000);
- }
+ this.setState(data as INotificationState);
}
/**
@@ -432,4 +449,85 @@ export default class NotificationComp extends React.Component<{}, IState> {
this.input.current.value = '';
}
}
+
+ /**
+ * Returns notification colors based on theme
+ * @param theme Current theme, can be either light or dark
+ */
+ private getThemeColors(): { [key: string]: string } {
+ const { theme, flash, isExternal, hasMention, color } = this.state;
+ const currentColors =
+ theme === Themes.DARK ? { ...Colors.dark } : { ...Colors.light };
+ if (flash && theme) {
+ if (isExternal) {
+ currentColors.notificationBorderColor = '#F7CA3B';
+ } else if (hasMention) {
+ currentColors.notificationBorderColor =
+ currentColors.notificationBorderColor;
+ } else {
+ // in case of regular message without mention
+ currentColors.notificationBackgroundColor = color
+ ? color
+ : currentColors.regularFlashingNotificationBgColor;
+ currentColors.notificationBorderColor = color
+ ? color
+ : theme === Themes.DARK
+ ? '#2996fd'
+ : 'transparent';
+ }
+ } else if (!flash && color) {
+ currentColors.notificationBackgroundColor = currentColors.notificationBorderColor = color;
+ }
+ return currentColors;
+ }
+
+ /**
+ * Renders reply button
+ * @param id
+ * @param theming
+ */
+ private renderReplyButton(
+ id: number,
+ theming: string,
+ ): JSX.Element | undefined {
+ const { hasReply } = this.state;
+ if (hasReply) {
+ return (
+
+ );
+ }
+ return;
+ }
+
+ /**
+ * This function aims at providing toast notification css classes
+ */
+ private getContainerCssClasses(): string[] {
+ const customClasses: string[] = [];
+ const { flash, theme, hasMention, isExternal } = this.state;
+ if (flash && theme) {
+ if (isExternal) {
+ if (hasMention) {
+ customClasses.push(`${theme}-ext-mention-flashing`);
+ } else {
+ customClasses.push(`${theme}-ext-flashing`);
+ }
+ } else if (hasMention) {
+ customClasses.push(`${theme}-mention-flashing`);
+ } else {
+ // In case it's a regular message notification
+ customClasses.push(`${theme}-flashing`);
+ }
+ } else if (isExternal) {
+ customClasses.push('external-border');
+ }
+ return customClasses;
+ }
}
diff --git a/src/renderer/notification-handler.ts b/src/renderer/notification-handler.ts
index 913b591d..b0d53019 100644
--- a/src/renderer/notification-handler.ts
+++ b/src/renderer/notification-handler.ts
@@ -26,8 +26,9 @@ interface ICorner {
}
type startCorner = 'upper-right' | 'upper-left' | 'lower-right' | 'lower-left';
-const NEXT_INSERT_POSITION = 96;
-const NEXT_INSERT_POSITION_WITH_INPUT = 128;
+const NEXT_INSERT_POSITION = 100;
+const NEXT_INSERT_POSITION_WITH_INPUT = 142;
+const NOTIFICATIONS_PADDING_SEPARATION = 12;
export default class NotificationHandler {
public settings: ISettings;
@@ -138,10 +139,11 @@ export default class NotificationHandler {
activeNotifications.forEach((notification) => {
if (notification && windowExists(notification)) {
const [, height] = notification.getSize();
- nextNotificationY +=
+ const shift =
height > this.settings.height
? NEXT_INSERT_POSITION_WITH_INPUT
: NEXT_INSERT_POSITION;
+ nextNotificationY += shift + NOTIFICATIONS_PADDING_SEPARATION;
}
});
if (activeNotifications.length < this.settings.maxVisibleNotifications) {
@@ -297,10 +299,9 @@ export default class NotificationHandler {
* Calculates the first and next notification insert position
*/
private calculateDimensions() {
- const vertSpace = 8;
-
// Calc totalHeight & totalWidth
- this.settings.totalHeight = this.settings.height + vertSpace;
+ this.settings.totalHeight =
+ this.settings.height + NOTIFICATIONS_PADDING_SEPARATION;
this.settings.totalWidth = this.settings.width;
let firstPosX;
diff --git a/src/renderer/notification.ts b/src/renderer/notification.ts
index 17be5b49..73f48e08 100644
--- a/src/renderer/notification.ts
+++ b/src/renderer/notification.ts
@@ -20,8 +20,9 @@ import NotificationHandler from './notification-handler';
const CLEAN_UP_INTERVAL = 60 * 1000; // Closes inactive notification
const animationQueue = new AnimationQueue();
-const CONTAINER_HEIGHT_WITH_INPUT = 120; // Notification container height
-
+const CONTAINER_HEIGHT = 104; // Notification container height
+const CONTAINER_HEIGHT_WITH_INPUT = 146; // Notification container height including input field
+const CONTAINER_WIDTH = 363;
interface ICustomBrowserWindow extends Electron.BrowserWindow {
winName: string;
notificationData: INotificationData;
@@ -34,8 +35,8 @@ type startCorner = 'upper-right' | 'upper-left' | 'lower-right' | 'lower-left';
const notificationSettings = {
startCorner: 'upper-right' as startCorner,
display: '',
- width: 344,
- height: 88,
+ width: CONTAINER_WIDTH,
+ height: CONTAINER_HEIGHT,
totalHeight: 0,
totalWidth: 0,
corner: {
@@ -54,7 +55,7 @@ const notificationSettings = {
animationStepMs: 5,
logging: true,
spacing: 8,
- differentialHeight: 32,
+ differentialHeight: 42,
};
class Notification extends NotificationHandler {
@@ -264,8 +265,8 @@ class Notification extends NotificationHandler {
isExternal,
theme,
hasReply,
+ hasMention,
} = data;
-
notificationWindow.webContents.send('notification-data', {
title,
company,
@@ -278,6 +279,7 @@ class Notification extends NotificationHandler {
isExternal,
theme,
hasReply,
+ hasMention,
});
notificationWindow.showInactive();
}
@@ -586,7 +588,11 @@ class Notification extends NotificationHandler {
return;
}
clearTimeout(notificationWindow.displayTimer);
- notificationWindow.setSize(344, CONTAINER_HEIGHT_WITH_INPUT, true);
+ notificationWindow.setSize(
+ CONTAINER_WIDTH,
+ CONTAINER_HEIGHT_WITH_INPUT,
+ true,
+ );
const pos = this.activeNotifications.indexOf(notificationWindow) + 1;
this.moveNotificationUp(pos, this.activeNotifications);
}
@@ -596,8 +602,8 @@ class Notification extends NotificationHandler {
*/
private getNotificationOpts(): Electron.BrowserWindowConstructorOptions {
return {
- width: 344,
- height: 88,
+ width: CONTAINER_WIDTH,
+ height: CONTAINER_HEIGHT,
alwaysOnTop: true,
skipTaskbar: true,
resizable: isWindowsOS,
diff --git a/src/renderer/preload-main.ts b/src/renderer/preload-main.ts
index 2cc384cd..bcd97876 100644
--- a/src/renderer/preload-main.ts
+++ b/src/renderer/preload-main.ts
@@ -89,6 +89,7 @@ if (ssfWindow.ssf) {
closeAllWrapperWindows: ssfWindow.ssf.closeAllWrapperWindows,
setZoomLevel: ssfWindow.ssf.setZoomLevel,
getZoomLevel: ssfWindow.ssf.getZoomLevel,
+ supportedSettings: ssfWindow.ssf.supportedSettings,
});
}
diff --git a/src/renderer/ssf-api.ts b/src/renderer/ssf-api.ts
index 3e691be1..fe2e9db9 100644
--- a/src/renderer/ssf-api.ts
+++ b/src/renderer/ssf-api.ts
@@ -25,6 +25,9 @@ import { throttle } from '../common/utils';
import { getSource } from './desktop-capturer';
import SSFNotificationHandler from './notification-ssf-hendler';
import { ScreenSnippetBcHandler } from './screen-snippet-bc-handler';
+
+const SUPPORTED_SETTINGS = ['flashing-notifications'];
+
const os = remote.require('os');
let isAltKey: boolean = false;
@@ -705,6 +708,14 @@ export class SSFApi {
throttledSetZoomLevel(zoomLevel);
}
}
+
+ /**
+ * Get SDA supported settings.
+ * @returns list of supported features
+ */
+ public supportedSettings(): string[] {
+ return SUPPORTED_SETTINGS || [];
+ }
}
/**
diff --git a/src/renderer/styles/notification-comp.less b/src/renderer/styles/notification-comp.less
index 78db995f..91bc82f9 100644
--- a/src/renderer/styles/notification-comp.less
+++ b/src/renderer/styles/notification-comp.less
@@ -1,28 +1,37 @@
@import 'theme';
-@inputWidth: 270px;
+@import 'variables';
+@import 'notifications-animations';
-.blackText {
+.black-text {
--text-color: #000000;
--button-bg-color: #52575f;
--button-test-color: #ffffff;
--logo-bg: url('../assets/symphony-logo.png');
}
+
.light {
- --text-color: #525760;
- --button-bg-color: linear-gradient(
- 0deg,
- rgba(255, 255, 255, 0.72),
- rgba(255, 255, 255, 0.72)
- ),
- #525760;
+ --text-color: #000000;
+ --notification-bg-color: @light-notification-bg-color;
+ --notification-border-color: transparent;
+ --button-color: #717681;
+ --button-border-color: #717681;
+ --button-hover-color: #717681;
+ --button-hover-border-color: #717681;
+ --button-hover-bg-color: #e3e5e7;
--button-test-color: #000000;
- --logo-bg: url('../assets/symphony-logo.png');
}
+
.dark {
--text-color: #ffffff;
- --button-bg-color: #52575f;
+ --notification-bg-color: @dark-notification-bg-color;
+ --notification-border-color: #717681;
+ --button-color: #b0b3ba;
+ --button-border-color: #b0b3ba;
+ --button-border-color: #717681;
+ --button-hover-color: #cdcfd4;
+ --button-hover-border-color: #cdcfd4;
+ --button-hover-bg-color: #3a3d43;
--button-test-color: #ffffff;
- --logo-bg: url('../assets/symphony-logo.png');
}
.big {
@@ -36,67 +45,117 @@
body {
margin: 0;
overflow: hidden;
- -webkit-user-select: none;
+ user-select: none;
font-family: sans-serif;
}
.container {
- width: 344px;
- height: 88px;
- display: flex;
- background-color: #ffffff;
- overflow: hidden;
position: relative;
- line-height: 15px;
- box-sizing: border-box;
+ display: flex;
flex-direction: column;
+ justify-content: space-between;
+ background-color: var(--notification-bg-color);
+ border: 2px solid;
border-radius: 10px;
+ border-color: var(--notification-border-color);
+ overflow: hidden;
+ line-height: 15px;
+ &:hover > .close-button {
+ display: block;
+ }
- &:hover .close {
- visibility: visible;
+ .main-container {
+ border-radius: 8px;
+ position: relative;
+ height: auto;
+ display: flex;
+ flex: 1;
+ padding-left: 12px;
+ padding-right: 12px;
+ padding-top: 12px;
+ line-height: 15px;
+ overflow: hidden;
+ .logo-container {
+ margin-right: 12px;
+ display: flex;
+ height: 64px;
+ position: relative;
+ .logo {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ .profile-picture {
+ width: 64px;
+ border-radius: 50%;
+ }
+ .default-logo {
+ top: 0;
+ width: 40px;
+ border-radius: 5px;
+ }
+ .profile-picture-badge {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ }
+ }
+ }
+ .notification-container {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ position: relative;
+ overflow: hidden;
+
+ .notification-header {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ .notification-header-content {
+ display: flex;
+ margin-bottom: 8px;
+ .title {
+ font-family: sans-serif;
+ font-weight: 600;
+ max-width: 190px;
+ font-size: 14px;
+ font-style: normal;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ line-height: 20px;
+ -webkit-box-orient: vertical;
+ cursor: default;
+ color: var(--text-color);
+ }
+ }
+ }
+ .message-preview {
+ font-family: sans-serif;
+ width: 100%;
+ overflow-wrap: break-word;
+ font-size: 12px;
+ line-height: 16px;
+ overflow: hidden;
+ -webkit-line-clamp: 3;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ cursor: default;
+ text-overflow: ellipsis;
+ color: var(--text-color);
+ }
+ }
}
}
.external-border {
- border: 3px solid #f6b202;
-}
-
-.main-container {
- height: 88px;
- display: flex;
- justify-content: center;
- background-color: #ffffff;
- overflow: hidden;
- position: relative;
- line-height: 15px;
- align-items: flex-start;
-}
-
-.ext-border {
- border: 3px solid #f6b202;
- border-radius: 10px;
- width: 338px;
- height: var(--border-height);
- position: fixed;
-}
-
-.header {
- width: 232px;
- min-width: 215px;
- margin-top: 10px;
- display: flex;
- flex-direction: column;
- align-items: flex-start;
+ border: 2px solid #f7ca3b !important;
}
.header:lang(fr-FR) {
min-width: 190px;
}
-.title-container {
- display: flex;
-}
-
.user-profile-pic-container {
align-items: center;
display: flex;
@@ -123,8 +182,8 @@ body {
.ext-badge-container {
height: 16px;
- width: 32px;
- margin: auto 8px;
+ width: 26px;
+ margin-left: 8px;
align-items: center;
}
@@ -135,37 +194,30 @@ body {
margin: 12px;
}
-.actions-container {
- display: flex;
- flex-direction: column;
- justify-content: center;
- z-index: 5;
- margin-top: 4px;
-}
-
-.action-container-margin {
- margin-top: 8px;
-}
-
.action-button {
+ width: 59px;
+ height: 24px;
border-radius: 16px;
- padding: 2px 10px;
- background: var(--button-bg-color);
- color: var(--button-test-color);
+ background: transparent;
+ color: var(--button-color);
flex: none;
- font-weight: 600;
border-style: none;
font-size: 12px;
- line-height: 16px;
+ line-height: 14px;
align-items: center;
text-align: center;
text-transform: uppercase;
order: 0;
flex-grow: 0;
font-style: normal;
- margin: 4px 8px 4px 0;
font-family: @font-family;
outline: none;
+ border: 2px solid var(--button-border-color);
+ &:hover {
+ border-color: var(--button-hover-border-color) !important;
+ background-color: var(--button-hover-bg-color) !important;
+ color: var(--button-hover-color) !important;
+ }
}
.action-button:hover {
@@ -181,55 +233,54 @@ body {
}
.rte-container {
- width: 100%;
height: 38px;
- position: absolute;
- bottom: 0;
-}
-
-.input-container {
- width: 100%;
- height: 38px;
- outline: none;
-}
-
-.input-border {
- height: 2px;
- left: 8px;
- right: 8px;
- top: 0;
- background: #008eff;
- margin: 0 8px;
-}
-
-input {
- width: @inputWidth;
- height: 38px;
- border: none;
- outline: none;
+ position: relative;
margin-left: 8px;
- font-size: 14px;
- caret-color: #008eff;
- color: var(--text-color);
-}
-
-.rte-button-container {
+ margin-right: 8px;
display: flex;
- position: absolute;
- right: 0;
- bottom: 0;
- padding: 7px 13px;
-}
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ border-top: 2px solid #008eff;
+ .input-container {
+ display: flex;
+ flex: 1;
+ outline: none;
+ input {
+ width: @input-width;
+ height: 20px;
+ border: none;
+ outline: none;
+ font-size: 14px;
+ caret-color: #008eff;
+ color: var(--text-color);
+ background-color: transparent;
+ }
+ }
+ .rte-button-container {
+ display: flex;
+ .rte-thumbsup-button {
+ width: 25px;
+ height: 26px;
+ align-self: center;
+ padding: 3px;
+ background: none;
+ font-size: 14px;
+ border: none;
+ color: var(--text-color);
+ }
-.rte-thumbsup-button {
- width: 25px;
- height: 26px;
- align-self: center;
- padding: 3px;
- background: none;
- font-size: 14px;
- border: none;
- color: var(--text-color);
+ .rte-send-button {
+ width: 25px;
+ height: 25px;
+ align-self: center;
+ padding: 3px;
+ background: url('../assets/notification-send-button-enabled.svg')
+ no-repeat center;
+ border: none;
+ color: var(--text-color);
+ }
+ }
}
.rte-thumbsup-button:focus,
@@ -241,40 +292,11 @@ input {
outline: #008eff auto 1px;
}
-.rte-send-button {
- width: 25px;
- height: 25px;
- align-self: center;
- padding: 3px;
- background: url('../assets/notification-send-button-enabled.svg') no-repeat
- center;
- border: none;
- color: var(--text-color);
-}
-
.rte-send-button:disabled {
background: url('../assets/notification-send-button-disabled.svg') no-repeat
center;
}
-.title {
- font-family: sans-serif;
- font-weight: 600;
- width: auto;
- max-width: 175px;
- overflow-wrap: break-word;
- font-size: 14px;
- font-style: normal;
- overflow: hidden;
- -webkit-line-clamp: 1;
- white-space: nowrap;
- text-overflow: ellipsis;
- line-height: 24px;
- -webkit-box-orient: vertical;
- cursor: default;
- color: var(--text-color);
-}
-
.external-border .title {
max-width: 142px;
}
@@ -290,42 +312,47 @@ input {
-webkit-box-orient: vertical;
}
-.message {
- font-family: sans-serif;
- width: 205px;
- overflow-wrap: break-word;
- font-size: 12px;
- line-height: 16px;
- overflow: hidden;
- -webkit-line-clamp: 3;
- display: -webkit-box;
- -webkit-box-orient: vertical;
- cursor: default;
- text-overflow: ellipsis;
- color: var(--text-color);
-}
-
.message:lang(fr-FR) {
width: 182px;
}
-.logo-container {
- margin: 12px;
- display: flex;
- align-items: center;
+.close-button {
+ position: absolute;
+ top: -2;
+ right: 0;
+ width: 16px;
+ height: 16px;
+ display: none;
}
-.logo {
- width: 40px;
- content: var(--logo-bg);
+.light-flashing {
+ animation: light-flashing 1s infinite !important;
}
-@-webkit-keyframes blink {
- from,
- to {
- background: transparent;
- }
- 50% {
- background: #008eff;
- }
+.dark-flashing {
+ animation: dark-flashing 1s infinite !important;
+}
+
+.dark-ext-flashing {
+ animation: dark-ext-flashing 1s infinite !important;
+}
+
+.light-ext-flashing {
+ animation: light-ext-flashing 1s infinite !important;
+}
+
+.dark-mention-flashing {
+ animation: dark-mention-flashing 1s infinite !important;
+}
+
+.light-mention-flashing {
+ animation: light-mention-flashing 1s infinite !important;
+}
+
+.dark-ext-mention-flashing {
+ animation: dark-ext-mention-flashing 1s infinite !important;
+}
+
+.light-ext-mention-flashing {
+ animation: light-ext-mention-flashing 1s infinite !important;
}
diff --git a/src/renderer/styles/notifications-animations.less b/src/renderer/styles/notifications-animations.less
new file mode 100644
index 00000000..a4807306
--- /dev/null
+++ b/src/renderer/styles/notifications-animations.less
@@ -0,0 +1,82 @@
+@import 'theme';
+@import 'variables';
+
+@keyframes dark-mention-flashing {
+ 0% {
+ background-color: @dark-notification-bg-color;
+ border-color: @dark-notification-border-color;
+ }
+ 50% {
+ background-color: @dark-mention-flash-bg-color;
+ border: 2px solid @dark-mention-flash-border-color;
+ box-shadow: 0px 2px 4px rgba(5, 6, 6, 0.16),
+ 0px 12px 28px rgba(5, 6, 6, 0.64);
+ }
+}
+
+@keyframes light-mention-flashing {
+ 0% {
+ background-color: @light-notification-bg-color;
+ border-color: @light-notification-border-color;
+ }
+ 50% {
+ background-color: @light-mention-flash-mention-bg-color;
+ border-color: @light-mention-flash-border-color;
+ }
+}
+
+@keyframes dark-ext-mention-flashing {
+ 0% {
+ background-color: @dark-notification-bg-color;
+ border-color: @dark-external-flash-border-color;
+ }
+ 50% {
+ background-color: @dark-mention-flash-bg-color;
+ border: 2px solid @dark-mention-flash-border-color;
+ box-shadow: 0px 2px 4px rgba(5, 6, 6, 0.16),
+ 0px 12px 28px rgba(5, 6, 6, 0.64);
+ }
+}
+
+@keyframes light-ext-mention-flashing {
+ 0% {
+ background-color: @light-notification-bg-color;
+ border-color: @light-external-flash-border-color;
+ }
+ 50% {
+ background-color: @light-mention-flash-mention-bg-color;
+ border-color: @light-mention-flash-border-color;
+ }
+}
+
+@keyframes light-flashing {
+ 50% {
+ background-color: @light-notification-bg-color;
+ border-color: transparent;
+ }
+}
+
+@keyframes dark-flashing {
+ 50% {
+ background-color: @dark-notification-bg-color;
+ border-color: @dark-notification-border-color;
+ }
+}
+
+@keyframes light-ext-flashing {
+ 0% {
+ background-color: @light-notification-bg-color;
+ }
+ 50% {
+ background-color: @light-external-flash-mention-bg-color;
+ }
+}
+
+@keyframes dark-ext-flashing {
+ 0% {
+ background-color: @dark-notification-bg-color;
+ }
+ 50% {
+ background-color: @dark-external-flash-bg-color;
+ }
+}
diff --git a/src/renderer/styles/variables.less b/src/renderer/styles/variables.less
new file mode 100644
index 00000000..d92107d8
--- /dev/null
+++ b/src/renderer/styles/variables.less
@@ -0,0 +1,17 @@
+@input-width: 290px;
+@dark-notification-bg-color: #27292c;
+@dark-notification-border-color: #717681;
+@dark-regular-flash-bg-color: #27588e;
+@dark-regular-flash-border-color: #2996fd;
+@dark-mention-flash-bg-color: #99342c;
+@dark-mention-flash-border-color: #ff5d50;
+@dark-external-flash-border-color: #f7ca3b;
+@dark-external-flash-bg-color: #70511f;
+
+@light-notification-bg-color: #f1f1f3;
+@light-notification-border-color: transparent;
+@light-regular-flash-mention-bg-color: #aad4f8;
+@light-mention-flash-mention-bg-color: #fcc1b9;
+@light-mention-flash-border-color: #ff5d50;
+@light-external-flash-border-color: #f7ca3b;
+@light-external-flash-mention-bg-color: #f6e5a6;
From 662a67b73859fafb0e1ac254c63bbe45e2427b86 Mon Sep 17 00:00:00 2001
From: sbenmoussati <51402489+sbenmoussati@users.noreply.github.com>
Date: Tue, 3 Aug 2021 11:15:12 +0200
Subject: [PATCH 02/11] SDA-3268 Ext room name length fix
---
src/renderer/components/notification-comp.tsx | 22 ++++++++++++++--
src/renderer/styles/notification-comp.less | 25 +++++++++----------
2 files changed, 32 insertions(+), 15 deletions(-)
diff --git a/src/renderer/components/notification-comp.tsx b/src/renderer/components/notification-comp.tsx
index 12caecab..f20f6a69 100644
--- a/src/renderer/components/notification-comp.tsx
+++ b/src/renderer/components/notification-comp.tsx
@@ -58,6 +58,8 @@ type keyboardEvent = React.KeyboardEvent
;
// Notification container height
const CONTAINER_HEIGHT = 100;
const CONTAINER_HEIGHT_WITH_INPUT = 142;
+const LIGHT_THEME = '#EAEBEC';
+const DARK_THEME = '#25272B';
export default class NotificationComp extends React.Component<
{},
@@ -466,10 +468,12 @@ export default class NotificationComp extends React.Component<
currentColors.notificationBorderColor;
} else {
// in case of regular message without mention
- currentColors.notificationBackgroundColor = color
+ // FYI: SDA versions prior to 9.2.3 do not support theme color properly, reason why SFE-lite is pushing notification default background color.
+ // For this reason, to be backward compatible, we check if sent color correspond to 'default' background color. If yes, we should ignore it and not consider it as a custom color.
+ currentColors.notificationBackgroundColor = this.isCustomColor(color)
? color
: currentColors.regularFlashingNotificationBgColor;
- currentColors.notificationBorderColor = color
+ currentColors.notificationBorderColor = this.isCustomColor(color)
? color
: theme === Themes.DARK
? '#2996fd'
@@ -514,6 +518,7 @@ export default class NotificationComp extends React.Component<
const { flash, theme, hasMention, isExternal } = this.state;
if (flash && theme) {
if (isExternal) {
+ customClasses.push('external-border');
if (hasMention) {
customClasses.push(`${theme}-ext-mention-flashing`);
} else {
@@ -530,4 +535,17 @@ export default class NotificationComp extends React.Component<
}
return customClasses;
}
+
+ /**
+ * SDA versions prior to 9.2.3 do not support theme color properly, reason why SFE-lite is pushing notification default background color and theme.
+ * For that reason, we try to identify if provided color is the default one or not.
+ * @param color color sent through SDABridge
+ * @returns boolean
+ */
+ private isCustomColor(color: string): boolean {
+ if (color && color !== LIGHT_THEME && color !== DARK_THEME) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/src/renderer/styles/notification-comp.less b/src/renderer/styles/notification-comp.less
index 91bc82f9..1c596c31 100644
--- a/src/renderer/styles/notification-comp.less
+++ b/src/renderer/styles/notification-comp.less
@@ -184,6 +184,7 @@ body {
height: 16px;
width: 26px;
margin-left: 8px;
+ padding-top: 1px;
align-items: center;
}
@@ -269,20 +270,18 @@ body {
border: none;
color: var(--text-color);
}
-
- .rte-send-button {
- width: 25px;
- height: 25px;
- align-self: center;
- padding: 3px;
- background: url('../assets/notification-send-button-enabled.svg')
- no-repeat center;
- border: none;
- color: var(--text-color);
- }
}
}
-
+.rte-send-button {
+ width: 25px;
+ height: 25px;
+ align-self: center;
+ padding: 3px;
+ background: url('../assets/notification-send-button-enabled.svg') no-repeat
+ center;
+ border: none;
+ color: var(--text-color);
+}
.rte-thumbsup-button:focus,
.rte-send-button:focus {
outline: none;
@@ -298,7 +297,7 @@ body {
}
.external-border .title {
- max-width: 142px;
+ max-width: 142px !important;
}
.company {
From 019f530044dfe91bf9d2981d79f44b8a6e57b052 Mon Sep 17 00:00:00 2001
From: sbenmoussati <51402489+sbenmoussati@users.noreply.github.com>
Date: Wed, 4 Aug 2021 17:43:51 +0200
Subject: [PATCH 03/11] SDA-3237 Additional colors use-cases
---
src/renderer/components/notification-comp.tsx | 79 ++++++++++++++++++-
src/renderer/styles/notification-comp.less | 3 +-
.../styles/notifications-animations.less | 12 +--
src/renderer/styles/variables.less | 2 +-
4 files changed, 82 insertions(+), 14 deletions(-)
diff --git a/src/renderer/components/notification-comp.tsx b/src/renderer/components/notification-comp.tsx
index f20f6a69..c856771f 100644
--- a/src/renderer/components/notification-comp.tsx
+++ b/src/renderer/components/notification-comp.tsx
@@ -23,11 +23,15 @@ const Colors = {
regularFlashingNotificationBgColor: '#27588e',
notificationBackgroundColor: '#27292c',
notificationBorderColor: '#717681',
+ mentionBackgroundColor: '#99342c',
+ mentionBorderColor: '#ff5d50',
},
light: {
regularFlashingNotificationBgColor: '#aad4f8',
notificationBackgroundColor: '#f1f1f3',
notificationBorderColor: 'transparent',
+ mentionBackgroundColor: '#fcc1b9',
+ mentionBorderColor: 'transparent',
},
};
@@ -460,9 +464,23 @@ export default class NotificationComp extends React.Component<
const { theme, flash, isExternal, hasMention, color } = this.state;
const currentColors =
theme === Themes.DARK ? { ...Colors.dark } : { ...Colors.light };
+ const externalFlashingBackgroundColor =
+ theme === Themes.DARK ? '#70511f' : '#f6e5a6';
if (flash && theme) {
if (isExternal) {
- currentColors.notificationBorderColor = '#F7CA3B';
+ if (!hasMention) {
+ currentColors.notificationBorderColor = '#F7CA3B';
+ currentColors.notificationBackgroundColor = externalFlashingBackgroundColor;
+ if (this.isCustomColor(color)) {
+ currentColors.notificationBorderColor = this.getThemedCustomBorderColor(
+ theme,
+ color,
+ );
+ currentColors.notificationBackgroundColor = color;
+ }
+ } else {
+ currentColors.notificationBorderColor = '#F7CA3B';
+ }
} else if (hasMention) {
currentColors.notificationBorderColor =
currentColors.notificationBorderColor;
@@ -474,13 +492,26 @@ export default class NotificationComp extends React.Component<
? color
: currentColors.regularFlashingNotificationBgColor;
currentColors.notificationBorderColor = this.isCustomColor(color)
- ? color
+ ? this.getThemedCustomBorderColor(theme, color)
: theme === Themes.DARK
? '#2996fd'
: 'transparent';
}
- } else if (!flash && color) {
- currentColors.notificationBackgroundColor = currentColors.notificationBorderColor = color;
+ } else if (!flash) {
+ if (hasMention) {
+ currentColors.notificationBackgroundColor =
+ currentColors.mentionBackgroundColor;
+ currentColors.notificationBorderColor =
+ currentColors.mentionBorderColor;
+ } else if (this.isCustomColor(color)) {
+ currentColors.notificationBackgroundColor = color;
+ currentColors.notificationBorderColor = this.getThemedCustomBorderColor(
+ theme,
+ color,
+ );
+ } else if (isExternal) {
+ currentColors.notificationBorderColor = '#F7CA3B';
+ }
}
return currentColors;
}
@@ -548,4 +579,44 @@ export default class NotificationComp extends React.Component<
}
return false;
}
+
+ /**
+ * Function that allows to increase color brightness
+ * @param hex hes color
+ * @param percent percent
+ * @returns new hex color
+ */
+ private increaseBrightness(hex: string, percent: number) {
+ // strip the leading # if it's there
+ hex = hex.replace(/^\s*#|\s*$/g, '');
+ const r = parseInt(hex.substr(0, 2), 16);
+ const g = parseInt(hex.substr(2, 2), 16);
+ const b = parseInt(hex.substr(4, 2), 16);
+
+ return (
+ '#' +
+ // tslint:disable-next-line: no-bitwise
+ (0 | ((1 << 8) + r + ((256 - r) * percent) / 100))
+ .toString(16)
+ .substr(1) +
+ // tslint:disable-next-line: no-bitwise
+ (0 | ((1 << 8) + g + ((256 - g) * percent) / 100))
+ .toString(16)
+ .substr(1) +
+ // tslint:disable-next-line: no-bitwise
+ (0 | ((1 << 8) + b + ((256 - b) * percent) / 100)).toString(16).substr(1)
+ );
+ }
+
+ /**
+ * Returns custom border color
+ * @param theme current theme
+ * @param customColor color
+ * @returns custom border color
+ */
+ private getThemedCustomBorderColor(theme: string, customColor: string) {
+ return theme === Themes.DARK
+ ? this.increaseBrightness(customColor, 50)
+ : 'transparent';
+ }
}
diff --git a/src/renderer/styles/notification-comp.less b/src/renderer/styles/notification-comp.less
index 1c596c31..cb129828 100644
--- a/src/renderer/styles/notification-comp.less
+++ b/src/renderer/styles/notification-comp.less
@@ -143,13 +143,14 @@ body {
cursor: default;
text-overflow: ellipsis;
color: var(--text-color);
+ white-space: pre-line;
}
}
}
}
.external-border {
- border: 2px solid #f7ca3b !important;
+ border: 2px solid #f7ca3b;
}
.header:lang(fr-FR) {
diff --git a/src/renderer/styles/notifications-animations.less b/src/renderer/styles/notifications-animations.less
index a4807306..d38045d1 100644
--- a/src/renderer/styles/notifications-animations.less
+++ b/src/renderer/styles/notifications-animations.less
@@ -64,19 +64,15 @@
}
@keyframes light-ext-flashing {
- 0% {
- background-color: @light-notification-bg-color;
- }
50% {
- background-color: @light-external-flash-mention-bg-color;
+ background-color: @light-notification-bg-color;
+ border-color: @light-external-flash-border-color;
}
}
@keyframes dark-ext-flashing {
- 0% {
- background-color: @dark-notification-bg-color;
- }
50% {
- background-color: @dark-external-flash-bg-color;
+ background-color: @dark-notification-bg-color;
+ border-color: @dark-external-flash-border-color;
}
}
diff --git a/src/renderer/styles/variables.less b/src/renderer/styles/variables.less
index d92107d8..9d05fb02 100644
--- a/src/renderer/styles/variables.less
+++ b/src/renderer/styles/variables.less
@@ -14,4 +14,4 @@
@light-mention-flash-mention-bg-color: #fcc1b9;
@light-mention-flash-border-color: #ff5d50;
@light-external-flash-border-color: #f7ca3b;
-@light-external-flash-mention-bg-color: #f6e5a6;
+@light-external-flash-bg-color: #f6e5a6;
From fbcae64c745d9b2488e7ad65260c7d20d37dace2 Mon Sep 17 00:00:00 2001
From: sbenmoussati <51402489+sbenmoussati@users.noreply.github.com>
Date: Thu, 5 Aug 2021 20:02:16 +0200
Subject: [PATCH 04/11] Backward compatibility fix with SDA 9.2.0 and client
1.5
---
src/renderer/components/notification-comp.tsx | 20 ++++++++++++++++---
src/renderer/styles/notification-comp.less | 1 -
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/src/renderer/components/notification-comp.tsx b/src/renderer/components/notification-comp.tsx
index c856771f..548a1e64 100644
--- a/src/renderer/components/notification-comp.tsx
+++ b/src/renderer/components/notification-comp.tsx
@@ -169,7 +169,7 @@ export default class NotificationComp extends React.Component<
title={i18n.t('Close')()}
onClick={this.eventHandlers.onClose(id)}
>
-
+