[MM-14093] Rename 'team' to 'server' and 'tab' to 'view' in most cases, some additional cleanup (#2711)

* Rename MattermostTeam -> UniqueServer, MattermostTab -> UniqueView

* Rename 'team' to 'server'

* Some further cleanup

* Rename weirdly named function

* Rename 'tab' to 'view' in most instances

* Fix i18n

* PR feedback
This commit is contained in:
Devin Binnie
2023-05-08 09:17:01 -04:00
committed by GitHub
parent 9f75ddcf0f
commit 316beba950
110 changed files with 1698 additions and 1757 deletions

View File

@@ -95,9 +95,9 @@ describe('main/app/app', () => {
const promise = Promise.resolve({});
const certificate = {};
const view = {
tab: {
view: {
server: {
name: 'test-team',
name: 'test-server',
url: new URL(testURL),
},
},
@@ -163,7 +163,7 @@ describe('main/app/app', () => {
expect(CertificateStore.save).toHaveBeenCalled();
});
it('should load URL using MattermostView when trusting certificate', async () => {
it('should load URL using MattermostBrowserView when trusting certificate', async () => {
dialog.showMessageBox.mockResolvedValue({response: 0});
await handleAppCertificateError(event, webContents, testURL, 'error-1', certificate, callback);
expect(callback).toHaveBeenCalledWith(true);

View File

@@ -96,8 +96,8 @@ export async function handleAppCertificateError(event: Event, webContents: WebCo
const errorID = `${parsedURL.origin}:${error}`;
const view = ViewManager.getViewByWebContentsId(webContents.id);
if (view?.tab.server) {
const serverURL = parseURL(view.tab.server.url);
if (view?.view.server) {
const serverURL = parseURL(view.view.server.url);
if (serverURL && serverURL.origin !== parsedURL.origin) {
log.warn(`Ignoring certificate for unmatched origin ${parsedURL.origin}, will not trust`);
callback(false);

View File

@@ -93,14 +93,14 @@ describe('main/app/config', () => {
});
});
it('should recheck teams after config update if registry data is pulled in', () => {
it('should recheck servers after config update if registry data is pulled in', () => {
const originalPlatform = process.platform;
Object.defineProperty(process, 'platform', {
value: 'win32',
});
Config.registryConfigData = {};
handleConfigUpdate({teams: []});
handleConfigUpdate({servers: []});
expect(handleMainWindowIsShown).toHaveBeenCalled();
Object.defineProperty(process, 'platform', {

View File

@@ -6,7 +6,7 @@
import {initialize} from './initialize';
// TODO: Singletons, we need DI :D
import('main/views/teamDropdownView');
import('main/views/serverDropdownView');
import('main/views/downloadsDropdownMenuView');
import('main/views/downloadsDropdownView');

View File

@@ -278,7 +278,7 @@ describe('main/app/initialize', () => {
it('should allow permission requests for supported types from trusted URLs', async () => {
ViewManager.getViewByWebContentsId.mockReturnValue({
tab: {
view: {
server: {
url: new URL('http://server-1.com'),
},

View File

@@ -14,8 +14,8 @@ import {
SHOW_NEW_SERVER_MODAL,
NOTIFY_MENTION,
SWITCH_TAB,
CLOSE_TAB,
OPEN_TAB,
CLOSE_VIEW,
OPEN_VIEW,
SHOW_EDIT_SERVER_MODAL,
SHOW_REMOVE_SERVER_MODAL,
UPDATE_SHORTCUT_MENU,
@@ -100,8 +100,8 @@ import {
switchServer,
} from './servers';
import {
handleCloseTab, handleGetLastActive, handleGetOrderedTabsForServer, handleOpenTab,
} from './tabs';
handleCloseView, handleGetLastActive, handleGetOrderedViewsForServer, handleOpenView,
} from './views';
import {
clearAppCache,
getDeeplinkingURL,
@@ -279,8 +279,8 @@ function initializeInterCommunicationEventListeners() {
ipcMain.on(SWITCH_SERVER, (event, serverId) => switchServer(serverId));
ipcMain.on(SWITCH_TAB, (event, viewId) => ViewManager.showById(viewId));
ipcMain.on(CLOSE_TAB, handleCloseTab);
ipcMain.on(OPEN_TAB, handleOpenTab);
ipcMain.on(CLOSE_VIEW, handleCloseView);
ipcMain.on(OPEN_VIEW, handleOpenView);
ipcMain.on(QUIT, handleQuit);
@@ -296,10 +296,10 @@ function initializeInterCommunicationEventListeners() {
ipcMain.on(UPDATE_CONFIGURATION, updateConfiguration);
ipcMain.on(UPDATE_SERVER_ORDER, (event, serverOrder) => ServerManager.updateServerOrder(serverOrder));
ipcMain.on(UPDATE_TAB_ORDER, (event, serverId, tabOrder) => ServerManager.updateTabOrder(serverId, tabOrder));
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.toMattermostTeam()));
ipcMain.handle(GET_ORDERED_TABS_FOR_SERVER, handleGetOrderedTabsForServer);
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.on(WINDOW_CLOSE, handleClose);
@@ -453,7 +453,7 @@ async function initializeAfterAppReady() {
}
const requestingURL = webContents.getURL();
const serverURL = ViewManager.getViewByWebContentsId(webContents.id)?.tab.server.url;
const serverURL = ViewManager.getViewByWebContentsId(webContents.id)?.view.server.url;
if (!serverURL) {
callback(false);

View File

@@ -16,14 +16,14 @@ jest.mock('common/config', () => ({
}));
jest.mock('main/notifications', () => ({}));
jest.mock('common/servers/serverManager', () => ({
setTabIsOpen: jest.fn(),
setViewIsOpen: jest.fn(),
getAllServers: jest.fn(),
hasServers: jest.fn(),
addServer: jest.fn(),
editServer: jest.fn(),
removeServer: jest.fn(),
getServer: jest.fn(),
getTab: jest.fn(),
getView: jest.fn(),
getLastActiveTabForServer: jest.fn(),
}));
jest.mock('main/utils', () => ({

View File

@@ -3,7 +3,7 @@
import {app, IpcMainEvent, IpcMainInvokeEvent, Menu} from 'electron';
import {MattermostTeam} from 'types/config';
import {UniqueServer} from 'types/config';
import {MentionData} from 'types/notification';
import {Logger} from 'common/log';
@@ -93,11 +93,11 @@ export function handleWelcomeScreenModal() {
if (!mainWindow) {
return;
}
const modalPromise = ModalManager.addModal<MattermostTeam[], MattermostTeam>('welcomeScreen', html, preload, ServerManager.getAllServers().map((team) => team.toMattermostTeam()), mainWindow, !ServerManager.hasServers());
const modalPromise = ModalManager.addModal<UniqueServer[], UniqueServer>('welcomeScreen', html, preload, ServerManager.getAllServers().map((server) => server.toUniqueServer()), mainWindow, !ServerManager.hasServers());
if (modalPromise) {
modalPromise.then((data) => {
const newTeam = ServerManager.addServer(data);
switchServer(newTeam.id, true);
const newServer = ServerManager.addServer(data);
switchServer(newServer.id, true);
}).catch((e) => {
// e is undefined for user cancellation
if (e) {

View File

@@ -2,7 +2,7 @@
// See LICENSE.txt for license information.
import ServerManager from 'common/servers/serverManager';
import {getDefaultConfigTeamFromTeam} from 'common/tabs/TabView';
import {getDefaultViewsForConfigServer} from 'common/views/View';
import ModalManager from 'main/views/modalManager';
import {getLocalURLString, getLocalPreload} from 'main/utils';
@@ -18,19 +18,19 @@ jest.mock('electron', () => ({
}));
jest.mock('common/servers/serverManager', () => ({
setTabIsOpen: jest.fn(),
setViewIsOpen: jest.fn(),
getAllServers: jest.fn(),
hasServers: jest.fn(),
addServer: jest.fn(),
editServer: jest.fn(),
removeServer: jest.fn(),
getServer: jest.fn(),
getTab: jest.fn(),
getView: jest.fn(),
getLastActiveTabForServer: jest.fn(),
getServerLog: jest.fn(),
}));
jest.mock('common/tabs/TabView', () => ({
getDefaultConfigTeamFromTeam: jest.fn(),
jest.mock('common/views/View', () => ({
getDefaultViewsForConfigServer: jest.fn(),
}));
jest.mock('main/views/modalManager', () => ({
addModal: jest.fn(),
@@ -50,22 +50,22 @@ jest.mock('main/views/viewManager', () => ({
const tabs = [
{
name: 'tab-1',
name: 'view-1',
order: 0,
isOpen: false,
},
{
name: 'tab-2',
name: 'view-2',
order: 2,
isOpen: true,
},
{
name: 'tab-3',
name: 'view-3',
order: 1,
isOpen: true,
},
];
const teams = [
const servers = [
{
id: 'server-1',
name: 'server-1',
@@ -77,9 +77,9 @@ const teams = [
describe('main/app/servers', () => {
describe('switchServer', () => {
const views = new Map([
['tab-1', {id: 'tab-1'}],
['tab-2', {id: 'tab-2'}],
['tab-3', {id: 'tab-3'}],
['view-1', {id: 'view-1'}],
['view-2', {id: 'view-2'}],
['view-3', {id: 'view-3'}],
]);
beforeEach(() => {
@@ -119,69 +119,69 @@ describe('main/app/servers', () => {
expect(ViewManager.showById).not.toBeCalled();
});
it('should show first open tab in order when last active not defined', () => {
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'tab-3'});
it('should show first open view in order when last active not defined', () => {
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'view-3'});
Servers.switchServer('server-1');
expect(ViewManager.showById).toHaveBeenCalledWith('tab-3');
expect(ViewManager.showById).toHaveBeenCalledWith('view-3');
});
it('should show last active tab of chosen server', () => {
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'tab-2'});
it('should show last active view of chosen server', () => {
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'view-2'});
Servers.switchServer('server-2');
expect(ViewManager.showById).toHaveBeenCalledWith('tab-2');
expect(ViewManager.showById).toHaveBeenCalledWith('view-2');
});
it('should wait for view to exist if specified', () => {
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'tab-3'});
views.delete('tab-3');
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'view-3'});
views.delete('view-3');
Servers.switchServer('server-1', true);
expect(ViewManager.showById).not.toBeCalled();
jest.advanceTimersByTime(200);
expect(ViewManager.showById).not.toBeCalled();
views.set('tab-3', {});
views.set('view-3', {});
jest.advanceTimersByTime(200);
expect(ViewManager.showById).toBeCalledWith('tab-3');
expect(ViewManager.showById).toBeCalledWith('view-3');
});
});
describe('handleNewServerModal', () => {
let teamsCopy;
let serversCopy;
beforeEach(() => {
getLocalURLString.mockReturnValue('/some/index.html');
getLocalPreload.mockReturnValue('/some/preload.js');
MainWindow.get.mockReturnValue({});
teamsCopy = JSON.parse(JSON.stringify(teams));
serversCopy = JSON.parse(JSON.stringify(servers));
ServerManager.getAllServers.mockReturnValue([]);
ServerManager.addServer.mockImplementation(() => {
const newTeam = {
const newServer = {
id: 'server-1',
name: 'new-team',
url: 'http://new-team.com',
name: 'new-server',
url: 'http://new-server.com',
tabs,
};
teamsCopy = [
...teamsCopy,
newTeam,
serversCopy = [
...serversCopy,
newServer,
];
return newTeam;
return newServer;
});
ServerManager.hasServers.mockReturnValue(Boolean(teamsCopy.length));
ServerManager.hasServers.mockReturnValue(Boolean(serversCopy.length));
ServerManager.getServerLog.mockReturnValue({debug: jest.fn(), error: jest.fn()});
getDefaultConfigTeamFromTeam.mockImplementation((team) => ({
...team,
getDefaultViewsForConfigServer.mockImplementation((server) => ({
...server,
tabs,
}));
});
it('should add new team to the config', async () => {
it('should add new server to the config', async () => {
const data = {
name: 'new-team',
url: 'http://new-team.com',
name: 'new-server',
url: 'http://new-server.com',
};
const promise = Promise.resolve(data);
ModalManager.addModal.mockReturnValue(promise);
@@ -190,10 +190,10 @@ describe('main/app/servers', () => {
await promise;
expect(ServerManager.addServer).toHaveBeenCalledWith(data);
expect(teamsCopy).toContainEqual(expect.objectContaining({
expect(serversCopy).toContainEqual(expect.objectContaining({
id: 'server-1',
name: 'new-team',
url: 'http://new-team.com',
name: 'new-server',
url: 'http://new-server.com',
tabs,
}));
@@ -203,31 +203,31 @@ describe('main/app/servers', () => {
});
describe('handleEditServerModal', () => {
let teamsCopy;
let serversCopy;
beforeEach(() => {
getLocalURLString.mockReturnValue('/some/index.html');
getLocalPreload.mockReturnValue('/some/preload.js');
MainWindow.get.mockReturnValue({});
teamsCopy = JSON.parse(JSON.stringify(teams));
serversCopy = JSON.parse(JSON.stringify(servers));
ServerManager.getServer.mockImplementation((id) => {
if (id !== teamsCopy[0].id) {
if (id !== serversCopy[0].id) {
return undefined;
}
return {...teamsCopy[0], toMattermostTeam: jest.fn()};
return {...serversCopy[0], toUniqueServer: jest.fn()};
});
ServerManager.editServer.mockImplementation((id, team) => {
if (id !== teamsCopy[0].id) {
ServerManager.editServer.mockImplementation((id, server) => {
if (id !== serversCopy[0].id) {
return;
}
const newTeam = {
...teamsCopy[0],
...team,
const newServer = {
...serversCopy[0],
...server,
};
teamsCopy = [newTeam];
serversCopy = [newServer];
});
ServerManager.getAllServers.mockReturnValue(teamsCopy.map((team) => ({...team, toMattermostTeam: jest.fn()})));
ServerManager.getAllServers.mockReturnValue(serversCopy.map((server) => ({...server, toUniqueServer: jest.fn()})));
});
it('should do nothing when the server cannot be found', () => {
@@ -235,58 +235,58 @@ describe('main/app/servers', () => {
expect(ModalManager.addModal).not.toBeCalled();
});
it('should edit the existing team', async () => {
it('should edit the existing server', async () => {
const promise = Promise.resolve({
name: 'new-team',
url: 'http://new-team.com',
name: 'new-server',
url: 'http://new-server.com',
});
ModalManager.addModal.mockReturnValue(promise);
Servers.handleEditServerModal(null, 'server-1');
await promise;
expect(teamsCopy).not.toContainEqual(expect.objectContaining({
expect(serversCopy).not.toContainEqual(expect.objectContaining({
id: 'server-1',
name: 'server-1',
url: 'http://server-1.com',
tabs,
}));
expect(teamsCopy).toContainEqual(expect.objectContaining({
expect(serversCopy).toContainEqual(expect.objectContaining({
id: 'server-1',
name: 'new-team',
url: 'http://new-team.com',
name: 'new-server',
url: 'http://new-server.com',
tabs,
}));
});
});
describe('handleRemoveServerModal', () => {
let teamsCopy;
let serversCopy;
beforeEach(() => {
getLocalURLString.mockReturnValue('/some/index.html');
getLocalPreload.mockReturnValue('/some/preload.js');
MainWindow.get.mockReturnValue({});
teamsCopy = JSON.parse(JSON.stringify(teams));
serversCopy = JSON.parse(JSON.stringify(servers));
ServerManager.getServer.mockImplementation((id) => {
if (id !== teamsCopy[0].id) {
if (id !== serversCopy[0].id) {
return undefined;
}
return teamsCopy[0];
return serversCopy[0];
});
ServerManager.removeServer.mockImplementation(() => {
teamsCopy = [];
serversCopy = [];
});
ServerManager.getAllServers.mockReturnValue(teamsCopy);
ServerManager.getAllServers.mockReturnValue(serversCopy);
});
it('should remove the existing team', async () => {
it('should remove the existing server', async () => {
const promise = Promise.resolve(true);
ModalManager.addModal.mockReturnValue(promise);
Servers.handleRemoveServerModal(null, 'server-1');
await promise;
expect(teamsCopy).not.toContainEqual(expect.objectContaining({
expect(serversCopy).not.toContainEqual(expect.objectContaining({
id: 'server-1',
name: 'server-1',
url: 'http://server-1.com',
@@ -294,11 +294,11 @@ describe('main/app/servers', () => {
}));
});
it('should not remove the existing team when clicking Cancel', async () => {
it('should not remove the existing server when clicking Cancel', async () => {
const promise = Promise.resolve(false);
ModalManager.addModal.mockReturnValue(promise);
expect(teamsCopy).toContainEqual(expect.objectContaining({
expect(serversCopy).toContainEqual(expect.objectContaining({
id: 'server-1',
name: 'server-1',
url: 'http://server-1.com',
@@ -307,7 +307,7 @@ describe('main/app/servers', () => {
Servers.handleRemoveServerModal(null, 'server-1');
await promise;
expect(teamsCopy).toContainEqual(expect.objectContaining({
expect(serversCopy).toContainEqual(expect.objectContaining({
id: 'server-1',
name: 'server-1',
url: 'http://server-1.com',

View File

@@ -3,7 +3,7 @@
import {IpcMainEvent, ipcMain} from 'electron';
import {MattermostTeam, Team} from 'types/config';
import {UniqueServer, Server} from 'types/config';
import {UPDATE_SHORTCUT_MENU} from 'common/communication';
import {Logger} from 'common/log';
@@ -24,16 +24,16 @@ export const switchServer = (serverId: string, waitForViewToExist = false) => {
ServerManager.getServerLog(serverId, 'WindowManager').error('Cannot find server in config');
return;
}
const nextTab = ServerManager.getLastActiveTabForServer(serverId);
const nextView = ServerManager.getLastActiveTabForServer(serverId);
if (waitForViewToExist) {
const timeout = setInterval(() => {
if (ViewManager.getView(nextTab.id)) {
ViewManager.showById(nextTab.id);
if (ViewManager.getView(nextView.id)) {
ViewManager.showById(nextView.id);
clearInterval(timeout);
}
}, 100);
} else {
ViewManager.showById(nextTab.id);
ViewManager.showById(nextView.id);
}
ipcMain.emit(UPDATE_SHORTCUT_MENU);
};
@@ -49,11 +49,11 @@ export const handleNewServerModal = () => {
if (!mainWindow) {
return;
}
const modalPromise = ModalManager.addModal<MattermostTeam[], Team>('newServer', html, preload, ServerManager.getAllServers().map((team) => team.toMattermostTeam()), mainWindow, !ServerManager.hasServers());
const modalPromise = ModalManager.addModal<UniqueServer[], Server>('newServer', html, preload, ServerManager.getAllServers().map((server) => server.toUniqueServer()), mainWindow, !ServerManager.hasServers());
if (modalPromise) {
modalPromise.then((data) => {
const newTeam = ServerManager.addServer(data);
switchServer(newTeam.id, true);
const newServer = ServerManager.addServer(data);
switchServer(newServer.id, true);
}).catch((e) => {
// e is undefined for user cancellation
if (e) {
@@ -80,13 +80,13 @@ export const handleEditServerModal = (e: IpcMainEvent, id: string) => {
if (!server) {
return;
}
const modalPromise = ModalManager.addModal<{currentTeams: MattermostTeam[]; team: MattermostTeam}, Team>(
const modalPromise = ModalManager.addModal<{currentServers: UniqueServer[]; server: UniqueServer}, Server>(
'editServer',
html,
preload,
{
currentTeams: ServerManager.getAllServers().map((team) => team.toMattermostTeam()),
team: server.toMattermostTeam(),
currentServers: ServerManager.getAllServers().map((server) => server.toUniqueServer()),
server: server.toUniqueServer(),
},
mainWindow);
if (modalPromise) {

View File

@@ -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 {
handleCloseTab,
handleOpenTab,
} from './tabs';
jest.mock('common/servers/serverManager', () => ({
setTabIsOpen: jest.fn(),
getTab: jest.fn(),
getLastActiveTabForServer: jest.fn(),
}));
jest.mock('main/views/viewManager', () => ({
showById: jest.fn(),
}));
describe('main/app/tabs', () => {
describe('handleCloseTab', () => {
it('should close the specified tab and switch to the next open tab', () => {
ServerManager.getTab.mockReturnValue({server: {id: 'server-1'}});
ServerManager.getLastActiveTabForServer.mockReturnValue({id: 'tab-2'});
handleCloseTab(null, 'tab-3');
expect(ServerManager.setTabIsOpen).toBeCalledWith('tab-3', false);
expect(ViewManager.showById).toBeCalledWith('tab-2');
});
});
describe('handleOpenTab', () => {
it('should open the specified tab', () => {
handleOpenTab(null, 'tab-1');
expect(ViewManager.showById).toBeCalledWith('tab-1');
});
});
});

View File

@@ -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.Tabs');
export const handleCloseTab = (event: IpcMainEvent, tabId: string) => {
log.debug('handleCloseTab', {tabId});
const tab = ServerManager.getTab(tabId);
if (!tab) {
return;
}
ServerManager.setTabIsOpen(tabId, false);
const nextTab = ServerManager.getLastActiveTabForServer(tab.server.id);
ViewManager.showById(nextTab.id);
};
export const handleOpenTab = (event: IpcMainEvent, tabId: string) => {
log.debug('handleOpenTab', {tabId});
ServerManager.setTabIsOpen(tabId, true);
ViewManager.showById(tabId);
};
export const selectNextTab = () => {
selectTab((order) => order + 1);
};
export const selectPreviousTab = () => {
selectTab((order, length) => (length + (order - 1)));
};
export const handleGetOrderedTabsForServer = (event: IpcMainInvokeEvent, serverId: string) => {
return ServerManager.getOrderedTabsForServer(serverId).map((tab) => tab.toMattermostTab());
};
export const handleGetLastActive = () => {
const server = ServerManager.getCurrentServer();
const tab = ServerManager.getLastActiveTabForServer(server.id);
return {server: server.id, tab: tab.id};
};
const selectTab = (fn: (order: number, length: number) => number) => {
const currentView = ViewManager.getCurrentView();
if (!currentView) {
return;
}
const currentTeamTabs = ServerManager.getOrderedTabsForServer(currentView.tab.server.id).map((tab, index) => ({tab, index}));
const filteredTabs = currentTeamTabs?.filter((tab) => tab.tab.isOpen);
const currentTab = currentTeamTabs?.find((tab) => tab.tab.type === currentView.tab.type);
if (!currentTeamTabs || !currentTab || !filteredTabs) {
return;
}
let currentOrder = currentTab.index;
let nextIndex = -1;
while (nextIndex === -1) {
const nextOrder = (fn(currentOrder, currentTeamTabs.length) % currentTeamTabs.length);
nextIndex = filteredTabs.findIndex((tab) => tab.index === nextOrder);
currentOrder = nextOrder;
}
const newTab = filteredTabs[nextIndex].tab;
ViewManager.showById(newTab.id);
};

View File

@@ -0,0 +1,39 @@
// 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');
});
});
});

73
src/main/app/views.ts Normal file
View File

@@ -0,0 +1,73 @@
// 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);
};