[MM-33828] Define CSP for all BrowserWindows, enable contextIsolation for main/settings window, other fixes (#1517)
* [MM-33828] Added CSP to renderer process pages and turned off remote module when not needed * Turn on contextIsolation and turn off nodeIntegration for main and settings windows * Check for details.reason instead of object
This commit is contained in:
28
src/main/preload/mainWindow.js
Normal file
28
src/main/preload/mainWindow.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import os from 'os';
|
||||||
|
import {ipcRenderer, contextBridge} from 'electron';
|
||||||
|
|
||||||
|
contextBridge.exposeInMainWorld('ipcRenderer', {
|
||||||
|
send: ipcRenderer.send,
|
||||||
|
on: (channel, listener) => ipcRenderer.on(channel, (_, ...args) => listener(null, ...args)),
|
||||||
|
invoke: ipcRenderer.invoke,
|
||||||
|
});
|
||||||
|
|
||||||
|
contextBridge.exposeInMainWorld('os', {
|
||||||
|
isWindows10: os.platform() === 'win32' && os.release().startsWith('10'),
|
||||||
|
});
|
||||||
|
|
||||||
|
contextBridge.exposeInMainWorld('process', {
|
||||||
|
platform: process.platform,
|
||||||
|
env: process.env,
|
||||||
|
});
|
||||||
|
|
||||||
|
contextBridge.exposeInMainWorld('timers', {
|
||||||
|
setImmediate,
|
||||||
|
});
|
||||||
|
|
@@ -43,7 +43,7 @@ export class MattermostView extends EventEmitter {
|
|||||||
`version=${app.version}`,
|
`version=${app.version}`,
|
||||||
`appName=${app.name}`,
|
`appName=${app.name}`,
|
||||||
],
|
],
|
||||||
enableRemoteModule: true,
|
enableRemoteModule: process.env.NODE_ENV === 'test',
|
||||||
nodeIntegration: process.env.NODE_ENV === 'test',
|
nodeIntegration: process.env.NODE_ENV === 'test',
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
|
@@ -242,8 +242,8 @@ export const addWebContentsEventListeners = (mmview, getServersFunction) => {
|
|||||||
|
|
||||||
listeners[contents.id] = removeListeners;
|
listeners[contents.id] = removeListeners;
|
||||||
contents.once('render-process-gone', (event, details) => {
|
contents.once('render-process-gone', (event, details) => {
|
||||||
if (details !== 'clean-exit') {
|
if (details.reason !== 'clean-exit') {
|
||||||
log.error(`Renderer process for a webcontent is no longer available: ${details}`);
|
log.error('Renderer process for a webcontent is no longer available:', details.reason);
|
||||||
}
|
}
|
||||||
removeListeners();
|
removeListeners();
|
||||||
});
|
});
|
||||||
|
@@ -13,7 +13,7 @@ import {SELECT_NEXT_TAB, SELECT_PREVIOUS_TAB} from 'common/communication';
|
|||||||
|
|
||||||
import * as Validator from '../Validator';
|
import * as Validator from '../Validator';
|
||||||
import contextMenu from '../contextMenu';
|
import contextMenu from '../contextMenu';
|
||||||
import {getLocalURLString} from '../utils';
|
import {getLocalPreload, getLocalURLString} from '../utils';
|
||||||
|
|
||||||
function saveWindowState(file, window) {
|
function saveWindowState(file, window) {
|
||||||
const windowState = window.getBounds();
|
const windowState = window.getBounds();
|
||||||
@@ -37,6 +37,7 @@ function createMainWindow(config, options) {
|
|||||||
const minimumWindowHeight = 240;
|
const minimumWindowHeight = 240;
|
||||||
|
|
||||||
// Create the browser window.
|
// Create the browser window.
|
||||||
|
const preload = getLocalPreload('mainWindow.js');
|
||||||
const boundsInfoPath = path.join(app.getPath('userData'), 'bounds-info.json');
|
const boundsInfoPath = path.join(app.getPath('userData'), 'bounds-info.json');
|
||||||
let windowOptions;
|
let windowOptions;
|
||||||
try {
|
try {
|
||||||
@@ -70,9 +71,10 @@ function createMainWindow(config, options) {
|
|||||||
trafficLightPosition: {x: 12, y: 24},
|
trafficLightPosition: {x: 12, y: 24},
|
||||||
backgroundColor: '#fff', // prevents blurry text: https://electronjs.org/docs/faq#the-font-looks-blurry-what-is-this-and-what-can-i-do
|
backgroundColor: '#fff', // prevents blurry text: https://electronjs.org/docs/faq#the-font-looks-blurry-what-is-this-and-what-can-i-do
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: process.env.NODE_ENV === 'test',
|
||||||
contextIsolation: false,
|
contextIsolation: process.env.NODE_ENV !== 'test',
|
||||||
disableBlinkFeatures: 'Auxclick',
|
disableBlinkFeatures: 'Auxclick',
|
||||||
|
preload,
|
||||||
spellcheck,
|
spellcheck,
|
||||||
enableRemoteModule: process.env.NODE_ENV === 'test',
|
enableRemoteModule: process.env.NODE_ENV === 'test',
|
||||||
},
|
},
|
||||||
|
@@ -4,17 +4,19 @@
|
|||||||
import {BrowserWindow} from 'electron';
|
import {BrowserWindow} from 'electron';
|
||||||
import log from 'electron-log';
|
import log from 'electron-log';
|
||||||
|
|
||||||
import {getLocalURLString} from '../utils';
|
import {getLocalPreload, getLocalURLString} from '../utils';
|
||||||
|
|
||||||
export function createSettingsWindow(mainWindow, config, withDevTools) {
|
export function createSettingsWindow(mainWindow, config, withDevTools) {
|
||||||
|
const preload = getLocalPreload('mainWindow.js');
|
||||||
const spellcheck = (typeof config.useSpellChecker === 'undefined' ? true : config.useSpellChecker);
|
const spellcheck = (typeof config.useSpellChecker === 'undefined' ? true : config.useSpellChecker);
|
||||||
const settingsWindow = new BrowserWindow({
|
const settingsWindow = new BrowserWindow({
|
||||||
...config.data,
|
...config.data,
|
||||||
parent: mainWindow,
|
parent: mainWindow,
|
||||||
title: 'Desktop App Settings',
|
title: 'Desktop App Settings',
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: false,
|
||||||
contextIsolation: false,
|
contextIsolation: true,
|
||||||
|
preload,
|
||||||
spellcheck,
|
spellcheck,
|
||||||
enableRemoteModule: process.env.NODE_ENV === 'test',
|
enableRemoteModule: process.env.NODE_ENV === 'test',
|
||||||
}});
|
}});
|
||||||
|
@@ -2,15 +2,11 @@
|
|||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
// Copyright (c) 2015-2016 Yuya Ochiai
|
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||||
|
|
||||||
import os from 'os';
|
|
||||||
|
|
||||||
import React, {Fragment} from 'react';
|
import React, {Fragment} from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {Grid, Row} from 'react-bootstrap';
|
import {Grid, Row} from 'react-bootstrap';
|
||||||
import DotsVerticalIcon from 'mdi-react/DotsVerticalIcon';
|
import DotsVerticalIcon from 'mdi-react/DotsVerticalIcon';
|
||||||
|
|
||||||
import {ipcRenderer} from 'electron';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FOCUS_BROWSERVIEW,
|
FOCUS_BROWSERVIEW,
|
||||||
MAXIMIZE_CHANGE,
|
MAXIMIZE_CHANGE,
|
||||||
@@ -87,7 +83,7 @@ export default class MainPage extends React.PureComponent {
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
// set page on retry
|
// set page on retry
|
||||||
ipcRenderer.on(LOAD_RETRY, (_, server, retry, err, loadUrl) => {
|
window.ipcRenderer.on(LOAD_RETRY, (_, server, retry, err, loadUrl) => {
|
||||||
console.log(`${server}: failed to load ${err}, but retrying`);
|
console.log(`${server}: failed to load ${err}, but retrying`);
|
||||||
const status = this.state.tabStatus;
|
const status = this.state.tabStatus;
|
||||||
const statusValue = {
|
const statusValue = {
|
||||||
@@ -102,13 +98,13 @@ export default class MainPage extends React.PureComponent {
|
|||||||
this.setState({tabStatus: status});
|
this.setState({tabStatus: status});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(LOAD_SUCCESS, (_, server) => {
|
window.ipcRenderer.on(LOAD_SUCCESS, (_, server) => {
|
||||||
const status = this.state.tabStatus;
|
const status = this.state.tabStatus;
|
||||||
status.set(server, {status: DONE});
|
status.set(server, {status: DONE});
|
||||||
this.setState({tabStatus: status});
|
this.setState({tabStatus: status});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(LOAD_FAILED, (_, server, err, loadUrl) => {
|
window.ipcRenderer.on(LOAD_FAILED, (_, server, err, loadUrl) => {
|
||||||
console.log(`${server}: failed to load ${err}`);
|
console.log(`${server}: failed to load ${err}`);
|
||||||
const status = this.state.tabStatus;
|
const status = this.state.tabStatus;
|
||||||
const statusValue = {
|
const statusValue = {
|
||||||
@@ -122,16 +118,16 @@ export default class MainPage extends React.PureComponent {
|
|||||||
this.setState({tabStatus: status});
|
this.setState({tabStatus: status});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(DARK_MODE_CHANGE, (_, darkMode) => {
|
window.ipcRenderer.on(DARK_MODE_CHANGE, (_, darkMode) => {
|
||||||
this.setState({darkMode});
|
this.setState({darkMode});
|
||||||
});
|
});
|
||||||
|
|
||||||
// can't switch tabs sequentially for some reason...
|
// can't switch tabs sequentially for some reason...
|
||||||
ipcRenderer.on(SET_SERVER_KEY, (event, key) => {
|
window.ipcRenderer.on(SET_SERVER_KEY, (event, key) => {
|
||||||
const nextIndex = this.props.teams.findIndex((team) => team.order === key);
|
const nextIndex = this.props.teams.findIndex((team) => team.order === key);
|
||||||
this.handleSetServerKey(nextIndex);
|
this.handleSetServerKey(nextIndex);
|
||||||
});
|
});
|
||||||
ipcRenderer.on(SELECT_NEXT_TAB, () => {
|
window.ipcRenderer.on(SELECT_NEXT_TAB, () => {
|
||||||
const currentOrder = this.props.teams[this.state.key].order;
|
const currentOrder = this.props.teams[this.state.key].order;
|
||||||
const nextOrder = ((currentOrder + 1) % this.props.teams.length);
|
const nextOrder = ((currentOrder + 1) % this.props.teams.length);
|
||||||
const nextIndex = this.props.teams.findIndex((team) => team.order === nextOrder);
|
const nextIndex = this.props.teams.findIndex((team) => team.order === nextOrder);
|
||||||
@@ -139,7 +135,7 @@ export default class MainPage extends React.PureComponent {
|
|||||||
this.handleSelect(team.name, nextIndex);
|
this.handleSelect(team.name, nextIndex);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(SELECT_PREVIOUS_TAB, () => {
|
window.ipcRenderer.on(SELECT_PREVIOUS_TAB, () => {
|
||||||
const currentOrder = this.props.teams[this.state.key].order;
|
const currentOrder = this.props.teams[this.state.key].order;
|
||||||
|
|
||||||
// js modulo operator returns a negative number if result is negative, so we have to ensure it's positive
|
// js modulo operator returns a negative number if result is negative, so we have to ensure it's positive
|
||||||
@@ -149,32 +145,32 @@ export default class MainPage extends React.PureComponent {
|
|||||||
this.handleSelect(team.name, nextIndex);
|
this.handleSelect(team.name, nextIndex);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(MAXIMIZE_CHANGE, this.handleMaximizeState);
|
window.ipcRenderer.on(MAXIMIZE_CHANGE, this.handleMaximizeState);
|
||||||
|
|
||||||
ipcRenderer.on('enter-full-screen', () => this.handleFullScreenState(true));
|
window.ipcRenderer.on('enter-full-screen', () => this.handleFullScreenState(true));
|
||||||
ipcRenderer.on('leave-full-screen', () => this.handleFullScreenState(false));
|
window.ipcRenderer.on('leave-full-screen', () => this.handleFullScreenState(false));
|
||||||
|
|
||||||
ipcRenderer.on(ADD_SERVER, () => {
|
window.ipcRenderer.on(ADD_SERVER, () => {
|
||||||
this.addServer();
|
this.addServer();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(PLAY_SOUND, (_event, soundName) => {
|
window.ipcRenderer.on(PLAY_SOUND, (_event, soundName) => {
|
||||||
playSound(soundName);
|
playSound(soundName);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(MODAL_OPEN, () => {
|
window.ipcRenderer.on(MODAL_OPEN, () => {
|
||||||
this.setState({modalOpen: true});
|
this.setState({modalOpen: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(MODAL_CLOSE, () => {
|
window.ipcRenderer.on(MODAL_CLOSE, () => {
|
||||||
this.setState({modalOpen: false});
|
this.setState({modalOpen: false});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(TOGGLE_BACK_BUTTON, (event, showExtraBar) => {
|
window.ipcRenderer.on(TOGGLE_BACK_BUTTON, (event, showExtraBar) => {
|
||||||
this.setState({showExtraBar});
|
this.setState({showExtraBar});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(UPDATE_MENTIONS, (_event, team, mentions, unreads, isExpired) => {
|
window.ipcRenderer.on(UPDATE_MENTIONS, (_event, team, mentions, unreads, isExpired) => {
|
||||||
const key = this.props.teams.findIndex((server) => server.name === team);
|
const key = this.props.teams.findIndex((server) => server.name === team);
|
||||||
const {unreadCounts, mentionCounts, sessionsExpired} = this.state;
|
const {unreadCounts, mentionCounts, sessionsExpired} = this.state;
|
||||||
|
|
||||||
@@ -190,8 +186,8 @@ export default class MainPage extends React.PureComponent {
|
|||||||
this.setState({unreadCounts: newUnreads, mentionCounts: newMentionCounts, sessionsExpired: expired});
|
this.setState({unreadCounts: newUnreads, mentionCounts: newMentionCounts, sessionsExpired: expired});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (process.platform !== 'darwin') {
|
if (window.process.platform !== 'darwin') {
|
||||||
ipcRenderer.on(FOCUS_THREE_DOT_MENU, () => {
|
window.ipcRenderer.on(FOCUS_THREE_DOT_MENU, () => {
|
||||||
if (this.threeDotMenu.current) {
|
if (this.threeDotMenu.current) {
|
||||||
this.threeDotMenu.current.focus();
|
this.threeDotMenu.current.focus();
|
||||||
}
|
}
|
||||||
@@ -213,7 +209,7 @@ export default class MainPage extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleSelect = (name, key) => {
|
handleSelect = (name, key) => {
|
||||||
ipcRenderer.send(SWITCH_SERVER, name);
|
window.ipcRenderer.send(SWITCH_SERVER, name);
|
||||||
this.handleSetServerKey(key);
|
this.handleSetServerKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,40 +224,40 @@ export default class MainPage extends React.PureComponent {
|
|||||||
|
|
||||||
handleClose = (e) => {
|
handleClose = (e) => {
|
||||||
e.stopPropagation(); // since it is our button, the event goes into MainPage's onclick event, getting focus back.
|
e.stopPropagation(); // since it is our button, the event goes into MainPage's onclick event, getting focus back.
|
||||||
ipcRenderer.send(WINDOW_CLOSE);
|
window.ipcRenderer.send(WINDOW_CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMinimize = (e) => {
|
handleMinimize = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
ipcRenderer.send(WINDOW_MINIMIZE);
|
window.ipcRenderer.send(WINDOW_MINIMIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMaximize = (e) => {
|
handleMaximize = (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
ipcRenderer.send(WINDOW_MAXIMIZE);
|
window.ipcRenderer.send(WINDOW_MAXIMIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRestore = () => {
|
handleRestore = () => {
|
||||||
ipcRenderer.send(WINDOW_RESTORE);
|
window.ipcRenderer.send(WINDOW_RESTORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
openMenu = () => {
|
openMenu = () => {
|
||||||
if (process.platform !== 'darwin') {
|
if (window.process.platform !== 'darwin') {
|
||||||
this.threeDotMenu.current.blur();
|
this.threeDotMenu.current.blur();
|
||||||
}
|
}
|
||||||
this.props.openMenu();
|
this.props.openMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDoubleClick = () => {
|
handleDoubleClick = () => {
|
||||||
ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW);
|
window.ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
addServer = () => {
|
addServer = () => {
|
||||||
ipcRenderer.send(SHOW_NEW_SERVER_MODAL);
|
window.ipcRenderer.send(SHOW_NEW_SERVER_MODAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
focusOnWebView = () => {
|
focusOnWebView = () => {
|
||||||
ipcRenderer.send(FOCUS_BROWSERVIEW);
|
window.ipcRenderer.send(FOCUS_BROWSERVIEW);
|
||||||
}
|
}
|
||||||
|
|
||||||
setInputRef = (ref) => {
|
setInputRef = (ref) => {
|
||||||
@@ -287,7 +283,7 @@ export default class MainPage extends React.PureComponent {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let topBarClassName = 'topBar';
|
let topBarClassName = 'topBar';
|
||||||
if (process.platform === 'darwin') {
|
if (window.process.platform === 'darwin') {
|
||||||
topBarClassName += ' macOS';
|
topBarClassName += ' macOS';
|
||||||
}
|
}
|
||||||
if (this.state.darkMode) {
|
if (this.state.darkMode) {
|
||||||
@@ -319,14 +315,14 @@ export default class MainPage extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let overlayGradient;
|
let overlayGradient;
|
||||||
if (process.platform !== 'darwin') {
|
if (window.process.platform !== 'darwin') {
|
||||||
overlayGradient = (
|
overlayGradient = (
|
||||||
<span className='overlay-gradient'/>
|
<span className='overlay-gradient'/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let titleBarButtons;
|
let titleBarButtons;
|
||||||
if (os.platform() === 'win32' && os.release().startsWith('10')) {
|
if (window.os.isWindows10) {
|
||||||
titleBarButtons = (
|
titleBarButtons = (
|
||||||
<span className='title-bar-btns'>
|
<span className='title-bar-btns'>
|
||||||
<div
|
<div
|
||||||
@@ -421,7 +417,7 @@ export default class MainPage extends React.PureComponent {
|
|||||||
darkMode={this.state.darkMode}
|
darkMode={this.state.darkMode}
|
||||||
show={this.state.showExtraBar}
|
show={this.state.showExtraBar}
|
||||||
goBack={() => {
|
goBack={() => {
|
||||||
ipcRenderer.send(HISTORY, -1);
|
window.ipcRenderer.send(HISTORY, -1);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Row>
|
<Row>
|
||||||
|
@@ -8,7 +8,6 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {Checkbox, Col, FormGroup, Grid, HelpBlock, Navbar, Radio, Row, Button} from 'react-bootstrap';
|
import {Checkbox, Col, FormGroup, Grid, HelpBlock, Navbar, Radio, Row, Button} from 'react-bootstrap';
|
||||||
|
|
||||||
import {ipcRenderer} from 'electron';
|
|
||||||
import {debounce} from 'underscore';
|
import {debounce} from 'underscore';
|
||||||
|
|
||||||
import {GET_LOCAL_CONFIGURATION, UPDATE_CONFIGURATION, DOUBLE_CLICK_ON_WINDOW, GET_DOWNLOAD_LOCATION, SWITCH_SERVER, ADD_SERVER, RELOAD_CONFIGURATION} from 'common/communication';
|
import {GET_LOCAL_CONFIGURATION, UPDATE_CONFIGURATION, DOUBLE_CLICK_ON_WINDOW, GET_DOWNLOAD_LOCATION, SWITCH_SERVER, ADD_SERVER, RELOAD_CONFIGURATION} from 'common/communication';
|
||||||
@@ -20,7 +19,7 @@ const CONFIG_TYPE_SERVERS = 'servers';
|
|||||||
const CONFIG_TYPE_APP_OPTIONS = 'appOptions';
|
const CONFIG_TYPE_APP_OPTIONS = 'appOptions';
|
||||||
|
|
||||||
function backToIndex(serverName) {
|
function backToIndex(serverName) {
|
||||||
ipcRenderer.send(SWITCH_SERVER, serverName);
|
window.ipcRenderer.send(SWITCH_SERVER, serverName);
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,20 +53,20 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
ipcRenderer.on(ADD_SERVER, () => {
|
window.ipcRenderer.on(ADD_SERVER, () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
showAddTeamForm: true,
|
showAddTeamForm: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(RELOAD_CONFIGURATION, () => {
|
window.ipcRenderer.on(RELOAD_CONFIGURATION, () => {
|
||||||
this.updateSaveState();
|
this.updateSaveState();
|
||||||
this.getConfig();
|
this.getConfig();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getConfig = () => {
|
getConfig = () => {
|
||||||
ipcRenderer.invoke(GET_LOCAL_CONFIGURATION).then((config) => {
|
window.ipcRenderer.invoke(GET_LOCAL_CONFIGURATION).then((config) => {
|
||||||
this.setState({ready: true, maximized: false, ...this.convertConfigDataToState(config)});
|
this.setState({ready: true, maximized: false, ...this.convertConfigDataToState(config)});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -98,7 +97,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
processSaveQueue = debounce(() => {
|
processSaveQueue = debounce(() => {
|
||||||
ipcRenderer.send(UPDATE_CONFIGURATION, this.saveQueue.splice(0, this.saveQueue.length));
|
window.ipcRenderer.send(UPDATE_CONFIGURATION, this.saveQueue.splice(0, this.saveQueue.length));
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
updateSaveState = () => {
|
updateSaveState = () => {
|
||||||
@@ -135,7 +134,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
handleTeamsChange = (teams) => {
|
handleTeamsChange = (teams) => {
|
||||||
setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams});
|
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams});
|
||||||
this.setState({
|
this.setState({
|
||||||
showAddTeamForm: false,
|
showAddTeamForm: false,
|
||||||
teams,
|
teams,
|
||||||
@@ -147,12 +146,12 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
|
|
||||||
handleChangeShowTrayIcon = () => {
|
handleChangeShowTrayIcon = () => {
|
||||||
const shouldShowTrayIcon = !this.showTrayIconRef.current.props.checked;
|
const shouldShowTrayIcon = !this.showTrayIconRef.current.props.checked;
|
||||||
setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'showTrayIcon', data: shouldShowTrayIcon});
|
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'showTrayIcon', data: shouldShowTrayIcon});
|
||||||
this.setState({
|
this.setState({
|
||||||
showTrayIcon: shouldShowTrayIcon,
|
showTrayIcon: shouldShowTrayIcon,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (process.platform === 'darwin' && !shouldShowTrayIcon) {
|
if (window.process.platform === 'darwin' && !shouldShowTrayIcon) {
|
||||||
this.setState({
|
this.setState({
|
||||||
minimizeToTray: false,
|
minimizeToTray: false,
|
||||||
});
|
});
|
||||||
@@ -160,14 +159,14 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleChangeTrayIconTheme = (theme) => {
|
handleChangeTrayIconTheme = (theme) => {
|
||||||
setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'trayIconTheme', data: theme});
|
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'trayIconTheme', data: theme});
|
||||||
this.setState({
|
this.setState({
|
||||||
trayIconTheme: theme,
|
trayIconTheme: theme,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChangeAutoStart = () => {
|
handleChangeAutoStart = () => {
|
||||||
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.props.checked});
|
||||||
this.setState({
|
this.setState({
|
||||||
autostart: !this.autostartRef.current.props.checked,
|
autostart: !this.autostartRef.current.props.checked,
|
||||||
});
|
});
|
||||||
@@ -176,7 +175,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
handleChangeMinimizeToTray = () => {
|
handleChangeMinimizeToTray = () => {
|
||||||
const shouldMinimizeToTray = this.state.showTrayIcon && !this.minimizeToTrayRef.current.props.checked;
|
const shouldMinimizeToTray = this.state.showTrayIcon && !this.minimizeToTrayRef.current.props.checked;
|
||||||
|
|
||||||
setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'minimizeToTray', data: shouldMinimizeToTray});
|
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'minimizeToTray', data: shouldMinimizeToTray});
|
||||||
this.setState({
|
this.setState({
|
||||||
minimizeToTray: shouldMinimizeToTray,
|
minimizeToTray: shouldMinimizeToTray,
|
||||||
});
|
});
|
||||||
@@ -196,7 +195,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleFlashWindow = () => {
|
handleFlashWindow = () => {
|
||||||
setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {
|
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {
|
||||||
key: 'notifications',
|
key: 'notifications',
|
||||||
data: {
|
data: {
|
||||||
...this.state.notifications,
|
...this.state.notifications,
|
||||||
@@ -212,7 +211,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleBounceIcon = () => {
|
handleBounceIcon = () => {
|
||||||
setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {
|
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {
|
||||||
key: 'notifications',
|
key: 'notifications',
|
||||||
data: {
|
data: {
|
||||||
...this.state.notifications,
|
...this.state.notifications,
|
||||||
@@ -228,7 +227,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleBounceIconType = (event) => {
|
handleBounceIconType = (event) => {
|
||||||
setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {
|
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {
|
||||||
key: 'notifications',
|
key: 'notifications',
|
||||||
data: {
|
data: {
|
||||||
...this.state.notifications,
|
...this.state.notifications,
|
||||||
@@ -244,21 +243,21 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleShowUnreadBadge = () => {
|
handleShowUnreadBadge = () => {
|
||||||
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.props.checked});
|
||||||
this.setState({
|
this.setState({
|
||||||
showUnreadBadge: !this.showUnreadBadgeRef.current.props.checked,
|
showUnreadBadge: !this.showUnreadBadgeRef.current.props.checked,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChangeUseSpellChecker = () => {
|
handleChangeUseSpellChecker = () => {
|
||||||
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.props.checked});
|
||||||
this.setState({
|
this.setState({
|
||||||
useSpellChecker: !this.useSpellCheckerRef.current.props.checked,
|
useSpellChecker: !this.useSpellCheckerRef.current.props.checked,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChangeEnableHardwareAcceleration = () => {
|
handleChangeEnableHardwareAcceleration = () => {
|
||||||
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.props.checked});
|
||||||
this.setState({
|
this.setState({
|
||||||
enableHardwareAcceleration: !this.enableHardwareAccelerationRef.current.props.checked,
|
enableHardwareAcceleration: !this.enableHardwareAccelerationRef.current.props.checked,
|
||||||
});
|
});
|
||||||
@@ -268,7 +267,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
this.setState({
|
this.setState({
|
||||||
downloadLocation: location,
|
downloadLocation: location,
|
||||||
});
|
});
|
||||||
setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'downloadLocation', data: location});
|
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'downloadLocation', data: location});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChangeDownloadLocation = (e) => {
|
handleChangeDownloadLocation = (e) => {
|
||||||
@@ -277,7 +276,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
|
|
||||||
selectDownloadLocation = () => {
|
selectDownloadLocation = () => {
|
||||||
if (!this.state.userOpenedDownloadDialog) {
|
if (!this.state.userOpenedDownloadDialog) {
|
||||||
ipcRenderer.invoke(GET_DOWNLOAD_LOCATION, `/Users/${process.env.USER || process.env.USERNAME}/Downloads`).then((result) => this.saveDownloadLocation(result));
|
window.ipcRenderer.invoke(GET_DOWNLOAD_LOCATION, `/Users/${window.process.env.USER || window.process.env.USERNAME}/Downloads`).then((result) => this.saveDownloadLocation(result));
|
||||||
this.setState({userOpenedDownloadDialog: true});
|
this.setState({userOpenedDownloadDialog: true});
|
||||||
}
|
}
|
||||||
this.setState({userOpenedDownloadDialog: false});
|
this.setState({userOpenedDownloadDialog: false});
|
||||||
@@ -286,7 +285,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
updateTeam = (index, newData) => {
|
updateTeam = (index, newData) => {
|
||||||
const teams = this.state.teams;
|
const teams = this.state.teams;
|
||||||
teams[index] = newData;
|
teams[index] = newData;
|
||||||
setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams});
|
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams});
|
||||||
this.setState({
|
this.setState({
|
||||||
teams,
|
teams,
|
||||||
});
|
});
|
||||||
@@ -295,7 +294,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
addServer = (team) => {
|
addServer = (team) => {
|
||||||
const teams = this.state.teams;
|
const teams = this.state.teams;
|
||||||
teams.push(team);
|
teams.push(team);
|
||||||
setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams});
|
window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams});
|
||||||
this.setState({
|
this.setState({
|
||||||
teams,
|
teams,
|
||||||
});
|
});
|
||||||
@@ -308,7 +307,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleDoubleClick = () => {
|
handleDoubleClick = () => {
|
||||||
ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW, 'settings');
|
window.ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW, 'settings');
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -431,7 +430,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
const 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
|
// 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') {
|
if (window.process.platform === 'win32' || window.process.platform === 'linux') {
|
||||||
options.push(
|
options.push(
|
||||||
<Checkbox
|
<Checkbox
|
||||||
key='inputAutoStart'
|
key='inputAutoStart'
|
||||||
@@ -462,8 +461,8 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
</HelpBlock>
|
</HelpBlock>
|
||||||
</Checkbox>);
|
</Checkbox>);
|
||||||
|
|
||||||
if (process.platform === 'darwin' || process.platform === 'win32') {
|
if (window.process.platform === 'darwin' || window.process.platform === 'win32') {
|
||||||
const TASKBAR = process.platform === 'win32' ? 'taskbar' : 'Dock';
|
const TASKBAR = window.process.platform === 'win32' ? 'taskbar' : 'Dock';
|
||||||
options.push(
|
options.push(
|
||||||
<Checkbox
|
<Checkbox
|
||||||
key='inputShowUnreadBadge'
|
key='inputShowUnreadBadge'
|
||||||
@@ -479,7 +478,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
</Checkbox>);
|
</Checkbox>);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'win32' || process.platform === 'linux') {
|
if (window.process.platform === 'win32' || window.process.platform === 'linux') {
|
||||||
options.push(
|
options.push(
|
||||||
<Checkbox
|
<Checkbox
|
||||||
key='flashWindow'
|
key='flashWindow'
|
||||||
@@ -495,7 +494,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
</Checkbox>);
|
</Checkbox>);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'darwin') {
|
if (window.process.platform === 'darwin') {
|
||||||
options.push(
|
options.push(
|
||||||
<FormGroup
|
<FormGroup
|
||||||
key='OptionsForm'
|
key='OptionsForm'
|
||||||
@@ -545,7 +544,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'darwin' || process.platform === 'linux') {
|
if (window.process.platform === 'darwin' || window.process.platform === 'linux') {
|
||||||
options.push(
|
options.push(
|
||||||
<Checkbox
|
<Checkbox
|
||||||
key='inputShowTrayIcon'
|
key='inputShowTrayIcon'
|
||||||
@@ -554,14 +553,14 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
checked={this.state.showTrayIcon}
|
checked={this.state.showTrayIcon}
|
||||||
onChange={this.handleChangeShowTrayIcon}
|
onChange={this.handleChangeShowTrayIcon}
|
||||||
>
|
>
|
||||||
{process.platform === 'darwin' ? `Show ${this.state.appName} icon in the menu bar` : 'Show icon in the notification area'}
|
{window.process.platform === 'darwin' ? `Show ${this.state.appName} icon in the menu bar` : 'Show icon in the notification area'}
|
||||||
<HelpBlock>
|
<HelpBlock>
|
||||||
{'Setting takes effect after restarting the app.'}
|
{'Setting takes effect after restarting the app.'}
|
||||||
</HelpBlock>
|
</HelpBlock>
|
||||||
</Checkbox>);
|
</Checkbox>);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'linux') {
|
if (window.process.platform === 'linux') {
|
||||||
options.push(
|
options.push(
|
||||||
<FormGroup
|
<FormGroup
|
||||||
key='trayIconTheme'
|
key='trayIconTheme'
|
||||||
@@ -590,7 +589,7 @@ export default class SettingsPage extends React.PureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform === 'linux') {
|
if (window.process.platform === 'linux') {
|
||||||
options.push(
|
options.push(
|
||||||
<Checkbox
|
<Checkbox
|
||||||
key='inputMinimizeToTray'
|
key='inputMinimizeToTray'
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
// Copyright (c) 2015-2016 Yuya Ochiai
|
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {ipcRenderer} from 'electron';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {Nav, NavItem} from 'react-bootstrap';
|
import {Nav, NavItem} from 'react-bootstrap';
|
||||||
import {Container, Draggable} from 'react-smooth-dnd';
|
import {Container, Draggable} from 'react-smooth-dnd';
|
||||||
@@ -20,7 +19,7 @@ export default class TabBar extends React.PureComponent { // need "this"
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
ipcRenderer.invoke(GET_CONFIGURATION).then((config) => {
|
window.ipcRenderer.invoke(GET_CONFIGURATION).then((config) => {
|
||||||
this.setState({hasGPOTeams: config.registryTeams && config.registryTeams.length > 0});
|
this.setState({hasGPOTeams: config.registryTeams && config.registryTeams.length > 0});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline'">
|
||||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app" />
|
<div id="app" />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@@ -5,17 +5,8 @@
|
|||||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
import 'renderer/css/index.css';
|
import 'renderer/css/index.css';
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
|
||||||
window.eval = global.eval = () => { // eslint-disable-line no-multi-assign, no-eval
|
|
||||||
throw new Error('Sorry, Mattermost does not support window.eval() for security reasons.');
|
|
||||||
};
|
|
||||||
} else if (module.hot) {
|
|
||||||
module.hot.accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import {ipcRenderer} from 'electron';
|
|
||||||
|
|
||||||
import {GET_CONFIGURATION, UPDATE_TEAMS, QUIT, RELOAD_CONFIGURATION} from 'common/communication';
|
import {GET_CONFIGURATION, UPDATE_TEAMS, QUIT, RELOAD_CONFIGURATION} from 'common/communication';
|
||||||
|
|
||||||
@@ -29,11 +20,11 @@ class Root extends React.PureComponent {
|
|||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
await this.setInitialConfig();
|
await this.setInitialConfig();
|
||||||
|
|
||||||
ipcRenderer.on('synchronize-config', () => {
|
window.ipcRenderer.on('synchronize-config', () => {
|
||||||
this.reloadConfig();
|
this.reloadConfig();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on(RELOAD_CONFIGURATION, () => {
|
window.ipcRenderer.on(RELOAD_CONFIGURATION, () => {
|
||||||
this.reloadConfig();
|
this.reloadConfig();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -72,7 +63,7 @@ class Root extends React.PureComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
teamConfigChange = async (updatedTeams, callback) => {
|
teamConfigChange = async (updatedTeams, callback) => {
|
||||||
const updatedConfig = await ipcRenderer.invoke(UPDATE_TEAMS, updatedTeams);
|
const updatedConfig = await window.ipcRenderer.invoke(UPDATE_TEAMS, updatedTeams);
|
||||||
await this.reloadConfig();
|
await this.reloadConfig();
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(updatedConfig);
|
callback(updatedConfig);
|
||||||
@@ -87,20 +78,20 @@ class Root extends React.PureComponent {
|
|||||||
requestConfig = async (exitOnError) => {
|
requestConfig = async (exitOnError) => {
|
||||||
// todo: should we block?
|
// todo: should we block?
|
||||||
try {
|
try {
|
||||||
const configRequest = await ipcRenderer.invoke(GET_CONFIGURATION);
|
const configRequest = await window.ipcRenderer.invoke(GET_CONFIGURATION);
|
||||||
return configRequest;
|
return configRequest;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(`there was an error with the config: ${err}`);
|
console.log(`there was an error with the config: ${err}`);
|
||||||
if (exitOnError) {
|
if (exitOnError) {
|
||||||
ipcRenderer.send(QUIT, `unable to load configuration: ${err}`, err.stack);
|
window.ipcRenderer.send(QUIT, `unable to load configuration: ${err}`, err.stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
openMenu = () => {
|
openMenu = () => {
|
||||||
if (process.platform !== 'darwin') {
|
if (window.process.platform !== 'darwin') {
|
||||||
ipcRenderer.send('open-app-menu');
|
window.ipcRenderer.send('open-app-menu');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +113,7 @@ class Root extends React.PureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ipcRenderer.invoke('get-app-version').then(({name, version}) => {
|
window.ipcRenderer.invoke('get-app-version').then(({name, version}) => {
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
console.log(`Starting ${name} v${version} commit: ${__HASH_VERSION__}`);
|
console.log(`Starting ${name} v${version} commit: ${__HASH_VERSION__}`);
|
||||||
});
|
});
|
||||||
|
@@ -2,28 +2,18 @@
|
|||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
// Copyright (c) 2015-2016 Yuya Ochiai
|
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||||
|
|
||||||
import {ipcRenderer} from 'electron';
|
|
||||||
|
|
||||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
import 'renderer/css/index.css';
|
import 'renderer/css/index.css';
|
||||||
import 'renderer/css/settings.css';
|
import 'renderer/css/settings.css';
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
|
||||||
window.eval = global.eval = () => { // eslint-disable-line no-multi-assign, no-eval
|
|
||||||
throw new Error('Sorry, Mattermost does not support window.eval() for security reasons.');
|
|
||||||
};
|
|
||||||
} else if (module.hot) {
|
|
||||||
module.hot.accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
import SettingsPage from './components/SettingsPage.jsx';
|
import SettingsPage from './components/SettingsPage.jsx';
|
||||||
|
|
||||||
function openMenu() {
|
function openMenu() {
|
||||||
if (process.platform !== 'darwin') {
|
if (window.process.platform !== 'darwin') {
|
||||||
ipcRenderer.send('open-app-menu');
|
window.ipcRenderer.send('open-app-menu');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,17 +25,17 @@ class UpdaterPageContainer extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
ipcRenderer.on('start-download', () => {
|
window.ipcRenderer.on('start-download', () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
isDownloading: true,
|
isDownloading: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
ipcRenderer.on('progress', (event, progress) => {
|
window.ipcRenderer.on('progress', (event, progress) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
progress,
|
progress,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
ipcRenderer.on('zoom-in', () => {
|
window.ipcRenderer.on('zoom-in', () => {
|
||||||
const activeTabWebContents = this.getTabWebContents();
|
const activeTabWebContents = this.getTabWebContents();
|
||||||
if (!activeTabWebContents) {
|
if (!activeTabWebContents) {
|
||||||
return;
|
return;
|
||||||
@@ -46,7 +46,7 @@ class UpdaterPageContainer extends React.PureComponent {
|
|||||||
activeTabWebContents.zoomLevel += 1;
|
activeTabWebContents.zoomLevel += 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('zoom-out', () => {
|
window.ipcRenderer.on('zoom-out', () => {
|
||||||
const activeTabWebContents = this.getTabWebContents();
|
const activeTabWebContents = this.getTabWebContents();
|
||||||
if (!activeTabWebContents) {
|
if (!activeTabWebContents) {
|
||||||
return;
|
return;
|
||||||
@@ -57,7 +57,7 @@ class UpdaterPageContainer extends React.PureComponent {
|
|||||||
activeTabWebContents.zoomLevel -= 1;
|
activeTabWebContents.zoomLevel -= 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('zoom-reset', () => {
|
window.ipcRenderer.on('zoom-reset', () => {
|
||||||
const activeTabWebContents = this.getTabWebContents();
|
const activeTabWebContents = this.getTabWebContents();
|
||||||
if (!activeTabWebContents) {
|
if (!activeTabWebContents) {
|
||||||
return;
|
return;
|
||||||
@@ -65,7 +65,7 @@ class UpdaterPageContainer extends React.PureComponent {
|
|||||||
activeTabWebContents.zoomLevel = 0;
|
activeTabWebContents.zoomLevel = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('undo', () => {
|
window.ipcRenderer.on('undo', () => {
|
||||||
const activeTabWebContents = this.getTabWebContents();
|
const activeTabWebContents = this.getTabWebContents();
|
||||||
if (!activeTabWebContents) {
|
if (!activeTabWebContents) {
|
||||||
return;
|
return;
|
||||||
@@ -73,7 +73,7 @@ class UpdaterPageContainer extends React.PureComponent {
|
|||||||
activeTabWebContents.undo();
|
activeTabWebContents.undo();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('redo', () => {
|
window.ipcRenderer.on('redo', () => {
|
||||||
const activeTabWebContents = this.getTabWebContents();
|
const activeTabWebContents = this.getTabWebContents();
|
||||||
if (!activeTabWebContents) {
|
if (!activeTabWebContents) {
|
||||||
return;
|
return;
|
||||||
@@ -81,7 +81,7 @@ class UpdaterPageContainer extends React.PureComponent {
|
|||||||
activeTabWebContents.redo();
|
activeTabWebContents.redo();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('cut', () => {
|
window.ipcRenderer.on('cut', () => {
|
||||||
const activeTabWebContents = this.getTabWebContents();
|
const activeTabWebContents = this.getTabWebContents();
|
||||||
if (!activeTabWebContents) {
|
if (!activeTabWebContents) {
|
||||||
return;
|
return;
|
||||||
@@ -89,7 +89,7 @@ class UpdaterPageContainer extends React.PureComponent {
|
|||||||
activeTabWebContents.cut();
|
activeTabWebContents.cut();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('copy', () => {
|
window.ipcRenderer.on('copy', () => {
|
||||||
const activeTabWebContents = this.getTabWebContents();
|
const activeTabWebContents = this.getTabWebContents();
|
||||||
if (!activeTabWebContents) {
|
if (!activeTabWebContents) {
|
||||||
return;
|
return;
|
||||||
@@ -97,7 +97,7 @@ class UpdaterPageContainer extends React.PureComponent {
|
|||||||
activeTabWebContents.copy();
|
activeTabWebContents.copy();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('paste', () => {
|
window.ipcRenderer.on('paste', () => {
|
||||||
const activeTabWebContents = this.getTabWebContents();
|
const activeTabWebContents = this.getTabWebContents();
|
||||||
if (!activeTabWebContents) {
|
if (!activeTabWebContents) {
|
||||||
return;
|
return;
|
||||||
@@ -105,7 +105,7 @@ class UpdaterPageContainer extends React.PureComponent {
|
|||||||
activeTabWebContents.paste();
|
activeTabWebContents.paste();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('paste-and-match', () => {
|
window.ipcRenderer.on('paste-and-match', () => {
|
||||||
const activeTabWebContents = this.getTabWebContents();
|
const activeTabWebContents = this.getTabWebContents();
|
||||||
if (!activeTabWebContents) {
|
if (!activeTabWebContents) {
|
||||||
return;
|
return;
|
||||||
@@ -121,22 +121,22 @@ class UpdaterPageContainer extends React.PureComponent {
|
|||||||
notifyOnly={this.props.notifyOnly}
|
notifyOnly={this.props.notifyOnly}
|
||||||
{...this.state}
|
{...this.state}
|
||||||
onClickReleaseNotes={() => {
|
onClickReleaseNotes={() => {
|
||||||
ipcRenderer.send('click-release-notes');
|
window.ipcRenderer.send('click-release-notes');
|
||||||
}}
|
}}
|
||||||
onClickSkip={() => {
|
onClickSkip={() => {
|
||||||
ipcRenderer.send('click-skip');
|
window.ipcRenderer.send('click-skip');
|
||||||
}}
|
}}
|
||||||
onClickRemind={() => {
|
onClickRemind={() => {
|
||||||
ipcRenderer.send('click-remind');
|
window.ipcRenderer.send('click-remind');
|
||||||
}}
|
}}
|
||||||
onClickInstall={() => {
|
onClickInstall={() => {
|
||||||
ipcRenderer.send('click-install');
|
window.ipcRenderer.send('click-install');
|
||||||
}}
|
}}
|
||||||
onClickDownload={() => {
|
onClickDownload={() => {
|
||||||
ipcRenderer.send('click-download');
|
window.ipcRenderer.send('click-download');
|
||||||
}}
|
}}
|
||||||
onClickCancel={() => {
|
onClickCancel={() => {
|
||||||
ipcRenderer.send('click-cancel');
|
window.ipcRenderer.send('click-cancel');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@@ -17,6 +17,7 @@ const base = require('./webpack.config.base');
|
|||||||
module.exports = merge(base, {
|
module.exports = merge(base, {
|
||||||
entry: {
|
entry: {
|
||||||
index: './src/main/main.js',
|
index: './src/main/main.js',
|
||||||
|
mainWindow: './src/main/preload/mainWindow.js',
|
||||||
preload: './src/main/preload/mattermost.js',
|
preload: './src/main/preload/mattermost.js',
|
||||||
modalPreload: './src/main/preload/modalPreload.js',
|
modalPreload: './src/main/preload/modalPreload.js',
|
||||||
finderPreload: './src/main/preload/finderPreload.js',
|
finderPreload: './src/main/preload/finderPreload.js',
|
||||||
|
Reference in New Issue
Block a user