mirror of
https://github.com/zulip/zulip-desktop.git
synced 2025-11-04 22:13:13 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6738b7087 | ||
|
|
f70432f4e3 | ||
|
|
60d693700e | ||
|
|
6e7333eab6 | ||
|
|
0d8dd1cd90 | ||
|
|
0ee3757774 | ||
|
|
811df9f381 | ||
|
|
8bd02cc7e4 | ||
|
|
9d5d221371 | ||
|
|
6006f1a3f8 | ||
|
|
4f96df4a34 | ||
|
|
a13558fa16 | ||
|
|
a1d19a385c | ||
|
|
c98667236e |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -7,6 +7,13 @@ node_modules/
|
|||||||
# Compiled binary build directory
|
# Compiled binary build directory
|
||||||
dist/
|
dist/
|
||||||
|
|
||||||
|
#snap generated files
|
||||||
|
snap/parts
|
||||||
|
snap/prime
|
||||||
|
snap/snap
|
||||||
|
snap/stage
|
||||||
|
snap/*.snap
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
const os = require('os');
|
const os = require('os');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const { app, shell, BrowserWindow, Menu } = require('electron');
|
const { app, shell, BrowserWindow, Menu, dialog } = require('electron');
|
||||||
|
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ class AppMenu {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
label: 'Toggle Sidebar',
|
label: 'Toggle Sidebar',
|
||||||
accelerator: 'CommandOrControl+S',
|
accelerator: 'CommandOrControl+Shift+S',
|
||||||
click(item, focusedWindow) {
|
click(item, focusedWindow) {
|
||||||
if (focusedWindow) {
|
if (focusedWindow) {
|
||||||
const newValue = !ConfigUtil.getConfigItem('showSidebar');
|
const newValue = !ConfigUtil.getConfigItem('showSidebar');
|
||||||
@@ -388,20 +388,32 @@ class AppMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static resetAppSettings() {
|
static resetAppSettings() {
|
||||||
|
const resetAppSettingsMessage = 'By proceeding you will be removing all connected organizations and preferences from Zulip.';
|
||||||
|
|
||||||
// We save App's settings/configurations in following files
|
// We save App's settings/configurations in following files
|
||||||
const settingFiles = ['window-state.json', 'domain.json', 'settings.json'];
|
const settingFiles = ['window-state.json', 'domain.json', 'settings.json'];
|
||||||
|
|
||||||
settingFiles.forEach(settingFileName => {
|
dialog.showMessageBox({
|
||||||
const getSettingFilesPath = path.join(app.getPath('appData'), appName, settingFileName);
|
type: 'warning',
|
||||||
fs.access(getSettingFilesPath, error => {
|
buttons: ['YES', 'NO'],
|
||||||
if (error) {
|
defaultId: 0,
|
||||||
console.log(error);
|
message: 'Are you sure?',
|
||||||
} else {
|
detail: resetAppSettingsMessage
|
||||||
fs.unlink(getSettingFilesPath, () => {
|
}, response => {
|
||||||
AppMenu.sendAction('clear-app-data');
|
if (response === 0) {
|
||||||
|
settingFiles.forEach(settingFileName => {
|
||||||
|
const getSettingFilesPath = path.join(app.getPath('appData'), appName, settingFileName);
|
||||||
|
fs.access(getSettingFilesPath, error => {
|
||||||
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
|
} else {
|
||||||
|
fs.unlink(getSettingFilesPath, () => {
|
||||||
|
AppMenu.sendAction('clear-app-data');
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1380
app/package-lock.json
generated
1380
app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -30,12 +30,13 @@
|
|||||||
"electron-is-dev": "0.3.0",
|
"electron-is-dev": "0.3.0",
|
||||||
"electron-log": "2.2.7",
|
"electron-log": "2.2.7",
|
||||||
"electron-spellchecker": "1.1.2",
|
"electron-spellchecker": "1.1.2",
|
||||||
"electron-updater": "2.18.2",
|
"electron-updater": "2.21.4",
|
||||||
"electron-window-state": "4.1.1",
|
"electron-window-state": "4.1.1",
|
||||||
"is-online": "7.0.0",
|
"is-online": "7.0.0",
|
||||||
"node-json-db": "0.7.3",
|
"node-json-db": "0.7.3",
|
||||||
"request": "2.81.0",
|
"request": "2.81.0",
|
||||||
"semver": "5.4.1",
|
"semver": "5.4.1",
|
||||||
|
"@sentry/electron": "0.5.0",
|
||||||
"wurl": "2.5.0"
|
"wurl": "2.5.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
|||||||
@@ -262,6 +262,11 @@ webview {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
webview.download-webview {
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
webview.onload {
|
webview.onload {
|
||||||
transition: opacity 1s cubic-bezier(0.95, 0.05, 0.795, 0.035);
|
transition: opacity 1s cubic-bezier(0.95, 0.05, 0.795, 0.035);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -604,4 +604,20 @@ input.toggle-round:checked+label:after {
|
|||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
width: 40%;
|
width: 40%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.settings-card {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.server-info-right {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
36
app/renderer/js/components/handle-external-link.js
Normal file
36
app/renderer/js/components/handle-external-link.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
const { shell } = require('electron').remote;
|
||||||
|
const LinkUtil = require('../utils/link-util');
|
||||||
|
const DomainUtil = require('../utils/domain-util');
|
||||||
|
const hiddenWebView = require('../components/hidden-webview');
|
||||||
|
|
||||||
|
function handleExternalLink(event) {
|
||||||
|
const { url } = event;
|
||||||
|
const domainPrefix = DomainUtil.getDomain(this.props.index).url;
|
||||||
|
|
||||||
|
// Whitelist URLs which are allowed to be opened in the app
|
||||||
|
const {
|
||||||
|
isInternalUrl: isWhiteListURL,
|
||||||
|
isUploadsUrl: isUploadsURL
|
||||||
|
} = LinkUtil.isInternal(domainPrefix, url);
|
||||||
|
|
||||||
|
if (isWhiteListURL) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// only open the pdf, mp3, mp4 etc.. in hidden webview since opening the
|
||||||
|
// image in webview will do nothing and will not save it
|
||||||
|
// whereas the pdf will be saved to user desktop once openened in
|
||||||
|
// in the hidden webview and will not trigger webview reload
|
||||||
|
if (!LinkUtil.isImage(url) && isUploadsURL) {
|
||||||
|
hiddenWebView.loadURL(url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open internal urls inside the current webview.
|
||||||
|
this.$el.loadURL(url);
|
||||||
|
} else {
|
||||||
|
event.preventDefault();
|
||||||
|
shell.openExternal(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = handleExternalLink;
|
||||||
9
app/renderer/js/components/hidden-webview.js
Normal file
9
app/renderer/js/components/hidden-webview.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// this hidden webview will be used to open pdf url and
|
||||||
|
// save it to user's computer without triggering a reload
|
||||||
|
// when navigating to pdf url to download it.
|
||||||
|
const hiddenWebView = document.createElement('webview');
|
||||||
|
hiddenWebView.classList.add('download-webview');
|
||||||
|
hiddenWebView.src = 'about:blank';
|
||||||
|
document.querySelector('#webviews-container').appendChild(hiddenWebView);
|
||||||
|
|
||||||
|
module.exports = hiddenWebView;
|
||||||
@@ -3,13 +3,12 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const DomainUtil = require(__dirname + '/../utils/domain-util.js');
|
|
||||||
const ConfigUtil = require(__dirname + '/../utils/config-util.js');
|
const ConfigUtil = require(__dirname + '/../utils/config-util.js');
|
||||||
const SystemUtil = require(__dirname + '/../utils/system-util.js');
|
const SystemUtil = require(__dirname + '/../utils/system-util.js');
|
||||||
const LinkUtil = require(__dirname + '/../utils/link-util.js');
|
const { app, dialog } = require('electron').remote;
|
||||||
const { shell, app, dialog } = require('electron').remote;
|
|
||||||
|
|
||||||
const BaseComponent = require(__dirname + '/../components/base.js');
|
const BaseComponent = require(__dirname + '/../components/base.js');
|
||||||
|
const handleExternalLink = require(__dirname + '/../components/handle-external-link.js');
|
||||||
|
|
||||||
const shouldSilentWebview = ConfigUtil.getConfigItem('silent');
|
const shouldSilentWebview = ConfigUtil.getConfigItem('silent');
|
||||||
class WebView extends BaseComponent {
|
class WebView extends BaseComponent {
|
||||||
@@ -46,16 +45,7 @@ class WebView extends BaseComponent {
|
|||||||
|
|
||||||
registerListeners() {
|
registerListeners() {
|
||||||
this.$el.addEventListener('new-window', event => {
|
this.$el.addEventListener('new-window', event => {
|
||||||
const { url } = event;
|
handleExternalLink.call(this, event);
|
||||||
const domainPrefix = DomainUtil.getDomain(this.props.index).url;
|
|
||||||
|
|
||||||
if (LinkUtil.isInternal(domainPrefix, url) || url === (domainPrefix + '/')) {
|
|
||||||
event.preventDefault();
|
|
||||||
this.$el.loadURL(url);
|
|
||||||
} else {
|
|
||||||
event.preventDefault();
|
|
||||||
shell.openExternal(url);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (shouldSilentWebview) {
|
if (shouldSilentWebview) {
|
||||||
|
|||||||
@@ -78,14 +78,6 @@ class ShortcutsSection extends BaseSection {
|
|||||||
<td><kbd>${userOSKey}</kbd><kbd>A</kbd></td>
|
<td><kbd>${userOSKey}</kbd><kbd>A</kbd></td>
|
||||||
<td>Select All</td>
|
<td>Select All</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td><kbd>${userOSKey}</kbd><kbd>F</kbd></td>
|
|
||||||
<td>Find</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><kbd>${userOSKey}</kbd><kbd>G</kbd></td>
|
|
||||||
<td>Find Next</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><kbd>Control</kbd><kbd>${userOSKey}</kbd><kbd>Space</kbd></td>
|
<td><kbd>Control</kbd><kbd>${userOSKey}</kbd><kbd>Space</kbd></td>
|
||||||
<td>Emoji & Symbols</td>
|
<td>Emoji & Symbols</td>
|
||||||
@@ -121,7 +113,7 @@ class ShortcutsSection extends BaseSection {
|
|||||||
<td>Actual Size</td>
|
<td>Actual Size</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><kbd>${userOSKey}</kbd><kbd>S</kbd></td>
|
<td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd></td>
|
||||||
<td>Toggle Sidebar</td>
|
<td>Toggle Sidebar</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -256,7 +248,7 @@ class ShortcutsSection extends BaseSection {
|
|||||||
<td>Actual Size</td>
|
<td>Actual Size</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><kbd>${userOSKey}</kbd> + <kbd>S</kbd></td>
|
<td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd></td>
|
||||||
<td>Toggle Sidebar</td>
|
<td>Toggle Sidebar</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const { ipcRenderer } = require('electron');
|
|||||||
const SetupSpellChecker = require('./spellchecker');
|
const SetupSpellChecker = require('./spellchecker');
|
||||||
|
|
||||||
const ConfigUtil = require(__dirname + '/utils/config-util.js');
|
const ConfigUtil = require(__dirname + '/utils/config-util.js');
|
||||||
|
const LinkUtil = require(__dirname + '/utils/link-util.js');
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-unassigned-import
|
// eslint-disable-next-line import/no-unassigned-import
|
||||||
require('./notification');
|
require('./notification');
|
||||||
@@ -23,7 +24,7 @@ const shortcut = () => {
|
|||||||
// Create the menu for the below
|
// Create the menu for the below
|
||||||
const node = document.querySelector('a[data-overlay-trigger=keyboard-shortcuts]');
|
const node = document.querySelector('a[data-overlay-trigger=keyboard-shortcuts]');
|
||||||
// Additional check
|
// Additional check
|
||||||
if (node.text.trim().toLowerCase() === 'keyboard shortcuts') {
|
if (node.text.trim().toLowerCase() === 'keyboard shortcuts (?)') {
|
||||||
node.click();
|
node.click();
|
||||||
} else {
|
} else {
|
||||||
// Atleast click the dropdown
|
// Atleast click the dropdown
|
||||||
@@ -55,6 +56,24 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
ipcRenderer.send('forward-message', 'reload-viewer');
|
ipcRenderer.send('forward-message', 'reload-viewer');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open image attachment link in the lightbox instead of opening in the default browser
|
||||||
|
const { $, lightbox } = window;
|
||||||
|
|
||||||
|
$('#main_div').on('click', '.message_content p a', function (e) {
|
||||||
|
const url = $(this).attr('href');
|
||||||
|
|
||||||
|
if (LinkUtil.isImage(url)) {
|
||||||
|
const $img = $(this).parent().siblings('.message_inline_image').find('img');
|
||||||
|
|
||||||
|
// prevent the image link from opening in a new page.
|
||||||
|
e.preventDefault();
|
||||||
|
// prevent the message compose dialog from happening.
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
lightbox.open($img);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clean up spellchecker events after you navigate away from this page;
|
// Clean up spellchecker events after you navigate away from this page;
|
||||||
@@ -63,3 +82,10 @@ window.addEventListener('beforeunload', () => {
|
|||||||
SetupSpellChecker.unsubscribeSpellChecker();
|
SetupSpellChecker.unsubscribeSpellChecker();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// electron's globalShortcut can cause unexpected results
|
||||||
|
// so adding the reload shortcut in the old-school way
|
||||||
|
document.addEventListener('keydown', event => {
|
||||||
|
if (event.code === 'F5') {
|
||||||
|
ipcRenderer.send('forward-message', 'hard-reload');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -19,7 +19,20 @@ class LinkUtil {
|
|||||||
const currentDomain = wurl('hostname', currentUrl);
|
const currentDomain = wurl('hostname', currentUrl);
|
||||||
const newDomain = wurl('hostname', newUrl);
|
const newDomain = wurl('hostname', newUrl);
|
||||||
|
|
||||||
return (currentDomain === newDomain) && newUrl.includes('/#narrow');
|
const sameDomainUrl = (currentDomain === newDomain || newUrl === currentUrl + '/');
|
||||||
|
const isUploadsUrl = newUrl.includes(currentUrl + '/user_uploads/');
|
||||||
|
const isInternalUrl = newUrl.includes('/#narrow') || isUploadsUrl;
|
||||||
|
|
||||||
|
return {
|
||||||
|
isInternalUrl: sameDomainUrl && isInternalUrl,
|
||||||
|
isUploadsUrl
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
isImage(url) {
|
||||||
|
// test for images extension as well as urls like .png?s=100
|
||||||
|
const isImageUrl = /\.(bmp|gif|jpg|jpeg|png|webp)\?*.*$/i;
|
||||||
|
return isImageUrl.test(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ To build and run the app from source, you'll need the following:
|
|||||||
* [Python](https://www.python.org/downloads/release/python-2713/)
|
* [Python](https://www.python.org/downloads/release/python-2713/)
|
||||||
(v2.7.x recommended)
|
(v2.7.x recommended)
|
||||||
* A C++ compiler compatible with C++11
|
* A C++ compiler compatible with C++11
|
||||||
|
* Linux users also need [Snapcraft](https://snapcraft.io/)
|
||||||
* Development headers for the libXext, libXtst, and libxkbfile libraries
|
* Development headers for the libXext, libXtst, and libxkbfile libraries
|
||||||
|
|
||||||
### Debian/Ubuntu and friends
|
### Debian/Ubuntu and friends
|
||||||
@@ -25,7 +26,7 @@ manager (see [here][nodesource-install] for more on the first command):
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
|
$ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
|
||||||
$ sudo apt install git nodejs python build-essential libxext-dev libxtst-dev libxkbfile-dev libgconf-2-4
|
$ sudo apt install git nodejs python build-essential snapcraft libxext-dev libxtst-dev libxkbfile-dev libgconf-2-4
|
||||||
```
|
```
|
||||||
|
|
||||||
[nodesource-install]: https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions
|
[nodesource-install]: https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions
|
||||||
@@ -76,7 +77,7 @@ This command will produce distributable packages or installers for the
|
|||||||
operating system you're running on:
|
operating system you're running on:
|
||||||
* on Windows, a Windows installer file
|
* on Windows, a Windows installer file
|
||||||
* on macOS, a `.dmg` file
|
* on macOS, a `.dmg` file
|
||||||
* on Linux, a plain `.zip` file as well as a `.deb` file and an
|
* on Linux, a plain `.zip` file as well as a `.deb` file, `.snap` file and an
|
||||||
`AppImage` file.
|
`AppImage` file.
|
||||||
To generate all three types, you will need all three operating
|
To generate all three types, you will need all three operating
|
||||||
systems.
|
systems.
|
||||||
|
|||||||
9854
package-lock.json
generated
9854
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -22,7 +22,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron app --disable-http-cache --no-electron-connect",
|
"start": "electron app --disable-http-cache --no-electron-connect",
|
||||||
"reinstall": "./tools/reinstall-node-modules",
|
"reinstall": "node ./tools/reinstall-node-modules.js",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"test": "xo",
|
"test": "xo",
|
||||||
"test-e2e": "gulp test-e2e",
|
"test-e2e": "gulp test-e2e",
|
||||||
@@ -55,7 +55,8 @@
|
|||||||
"target": [
|
"target": [
|
||||||
"deb",
|
"deb",
|
||||||
"zip",
|
"zip",
|
||||||
"AppImage"
|
"AppImage",
|
||||||
|
"snap"
|
||||||
],
|
],
|
||||||
"maintainer": "Akash Nimare <svnitakash@gmail.com>"
|
"maintainer": "Akash Nimare <svnitakash@gmail.com>"
|
||||||
},
|
},
|
||||||
@@ -64,6 +65,9 @@
|
|||||||
"afterInstall": "./scripts/debian-add-repo.sh",
|
"afterInstall": "./scripts/debian-add-repo.sh",
|
||||||
"afterRemove": "./scripts/debian-uninstaller.sh"
|
"afterRemove": "./scripts/debian-uninstaller.sh"
|
||||||
},
|
},
|
||||||
|
"snap": {
|
||||||
|
"synopsis": "Zulip Desktop App"
|
||||||
|
},
|
||||||
"dmg": {
|
"dmg": {
|
||||||
"background": "build/appdmg.png",
|
"background": "build/appdmg.png",
|
||||||
"icon": "build/icon.icns",
|
"icon": "build/icon.icns",
|
||||||
@@ -114,7 +118,7 @@
|
|||||||
"cp-file": "^5.0.0",
|
"cp-file": "^5.0.0",
|
||||||
"devtron": "1.4.0",
|
"devtron": "1.4.0",
|
||||||
"electron": "1.8.4",
|
"electron": "1.8.4",
|
||||||
"electron-builder": "19.53.6",
|
"electron-builder": "20.8.1",
|
||||||
"electron-connect": "0.6.2",
|
"electron-connect": "0.6.2",
|
||||||
"electron-debug": "1.4.0",
|
"electron-debug": "1.4.0",
|
||||||
"google-translate-api": "2.3.0",
|
"google-translate-api": "2.3.0",
|
||||||
|
|||||||
37
snap/snapcraft.yaml
Normal file
37
snap/snapcraft.yaml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
name: zulip
|
||||||
|
version: 1.8.2
|
||||||
|
summary: Zulip
|
||||||
|
description: Zulip Desktop Client for Linux
|
||||||
|
confinement: strict
|
||||||
|
grade: stable
|
||||||
|
icon: ../build/icon.png
|
||||||
|
apps:
|
||||||
|
zulip:
|
||||||
|
command: env TMPDIR=$XDG_RUNTIME_DIR desktop-launch $SNAP/zulip
|
||||||
|
plugs:
|
||||||
|
- desktop
|
||||||
|
- desktop-legacy
|
||||||
|
- home
|
||||||
|
- x11
|
||||||
|
- unity7
|
||||||
|
- browser-support
|
||||||
|
- network
|
||||||
|
- gsettings
|
||||||
|
- pulseaudio
|
||||||
|
- opengl
|
||||||
|
parts:
|
||||||
|
app:
|
||||||
|
plugin: dump
|
||||||
|
stage-packages:
|
||||||
|
- libasound2
|
||||||
|
- libgconf2-4
|
||||||
|
- libnotify4
|
||||||
|
- libnspr4
|
||||||
|
- libnss3
|
||||||
|
- libpcre3
|
||||||
|
- libpulse0
|
||||||
|
- libxss1
|
||||||
|
- libxtst6
|
||||||
|
source: ../dist/linux-unpacked
|
||||||
|
after:
|
||||||
|
- desktop-gtk2
|
||||||
17
tests/test-new-organization.js
Normal file
17
tests/test-new-organization.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
const test = require('tape')
|
||||||
|
const setup = require('./setup')
|
||||||
|
|
||||||
|
// Create new org link should open in the default browser [WIP]
|
||||||
|
|
||||||
|
test('new-org-link', function (t) {
|
||||||
|
t.timeoutAfter(50e3)
|
||||||
|
setup.resetTestDataDir()
|
||||||
|
const app = setup.createApp()
|
||||||
|
setup.waitForLoad(app, t)
|
||||||
|
.then(() => app.client.windowByIndex(1)) // focus on webview
|
||||||
|
.then(() => app.client.click('#open-create-org-link')) // Click on new org link button
|
||||||
|
.then(() => setup.wait(5000))
|
||||||
|
.then(() => setup.endTest(app, t),
|
||||||
|
(err) => setup.endTest(app, t, err || 'error'))
|
||||||
|
})
|
||||||
|
|
||||||
18
tools/reinstall-node-modules.js
Normal file
18
tools/reinstall-node-modules.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
const {exec} = require('child_process');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const isWindows = process.platform === 'win32';
|
||||||
|
const command = path.join(__dirname, `reinstall-node-modules${isWindows ? '.cmd' : ''}`);
|
||||||
|
|
||||||
|
const proc = exec(command, error => {
|
||||||
|
if (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
proc.stdout.on('data', data => console.log(data.toString()));
|
||||||
|
proc.stderr.on('data', data => console.error(data.toString()));
|
||||||
|
proc.on('exit', code => {
|
||||||
|
process.exit(code);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user