C2-18497 Add Updated badge on updated message notification

This commit is contained in:
eliseschravendeel 2023-03-14 11:14:13 +01:00 committed by Salah Benmoussati
parent 7e495f037b
commit 0fb76420ee
13 changed files with 99 additions and 19 deletions

6
.gitignore vendored
View File

@ -1,6 +1,5 @@
node_modules
dist
.DS_Store
js/preload/_*.js
.idea/
coverage/
@ -35,3 +34,8 @@ out
lib
build
# Mac system file
.DS_Store
# Local History plugin
.history

View File

@ -22,6 +22,22 @@ describe('Toast notification component', () => {
expect(container.text()).toBe(defaultProps.title);
});
it('should close the notification when the close button is clicked', async () => {
const spy = jest.spyOn(ipcRenderer, 'send');
const closeButton = wrapper.find('.close-button img');
expect(closeButton).toBeTruthy();
closeButton.simulate('click', { stopPropagation: jest.fn() });
expect(spy).toBeCalledWith('close-notification', 0);
});
it('should click on the notification when use clicks on main container', async () => {
const spy = jest.spyOn(ipcRenderer, 'send');
const notificationContainer = wrapper.find('.main-container');
expect(notificationContainer).toBeTruthy();
notificationContainer.simulate('click', { stopPropagation: jest.fn() });
expect(spy).toBeCalledWith('notification-clicked', 0);
});
it('should render Symphony logo if no image provided', () => {
const logo = '';
ipcRenderer.send(IPC_RENDERER_NOTIFICATION_DATA_CHANNEL, {
@ -151,4 +167,17 @@ describe('Toast notification component', () => {
notificationContainer.simulate('mouseenter');
expect(spy).toBeCalledWith('notification-mouseenter', 0);
});
it('should display the updated badge when message is an update', async () => {
let updatedBadge = wrapper.find('.updated-badge');
expect(updatedBadge.exists()).toBeFalsy();
const isUpdated = true;
ipcRenderer.send(IPC_RENDERER_NOTIFICATION_DATA_CHANNEL, {
...defaultProps,
isUpdated,
});
updatedBadge = wrapper.find('.updated-badge');
expect(updatedBadge.exists()).toBeTruthy();
});
});

View File

@ -253,6 +253,7 @@ export interface INotificationData {
company: string;
displayTime: number;
isExternal: boolean;
isUpdated: boolean;
theme: Theme;
isElectronNotification?: boolean;
callback?: () => void;

View File

@ -110,6 +110,10 @@
<label for="isExternal">external:</label>
<input type="checkbox" id="isExternal" />
</p>
<p>
<label for="isUpdated">is updated:</label>
<input type="checkbox" id="isUpdated" />
</p>
<p>
<label for="hasMention">has mention:</label>
<input type="checkbox" id="hasMention" />
@ -359,13 +363,15 @@
var imageUrl = document.getElementById('image').value;
var shouldFlash = document.getElementById('flash').checked;
var isExternal = document.getElementById('isExternal').checked;
var isUpdated = document.getElementById('isUpdated').checked;
var hasMention = document.getElementById('hasMention').checked;
var shouldStick = document.getElementById('sticky').checked;
var color = document.getElementById('color').value;
var tag = document.getElementById('tag').value;
var company = document.getElementById('company').value;
var isNativeNotification = document.getElementById('isNativeNotification')
.checked;
var isNativeNotification = document.getElementById(
'isNativeNotification',
).checked;
num++;
var theme = document.getElementById('select-theme').value;
@ -379,6 +385,7 @@
color: color,
sticky: shouldStick,
isExternal: isExternal,
isUpdated,
theme: theme,
data: {
hello: `Notification with id ${num} clicked')`,
@ -1196,8 +1203,9 @@
.join('');
document.getElementById('text-window-handle').value = handleStr;
};
const windowName = document.getElementById('text-window-handle-name')
.value;
const windowName = document.getElementById(
'text-window-handle-name',
).value;
if (window.ssf) {
window.ssf.getNativeWindowHandle(windowName).then(resultCallback);
} else if (window.manaSSF) {

View File

@ -214,6 +214,7 @@
"Unable to generate crash reports due to ": "Unable to generate crash reports due to ",
"Unable to generate logs due to ": "Unable to generate logs due to ",
"Undo": "Undo",
"Updated": "Updated",
"Updating Title bar style requires Symphony to relaunch.": "Updating Title bar style requires Symphony to relaunch.",
"View": "View",
"Welcome": {

View File

@ -214,6 +214,7 @@
"Unable to generate crash reports due to ": "Unable to generate crash reports due to ",
"Unable to generate logs due to ": "Unable to generate logs due to ",
"Undo": "Undo",
"Updated": "Updated",
"Updating Title bar style requires Symphony to relaunch.": "Updating Title bar style requires Symphony to relaunch.",
"View": "View",
"Welcome": {

View File

@ -214,6 +214,7 @@
"Unable to generate crash reports due to ": "Impossible de générer le rapport de crash en raison de ",
"Unable to generate logs due to ": "Impossible de générer le journal d'évènements en raison de ",
"Undo": "Annuler la dernière opération",
"Updated": "Modifié",
"Updating Title bar style requires Symphony to relaunch.": "La mise à jour du style de la barre de titre nécessite le redémarrage de Symphony.",
"View": "Visualiser",
"Welcome": {

View File

@ -214,6 +214,7 @@
"Unable to generate crash reports due to ": "Impossible de générer le rapport de crash en raison de ",
"Unable to generate logs due to ": "Impossible de générer le journal d'évenements en raison de",
"Undo": "Annuler la dernière opération",
"Updated": "Modifié",
"Updating Title bar style requires Symphony to relaunch.": "La mise à jour du style de la barre de titre nécessite le redémarrage de Symphony.",
"View": "Visualiser",
"Welcome": {

View File

@ -214,6 +214,7 @@
"Unable to generate crash reports due to ": "クラッシュレポートを生成できません。理由: ",
"Unable to generate logs due to ": "ログを生成できません。理由:",
"Undo": "元に戻す",
"Updated": "編集済み",
"Updating Title bar style requires Symphony to relaunch.": "タイトルバーのスタイルを更新するには、Symphonyが再起動する必要があります。",
"View": "ビュー",
"Welcome": {

View File

@ -214,6 +214,7 @@
"Unable to generate crash reports due to ": "クラッシュレポートを生成できません。理由: ",
"Unable to generate logs due to ": "ログを生成できません。理由:",
"Undo": "元に戻す",
"Updated": "編集済み",
"Updating Title bar style requires Symphony to relaunch.": "タイトルバーのスタイルを更新するには、Symphonyが再起動する必要があります。",
"View": "ビュー",
"Welcome": {

View File

@ -46,6 +46,7 @@ interface INotificationState {
color: string;
flash: boolean;
isExternal: boolean;
isUpdated: boolean;
theme: Theme;
hasIgnore: boolean;
hasReply: boolean;
@ -100,6 +101,7 @@ export default class NotificationComp extends React.Component<
color: '',
flash: false,
isExternal: false,
isUpdated: false,
theme: '',
isInputHidden: true,
hasIgnore: false,
@ -140,6 +142,7 @@ export default class NotificationComp extends React.Component<
id,
color,
isExternal,
isUpdated,
theme,
containerHeight,
icon,
@ -198,7 +201,10 @@ export default class NotificationComp extends React.Component<
{this.renderReplyButton(id, themeClassName)}
{this.renderIgnoreButton(id, themeClassName)}
</div>
<span className={`message-preview ${themeClassName}`}>{body}</span>
<div className={`message-preview ${themeClassName}`}>
{this.renderUpdatedBadge(isUpdated)}
{body}
</div>
</div>
</div>
{this.renderRTE(themeClassName)}
@ -247,6 +253,18 @@ export default class NotificationComp extends React.Component<
return;
}
/**
* Renders the UPDATED badge
* @param isUpdated
* @returns the updated badge if the message is updated
*/
private renderUpdatedBadge(isUpdated: boolean) {
if (!isUpdated) {
return;
}
return <div className='updated-badge'>{i18n.t('Updated')()}</div>;
}
/**
* Renders external badge if the content is from external
* @param isExternal
@ -504,12 +522,11 @@ export default class NotificationComp extends React.Component<
if (isExternal) {
if (!hasMention) {
currentColors.notificationBorderColor = '#F7CA3B';
currentColors.notificationBackgroundColor = externalFlashingBackgroundColor;
currentColors.notificationBackgroundColor =
externalFlashingBackgroundColor;
if (this.isCustomColor(color)) {
currentColors.notificationBorderColor = this.getThemedCustomBorderColor(
theme,
color,
);
currentColors.notificationBorderColor =
this.getThemedCustomBorderColor(theme, color);
currentColors.notificationBackgroundColor = color;
}
} else {

View File

@ -202,12 +202,10 @@ class Notification extends NotificationHandler {
notificationWindow.notificationData = data;
notificationWindow.winName = apiName.notificationWindowName;
notificationWindow.once('closed', () => {
const activeWindowIndex = this.activeNotifications.indexOf(
notificationWindow,
);
const inactiveWindowIndex = this.inactiveWindows.indexOf(
notificationWindow,
);
const activeWindowIndex =
this.activeNotifications.indexOf(notificationWindow);
const inactiveWindowIndex =
this.inactiveWindows.indexOf(notificationWindow);
if (activeWindowIndex !== -1) {
this.activeNotifications.splice(activeWindowIndex, 1);
@ -275,6 +273,7 @@ class Notification extends NotificationHandler {
color,
flash,
isExternal,
isUpdated,
theme,
hasIgnore,
hasReply,
@ -290,6 +289,7 @@ class Notification extends NotificationHandler {
color,
flash,
isExternal,
isUpdated,
theme,
hasIgnore,
hasReply,
@ -507,7 +507,8 @@ class Notification extends NotificationHandler {
* fullscreen state when notification is clicked
*/
public exitFullScreen(): void {
const browserWindows: ICustomBrowserWindow[] = BrowserWindow.getAllWindows() as ICustomBrowserWindow[];
const browserWindows: ICustomBrowserWindow[] =
BrowserWindow.getAllWindows() as ICustomBrowserWindow[];
for (const win in browserWindows) {
if (Object.prototype.hasOwnProperty.call(browserWindows, win)) {
const browserWin = browserWindows[win];

View File

@ -146,7 +146,21 @@ body {
cursor: default;
text-overflow: ellipsis;
color: var(--text-color);
white-space: pre-line;
.updated-badge {
float: left;
display: inline-flex;
font-weight: 600;
padding: 0rem 0.25rem;
text-transform: uppercase;
text-align: center;
align-items: center;
white-space: nowrap;
color: #27292c;
background-color: #cdcfd4;
border-radius: 0.1875rem;
margin-right: 2px;
}
}
}
}