[MM-46634] Force window to be focused after navigation on notification click (#3051)

This commit is contained in:
Devin Binnie 2024-06-04 15:43:22 -04:00 committed by GitHub
parent fd8212a756
commit 923df7c187
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 9 deletions

View file

@ -4,8 +4,8 @@
'use strict'; 'use strict';
import notMockedCP from 'child_process'; import notMockedCP from 'child_process';
import type {BrowserWindow, WebContents} from 'electron'; import type {BrowserWindow, IpcMain, IpcMainEvent, WebContents} from 'electron';
import {Notification as NotMockedNotification, shell, app} from 'electron'; import {Notification as NotMockedNotification, shell, app, ipcMain as NotMockedIpcMain} from 'electron';
import {getDoNotDisturb as notMockedGetDarwinDoNotDisturb} from 'macos-notification-state'; import {getDoNotDisturb as notMockedGetDarwinDoNotDisturb} from 'macos-notification-state';
import {getFocusAssist as notMockedGetFocusAssist} from 'windows-focus-assist'; import {getFocusAssist as notMockedGetFocusAssist} from 'windows-focus-assist';
@ -28,6 +28,7 @@ const Config = jest.mocked(notMockedConfig);
const MainWindow = jest.mocked(notMockedMainWindow); const MainWindow = jest.mocked(notMockedMainWindow);
const localizeMessage = jest.mocked(notMockedLocalizeMessage); const localizeMessage = jest.mocked(notMockedLocalizeMessage);
const cp = jest.mocked(notMockedCP); const cp = jest.mocked(notMockedCP);
const ipcMain = jest.mocked(NotMockedIpcMain);
const mentions: Array<{body: string; value: any}> = []; const mentions: Array<{body: string; value: any}> = [];
@ -69,6 +70,10 @@ jest.mock('electron', () => {
bounce: jest.fn(), bounce: jest.fn(),
}, },
}, },
ipcMain: {
on: jest.fn(),
off: jest.fn(),
},
Notification: NotificationMock, Notification: NotificationMock,
shell: { shell: {
showItemInFolder: jest.fn(), showItemInFolder: jest.fn(),
@ -273,7 +278,12 @@ describe('main/notifications', () => {
}); });
}); });
it('should switch view when clicking on notification', async () => { it('should switch view when clicking on notification, but after the navigation has happened', async () => {
let listener: (event: IpcMainEvent, ...args: any[]) => void;
ipcMain.on.mockImplementation((channel: string, cb: (event: IpcMainEvent, ...args: any[]) => void): IpcMain => {
listener = cb;
return ipcMain;
});
await NotificationManager.displayMention( await NotificationManager.displayMention(
'click_test', 'click_test',
'mention_click_body', 'mention_click_body',
@ -286,6 +296,12 @@ describe('main/notifications', () => {
); );
const mention = mentions.find((m) => m.body === 'mention_click_body'); const mention = mentions.find((m) => m.body === 'mention_click_body');
mention?.value.click(); mention?.value.click();
expect(MainWindow.show).not.toHaveBeenCalled();
expect(ViewManager.showById).not.toHaveBeenCalledWith('server_id');
// @ts-expect-error "Set by the click handler"
listener?.({} as unknown as IpcMainEvent);
expect(MainWindow.show).toHaveBeenCalled(); expect(MainWindow.show).toHaveBeenCalled();
expect(ViewManager.showById).toHaveBeenCalledWith('server_id'); expect(ViewManager.showById).toHaveBeenCalledWith('server_id');
}); });

View file

@ -1,11 +1,11 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import {app, shell, Notification} from 'electron'; import {app, shell, Notification, ipcMain} from 'electron';
import isDev from 'electron-is-dev'; import isDev from 'electron-is-dev';
import {getDoNotDisturb as getDarwinDoNotDisturb} from 'macos-notification-state'; import {getDoNotDisturb as getDarwinDoNotDisturb} from 'macos-notification-state';
import {PLAY_SOUND, NOTIFICATION_CLICKED} from 'common/communication'; import {PLAY_SOUND, NOTIFICATION_CLICKED, BROWSER_HISTORY_PUSH} from 'common/communication';
import Config from 'common/config'; import Config from 'common/config';
import {Logger} from 'common/log'; import {Logger} from 'common/log';
@ -70,11 +70,16 @@ class NotificationManager {
log.debug('notification click', serverName, mention.uId); log.debug('notification click', serverName, mention.uId);
this.allActiveNotifications.delete(mention.uId); this.allActiveNotifications.delete(mention.uId);
MainWindow.show();
if (serverName) { // Show the window after navigation has finished to avoid the focus handler
// being called before the current channel has updated
const focus = () => {
MainWindow.show();
ViewManager.showById(view.id); ViewManager.showById(view.id);
webcontents.send(NOTIFICATION_CLICKED, channelId, teamId, url); ipcMain.off(BROWSER_HISTORY_PUSH, focus);
} };
ipcMain.on(BROWSER_HISTORY_PUSH, focus);
webcontents.send(NOTIFICATION_CLICKED, channelId, teamId, url);
}); });
mention.on('close', () => { mention.on('close', () => {