Merge branch 'master' into dev

This commit is contained in:
Yuya Ochiai 2016-06-17 23:39:45 +09:00
commit 517cc16835
13 changed files with 172 additions and 50 deletions

View file

@ -34,6 +34,8 @@
#### Windows #### Windows
- Added the tooltip text for the tray icon in order to show count of unread channels/mantions. - Added the tooltip text for the tray icon in order to show count of unread channels/mantions.
- Added the option to launch the application on login.
- Added the option to blink the taskbar icon when a new message has arrived.
- Added installers (experimemtal) - Added installers (experimemtal)
#### OS X #### OS X
@ -41,6 +43,7 @@
#### Linux #### Linux
- Added the option to show the icon on menu bar. (requires libappindicator1 on Ubuntu) - Added the option to show the icon on menu bar. (requires libappindicator1 on Ubuntu)
- Added the option to launch the application on login.
## Release v1.2.1 (Beta) ## Release v1.2.1 (Beta)

View file

@ -1 +1,9 @@
- [ ] Did you read `CONTRIBUTING.md`? First of all, please read `CONTRIBUTING.md`.
---
When you have a trouble, please write below.
- Operationg system
- Mattermost desktop app version
- Mattermost server version
- How to reproduce the trouble

8
PULL_REQUEST_TEMPLATE.md Normal file
View file

@ -0,0 +1,8 @@
First of all, please read `CONTRIBUTING.md`
---
- [ ] Complete [Mattermost Contributor Agreement](http://www.mattermost.org/mattermost-contributor-agreement/)
- [ ] Execute `npm run prettify` to format codes
- [ ] Write about environment which you tested
- Operating system

View file

@ -52,7 +52,7 @@ deploy win64 zip
deploy osx tar.gz deploy osx tar.gz
deploy linux-ia32 tar.gz deploy linux-ia32 tar.gz
deploy linux-x64 tar.gz deploy linux-x64 tar.gz
upload mattermost-desktop-$RELEASE_TAG-linux-i386.deb release/mattermost-desktop-$RELEASE_TAG-i386.deb upload mattermost-desktop-$RELEASE_TAG-linux-ia32.deb release/mattermost-desktop-$RELEASE_TAG-ia32.deb
upload mattermost-desktop-$RELEASE_TAG-linux-amd64.deb release/mattermost-desktop-$RELEASE_TAG-amd64.deb upload mattermost-desktop-$RELEASE_TAG-linux-x64.deb release/mattermost-desktop-$RELEASE_TAG.deb
upload mattermost-setup-$RELEASE_TAG-win32.exe release/windows-installer-ia32/mattermost-setup-ia32.exe upload mattermost-setup-$RELEASE_TAG-win32.exe release/windows-installer-ia32/mattermost-setup-ia32.exe
upload mattermost-setup-$RELEASE_TAG-win64.exe release/windows-installer-x64/mattermost-setup-x64.exe upload mattermost-setup-$RELEASE_TAG-win64.exe release/windows-installer-x64/mattermost-setup-x64.exe

View file

@ -122,6 +122,8 @@ The Settings Page is available from the **File** menu under **Settings** (Click
- **Allow insecure contents** - **Allow insecure contents**
- If your team is hosted on `https://`, images with `http://` are not rendered by default. - If your team is hosted on `https://`, images with `http://` are not rendered by default.
This option allows such images to be rendered, but please be careful for security. This option allows such images to be rendered, but please be careful for security.
- **Start app on login** (Windows, Linux)
- This option starts the application when you login.
## Menu Bar ## Menu Bar

View file

@ -202,7 +202,7 @@ function makePackage(platform, arch, callback) {
icon: 'resources/icon', icon: 'resources/icon',
"version-string": { "version-string": {
CompanyName: distPackageAuthor, CompanyName: distPackageAuthor,
LegalCopyright: `Copyright (c) 2015 - 2016 ${packageJson.author.name}`, LegalCopyright: `Copyright (c) 2015 - ${new Date().getFullYear()} ${packageJson.author.name}`,
FileDescription: packageJson.description, FileDescription: packageJson.description,
OriginalFilename: packageJson.productName + '.exe', OriginalFilename: packageJson.productName + '.exe',
ProductVersion: packageJson.version, ProductVersion: packageJson.version,

View file

@ -23,7 +23,7 @@
"package": "gulp package", "package": "gulp package",
"package:windows": "gulp package:windows", "package:windows": "gulp package:windows",
"package:osx": "gulp package:osx", "package:osx": "gulp package:osx",
"package:linux": "gulp build && build --platform linux --arch all -d deb", "package:linux": "gulp build && build --platform linux --arch all",
"package:all": "gulp package:all", "package:all": "gulp package:all",
"prettify": "gulp prettify", "prettify": "gulp prettify",
"installer": "node ./script/installer.js" "installer": "node ./script/installer.js"
@ -35,7 +35,7 @@
"chai": "^3.5.0", "chai": "^3.5.0",
"chai-as-promised": "^5.3.0", "chai-as-promised": "^5.3.0",
"del": "^2.2.0", "del": "^2.2.0",
"electron-builder": "3.20.0", "electron-builder": "5.2.1",
"electron-connect": "^0.3.7", "electron-connect": "^0.3.7",
"electron-packager": "^7.0.1", "electron-packager": "^7.0.1",
"electron-prebuilt": "1.2.2", "electron-prebuilt": "1.2.2",
@ -62,7 +62,8 @@
"app-bundle-id": "com.mattermost.desktop", "app-bundle-id": "com.mattermost.desktop",
"app-category-type": "public.app-category.productivity", "app-category-type": "public.app-category.productivity",
"linux": { "linux": {
"synopsis": "Mattermost Desktop" "synopsis": "Mattermost Desktop",
"target": "deb"
} }
}, },
"directories": { "directories": {

View file

@ -6,6 +6,7 @@ const settings = require('../common/settings');
const React = require('react'); const React = require('react');
const ReactDOM = require('react-dom'); const ReactDOM = require('react-dom');
const ReactBootstrap = require('react-bootstrap'); const ReactBootstrap = require('react-bootstrap');
var AutoLaunch = require('auto-launch');
const Grid = ReactBootstrap.Grid; const Grid = ReactBootstrap.Grid;
const Row = ReactBootstrap.Row; const Row = ReactBootstrap.Row;
@ -16,6 +17,10 @@ const ListGroup = ReactBootstrap.ListGroup;
const ListGroupItem = ReactBootstrap.ListGroupItem; const ListGroupItem = ReactBootstrap.ListGroupItem;
const Glyphicon = ReactBootstrap.Glyphicon; const Glyphicon = ReactBootstrap.Glyphicon;
var appLauncher = new AutoLaunch({
name: 'Mattermost'
});
function backToIndex() { function backToIndex() {
remote.getCurrentWindow().loadURL('file://' + __dirname + '/index.html'); remote.getCurrentWindow().loadURL('file://' + __dirname + '/index.html');
} }
@ -35,6 +40,16 @@ var SettingsPage = React.createClass({
return config; return config;
}, },
componentDidMount: function() {
if (process.platform === 'win32' || process.platform === 'linux') {
var self = this;
appLauncher.isEnabled().then(function(enabled) {
self.setState({
autostart: enabled
});
});
}
},
handleTeamsChange: function(teams) { handleTeamsChange: function(teams) {
this.setState({ this.setState({
teams: teams teams: teams
@ -49,13 +64,25 @@ var SettingsPage = React.createClass({
showTrayIcon: this.state.showTrayIcon, showTrayIcon: this.state.showTrayIcon,
trayIconTheme: this.state.trayIconTheme, trayIconTheme: this.state.trayIconTheme,
disablewebsecurity: this.state.disablewebsecurity, disablewebsecurity: this.state.disablewebsecurity,
version: settings.version version: settings.version,
notifications: {
flashWindow: this.state.notifications.flashWindow
}
}; };
settings.writeFileSync(this.props.configFile, config); settings.writeFileSync(this.props.configFile, config);
if (process.platform === 'win32' || process.platform === 'linux') { if (process.platform === 'win32' || process.platform === 'linux') {
var currentWindow = remote.getCurrentWindow(); var currentWindow = remote.getCurrentWindow();
currentWindow.setAutoHideMenuBar(config.hideMenuBar); currentWindow.setAutoHideMenuBar(config.hideMenuBar);
currentWindow.setMenuBarVisibility(!config.hideMenuBar); currentWindow.setMenuBarVisibility(!config.hideMenuBar);
var autostart = this.state.autostart;
appLauncher.isEnabled().then(function(enabled) {
if (enabled && !autostart) {
appLauncher.disable();
} else if (!enabled && autostart) {
appLauncher.enable();
}
});
} }
ipcRenderer.send('update-menu', config); ipcRenderer.send('update-menu', config);
@ -87,6 +114,11 @@ var SettingsPage = React.createClass({
trayIconTheme: this.refs.trayIconTheme.getValue() trayIconTheme: this.refs.trayIconTheme.getValue()
}); });
}, },
handleChangeAutoStart: function() {
this.setState({
autostart: this.refs.autostart.getChecked()
});
},
handleShowTeamForm: function() { handleShowTeamForm: function() {
if (!this.state.showAddTeamForm) { if (!this.state.showAddTeamForm) {
this.setState({ this.setState({
@ -98,6 +130,13 @@ var SettingsPage = React.createClass({
}); });
} }
}, },
handleFlashWindowSetting: function(item) {
this.setState({
notifications: {
flashWindow: item.state
}
});
},
render: function() { render: function() {
var buttonStyle = { var buttonStyle = {
@ -129,6 +168,10 @@ var SettingsPage = React.createClass({
} }
options.push(<Input key="inputDisableWebSecurity" ref="disablewebsecurity" type="checkbox" label="Allow mixed content (Enabling allows both secure and insecure content, images and scripts to render and execute. Disabling allows only secure content.)" options.push(<Input key="inputDisableWebSecurity" ref="disablewebsecurity" type="checkbox" label="Allow mixed content (Enabling allows both secure and insecure content, images and scripts to render and execute. Disabling allows only secure content.)"
checked={ this.state.disablewebsecurity } onChange={ this.handleChangeDisableWebSecurity } />); checked={ this.state.disablewebsecurity } onChange={ this.handleChangeDisableWebSecurity } />);
//OSX has an option in the tray, to set the app to autostart, so we choose to not support this option for OSX
if (process.platform === 'win32' || process.platform === 'linux') {
options.push(<Input key="inputAutoStart" ref="autostart" type="checkbox" label="Start app on login." checked={ this.state.autostart } onChange={ this.handleChangeAutoStart } />);
}
var options_row = (options.length > 0) ? ( var options_row = (options.length > 0) ? (
<Row> <Row>
<Col md={ 12 }> <Col md={ 12 }>
@ -138,6 +181,40 @@ var SettingsPage = React.createClass({
</Row> </Row>
) : null; ) : null;
var notificationSettings = [
{
label: 'Never',
state: 0
},
/* ToDo: Idle isn't implemented yet
{
label: 'Only when idle (after 10 seconds)',
state: 1
},*/
{
label: 'Always',
state: 2
}
];
var that = this;
var notificationElements = notificationSettings.map(function(item) {
var boundClick = that.handleFlashWindowSetting.bind(that, item);
return (
<Input key={ "flashWindow" + item.state } name="handleFlashWindow" ref={ "flashWindow" + item.state } type="radio" label={ item.label } value={ item.state } onChange={ boundClick }
checked={ that.state.notifications.flashWindow == item.state ? "checked" : "" } />
);
});
var notifications = (
<Row>
<Col md={ 12 }>
<h2>Notifications</h2> Configure, that the taskicon in the taskbar blinks when you were mentioned.
{ notificationElements }
</Col>
</Row>
)
return ( return (
<Grid className="settingsPage"> <Grid className="settingsPage">
<Row> <Row>
@ -152,6 +229,10 @@ var SettingsPage = React.createClass({
</Row> </Row>
{ teams_row } { teams_row }
{ options_row } { options_row }
{ notifications }
<div>
<hr />
</div>
<Row> <Row>
<Col md={ 12 }> <Col md={ 12 }>
<Button id="btnCancel" onClick={ this.handleCancel }>Cancel</Button> <Button id="btnCancel" onClick={ this.handleCancel }>Cancel</Button>

View file

@ -97,30 +97,15 @@ function isElementVisible(elem) {
return elem.offsetHeight !== 0; return elem.offsetHeight !== 0;
} }
// On Windows 8.1 and Windows 8, a shortcut with a Application User Model ID must be installed to the Start screen.
// In current version, use tray balloon for notification
function isLowerThanOrEqualWindows8_1() {
if (process.platform != 'win32') {
return false;
}
var osVersion = require('../../common/osVersion');
return (osVersion.major <= 6 && osVersion.minor <= 3);
};
if (process.platform === 'win32' && isLowerThanOrEqualWindows8_1()) {
// Show balloon when notified.
notification.override({ notification.override({
// Send a notification event to the main process.
notification: function(title, options) { notification: function(title, options) {
ipc.send('notified', { ipc.send('notified', {
title: title, title: title,
options: options options: options
}); });
} },
});
}
else {
// Show window even if it is hidden/minimized when notification is clicked. // Show window even if it is hidden/minimized when notification is clicked.
notification.override({
onclick: function() { onclick: function() {
if (process.platform === 'win32') { if (process.platform === 'win32') {
// show() breaks Aero Snap state. // show() breaks Aero Snap state.
@ -132,4 +117,3 @@ else {
ipc.sendToHost('onNotificationClick'); ipc.sendToHost('onNotificationClick');
} }
}); });
}

View file

@ -3,5 +3,12 @@ var release_split = os.release().split('.');
module.exports = { module.exports = {
major: parseInt(release_split[0]), major: parseInt(release_split[0]),
minor: parseInt(release_split[1]) minor: parseInt(release_split[1]),
isLowerThanOrEqualWindows8_1: function() {
if (process.platform != 'win32') {
return false;
}
// consider Windows 7 and later.
return (this.major <= 6 && this.minor <= 3);
}
}; };

View file

@ -26,7 +26,10 @@ var loadDefault = function(version) {
showTrayIcon: false, showTrayIcon: false,
trayIconTheme: '', trayIconTheme: '',
disablewebsecurity: true, disablewebsecurity: true,
version: 1 version: 1,
notifications: {
flashWindow: 0 // 0 = flash never, 1 = only when idle (after 10 seconds), 2 = always
}
}; };
} }
} }

View file

@ -11,12 +11,27 @@ const {
systemPreferences systemPreferences
} = require('electron'); } = require('electron');
if (require('electron-squirrel-startup')) app.quit(); if (process.platform === 'win32') {
var cmd = process.argv[1];
if (cmd === '--squirrel-uninstall') {
var AutoLaunch = require('auto-launch');
var appLauncher = new AutoLaunch({
name: 'Mattermost'
});
appLauncher.isEnabled().then(function(enabled) {
if (enabled)
appLauncher.disable();
});
}
}
require('electron-squirrel-startup');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
var settings = require('./common/settings'); var settings = require('./common/settings');
const osVersion = require('./common/osVersion');
var certificateStore = require('./main/certificateStore').load(path.resolve(app.getPath('userData'), 'certificate.json')); var certificateStore = require('./main/certificateStore').load(path.resolve(app.getPath('userData'), 'certificate.json'));
var appMenu = require('./main/menus/app'); var appMenu = require('./main/menus/app');
const allowProtocolDialog = require('./main/allowProtocolDialog'); const allowProtocolDialog = require('./main/allowProtocolDialog');
@ -218,11 +233,20 @@ app.on('ready', function() {
mainWindow.focus(); mainWindow.focus();
}); });
ipcMain.on('notified', function(event, arg) { ipcMain.on('notified', function(event, arg) {
if (process.platform === 'win32') {
if (config.notifications.flashWindow === 2) {
mainWindow.flashFrame(true);
}
// On Windows 8.1 and Windows 8, a shortcut with a Application User Model ID must be installed to the Start screen.
// In current version, use tray balloon for notification
if (osVersion.isLowerThanOrEqualWindows8_1()) {
trayIcon.displayBalloon({ trayIcon.displayBalloon({
icon: path.resolve(__dirname, 'resources/appicon.png'), icon: path.resolve(__dirname, 'resources/appicon.png'),
title: arg.title, title: arg.title,
content: arg.options.body content: arg.options.body
}); });
}
}
}); });
// Set overlay icon from dataURL // Set overlay icon from dataURL

View file

@ -13,6 +13,7 @@
"electron-connect": "^0.3.3" "electron-connect": "^0.3.3"
}, },
"dependencies": { "dependencies": {
"auto-launch": "^2.0.1",
"bootstrap": "^3.3.6", "bootstrap": "^3.3.6",
"electron-squirrel-startup": "^1.0.0", "electron-squirrel-startup": "^1.0.0",
"os-locale": "^1.4.0", "os-locale": "^1.4.0",