MM-25003_Improve Onboarding screens for the desktop app - Intro Screen (#2220)
This commit is contained in:
@@ -55,7 +55,7 @@ function parseArgs(args: string[]) {
|
||||
// build. As such, we provide the version manually.
|
||||
version(app.getVersion()).
|
||||
help('help').
|
||||
parse(args);
|
||||
parse(args) as Args;
|
||||
}
|
||||
|
||||
function validateArgs(args: Args) {
|
||||
|
@@ -7,7 +7,7 @@ import {RELOAD_CONFIGURATION} from 'common/communication';
|
||||
import Config from 'common/config';
|
||||
|
||||
import {handleConfigUpdate} from 'main/app/config';
|
||||
import {addNewServerModalWhenMainWindowIsShown} from 'main/app/intercom';
|
||||
import {handleMainWindowIsShown} from 'main/app/intercom';
|
||||
import {setLoggingLevel} from 'main/app/utils';
|
||||
|
||||
import WindowManager from 'main/windows/windowManager';
|
||||
@@ -32,7 +32,7 @@ jest.mock('main/app/utils', () => ({
|
||||
setLoggingLevel: jest.fn(),
|
||||
}));
|
||||
jest.mock('main/app/intercom', () => ({
|
||||
addNewServerModalWhenMainWindowIsShown: jest.fn(),
|
||||
handleMainWindowIsShown: jest.fn(),
|
||||
}));
|
||||
jest.mock('main/AutoLauncher', () => ({
|
||||
enable: jest.fn(),
|
||||
@@ -98,7 +98,7 @@ describe('main/app/config', () => {
|
||||
Config.registryConfigData = {};
|
||||
|
||||
handleConfigUpdate({teams: []});
|
||||
expect(addNewServerModalWhenMainWindowIsShown).toHaveBeenCalled();
|
||||
expect(handleMainWindowIsShown).toHaveBeenCalled();
|
||||
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
|
@@ -14,7 +14,7 @@ import {setUnreadBadgeSetting} from 'main/badge';
|
||||
import {refreshTrayImages} from 'main/tray/tray';
|
||||
import WindowManager from 'main/windows/windowManager';
|
||||
|
||||
import {addNewServerModalWhenMainWindowIsShown} from './intercom';
|
||||
import {handleMainWindowIsShown} from './intercom';
|
||||
import {handleUpdateMenuEvent, setLoggingLevel, updateServerInfos, updateSpellCheckerLocales} from './utils';
|
||||
|
||||
let didCheckForAddServerModal = false;
|
||||
@@ -61,7 +61,7 @@ export function handleConfigUpdate(newConfig: CombinedConfig) {
|
||||
updateServerInfos(newConfig.teams);
|
||||
WindowManager.initializeCurrentServerName();
|
||||
if (newConfig.teams.length === 0) {
|
||||
addNewServerModalWhenMainWindowIsShown();
|
||||
handleMainWindowIsShown();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -98,7 +98,7 @@ jest.mock('main/app/config', () => ({
|
||||
handleConfigUpdate: jest.fn(),
|
||||
}));
|
||||
jest.mock('main/app/intercom', () => ({
|
||||
addNewServerModalWhenMainWindowIsShown: jest.fn(),
|
||||
handleMainWindowIsShown: jest.fn(),
|
||||
}));
|
||||
jest.mock('main/app/utils', () => ({
|
||||
clearAppCache: jest.fn(),
|
||||
|
@@ -34,6 +34,7 @@ import {
|
||||
START_UPGRADE,
|
||||
START_DOWNLOAD,
|
||||
PING_DOMAIN,
|
||||
MAIN_WINDOW_SHOWN,
|
||||
} from 'common/communication';
|
||||
import Config from 'common/config';
|
||||
import urlUtils from 'common/utils/url';
|
||||
@@ -68,7 +69,7 @@ import {
|
||||
} from './app';
|
||||
import {handleConfigUpdate, handleDarkModeChange} from './config';
|
||||
import {
|
||||
addNewServerModalWhenMainWindowIsShown,
|
||||
handleMainWindowIsShown,
|
||||
handleAppVersion,
|
||||
handleCloseTab,
|
||||
handleEditServerModal,
|
||||
@@ -247,6 +248,7 @@ function initializeInterCommunicationEventListeners() {
|
||||
ipcMain.on(SHOW_NEW_SERVER_MODAL, handleNewServerModal);
|
||||
ipcMain.on(SHOW_EDIT_SERVER_MODAL, handleEditServerModal);
|
||||
ipcMain.on(SHOW_REMOVE_SERVER_MODAL, handleRemoveServerModal);
|
||||
ipcMain.on(MAIN_WINDOW_SHOWN, handleMainWindowIsShown);
|
||||
ipcMain.on(WINDOW_CLOSE, WindowManager.close);
|
||||
ipcMain.on(WINDOW_MAXIMIZE, WindowManager.maximize);
|
||||
ipcMain.on(WINDOW_MINIMIZE, WindowManager.minimize);
|
||||
@@ -423,7 +425,7 @@ function initializeAfterAppReady() {
|
||||
// only check for non-Windows, as with Windows we have to wait for GPO teams
|
||||
if (process.platform !== 'win32' || typeof Config.registryConfigData !== 'undefined') {
|
||||
if (Config.teams.length === 0) {
|
||||
addNewServerModalWhenMainWindowIsShown();
|
||||
handleMainWindowIsShown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ import {
|
||||
handleNewServerModal,
|
||||
handleEditServerModal,
|
||||
handleRemoveServerModal,
|
||||
handleWelcomeScreenModal,
|
||||
} from './intercom';
|
||||
|
||||
jest.mock('common/config', () => ({
|
||||
@@ -235,4 +236,24 @@ describe('main/app/intercom', () => {
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleWelcomeScreenModal', () => {
|
||||
beforeEach(() => {
|
||||
getLocalURLString.mockReturnValue('/some/index.html');
|
||||
getLocalPreload.mockReturnValue('/some/preload.js');
|
||||
WindowManager.getMainWindow.mockReturnValue({});
|
||||
|
||||
Config.set.mockImplementation((name, value) => {
|
||||
Config[name] = value;
|
||||
});
|
||||
});
|
||||
|
||||
it('should show welcomeScreen modal', async () => {
|
||||
const promise = Promise.resolve({});
|
||||
ModalManager.addModal.mockReturnValue(promise);
|
||||
|
||||
handleWelcomeScreenModal();
|
||||
expect(ModalManager.addModal).toHaveBeenCalledWith('welcomeScreen', '/some/index.html', '/some/preload.js', {}, {}, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -85,15 +85,26 @@ export function handleOpenTab(event: IpcMainEvent, serverName: string, tabName:
|
||||
Config.set('teams', teams);
|
||||
}
|
||||
|
||||
export function addNewServerModalWhenMainWindowIsShown() {
|
||||
export function handleMainWindowIsShown() {
|
||||
const showWelcomeScreen = !Config.teams.length;
|
||||
const mainWindow = WindowManager.getMainWindow();
|
||||
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isVisible()) {
|
||||
handleNewServerModal();
|
||||
if (showWelcomeScreen) {
|
||||
handleWelcomeScreenModal();
|
||||
} else {
|
||||
handleNewServerModal();
|
||||
}
|
||||
} else {
|
||||
mainWindow.once('show', () => {
|
||||
log.debug('Intercom.addNewServerModalWhenMainWindowIsShown.show');
|
||||
handleNewServerModal();
|
||||
if (showWelcomeScreen) {
|
||||
log.debug('Intercom.handleMainWindowIsShown.show.welcomeScreenModal');
|
||||
handleWelcomeScreenModal();
|
||||
} else {
|
||||
log.debug('Intercom.handleMainWindowIsShown.show.newServerModal');
|
||||
handleNewServerModal();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -213,6 +224,32 @@ export function handleRemoveServerModal(e: IpcMainEvent, name: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function handleWelcomeScreenModal() {
|
||||
log.debug('Intercom.handleWelcomeScreenModal');
|
||||
|
||||
const html = getLocalURLString('welcomeScreen.html');
|
||||
|
||||
const modalPreload = getLocalPreload('modalPreload.js');
|
||||
|
||||
const mainWindow = WindowManager.getMainWindow();
|
||||
if (!mainWindow) {
|
||||
return;
|
||||
}
|
||||
const modalPromise = ModalManager.addModal('welcomeScreen', html, modalPreload, {}, mainWindow, true);
|
||||
if (modalPromise) {
|
||||
modalPromise.then(() => {
|
||||
handleNewServerModal();
|
||||
}).catch((e) => {
|
||||
// e is undefined for user cancellation
|
||||
if (e) {
|
||||
log.error(`there was an error in the welcome screen modal: ${e}`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.warn('There is already a welcome screen modal');
|
||||
}
|
||||
}
|
||||
|
||||
export function handleMentionNotification(event: IpcMainEvent, title: string, body: string, channel: {id: string}, teamId: string, url: string, silent: boolean, data: MentionData) {
|
||||
log.debug('Intercom.handleMentionNotification', {title, body, channel, teamId, url, silent, data});
|
||||
displayMention(title, body, channel, teamId, url, silent, event.sender, data);
|
||||
|
@@ -7,7 +7,7 @@
|
||||
import {dialog, ipcMain} from 'electron';
|
||||
import {Tuple as tuple} from '@bloomberg/record-tuple-polyfill';
|
||||
|
||||
import {BROWSER_HISTORY_PUSH, LOAD_SUCCESS, SHOW_NEW_SERVER_MODAL} from 'common/communication';
|
||||
import {BROWSER_HISTORY_PUSH, LOAD_SUCCESS, MAIN_WINDOW_SHOWN} from 'common/communication';
|
||||
import {MattermostServer} from 'common/servers/MattermostServer';
|
||||
import {getServerView, getTabViewName} from 'common/tabs/TabView';
|
||||
import urlUtils from 'common/utils/url';
|
||||
@@ -547,7 +547,7 @@ describe('main/views/viewManager', () => {
|
||||
};
|
||||
viewManager.getServers = () => [];
|
||||
viewManager.showInitial();
|
||||
expect(ipcMain.emit).toHaveBeenCalledWith(SHOW_NEW_SERVER_MODAL);
|
||||
expect(ipcMain.emit).toHaveBeenCalledWith(MAIN_WINDOW_SHOWN);
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -20,7 +20,7 @@ import {
|
||||
BROWSER_HISTORY_PUSH,
|
||||
UPDATE_LAST_ACTIVE,
|
||||
UPDATE_URL_VIEW_WIDTH,
|
||||
SHOW_NEW_SERVER_MODAL,
|
||||
MAIN_WINDOW_SHOWN,
|
||||
} from 'common/communication';
|
||||
import Config from 'common/config';
|
||||
import urlUtils from 'common/utils/url';
|
||||
@@ -215,7 +215,7 @@ export class ViewManager {
|
||||
}
|
||||
} else {
|
||||
this.mainWindow.webContents.send(SET_ACTIVE_VIEW, null, null);
|
||||
ipcMain.emit(SHOW_NEW_SERVER_MODAL);
|
||||
ipcMain.emit(MAIN_WINDOW_SHOWN);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -217,7 +217,17 @@ describe('main/windows/windowManager', () => {
|
||||
});
|
||||
|
||||
it('should use getSize when the platform is linux', () => {
|
||||
const originalPlatform = process.platform;
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'linux',
|
||||
});
|
||||
|
||||
windowManager.handleResizeMainWindow();
|
||||
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
});
|
||||
|
||||
expect(view.setBounds).not.toHaveBeenCalled();
|
||||
jest.runAllTimers();
|
||||
expect(view.setBounds).toHaveBeenCalledWith({width: 1000, height: 900});
|
||||
@@ -281,6 +291,76 @@ describe('main/windows/windowManager', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleResizedMainWindow', () => {
|
||||
const windowManager = new WindowManager();
|
||||
const view = {
|
||||
setBounds: jest.fn(),
|
||||
tab: {
|
||||
url: 'http://server-1.com',
|
||||
},
|
||||
view: {
|
||||
webContents: {
|
||||
getURL: jest.fn(),
|
||||
},
|
||||
},
|
||||
};
|
||||
windowManager.mainWindow = {
|
||||
getContentBounds: () => ({width: 800, height: 600}),
|
||||
getSize: () => [1000, 900],
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
getAdjustedWindowBoundaries.mockImplementation((width, height) => ({width, height}));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
windowManager.isResizing = true;
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('should not handle bounds if no window available', () => {
|
||||
windowManager.handleResizedMainWindow();
|
||||
expect(windowManager.isResizing).toBe(false);
|
||||
expect(view.setBounds).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should use getContentBounds when the platform is different to linux', () => {
|
||||
windowManager.viewManager = {
|
||||
getCurrentView: () => view,
|
||||
};
|
||||
|
||||
const originalPlatform = process.platform;
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'windows',
|
||||
});
|
||||
|
||||
windowManager.handleResizedMainWindow();
|
||||
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
});
|
||||
|
||||
expect(windowManager.isResizing).toBe(false);
|
||||
expect(view.setBounds).toHaveBeenCalledWith({width: 800, height: 600});
|
||||
});
|
||||
|
||||
it('should use getSize when the platform is linux', () => {
|
||||
const originalPlatform = process.platform;
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'linux',
|
||||
});
|
||||
|
||||
windowManager.handleResizedMainWindow();
|
||||
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
});
|
||||
|
||||
expect(windowManager.isResizing).toBe(false);
|
||||
expect(view.setBounds).toHaveBeenCalledWith({width: 1000, height: 900});
|
||||
});
|
||||
});
|
||||
|
||||
describe('restoreMain', () => {
|
||||
const windowManager = new WindowManager();
|
||||
windowManager.mainWindow = {
|
||||
|
@@ -203,8 +203,12 @@ export class WindowManager {
|
||||
}
|
||||
|
||||
handleResizedMainWindow = () => {
|
||||
log.silly('WindowManager.handleResizedMainWindow');
|
||||
|
||||
if (this.mainWindow) {
|
||||
this.throttledWillResize(this.mainWindow?.getContentBounds());
|
||||
const bounds = this.getBounds();
|
||||
this.throttledWillResize(bounds);
|
||||
ipcMain.emit(RESIZE_MODAL, null, bounds);
|
||||
}
|
||||
this.isResizing = false;
|
||||
}
|
||||
@@ -228,17 +232,7 @@ export class WindowManager {
|
||||
return;
|
||||
}
|
||||
|
||||
let bounds;
|
||||
|
||||
// Workaround for linux maximizing/minimizing, which doesn't work properly because of these bugs:
|
||||
// https://github.com/electron/electron/issues/28699
|
||||
// https://github.com/electron/electron/issues/28106
|
||||
if (process.platform === 'linux') {
|
||||
const size = this.mainWindow.getSize();
|
||||
bounds = {width: size[0], height: size[1]};
|
||||
} else {
|
||||
bounds = this.mainWindow.getContentBounds();
|
||||
}
|
||||
const bounds = this.getBounds();
|
||||
|
||||
// Another workaround since the window doesn't update p roperly under Linux for some reason
|
||||
// See above comment
|
||||
@@ -261,6 +255,24 @@ export class WindowManager {
|
||||
currentView.setBounds(bounds);
|
||||
};
|
||||
|
||||
private getBounds = () => {
|
||||
let bounds;
|
||||
|
||||
if (this.mainWindow) {
|
||||
// Workaround for linux maximizing/minimizing, which doesn't work properly because of these bugs:
|
||||
// https://github.com/electron/electron/issues/28699
|
||||
// https://github.com/electron/electron/issues/28106
|
||||
if (process.platform === 'linux') {
|
||||
const size = this.mainWindow.getSize();
|
||||
bounds = {width: size[0], height: size[1]};
|
||||
} else {
|
||||
bounds = this.mainWindow.getContentBounds();
|
||||
}
|
||||
}
|
||||
|
||||
return bounds as Electron.Rectangle;
|
||||
}
|
||||
|
||||
// max retries allows the message to get to the renderer even if it is sent while the app is starting up.
|
||||
sendToRendererWithRetry = (maxRetries: number, channel: string, ...args: any[]) => {
|
||||
if (!this.mainWindow || !this.mainWindowReady) {
|
||||
|
Reference in New Issue
Block a user