[MM-52333] Create Server View State module, move into new app
module (#2739)
* Create Server View State Module * Move currentServerId to serverViewState * Move view state into server view state module * PR feedback/bug fixes
This commit is contained in:
@@ -12,10 +12,12 @@ import {getLocalURLString, getLocalPreload} from 'main/utils';
|
|||||||
import MainWindow from 'main/windows/mainWindow';
|
import MainWindow from 'main/windows/mainWindow';
|
||||||
import ViewManager from 'main/views/viewManager';
|
import ViewManager from 'main/views/viewManager';
|
||||||
|
|
||||||
import * as Servers from './servers';
|
import {ServerViewState} from './serverViewState';
|
||||||
|
|
||||||
jest.mock('electron', () => ({
|
jest.mock('electron', () => ({
|
||||||
ipcMain: {
|
ipcMain: {
|
||||||
|
on: jest.fn(),
|
||||||
|
handle: jest.fn(),
|
||||||
emit: jest.fn(),
|
emit: jest.fn(),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
@@ -32,6 +34,7 @@ jest.mock('common/servers/serverManager', () => ({
|
|||||||
getLastActiveTabForServer: jest.fn(),
|
getLastActiveTabForServer: jest.fn(),
|
||||||
getServerLog: jest.fn(),
|
getServerLog: jest.fn(),
|
||||||
lookupViewByURL: jest.fn(),
|
lookupViewByURL: jest.fn(),
|
||||||
|
getOrderedServers: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('common/servers/MattermostServer', () => ({
|
jest.mock('common/servers/MattermostServer', () => ({
|
||||||
MattermostServer: jest.fn(),
|
MattermostServer: jest.fn(),
|
||||||
@@ -84,8 +87,9 @@ const servers = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('main/app/servers', () => {
|
describe('app/serverViewState', () => {
|
||||||
describe('switchServer', () => {
|
describe('switchServer', () => {
|
||||||
|
const serverViewState = new ServerViewState();
|
||||||
const views = new Map([
|
const views = new Map([
|
||||||
['view-1', {id: 'view-1'}],
|
['view-1', {id: 'view-1'}],
|
||||||
['view-2', {id: 'view-2'}],
|
['view-2', {id: 'view-2'}],
|
||||||
@@ -125,26 +129,26 @@ describe('main/app/servers', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should do nothing if cannot find the server', () => {
|
it('should do nothing if cannot find the server', () => {
|
||||||
Servers.switchServer('server-3');
|
serverViewState.switchServer('server-3');
|
||||||
expect(ViewManager.showById).not.toBeCalled();
|
expect(ViewManager.showById).not.toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show first open view in order when last active not defined', () => {
|
it('should show first open view in order when last active not defined', () => {
|
||||||
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'view-3'});
|
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'view-3'});
|
||||||
Servers.switchServer('server-1');
|
serverViewState.switchServer('server-1');
|
||||||
expect(ViewManager.showById).toHaveBeenCalledWith('view-3');
|
expect(ViewManager.showById).toHaveBeenCalledWith('view-3');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show last active view of chosen server', () => {
|
it('should show last active view of chosen server', () => {
|
||||||
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'view-2'});
|
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'view-2'});
|
||||||
Servers.switchServer('server-2');
|
serverViewState.switchServer('server-2');
|
||||||
expect(ViewManager.showById).toHaveBeenCalledWith('view-2');
|
expect(ViewManager.showById).toHaveBeenCalledWith('view-2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should wait for view to exist if specified', () => {
|
it('should wait for view to exist if specified', () => {
|
||||||
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'view-3'});
|
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'view-3'});
|
||||||
views.delete('view-3');
|
views.delete('view-3');
|
||||||
Servers.switchServer('server-1', true);
|
serverViewState.switchServer('server-1', true);
|
||||||
expect(ViewManager.showById).not.toBeCalled();
|
expect(ViewManager.showById).not.toBeCalled();
|
||||||
|
|
||||||
jest.advanceTimersByTime(200);
|
jest.advanceTimersByTime(200);
|
||||||
@@ -156,7 +160,8 @@ describe('main/app/servers', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handleNewServerModal', () => {
|
describe('showNewServerModal', () => {
|
||||||
|
const serverViewState = new ServerViewState();
|
||||||
let serversCopy;
|
let serversCopy;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -196,7 +201,7 @@ describe('main/app/servers', () => {
|
|||||||
const promise = Promise.resolve(data);
|
const promise = Promise.resolve(data);
|
||||||
ModalManager.addModal.mockReturnValue(promise);
|
ModalManager.addModal.mockReturnValue(promise);
|
||||||
|
|
||||||
Servers.handleNewServerModal();
|
serverViewState.showNewServerModal();
|
||||||
await promise;
|
await promise;
|
||||||
|
|
||||||
expect(ServerManager.addServer).toHaveBeenCalledWith(data);
|
expect(ServerManager.addServer).toHaveBeenCalledWith(data);
|
||||||
@@ -213,6 +218,7 @@ describe('main/app/servers', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('handleEditServerModal', () => {
|
describe('handleEditServerModal', () => {
|
||||||
|
const serverViewState = new ServerViewState();
|
||||||
let serversCopy;
|
let serversCopy;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -241,7 +247,7 @@ describe('main/app/servers', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should do nothing when the server cannot be found', () => {
|
it('should do nothing when the server cannot be found', () => {
|
||||||
Servers.handleEditServerModal(null, 'bad-server');
|
serverViewState.showEditServerModal(null, 'bad-server');
|
||||||
expect(ModalManager.addModal).not.toBeCalled();
|
expect(ModalManager.addModal).not.toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -252,7 +258,7 @@ describe('main/app/servers', () => {
|
|||||||
});
|
});
|
||||||
ModalManager.addModal.mockReturnValue(promise);
|
ModalManager.addModal.mockReturnValue(promise);
|
||||||
|
|
||||||
Servers.handleEditServerModal(null, 'server-1');
|
serverViewState.showEditServerModal(null, 'server-1');
|
||||||
await promise;
|
await promise;
|
||||||
expect(serversCopy).not.toContainEqual(expect.objectContaining({
|
expect(serversCopy).not.toContainEqual(expect.objectContaining({
|
||||||
id: 'server-1',
|
id: 'server-1',
|
||||||
@@ -270,6 +276,7 @@ describe('main/app/servers', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('handleRemoveServerModal', () => {
|
describe('handleRemoveServerModal', () => {
|
||||||
|
const serverViewState = new ServerViewState();
|
||||||
let serversCopy;
|
let serversCopy;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -278,23 +285,20 @@ describe('main/app/servers', () => {
|
|||||||
MainWindow.get.mockReturnValue({});
|
MainWindow.get.mockReturnValue({});
|
||||||
|
|
||||||
serversCopy = JSON.parse(JSON.stringify(servers));
|
serversCopy = JSON.parse(JSON.stringify(servers));
|
||||||
ServerManager.getServer.mockImplementation((id) => {
|
ServerManager.getServer.mockImplementation(() => {
|
||||||
if (id !== serversCopy[0].id) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return serversCopy[0];
|
return serversCopy[0];
|
||||||
});
|
});
|
||||||
ServerManager.removeServer.mockImplementation(() => {
|
ServerManager.removeServer.mockImplementation(() => {
|
||||||
serversCopy = [];
|
serversCopy = [];
|
||||||
});
|
});
|
||||||
ServerManager.getAllServers.mockReturnValue(serversCopy);
|
ServerManager.getOrderedServers.mockReturnValue(serversCopy);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove the existing server', async () => {
|
it('should remove the existing server', async () => {
|
||||||
const promise = Promise.resolve(true);
|
const promise = Promise.resolve(true);
|
||||||
ModalManager.addModal.mockReturnValue(promise);
|
ModalManager.addModal.mockReturnValue(promise);
|
||||||
|
|
||||||
Servers.handleRemoveServerModal(null, 'server-1');
|
serverViewState.showRemoveServerModal(null, 'server-1');
|
||||||
await promise;
|
await promise;
|
||||||
expect(serversCopy).not.toContainEqual(expect.objectContaining({
|
expect(serversCopy).not.toContainEqual(expect.objectContaining({
|
||||||
id: 'server-1',
|
id: 'server-1',
|
||||||
@@ -315,7 +319,7 @@ describe('main/app/servers', () => {
|
|||||||
tabs,
|
tabs,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Servers.handleRemoveServerModal(null, 'server-1');
|
serverViewState.showRemoveServerModal(null, 'server-1');
|
||||||
await promise;
|
await promise;
|
||||||
expect(serversCopy).toContainEqual(expect.objectContaining({
|
expect(serversCopy).toContainEqual(expect.objectContaining({
|
||||||
id: 'server-1',
|
id: 'server-1',
|
||||||
@@ -327,6 +331,8 @@ describe('main/app/servers', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('handleServerURLValidation', () => {
|
describe('handleServerURLValidation', () => {
|
||||||
|
const serverViewState = new ServerViewState();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
MattermostServer.mockImplementation(({url}) => ({url}));
|
MattermostServer.mockImplementation(({url}) => ({url}));
|
||||||
ServerInfo.mockImplementation(({url}) => ({
|
ServerInfo.mockImplementation(({url}) => ({
|
||||||
@@ -343,43 +349,43 @@ describe('main/app/servers', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should return Missing when you get no URL', async () => {
|
it('should return Missing when you get no URL', async () => {
|
||||||
const result = await Servers.handleServerURLValidation({});
|
const result = await serverViewState.handleServerURLValidation({});
|
||||||
expect(result.status).toBe(URLValidationStatus.Missing);
|
expect(result.status).toBe(URLValidationStatus.Missing);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return Invalid when you pass in invalid characters', async () => {
|
it('should return Invalid when you pass in invalid characters', async () => {
|
||||||
const result = await Servers.handleServerURLValidation({}, '!@#$%^&*()!@#$%^&*()');
|
const result = await serverViewState.handleServerURLValidation({}, '!@#$%^&*()!@#$%^&*()');
|
||||||
expect(result.status).toBe(URLValidationStatus.Invalid);
|
expect(result.status).toBe(URLValidationStatus.Invalid);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should include HTTPS when missing', async () => {
|
it('should include HTTPS when missing', async () => {
|
||||||
const result = await Servers.handleServerURLValidation({}, 'server.com');
|
const result = await serverViewState.handleServerURLValidation({}, 'server.com');
|
||||||
expect(result.status).toBe(URLValidationStatus.OK);
|
expect(result.status).toBe(URLValidationStatus.OK);
|
||||||
expect(result.validatedURL).toBe('https://server.com/');
|
expect(result.validatedURL).toBe('https://server.com/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correct typos in the protocol', async () => {
|
it('should correct typos in the protocol', async () => {
|
||||||
const result = await Servers.handleServerURLValidation({}, 'htpst://server.com');
|
const result = await serverViewState.handleServerURLValidation({}, 'htpst://server.com');
|
||||||
expect(result.status).toBe(URLValidationStatus.OK);
|
expect(result.status).toBe(URLValidationStatus.OK);
|
||||||
expect(result.validatedURL).toBe('https://server.com/');
|
expect(result.validatedURL).toBe('https://server.com/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should replace HTTP with HTTPS when applicable', async () => {
|
it('should replace HTTP with HTTPS when applicable', async () => {
|
||||||
const result = await Servers.handleServerURLValidation({}, 'http://server.com');
|
const result = await serverViewState.handleServerURLValidation({}, 'http://server.com');
|
||||||
expect(result.status).toBe(URLValidationStatus.OK);
|
expect(result.status).toBe(URLValidationStatus.OK);
|
||||||
expect(result.validatedURL).toBe('https://server.com/');
|
expect(result.validatedURL).toBe('https://server.com/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate a warning when the server already exists', async () => {
|
it('should generate a warning when the server already exists', async () => {
|
||||||
ServerManager.lookupViewByURL.mockReturnValue({server: {id: 'server-1', url: new URL('https://server.com')}});
|
ServerManager.lookupViewByURL.mockReturnValue({server: {id: 'server-1', url: new URL('https://server.com')}});
|
||||||
const result = await Servers.handleServerURLValidation({}, 'https://server.com');
|
const result = await serverViewState.handleServerURLValidation({}, 'https://server.com');
|
||||||
expect(result.status).toBe(URLValidationStatus.URLExists);
|
expect(result.status).toBe(URLValidationStatus.URLExists);
|
||||||
expect(result.validatedURL).toBe('https://server.com/');
|
expect(result.validatedURL).toBe('https://server.com/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should generate a warning if the server exists when editing', async () => {
|
it('should generate a warning if the server exists when editing', async () => {
|
||||||
ServerManager.lookupViewByURL.mockReturnValue({server: {name: 'Server 1', id: 'server-1', url: new URL('https://server.com')}});
|
ServerManager.lookupViewByURL.mockReturnValue({server: {name: 'Server 1', id: 'server-1', url: new URL('https://server.com')}});
|
||||||
const result = await Servers.handleServerURLValidation({}, 'https://server.com', 'server-2');
|
const result = await serverViewState.handleServerURLValidation({}, 'https://server.com', 'server-2');
|
||||||
expect(result.status).toBe(URLValidationStatus.URLExists);
|
expect(result.status).toBe(URLValidationStatus.URLExists);
|
||||||
expect(result.validatedURL).toBe('https://server.com/');
|
expect(result.validatedURL).toBe('https://server.com/');
|
||||||
expect(result.existingServerName).toBe('Server 1');
|
expect(result.existingServerName).toBe('Server 1');
|
||||||
@@ -387,7 +393,7 @@ describe('main/app/servers', () => {
|
|||||||
|
|
||||||
it('should not generate a warning if editing the same server', async () => {
|
it('should not generate a warning if editing the same server', async () => {
|
||||||
ServerManager.lookupViewByURL.mockReturnValue({server: {name: 'Server 1', id: 'server-1', url: new URL('https://server.com')}});
|
ServerManager.lookupViewByURL.mockReturnValue({server: {name: 'Server 1', id: 'server-1', url: new URL('https://server.com')}});
|
||||||
const result = await Servers.handleServerURLValidation({}, 'https://server.com', 'server-1');
|
const result = await serverViewState.handleServerURLValidation({}, 'https://server.com', 'server-1');
|
||||||
expect(result.status).toBe(URLValidationStatus.OK);
|
expect(result.status).toBe(URLValidationStatus.OK);
|
||||||
expect(result.validatedURL).toBe('https://server.com/');
|
expect(result.validatedURL).toBe('https://server.com/');
|
||||||
});
|
});
|
||||||
@@ -407,7 +413,7 @@ describe('main/app/servers', () => {
|
|||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const result = await Servers.handleServerURLValidation({}, 'http://server.com');
|
const result = await serverViewState.handleServerURLValidation({}, 'http://server.com');
|
||||||
expect(result.status).toBe(URLValidationStatus.Insecure);
|
expect(result.status).toBe(URLValidationStatus.Insecure);
|
||||||
expect(result.validatedURL).toBe('http://server.com/');
|
expect(result.validatedURL).toBe('http://server.com/');
|
||||||
});
|
});
|
||||||
@@ -419,7 +425,7 @@ describe('main/app/servers', () => {
|
|||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const result = await Servers.handleServerURLValidation({}, 'https://not-server.com');
|
const result = await serverViewState.handleServerURLValidation({}, 'https://not-server.com');
|
||||||
expect(result.status).toBe(URLValidationStatus.NotMattermost);
|
expect(result.status).toBe(URLValidationStatus.NotMattermost);
|
||||||
expect(result.validatedURL).toBe('https://not-server.com/');
|
expect(result.validatedURL).toBe('https://not-server.com/');
|
||||||
});
|
});
|
||||||
@@ -435,7 +441,7 @@ describe('main/app/servers', () => {
|
|||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const result = await Servers.handleServerURLValidation({}, 'https://server.com');
|
const result = await serverViewState.handleServerURLValidation({}, 'https://server.com');
|
||||||
expect(result.status).toBe(URLValidationStatus.URLUpdated);
|
expect(result.status).toBe(URLValidationStatus.URLUpdated);
|
||||||
expect(result.validatedURL).toBe('https://mainserver.com/');
|
expect(result.validatedURL).toBe('https://mainserver.com/');
|
||||||
});
|
});
|
||||||
@@ -454,7 +460,7 @@ describe('main/app/servers', () => {
|
|||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const result = await Servers.handleServerURLValidation({}, 'https://server.com');
|
const result = await serverViewState.handleServerURLValidation({}, 'https://server.com');
|
||||||
expect(result.status).toBe(URLValidationStatus.URLNotMatched);
|
expect(result.status).toBe(URLValidationStatus.URLNotMatched);
|
||||||
expect(result.validatedURL).toBe('https://server.com/');
|
expect(result.validatedURL).toBe('https://server.com/');
|
||||||
});
|
});
|
||||||
@@ -471,10 +477,31 @@ describe('main/app/servers', () => {
|
|||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const result = await Servers.handleServerURLValidation({}, 'https://server.com');
|
const result = await serverViewState.handleServerURLValidation({}, 'https://server.com');
|
||||||
expect(result.status).toBe(URLValidationStatus.URLExists);
|
expect(result.status).toBe(URLValidationStatus.URLExists);
|
||||||
expect(result.validatedURL).toBe('https://mainserver.com/');
|
expect(result.validatedURL).toBe('https://mainserver.com/');
|
||||||
expect(result.existingServerName).toBe('Server 1');
|
expect(result.existingServerName).toBe('Server 1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('handleCloseView', () => {
|
||||||
|
const serverViewState = new ServerViewState();
|
||||||
|
|
||||||
|
it('should close the specified view and switch to the next open view', () => {
|
||||||
|
ServerManager.getView.mockReturnValue({server: {id: 'server-1'}});
|
||||||
|
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'view-2'});
|
||||||
|
serverViewState.handleCloseView(null, 'view-3');
|
||||||
|
expect(ServerManager.setViewIsOpen).toBeCalledWith('view-3', false);
|
||||||
|
expect(ViewManager.showById).toBeCalledWith('view-2');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('handleOpenView', () => {
|
||||||
|
const serverViewState = new ServerViewState();
|
||||||
|
|
||||||
|
it('should open the specified view', () => {
|
||||||
|
serverViewState.handleOpenView(null, 'view-1');
|
||||||
|
expect(ViewManager.showById).toBeCalledWith('view-1');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
380
src/app/serverViewState.ts
Normal file
380
src/app/serverViewState.ts
Normal file
@@ -0,0 +1,380 @@
|
|||||||
|
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {IpcMainEvent, IpcMainInvokeEvent, ipcMain} from 'electron';
|
||||||
|
|
||||||
|
import {UniqueServer, Server} from 'types/config';
|
||||||
|
import {URLValidationResult} from 'types/server';
|
||||||
|
|
||||||
|
import {
|
||||||
|
CLOSE_VIEW,
|
||||||
|
GET_LAST_ACTIVE,
|
||||||
|
GET_ORDERED_SERVERS,
|
||||||
|
GET_ORDERED_TABS_FOR_SERVER,
|
||||||
|
OPEN_VIEW,
|
||||||
|
SHOW_EDIT_SERVER_MODAL,
|
||||||
|
SHOW_NEW_SERVER_MODAL,
|
||||||
|
SHOW_REMOVE_SERVER_MODAL,
|
||||||
|
SWITCH_SERVER,
|
||||||
|
UPDATE_SERVER_ORDER,
|
||||||
|
UPDATE_SHORTCUT_MENU,
|
||||||
|
UPDATE_TAB_ORDER,
|
||||||
|
VALIDATE_SERVER_URL,
|
||||||
|
} from 'common/communication';
|
||||||
|
import {Logger} from 'common/log';
|
||||||
|
import ServerManager from 'common/servers/serverManager';
|
||||||
|
import {MattermostServer} from 'common/servers/MattermostServer';
|
||||||
|
import {isValidURI, isValidURL, parseURL} from 'common/utils/url';
|
||||||
|
import {URLValidationStatus} from 'common/utils/constants';
|
||||||
|
import Config from 'common/config';
|
||||||
|
|
||||||
|
import ViewManager from 'main/views/viewManager';
|
||||||
|
import ModalManager from 'main/views/modalManager';
|
||||||
|
import MainWindow from 'main/windows/mainWindow';
|
||||||
|
import {getLocalPreload, getLocalURLString} from 'main/utils';
|
||||||
|
import {ServerInfo} from 'main/server/serverInfo';
|
||||||
|
|
||||||
|
const log = new Logger('App', 'ServerViewState');
|
||||||
|
|
||||||
|
export class ServerViewState {
|
||||||
|
private currentServerId?: string;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
ipcMain.on(SWITCH_SERVER, (event, serverId) => this.switchServer(serverId));
|
||||||
|
ipcMain.on(SHOW_NEW_SERVER_MODAL, this.showNewServerModal);
|
||||||
|
ipcMain.on(SHOW_EDIT_SERVER_MODAL, this.showEditServerModal);
|
||||||
|
ipcMain.on(SHOW_REMOVE_SERVER_MODAL, this.showRemoveServerModal);
|
||||||
|
ipcMain.handle(VALIDATE_SERVER_URL, this.handleServerURLValidation);
|
||||||
|
ipcMain.handle(GET_ORDERED_SERVERS, this.handleGetOrderedServers);
|
||||||
|
ipcMain.on(UPDATE_SERVER_ORDER, this.updateServerOrder);
|
||||||
|
|
||||||
|
ipcMain.on(CLOSE_VIEW, this.handleCloseView);
|
||||||
|
ipcMain.on(OPEN_VIEW, this.handleOpenView);
|
||||||
|
ipcMain.handle(GET_LAST_ACTIVE, this.handleGetLastActive);
|
||||||
|
ipcMain.handle(GET_ORDERED_TABS_FOR_SERVER, this.handleGetOrderedViewsForServer);
|
||||||
|
ipcMain.on(UPDATE_TAB_ORDER, this.updateTabOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
init = () => {
|
||||||
|
const orderedServers = ServerManager.getOrderedServers();
|
||||||
|
if (orderedServers.length) {
|
||||||
|
if (Config.lastActiveServer && orderedServers[Config.lastActiveServer]) {
|
||||||
|
this.currentServerId = orderedServers[Config.lastActiveServer].id;
|
||||||
|
} else {
|
||||||
|
this.currentServerId = orderedServers[0].id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentServer = () => {
|
||||||
|
log.debug('getCurrentServer');
|
||||||
|
|
||||||
|
if (!this.currentServerId) {
|
||||||
|
throw new Error('No server set as current');
|
||||||
|
}
|
||||||
|
const server = ServerManager.getServer(this.currentServerId);
|
||||||
|
if (!server) {
|
||||||
|
throw new Error('Current server does not exist');
|
||||||
|
}
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
switchServer = (serverId: string, waitForViewToExist = false) => {
|
||||||
|
ServerManager.getServerLog(serverId, 'WindowManager').debug('switchServer');
|
||||||
|
MainWindow.show();
|
||||||
|
const server = ServerManager.getServer(serverId);
|
||||||
|
if (!server) {
|
||||||
|
ServerManager.getServerLog(serverId, 'WindowManager').error('Cannot find server in config');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.currentServerId = serverId;
|
||||||
|
const nextView = ServerManager.getLastActiveTabForServer(serverId);
|
||||||
|
if (waitForViewToExist) {
|
||||||
|
const timeout = setInterval(() => {
|
||||||
|
if (ViewManager.getView(nextView.id)) {
|
||||||
|
ViewManager.showById(nextView.id);
|
||||||
|
clearInterval(timeout);
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
ViewManager.showById(nextView.id);
|
||||||
|
}
|
||||||
|
ipcMain.emit(UPDATE_SHORTCUT_MENU);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectNextView = () => {
|
||||||
|
this.selectView((order) => order + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
selectPreviousView = () => {
|
||||||
|
this.selectView((order, length) => (length + (order - 1)));
|
||||||
|
};
|
||||||
|
|
||||||
|
updateCurrentView = (serverId: string, viewId: string) => {
|
||||||
|
this.currentServerId = serverId;
|
||||||
|
ServerManager.updateLastActive(viewId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server Modals
|
||||||
|
*/
|
||||||
|
|
||||||
|
showNewServerModal = () => {
|
||||||
|
log.debug('showNewServerModal');
|
||||||
|
|
||||||
|
const mainWindow = MainWindow.get();
|
||||||
|
if (!mainWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modalPromise = ModalManager.addModal<null, Server>(
|
||||||
|
'newServer',
|
||||||
|
getLocalURLString('newServer.html'),
|
||||||
|
getLocalPreload('desktopAPI.js'),
|
||||||
|
null,
|
||||||
|
mainWindow,
|
||||||
|
!ServerManager.hasServers(),
|
||||||
|
);
|
||||||
|
|
||||||
|
modalPromise.then((data) => {
|
||||||
|
const newServer = ServerManager.addServer(data);
|
||||||
|
this.switchServer(newServer.id, true);
|
||||||
|
}).catch((e) => {
|
||||||
|
// e is undefined for user cancellation
|
||||||
|
if (e) {
|
||||||
|
log.error(`there was an error in the new server modal: ${e}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
private showEditServerModal = (e: IpcMainEvent, id: string) => {
|
||||||
|
log.debug('showEditServerModal', id);
|
||||||
|
|
||||||
|
const mainWindow = MainWindow.get();
|
||||||
|
if (!mainWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const server = ServerManager.getServer(id);
|
||||||
|
if (!server) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modalPromise = ModalManager.addModal<UniqueServer, Server>(
|
||||||
|
'editServer',
|
||||||
|
getLocalURLString('editServer.html'),
|
||||||
|
getLocalPreload('desktopAPI.js'),
|
||||||
|
server.toUniqueServer(),
|
||||||
|
mainWindow);
|
||||||
|
|
||||||
|
modalPromise.then((data) => ServerManager.editServer(id, data)).catch((e) => {
|
||||||
|
// e is undefined for user cancellation
|
||||||
|
if (e) {
|
||||||
|
log.error(`there was an error in the edit server modal: ${e}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
private showRemoveServerModal = (e: IpcMainEvent, id: string) => {
|
||||||
|
log.debug('handleRemoveServerModal', id);
|
||||||
|
|
||||||
|
const mainWindow = MainWindow.get();
|
||||||
|
if (!mainWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const server = ServerManager.getServer(id);
|
||||||
|
if (!server) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modalPromise = ModalManager.addModal<string, boolean>(
|
||||||
|
'removeServer',
|
||||||
|
getLocalURLString('removeServer.html'),
|
||||||
|
getLocalPreload('desktopAPI.js'),
|
||||||
|
server.name,
|
||||||
|
mainWindow,
|
||||||
|
);
|
||||||
|
|
||||||
|
modalPromise.then((remove) => {
|
||||||
|
if (remove) {
|
||||||
|
const remainingServers = ServerManager.getOrderedServers().filter((orderedServer) => server.id !== orderedServer.id);
|
||||||
|
if (this.currentServerId === server.id && remainingServers.length) {
|
||||||
|
this.currentServerId = remainingServers[0].id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!remainingServers.length) {
|
||||||
|
delete this.currentServerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerManager.removeServer(server.id);
|
||||||
|
}
|
||||||
|
}).catch((e) => {
|
||||||
|
// e is undefined for user cancellation
|
||||||
|
if (e) {
|
||||||
|
log.error(`there was an error in the edit server modal: ${e}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IPC Handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
private handleServerURLValidation = async (e: IpcMainInvokeEvent, url?: string, currentId?: string): Promise<URLValidationResult> => {
|
||||||
|
log.debug('handleServerURLValidation', url, currentId);
|
||||||
|
|
||||||
|
// If the URL is missing or null, reject
|
||||||
|
if (!url) {
|
||||||
|
return {status: URLValidationStatus.Missing};
|
||||||
|
}
|
||||||
|
|
||||||
|
let httpUrl = url;
|
||||||
|
if (!isValidURL(url)) {
|
||||||
|
// If it already includes the protocol, tell them it's invalid
|
||||||
|
if (isValidURI(url)) {
|
||||||
|
httpUrl = url.replace(/^(.+):/, 'https:');
|
||||||
|
} else {
|
||||||
|
// Otherwise add HTTPS for them
|
||||||
|
httpUrl = `https://${url}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the final URL is valid
|
||||||
|
const parsedURL = parseURL(httpUrl);
|
||||||
|
if (!parsedURL) {
|
||||||
|
return {status: URLValidationStatus.Invalid};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try and add HTTPS to see if we can get a more secure URL
|
||||||
|
let secureURL = parsedURL;
|
||||||
|
if (parsedURL.protocol === 'http:') {
|
||||||
|
secureURL = parseURL(parsedURL.toString().replace(/^http:/, 'https:')) ?? parsedURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell the user if they already have a server for this URL
|
||||||
|
const existingServer = ServerManager.lookupViewByURL(secureURL, true);
|
||||||
|
if (existingServer && existingServer.server.id !== currentId) {
|
||||||
|
return {status: URLValidationStatus.URLExists, existingServerName: existingServer.server.name, validatedURL: existingServer.server.url.toString()};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try and get remote info from the most secure URL, otherwise use the insecure one
|
||||||
|
let remoteURL = secureURL;
|
||||||
|
let remoteInfo = await this.testRemoteServer(secureURL);
|
||||||
|
if (!remoteInfo) {
|
||||||
|
if (secureURL.toString() !== parsedURL.toString()) {
|
||||||
|
remoteURL = parsedURL;
|
||||||
|
remoteInfo = await this.testRemoteServer(parsedURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we can't get the remote info, warn the user that this might not be the right URL
|
||||||
|
// If the original URL was invalid, don't replace that as they probably have a typo somewhere
|
||||||
|
if (!remoteInfo) {
|
||||||
|
return {status: URLValidationStatus.NotMattermost, validatedURL: parsedURL.toString()};
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we were only able to connect via HTTP, warn the user that the connection is not secure
|
||||||
|
if (remoteURL.protocol === 'http:') {
|
||||||
|
return {status: URLValidationStatus.Insecure, serverVersion: remoteInfo.serverVersion, validatedURL: remoteURL.toString()};
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the URL doesn't match the Site URL, set the URL to the correct one
|
||||||
|
if (remoteInfo.siteURL && remoteURL.toString() !== new URL(remoteInfo.siteURL).toString()) {
|
||||||
|
const parsedSiteURL = parseURL(remoteInfo.siteURL);
|
||||||
|
if (parsedSiteURL) {
|
||||||
|
// Check the Site URL as well to see if it's already pre-configured
|
||||||
|
const existingServer = ServerManager.lookupViewByURL(parsedSiteURL, true);
|
||||||
|
if (existingServer && existingServer.server.id !== currentId) {
|
||||||
|
return {status: URLValidationStatus.URLExists, existingServerName: existingServer.server.name, validatedURL: existingServer.server.url.toString()};
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we can't reach the remote Site URL, there's probably a configuration issue
|
||||||
|
const remoteSiteURLInfo = await this.testRemoteServer(parsedSiteURL);
|
||||||
|
if (!remoteSiteURLInfo) {
|
||||||
|
return {status: URLValidationStatus.URLNotMatched, serverVersion: remoteInfo.serverVersion, serverName: remoteInfo.siteName, validatedURL: remoteURL.toString()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise fix it for them and return
|
||||||
|
return {status: URLValidationStatus.URLUpdated, serverVersion: remoteInfo.serverVersion, serverName: remoteInfo.siteName, validatedURL: remoteInfo.siteURL};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {status: URLValidationStatus.OK, serverVersion: remoteInfo.serverVersion, serverName: remoteInfo.siteName, validatedURL: remoteInfo.siteURL};
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleCloseView = (event: IpcMainEvent, viewId: string) => {
|
||||||
|
log.debug('handleCloseView', {viewId});
|
||||||
|
|
||||||
|
const view = ServerManager.getView(viewId);
|
||||||
|
if (!view) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ServerManager.setViewIsOpen(viewId, false);
|
||||||
|
const nextView = ServerManager.getLastActiveTabForServer(view.server.id);
|
||||||
|
ViewManager.showById(nextView.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleOpenView = (event: IpcMainEvent, viewId: string) => {
|
||||||
|
log.debug('handleOpenView', {viewId});
|
||||||
|
|
||||||
|
ServerManager.setViewIsOpen(viewId, true);
|
||||||
|
ViewManager.showById(viewId);
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleGetOrderedViewsForServer = (event: IpcMainInvokeEvent, serverId: string) => {
|
||||||
|
return ServerManager.getOrderedTabsForServer(serverId).map((view) => view.toUniqueView());
|
||||||
|
};
|
||||||
|
|
||||||
|
private handleGetLastActive = () => {
|
||||||
|
const server = this.getCurrentServer();
|
||||||
|
const view = ServerManager.getLastActiveTabForServer(server.id);
|
||||||
|
return {server: server.id, view: view.id};
|
||||||
|
};
|
||||||
|
|
||||||
|
private updateServerOrder = (event: IpcMainEvent, serverOrder: string[]) => ServerManager.updateServerOrder(serverOrder);
|
||||||
|
private updateTabOrder = (event: IpcMainEvent, serverId: string, viewOrder: string[]) => ServerManager.updateTabOrder(serverId, viewOrder);
|
||||||
|
|
||||||
|
private handleGetOrderedServers = () => ServerManager.getOrderedServers().map((srv) => srv.toUniqueServer());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
private testRemoteServer = async (parsedURL: URL) => {
|
||||||
|
const server = new MattermostServer({name: 'temp', url: parsedURL.toString()}, false);
|
||||||
|
const serverInfo = new ServerInfo(server);
|
||||||
|
try {
|
||||||
|
const remoteInfo = await serverInfo.fetchRemoteInfo();
|
||||||
|
return remoteInfo;
|
||||||
|
} catch (error) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private selectView = (fn: (order: number, length: number) => number) => {
|
||||||
|
const currentView = ViewManager.getCurrentView();
|
||||||
|
if (!currentView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentServerViews = ServerManager.getOrderedTabsForServer(currentView.view.server.id).map((view, index) => ({view, index}));
|
||||||
|
const filteredViews = currentServerViews?.filter((view) => view.view.isOpen);
|
||||||
|
const currentServerView = currentServerViews?.find((view) => view.view.type === currentView.view.type);
|
||||||
|
if (!currentServerViews || !currentServerView || !filteredViews) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentOrder = currentServerView.index;
|
||||||
|
let nextIndex = -1;
|
||||||
|
while (nextIndex === -1) {
|
||||||
|
const nextOrder = (fn(currentOrder, currentServerViews.length) % currentServerViews.length);
|
||||||
|
nextIndex = filteredViews.findIndex((view) => view.index === nextOrder);
|
||||||
|
currentOrder = nextOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newView = filteredViews[nextIndex].view;
|
||||||
|
ViewManager.showById(newView.id);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const serverViewState = new ServerViewState();
|
||||||
|
export default serverViewState;
|
@@ -26,7 +26,6 @@ export class ServerManager extends EventEmitter {
|
|||||||
private servers: Map<string, MattermostServer>;
|
private servers: Map<string, MattermostServer>;
|
||||||
private remoteInfo: Map<string, RemoteInfo>;
|
private remoteInfo: Map<string, RemoteInfo>;
|
||||||
private serverOrder: string[];
|
private serverOrder: string[];
|
||||||
private currentServerId?: string;
|
|
||||||
|
|
||||||
private views: Map<string, MattermostView>;
|
private views: Map<string, MattermostView>;
|
||||||
private viewOrder: Map<string, string[]>;
|
private viewOrder: Map<string, string[]>;
|
||||||
@@ -71,19 +70,6 @@ export class ServerManager extends EventEmitter {
|
|||||||
}, [] as MattermostServer[]);
|
}, [] as MattermostServer[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentServer = () => {
|
|
||||||
log.debug('getCurrentServer');
|
|
||||||
|
|
||||||
if (!this.currentServerId) {
|
|
||||||
throw new Error('No server set as current');
|
|
||||||
}
|
|
||||||
const server = this.servers.get(this.currentServerId);
|
|
||||||
if (!server) {
|
|
||||||
throw new Error('Current server does not exist');
|
|
||||||
}
|
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLastActiveTabForServer = (serverId: string) => {
|
getLastActiveTabForServer = (serverId: string) => {
|
||||||
log.withPrefix(serverId).debug('getLastActiveTabForServer');
|
log.withPrefix(serverId).debug('getLastActiveTabForServer');
|
||||||
|
|
||||||
@@ -187,10 +173,6 @@ export class ServerManager extends EventEmitter {
|
|||||||
});
|
});
|
||||||
this.viewOrder.set(newServer.id, viewOrder);
|
this.viewOrder.set(newServer.id, viewOrder);
|
||||||
|
|
||||||
if (!this.currentServerId) {
|
|
||||||
this.currentServerId = newServer.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit this event whenever we update a server URL to ensure remote info is fetched
|
// Emit this event whenever we update a server URL to ensure remote info is fetched
|
||||||
this.emit(SERVERS_URL_MODIFIED, [newServer.id]);
|
this.emit(SERVERS_URL_MODIFIED, [newServer.id]);
|
||||||
this.persistServers();
|
this.persistServers();
|
||||||
@@ -234,14 +216,6 @@ export class ServerManager extends EventEmitter {
|
|||||||
this.remoteInfo.delete(serverId);
|
this.remoteInfo.delete(serverId);
|
||||||
this.servers.delete(serverId);
|
this.servers.delete(serverId);
|
||||||
|
|
||||||
if (this.currentServerId === serverId && this.hasServers()) {
|
|
||||||
this.currentServerId = this.serverOrder[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.hasServers()) {
|
|
||||||
delete this.currentServerId;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.persistServers();
|
this.persistServers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,8 +236,6 @@ export class ServerManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
this.lastActiveView.set(view.server.id, viewId);
|
this.lastActiveView.set(view.server.id, viewId);
|
||||||
|
|
||||||
this.currentServerId = view.server.id;
|
|
||||||
|
|
||||||
const serverOrder = this.serverOrder.findIndex((srv) => srv === view.server.id);
|
const serverOrder = this.serverOrder.findIndex((srv) => srv === view.server.id);
|
||||||
if (serverOrder < 0) {
|
if (serverOrder < 0) {
|
||||||
throw new Error('Server order corrupt, ID not found.');
|
throw new Error('Server order corrupt, ID not found.');
|
||||||
@@ -286,11 +258,6 @@ export class ServerManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
this.filterOutDuplicateServers();
|
this.filterOutDuplicateServers();
|
||||||
this.serverOrder = serverOrder;
|
this.serverOrder = serverOrder;
|
||||||
if (Config.lastActiveServer && this.serverOrder[Config.lastActiveServer]) {
|
|
||||||
this.currentServerId = this.serverOrder[Config.lastActiveServer];
|
|
||||||
} else {
|
|
||||||
this.currentServerId = this.serverOrder[0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private filterOutDuplicateServers = () => {
|
private filterOutDuplicateServers = () => {
|
||||||
|
@@ -97,6 +97,9 @@ jest.mock('../../../electron-builder.json', () => ([
|
|||||||
},
|
},
|
||||||
]));
|
]));
|
||||||
|
|
||||||
|
jest.mock('app/serverViewState', () => ({
|
||||||
|
init: jest.fn(),
|
||||||
|
}));
|
||||||
jest.mock('common/config', () => ({
|
jest.mock('common/config', () => ({
|
||||||
once: jest.fn(),
|
once: jest.fn(),
|
||||||
on: jest.fn(),
|
on: jest.fn(),
|
||||||
@@ -120,7 +123,6 @@ jest.mock('main/app/config', () => ({
|
|||||||
jest.mock('main/app/intercom', () => ({
|
jest.mock('main/app/intercom', () => ({
|
||||||
handleMainWindowIsShown: jest.fn(),
|
handleMainWindowIsShown: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('main/app/servers', () => ({}));
|
|
||||||
jest.mock('main/app/utils', () => ({
|
jest.mock('main/app/utils', () => ({
|
||||||
clearAppCache: jest.fn(),
|
clearAppCache: jest.fn(),
|
||||||
getDeeplinkingURL: jest.fn(),
|
getDeeplinkingURL: jest.fn(),
|
||||||
|
@@ -8,16 +8,9 @@ import installExtension, {REACT_DEVELOPER_TOOLS} from 'electron-devtools-install
|
|||||||
import isDev from 'electron-is-dev';
|
import isDev from 'electron-is-dev';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SWITCH_SERVER,
|
|
||||||
FOCUS_BROWSERVIEW,
|
FOCUS_BROWSERVIEW,
|
||||||
QUIT,
|
QUIT,
|
||||||
SHOW_NEW_SERVER_MODAL,
|
|
||||||
NOTIFY_MENTION,
|
NOTIFY_MENTION,
|
||||||
SWITCH_TAB,
|
|
||||||
CLOSE_VIEW,
|
|
||||||
OPEN_VIEW,
|
|
||||||
SHOW_EDIT_SERVER_MODAL,
|
|
||||||
SHOW_REMOVE_SERVER_MODAL,
|
|
||||||
UPDATE_SHORTCUT_MENU,
|
UPDATE_SHORTCUT_MENU,
|
||||||
GET_AVAILABLE_SPELL_CHECKER_LANGUAGES,
|
GET_AVAILABLE_SPELL_CHECKER_LANGUAGES,
|
||||||
USER_ACTIVITY_UPDATE,
|
USER_ACTIVITY_UPDATE,
|
||||||
@@ -29,11 +22,6 @@ import {
|
|||||||
GET_LOCAL_CONFIGURATION,
|
GET_LOCAL_CONFIGURATION,
|
||||||
UPDATE_CONFIGURATION,
|
UPDATE_CONFIGURATION,
|
||||||
UPDATE_PATHS,
|
UPDATE_PATHS,
|
||||||
UPDATE_SERVER_ORDER,
|
|
||||||
UPDATE_TAB_ORDER,
|
|
||||||
GET_LAST_ACTIVE,
|
|
||||||
GET_ORDERED_SERVERS,
|
|
||||||
GET_ORDERED_TABS_FOR_SERVER,
|
|
||||||
SERVERS_URL_MODIFIED,
|
SERVERS_URL_MODIFIED,
|
||||||
GET_DARK_MODE,
|
GET_DARK_MODE,
|
||||||
WINDOW_CLOSE,
|
WINDOW_CLOSE,
|
||||||
@@ -41,7 +29,6 @@ import {
|
|||||||
WINDOW_MINIMIZE,
|
WINDOW_MINIMIZE,
|
||||||
WINDOW_RESTORE,
|
WINDOW_RESTORE,
|
||||||
DOUBLE_CLICK_ON_WINDOW,
|
DOUBLE_CLICK_ON_WINDOW,
|
||||||
VALIDATE_SERVER_URL,
|
|
||||||
} from 'common/communication';
|
} from 'common/communication';
|
||||||
import Config from 'common/config';
|
import Config from 'common/config';
|
||||||
import {isTrustedURL, parseURL} from 'common/utils/url';
|
import {isTrustedURL, parseURL} from 'common/utils/url';
|
||||||
@@ -94,16 +81,6 @@ import {
|
|||||||
handleQuit,
|
handleQuit,
|
||||||
handlePingDomain,
|
handlePingDomain,
|
||||||
} from './intercom';
|
} from './intercom';
|
||||||
import {
|
|
||||||
handleEditServerModal,
|
|
||||||
handleNewServerModal,
|
|
||||||
handleRemoveServerModal,
|
|
||||||
handleServerURLValidation,
|
|
||||||
switchServer,
|
|
||||||
} from './servers';
|
|
||||||
import {
|
|
||||||
handleCloseView, handleGetLastActive, handleGetOrderedViewsForServer, handleOpenView,
|
|
||||||
} from './views';
|
|
||||||
import {
|
import {
|
||||||
clearAppCache,
|
clearAppCache,
|
||||||
getDeeplinkingURL,
|
getDeeplinkingURL,
|
||||||
@@ -279,17 +256,8 @@ function initializeInterCommunicationEventListeners() {
|
|||||||
ipcMain.on(OPEN_APP_MENU, handleOpenAppMenu);
|
ipcMain.on(OPEN_APP_MENU, handleOpenAppMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
ipcMain.on(SWITCH_SERVER, (event, serverId) => switchServer(serverId));
|
|
||||||
ipcMain.on(SWITCH_TAB, (event, viewId) => ViewManager.showById(viewId));
|
|
||||||
ipcMain.on(CLOSE_VIEW, handleCloseView);
|
|
||||||
ipcMain.on(OPEN_VIEW, handleOpenView);
|
|
||||||
|
|
||||||
ipcMain.on(QUIT, handleQuit);
|
ipcMain.on(QUIT, handleQuit);
|
||||||
|
|
||||||
ipcMain.on(SHOW_NEW_SERVER_MODAL, handleNewServerModal);
|
|
||||||
ipcMain.on(SHOW_EDIT_SERVER_MODAL, handleEditServerModal);
|
|
||||||
ipcMain.on(SHOW_REMOVE_SERVER_MODAL, handleRemoveServerModal);
|
|
||||||
ipcMain.handle(VALIDATE_SERVER_URL, handleServerURLValidation);
|
|
||||||
ipcMain.handle(GET_AVAILABLE_SPELL_CHECKER_LANGUAGES, () => session.defaultSession.availableSpellCheckerLanguages);
|
ipcMain.handle(GET_AVAILABLE_SPELL_CHECKER_LANGUAGES, () => session.defaultSession.availableSpellCheckerLanguages);
|
||||||
ipcMain.on(START_UPDATE_DOWNLOAD, handleStartDownload);
|
ipcMain.on(START_UPDATE_DOWNLOAD, handleStartDownload);
|
||||||
ipcMain.on(START_UPGRADE, handleStartUpgrade);
|
ipcMain.on(START_UPGRADE, handleStartUpgrade);
|
||||||
@@ -298,12 +266,6 @@ function initializeInterCommunicationEventListeners() {
|
|||||||
ipcMain.handle(GET_LOCAL_CONFIGURATION, handleGetLocalConfiguration);
|
ipcMain.handle(GET_LOCAL_CONFIGURATION, handleGetLocalConfiguration);
|
||||||
ipcMain.on(UPDATE_CONFIGURATION, updateConfiguration);
|
ipcMain.on(UPDATE_CONFIGURATION, updateConfiguration);
|
||||||
|
|
||||||
ipcMain.on(UPDATE_SERVER_ORDER, (event, serverOrder) => ServerManager.updateServerOrder(serverOrder));
|
|
||||||
ipcMain.on(UPDATE_TAB_ORDER, (event, serverId, viewOrder) => ServerManager.updateTabOrder(serverId, viewOrder));
|
|
||||||
ipcMain.handle(GET_LAST_ACTIVE, handleGetLastActive);
|
|
||||||
ipcMain.handle(GET_ORDERED_SERVERS, () => ServerManager.getOrderedServers().map((srv) => srv.toUniqueServer()));
|
|
||||||
ipcMain.handle(GET_ORDERED_TABS_FOR_SERVER, handleGetOrderedViewsForServer);
|
|
||||||
|
|
||||||
ipcMain.handle(GET_DARK_MODE, handleGetDarkMode);
|
ipcMain.handle(GET_DARK_MODE, handleGetDarkMode);
|
||||||
ipcMain.on(WINDOW_CLOSE, handleClose);
|
ipcMain.on(WINDOW_CLOSE, handleClose);
|
||||||
ipcMain.on(WINDOW_MAXIMIZE, handleMaximize);
|
ipcMain.on(WINDOW_MAXIMIZE, handleMaximize);
|
||||||
|
@@ -11,6 +11,7 @@ import {
|
|||||||
handleMainWindowIsShown,
|
handleMainWindowIsShown,
|
||||||
} from './intercom';
|
} from './intercom';
|
||||||
|
|
||||||
|
jest.mock('app/serverViewState', () => ({}));
|
||||||
jest.mock('common/config', () => ({
|
jest.mock('common/config', () => ({
|
||||||
setServers: jest.fn(),
|
setServers: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
@@ -6,6 +6,8 @@ import {app, IpcMainEvent, IpcMainInvokeEvent, Menu} from 'electron';
|
|||||||
import {UniqueServer} from 'types/config';
|
import {UniqueServer} from 'types/config';
|
||||||
import {MentionData} from 'types/notification';
|
import {MentionData} from 'types/notification';
|
||||||
|
|
||||||
|
import ServerViewState from 'app/serverViewState';
|
||||||
|
|
||||||
import {Logger} from 'common/log';
|
import {Logger} from 'common/log';
|
||||||
import ServerManager from 'common/servers/serverManager';
|
import ServerManager from 'common/servers/serverManager';
|
||||||
import {ping} from 'common/utils/requests';
|
import {ping} from 'common/utils/requests';
|
||||||
@@ -16,7 +18,6 @@ import ModalManager from 'main/views/modalManager';
|
|||||||
import MainWindow from 'main/windows/mainWindow';
|
import MainWindow from 'main/windows/mainWindow';
|
||||||
|
|
||||||
import {handleAppBeforeQuit} from './app';
|
import {handleAppBeforeQuit} from './app';
|
||||||
import {handleNewServerModal, switchServer} from './servers';
|
|
||||||
|
|
||||||
const log = new Logger('App.Intercom');
|
const log = new Logger('App.Intercom');
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ function handleShowOnboardingScreens(showWelcomeScreen: boolean, showNewServerMo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (showNewServerModal) {
|
if (showNewServerModal) {
|
||||||
handleNewServerModal();
|
ServerViewState.showNewServerModal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +102,7 @@ export function handleWelcomeScreenModal() {
|
|||||||
if (modalPromise) {
|
if (modalPromise) {
|
||||||
modalPromise.then((data) => {
|
modalPromise.then((data) => {
|
||||||
const newServer = ServerManager.addServer(data);
|
const newServer = ServerManager.addServer(data);
|
||||||
switchServer(newServer.id, true);
|
ServerViewState.switchServer(newServer.id, true);
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
// e is undefined for user cancellation
|
// e is undefined for user cancellation
|
||||||
if (e) {
|
if (e) {
|
||||||
|
@@ -1,229 +0,0 @@
|
|||||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See LICENSE.txt for license information.
|
|
||||||
|
|
||||||
import {IpcMainEvent, IpcMainInvokeEvent, ipcMain} from 'electron';
|
|
||||||
|
|
||||||
import {UniqueServer, Server} from 'types/config';
|
|
||||||
import {URLValidationResult} from 'types/server';
|
|
||||||
|
|
||||||
import {UPDATE_SHORTCUT_MENU} from 'common/communication';
|
|
||||||
import {Logger} from 'common/log';
|
|
||||||
import ServerManager from 'common/servers/serverManager';
|
|
||||||
import {MattermostServer} from 'common/servers/MattermostServer';
|
|
||||||
import {isValidURI, isValidURL, parseURL} from 'common/utils/url';
|
|
||||||
import {URLValidationStatus} from 'common/utils/constants';
|
|
||||||
|
|
||||||
import ViewManager from 'main/views/viewManager';
|
|
||||||
import ModalManager from 'main/views/modalManager';
|
|
||||||
import MainWindow from 'main/windows/mainWindow';
|
|
||||||
import {getLocalPreload, getLocalURLString} from 'main/utils';
|
|
||||||
import {ServerInfo} from 'main/server/serverInfo';
|
|
||||||
|
|
||||||
const log = new Logger('App.Servers');
|
|
||||||
|
|
||||||
export const switchServer = (serverId: string, waitForViewToExist = false) => {
|
|
||||||
ServerManager.getServerLog(serverId, 'WindowManager').debug('switchServer');
|
|
||||||
MainWindow.show();
|
|
||||||
const server = ServerManager.getServer(serverId);
|
|
||||||
if (!server) {
|
|
||||||
ServerManager.getServerLog(serverId, 'WindowManager').error('Cannot find server in config');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const nextView = ServerManager.getLastActiveTabForServer(serverId);
|
|
||||||
if (waitForViewToExist) {
|
|
||||||
const timeout = setInterval(() => {
|
|
||||||
if (ViewManager.getView(nextView.id)) {
|
|
||||||
ViewManager.showById(nextView.id);
|
|
||||||
clearInterval(timeout);
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
} else {
|
|
||||||
ViewManager.showById(nextView.id);
|
|
||||||
}
|
|
||||||
ipcMain.emit(UPDATE_SHORTCUT_MENU);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const handleNewServerModal = () => {
|
|
||||||
log.debug('handleNewServerModal');
|
|
||||||
|
|
||||||
const html = getLocalURLString('newServer.html');
|
|
||||||
|
|
||||||
const preload = getLocalPreload('desktopAPI.js');
|
|
||||||
|
|
||||||
const mainWindow = MainWindow.get();
|
|
||||||
if (!mainWindow) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const modalPromise = ModalManager.addModal<null, Server>('newServer', html, preload, null, mainWindow, !ServerManager.hasServers());
|
|
||||||
if (modalPromise) {
|
|
||||||
modalPromise.then((data) => {
|
|
||||||
const newServer = ServerManager.addServer(data);
|
|
||||||
switchServer(newServer.id, true);
|
|
||||||
}).catch((e) => {
|
|
||||||
// e is undefined for user cancellation
|
|
||||||
if (e) {
|
|
||||||
log.error(`there was an error in the new server modal: ${e}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
log.warn('There is already a new server modal');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const handleEditServerModal = (e: IpcMainEvent, id: string) => {
|
|
||||||
log.debug('handleEditServerModal', id);
|
|
||||||
|
|
||||||
const html = getLocalURLString('editServer.html');
|
|
||||||
|
|
||||||
const preload = getLocalPreload('desktopAPI.js');
|
|
||||||
|
|
||||||
const mainWindow = MainWindow.get();
|
|
||||||
if (!mainWindow) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const server = ServerManager.getServer(id);
|
|
||||||
if (!server) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const modalPromise = ModalManager.addModal<UniqueServer, Server>(
|
|
||||||
'editServer',
|
|
||||||
html,
|
|
||||||
preload,
|
|
||||||
server.toUniqueServer(),
|
|
||||||
mainWindow);
|
|
||||||
if (modalPromise) {
|
|
||||||
modalPromise.then((data) => ServerManager.editServer(id, data)).catch((e) => {
|
|
||||||
// e is undefined for user cancellation
|
|
||||||
if (e) {
|
|
||||||
log.error(`there was an error in the edit server modal: ${e}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
log.warn('There is already an edit server modal');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const handleRemoveServerModal = (e: IpcMainEvent, id: string) => {
|
|
||||||
log.debug('handleRemoveServerModal', id);
|
|
||||||
|
|
||||||
const html = getLocalURLString('removeServer.html');
|
|
||||||
|
|
||||||
const preload = getLocalPreload('desktopAPI.js');
|
|
||||||
|
|
||||||
const server = ServerManager.getServer(id);
|
|
||||||
if (!server) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const mainWindow = MainWindow.get();
|
|
||||||
if (!mainWindow) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const modalPromise = ModalManager.addModal<string, boolean>('removeServer', html, preload, server.name, mainWindow);
|
|
||||||
if (modalPromise) {
|
|
||||||
modalPromise.then((remove) => {
|
|
||||||
if (remove) {
|
|
||||||
ServerManager.removeServer(server.id);
|
|
||||||
}
|
|
||||||
}).catch((e) => {
|
|
||||||
// e is undefined for user cancellation
|
|
||||||
if (e) {
|
|
||||||
log.error(`there was an error in the edit server modal: ${e}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
log.warn('There is already an edit server modal');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const handleServerURLValidation = async (e: IpcMainInvokeEvent, url?: string, currentId?: string): Promise<URLValidationResult> => {
|
|
||||||
log.debug('handleServerURLValidation', url, currentId);
|
|
||||||
|
|
||||||
// If the URL is missing or null, reject
|
|
||||||
if (!url) {
|
|
||||||
return {status: URLValidationStatus.Missing};
|
|
||||||
}
|
|
||||||
|
|
||||||
let httpUrl = url;
|
|
||||||
if (!isValidURL(url)) {
|
|
||||||
// If it already includes the protocol, tell them it's invalid
|
|
||||||
if (isValidURI(url)) {
|
|
||||||
httpUrl = url.replace(/^(.+):/, 'https:');
|
|
||||||
} else {
|
|
||||||
// Otherwise add HTTPS for them
|
|
||||||
httpUrl = `https://${url}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the final URL is valid
|
|
||||||
const parsedURL = parseURL(httpUrl);
|
|
||||||
if (!parsedURL) {
|
|
||||||
return {status: URLValidationStatus.Invalid};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try and add HTTPS to see if we can get a more secure URL
|
|
||||||
let secureURL = parsedURL;
|
|
||||||
if (parsedURL.protocol === 'http:') {
|
|
||||||
secureURL = parseURL(parsedURL.toString().replace(/^http:/, 'https:')) ?? parsedURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell the user if they already have a server for this URL
|
|
||||||
const existingServer = ServerManager.lookupViewByURL(secureURL, true);
|
|
||||||
if (existingServer && existingServer.server.id !== currentId) {
|
|
||||||
return {status: URLValidationStatus.URLExists, existingServerName: existingServer.server.name, validatedURL: existingServer.server.url.toString()};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try and get remote info from the most secure URL, otherwise use the insecure one
|
|
||||||
let remoteURL = secureURL;
|
|
||||||
let remoteInfo = await testRemoteServer(secureURL);
|
|
||||||
if (!remoteInfo) {
|
|
||||||
if (secureURL.toString() !== parsedURL.toString()) {
|
|
||||||
remoteURL = parsedURL;
|
|
||||||
remoteInfo = await testRemoteServer(parsedURL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we can't get the remote info, warn the user that this might not be the right URL
|
|
||||||
// If the original URL was invalid, don't replace that as they probably have a typo somewhere
|
|
||||||
if (!remoteInfo) {
|
|
||||||
return {status: URLValidationStatus.NotMattermost, validatedURL: parsedURL.toString()};
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we were only able to connect via HTTP, warn the user that the connection is not secure
|
|
||||||
if (remoteURL.protocol === 'http:') {
|
|
||||||
return {status: URLValidationStatus.Insecure, serverVersion: remoteInfo.serverVersion, validatedURL: remoteURL.toString()};
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the URL doesn't match the Site URL, set the URL to the correct one
|
|
||||||
if (remoteInfo.siteURL && remoteURL.toString() !== new URL(remoteInfo.siteURL).toString()) {
|
|
||||||
const parsedSiteURL = parseURL(remoteInfo.siteURL);
|
|
||||||
if (parsedSiteURL) {
|
|
||||||
// Check the Site URL as well to see if it's already pre-configured
|
|
||||||
const existingServer = ServerManager.lookupViewByURL(parsedSiteURL, true);
|
|
||||||
if (existingServer && existingServer.server.id !== currentId) {
|
|
||||||
return {status: URLValidationStatus.URLExists, existingServerName: existingServer.server.name, validatedURL: existingServer.server.url.toString()};
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we can't reach the remote Site URL, there's probably a configuration issue
|
|
||||||
const remoteSiteURLInfo = await testRemoteServer(parsedSiteURL);
|
|
||||||
if (!remoteSiteURLInfo) {
|
|
||||||
return {status: URLValidationStatus.URLNotMatched, serverVersion: remoteInfo.serverVersion, serverName: remoteInfo.siteName, validatedURL: remoteURL.toString()};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise fix it for them and return
|
|
||||||
return {status: URLValidationStatus.URLUpdated, serverVersion: remoteInfo.serverVersion, serverName: remoteInfo.siteName, validatedURL: remoteInfo.siteURL};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {status: URLValidationStatus.OK, serverVersion: remoteInfo.serverVersion, serverName: remoteInfo.siteName, validatedURL: remoteInfo.siteURL};
|
|
||||||
};
|
|
||||||
|
|
||||||
const testRemoteServer = async (parsedURL: URL) => {
|
|
||||||
const server = new MattermostServer({name: 'temp', url: parsedURL.toString()}, false);
|
|
||||||
const serverInfo = new ServerInfo(server);
|
|
||||||
try {
|
|
||||||
const remoteInfo = await serverInfo.fetchRemoteInfo();
|
|
||||||
return remoteInfo;
|
|
||||||
} catch (error) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
@@ -1,39 +0,0 @@
|
|||||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See LICENSE.txt for license information.
|
|
||||||
|
|
||||||
import ServerManager from 'common/servers/serverManager';
|
|
||||||
import ViewManager from 'main/views/viewManager';
|
|
||||||
|
|
||||||
import {
|
|
||||||
handleCloseView,
|
|
||||||
handleOpenView,
|
|
||||||
} from './views';
|
|
||||||
|
|
||||||
jest.mock('common/servers/serverManager', () => ({
|
|
||||||
setViewIsOpen: jest.fn(),
|
|
||||||
getView: jest.fn(),
|
|
||||||
getLastActiveTabForServer: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
jest.mock('main/views/viewManager', () => ({
|
|
||||||
showById: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('main/app/views', () => {
|
|
||||||
describe('handleCloseView', () => {
|
|
||||||
it('should close the specified view and switch to the next open view', () => {
|
|
||||||
ServerManager.getView.mockReturnValue({server: {id: 'server-1'}});
|
|
||||||
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'view-2'});
|
|
||||||
handleCloseView(null, 'view-3');
|
|
||||||
expect(ServerManager.setViewIsOpen).toBeCalledWith('view-3', false);
|
|
||||||
expect(ViewManager.showById).toBeCalledWith('view-2');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('handleOpenView', () => {
|
|
||||||
it('should open the specified view', () => {
|
|
||||||
handleOpenView(null, 'view-1');
|
|
||||||
expect(ViewManager.showById).toBeCalledWith('view-1');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,73 +0,0 @@
|
|||||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See LICENSE.txt for license information.
|
|
||||||
|
|
||||||
import {IpcMainEvent, IpcMainInvokeEvent} from 'electron';
|
|
||||||
|
|
||||||
import ServerManager from 'common/servers/serverManager';
|
|
||||||
import {Logger} from 'common/log';
|
|
||||||
|
|
||||||
import ViewManager from 'main/views/viewManager';
|
|
||||||
|
|
||||||
const log = new Logger('App.Views');
|
|
||||||
|
|
||||||
export const handleCloseView = (event: IpcMainEvent, viewId: string) => {
|
|
||||||
log.debug('handleCloseView', {viewId});
|
|
||||||
|
|
||||||
const view = ServerManager.getView(viewId);
|
|
||||||
if (!view) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ServerManager.setViewIsOpen(viewId, false);
|
|
||||||
const nextView = ServerManager.getLastActiveTabForServer(view.server.id);
|
|
||||||
ViewManager.showById(nextView.id);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const handleOpenView = (event: IpcMainEvent, viewId: string) => {
|
|
||||||
log.debug('handleOpenView', {viewId});
|
|
||||||
|
|
||||||
ServerManager.setViewIsOpen(viewId, true);
|
|
||||||
ViewManager.showById(viewId);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const selectNextView = () => {
|
|
||||||
selectView((order) => order + 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const selectPreviousView = () => {
|
|
||||||
selectView((order, length) => (length + (order - 1)));
|
|
||||||
};
|
|
||||||
|
|
||||||
export const handleGetOrderedViewsForServer = (event: IpcMainInvokeEvent, serverId: string) => {
|
|
||||||
return ServerManager.getOrderedTabsForServer(serverId).map((view) => view.toUniqueView());
|
|
||||||
};
|
|
||||||
|
|
||||||
export const handleGetLastActive = () => {
|
|
||||||
const server = ServerManager.getCurrentServer();
|
|
||||||
const view = ServerManager.getLastActiveTabForServer(server.id);
|
|
||||||
return {server: server.id, view: view.id};
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectView = (fn: (order: number, length: number) => number) => {
|
|
||||||
const currentView = ViewManager.getCurrentView();
|
|
||||||
if (!currentView) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentServerViews = ServerManager.getOrderedTabsForServer(currentView.view.server.id).map((view, index) => ({view, index}));
|
|
||||||
const filteredViews = currentServerViews?.filter((view) => view.view.isOpen);
|
|
||||||
const currentServerView = currentServerViews?.find((view) => view.view.type === currentView.view.type);
|
|
||||||
if (!currentServerViews || !currentServerView || !filteredViews) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentOrder = currentServerView.index;
|
|
||||||
let nextIndex = -1;
|
|
||||||
while (nextIndex === -1) {
|
|
||||||
const nextOrder = (fn(currentOrder, currentServerViews.length) % currentServerViews.length);
|
|
||||||
nextIndex = filteredViews.findIndex((view) => view.index === nextOrder);
|
|
||||||
currentOrder = nextOrder;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newView = filteredViews[nextIndex].view;
|
|
||||||
ViewManager.showById(newView.id);
|
|
||||||
};
|
|
@@ -8,6 +8,8 @@ import {getDoNotDisturb as getDarwinDoNotDisturb} from 'macos-notification-state
|
|||||||
import {localizeMessage} from 'main/i18nManager';
|
import {localizeMessage} from 'main/i18nManager';
|
||||||
import ServerManager from 'common/servers/serverManager';
|
import ServerManager from 'common/servers/serverManager';
|
||||||
|
|
||||||
|
import ServerViewState from 'app/serverViewState';
|
||||||
|
|
||||||
import {createTemplate} from './app';
|
import {createTemplate} from './app';
|
||||||
|
|
||||||
jest.mock('electron', () => {
|
jest.mock('electron', () => {
|
||||||
@@ -51,12 +53,12 @@ jest.mock('main/i18nManager', () => ({
|
|||||||
}));
|
}));
|
||||||
jest.mock('common/servers/serverManager', () => ({
|
jest.mock('common/servers/serverManager', () => ({
|
||||||
hasServers: jest.fn(),
|
hasServers: jest.fn(),
|
||||||
getCurrentServer: jest.fn(),
|
|
||||||
getOrderedServers: jest.fn(),
|
getOrderedServers: jest.fn(),
|
||||||
getOrderedTabsForServer: jest.fn(),
|
getOrderedTabsForServer: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('main/app/servers', () => ({
|
jest.mock('app/serverViewState', () => ({
|
||||||
switchServer: jest.fn(),
|
switchServer: jest.fn(),
|
||||||
|
getCurrentServer: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('main/diagnostics', () => ({}));
|
jest.mock('main/diagnostics', () => ({}));
|
||||||
jest.mock('main/downloadsManager', () => ({
|
jest.mock('main/downloadsManager', () => ({
|
||||||
@@ -107,7 +109,7 @@ describe('main/menus/app', () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ServerManager.getCurrentServer.mockReturnValue(servers[0]);
|
ServerViewState.getCurrentServer.mockReturnValue(servers[0]);
|
||||||
ServerManager.getOrderedServers.mockReturnValue(servers);
|
ServerManager.getOrderedServers.mockReturnValue(servers);
|
||||||
ServerManager.getOrderedTabsForServer.mockReturnValue(views);
|
ServerManager.getOrderedTabsForServer.mockReturnValue(views);
|
||||||
getDarwinDoNotDisturb.mockReturnValue(false);
|
getDarwinDoNotDisturb.mockReturnValue(false);
|
||||||
@@ -278,7 +280,7 @@ describe('main/menus/app', () => {
|
|||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
});
|
});
|
||||||
ServerManager.getCurrentServer.mockImplementation(() => ({id: servers[0].id}));
|
ServerViewState.getCurrentServer.mockImplementation(() => ({id: servers[0].id}));
|
||||||
|
|
||||||
const modifiedViews = [...Array(15).keys()].map((key) => ({
|
const modifiedViews = [...Array(15).keys()].map((key) => ({
|
||||||
id: `view-${key}`,
|
id: `view-${key}`,
|
||||||
|
@@ -6,6 +6,8 @@
|
|||||||
import {app, ipcMain, Menu, MenuItemConstructorOptions, MenuItem, session, shell, WebContents, clipboard} from 'electron';
|
import {app, ipcMain, Menu, MenuItemConstructorOptions, MenuItem, session, shell, WebContents, clipboard} from 'electron';
|
||||||
import log from 'electron-log';
|
import log from 'electron-log';
|
||||||
|
|
||||||
|
import ServerViewState from 'app/serverViewState';
|
||||||
|
|
||||||
import {OPEN_SERVERS_DROPDOWN, SHOW_NEW_SERVER_MODAL} from 'common/communication';
|
import {OPEN_SERVERS_DROPDOWN, SHOW_NEW_SERVER_MODAL} from 'common/communication';
|
||||||
import {t} from 'common/utils/util';
|
import {t} from 'common/utils/util';
|
||||||
import {getViewDisplayName, ViewType} from 'common/views/View';
|
import {getViewDisplayName, ViewType} from 'common/views/View';
|
||||||
@@ -18,8 +20,6 @@ import downloadsManager from 'main/downloadsManager';
|
|||||||
import Diagnostics from 'main/diagnostics';
|
import Diagnostics from 'main/diagnostics';
|
||||||
import ViewManager from 'main/views/viewManager';
|
import ViewManager from 'main/views/viewManager';
|
||||||
import SettingsWindow from 'main/windows/settingsWindow';
|
import SettingsWindow from 'main/windows/settingsWindow';
|
||||||
import {selectNextView, selectPreviousView} from 'main/app/views';
|
|
||||||
import {switchServer} from 'main/app/servers';
|
|
||||||
|
|
||||||
export function createTemplate(config: Config, updateManager: UpdateManager) {
|
export function createTemplate(config: Config, updateManager: UpdateManager) {
|
||||||
const separatorItem: MenuItemConstructorOptions = {
|
const separatorItem: MenuItemConstructorOptions = {
|
||||||
@@ -266,10 +266,10 @@ export function createTemplate(config: Config, updateManager: UpdateManager) {
|
|||||||
label: server.name,
|
label: server.name,
|
||||||
accelerator: `${process.platform === 'darwin' ? 'Cmd+Ctrl' : 'Ctrl+Shift'}+${i + 1}`,
|
accelerator: `${process.platform === 'darwin' ? 'Cmd+Ctrl' : 'Ctrl+Shift'}+${i + 1}`,
|
||||||
click() {
|
click() {
|
||||||
switchServer(server.id);
|
ServerViewState.switchServer(server.id);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (ServerManager.getCurrentServer().id === server.id) {
|
if (ServerViewState.getCurrentServer().id === server.id) {
|
||||||
ServerManager.getOrderedTabsForServer(server.id).slice(0, 9).forEach((view, i) => {
|
ServerManager.getOrderedTabsForServer(server.id).slice(0, 9).forEach((view, i) => {
|
||||||
items.push({
|
items.push({
|
||||||
label: ` ${localizeMessage(`common.views.${view.type}`, getViewDisplayName(view.type as ViewType))}`,
|
label: ` ${localizeMessage(`common.views.${view.type}`, getViewDisplayName(view.type as ViewType))}`,
|
||||||
@@ -285,14 +285,14 @@ export function createTemplate(config: Config, updateManager: UpdateManager) {
|
|||||||
label: localizeMessage('main.menus.app.window.selectNextTab', 'Select Next Tab'),
|
label: localizeMessage('main.menus.app.window.selectNextTab', 'Select Next Tab'),
|
||||||
accelerator: 'Ctrl+Tab',
|
accelerator: 'Ctrl+Tab',
|
||||||
click() {
|
click() {
|
||||||
selectNextView();
|
ServerViewState.selectNextView();
|
||||||
},
|
},
|
||||||
enabled: (servers.length > 1),
|
enabled: (servers.length > 1),
|
||||||
}, {
|
}, {
|
||||||
label: localizeMessage('main.menus.app.window.selectPreviousTab', 'Select Previous Tab'),
|
label: localizeMessage('main.menus.app.window.selectPreviousTab', 'Select Previous Tab'),
|
||||||
accelerator: 'Ctrl+Shift+Tab',
|
accelerator: 'Ctrl+Shift+Tab',
|
||||||
click() {
|
click() {
|
||||||
selectPreviousView();
|
ServerViewState.selectPreviousView();
|
||||||
},
|
},
|
||||||
enabled: (servers.length > 1),
|
enabled: (servers.length > 1),
|
||||||
}, ...(isMac ? [separatorItem, {
|
}, ...(isMac ? [separatorItem, {
|
||||||
|
@@ -14,7 +14,7 @@ jest.mock('main/i18nManager', () => ({
|
|||||||
jest.mock('common/servers/serverManager', () => ({
|
jest.mock('common/servers/serverManager', () => ({
|
||||||
getOrderedServers: jest.fn(),
|
getOrderedServers: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('main/app/servers', () => ({
|
jest.mock('app/serverViewState', () => ({
|
||||||
switchServer: jest.fn(),
|
switchServer: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('main/windows/settingsWindow', () => ({}));
|
jest.mock('main/windows/settingsWindow', () => ({}));
|
||||||
|
@@ -5,11 +5,12 @@
|
|||||||
|
|
||||||
import {Menu, MenuItem, MenuItemConstructorOptions} from 'electron';
|
import {Menu, MenuItem, MenuItemConstructorOptions} from 'electron';
|
||||||
|
|
||||||
|
import ServerViewState from 'app/serverViewState';
|
||||||
|
|
||||||
import ServerManager from 'common/servers/serverManager';
|
import ServerManager from 'common/servers/serverManager';
|
||||||
|
|
||||||
import {localizeMessage} from 'main/i18nManager';
|
import {localizeMessage} from 'main/i18nManager';
|
||||||
import SettingsWindow from 'main/windows/settingsWindow';
|
import SettingsWindow from 'main/windows/settingsWindow';
|
||||||
import {switchServer} from 'main/app/servers';
|
|
||||||
|
|
||||||
export function createTemplate() {
|
export function createTemplate() {
|
||||||
const servers = ServerManager.getOrderedServers();
|
const servers = ServerManager.getOrderedServers();
|
||||||
@@ -18,7 +19,7 @@ export function createTemplate() {
|
|||||||
return {
|
return {
|
||||||
label: server.name.length > 50 ? `${server.name.slice(0, 50)}...` : server.name,
|
label: server.name.length > 50 ? `${server.name.slice(0, 50)}...` : server.name,
|
||||||
click: () => {
|
click: () => {
|
||||||
switchServer(server.id);
|
ServerViewState.switchServer(server.id);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}), {
|
}), {
|
||||||
|
@@ -9,6 +9,8 @@ import MainWindow from 'main/windows/mainWindow';
|
|||||||
|
|
||||||
import {ServerDropdownView} from './serverDropdownView';
|
import {ServerDropdownView} from './serverDropdownView';
|
||||||
|
|
||||||
|
jest.mock('app/serverViewState', () => ({}));
|
||||||
|
|
||||||
jest.mock('main/utils', () => ({
|
jest.mock('main/utils', () => ({
|
||||||
getLocalPreload: (file) => file,
|
getLocalPreload: (file) => file,
|
||||||
getLocalURLString: (file) => file,
|
getLocalURLString: (file) => file,
|
||||||
|
@@ -5,6 +5,8 @@ import {BrowserView, ipcMain, IpcMainEvent} from 'electron';
|
|||||||
|
|
||||||
import {UniqueServer} from 'types/config';
|
import {UniqueServer} from 'types/config';
|
||||||
|
|
||||||
|
import ServerViewState from 'app/serverViewState';
|
||||||
|
|
||||||
import AppState from 'common/appState';
|
import AppState from 'common/appState';
|
||||||
import {
|
import {
|
||||||
CLOSE_SERVERS_DROPDOWN,
|
CLOSE_SERVERS_DROPDOWN,
|
||||||
@@ -98,7 +100,7 @@ export class ServerDropdownView {
|
|||||||
this.servers,
|
this.servers,
|
||||||
Config.darkMode,
|
Config.darkMode,
|
||||||
this.windowBounds,
|
this.windowBounds,
|
||||||
ServerManager.hasServers() ? ServerManager.getCurrentServer().id : undefined,
|
ServerManager.hasServers() ? ServerViewState.getCurrentServer().id : undefined,
|
||||||
Config.enableServerManagement,
|
Config.enableServerManagement,
|
||||||
this.hasGPOServers,
|
this.hasGPOServers,
|
||||||
this.expired,
|
this.expired,
|
||||||
|
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
import {dialog} from 'electron';
|
import {dialog} from 'electron';
|
||||||
|
|
||||||
|
import ServerViewState from 'app/serverViewState';
|
||||||
|
|
||||||
import {BROWSER_HISTORY_PUSH, LOAD_SUCCESS, SET_ACTIVE_VIEW} from 'common/communication';
|
import {BROWSER_HISTORY_PUSH, LOAD_SUCCESS, SET_ACTIVE_VIEW} from 'common/communication';
|
||||||
import {TAB_MESSAGING} from 'common/views/View';
|
import {TAB_MESSAGING} from 'common/views/View';
|
||||||
import ServerManager from 'common/servers/serverManager';
|
import ServerManager from 'common/servers/serverManager';
|
||||||
@@ -30,6 +32,11 @@ jest.mock('electron', () => ({
|
|||||||
handle: jest.fn(),
|
handle: jest.fn(),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
jest.mock('app/serverViewState', () => ({
|
||||||
|
getCurrentServer: jest.fn(),
|
||||||
|
updateCurrentView: jest.fn(),
|
||||||
|
init: jest.fn(),
|
||||||
|
}));
|
||||||
jest.mock('common/views/View', () => ({
|
jest.mock('common/views/View', () => ({
|
||||||
getViewName: jest.fn((a, b) => `${a}-${b}`),
|
getViewName: jest.fn((a, b) => `${a}-${b}`),
|
||||||
TAB_MESSAGING: 'view',
|
TAB_MESSAGING: 'view',
|
||||||
@@ -70,13 +77,11 @@ jest.mock('main/windows/mainWindow', () => ({
|
|||||||
on: jest.fn(),
|
on: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('common/servers/serverManager', () => ({
|
jest.mock('common/servers/serverManager', () => ({
|
||||||
getCurrentServer: jest.fn(),
|
|
||||||
getOrderedTabsForServer: jest.fn(),
|
getOrderedTabsForServer: jest.fn(),
|
||||||
getAllServers: jest.fn(),
|
getAllServers: jest.fn(),
|
||||||
hasServers: jest.fn(),
|
hasServers: jest.fn(),
|
||||||
getLastActiveServer: jest.fn(),
|
getLastActiveServer: jest.fn(),
|
||||||
getLastActiveTabForServer: jest.fn(),
|
getLastActiveTabForServer: jest.fn(),
|
||||||
updateLastActive: jest.fn(),
|
|
||||||
lookupViewByURL: jest.fn(),
|
lookupViewByURL: jest.fn(),
|
||||||
getRemoteInfo: jest.fn(),
|
getRemoteInfo: jest.fn(),
|
||||||
on: jest.fn(),
|
on: jest.fn(),
|
||||||
@@ -351,7 +356,7 @@ describe('main/views/viewManager', () => {
|
|||||||
viewManager.showById = jest.fn();
|
viewManager.showById = jest.fn();
|
||||||
MainWindow.get.mockReturnValue(window);
|
MainWindow.get.mockReturnValue(window);
|
||||||
ServerManager.hasServers.mockReturnValue(true);
|
ServerManager.hasServers.mockReturnValue(true);
|
||||||
ServerManager.getCurrentServer.mockReturnValue({id: 'server-0'});
|
ServerViewState.getCurrentServer.mockReturnValue({id: 'server-0'});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -440,7 +445,7 @@ describe('main/views/viewManager', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ServerManager.getAllServers.mockReturnValue(servers);
|
ServerManager.getAllServers.mockReturnValue(servers);
|
||||||
ServerManager.getCurrentServer.mockReturnValue(servers[0]);
|
ServerViewState.getCurrentServer.mockReturnValue(servers[0]);
|
||||||
urlUtils.cleanPathName.mockImplementation((base, path) => path);
|
urlUtils.cleanPathName.mockImplementation((base, path) => path);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
import {BrowserView, dialog, ipcMain, IpcMainEvent, IpcMainInvokeEvent} from 'electron';
|
import {BrowserView, dialog, ipcMain, IpcMainEvent, IpcMainInvokeEvent} from 'electron';
|
||||||
|
|
||||||
|
import ServerViewState from 'app/serverViewState';
|
||||||
|
|
||||||
import AppState from 'common/appState';
|
import AppState from 'common/appState';
|
||||||
import {SECOND, TAB_BAR_HEIGHT} from 'common/utils/constants';
|
import {SECOND, TAB_BAR_HEIGHT} from 'common/utils/constants';
|
||||||
import {
|
import {
|
||||||
@@ -27,6 +29,7 @@ import {
|
|||||||
MAIN_WINDOW_CREATED,
|
MAIN_WINDOW_CREATED,
|
||||||
MAIN_WINDOW_RESIZED,
|
MAIN_WINDOW_RESIZED,
|
||||||
MAIN_WINDOW_FOCUSED,
|
MAIN_WINDOW_FOCUSED,
|
||||||
|
SWITCH_TAB,
|
||||||
} from 'common/communication';
|
} from 'common/communication';
|
||||||
import Config from 'common/config';
|
import Config from 'common/config';
|
||||||
import {Logger} from 'common/log';
|
import {Logger} from 'common/log';
|
||||||
@@ -74,6 +77,8 @@ export class ViewManager {
|
|||||||
ipcMain.on(UNREAD_RESULT, this.handleFaviconIsUnread);
|
ipcMain.on(UNREAD_RESULT, this.handleFaviconIsUnread);
|
||||||
ipcMain.on(SESSION_EXPIRED, this.handleSessionExpired);
|
ipcMain.on(SESSION_EXPIRED, this.handleSessionExpired);
|
||||||
|
|
||||||
|
ipcMain.on(SWITCH_TAB, (event, viewId) => this.showById(viewId));
|
||||||
|
|
||||||
ServerManager.on(SERVERS_UPDATE, this.handleReloadConfiguration);
|
ServerManager.on(SERVERS_UPDATE, this.handleReloadConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +132,7 @@ export class ViewManager {
|
|||||||
}
|
}
|
||||||
hidePrevious?.();
|
hidePrevious?.();
|
||||||
MainWindow.get()?.webContents.send(SET_ACTIVE_VIEW, newView.view.server.id, newView.view.id);
|
MainWindow.get()?.webContents.send(SET_ACTIVE_VIEW, newView.view.server.id, newView.view.id);
|
||||||
ServerManager.updateLastActive(newView.view.id);
|
ServerViewState.updateCurrentView(newView.view.server.id, newView.view.id);
|
||||||
} else {
|
} else {
|
||||||
this.getViewLogger(viewId).warn(`Couldn't find a view with name: ${viewId}`);
|
this.getViewLogger(viewId).warn(`Couldn't find a view with name: ${viewId}`);
|
||||||
}
|
}
|
||||||
@@ -263,8 +268,10 @@ export class ViewManager {
|
|||||||
private showInitial = () => {
|
private showInitial = () => {
|
||||||
log.verbose('showInitial');
|
log.verbose('showInitial');
|
||||||
|
|
||||||
|
// TODO: This init should be happening elsewhere, future refactor will fix this
|
||||||
|
ServerViewState.init();
|
||||||
if (ServerManager.hasServers()) {
|
if (ServerManager.hasServers()) {
|
||||||
const lastActiveServer = ServerManager.getCurrentServer();
|
const lastActiveServer = ServerViewState.getCurrentServer();
|
||||||
const lastActiveView = ServerManager.getLastActiveTabForServer(lastActiveServer.id);
|
const lastActiveView = ServerManager.getLastActiveTabForServer(lastActiveServer.id);
|
||||||
this.showById(lastActiveView.id);
|
this.showById(lastActiveView.id);
|
||||||
} else {
|
} else {
|
||||||
@@ -485,7 +492,7 @@ export class ViewManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let redirectedView = this.getView(redirectedviewId) || currentView;
|
let redirectedView = this.getView(redirectedviewId) || currentView;
|
||||||
if (redirectedView !== currentView && redirectedView?.view.server.id === ServerManager.getCurrentServer().id && redirectedView?.isLoggedIn) {
|
if (redirectedView !== currentView && redirectedView?.view.server.id === ServerViewState.getCurrentServer().id && redirectedView?.isLoggedIn) {
|
||||||
log.info('redirecting to a new view', redirectedView?.id || viewId);
|
log.info('redirecting to a new view', redirectedView?.id || viewId);
|
||||||
this.showById(redirectedView?.id || viewId);
|
this.showById(redirectedView?.id || viewId);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
import {BrowserWindow, desktopCapturer, systemPreferences} from 'electron';
|
import {BrowserWindow, desktopCapturer, systemPreferences} from 'electron';
|
||||||
|
|
||||||
|
import ServerViewState from 'app/serverViewState';
|
||||||
|
|
||||||
import {CALLS_WIDGET_SHARE_SCREEN, CALLS_JOINED_CALL} from 'common/communication';
|
import {CALLS_WIDGET_SHARE_SCREEN, CALLS_JOINED_CALL} from 'common/communication';
|
||||||
import {
|
import {
|
||||||
MINIMUM_CALLS_WIDGET_WIDTH,
|
MINIMUM_CALLS_WIDGET_WIDTH,
|
||||||
@@ -13,7 +15,6 @@ import {
|
|||||||
} from 'common/utils/constants';
|
} from 'common/utils/constants';
|
||||||
import urlUtils from 'common/utils/url';
|
import urlUtils from 'common/utils/url';
|
||||||
|
|
||||||
import {switchServer} from 'main/app/servers';
|
|
||||||
import MainWindow from 'main/windows/mainWindow';
|
import MainWindow from 'main/windows/mainWindow';
|
||||||
import ViewManager from 'main/views/viewManager';
|
import ViewManager from 'main/views/viewManager';
|
||||||
import {
|
import {
|
||||||
@@ -56,7 +57,7 @@ jest.mock('main/windows/mainWindow', () => ({
|
|||||||
get: jest.fn(),
|
get: jest.fn(),
|
||||||
focus: jest.fn(),
|
focus: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('main/app/servers', () => ({
|
jest.mock('app/serverViewState', () => ({
|
||||||
switchServer: jest.fn(),
|
switchServer: jest.fn(),
|
||||||
}));
|
}));
|
||||||
jest.mock('main/views/viewManager', () => ({
|
jest.mock('main/views/viewManager', () => ({
|
||||||
@@ -810,7 +811,7 @@ describe('main/windows/callsWidgetWindow', () => {
|
|||||||
|
|
||||||
it('should switch server', () => {
|
it('should switch server', () => {
|
||||||
callsWidgetWindow.handleDesktopSourcesModalRequest();
|
callsWidgetWindow.handleDesktopSourcesModalRequest();
|
||||||
expect(switchServer).toHaveBeenCalledWith('server-1');
|
expect(ServerViewState.switchServer).toHaveBeenCalledWith('server-1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -877,7 +878,7 @@ describe('main/windows/callsWidgetWindow', () => {
|
|||||||
|
|
||||||
it('should switch server', () => {
|
it('should switch server', () => {
|
||||||
callsWidgetWindow.handleCallsWidgetChannelLinkClick();
|
callsWidgetWindow.handleCallsWidgetChannelLinkClick();
|
||||||
expect(switchServer).toHaveBeenCalledWith('server-2');
|
expect(ServerViewState.switchServer).toHaveBeenCalledWith('server-2');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -903,7 +904,7 @@ describe('main/windows/callsWidgetWindow', () => {
|
|||||||
|
|
||||||
it('should focus view and propagate error to main view', () => {
|
it('should focus view and propagate error to main view', () => {
|
||||||
callsWidgetWindow.handleCallsError('', {err: 'client-error'});
|
callsWidgetWindow.handleCallsError('', {err: 'client-error'});
|
||||||
expect(switchServer).toHaveBeenCalledWith('server-2');
|
expect(ServerViewState.switchServer).toHaveBeenCalledWith('server-2');
|
||||||
expect(focus).toHaveBeenCalled();
|
expect(focus).toHaveBeenCalled();
|
||||||
expect(callsWidgetWindow.mainView.sendToRenderer).toHaveBeenCalledWith('calls-error', {err: 'client-error'});
|
expect(callsWidgetWindow.mainView.sendToRenderer).toHaveBeenCalledWith('calls-error', {err: 'client-error'});
|
||||||
});
|
});
|
||||||
@@ -931,7 +932,7 @@ describe('main/windows/callsWidgetWindow', () => {
|
|||||||
|
|
||||||
it('should pass through the click link to browser history push', () => {
|
it('should pass through the click link to browser history push', () => {
|
||||||
callsWidgetWindow.handleCallsLinkClick('', {link: '/other/subpath'});
|
callsWidgetWindow.handleCallsLinkClick('', {link: '/other/subpath'});
|
||||||
expect(switchServer).toHaveBeenCalledWith('server-1');
|
expect(ServerViewState.switchServer).toHaveBeenCalledWith('server-1');
|
||||||
expect(view.sendToRenderer).toBeCalledWith('browser-history-push', '/other/subpath');
|
expect(view.sendToRenderer).toBeCalledWith('browser-history-push', '/other/subpath');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -14,14 +14,7 @@ import {
|
|||||||
CallsWidgetWindowConfig,
|
CallsWidgetWindowConfig,
|
||||||
} from 'types/calls';
|
} from 'types/calls';
|
||||||
|
|
||||||
import {MattermostBrowserView} from 'main/views/MattermostBrowserView';
|
import ServerViewState from 'app/serverViewState';
|
||||||
|
|
||||||
import {
|
|
||||||
composeUserAgent,
|
|
||||||
getLocalPreload,
|
|
||||||
openScreensharePermissionsSettingsMacOS,
|
|
||||||
resetScreensharePermissionsMacOS,
|
|
||||||
} from 'main/utils';
|
|
||||||
|
|
||||||
import {Logger} from 'common/log';
|
import {Logger} from 'common/log';
|
||||||
import {CALLS_PLUGIN_ID, MINIMUM_CALLS_WIDGET_HEIGHT, MINIMUM_CALLS_WIDGET_WIDTH} from 'common/utils/constants';
|
import {CALLS_PLUGIN_ID, MINIMUM_CALLS_WIDGET_HEIGHT, MINIMUM_CALLS_WIDGET_WIDTH} from 'common/utils/constants';
|
||||||
@@ -43,7 +36,13 @@ import {
|
|||||||
DISPATCH_GET_DESKTOP_SOURCES,
|
DISPATCH_GET_DESKTOP_SOURCES,
|
||||||
} from 'common/communication';
|
} from 'common/communication';
|
||||||
|
|
||||||
import {switchServer} from 'main/app/servers';
|
import {MattermostBrowserView} from 'main/views/MattermostBrowserView';
|
||||||
|
import {
|
||||||
|
composeUserAgent,
|
||||||
|
getLocalPreload,
|
||||||
|
openScreensharePermissionsSettingsMacOS,
|
||||||
|
resetScreensharePermissionsMacOS,
|
||||||
|
} from 'main/utils';
|
||||||
import webContentsEventManager from 'main/views/webContentEvents';
|
import webContentsEventManager from 'main/views/webContentEvents';
|
||||||
import MainWindow from 'main/windows/mainWindow';
|
import MainWindow from 'main/windows/mainWindow';
|
||||||
import ViewManager from 'main/views/viewManager';
|
import ViewManager from 'main/views/viewManager';
|
||||||
@@ -485,7 +484,7 @@ export class CallsWidgetWindow {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switchServer(this.serverID);
|
ServerViewState.switchServer(this.serverID);
|
||||||
MainWindow.get()?.focus();
|
MainWindow.get()?.focus();
|
||||||
this.mainView?.sendToRenderer(DESKTOP_SOURCES_MODAL_REQUEST);
|
this.mainView?.sendToRenderer(DESKTOP_SOURCES_MODAL_REQUEST);
|
||||||
}
|
}
|
||||||
@@ -503,7 +502,7 @@ export class CallsWidgetWindow {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switchServer(this.serverID);
|
ServerViewState.switchServer(this.serverID);
|
||||||
MainWindow.get()?.focus();
|
MainWindow.get()?.focus();
|
||||||
this.mainView?.sendToRenderer(BROWSER_HISTORY_PUSH, this.options?.channelURL);
|
this.mainView?.sendToRenderer(BROWSER_HISTORY_PUSH, this.options?.channelURL);
|
||||||
}
|
}
|
||||||
@@ -515,7 +514,7 @@ export class CallsWidgetWindow {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switchServer(this.serverID);
|
ServerViewState.switchServer(this.serverID);
|
||||||
MainWindow.get()?.focus();
|
MainWindow.get()?.focus();
|
||||||
this.mainView?.sendToRenderer(CALLS_ERROR, msg);
|
this.mainView?.sendToRenderer(CALLS_ERROR, msg);
|
||||||
}
|
}
|
||||||
@@ -527,7 +526,7 @@ export class CallsWidgetWindow {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switchServer(this.serverID);
|
ServerViewState.switchServer(this.serverID);
|
||||||
MainWindow.get()?.focus();
|
MainWindow.get()?.focus();
|
||||||
this.mainView?.sendToRenderer(BROWSER_HISTORY_PUSH, msg.link);
|
this.mainView?.sendToRenderer(BROWSER_HISTORY_PUSH, msg.link);
|
||||||
}
|
}
|
||||||
|
@@ -43,6 +43,7 @@ module.exports = {
|
|||||||
alias: {
|
alias: {
|
||||||
renderer: path.resolve(__dirname, 'src/renderer'),
|
renderer: path.resolve(__dirname, 'src/renderer'),
|
||||||
main: path.resolve(__dirname, './src/main'),
|
main: path.resolve(__dirname, './src/main'),
|
||||||
|
app: path.resolve(__dirname, './src/app'),
|
||||||
common: path.resolve(__dirname, './src/common'),
|
common: path.resolve(__dirname, './src/common'),
|
||||||
static: path.resolve(__dirname, './src/assets'),
|
static: path.resolve(__dirname, './src/assets'),
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user