Merge remote-tracking branch 'mattermost/master' into startup-via-config-json
This commit is contained in:
@@ -17,10 +17,10 @@
|
||||
"no-console": 0,
|
||||
"no-process-env": 0,
|
||||
"no-underscore-dangle": 1,
|
||||
"no-var": 2,
|
||||
"react/jsx-indent": [2, 2],
|
||||
"react/jsx-indent-props": [2, 2],
|
||||
"react/no-set-state": 1,
|
||||
"react/prefer-es6-class": 1,
|
||||
"react/require-optimization": 0
|
||||
}
|
||||
}
|
||||
|
@@ -21,6 +21,8 @@ Release date: TBD
|
||||
#### Mac
|
||||
- Add **.dmg** package to support installation.
|
||||
[#588](https://github.com/mattermost/desktop/pull/588)
|
||||
- Support "Hide" option of Login Items in Preferences.
|
||||
[#853](https://github.com/mattermost/desktop/pull/853)
|
||||
|
||||
#### Linux
|
||||
- [tar.gz] Use SVG icon for Linux application menus in place of PNG icon
|
||||
@@ -30,8 +32,9 @@ Release date: TBD
|
||||
[#818](https://github.com/mattermost/desktop/pull/818)
|
||||
|
||||
### Architectural Changes
|
||||
- Major version upgrade of Electron to v2.0.2. Electron is the underlying technology used to build the Desktop apps.
|
||||
- Major version upgrade of Electron to v2.0.8. Electron is the underlying technology used to build the Desktop apps.
|
||||
[#820](https://github.com/mattermost/desktop/pull/820)
|
||||
[#847](https://github.com/mattermost/desktop/pull/847)
|
||||
- Artifact names are configured via `electron-builder.json`.
|
||||
[#825](https://github.com/mattermost/desktop/pull/825)
|
||||
|
||||
|
@@ -428,7 +428,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
## react
|
||||
|
||||
This product contains a modified portion of 'react', a declarative, efficient, and flexible JavaScript library for building user interfaces,
|
||||
'create-react-class', a drop-in replacement for React.createClass, and 'react-dom', the entry point of the DOM-related
|
||||
and 'react-dom', the entry point of the DOM-related
|
||||
rendering paths, by Facebook, Inc.
|
||||
|
||||
* HOMEPAGE:
|
||||
|
@@ -49,7 +49,7 @@
|
||||
"cross-env": "^5.1.6",
|
||||
"css-loader": "^0.28.11",
|
||||
"devtron": "^1.4.0",
|
||||
"electron": "2.0.2",
|
||||
"electron": "2.0.8",
|
||||
"electron-builder": "20.14.7",
|
||||
"electron-builder-squirrel-windows": "~20.14.0",
|
||||
"electron-connect": "^0.6.3",
|
||||
|
@@ -22,7 +22,7 @@ export default class LoginModal extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
var theServer = '';
|
||||
let theServer = '';
|
||||
if (!this.props.show) {
|
||||
theServer = '';
|
||||
} else if (this.props.authInfo.isProxy) {
|
||||
|
@@ -1,11 +1,13 @@
|
||||
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
/* eslint-disable react/no-set-state */
|
||||
|
||||
import url from 'url';
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import {CSSTransition, TransitionGroup} from 'react-transition-group';
|
||||
import {Grid, Row} from 'react-bootstrap';
|
||||
|
||||
@@ -21,24 +23,13 @@ import PermissionRequestDialog from './PermissionRequestDialog.jsx';
|
||||
import Finder from './Finder.jsx';
|
||||
import NewTeamModal from './NewTeamModal.jsx';
|
||||
|
||||
const MainPage = createReactClass({
|
||||
propTypes: {
|
||||
onUnreadCountChange: PropTypes.func.isRequired,
|
||||
teams: PropTypes.array.isRequired,
|
||||
onTeamConfigChange: PropTypes.func.isRequired,
|
||||
initialIndex: PropTypes.number.isRequired,
|
||||
useSpellChecker: PropTypes.bool.isRequired,
|
||||
onSelectSpellCheckerLocale: PropTypes.func.isRequired,
|
||||
deeplinkingUrl: PropTypes.string,
|
||||
showAddServerButton: PropTypes.bool.isRequired,
|
||||
requestingPermission: TabBar.propTypes.requestingPermission,
|
||||
onClickPermissionDialog: PropTypes.func,
|
||||
},
|
||||
export default class MainPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
getInitialState() {
|
||||
let key = this.props.initialIndex;
|
||||
if (this.props.deeplinkingUrl !== null) {
|
||||
for (var i = 0; i < this.props.teams.length; i++) {
|
||||
for (let i = 0; i < this.props.teams.length; i++) {
|
||||
if (this.props.deeplinkingUrl.includes(this.props.teams[i].url)) {
|
||||
key = i;
|
||||
break;
|
||||
@@ -46,7 +37,7 @@ const MainPage = createReactClass({
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
this.state = {
|
||||
key,
|
||||
unreadCounts: new Array(this.props.teams.length),
|
||||
mentionCounts: new Array(this.props.teams.length),
|
||||
@@ -55,9 +46,24 @@ const MainPage = createReactClass({
|
||||
loginQueue: [],
|
||||
targetURL: '',
|
||||
};
|
||||
},
|
||||
|
||||
this.activateFinder = this.activateFinder.bind(this);
|
||||
this.addServer = this.addServer.bind(this);
|
||||
this.closeFinder = this.closeFinder.bind(this);
|
||||
this.focusOnWebView = this.focusOnWebView.bind(this);
|
||||
this.handleLogin = this.handleLogin.bind(this);
|
||||
this.handleLoginCancel = this.handleLoginCancel.bind(this);
|
||||
this.handleOnTeamFocused = this.handleOnTeamFocused.bind(this);
|
||||
this.handleSelect = this.handleSelect.bind(this);
|
||||
this.handleTargetURLChange = this.handleTargetURLChange.bind(this);
|
||||
this.handleUnreadCountChange = this.handleUnreadCountChange.bind(this);
|
||||
this.handleUnreadCountTotalChange = this.handleUnreadCountTotalChange.bind(this);
|
||||
this.inputBlur = this.inputBlur.bind(this);
|
||||
this.markReadAtActive = this.markReadAtActive.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
var self = this;
|
||||
const self = this;
|
||||
ipcRenderer.on('login-request', (event, request, authInfo) => {
|
||||
self.setState({
|
||||
loginRequired: true,
|
||||
@@ -96,7 +102,7 @@ const MainPage = createReactClass({
|
||||
self.refs[`mattermostView${self.state.key}`].focusOnWebView();
|
||||
}
|
||||
|
||||
var currentWindow = remote.getCurrentWindow();
|
||||
const currentWindow = remote.getCurrentWindow();
|
||||
currentWindow.on('focus', focusListener);
|
||||
window.addEventListener('beforeunload', () => {
|
||||
currentWindow.removeListener('focus', focusListener);
|
||||
@@ -132,7 +138,7 @@ const MainPage = createReactClass({
|
||||
|
||||
ipcRenderer.on('protocol-deeplink', (event, deepLinkUrl) => {
|
||||
const lastUrlDomain = Utils.getDomain(deepLinkUrl);
|
||||
for (var i = 0; i < this.props.teams.length; i++) {
|
||||
for (let i = 0; i < this.props.teams.length; i++) {
|
||||
if (lastUrlDomain === Utils.getDomain(self.refs[`mattermostView${i}`].getSrc())) {
|
||||
if (this.state.key !== i) {
|
||||
this.handleSelect(i);
|
||||
@@ -146,30 +152,32 @@ const MainPage = createReactClass({
|
||||
ipcRenderer.on('toggle-find', () => {
|
||||
this.activateFinder(true);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (prevState.key !== this.state.key) { // i.e. When tab has been changed
|
||||
this.refs[`mattermostView${this.state.key}`].focusOnWebView();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
handleSelect(key) {
|
||||
const newKey = (this.props.teams.length + key) % this.props.teams.length;
|
||||
this.setState({
|
||||
key: newKey,
|
||||
finderVisible: false,
|
||||
});
|
||||
var webview = document.getElementById('mattermostView' + newKey);
|
||||
const webview = document.getElementById('mattermostView' + newKey);
|
||||
ipcRenderer.send('update-title', {
|
||||
title: webview.getTitle(),
|
||||
});
|
||||
this.handleOnTeamFocused(newKey);
|
||||
},
|
||||
}
|
||||
|
||||
handleUnreadCountChange(index, unreadCount, mentionCount, isUnread, isMentioned) {
|
||||
var unreadCounts = this.state.unreadCounts;
|
||||
var mentionCounts = this.state.mentionCounts;
|
||||
var unreadAtActive = this.state.unreadAtActive;
|
||||
var mentionAtActiveCounts = this.state.mentionAtActiveCounts;
|
||||
const unreadCounts = this.state.unreadCounts;
|
||||
const mentionCounts = this.state.mentionCounts;
|
||||
const unreadAtActive = this.state.unreadAtActive;
|
||||
const mentionAtActiveCounts = this.state.mentionAtActiveCounts;
|
||||
unreadCounts[index] = unreadCount;
|
||||
mentionCounts[index] = mentionCount;
|
||||
|
||||
@@ -187,10 +195,11 @@ const MainPage = createReactClass({
|
||||
mentionAtActiveCounts,
|
||||
});
|
||||
this.handleUnreadCountTotalChange();
|
||||
},
|
||||
}
|
||||
|
||||
markReadAtActive(index) {
|
||||
var unreadAtActive = this.state.unreadAtActive;
|
||||
var mentionAtActiveCounts = this.state.mentionAtActiveCounts;
|
||||
const unreadAtActive = this.state.unreadAtActive;
|
||||
const mentionAtActiveCounts = this.state.mentionAtActiveCounts;
|
||||
unreadAtActive[index] = false;
|
||||
mentionAtActiveCounts[index] = 0;
|
||||
this.setState({
|
||||
@@ -198,10 +207,11 @@ const MainPage = createReactClass({
|
||||
mentionAtActiveCounts,
|
||||
});
|
||||
this.handleUnreadCountTotalChange();
|
||||
},
|
||||
}
|
||||
|
||||
handleUnreadCountTotalChange() {
|
||||
if (this.props.onUnreadCountChange) {
|
||||
var allUnreadCount = this.state.unreadCounts.reduce((prev, curr) => {
|
||||
let allUnreadCount = this.state.unreadCounts.reduce((prev, curr) => {
|
||||
return prev + curr;
|
||||
}, 0);
|
||||
this.state.unreadAtActive.forEach((state) => {
|
||||
@@ -209,7 +219,7 @@ const MainPage = createReactClass({
|
||||
allUnreadCount += 1;
|
||||
}
|
||||
});
|
||||
var allMentionCount = this.state.mentionCounts.reduce((prev, curr) => {
|
||||
let allMentionCount = this.state.mentionCounts.reduce((prev, curr) => {
|
||||
return prev + curr;
|
||||
}, 0);
|
||||
this.state.mentionAtActiveCounts.forEach((count) => {
|
||||
@@ -217,23 +227,26 @@ const MainPage = createReactClass({
|
||||
});
|
||||
this.props.onUnreadCountChange(allUnreadCount, allMentionCount);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
handleOnTeamFocused(index) {
|
||||
// Turn off the flag to indicate whether unread message of active channel contains at current tab.
|
||||
this.markReadAtActive(index);
|
||||
},
|
||||
}
|
||||
|
||||
handleLogin(request, username, password) {
|
||||
ipcRenderer.send('login-credentials', request, username, password);
|
||||
const loginQueue = this.state.loginQueue;
|
||||
loginQueue.shift();
|
||||
this.setState({loginQueue});
|
||||
},
|
||||
}
|
||||
|
||||
handleLoginCancel() {
|
||||
const loginQueue = this.state.loginQueue;
|
||||
loginQueue.shift();
|
||||
this.setState({loginQueue});
|
||||
},
|
||||
}
|
||||
|
||||
handleTargetURLChange(targetURL) {
|
||||
clearTimeout(this.targetURLDisappearTimeout);
|
||||
if (targetURL === '') {
|
||||
@@ -244,41 +257,42 @@ const MainPage = createReactClass({
|
||||
} else {
|
||||
this.setState({targetURL});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
addServer() {
|
||||
this.setState({
|
||||
showNewTeamModal: true,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
focusOnWebView(e) {
|
||||
if (e.target.className !== 'finder-input') {
|
||||
this.refs[`mattermostView${this.state.key}`].focusOnWebView();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
activateFinder() {
|
||||
this.setState({
|
||||
finderVisible: true,
|
||||
focusFinder: true,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
closeFinder() {
|
||||
this.setState({
|
||||
finderVisible: false,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
inputBlur() {
|
||||
this.setState({
|
||||
focusFinder: false,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
var self = this;
|
||||
var tabsRow;
|
||||
const self = this;
|
||||
let tabsRow;
|
||||
if (this.props.teams.length > 1) {
|
||||
tabsRow = (
|
||||
<Row>
|
||||
@@ -300,15 +314,15 @@ const MainPage = createReactClass({
|
||||
);
|
||||
}
|
||||
|
||||
var views = this.props.teams.map((team, index) => {
|
||||
const views = this.props.teams.map((team, index) => {
|
||||
function handleUnreadCountChange(unreadCount, mentionCount, isUnread, isMentioned) {
|
||||
self.handleUnreadCountChange(index, unreadCount, mentionCount, isUnread, isMentioned);
|
||||
}
|
||||
function handleNotificationClick() {
|
||||
self.handleSelect(index);
|
||||
}
|
||||
var id = 'mattermostView' + index;
|
||||
var isActive = self.state.key === index;
|
||||
const id = 'mattermostView' + index;
|
||||
const isActive = self.state.key === index;
|
||||
|
||||
let teamUrl = team.url;
|
||||
const deeplinkingUrl = this.props.deeplinkingUrl;
|
||||
@@ -332,21 +346,21 @@ const MainPage = createReactClass({
|
||||
active={isActive}
|
||||
/>);
|
||||
});
|
||||
var viewsRow = (
|
||||
const viewsRow = (
|
||||
<Row>
|
||||
{views}
|
||||
</Row>);
|
||||
|
||||
var request = null;
|
||||
var authServerURL = null;
|
||||
var authInfo = null;
|
||||
let request = null;
|
||||
let authServerURL = null;
|
||||
let authInfo = null;
|
||||
if (this.state.loginQueue.length !== 0) {
|
||||
request = this.state.loginQueue[0].request;
|
||||
const tmpURL = url.parse(this.state.loginQueue[0].request.url);
|
||||
authServerURL = `${tmpURL.protocol}//${tmpURL.host}`;
|
||||
authInfo = this.state.loginQueue[0].authInfo;
|
||||
}
|
||||
var modal = (
|
||||
const modal = (
|
||||
<NewTeamModal
|
||||
show={this.state.showNewTeamModal}
|
||||
onClose={() => {
|
||||
@@ -419,7 +433,18 @@ const MainPage = createReactClass({
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default MainPage;
|
||||
MainPage.propTypes = {
|
||||
onUnreadCountChange: PropTypes.func.isRequired,
|
||||
teams: PropTypes.array.isRequired,
|
||||
onTeamConfigChange: PropTypes.func.isRequired,
|
||||
initialIndex: PropTypes.number.isRequired,
|
||||
useSpellChecker: PropTypes.bool.isRequired,
|
||||
onSelectSpellCheckerLocale: PropTypes.func.isRequired,
|
||||
deeplinkingUrl: PropTypes.string,
|
||||
showAddServerButton: PropTypes.bool.isRequired,
|
||||
requestingPermission: TabBar.propTypes.requestingPermission,
|
||||
onClickPermissionDialog: PropTypes.func,
|
||||
};
|
||||
|
@@ -9,7 +9,6 @@ import url from 'url';
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import {ipcRenderer, remote, shell} from 'electron';
|
||||
|
||||
@@ -43,37 +42,38 @@ function isNetworkDrive(fileURL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const MattermostView = createReactClass({
|
||||
propTypes: {
|
||||
name: PropTypes.string,
|
||||
id: PropTypes.string,
|
||||
onTargetURLChange: PropTypes.func,
|
||||
onUnreadCountChange: PropTypes.func,
|
||||
src: PropTypes.string,
|
||||
active: PropTypes.bool,
|
||||
withTab: PropTypes.bool,
|
||||
useSpellChecker: PropTypes.bool,
|
||||
onSelectSpellCheckerLocale: PropTypes.func,
|
||||
},
|
||||
export default class MattermostView extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
this.state = {
|
||||
errorInfo: null,
|
||||
isContextMenuAdded: false,
|
||||
reloadTimeoutID: null,
|
||||
isLoaded: false,
|
||||
};
|
||||
},
|
||||
|
||||
this.handleUnreadCountChange = this.handleUnreadCountChange.bind(this);
|
||||
this.reload = this.reload.bind(this);
|
||||
this.clearCacheAndReload = this.clearCacheAndReload.bind(this);
|
||||
this.focusOnWebView = this.focusOnWebView.bind(this);
|
||||
this.canGoBack = this.canGoBack.bind(this);
|
||||
this.canGoForward = this.canGoForward.bind(this);
|
||||
this.goBack = this.goBack.bind(this);
|
||||
this.goForward = this.goForward.bind(this);
|
||||
this.getSrc = this.getSrc.bind(this);
|
||||
this.handleDeepLink = this.handleDeepLink.bind(this);
|
||||
}
|
||||
|
||||
handleUnreadCountChange(unreadCount, mentionCount, isUnread, isMentioned) {
|
||||
if (this.props.onUnreadCountChange) {
|
||||
this.props.onUnreadCountChange(unreadCount, mentionCount, isUnread, isMentioned);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
var self = this;
|
||||
var webview = findDOMNode(this.refs.webview);
|
||||
const self = this;
|
||||
const webview = findDOMNode(this.refs.webview);
|
||||
|
||||
webview.addEventListener('did-fail-load', (e) => {
|
||||
console.log(self.props.name, 'webview did-fail-load', e);
|
||||
@@ -105,8 +105,8 @@ const MattermostView = createReactClass({
|
||||
|
||||
// Open link in browserWindow. for exmaple, attached files.
|
||||
webview.addEventListener('new-window', (e) => {
|
||||
var currentURL = url.parse(webview.getURL());
|
||||
var destURL = url.parse(e.url);
|
||||
const currentURL = url.parse(webview.getURL());
|
||||
const destURL = url.parse(e.url);
|
||||
if (destURL.protocol !== 'http:' && destURL.protocol !== 'https:' && destURL.protocol !== `${scheme}:`) {
|
||||
ipcRenderer.send('confirm-protocol', destURL.protocol, e.url);
|
||||
return;
|
||||
@@ -157,15 +157,17 @@ const MattermostView = createReactClass({
|
||||
isLoaded: true,
|
||||
});
|
||||
break;
|
||||
case 'onUnreadCountChange':
|
||||
var unreadCount = event.args[0];
|
||||
var mentionCount = event.args[1];
|
||||
case 'onUnreadCountChange': {
|
||||
const unreadCount = event.args[0];
|
||||
const mentionCount = event.args[1];
|
||||
|
||||
// isUnread and isMentioned is pulse flag.
|
||||
var isUnread = event.args[2];
|
||||
var isMentioned = event.args[3];
|
||||
const isUnread = event.args[2];
|
||||
const isMentioned = event.args[3];
|
||||
self.handleUnreadCountChange(unreadCount, mentionCount, isUnread, isMentioned);
|
||||
|
||||
break;
|
||||
}
|
||||
case 'onNotificationClick':
|
||||
self.props.onNotificationClick();
|
||||
break;
|
||||
@@ -207,7 +209,7 @@ const MattermostView = createReactClass({
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
reload() {
|
||||
clearTimeout(this.state.reloadTimeoutID);
|
||||
@@ -216,19 +218,19 @@ const MattermostView = createReactClass({
|
||||
reloadTimeoutID: null,
|
||||
isLoaded: false,
|
||||
});
|
||||
var webview = findDOMNode(this.refs.webview);
|
||||
const webview = findDOMNode(this.refs.webview);
|
||||
webview.reload();
|
||||
},
|
||||
}
|
||||
|
||||
clearCacheAndReload() {
|
||||
this.setState({
|
||||
errorInfo: null,
|
||||
});
|
||||
var webContents = findDOMNode(this.refs.webview).getWebContents();
|
||||
const webContents = findDOMNode(this.refs.webview).getWebContents();
|
||||
webContents.session.clearCache(() => {
|
||||
webContents.reload();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
focusOnWebView() {
|
||||
const webview = findDOMNode(this.refs.webview);
|
||||
@@ -237,32 +239,32 @@ const MattermostView = createReactClass({
|
||||
webview.focus();
|
||||
webContents.focus();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
canGoBack() {
|
||||
const webview = findDOMNode(this.refs.webview);
|
||||
return webview.getWebContents().canGoBack();
|
||||
},
|
||||
}
|
||||
|
||||
canGoForward() {
|
||||
const webview = findDOMNode(this.refs.webview);
|
||||
return webview.getWebContents().canGoForward();
|
||||
},
|
||||
}
|
||||
|
||||
goBack() {
|
||||
const webview = findDOMNode(this.refs.webview);
|
||||
webview.getWebContents().goBack();
|
||||
},
|
||||
}
|
||||
|
||||
goForward() {
|
||||
const webview = findDOMNode(this.refs.webview);
|
||||
webview.getWebContents().goForward();
|
||||
},
|
||||
}
|
||||
|
||||
getSrc() {
|
||||
const webview = findDOMNode(this.refs.webview);
|
||||
return webview.src;
|
||||
},
|
||||
}
|
||||
|
||||
handleDeepLink(relativeUrl) {
|
||||
const webview = findDOMNode(this.refs.webview);
|
||||
@@ -272,7 +274,7 @@ const MattermostView = createReactClass({
|
||||
webview.executeJavaScript(
|
||||
'dispatchEvent(new PopStateEvent("popstate", null));'
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
const errorView = this.state.errorInfo ? (
|
||||
@@ -316,7 +318,17 @@ const MattermostView = createReactClass({
|
||||
/>
|
||||
{ loadingImage }
|
||||
</div>);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default MattermostView;
|
||||
MattermostView.propTypes = {
|
||||
name: PropTypes.string,
|
||||
id: PropTypes.string,
|
||||
onTargetURLChange: PropTypes.func,
|
||||
onUnreadCountChange: PropTypes.func,
|
||||
src: PropTypes.string,
|
||||
active: PropTypes.bool,
|
||||
withTab: PropTypes.bool,
|
||||
useSpellChecker: PropTypes.bool,
|
||||
onSelectSpellCheckerLocale: PropTypes.func,
|
||||
};
|
||||
|
@@ -1,9 +1,11 @@
|
||||
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
/* eslint-disable react/no-set-state */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {Button, Checkbox, Col, FormGroup, Grid, HelpBlock, Navbar, Radio, Row} from 'react-bootstrap';
|
||||
|
||||
@@ -25,20 +27,16 @@ function backToIndex(index) {
|
||||
const CONFIG_TYPE_SERVERS = 'servers';
|
||||
const CONFIG_TYPE_APP_OPTIONS = 'appOptions';
|
||||
|
||||
const SettingsPage = createReactClass({
|
||||
propTypes: {
|
||||
configFile: PropTypes.string,
|
||||
enableServerManagement: PropTypes.bool,
|
||||
},
|
||||
export default class SettingsPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
getInitialState() {
|
||||
var initialState;
|
||||
let initialState;
|
||||
try {
|
||||
initialState = settings.readFileSync(this.props.configFile);
|
||||
} catch (e) {
|
||||
initialState = settings.loadDefault();
|
||||
}
|
||||
|
||||
initialState.showAddTeamForm = false;
|
||||
initialState.trayWasVisible = remote.getCurrentWindow().trayWasVisible;
|
||||
if (initialState.teams.length === 0) {
|
||||
@@ -48,9 +46,29 @@ const SettingsPage = createReactClass({
|
||||
appOptions: AutoSaveIndicator.SAVING_STATE_DONE,
|
||||
servers: AutoSaveIndicator.SAVING_STATE_DONE,
|
||||
};
|
||||
this.state = initialState;
|
||||
|
||||
this.startSaveConfig = this.startSaveConfig.bind(this);
|
||||
this.didSaveConfig = this.didSaveConfig.bind(this);
|
||||
this.handleTeamsChange = this.handleTeamsChange.bind(this);
|
||||
this.saveConfig = this.saveConfig.bind(this);
|
||||
this.handleCancel = this.handleCancel.bind(this);
|
||||
this.handleChangeShowTrayIcon = this.handleChangeShowTrayIcon.bind(this);
|
||||
this.handleChangeTrayIconTheme = this.handleChangeTrayIconTheme.bind(this);
|
||||
this.handleChangeAutoStart = this.handleChangeAutoStart.bind(this);
|
||||
this.handleChangeMinimizeToTray = this.handleChangeMinimizeToTray.bind(this);
|
||||
this.toggleShowTeamForm = this.toggleShowTeamForm.bind(this);
|
||||
this.setShowTeamFormVisibility = this.setShowTeamFormVisibility.bind(this);
|
||||
this.handleFlashWindow = this.handleFlashWindow.bind(this);
|
||||
this.handleBounceIcon = this.handleBounceIcon.bind(this);
|
||||
this.handleBounceIconType = this.handleBounceIconType.bind(this);
|
||||
this.handleShowUnreadBadge = this.handleShowUnreadBadge.bind(this);
|
||||
this.handleChangeUseSpellChecker = this.handleChangeUseSpellChecker.bind(this);
|
||||
this.handleChangeEnableHardwareAcceleration = this.handleChangeEnableHardwareAcceleration.bind(this);
|
||||
this.updateTeam = this.updateTeam.bind(this);
|
||||
this.addServer = this.addServer.bind(this);
|
||||
}
|
||||
|
||||
return initialState;
|
||||
},
|
||||
componentDidMount() {
|
||||
ipcRenderer.on('add-server', () => {
|
||||
this.setState({
|
||||
@@ -60,7 +78,7 @@ const SettingsPage = createReactClass({
|
||||
ipcRenderer.on('switch-tab', (event, key) => {
|
||||
backToIndex(key);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
startSaveConfig(configType) {
|
||||
if (!this.startSaveConfigImpl) {
|
||||
@@ -83,7 +101,7 @@ const SettingsPage = createReactClass({
|
||||
savingState[configType] = AutoSaveIndicator.SAVING_STATE_SAVING;
|
||||
this.setState({savingState});
|
||||
this.startSaveConfigImpl[configType]();
|
||||
},
|
||||
}
|
||||
|
||||
didSaveConfig(configType) {
|
||||
if (!this.didSaveConfigImpl) {
|
||||
@@ -97,7 +115,7 @@ const SettingsPage = createReactClass({
|
||||
}, 2000);
|
||||
}
|
||||
this.didSaveConfigImpl[configType]();
|
||||
},
|
||||
}
|
||||
|
||||
handleTeamsChange(teams) {
|
||||
this.setState({
|
||||
@@ -108,10 +126,10 @@ const SettingsPage = createReactClass({
|
||||
this.setState({showAddTeamForm: true});
|
||||
}
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_SERVERS);
|
||||
},
|
||||
}
|
||||
|
||||
saveConfig(callback) {
|
||||
var config = {
|
||||
const config = {
|
||||
teams: this.state.teams,
|
||||
showTrayIcon: this.state.showTrayIcon,
|
||||
trayIconTheme: this.state.trayIconTheme,
|
||||
@@ -138,13 +156,14 @@ const SettingsPage = createReactClass({
|
||||
ipcRenderer.send('update-config');
|
||||
callback();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
handleCancel() {
|
||||
backToIndex();
|
||||
},
|
||||
}
|
||||
|
||||
handleChangeShowTrayIcon() {
|
||||
var shouldShowTrayIcon = !this.refs.showTrayIcon.props.checked;
|
||||
const shouldShowTrayIcon = !this.refs.showTrayIcon.props.checked;
|
||||
this.setState({
|
||||
showTrayIcon: shouldShowTrayIcon,
|
||||
});
|
||||
@@ -156,19 +175,22 @@ const SettingsPage = createReactClass({
|
||||
}
|
||||
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_APP_OPTIONS);
|
||||
},
|
||||
}
|
||||
|
||||
handleChangeTrayIconTheme() {
|
||||
this.setState({
|
||||
trayIconTheme: ReactDOM.findDOMNode(this.refs.trayIconTheme).value,
|
||||
});
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_APP_OPTIONS);
|
||||
},
|
||||
}
|
||||
|
||||
handleChangeAutoStart() {
|
||||
this.setState({
|
||||
autostart: !this.refs.autostart.props.checked,
|
||||
});
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_APP_OPTIONS);
|
||||
},
|
||||
}
|
||||
|
||||
handleChangeMinimizeToTray() {
|
||||
const shouldMinimizeToTray = this.state.showTrayIcon && !this.refs.minimizeToTray.props.checked;
|
||||
|
||||
@@ -176,18 +198,21 @@ const SettingsPage = createReactClass({
|
||||
minimizeToTray: shouldMinimizeToTray,
|
||||
});
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_APP_OPTIONS);
|
||||
},
|
||||
}
|
||||
|
||||
toggleShowTeamForm() {
|
||||
this.setState({
|
||||
showAddTeamForm: !this.state.showAddTeamForm,
|
||||
});
|
||||
document.activeElement.blur();
|
||||
},
|
||||
}
|
||||
|
||||
setShowTeamFormVisibility(val) {
|
||||
this.setState({
|
||||
showAddTeamForm: val,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
handleFlashWindow() {
|
||||
this.setState({
|
||||
notifications: {
|
||||
@@ -196,7 +221,8 @@ const SettingsPage = createReactClass({
|
||||
},
|
||||
});
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_APP_OPTIONS);
|
||||
},
|
||||
}
|
||||
|
||||
handleBounceIcon() {
|
||||
this.setState({
|
||||
notifications: {
|
||||
@@ -205,7 +231,8 @@ const SettingsPage = createReactClass({
|
||||
},
|
||||
});
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_APP_OPTIONS);
|
||||
},
|
||||
}
|
||||
|
||||
handleBounceIconType(event) {
|
||||
this.setState({
|
||||
notifications: {
|
||||
@@ -214,45 +241,46 @@ const SettingsPage = createReactClass({
|
||||
},
|
||||
});
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_APP_OPTIONS);
|
||||
},
|
||||
}
|
||||
|
||||
handleShowUnreadBadge() {
|
||||
this.setState({
|
||||
showUnreadBadge: !this.refs.showUnreadBadge.props.checked,
|
||||
});
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_APP_OPTIONS);
|
||||
},
|
||||
}
|
||||
|
||||
handleChangeUseSpellChecker() {
|
||||
this.setState({
|
||||
useSpellChecker: !this.refs.useSpellChecker.props.checked,
|
||||
});
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_APP_OPTIONS);
|
||||
},
|
||||
}
|
||||
|
||||
handleChangeEnableHardwareAcceleration() {
|
||||
this.setState({
|
||||
enableHardwareAcceleration: !this.refs.enableHardwareAcceleration.props.checked,
|
||||
});
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_APP_OPTIONS);
|
||||
},
|
||||
}
|
||||
|
||||
updateTeam(index, newData) {
|
||||
var teams = this.state.teams;
|
||||
const teams = this.state.teams;
|
||||
teams[index] = newData;
|
||||
this.setState({
|
||||
teams,
|
||||
});
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_SERVERS);
|
||||
},
|
||||
}
|
||||
|
||||
addServer(team) {
|
||||
var teams = this.state.teams;
|
||||
const teams = this.state.teams;
|
||||
teams.push(team);
|
||||
this.setState({
|
||||
teams,
|
||||
});
|
||||
setImmediate(this.startSaveConfig, CONFIG_TYPE_SERVERS);
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
const settingsPage = {
|
||||
@@ -290,7 +318,7 @@ const SettingsPage = createReactClass({
|
||||
},
|
||||
};
|
||||
|
||||
var teamsRow = (
|
||||
const teamsRow = (
|
||||
<Row>
|
||||
<Col md={12}>
|
||||
<TeamList
|
||||
@@ -310,7 +338,7 @@ const SettingsPage = createReactClass({
|
||||
</Row>
|
||||
);
|
||||
|
||||
var serversRow = (
|
||||
const serversRow = (
|
||||
<Row>
|
||||
<Col
|
||||
md={10}
|
||||
@@ -341,7 +369,7 @@ const SettingsPage = createReactClass({
|
||||
</Row>
|
||||
);
|
||||
|
||||
var srvMgmt;
|
||||
let srvMgmt;
|
||||
if (this.props.enableServerManagement === true) {
|
||||
srvMgmt = (
|
||||
<div>
|
||||
@@ -352,7 +380,7 @@ const SettingsPage = createReactClass({
|
||||
);
|
||||
}
|
||||
|
||||
var options = [];
|
||||
const options = [];
|
||||
|
||||
// MacOS has an option in the Dock, to set the app to autostart, so we choose to not support this option for OSX
|
||||
if (process.platform === 'win32' || process.platform === 'linux') {
|
||||
@@ -383,7 +411,7 @@ const SettingsPage = createReactClass({
|
||||
{'Check spelling'}
|
||||
<HelpBlock>
|
||||
{'Highlight misspelled words in your messages.'}
|
||||
{' Available for English, French, German, Spanish, and Dutch.'}
|
||||
{' Available for English, French, German, Portuguese, Spanish, and Dutch.'}
|
||||
</HelpBlock>
|
||||
</Checkbox>);
|
||||
|
||||
@@ -542,7 +570,7 @@ const SettingsPage = createReactClass({
|
||||
</Checkbox>
|
||||
);
|
||||
|
||||
var optionsRow = (options.length > 0) ? (
|
||||
const optionsRow = (options.length > 0) ? (
|
||||
<Row>
|
||||
<Col md={12}>
|
||||
<h2 style={settingsPage.sectionHeading}>{'App Options'}</h2>
|
||||
@@ -591,7 +619,10 @@ const SettingsPage = createReactClass({
|
||||
</Grid>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default SettingsPage;
|
||||
SettingsPage.propTypes = {
|
||||
configFile: PropTypes.string,
|
||||
enableServerManagement: PropTypes.bool,
|
||||
};
|
||||
|
@@ -3,27 +3,17 @@
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
import {ListGroup} from 'react-bootstrap';
|
||||
|
||||
import TeamListItem from './TeamListItem.jsx';
|
||||
import NewTeamModal from './NewTeamModal.jsx';
|
||||
import RemoveServerModal from './RemoveServerModal.jsx';
|
||||
|
||||
const TeamList = createReactClass({
|
||||
propTypes: {
|
||||
onTeamsChange: PropTypes.func,
|
||||
showAddTeamForm: PropTypes.bool,
|
||||
teams: PropTypes.array,
|
||||
addServer: PropTypes.func,
|
||||
updateTeam: PropTypes.func,
|
||||
toggleAddTeamForm: PropTypes.func,
|
||||
setAddTeamFormVisibility: PropTypes.func,
|
||||
onTeamClick: PropTypes.func,
|
||||
},
|
||||
export default class TeamList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
this.state = {
|
||||
showEditTeamForm: false,
|
||||
indexToRemoveServer: -1,
|
||||
team: {
|
||||
@@ -32,15 +22,23 @@ const TeamList = createReactClass({
|
||||
index: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
this.handleTeamRemove = this.handleTeamRemove.bind(this);
|
||||
this.handleTeamAdd = this.handleTeamAdd.bind(this);
|
||||
this.handleTeamEditing = this.handleTeamEditing.bind(this);
|
||||
this.openServerRemoveModal = this.openServerRemoveModal.bind(this);
|
||||
this.closeServerRemoveModal = this.closeServerRemoveModal.bind(this);
|
||||
}
|
||||
|
||||
handleTeamRemove(index) {
|
||||
console.log(index);
|
||||
var teams = this.props.teams;
|
||||
const teams = this.props.teams;
|
||||
teams.splice(index, 1);
|
||||
this.props.onTeamsChange(teams);
|
||||
},
|
||||
}
|
||||
|
||||
handleTeamAdd(team) {
|
||||
var teams = this.props.teams;
|
||||
const teams = this.props.teams;
|
||||
|
||||
// check if team already exists and then change existing team or add new one
|
||||
if ((typeof team.index !== 'undefined') && teams[team.index]) {
|
||||
@@ -60,7 +58,8 @@ const TeamList = createReactClass({
|
||||
});
|
||||
|
||||
this.props.onTeamsChange(teams);
|
||||
},
|
||||
}
|
||||
|
||||
handleTeamEditing(teamName, teamUrl, teamIndex) {
|
||||
this.setState({
|
||||
showEditTeamForm: true,
|
||||
@@ -70,19 +69,19 @@ const TeamList = createReactClass({
|
||||
index: teamIndex,
|
||||
},
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
openServerRemoveModal(indexForServer) {
|
||||
this.setState({indexToRemoveServer: indexForServer});
|
||||
},
|
||||
}
|
||||
|
||||
closeServerRemoveModal() {
|
||||
this.setState({indexToRemoveServer: -1});
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
var self = this;
|
||||
var teamNodes = this.props.teams.map((team, i) => {
|
||||
const self = this;
|
||||
const teamNodes = this.props.teams.map((team, i) => {
|
||||
function handleTeamRemove() {
|
||||
document.activeElement.blur();
|
||||
self.openServerRemoveModal(i);
|
||||
@@ -110,7 +109,7 @@ const TeamList = createReactClass({
|
||||
);
|
||||
});
|
||||
|
||||
var addServerForm = (
|
||||
const addServerForm = (
|
||||
<NewTeamModal
|
||||
show={this.props.showAddTeamForm || this.state.showEditTeamForm}
|
||||
editMode={this.state.showEditTeamForm}
|
||||
@@ -126,7 +125,7 @@ const TeamList = createReactClass({
|
||||
this.props.setAddTeamFormVisibility(false);
|
||||
}}
|
||||
onSave={(newTeam) => {
|
||||
var teamData = {
|
||||
const teamData = {
|
||||
name: newTeam.name,
|
||||
url: newTeam.url,
|
||||
};
|
||||
@@ -171,7 +170,16 @@ const TeamList = createReactClass({
|
||||
{ removeServerModal}
|
||||
</ListGroup>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default TeamList;
|
||||
TeamList.propTypes = {
|
||||
onTeamsChange: PropTypes.func,
|
||||
showAddTeamForm: PropTypes.bool,
|
||||
teams: PropTypes.array,
|
||||
addServer: PropTypes.func,
|
||||
updateTeam: PropTypes.func,
|
||||
toggleAddTeamForm: PropTypes.func,
|
||||
setAddTeamFormVisibility: PropTypes.func,
|
||||
onTeamClick: PropTypes.func,
|
||||
};
|
||||
|
@@ -22,7 +22,7 @@ function getSuggestionsMenus(win, suggestions) {
|
||||
function getSpellCheckerLocaleMenus(onSelectSpellCheckerLocale) {
|
||||
const currentLocale = ipcRenderer.sendSync('get-spellchecker-locale');
|
||||
const locales = [
|
||||
{language: 'English', locale: 'en-US'},
|
||||
{language: 'English (US)', locale: 'en-US'},
|
||||
{language: 'French', locale: 'fr-FR'},
|
||||
{language: 'German', locale: 'de-DE'},
|
||||
{language: 'Spanish', locale: 'es-ES'},
|
||||
|
@@ -51,7 +51,7 @@ window.addEventListener('load', () => {
|
||||
});
|
||||
|
||||
function hasClass(element, className) {
|
||||
var rclass = /[\t\r\n\f]/g;
|
||||
const rclass = /[\t\r\n\f]/g;
|
||||
if ((' ' + element.className + ' ').replace(rclass, ' ').indexOf(className) > -1) {
|
||||
return true;
|
||||
}
|
||||
@@ -77,7 +77,7 @@ function getUnreadCount() {
|
||||
|
||||
// unreadCount in sidebar
|
||||
// Note: the active channel doesn't have '.unread-title'.
|
||||
var unreadCount = document.getElementsByClassName('unread-title').length;
|
||||
let unreadCount = document.getElementsByClassName('unread-title').length;
|
||||
|
||||
// unreadCount in team sidebar
|
||||
const teamSideBar = document.getElementsByClassName('team-sidebar'); // team-sidebar doesn't have id
|
||||
@@ -86,30 +86,30 @@ function getUnreadCount() {
|
||||
}
|
||||
|
||||
// mentionCount in sidebar
|
||||
var elem = document.getElementsByClassName('badge');
|
||||
var mentionCount = 0;
|
||||
for (var i = 0; i < elem.length; i++) {
|
||||
const elem = document.getElementsByClassName('badge');
|
||||
let mentionCount = 0;
|
||||
for (let i = 0; i < elem.length; i++) {
|
||||
if (isElementVisible(elem[i]) && !hasClass(elem[i], 'badge-notify')) {
|
||||
mentionCount += Number(elem[i].innerHTML);
|
||||
}
|
||||
}
|
||||
|
||||
var postAttrName = 'data-reactid';
|
||||
var lastPostElem = document.querySelector('div[' + postAttrName + '="' + this.lastCheckedPostId + '"]');
|
||||
var isUnread = false;
|
||||
var isMentioned = false;
|
||||
const postAttrName = 'data-reactid';
|
||||
const lastPostElem = document.querySelector('div[' + postAttrName + '="' + this.lastCheckedPostId + '"]');
|
||||
let isUnread = false;
|
||||
let isMentioned = false;
|
||||
if (lastPostElem === null || !isElementVisible(lastPostElem)) {
|
||||
// When load channel or change channel, this.lastCheckedPostId is invalid.
|
||||
// So we get latest post and save lastCheckedPostId.
|
||||
|
||||
// find active post-list.
|
||||
var postLists = document.querySelectorAll('div.post-list__content');
|
||||
const postLists = document.querySelectorAll('div.post-list__content');
|
||||
if (postLists.length === 0) {
|
||||
setTimeout(getUnreadCount, UNREAD_COUNT_INTERVAL);
|
||||
return;
|
||||
}
|
||||
var post = null;
|
||||
for (var j = 0; j < postLists.length; j++) {
|
||||
let post = null;
|
||||
for (let j = 0; j < postLists.length; j++) {
|
||||
if (isElementVisible(postLists[j])) {
|
||||
post = postLists[j].children[0];
|
||||
}
|
||||
@@ -130,19 +130,19 @@ function getUnreadCount() {
|
||||
post = post.nextSibling;
|
||||
}
|
||||
} else if (lastPostElem !== null) {
|
||||
var newPostElem = lastPostElem.nextSibling;
|
||||
let newPostElem = lastPostElem.nextSibling;
|
||||
while (newPostElem) {
|
||||
this.lastCheckedPostId = newPostElem.getAttribute(postAttrName);
|
||||
isUnread = true;
|
||||
var activeChannel = document.querySelector('.active .sidebar-channel');
|
||||
var closeButton = activeChannel.getElementsByClassName('btn-close');
|
||||
const activeChannel = document.querySelector('.active .sidebar-channel');
|
||||
const closeButton = activeChannel.getElementsByClassName('btn-close');
|
||||
if (closeButton.length === 1 && closeButton[0].getAttribute('aria-describedby') === 'remove-dm-tooltip') {
|
||||
// If active channel is DM, all posts is treated as menion.
|
||||
isMentioned = true;
|
||||
break;
|
||||
} else {
|
||||
// If active channel is public/private channel, only mentioned post is treated as mention.
|
||||
var highlight = newPostElem.getElementsByClassName('mention-highlight');
|
||||
const highlight = newPostElem.getElementsByClassName('mention-highlight');
|
||||
if (highlight.length !== 0 && isElementVisible(highlight[0])) {
|
||||
isMentioned = true;
|
||||
break;
|
||||
|
@@ -20,7 +20,7 @@ function upgradeV0toV1(configV0) {
|
||||
}
|
||||
|
||||
export default function upgradeToLatest(config) {
|
||||
var configVersion = config.version ? config.version : 0;
|
||||
const configVersion = config.version ? config.version : 0;
|
||||
switch (configVersion) {
|
||||
case 0:
|
||||
return upgradeToLatest(upgradeV0toV1(config));
|
||||
|
@@ -4,7 +4,7 @@
|
||||
'use strict';
|
||||
|
||||
import os from 'os';
|
||||
var releaseSplit = os.release().split('.');
|
||||
const releaseSplit = os.release().split('.');
|
||||
|
||||
export default {
|
||||
major: parseInt(releaseSplit[0], 10),
|
||||
|
@@ -45,7 +45,7 @@ export default {
|
||||
if (config.version !== defaultPreferences.version) {
|
||||
throw new Error('version ' + config.version + ' is not equal to ' + defaultPreferences.version);
|
||||
}
|
||||
var data = JSON.stringify(config, null, ' ');
|
||||
const data = JSON.stringify(config, null, ' ');
|
||||
fs.writeFile(configFile, data, 'utf8', callback);
|
||||
},
|
||||
|
||||
@@ -59,7 +59,7 @@ export default {
|
||||
fs.mkdirSync(dir);
|
||||
}
|
||||
|
||||
var data = JSON.stringify(config, null, ' ');
|
||||
const data = JSON.stringify(config, null, ' ');
|
||||
fs.writeFileSync(configFile, data, 'utf8');
|
||||
},
|
||||
|
||||
|
21
src/main.js
21
src/main.js
@@ -51,6 +51,7 @@ import PermissionManager from './main/PermissionManager';
|
||||
import permissionRequestHandler from './main/permissionRequestHandler';
|
||||
import AppStateManager from './main/AppStateManager';
|
||||
import initCookieManager from './main/cookieManager';
|
||||
import {shouldBeHiddenOnStartup} from './main/utils';
|
||||
|
||||
import SpellChecker from './main/SpellChecker';
|
||||
|
||||
@@ -58,7 +59,7 @@ const assetsDir = path.resolve(app.getAppPath(), 'assets');
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
var mainWindow = null;
|
||||
let mainWindow = null;
|
||||
let spellChecker = null;
|
||||
let deeplinkingUrl = null;
|
||||
let scheme = null;
|
||||
@@ -66,11 +67,7 @@ let appState = null;
|
||||
let permissionManager = null;
|
||||
|
||||
const argv = parseArgv(process.argv.slice(1));
|
||||
|
||||
var hideOnStartup;
|
||||
if (argv.hidden) {
|
||||
hideOnStartup = true;
|
||||
}
|
||||
const hideOnStartup = shouldBeHiddenOnStartup(argv);
|
||||
|
||||
if (argv['data-dir']) {
|
||||
app.setPath('userData', path.resolve(argv['data-dir']));
|
||||
@@ -78,7 +75,7 @@ if (argv['data-dir']) {
|
||||
|
||||
global.isDev = isDev && !argv.disableDevMode;
|
||||
|
||||
var config = {};
|
||||
let config = {};
|
||||
try {
|
||||
const configFile = app.getPath('userData') + '/config.json';
|
||||
config = settings.readFileSync(configFile);
|
||||
@@ -130,7 +127,7 @@ function switchMenuIconImages(icons, isDarkMode) {
|
||||
}
|
||||
}
|
||||
|
||||
var trayIcon = null;
|
||||
let trayIcon = null;
|
||||
const trayImages = (() => {
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
@@ -306,7 +303,7 @@ app.on('certificate-error', (event, webContents, url, error, certificate, callba
|
||||
event.preventDefault();
|
||||
callback(true);
|
||||
} else {
|
||||
var detail = `URL: ${url}\nError: ${error}`;
|
||||
let detail = `URL: ${url}\nError: ${error}`;
|
||||
if (certificateStore.isExisting(url)) {
|
||||
detail = 'Certificate is different from previous one.\n\n' + detail;
|
||||
}
|
||||
@@ -556,8 +553,8 @@ app.on('ready', () => {
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
session.defaultSession.on('will-download', (event, item) => {
|
||||
var filename = item.getFilename();
|
||||
var savePath = dialog.showSaveDialog({
|
||||
const filename = item.getFilename();
|
||||
const savePath = dialog.showSaveDialog({
|
||||
title: filename,
|
||||
defaultPath: os.homedir() + '/Downloads/' + filename,
|
||||
});
|
||||
@@ -572,7 +569,7 @@ app.on('ready', () => {
|
||||
|
||||
// Set application menu
|
||||
ipcMain.on('update-menu', (event, configData) => {
|
||||
var aMenu = appMenu.createMenu(mainWindow, configData, global.isDev);
|
||||
const aMenu = appMenu.createMenu(mainWindow, configData, global.isDev);
|
||||
Menu.setApplicationMenu(aMenu);
|
||||
|
||||
// set up context menu for tray icon
|
||||
|
@@ -9,7 +9,7 @@ import fs from 'fs';
|
||||
import {app, dialog, ipcMain, shell} from 'electron';
|
||||
|
||||
const allowedProtocolFile = path.resolve(app.getPath('userData'), 'allowedProtocols.json');
|
||||
var allowedProtocols = [];
|
||||
let allowedProtocols = [];
|
||||
|
||||
function init(mainWindow) {
|
||||
fs.readFile(allowedProtocolFile, 'utf-8', (err, data) => {
|
||||
|
@@ -56,7 +56,7 @@ CertificateStore.prototype.isExisting = function isExisting(targetURL) {
|
||||
};
|
||||
|
||||
CertificateStore.prototype.isTrusted = function isTrusted(targetURL, certificate) {
|
||||
var host = getHost(targetURL);
|
||||
const host = getHost(targetURL);
|
||||
if (!this.isExisting(targetURL)) {
|
||||
return false;
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import path from 'path';
|
||||
import {app, BrowserWindow} from 'electron';
|
||||
|
||||
function saveWindowState(file, window) {
|
||||
var windowState = window.getBounds();
|
||||
const windowState = window.getBounds();
|
||||
windowState.maximized = window.isMaximized();
|
||||
windowState.fullscreen = window.isFullScreen();
|
||||
try {
|
||||
@@ -26,7 +26,7 @@ function createMainWindow(config, options) {
|
||||
|
||||
// Create the browser window.
|
||||
const boundsInfoPath = path.join(app.getPath('userData'), 'bounds-info.json');
|
||||
var windowOptions;
|
||||
let windowOptions;
|
||||
try {
|
||||
windowOptions = JSON.parse(fs.readFileSync(boundsInfoPath, 'utf-8'));
|
||||
} catch (e) {
|
||||
|
@@ -15,11 +15,11 @@ function createTemplate(mainWindow, config, isDev) {
|
||||
type: 'separator',
|
||||
};
|
||||
|
||||
var appName = app.getName();
|
||||
var firstMenuName = (process.platform === 'darwin') ? appName : 'File';
|
||||
var template = [];
|
||||
const appName = app.getName();
|
||||
const firstMenuName = (process.platform === 'darwin') ? appName : 'File';
|
||||
const template = [];
|
||||
|
||||
var platformAppMenu = process.platform === 'darwin' ? [{
|
||||
let platformAppMenu = process.platform === 'darwin' ? [{
|
||||
label: 'About ' + appName,
|
||||
role: 'about',
|
||||
click() {
|
||||
@@ -217,7 +217,7 @@ function createTemplate(mainWindow, config, isDev) {
|
||||
}],
|
||||
};
|
||||
template.push(windowMenu);
|
||||
var submenu = [];
|
||||
const submenu = [];
|
||||
if (buildConfig.helpLink) {
|
||||
submenu.push({
|
||||
label: 'Learn More...',
|
||||
|
@@ -10,7 +10,7 @@ import settings from '../../common/settings';
|
||||
function createTemplate(mainWindow, config, isDev) {
|
||||
const settingsURL = isDev ? 'http://localhost:8080/browser/settings.html' : `file://${app.getAppPath()}/browser/settings.html`;
|
||||
const teams = settings.mergeDefaultTeams(config.teams);
|
||||
var template = [
|
||||
const template = [
|
||||
...teams.slice(0, 9).map((team, i) => {
|
||||
return {
|
||||
label: team.name,
|
||||
|
17
src/main/utils.js
Normal file
17
src/main/utils.js
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {app} from 'electron';
|
||||
|
||||
export function shouldBeHiddenOnStartup(parsedArgv) {
|
||||
if (parsedArgv.hidden) {
|
||||
return true;
|
||||
}
|
||||
if (process.platform === 'darwin') {
|
||||
if (app.getLoginItemSettings().wasOpenedAsHidden) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
@@ -11,7 +11,6 @@
|
||||
"dependencies": {
|
||||
"auto-launch": "^5.0.5",
|
||||
"bootstrap": "^3.3.7",
|
||||
"create-react-class": "^15.6.3",
|
||||
"electron-context-menu": "0.9.0",
|
||||
"electron-devtools-installer": "^2.2.4",
|
||||
"electron-is-dev": "^0.3.0",
|
||||
|
@@ -107,14 +107,6 @@ core-js@^2.4.0:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b"
|
||||
|
||||
create-react-class@^15.6.3:
|
||||
version "15.6.3"
|
||||
resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036"
|
||||
dependencies:
|
||||
fbjs "^0.8.9"
|
||||
loose-envify "^1.3.1"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
cross-unzip@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/cross-unzip/-/cross-unzip-0.0.2.tgz#5183bc47a09559befcf98cc4657964999359372f"
|
||||
|
@@ -3726,9 +3726,9 @@ electron-to-chromium@^1.3.47:
|
||||
version "1.3.48"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz#d3b0d8593814044e092ece2108fc3ac9aea4b900"
|
||||
|
||||
electron@2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-2.0.2.tgz#b77e05f83419cc5ec921a2d21f35b55e4bfc3d68"
|
||||
electron@2.0.8:
|
||||
version "2.0.8"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-2.0.8.tgz#6ec7113b356e09cc9899797e0d41ebff8163e962"
|
||||
dependencies:
|
||||
"@types/node" "^8.0.24"
|
||||
electron-download "^3.0.1"
|
||||
|
Reference in New Issue
Block a user