[MM-43039] Upgrade and clean up dependencies (#2038)

* Upgrade Electron to v18

* Fix a test

* Upgrade ESLint and TypeScript

* Update Joi

* Clean up and upgrade dependencies

* Upgrade dev dependencies

* Upgrade to Webpack 5

* Update NOTICE.txt

* Update test runtime
This commit is contained in:
Devin Binnie
2022-04-06 19:08:27 -04:00
committed by GitHub
parent 61de4dfb7b
commit 0fea052a9b
20 changed files with 18096 additions and 20756 deletions

View File

@@ -2,7 +2,7 @@
// See LICENSE.txt for license information.
import log from 'electron-log';
import Joi from '@hapi/joi';
import Joi from 'joi';
import {Args} from 'types/args';
import {ConfigV0, ConfigV1, ConfigV2, ConfigV3, TeamWithTabs} from 'types/config';

View File

@@ -261,28 +261,31 @@ describe('main/app/utils', () => {
expect(updatePaths).not.toHaveBeenCalled();
});
it('should copy all of the configs when they exist to the new directory', () => {
const migrationPrefs = {
getValue: () => false,
setValue: jest.fn(),
};
JsonFileManager.mockImplementation(() => migrationPrefs);
fs.readFileSync.mockReturnValue('config-data');
fs.existsSync.mockImplementation((path) => {
if (path === '/Library/Application Support/Mattermost') {
return true;
}
return ['config', 'app-state', 'bounds-info', 'migration-info'].some((filename) => path.endsWith(`${filename}.json`));
// this doesn't run on windows because of path resolution
if (process.platform !== 'win32') {
it('should copy all of the configs when they exist to the new directory', () => {
const migrationPrefs = {
getValue: () => false,
setValue: jest.fn(),
};
JsonFileManager.mockImplementation(() => migrationPrefs);
fs.readFileSync.mockReturnValue('config-data');
fs.existsSync.mockImplementation((path) => {
if (path === '/Library/Application Support/Mattermost') {
return true;
}
return ['config', 'app-state', 'bounds-info', 'migration-info'].some((filename) => path.endsWith(`${filename}.json`));
});
dialog.showMessageBoxSync.mockReturnValue(0);
dialog.showOpenDialogSync.mockReturnValue(['/old/data/path']);
migrateMacAppStore();
expect(fs.readFileSync).toHaveBeenCalledWith('/old/data/path/config.json');
expect(fs.writeFileSync).toHaveBeenCalledWith('/path/to/data/config.json', 'config-data');
expect(fs.readFileSync).not.toHaveBeenCalledWith('/old/data/path/allowedProtocols.json');
expect(fs.writeFileSync).not.toHaveBeenCalledWith('/path/to/data/allowedProtocols.json', 'config-data');
expect(updatePaths).toHaveBeenCalled();
expect(migrationPrefs.setValue).toHaveBeenCalledWith('masConfigs', true);
});
dialog.showMessageBoxSync.mockReturnValue(0);
dialog.showOpenDialogSync.mockReturnValue(['/old/data/path']);
migrateMacAppStore();
expect(fs.readFileSync).toHaveBeenCalledWith('/old/data/path/config.json');
expect(fs.writeFileSync).toHaveBeenCalledWith('/path/to/data/config.json', 'config-data');
expect(fs.readFileSync).not.toHaveBeenCalledWith('/old/data/path/allowedProtocols.json');
expect(fs.writeFileSync).not.toHaveBeenCalledWith('/path/to/data/allowedProtocols.json', 'config-data');
expect(updatePaths).toHaveBeenCalled();
expect(migrationPrefs.setValue).toHaveBeenCalledWith('masConfigs', true);
});
}
});
});

View File

@@ -3,6 +3,7 @@
import os from 'os';
import path from 'path';
import {app, Notification} from 'electron';
import Utils from 'common/utils/util';

View File

@@ -2,6 +2,7 @@
// See LICENSE.txt for license information.
import path from 'path';
import {app, Notification} from 'electron';
const assetsDir = path.resolve(app.getAppPath(), 'assets');

View File

@@ -2,6 +2,7 @@
// See LICENSE.txt for license information.
import path from 'path';
import {app, nativeImage, Tray, systemPreferences, nativeTheme} from 'electron';
import {UPDATE_TRAY} from 'common/communication';

View File

@@ -2,9 +2,10 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {app, BrowserWindow} from 'electron';
import path from 'path';
import {app, BrowserWindow} from 'electron';
import {Args} from 'types/args';
import {BACK_BAR_HEIGHT, PRODUCTION, TAB_BAR_HEIGHT} from 'common/utils/constants';

View File

@@ -3,6 +3,7 @@
/* eslint-disable max-lines */
import path from 'path';
import {app, BrowserWindow, nativeImage, systemPreferences, ipcMain, IpcMainEvent, IpcMainInvokeEvent, desktopCapturer} from 'electron';
import log from 'electron-log';

View File

@@ -37,7 +37,7 @@ export default class ExtraBar extends React.PureComponent<Props> {
variant={'link'}
size={'sm'}
>
<span className={'backIcon fa fa-1x fa-angle-left'}/>
<span className={'backIcon icon-arrow-left'}/>
<span className={'backLabel'}>
{'Back'}
</span>

View File

@@ -6,7 +6,6 @@ import classNames from 'classnames';
import React, {Fragment} from 'react';
import {Container, Row} from 'react-bootstrap';
import {DropResult} from 'react-beautiful-dnd';
import DotsVerticalIcon from 'mdi-react/DotsVerticalIcon';
import {IpcRendererEvent} from 'electron/renderer';
import prettyBytes from 'pretty-bytes';
@@ -504,7 +503,7 @@ export default class MainPage extends React.PureComponent<Props, State> {
ref={this.threeDotMenu}
aria-label='Context menu'
>
<DotsVerticalIcon/>
<i className='icon-dots-vertical'/>
</button>
<TeamDropdownButton
isDisabled={this.state.modalOpen}

View File

@@ -8,9 +8,7 @@ import 'renderer/css/settings.css';
import React from 'react';
import {FormCheck, Col, FormGroup, FormText, Container, Row, Button, FormControl} from 'react-bootstrap';
import ReactSelect, {ActionMeta, OptionsType} from 'react-select';
import {debounce} from 'underscore';
import ReactSelect, {ActionMeta, MultiValue} from 'react-select';
import {CombinedConfig, LocalConfiguration} from 'types/config';
import {DeepPartial} from 'types/utils';
@@ -76,6 +74,9 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
selectedSpellCheckerLocales: Array<{label: string; value: string}>;
savingIsDebounced: boolean;
resetSaveStateIsDebounced: boolean;
constructor(props: Record<string, never>) {
super(props);
this.state = {
@@ -108,6 +109,9 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
this.saveQueue = [];
this.selectedSpellCheckerLocales = [];
this.savingIsDebounced = false;
this.resetSaveStateIsDebounced = false;
}
componentDidMount() {
@@ -149,9 +153,17 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
this.processSaveQueue();
}
processSaveQueue = debounce(() => {
processSaveQueue = () => {
if (this.savingIsDebounced) {
return;
}
this.savingIsDebounced = true;
setTimeout(() => {
this.savingIsDebounced = false;
}, 500);
window.ipcRenderer.send(UPDATE_CONFIGURATION, this.saveQueue.splice(0, this.saveQueue.length));
}, 500);
}
updateSaveState = () => {
let queuedUpdateCounts = {
@@ -178,13 +190,21 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
this.setState({savingState});
}
resetSaveState = debounce((configType: keyof SavingStateItems) => {
resetSaveState = (configType: keyof SavingStateItems) => {
if (this.resetSaveStateIsDebounced) {
return;
}
this.resetSaveStateIsDebounced = true;
setTimeout(() => {
this.resetSaveStateIsDebounced = false;
}, 2000);
if (this.state.savingState[configType] !== SavingState.SAVING_STATE_SAVING) {
const savingState = Object.assign({}, this.state.savingState);
savingState[configType] = SavingState.SAVING_STATE_DONE;
this.setState({savingState});
}
}, 2000);
}
handleChangeShowTrayIcon = () => {
const shouldShowTrayIcon = this.showTrayIconRef.current?.checked;
@@ -314,7 +334,7 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
window.ipcRenderer.send(CHECK_FOR_UPDATES);
}
handleChangeSpellCheckerLocales = (value: OptionsType<{label: string; value: string}>, actionMeta: ActionMeta<{label: string; value: string}>) => {
handleChangeSpellCheckerLocales = (value: MultiValue<{label: string; value: string}>, actionMeta: ActionMeta<{label: string; value: string}>) => {
switch (actionMeta.action) {
case 'select-option':
this.selectedSpellCheckerLocales = [...value];

View File

@@ -1,6 +1,5 @@
@import url("components/index.css");
@import url("fonts.css");
@import '~font-awesome/css/font-awesome.css';
@import '~@mattermost/compass-icons/css/compass-icons.css';
html {
@@ -63,6 +62,7 @@ body {
line-height: 20px;
height: 36px;
float: left;
margin-left: 4px;
padding-top: 5px;
border: none;
flex: 0 0 40px;
@@ -72,9 +72,9 @@ body {
background-color: transparent;
}
.topBar .three-dot-menu svg {
.topBar .three-dot-menu i.icon-dots-vertical {
border-radius: 100px;
padding: 4px;
padding: 2px;
height: 28px;
width: 28px;
}
@@ -83,16 +83,16 @@ body {
outline: none;
}
.topBar .three-dot-menu:hover svg, .topBar .three-dot-menu:focus svg, .topBar .three-dot-menu:active svg {
.topBar .three-dot-menu:hover i.icon-dots-vertical, .topBar .three-dot-menu:focus i.icon-dots-vertical, .topBar .three-dot-menu:active i.icon-dots-vertical {
outline: none;
background-color: #c8c8c8;
}
.topBar.darkMode .three-dot-menu:hover svg, .topBar.darkMode .three-dot-menu:focus svg, .topBar.darkMode .three-dot-menu:active svg {
.topBar.darkMode .three-dot-menu:hover i.icon-dots-vertical, .topBar.darkMode .three-dot-menu:focus i.icon-dots-vertical, .topBar.darkMode .three-dot-menu:active i.icon-dots-vertical {
background-color: #383A3F;
}
.topBar.macOS .three-dot-menu:hover svg, .topBar.macOS .three-dot-menu:focus svg, .topBar.macOS .three-dot-menu:active svg {
.topBar.macOS .three-dot-menu:hover i.icon-dots-vertical, .topBar.macOS .three-dot-menu:focus i.icon-dots-vertical, .topBar.macOS .three-dot-menu:active i.icon-dots-vertical {
background: none !important;
}
@@ -105,7 +105,7 @@ body {
flex-basis: 0px;
}
.topBar.macOS .three-dot-menu>svg {
.topBar.macOS .three-dot-menu>i.icon-dots-vertical {
display: none;
}

View File

@@ -1,8 +1,6 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {throttle} from 'underscore';
import ding from 'static/sounds/ding.mp3';
import bing from 'static/sounds/bing.mp3';
import crackle from 'static/sounds/crackle.mp3';
@@ -22,9 +20,15 @@ const notificationSounds = new Map([
['Upstairs', upstairs],
]);
export const playSound = throttle((soundName: string) => {
if (soundName) {
let canPlaySound = true;
export const playSound = (soundName: string) => {
if (soundName && canPlaySound) {
canPlaySound = false;
setTimeout(() => {
canPlaySound = true;
}, 3000);
const audio = new Audio(notificationSounds.get(soundName));
audio.play();
}
}, 3000, {trailing: false});
};