Merge branch 'master' into auto-updater
This commit is contained in:
commit
85495ef77a
12
.babelrc
12
.babelrc
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"targets": {
|
||||
"browsers": ["Electron >= 1.8"],
|
||||
"node": "8.2"
|
||||
}
|
||||
}],
|
||||
"react"
|
||||
],
|
||||
"plugins": ["transform-object-rest-spread", "transform-class-properties"]
|
||||
}
|
48
CHANGELOG.md
48
CHANGELOG.md
|
@ -12,45 +12,69 @@ Release date: TBD
|
|||
|
||||
### Improvements
|
||||
|
||||
### Architectural Changes
|
||||
- Major version upgrade of Electron to v3.0.10. Electron is the underlying technology used to build the Desktop apps.
|
||||
[#892](https://github.com/mattermost/desktop/pull/892)
|
||||
|
||||
### Bug Fixes
|
||||
- Fixed several typos.
|
||||
[#905](https://github.com/mattermost/desktop/pull/905)
|
||||
|
||||
----
|
||||
|
||||
## Release v4.2.0
|
||||
|
||||
Release date: Nov 27, 2018
|
||||
|
||||
- Mattermost v4.2.0 contains a high level security fix. [Upgrading](http://docs.mattermost.com/administration/upgrade.html) is highly recommended. Details will be posted on our [security updates page](https://about.mattermost.com/security-updates/) 30 days after release as per the [Mattermost Responsible Disclosure Policy](https://www.mattermost.org/responsible-disclosure-policy/).
|
||||
|
||||
### Improvements
|
||||
|
||||
#### All Platforms
|
||||
- Added Portuguese spell checker
|
||||
- Added English (UK), Portuguese (BR), Spanish (ES) and Spanish (MX) to the spell checker.
|
||||
[#843](https://github.com/mattermost/desktop/pull/843)
|
||||
[#875](https://github.com/mattermost/desktop/pull/875)
|
||||
- Added `Ctrl/Cmd+F` shortcut to work as browser-like search.
|
||||
[#399](https://github.com/mattermost/desktop/issues/399)
|
||||
- Preserved case of first letter in spellcheck.
|
||||
[#869](https://github.com/mattermost/desktop/pull/869)
|
||||
- Added support for session expiry notification.
|
||||
[#866](https://github.com/mattermost/desktop/pull/866)
|
||||
|
||||
#### Windows
|
||||
- Set "app start on login" preference to default on and synchronize its state with config.json.
|
||||
- Set "app start on login" preference as enabled by default and synchronized its state with config.json.
|
||||
[#846](https://github.com/mattermost/desktop/pull/846)
|
||||
- Removed the ability to open UNC path and file:// links.
|
||||
[#881](https://github.com/mattermost/desktop/pull/881)
|
||||
|
||||
#### Mac
|
||||
- Add **.dmg** package to support installation.
|
||||
- Added **.dmg** package to support installation.
|
||||
[#588](https://github.com/mattermost/desktop/pull/588)
|
||||
- Support "Hide" option of Login Items in Preferences.
|
||||
- Added "Hide" option to 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
|
||||
- [tar.gz] Added support for using SVG icons for Linux application menus in place of PNG icons.
|
||||
[#815](https://github.com/mattermost/desktop/pull/815)
|
||||
- Updated categories in order to be listed under the appropriate submenu of the application starter.
|
||||
[#816](https://github.com/mattermost/desktop/pull/816)
|
||||
[#818](https://github.com/mattermost/desktop/pull/818)
|
||||
- Set "app start on login" preference to default on and synchronize its state with config.json.
|
||||
- Set "app start on login" preference as enabled by default and synchronized its state with config.json.
|
||||
[#846](https://github.com/mattermost/desktop/pull/846)
|
||||
- Added AppImage packages as unofficial build
|
||||
- Added AppImage packages as an unofficial build.
|
||||
[#864](https://github.com/mattermost/desktop/pull/864)
|
||||
|
||||
### Architectural Changes
|
||||
- Major version upgrade of Electron to v2.0.8. Electron is the underlying technology used to build the Desktop apps.
|
||||
- Major version upgrade of Electron to v2.0.12. 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`.
|
||||
[#882](https://github.com/mattermost/desktop/pull/882)
|
||||
- Artifact names are now configured via `electron-builder.json`.
|
||||
[#825](https://github.com/mattermost/desktop/pull/825)
|
||||
|
||||
### Bug Fixes
|
||||
### Contributors
|
||||
|
||||
Many thanks to all our contributors. In alphabetical order:
|
||||
|
||||
- [danmaas](https://github.com/danmaas), [hmhealey](https://github.com/hmhealey), [j1mc](https://github.com/j1mc),[jasonblais](https://github.com/jasonblais), [lieut-data](https://github.com/lieut-data), [rodcorsi](https://github.com/rodcorsi), [scherno2](https://github.com/scherno2), [sudheerDev](https://github.com/sudheerDev), [svelle](https://github.com/svelle), [torlenor](https://github.com/torlenor), [yuya-oc](https://github.com/yuya-oc)
|
||||
|
||||
----
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ The most popular front-end framework for developing responsive, mobile first pro
|
|||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2011-2016 Twitter, Inc.
|
||||
Copyright (c) 2011-2018 Twitter, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -514,7 +514,7 @@ A react component toolset for managing animations
|
|||
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2016, React Community
|
||||
Copyright (c) 2018, React Community
|
||||
Forked from React (https://github.com/facebook/react) Copyright 2013-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
|
|
19
babel.config.js
Normal file
19
babel.config.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
module.exports = (api) => { // eslint-disable-line import/no-commonjs
|
||||
api.cache.forever();
|
||||
return {
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: ['Electron >= 2.0'],
|
||||
node: '8.9',
|
||||
},
|
||||
}],
|
||||
'@babel/preset-react',
|
||||
],
|
||||
plugins: ['@babel/plugin-proposal-object-rest-spread', '@babel/plugin-proposal-class-properties'],
|
||||
};
|
||||
};
|
|
@ -76,7 +76,7 @@ Test coding style:
|
|||
$ npm run lint:js
|
||||
```
|
||||
|
||||
### Helper commmands
|
||||
### Helper commands
|
||||
|
||||
#### `npm run watch`
|
||||
Reload the application automatically when you have saved source codes.
|
||||
|
|
|
@ -61,7 +61,7 @@ Pre-work for the current release begins at the code complete date of the previou
|
|||
- Post links to final tickets for next RC to the Desktop App channel
|
||||
- Submit PRs for hotfixes against the release branch, and review, test and merge prior to next RC
|
||||
4. Build:
|
||||
- Push next RC to acceptance and announce in Destkop App channel with new RC link
|
||||
- Push next RC to acceptance and announce in Desktop App channel with new RC link
|
||||
5. PM:
|
||||
- Test the new RC to verify fixes merged to the release branch work and post in Desktop App channel after testing
|
||||
- Update the meta issue with download links to the new RCs and a list of approved fixes
|
||||
|
@ -152,4 +152,4 @@ If a bug fix release is required, run through the following steps:
|
|||
- Post and review [Mattermost Security Updates](https://about.mattermost.com/security-updates/) for the Desktop App
|
||||
- Update Security Issues spreadsheet with issue number from posted update (e.g. v3.2.0.1)
|
||||
- Confirm the Security Researchers list on the [Responsible Disclosure Policy](https://www.mattermost.org/responsible-disclosure-policy/) is up to date
|
||||
- Review community installers for the Desktop App and update version numbers if there are any discrepencies https://www.mattermost.org/installation/
|
||||
- Review community installers for the Desktop App and update version numbers if there are any discrepancies https://www.mattermost.org/installation/
|
||||
|
|
|
@ -105,7 +105,7 @@ The Mattermost desktop application offers:
|
|||
- Icon notifications from Windows Task Bar
|
||||
- Desktop notifications
|
||||
|
||||
See the Mattermost [help documention](http://docs.mattermost.com/help/getting-started/signing-in.html) for how to use the Mattermost team site.
|
||||
See the Mattermost [help documentation](http://docs.mattermost.com/help/getting-started/signing-in.html) for how to use the Mattermost team site.
|
||||
|
||||
|
||||
## Settings Page
|
||||
|
@ -121,7 +121,7 @@ The Settings Page is available from the **File** menu under **Settings** (Click
|
|||
- **Hide Menu Bar** (Windows, Linux)
|
||||
- This option hides the menu bar. Press "Alt" to show it.
|
||||
- **Show Icon on Menu Bar** (OS X)
|
||||
- The icon apeears on menu bar to indicate whether there are new messages or mention.
|
||||
- The icon appears on menu bar to indicate whether there are new messages or mention.
|
||||
- **Allow insecure contents**
|
||||
- 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.
|
||||
|
@ -180,7 +180,7 @@ Below lists menu options (shortcut keys are listed in brackets, `Ctrl` becomes `
|
|||
|
||||
Mattermost lets users configure [desktop notifications](http://docs.mattermost.com/help/getting-started/configuring-notifications.html#desktop-notifications) to alert users to new events in a team site.
|
||||
|
||||
For the Mattermost Windows application, these appear as ballon notifications from the task bar on Windows 7 and Windows 8.1, and as a "toast" pop-up on Windows 10.
|
||||
For the Mattermost Windows application, these appear as balloon notifications from the task bar on Windows 7 and Windows 8.1, and as a "toast" pop-up on Windows 10.
|
||||
|
||||
|
||||
## Start Menu and Task Bar shortcuts (Windows)
|
||||
|
|
41
package.json
41
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "mattermost-desktop",
|
||||
"productName": "Mattermost",
|
||||
"version": "4.2.0-develop",
|
||||
"version": "4.3.0-develop",
|
||||
"description": "Mattermost",
|
||||
"main": "main.js",
|
||||
"author": "Mattermost, Inc. <feedback@mattermost.com>",
|
||||
|
@ -26,29 +26,32 @@
|
|||
"watch:main": "node scripts/watch_main_and_preload.js",
|
||||
"watch:renderer": "webpack-dev-server --config webpack.config.renderer.js",
|
||||
"test": "npm-run-all test:* lint:*",
|
||||
"test:app": "cross-env NODE_ENV=production npm run build && mocha -r babel-register --reporter mocha-circleci-reporter --recursive test/specs",
|
||||
"test:app": "cross-env NODE_ENV=production npm run build && mocha -r @babel/register --reporter mocha-circleci-reporter --recursive test/specs",
|
||||
"package:all": "cross-env NODE_ENV=production npm-run-all check-build-config package:windows package:mac package:linux",
|
||||
"package:windows": "cross-env NODE_ENV=production npm-run-all check-build-config build && build --win --x64 --ia32 --publish=never",
|
||||
"package:mac": "cross-env NODE_ENV=production npm-run-all check-build-config build && build --mac --publish=never",
|
||||
"package:linux": "cross-env NODE_ENV=production npm-run-all check-build-config build && build --linux --x64 --ia32 --publish=never",
|
||||
"lint:js": "eslint --ignore-path .gitignore --ignore-pattern node_modules --ext .js --ext .jsx .",
|
||||
"fix:js": "eslint --ignore-path .gitignore --ignore-pattern node_modules --quiet --ext .js --ext .jsx . --fix",
|
||||
"check-build-config": "node -r babel-register scripts/check_build_config.js"
|
||||
"check-build-config": "node -r @babel/register scripts/check_build_config.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"7zip-bin": "^4.0.2",
|
||||
"@storybook/react": "^3.4.6",
|
||||
"babel-core": "^6.26.3",
|
||||
"@babel/core": "^7.1.6",
|
||||
"@babel/plugin-proposal-class-properties": "^7.1.0",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
|
||||
"@babel/preset-env": "^7.1.6",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/register": "^7.0.0",
|
||||
"@storybook/addon-actions": "^4.0.9",
|
||||
"@storybook/react": "^4.0.9",
|
||||
"babel-eslint": "^8.2.3",
|
||||
"babel-loader": "^7.1.4",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"babel-loader": "^8.0.4",
|
||||
"chai": "^4.1.2",
|
||||
"cross-env": "^5.1.6",
|
||||
"css-loader": "^0.28.11",
|
||||
"css-loader": "^1.0.1",
|
||||
"devtron": "^1.4.0",
|
||||
"electron": "2.0.8",
|
||||
"electron": "^3.0.10",
|
||||
"electron-builder": "20.14.7",
|
||||
"electron-builder-squirrel-windows": "~20.14.0",
|
||||
"electron-connect": "^0.6.3",
|
||||
|
@ -56,18 +59,18 @@
|
|||
"eslint-plugin-header": "^1.2.0",
|
||||
"eslint-plugin-import": "^2.12.0",
|
||||
"eslint-plugin-react": "^7.8.2",
|
||||
"file-loader": "^1.1.6",
|
||||
"file-loader": "^2.0.0",
|
||||
"mocha": "^5.2.0",
|
||||
"mocha-circleci-reporter": "0.0.3",
|
||||
"npm-run-all": "^4.1.3",
|
||||
"react": "^16.4.0",
|
||||
"react-dom": "^16.4.0",
|
||||
"spectron": "~3.8.0",
|
||||
"style-loader": "^0.21.0",
|
||||
"url-loader": "^1.0.1",
|
||||
"webpack": "^4.8.3",
|
||||
"webpack-cli": "^2.1.4",
|
||||
"webpack-dev-server": "^3.1.4",
|
||||
"webpack-merge": "^4.1.2"
|
||||
"spectron": "^5.0.0",
|
||||
"style-loader": "^0.23.1",
|
||||
"url-loader": "^1.1.2",
|
||||
"webpack": "^4.26.1",
|
||||
"webpack-cli": "^3.1.2",
|
||||
"webpack-dev-server": "^3.1.10",
|
||||
"webpack-merge": "^4.1.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ VERSION=`cat package.json | jq -r '.version'`
|
|||
SRC=$1
|
||||
DEST=$2
|
||||
|
||||
cp "${SRC}/mattermost-desktop-${VERSION}-win-ia32.zip" "${DEST}/"
|
||||
cp "${SRC}/mattermost-desktop-${VERSION}-win-x64.zip" "${DEST}/"
|
||||
cp "${SRC}/mattermost-desktop-${VERSION}-win-ia32.zip" "${DEST}/mattermost-desktop-${VERSION}-win32.zip"
|
||||
cp "${SRC}/mattermost-desktop-${VERSION}-win-x64.zip" "${DEST}/mattermost-desktop-${VERSION}-win64.zip"
|
||||
cp "${SRC}/mattermost-desktop-setup-${VERSION}-win.exe" "${DEST}/"
|
||||
cp "${SRC}"/mattermost-desktop-*.zip "${DEST}/"
|
||||
cp "${SRC}"/*.tar.gz "${DEST}/"
|
||||
|
|
|
@ -4,7 +4,7 @@ set -eu
|
|||
function print_link() {
|
||||
local URL="${1}"
|
||||
local CHECKSUM="$(curl -s -S -L "${URL}" | sha256sum | awk '{print $1}')"
|
||||
echo "${URL}"
|
||||
echo "- ${URL}"
|
||||
echo " - SHA-256 Checksum: \`${CHECKSUM}\`"
|
||||
}
|
||||
|
||||
|
@ -15,18 +15,26 @@ cat <<-MD
|
|||
### Mattermost Desktop ${VERSION} has been cut!
|
||||
The download links can be found below.
|
||||
|
||||
#### Windows
|
||||
$(print_link "${BASE_URL}/mattermost-setup-${VERSION}-win32.exe")
|
||||
$(print_link "${BASE_URL}/mattermost-setup-${VERSION}-win64.exe")
|
||||
|
||||
#### Windows - zip files
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-win32.zip")
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-win64.zip")
|
||||
|
||||
#### Mac
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-mac.dmg")
|
||||
|
||||
#### Linux
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-linux-ia32.tar.gz")
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-linux-x64.tar.gz")
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-linux-amd64.deb")
|
||||
|
||||
#### Linux (Unofficial) - deb files
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-linux-i386.deb")
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-linux-amd64.deb")
|
||||
|
||||
#### Mac
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-osx.tar.gz")
|
||||
|
||||
#### Windows
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-win32.zip")
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-win64.zip")
|
||||
$(print_link "${BASE_URL}/mattermost-setup-${VERSION}-win32.exe")
|
||||
$(print_link "${BASE_URL}/mattermost-setup-${VERSION}-win64.exe")
|
||||
#### Linux (Unofficial) - AppImage files
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-linux-i386.AppImage")
|
||||
$(print_link "${BASE_URL}/mattermost-desktop-${VERSION}-linux-x86_64.AppImage")
|
||||
MD
|
||||
|
|
1
src/.storybook/addons.js
Normal file
1
src/.storybook/addons.js
Normal file
|
@ -0,0 +1 @@
|
|||
import '@storybook/addon-actions/register';
|
|
@ -1,7 +1,18 @@
|
|||
const path = require("path");
|
||||
|
||||
const rendererConfig = require('../../webpack.config.renderer');
|
||||
|
||||
// https://storybook.js.org/configurations/custom-webpack-config/#full-control-mode--default
|
||||
module.exports = (baseConfig, env, defaultConfig) => {
|
||||
defaultConfig.resolve.modules = [path.resolve(__dirname, '../node_modules'), 'node_modules'];
|
||||
return defaultConfig;
|
||||
module.exports = (storybookBaseConfig, configType) => {
|
||||
// Avoid conflicting two instances of React due to two package.json structure
|
||||
storybookBaseConfig.resolve.modules.unshift(path.resolve(__dirname, '../node_modules'));
|
||||
|
||||
// Use same rules
|
||||
storybookBaseConfig.module.rules = rendererConfig.module.rules.concat({
|
||||
test: /\.(ttf|woff2?|eot|svg)/,
|
||||
use: {
|
||||
loader: 'file-loader'
|
||||
}
|
||||
});
|
||||
return storybookBaseConfig;
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ export default class MainPage extends React.Component {
|
|||
});
|
||||
});
|
||||
|
||||
// can't switch tabs sequencially for some reason...
|
||||
// can't switch tabs sequentially for some reason...
|
||||
ipcRenderer.on('switch-tab', (event, key) => {
|
||||
this.handleSelect(key);
|
||||
});
|
||||
|
|
|
@ -85,7 +85,7 @@ export default class MattermostView extends React.Component {
|
|||
}
|
||||
});
|
||||
|
||||
// Open link in browserWindow. for exmaple, attached files.
|
||||
// Open link in browserWindow. for example, attached files.
|
||||
webview.addEventListener('new-window', (e) => {
|
||||
const currentURL = url.parse(webview.getURL());
|
||||
const destURL = url.parse(e.url);
|
||||
|
@ -98,7 +98,7 @@ export default class MattermostView extends React.Component {
|
|||
if (destURL.path.match(/^\/api\/v[3-4]\/public\/files\//)) {
|
||||
ipcRenderer.send('download-url', e.url);
|
||||
} else {
|
||||
// New window should disable nodeIntergration.
|
||||
// New window should disable nodeIntegration.
|
||||
window.open(e.url, remote.app.getName(), 'nodeIntegration=no, show=yes');
|
||||
}
|
||||
} else {
|
||||
|
@ -119,7 +119,7 @@ export default class MattermostView extends React.Component {
|
|||
if (this.props.onSelectSpellCheckerLocale) {
|
||||
this.props.onSelectSpellCheckerLocale(locale);
|
||||
}
|
||||
webview.send('set-spellcheker');
|
||||
webview.send('set-spellchecker');
|
||||
},
|
||||
});
|
||||
this.setState({isContextMenuAdded: true});
|
||||
|
|
|
@ -22,12 +22,14 @@ function getSuggestionsMenus(win, suggestions) {
|
|||
function getSpellCheckerLocaleMenus(onSelectSpellCheckerLocale) {
|
||||
const currentLocale = ipcRenderer.sendSync('get-spellchecker-locale');
|
||||
const locales = [
|
||||
{language: 'English (UK)', locale: 'en-GB'},
|
||||
{language: 'English (US)', locale: 'en-US'},
|
||||
{language: 'French', locale: 'fr-FR'},
|
||||
{language: 'German', locale: 'de-DE'},
|
||||
{language: 'Spanish', locale: 'es-ES'},
|
||||
{language: 'Portuguese (BR)', locale: 'pt-BR'},
|
||||
{language: 'Spanish (ES)', locale: 'es-ES'},
|
||||
{language: 'Spanish (MX)', locale: 'es-MX'},
|
||||
{language: 'Dutch', locale: 'nl-NL'},
|
||||
{language: 'Portuguese', locale: 'pt-BR'},
|
||||
];
|
||||
return locales.map((l) => ({
|
||||
label: l.language,
|
||||
|
|
|
@ -141,7 +141,7 @@ function getUnreadCount() {
|
|||
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.
|
||||
// If active channel is DM, all posts is treated as mention.
|
||||
isMentioned = true;
|
||||
break;
|
||||
} else {
|
||||
|
@ -192,7 +192,7 @@ function setSpellChecker() {
|
|||
resetMisspelledState();
|
||||
}
|
||||
setSpellChecker();
|
||||
ipcRenderer.on('set-spellcheker', setSpellChecker);
|
||||
ipcRenderer.on('set-spellchecker', setSpellChecker);
|
||||
|
||||
// mattermost-webapp is SPA. So cache is not cleared due to no navigation.
|
||||
// We needed to manually clear cache to free memory in long-term-use.
|
||||
|
|
19
src/main.js
19
src/main.js
|
@ -174,14 +174,19 @@ const trayImages = (() => {
|
|||
}
|
||||
})();
|
||||
|
||||
// If there is already an instance, activate the window in the existing instace and quit this one
|
||||
if (app.makeSingleInstance((commandLine/*, workingDirectory*/) => {
|
||||
// If there is already an instance, activate the window in the existing instance and quit this one
|
||||
const gotTheLock = app.requestSingleInstanceLock();
|
||||
if (!gotTheLock) {
|
||||
app.exit();
|
||||
global.willAppQuit = true;
|
||||
}
|
||||
app.on('second-instance', (event, secondArgv) => {
|
||||
// Protocol handler for win32
|
||||
// argv: An array of the second instance’s (command line / deep linked) arguments
|
||||
if (process.platform === 'win32') {
|
||||
// Keep only command line / deep linked arguments
|
||||
if (Array.isArray(commandLine.slice(1)) && commandLine.slice(1).length > 0) {
|
||||
setDeeplinkingUrl(commandLine.slice(1)[0]);
|
||||
if (Array.isArray(secondArgv.slice(1)) && secondArgv.slice(1).length > 0) {
|
||||
setDeeplinkingUrl(secondArgv.slice(1)[0]);
|
||||
mainWindow.webContents.send('protocol-deeplink', deeplinkingUrl);
|
||||
}
|
||||
}
|
||||
|
@ -194,9 +199,7 @@ if (app.makeSingleInstance((commandLine/*, workingDirectory*/) => {
|
|||
mainWindow.show();
|
||||
}
|
||||
}
|
||||
})) {
|
||||
app.exit();
|
||||
}
|
||||
});
|
||||
|
||||
function shouldShowTrayIcon() {
|
||||
if (process.platform === 'win32') {
|
||||
|
@ -328,7 +331,7 @@ app.on('certificate-error', (event, webContents, url, error, certificate, callba
|
|||
});
|
||||
|
||||
app.on('gpu-process-crashed', (event, killed) => {
|
||||
console.log(`The GPU process has crached (killed = ${killed})`);
|
||||
console.log(`The GPU process has crashed (killed = ${killed})`);
|
||||
});
|
||||
|
||||
const loginCallbackMap = new Map();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "mattermost-desktop",
|
||||
"productName": "Mattermost",
|
||||
"desktopName": "Mattermost.desktop",
|
||||
"version": "4.2.0-develop",
|
||||
"version": "4.3.0-develop",
|
||||
"description": "Mattermost",
|
||||
"main": "main_bundle.js",
|
||||
"author": "Mattermost, Inc. <feedback@mattermost.com>",
|
||||
|
|
16
test/modules/utils.js
Normal file
16
test/modules/utils.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
function asyncSleep(timeout) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, timeout);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
asyncSleep,
|
||||
};
|
|
@ -75,7 +75,7 @@ describe('application', function desc() {
|
|||
url: env.mattermostURL,
|
||||
}));
|
||||
await this.app.restart();
|
||||
await this.app.client.waitUntilWindowLoaded();
|
||||
|
||||
const url = await this.app.client.getUrl();
|
||||
url.should.match(/\/index.html$/);
|
||||
});
|
||||
|
@ -86,7 +86,6 @@ describe('application', function desc() {
|
|||
url: env.mattermostURL,
|
||||
}));
|
||||
await this.app.restart();
|
||||
await this.app.client.waitUntilWindowLoaded();
|
||||
|
||||
const url = await this.app.client.getUrl();
|
||||
url.should.match(/\/index.html$/);
|
||||
|
|
|
@ -8,6 +8,7 @@ const http = require('http');
|
|||
const path = require('path');
|
||||
|
||||
const env = require('../../modules/environment');
|
||||
const {asyncSleep} = require('../../modules/utils');
|
||||
|
||||
describe('browser/index.html', function desc() {
|
||||
this.timeout(30000);
|
||||
|
@ -35,10 +36,11 @@ describe('browser/index.html', function desc() {
|
|||
this.server = http.createServer(serverCallback).listen(serverPort, '127.0.0.1');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
fs.writeFileSync(env.configFilePath, JSON.stringify(config));
|
||||
await asyncSleep(1000);
|
||||
this.app = env.getSpectronApp();
|
||||
return this.app.start();
|
||||
await this.app.start();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
@ -56,15 +58,12 @@ describe('browser/index.html', function desc() {
|
|||
url: env.mattermostURL,
|
||||
}));
|
||||
await this.app.restart();
|
||||
await this.app.client.waitUntilWindowLoaded();
|
||||
|
||||
const existing = await this.app.client.isExisting('#tabBar');
|
||||
existing.should.be.false;
|
||||
});
|
||||
|
||||
it('should set src of webview from config file', async () => {
|
||||
await this.app.client.waitUntilWindowLoaded();
|
||||
|
||||
const src0 = await this.app.client.getAttribute('#mattermostView0', 'src');
|
||||
src0.should.equal(config.teams[0].url);
|
||||
|
||||
|
@ -76,8 +75,6 @@ describe('browser/index.html', function desc() {
|
|||
});
|
||||
|
||||
it('should set name of tab from config file', async () => {
|
||||
await this.app.client.waitUntilWindowLoaded();
|
||||
|
||||
const tabName0 = await this.app.client.getText('#teamTabItem0');
|
||||
tabName0.should.equal(config.teams[0].name);
|
||||
|
||||
|
@ -86,7 +83,7 @@ describe('browser/index.html', function desc() {
|
|||
});
|
||||
|
||||
it('should show only the selected team', () => {
|
||||
return this.app.client.waitUntilWindowLoaded().
|
||||
return this.app.client.
|
||||
waitForVisible('#mattermostView0', 2000).
|
||||
waitForVisible('#mattermostView1', 2000, true).
|
||||
click('#teamTabItem1').
|
||||
|
@ -104,7 +101,7 @@ describe('browser/index.html', function desc() {
|
|||
}],
|
||||
}));
|
||||
await this.app.restart();
|
||||
return this.app.client.waitUntilWindowLoaded().
|
||||
return this.app.client.
|
||||
waitForVisible('#mattermostView0-fail', 20000);
|
||||
});
|
||||
|
||||
|
@ -117,7 +114,7 @@ describe('browser/index.html', function desc() {
|
|||
}],
|
||||
}));
|
||||
await this.app.restart();
|
||||
await this.app.client.waitUntilWindowLoaded().pause(2000);
|
||||
await this.app.client.pause(2000);
|
||||
const windowTitle = await this.app.browserWindow.getTitle();
|
||||
windowTitle.should.equal('Mattermost Desktop testing html');
|
||||
});
|
||||
|
@ -135,7 +132,7 @@ describe('browser/index.html', function desc() {
|
|||
}],
|
||||
}));
|
||||
await this.app.restart();
|
||||
await this.app.client.waitUntilWindowLoaded().pause(500);
|
||||
await this.app.client.pause(500);
|
||||
|
||||
// Note: Indices of webview are correct.
|
||||
// Somehow they are swapped.
|
||||
|
@ -174,7 +171,7 @@ describe('browser/index.html', function desc() {
|
|||
|
||||
// Note: Indices of webview are correct.
|
||||
// Somehow they are swapped.
|
||||
await this.app.client.waitUntilWindowLoaded().pause(500);
|
||||
await this.app.client.pause(500);
|
||||
|
||||
await this.app.client.
|
||||
windowByIndex(2).
|
||||
|
@ -198,7 +195,6 @@ describe('browser/index.html', function desc() {
|
|||
|
||||
it('should open the new server prompt after clicking the add button', async () => {
|
||||
// See settings_test for specs that cover the actual prompt
|
||||
await this.app.client.waitUntilWindowLoaded();
|
||||
await this.app.client.click('#addServerButton').pause(500);
|
||||
const isModalExisting = await this.app.client.isExisting('#newServerModal');
|
||||
isModalExisting.should.be.true;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
const fs = require('fs');
|
||||
|
||||
const env = require('../../modules/environment');
|
||||
const {asyncSleep} = require('../../modules/utils');
|
||||
|
||||
describe('browser/settings.html', function desc() {
|
||||
this.timeout(30000);
|
||||
|
@ -21,10 +22,11 @@ describe('browser/settings.html', function desc() {
|
|||
}],
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
fs.writeFileSync(env.configFilePath, JSON.stringify(config));
|
||||
await asyncSleep(1000);
|
||||
this.app = env.getSpectronApp();
|
||||
return this.app.start();
|
||||
await this.app.start();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
@ -34,7 +36,7 @@ describe('browser/settings.html', function desc() {
|
|||
});
|
||||
|
||||
describe('Close button', async () => {
|
||||
it('should show index.html when it\'s clicked', async () => {
|
||||
it.skip('should show index.html when it\'s clicked', async () => {
|
||||
env.addClientCommands(this.app.client);
|
||||
await this.app.client.
|
||||
loadSettingsPage().
|
||||
|
@ -89,7 +91,7 @@ describe('browser/settings.html', function desc() {
|
|||
});
|
||||
|
||||
describe('Server list', () => {
|
||||
it('should open the corresponding tab when a server list item is clicked', async () => {
|
||||
it.skip('should open the corresponding tab when a server list item is clicked', async () => {
|
||||
env.addClientCommands(this.app.client);
|
||||
await this.app.client.
|
||||
loadSettingsPage().
|
||||
|
@ -339,13 +341,9 @@ describe('browser/settings.html', function desc() {
|
|||
it('should remove existing team on click Remove', async () => {
|
||||
await this.app.client.
|
||||
element('.modal-dialog').click('.btn=Remove').
|
||||
pause(500);
|
||||
const existing = await this.app.client.isExisting(modalTitleSelector);
|
||||
existing.should.be.false;
|
||||
waitForExist(modalTitleSelector, 5000, true);
|
||||
|
||||
await this.app.client.
|
||||
click('#btnClose').
|
||||
pause(500);
|
||||
await this.app.client.waitForVisible('#serversSaveIndicator', 10000, true);
|
||||
|
||||
const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));
|
||||
savedConfig.teams.should.deep.equal(config.teams.slice(1));
|
||||
|
@ -354,13 +352,9 @@ describe('browser/settings.html', function desc() {
|
|||
it('should NOT remove existing team on click Cancel', async () => {
|
||||
await this.app.client.
|
||||
element('.modal-dialog').click('.btn=Cancel').
|
||||
pause(500);
|
||||
const existing = await this.app.client.isExisting(modalTitleSelector);
|
||||
existing.should.be.false;
|
||||
waitForExist(modalTitleSelector, 5000, true);
|
||||
|
||||
await this.app.client.
|
||||
click('#btnClose').
|
||||
pause(500);
|
||||
await this.app.client.waitForVisible('#serversSaveIndicator', 10000, true);
|
||||
|
||||
const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));
|
||||
savedConfig.teams.should.deep.equal(config.teams);
|
||||
|
|
|
@ -16,7 +16,7 @@ describe('PermissionManager', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should grant a permisson for an origin', function() {
|
||||
it('should grant a permission for an origin', function() {
|
||||
const ORIGIN = 'origin';
|
||||
const PERMISSION = 'permission';
|
||||
const manager = new PermissionManager(permissionFile);
|
||||
|
@ -33,7 +33,7 @@ describe('PermissionManager', function() {
|
|||
manager.isGranted(ORIGIN, PERMISSION + '_another').should.be.false;
|
||||
});
|
||||
|
||||
it('should deny a permisson for an origin', function() {
|
||||
it('should deny a permission for an origin', function() {
|
||||
const ORIGIN = 'origin';
|
||||
const PERMISSION = 'permission';
|
||||
const manager = new PermissionManager(permissionFile);
|
||||
|
@ -50,7 +50,7 @@ describe('PermissionManager', function() {
|
|||
manager.isDenied(ORIGIN, PERMISSION + '_another').should.be.false;
|
||||
});
|
||||
|
||||
it('should save permissons to the file', function() {
|
||||
it('should save permissions to the file', function() {
|
||||
const ORIGIN = 'origin';
|
||||
const PERMISSION = 'permission';
|
||||
const manager = new PermissionManager(permissionFile);
|
||||
|
|
Loading…
Reference in a new issue