diff --git a/gulpfile.js b/gulpfile.js index 0786734f..aa437a27 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -3,9 +3,6 @@ var gulp = require('gulp'); var prettify = require('gulp-jsbeautifier'); var diff = require('gulp-diff'); -var esformatter = require('gulp-esformatter'); -var esformatter_origin = require('esformatter'); -var through = require('through2'); var electron = require('electron-connect').server.create({ path: './dist' }); @@ -18,10 +15,10 @@ const distPackageAuthor = 'Mattermost, Inc.'; var sources = ['**/*.js', '**/*.json', '**/*.css', '**/*.html', '!**/node_modules/**', '!dist/**', '!release/**', '!**/test_config.json']; -gulp.task('prettify', ['prettify:sources', 'prettify:jsx']); -gulp.task('prettify:verify', ['prettify:sources:verify', 'prettify:jsx:verify']); +gulp.task('prettify', ['prettify:sources']); +gulp.task('prettify:verify', ['prettify:sources:verify']); -var prettify_options = { +var prettifyOptions = { html: { indent_size: 2, end_with_newline: true @@ -32,62 +29,35 @@ var prettify_options = { }, js: { indent_size: 2, - brace_style: "end-expand", + brace_style: 'end-expand', end_with_newline: true } }; -gulp.task('prettify:sources', ['sync-meta'], function() { - return gulp.src(sources) - .pipe(prettify(prettify_options)) - .pipe(prettify.reporter()) - .pipe(diff()) - .pipe(diff.reporter({ +gulp.task('prettify:sources', ['sync-meta'], () => { + return gulp.src(sources). + pipe(prettify(prettifyOptions)). + pipe(prettify.reporter()). + pipe(diff()). + pipe(diff.reporter({ quiet: true, fail: false - })) - .pipe(gulp.dest('.')); + })). + pipe(gulp.dest('.')); }); -gulp.task('prettify:sources:verify', function() { - return gulp.src(sources) - .pipe(prettify(prettify_options)) - .pipe(prettify.reporter()) - .pipe(diff()) - .pipe(diff.reporter({ +gulp.task('prettify:sources:verify', () => { + return gulp.src(sources). + pipe(prettify(prettifyOptions)). + pipe(prettify.reporter()). + pipe(diff()). + pipe(diff.reporter({ quiet: true, fail: true })); }); - -var esformatter_jsx_options = { - indent: { - value: ' ' - }, - plugins: ['esformatter-jsx'] -}; - -gulp.task('prettify:jsx', function() { - return gulp.src('src/browser/**/*.jsx') - .pipe(esformatter(esformatter_jsx_options)) - .pipe(gulp.dest('src/browser')); -}); - -gulp.task('prettify:jsx:verify', function() { - return gulp.src('src/browser/**/*.jsx') - .pipe(through.obj(function(file, enc, cb) { - var result = esformatter_origin.diff.unified(file.contents.toString(), esformatter_origin.rc(file.path, esformatter_jsx_options)); - if (result !== "") { - console.log('Error: ' + file.path + ' must be formatted'); - process.exit(1); - } - cb(); - })); -}); - - -gulp.task('build', ['sync-meta', 'copy'], function(cb) { +gulp.task('build', ['sync-meta', 'copy'], (cb) => { const appPackageJson = require('./src/package.json'); const distPackageJson = Object.assign({}, appPackageJson, { author: { @@ -100,23 +70,23 @@ gulp.task('build', ['sync-meta', 'copy'], function(cb) { gulp.task('copy', ['copy:resources', 'copy:html/css', 'copy:modules']); -gulp.task('copy:resources', function() { - return gulp.src('src/resources/**') - .pipe(gulp.dest('dist/resources')); +gulp.task('copy:resources', () => { + return gulp.src('src/resources/**'). + pipe(gulp.dest('dist/resources')); }); -gulp.task('copy:html/css', function() { - return gulp.src(['src/browser/**/*.html', 'src/browser/**/*.css']) - .pipe(gulp.dest('dist/browser')); +gulp.task('copy:html/css', () => { + return gulp.src(['src/browser/**/*.html', 'src/browser/**/*.css']). + pipe(gulp.dest('dist/browser')); }); -gulp.task('copy:modules', function() { - return gulp.src(['src/node_modules/bootstrap/dist/**']) - .pipe(gulp.dest('dist/browser/modules/bootstrap')); +gulp.task('copy:modules', () => { + return gulp.src(['src/node_modules/bootstrap/dist/**']). + pipe(gulp.dest('dist/browser/modules/bootstrap')); }); function spawnWebpack(config, cb) { - const ext = process.platform === 'win32' ? '.cmd' : '' + const ext = process.platform === 'win32' ? '.cmd' : ''; spawn(path.resolve(`./node_modules/.bin/webpack${ext}`), ['--config', config], { stdio: 'inherit' }).on('exit', (code) => { @@ -132,7 +102,7 @@ gulp.task('webpack:renderer', (cb) => { spawnWebpack('webpack.config.renderer.js', cb); }); -gulp.task('watch', ['build', 'webpack:main', 'webpack:renderer'], function() { +gulp.task('watch', ['build', 'webpack:main', 'webpack:renderer'], () => { var options = ['--livereload']; electron.start(options); @@ -140,13 +110,13 @@ gulp.task('watch', ['build', 'webpack:main', 'webpack:renderer'], function() { gulp.watch(['src/browser/**/*.js', 'src/browser/**/*.jsx'], ['webpack:renderer']); gulp.watch(['src/browser/**/*.css', 'src/browser/**/*.html', 'src/resources/**/*.png'], ['copy']); - gulp.watch(['dist/main.js', 'dist/resources/**'], function() { + gulp.watch(['dist/main.js', 'dist/resources/**'], () => { electron.restart(options); }); gulp.watch(['dist/browser/*.js'], electron.reload); }); -gulp.task('sync-meta', function() { +gulp.task('sync-meta', () => { var appPackageJson = require('./src/package.json'); var packageJson = require('./package.json'); appPackageJson.name = packageJson.name; diff --git a/package.json b/package.json index 108db080..3aa58778 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,6 @@ "electron-builder": "^7.11.2", "electron-connect": "~0.6.0", "electron-prebuilt": "1.4.2", - "esformatter": "^0.9.6", - "esformatter-jsx": "^7.0.1", "eslint": "^3.4.0", "eslint-plugin-react": "^6.2.0", "gulp": "^3.9.1", @@ -58,7 +56,6 @@ "mocha": "^3.0.2", "mocha-circleci-reporter": "0.0.2", "spectron": "~3.4.0", - "through2": "^2.0.1", "webpack": "^1.13.1", "webpack-merge": "^0.14.1" }, diff --git a/src/browser/components/loginModal.jsx b/src/browser/components/loginModal.jsx index 4a1c1c0c..1ddb2d51 100644 --- a/src/browser/components/loginModal.jsx +++ b/src/browser/components/loginModal.jsx @@ -11,7 +11,7 @@ const Col = ReactBootstrap.Col; const Button = ReactBootstrap.Button; const LoginModal = React.createClass({ - handleSubmit: function(event) { + handleSubmit(event) { event.preventDefault(); const usernameNode = ReactDOM.findDOMNode(this.refs.username); const passwordNode = ReactDOM.findDOMNode(this.refs.password); @@ -19,7 +19,7 @@ const LoginModal = React.createClass({ usernameNode.value = ''; passwordNode.value = ''; }, - render: function() { + render() { var theServer = ''; if (!this.props.show) { theServer = ''; @@ -30,34 +30,54 @@ const LoginModal = React.createClass({ } const message = `${theServer} requires a username and password.`; return ( - + - Authentication Required + {'Authentication Required'}

{ message }

-
+ - User Name - - + {'User Name'} + + - Password - - + {'Password'} + + - -
- - { ' ' } - -
+ +
+ + { ' ' } + +
diff --git a/src/browser/index.jsx b/src/browser/index.jsx index 2428d97a..29bf0d08 100644 --- a/src/browser/index.jsx +++ b/src/browser/index.jsx @@ -1,8 +1,8 @@ 'use strict'; -window.eval = global.eval = function() { - throw new Error("Sorry, Mattermost does not support window.eval() for security reasons."); -} +window.eval = global.eval = () => { + throw new Error('Sorry, Mattermost does not support window.eval() for security reasons.'); +}; const React = require('react'); const ReactDOM = require('react-dom'); @@ -13,25 +13,34 @@ const Row = ReactBootstrap.Row; const Col = ReactBootstrap.Col; const Nav = ReactBootstrap.Nav; const NavItem = ReactBootstrap.NavItem; -const Badge = ReactBootstrap.Badge; -const ListGroup = ReactBootstrap.ListGroup; -const ListGroupItem = ReactBootstrap.ListGroupItem; const LoginModal = require('./components/loginModal.jsx'); -const {remote, ipcRenderer, webFrame, shell} = require('electron'); +const {remote, ipcRenderer, shell} = require('electron'); +const electronContextMenu = require('electron-context-menu'); const osLocale = require('os-locale'); const fs = require('fs'); const url = require('url'); -const path = require('path'); const settings = require('../common/settings'); +const badge = require('./js/badge'); remote.getCurrentWindow().removeAllListeners('focus'); +var config; +try { + var configFile = remote.getGlobal('config-file'); + config = settings.readFileSync(configFile); +} catch (e) { + window.location = 'settings.html'; +} +if (config.teams.length === 0) { + window.location = 'settings.html'; +} + var MainPage = React.createClass({ - getInitialState: function() { + getInitialState() { return { key: 0, unreadCounts: new Array(this.props.teams.length), @@ -41,84 +50,85 @@ var MainPage = React.createClass({ loginQueue: [] }; }, - componentDidMount: function() { - var thisObj = this; - ipcRenderer.on('login-request', function(event, request, authInfo) { - thisObj.setState({ + componentDidMount() { + var self = this; + ipcRenderer.on('login-request', (event, request, authInfo) => { + self.setState({ loginRequired: true }); - const loginQueue = thisObj.state.loginQueue; + const loginQueue = self.state.loginQueue; loginQueue.push({ - request: request, - authInfo: authInfo + request, + authInfo }); - thisObj.setState({ - loginQueue: loginQueue + self.setState({ + loginQueue }); }); + // can't switch tabs sequencially for some reason... ipcRenderer.on('switch-tab', (event, key) => { this.handleSelect(key); }); - ipcRenderer.on('select-next-tab', (event) => { + ipcRenderer.on('select-next-tab', () => { this.handleSelect(this.state.key + 1); }); - ipcRenderer.on('select-previous-tab', (event) => { + ipcRenderer.on('select-previous-tab', () => { this.handleSelect(this.state.key - 1); }); // reload the activated tab - ipcRenderer.on('reload-tab', (event) => { + ipcRenderer.on('reload-tab', () => { this.refs[`mattermostView${this.state.key}`].reload(); }); - ipcRenderer.on('clear-cache-and-reload-tab', (event) => { + ipcRenderer.on('clear-cache-and-reload-tab', () => { this.refs[`mattermostView${this.state.key}`].clearCacheAndReload(); }); // activate search box in current tab - ipcRenderer.on('activate-search-box', (event) => { - let webview = document.getElementById('mattermostView' + thisObj.state.key); + ipcRenderer.on('activate-search-box', () => { + const webview = document.getElementById('mattermostView' + self.state.key); webview.send('activate-search-box'); }); // activate search box in current chunnel - ipcRenderer.on('activate-search-box-in-channel', (event) => { - let webview = document.getElementById('mattermostView' + thisObj.state.key); + ipcRenderer.on('activate-search-box-in-channel', () => { + const webview = document.getElementById('mattermostView' + self.state.key); webview.send('activate-search-box-in-channel'); }); - var focusListener = function() { - thisObj.handleOnTeamFocused(thisObj.state.key); - thisObj.refs[`mattermostView${thisObj.state.key}`].focusOnWebView(); - }; + function focusListener() { + self.handleOnTeamFocused(self.state.key); + self.refs[`mattermostView${self.state.key}`].focusOnWebView(); + } var currentWindow = remote.getCurrentWindow(); currentWindow.on('focus', focusListener); - window.addEventListener('beforeunload', function() { + window.addEventListener('beforeunload', () => { currentWindow.removeListener('focus', focusListener); }); //goBack and goForward ipcRenderer.on('go-back', () => { - const mattermost = thisObj.refs[`mattermostView${thisObj.state.key}`]; + const mattermost = self.refs[`mattermostView${self.state.key}`]; if (mattermost.canGoBack()) { mattermost.goBack(); } }); ipcRenderer.on('go-forward', () => { - const mattermost = thisObj.refs[`mattermostView${thisObj.state.key}`]; + const mattermost = self.refs[`mattermostView${self.state.key}`]; if (mattermost.canGoForward()) { mattermost.goForward(); } }); }, - componentDidUpdate: function(prevProps, prevState) { + componentDidUpdate(prevProps, prevState) { if (prevState.key !== this.state.key) { // i.e. When tab has been changed this.refs[`mattermostView${this.state.key}`].focusOnWebView(); } }, - handleSelect: function(key) { + handleSelect(key) { const newKey = (this.props.teams.length + key) % this.props.teams.length; this.setState({ key: newKey @@ -130,13 +140,14 @@ var MainPage = React.createClass({ title: webview.getTitle() }); }, - handleUnreadCountChange: function(index, unreadCount, mentionCount, isUnread, isMentioned) { + 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; unreadCounts[index] = unreadCount; mentionCounts[index] = mentionCount; + // Never turn on the unreadAtActive flag at current focused tab. if (this.state.key !== index || !remote.getCurrentWindow().isFocused()) { unreadAtActive[index] = unreadAtActive[index] || isUnread; @@ -145,49 +156,49 @@ var MainPage = React.createClass({ } } this.setState({ - unreadCounts: unreadCounts, - mentionCounts: mentionCounts, - unreadAtActive: unreadAtActive, - mentionAtActiveCounts: mentionAtActiveCounts + unreadCounts, + mentionCounts, + unreadAtActive, + mentionAtActiveCounts }); this.handleUnreadCountTotalChange(); }, - markReadAtActive: function(index) { + markReadAtActive(index) { var unreadAtActive = this.state.unreadAtActive; var mentionAtActiveCounts = this.state.mentionAtActiveCounts; unreadAtActive[index] = false; mentionAtActiveCounts[index] = 0; this.setState({ - unreadAtActive: unreadAtActive, - mentionAtActiveCounts: mentionAtActiveCounts + unreadAtActive, + mentionAtActiveCounts }); this.handleUnreadCountTotalChange(); }, - handleUnreadCountTotalChange: function() { + handleUnreadCountTotalChange() { if (this.props.onUnreadCountChange) { - var allUnreadCount = this.state.unreadCounts.reduce(function(prev, curr) { + var allUnreadCount = this.state.unreadCounts.reduce((prev, curr) => { return prev + curr; }, 0); - this.state.unreadAtActive.forEach(function(state) { + this.state.unreadAtActive.forEach((state) => { if (state) { allUnreadCount += 1; } }); - var allMentionCount = this.state.mentionCounts.reduce(function(prev, curr) { + var allMentionCount = this.state.mentionCounts.reduce((prev, curr) => { return prev + curr; }, 0); - this.state.mentionAtActiveCounts.forEach(function(count) { + this.state.mentionAtActiveCounts.forEach((count) => { allMentionCount += count; }); this.props.onUnreadCountChange(allUnreadCount, allMentionCount); } }, - handleOnTeamFocused: function(index) { + handleOnTeamFocused(index) { // Turn off the flag to indicate whether unread message of active channel contains at current tab. this.markReadAtActive(index); }, - visibleStyle: function(visible) { + visibleStyle(visible) { var visibility = visible ? 'visible' : 'hidden'; return { position: 'absolute', @@ -195,66 +206,91 @@ var MainPage = React.createClass({ right: 0, bottom: 0, left: 0, - visibility: visibility + visibility }; }, - handleLogin: function(request, username, password) { + handleLogin(request, username, password) { ipcRenderer.send('login-credentials', request, username, password); const loginQueue = this.state.loginQueue; loginQueue.shift(); this.setState(loginQueue); }, - handleLoginCancel: function() { + handleLoginCancel() { const loginQueue = this.state.loginQueue; loginQueue.shift(); this.setState(loginQueue); }, - render: function() { - var thisObj = this; + render() { + var self = this; - var tabs_row; + var tabsRow; if (this.props.teams.length > 1) { - tabs_row = ( + tabsRow = ( - + ); } - var views = this.props.teams.map(function(team, index) { - var handleUnreadCountChange = function(unreadCount, mentionCount, isUnread, isMentioned) { - thisObj.handleUnreadCountChange(index, unreadCount, mentionCount, isUnread, isMentioned); - }; - var handleNotificationClick = function() { - thisObj.handleSelect(index); + var 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 is_active = thisObj.state.key === index; - return () + var isActive = self.state.key === index; + return ( + ); }); - var views_row = ( - { views } - ); + var viewsRow = ( + + {views} + ); var request = null; var authServerURL = null; var authInfo = null; if (this.state.loginQueue.length !== 0) { request = this.state.loginQueue[0].request; - const tmp_url = url.parse(this.state.loginQueue[0].request.url); - authServerURL = `${tmp_url.protocol}//${tmp_url.host}`; + const tmpURL = url.parse(this.state.loginQueue[0].request.url); + authServerURL = `${tmpURL.protocol}//${tmpURL.host}`; authInfo = this.state.loginQueue[0].authInfo; } return (
- + - { tabs_row } - { views_row } + { tabsRow } + { viewsRow }
); @@ -262,9 +298,9 @@ var MainPage = React.createClass({ }); var TabBar = React.createClass({ - render: function() { - var thisObj = this; - var tabs = this.props.teams.map(function(team, index) { + render() { + var self = this; + var tabs = this.props.teams.map((team, index) => { var unreadCount = 0; var badgeStyle = { background: '#FF1744', @@ -276,48 +312,64 @@ var TabBar = React.createClass({ lineHeight: '20px', height: '19px', marginLeft: '5px', - borderRadius: '50%', + borderRadius: '50%' }; - if (thisObj.props.unreadCounts[index] > 0) { - unreadCount = thisObj.props.unreadCounts[index]; + if (self.props.unreadCounts[index] > 0) { + unreadCount = self.props.unreadCounts[index]; } - if (thisObj.props.unreadAtActive[index]) { + if (self.props.unreadAtActive[index]) { unreadCount += 1; } var mentionCount = 0; - if (thisObj.props.mentionCounts[index] > 0) { - mentionCount = thisObj.props.mentionCounts[index]; + if (self.props.mentionCounts[index] > 0) { + mentionCount = self.props.mentionCounts[index]; } - if (thisObj.props.mentionAtActiveCounts[index] > 0) { - mentionCount += thisObj.props.mentionAtActiveCounts[index]; + if (self.props.mentionAtActiveCounts[index] > 0) { + mentionCount += self.props.mentionAtActiveCounts[index]; } - var badge; - if (mentionCount != 0) { - badge = (
- { mentionCount } -
); + var badgeDiv; + if (mentionCount !== 0) { + badgeDiv = ( +
+ {mentionCount} +
); } - if (unreadCount == 0) { - var id = 'teamTabItem' + index; - return ( - { team.name } - { ' ' } - { badge } - ); - } else { - var id = 'teamTabItem' + index; - return ( - { team.name } - { ' ' } - { badge } - ); + var id = 'teamTabItem' + index; + if (unreadCount === 0) { + return ( + + { team.name } + { ' ' } + { badgeDiv } + ); } + return ( + + { team.name } + { ' ' } + { badgeDiv } + ); }); return ( -