[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:
@@ -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';
|
||||
|
@@ -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);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
import {app, Notification} from 'electron';
|
||||
|
||||
import Utils from 'common/utils/util';
|
||||
|
@@ -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');
|
||||
|
@@ -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';
|
||||
|
@@ -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';
|
||||
|
@@ -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';
|
||||
|
||||
|
@@ -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>
|
||||
|
@@ -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}
|
||||
|
@@ -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];
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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});
|
||||
};
|
||||
|
Reference in New Issue
Block a user