React bootstrap upgrade to v1, migrate to react-beautiful-dnd (#1639)

* Upgrade packages, fix errors, still WIP

* WIP

* Bootstrap v4 upgrade

* Switch to react-beautiful-dnd

* Fixed some issues

* Added to generate signed Mac build for UX

* PR feedback

* Missed one

* PR feedback
This commit is contained in:
Devin Binnie
2021-07-05 21:19:11 -04:00
committed by GitHub
parent 86a3f13a6b
commit 4130c2c37d
27 changed files with 869 additions and 554 deletions

View File

@@ -7,7 +7,7 @@
import 'renderer/css/settings.css';
import React from 'react';
import {Checkbox, Col, FormGroup, Grid, HelpBlock, Navbar, Radio, Row, Button} from 'react-bootstrap';
import {FormCheck, Col, FormGroup, FormText, Container, Row, Button} from 'react-bootstrap';
import {debounce} from 'underscore';
@@ -52,16 +52,16 @@ function backToIndex(serverName: string) {
}
export default class SettingsPage extends React.PureComponent<Record<string, never>, State> {
trayIconThemeRef: React.RefObject<FormGroup>;
trayIconThemeRef: React.RefObject<HTMLDivElement>;
downloadLocationRef: React.RefObject<HTMLInputElement>;
showTrayIconRef: React.RefObject<Checkbox>;
autostartRef: React.RefObject<Checkbox>;
minimizeToTrayRef: React.RefObject<Checkbox>;
flashWindowRef: React.RefObject<Checkbox>;
bounceIconRef: React.RefObject<Checkbox>;
showUnreadBadgeRef: React.RefObject<Checkbox>;
useSpellCheckerRef: React.RefObject<Checkbox>;
enableHardwareAccelerationRef: React.RefObject<Checkbox>;
showTrayIconRef: React.RefObject<HTMLInputElement>;
autostartRef: React.RefObject<HTMLInputElement>;
minimizeToTrayRef: React.RefObject<HTMLInputElement>;
flashWindowRef: React.RefObject<HTMLInputElement>;
bounceIconRef: React.RefObject<HTMLInputElement>;
showUnreadBadgeRef: React.RefObject<HTMLInputElement>;
useSpellCheckerRef: React.RefObject<HTMLInputElement>;
enableHardwareAccelerationRef: React.RefObject<HTMLInputElement>;
saveQueue: SaveQueueItem[];
@@ -186,7 +186,7 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
}
handleChangeShowTrayIcon = () => {
const shouldShowTrayIcon = !this.showTrayIconRef.current?.props.checked;
const shouldShowTrayIcon = this.showTrayIconRef.current?.checked;
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'showTrayIcon', data: shouldShowTrayIcon});
this.setState({
showTrayIcon: shouldShowTrayIcon,
@@ -207,14 +207,14 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
}
handleChangeAutoStart = () => {
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'autostart', data: !this.autostartRef.current?.props.checked});
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'autostart', data: this.autostartRef.current?.checked});
this.setState({
autostart: !this.autostartRef.current?.props.checked,
autostart: this.autostartRef.current?.checked,
});
}
handleChangeMinimizeToTray = () => {
const shouldMinimizeToTray = this.state.showTrayIcon && !this.minimizeToTrayRef.current?.props.checked;
const shouldMinimizeToTray = this.state.showTrayIcon && !this.minimizeToTrayRef.current?.checked;
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'minimizeToTray', data: shouldMinimizeToTray});
this.setState({
@@ -240,13 +240,13 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
key: 'notifications',
data: {
...this.state.notifications,
flashWindow: this.flashWindowRef.current?.props.checked ? 0 : 2,
flashWindow: this.flashWindowRef.current?.checked ? 0 : 2,
},
});
this.setState({
notifications: {
...this.state.notifications,
flashWindow: this.flashWindowRef.current?.props.checked ? 0 : 2,
flashWindow: this.flashWindowRef.current?.checked ? 0 : 2,
},
});
}
@@ -256,18 +256,18 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
key: 'notifications',
data: {
...this.state.notifications,
bounceIcon: !this.bounceIconRef.current?.props.checked,
bounceIcon: this.bounceIconRef.current?.checked,
},
});
this.setState({
notifications: {
...this.state.notifications,
bounceIcon: !this.bounceIconRef.current?.props.checked,
bounceIcon: this.bounceIconRef.current?.checked,
},
});
}
handleBounceIconType = (event: React.ChangeEvent<Radio & HTMLInputElement>) => {
handleBounceIconType = (event: React.ChangeEvent<HTMLInputElement>) => {
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {
key: 'notifications',
data: {
@@ -284,23 +284,23 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
}
handleShowUnreadBadge = () => {
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'showUnreadBadge', data: !this.showUnreadBadgeRef.current?.props.checked});
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'showUnreadBadge', data: this.showUnreadBadgeRef.current?.checked});
this.setState({
showUnreadBadge: !this.showUnreadBadgeRef.current?.props.checked,
showUnreadBadge: this.showUnreadBadgeRef.current?.checked,
});
}
handleChangeUseSpellChecker = () => {
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'useSpellChecker', data: !this.useSpellCheckerRef.current?.props.checked});
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'useSpellChecker', data: this.useSpellCheckerRef.current?.checked});
this.setState({
useSpellChecker: !this.useSpellCheckerRef.current?.props.checked,
useSpellChecker: this.useSpellCheckerRef.current?.checked,
});
}
handleChangeEnableHardwareAcceleration = () => {
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'enableHardwareAcceleration', data: !this.enableHardwareAccelerationRef.current?.props.checked});
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'enableHardwareAcceleration', data: this.enableHardwareAccelerationRef.current?.checked});
this.setState({
enableHardwareAcceleration: !this.enableHardwareAccelerationRef.current?.props.checked,
enableHardwareAcceleration: this.enableHardwareAccelerationRef.current?.checked,
});
}
@@ -350,10 +350,6 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
render() {
const settingsPage = {
navbar: {
backgroundColor: '#fff',
position: 'relative' as const,
},
close: {
textDecoration: 'none',
position: 'absolute',
@@ -424,7 +420,6 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
const serversRow = (
<Row>
<Col
md={10}
xs={8}
>
<h2 style={settingsPage.sectionHeading}>{'Server Management'}</h2>
@@ -437,7 +432,6 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
</div>
</Col>
<Col
md={2}
xs={4}
>
<p className='text-right'>
@@ -468,66 +462,74 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
// MacOS has an option in the Dock, to set the app to autostart, so we choose to not support this option for OSX
if (window.process.platform === 'win32' || window.process.platform === 'linux') {
options.push(
<Checkbox
key='inputAutoStart'
id='inputAutoStart'
ref={this.autostartRef}
checked={this.state.autostart}
onChange={this.handleChangeAutoStart}
>
<FormCheck>
<FormCheck.Input
type='checkbox'
key='inputAutoStart'
id='inputAutoStart'
ref={this.autostartRef}
checked={this.state.autostart}
onChange={this.handleChangeAutoStart}
/>
{'Start app on login'}
<HelpBlock>
<FormText>
{'If enabled, the app starts automatically when you log in to your machine.'}
</HelpBlock>
</Checkbox>);
</FormText>
</FormCheck>);
}
options.push(
<Checkbox
key='inputSpellChecker'
id='inputSpellChecker'
ref={this.useSpellCheckerRef}
checked={this.state.useSpellChecker}
onChange={this.handleChangeUseSpellChecker}
>
<FormCheck>
<FormCheck.Input
type='checkbox'
key='inputSpellChecker'
id='inputSpellChecker'
ref={this.useSpellCheckerRef}
checked={this.state.useSpellChecker}
onChange={this.handleChangeUseSpellChecker}
/>
{'Check spelling'}
<HelpBlock>
<FormText>
{'Highlight misspelled words in your messages based on your system language configuration. '}
{'Setting takes effect after restarting the app.'}
</HelpBlock>
</Checkbox>);
</FormText>
</FormCheck>);
if (window.process.platform === 'darwin' || window.process.platform === 'win32') {
const TASKBAR = window.process.platform === 'win32' ? 'taskbar' : 'Dock';
options.push(
<Checkbox
key='inputShowUnreadBadge'
id='inputShowUnreadBadge'
ref={this.showUnreadBadgeRef}
checked={this.state.showUnreadBadge}
onChange={this.handleShowUnreadBadge}
>
<FormCheck>
<FormCheck.Input
type='checkbox'
key='inputShowUnreadBadge'
id='inputShowUnreadBadge'
ref={this.showUnreadBadgeRef}
checked={this.state.showUnreadBadge}
onChange={this.handleShowUnreadBadge}
/>
{`Show red badge on ${TASKBAR} icon to indicate unread messages`}
<HelpBlock>
<FormText>
{`Regardless of this setting, mentions are always indicated with a red badge and item count on the ${TASKBAR} icon.`}
</HelpBlock>
</Checkbox>);
</FormText>
</FormCheck>);
}
if (window.process.platform === 'win32' || window.process.platform === 'linux') {
options.push(
<Checkbox
key='flashWindow'
id='inputflashWindow'
ref={this.flashWindowRef}
checked={!this.state.notifications || this.state.notifications.flashWindow === 2}
onChange={this.handleFlashWindow}
>
<FormCheck>
<FormCheck.Input
type='checkbox'
key='flashWindow'
id='inputflashWindow'
ref={this.flashWindowRef}
checked={!this.state.notifications || this.state.notifications.flashWindow === 2}
onChange={this.handleFlashWindow}
/>
{'Flash app window and taskbar icon when a new message is received'}
<HelpBlock>
<FormText>
{'If enabled, app window and taskbar icon flash for a few seconds when a new message is received.'}
</HelpBlock>
</Checkbox>);
</FormText>
</FormCheck>);
}
if (window.process.platform === 'darwin') {
@@ -535,7 +537,8 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
<FormGroup
key='OptionsForm'
>
<Checkbox
<FormCheck
type='checkbox'
inline={true}
key='bounceIcon'
id='inputBounceIcon'
@@ -543,10 +546,10 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
checked={this.state.notifications ? this.state.notifications.bounceIcon : false}
onChange={this.handleBounceIcon}
style={{marginRight: '10px'}}
>
{'Bounce the Dock icon'}
</Checkbox>
<Radio
label='Bounce the Dock icon'
/>
<FormCheck
type='radio'
inline={true}
name='bounceIconType'
value='informational'
@@ -557,43 +560,44 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
this.state.notifications.bounceIconType === 'informational'
}
onChange={this.handleBounceIconType}
>
{'once'}
</Radio>
label='once'
/>
{' '}
<Radio
<FormCheck
type='radio'
inline={true}
name='bounceIconType'
value='critical'
disabled={!this.state.notifications || !this.state.notifications.bounceIcon}
defaultChecked={this.state.notifications && this.state.notifications.bounceIconType === 'critical'}
onChange={this.handleBounceIconType}
>
{'until I open the app'}
</Radio>
<HelpBlock
label={'until I open the app'}
/>
<FormText
style={{marginLeft: '20px'}}
>
{'If enabled, the Dock icon bounces once or until the user opens the app when a new notification is received.'}
</HelpBlock>
</FormText>
</FormGroup>,
);
}
if (window.process.platform === 'darwin' || window.process.platform === 'linux') {
options.push(
<Checkbox
key='inputShowTrayIcon'
id='inputShowTrayIcon'
ref={this.showTrayIconRef}
checked={this.state.showTrayIcon}
onChange={this.handleChangeShowTrayIcon}
>
<FormCheck>
<FormCheck.Input
type='checkbox'
key='inputShowTrayIcon'
id='inputShowTrayIcon'
ref={this.showTrayIconRef}
checked={this.state.showTrayIcon}
onChange={this.handleChangeShowTrayIcon}
/>
{window.process.platform === 'darwin' ? `Show ${this.state.appName} icon in the menu bar` : 'Show icon in the notification area'}
<HelpBlock>
<FormText>
{'Setting takes effect after restarting the app.'}
</HelpBlock>
</Checkbox>);
</FormText>
</FormCheck>);
}
if (window.process.platform === 'linux') {
@@ -604,30 +608,33 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
style={{marginLeft: '20px'}}
>
{'Icon theme: '}
<Radio
<FormCheck
type='radio'
inline={true}
name='trayIconTheme'
value='light'
defaultChecked={this.state.trayIconTheme === 'light' || !this.state.trayIconTheme}
onChange={() => this.handleChangeTrayIconTheme('light')}
>
{'Light'}
</Radio>
label={'Light'}
/>
{' '}
<Radio
<FormCheck
type='radio'
inline={true}
name='trayIconTheme'
value='dark'
defaultChecked={this.state.trayIconTheme === 'dark'}
onChange={() => this.handleChangeTrayIconTheme('dark')}
>{'Dark'}</Radio>
label={'Dark'}
/>
</FormGroup>,
);
}
if (window.process.platform === 'linux') {
options.push(
<Checkbox
<FormCheck
type='radio'
key='inputMinimizeToTray'
id='inputMinimizeToTray'
ref={this.minimizeToTrayRef}
@@ -636,27 +643,29 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
onChange={this.handleChangeMinimizeToTray}
>
{'Leave app running in notification area when application window is closed'}
<HelpBlock>
<FormText>
{'If enabled, the app stays running in the notification area after app window is closed.'}
{this.state.trayWasVisible || !this.state.showTrayIcon ? '' : ' Setting takes effect after restarting the app.'}
</HelpBlock>
</Checkbox>);
</FormText>
</FormCheck>);
}
options.push(
<Checkbox
key='inputEnableHardwareAcceleration'
id='inputEnableHardwareAcceleration'
ref={this.enableHardwareAccelerationRef}
checked={this.state.enableHardwareAcceleration}
onChange={this.handleChangeEnableHardwareAcceleration}
>
<FormCheck>
<FormCheck.Input
type='checkbox'
key='inputEnableHardwareAcceleration'
id='inputEnableHardwareAcceleration'
ref={this.enableHardwareAccelerationRef}
checked={this.state.enableHardwareAcceleration}
onChange={this.handleChangeEnableHardwareAcceleration}
/>
{'Use GPU hardware acceleration'}
<HelpBlock>
<FormText>
{'If enabled, Mattermost UI is rendered more efficiently but can lead to decreased stability for some systems.'}
{' Setting takes effect after restarting the app.'}
</HelpBlock>
</Checkbox>,
</FormText>
</FormCheck>,
);
options.push(
@@ -679,9 +688,9 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
>
<span>{'Change'}</span>
</Button>
<HelpBlock>
<FormText>
{'Specify the folder where files will download.'}
</HelpBlock>
</FormText>
</div>,
);
@@ -734,19 +743,15 @@ export default class SettingsPage extends React.PureComponent<Record<string, nev
margin: '0 -15px',
}}
>
<Navbar
className='navbar-fixed-top'
style={settingsPage.navbar}
>
<div style={{position: 'relative'}}>
<h1 style={settingsPage.heading}>{'Settings'}</h1>
</div>
</Navbar>
<Grid
<div style={{position: 'relative'}}>
<h1 style={settingsPage.heading}>{'Settings'}</h1>
<hr/>
</div>
<Container
className='settingsPage'
>
{waitForIpc}
</Grid>
</Container>
</div>
</div>
);