mirror of
https://github.com/zulip/zulip-desktop.git
synced 2025-10-23 16:13:37 +00:00
Compare commits
17 Commits
v2.3.5
...
v2.3.7-bet
Author | SHA1 | Date | |
---|---|---|---|
|
50647e330b | ||
|
73dc3db436 | ||
|
09cf21bf49 | ||
|
c30d0cc77b | ||
|
872ad4d3e7 | ||
|
6fd9e1be8b | ||
|
76c7f24161 | ||
|
f9c270492c | ||
|
371c580934 | ||
|
3eec4c2209 | ||
|
debbfb6b7d | ||
|
8bd1492586 | ||
|
1115c6d5c3 | ||
|
9ba279213c | ||
|
89c35cb1d4 | ||
|
21d6eb52c5 | ||
|
aa1538837b |
23
README.md
23
README.md
@@ -2,31 +2,26 @@
|
||||
[](https://travis-ci.org/zulip/zulip-electron)
|
||||
[](https://ci.appveyor.com/project/akashnimare/zulip-electron/branch/master)
|
||||
[](https://github.com/sindresorhus/xo)
|
||||
[](https://chat.zulip.org)
|
||||
|
||||
Desktop client for Zulip. Available for Mac, Linux and Windows.
|
||||
Desktop client for Zulip. Available for Mac, Linux, and Windows.
|
||||
|
||||
<img src="http://i.imgur.com/ChzTq4F.png"/>
|
||||
|
||||
# Download
|
||||
Please see [installation guide](https://zulipchat.com/help/desktop-app-install-guide).
|
||||
Please see the [installation guide](https://zulipchat.com/help/desktop-app-install-guide).
|
||||
|
||||
# Features
|
||||
* Sign in to multiple teams
|
||||
* Desktop Notifications with inline reply support
|
||||
* Multilanguage SpellChecker
|
||||
* OSX/Win/Linux installers
|
||||
* Automatic Updates (macOS/Windows/Linux)
|
||||
* Keyboard shortcuts
|
||||
|
||||
# Development
|
||||
Please see our [development guide](./development.md) to get started and run app locally.
|
||||
* Desktop notifications with inline reply
|
||||
* Tray/dock integration
|
||||
* Multi-language spell checker
|
||||
* Automatic updates
|
||||
|
||||
# Contribute
|
||||
|
||||
If you want to contribute please make sure to read [our documentation about contributing](./CONTRIBUTING.md) first.
|
||||
|
||||
* [Issue Tracker](https://github.com/zulip/zulip-electron/issues)
|
||||
* [Source Code](https://github.com/zulip/zulip-electron/)
|
||||
First, join us on the [Zulip community server](https://zulip.readthedocs.io/en/latest/contributing/chat-zulip-org.html)!
|
||||
Also see our [contribution guidelines](./CONTRIBUTING.md) and our [development guide](./development.md).
|
||||
|
||||
# License
|
||||
Released under the [Apache-2.0](./LICENSE) license.
|
||||
|
@@ -176,7 +176,7 @@ app.on('ready', () => {
|
||||
});
|
||||
|
||||
page.once('did-frame-finish-load', () => {
|
||||
// Initate auto-updates on MacOS and Windows
|
||||
// Initiate auto-updates on MacOS and Windows
|
||||
if (ConfigUtil.getConfigItem('autoUpdate')) {
|
||||
appUpdater();
|
||||
}
|
||||
@@ -196,6 +196,32 @@ app.on('ready', () => {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
// Show pdf in a new BrowserWindow
|
||||
ipcMain.on('pdf-view', (event, url) => {
|
||||
// Paddings for pdfWindow so that it fits into the main browserWindow
|
||||
const paddingWidth = 55;
|
||||
const paddingHeight = 22;
|
||||
|
||||
// Get the config of main browserWindow
|
||||
const mainWindowState = global.mainWindowState;
|
||||
|
||||
// Window to view the pdf file
|
||||
const pdfWindow = new electron.BrowserWindow({
|
||||
x: mainWindowState.x + paddingWidth,
|
||||
y: mainWindowState.y + paddingHeight,
|
||||
width: mainWindowState.width - paddingWidth,
|
||||
height: mainWindowState.height - paddingHeight,
|
||||
webPreferences: {
|
||||
plugins: true,
|
||||
partition: 'persist:webviewsession'
|
||||
}
|
||||
});
|
||||
pdfWindow.loadURL(url);
|
||||
|
||||
// We don't want to have the menu bar in pdf window
|
||||
pdfWindow.setMenu(null);
|
||||
});
|
||||
|
||||
// Reload full app not just webview, useful in debugging
|
||||
ipcMain.on('reload-full-app', () => {
|
||||
mainWindow.reload();
|
||||
@@ -249,7 +275,7 @@ app.on('ready', () => {
|
||||
item.setSavePath(filePath);
|
||||
item.on('updated', (event, state) => {
|
||||
switch (state) {
|
||||
case 'interrupted' : {
|
||||
case 'interrupted': {
|
||||
// Can interrupted to due to network error, cancel download then
|
||||
console.log('Download interrupted, cancelling and fallback to dialog download.');
|
||||
item.cancel();
|
||||
|
@@ -4,6 +4,7 @@ const { Notification } = require('electron');
|
||||
const request = require('request');
|
||||
const semver = require('semver');
|
||||
const ConfigUtil = require('../renderer/js/utils/config-util');
|
||||
const ProxyUtil = require('../renderer/js/utils/proxy-util');
|
||||
const LinuxUpdateUtil = require('../renderer/js/utils/linux-update-util');
|
||||
const Logger = require('../renderer/js/utils/logger-util');
|
||||
|
||||
@@ -15,10 +16,12 @@ const logger = new Logger({
|
||||
function linuxUpdateNotification() {
|
||||
let url = 'https://api.github.com/repos/zulip/zulip-electron/releases';
|
||||
url = ConfigUtil.getConfigItem('betaUpdate') ? url : url + '/latest';
|
||||
const proxyEnabled = ConfigUtil.getConfigItem('useManualProxy') || ConfigUtil.getConfigItem('useSystemProxy');
|
||||
|
||||
const options = {
|
||||
url,
|
||||
headers: {'User-Agent': 'request'}
|
||||
headers: {'User-Agent': 'request'},
|
||||
proxy: proxyEnabled ? ProxyUtil.getProxy(url) : ''
|
||||
};
|
||||
|
||||
request(options, (error, response, body) => {
|
||||
|
139
app/package-lock.json
generated
139
app/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "zulip",
|
||||
"version": "2.3.5",
|
||||
"version": "2.3.6",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -37,56 +37,91 @@
|
||||
}
|
||||
},
|
||||
"@sentry/browser": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-0.5.4.tgz",
|
||||
"integrity": "sha1-Yh/5chgrc7YoVlhLkvxl/elpBMw=",
|
||||
"version": "4.0.0-beta.12",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-4.0.0-beta.12.tgz",
|
||||
"integrity": "sha512-At8qp2aM4q4KnuIQuC6wbbQ6gLykmzwZdHwWRN99GS5TNC7kXJNgO9WgiMLadA4ph12JtC1petrUIgY8t+aoSA==",
|
||||
"requires": {
|
||||
"@sentry/core": "0.5.4",
|
||||
"@sentry/shim": "0.5.4"
|
||||
"@sentry/core": "4.0.0-beta.12",
|
||||
"@sentry/hub": "4.0.0-beta.12",
|
||||
"@sentry/minimal": "4.0.0-beta.12",
|
||||
"@sentry/types": "4.0.0-beta.12",
|
||||
"@sentry/utils": "4.0.0-beta.12"
|
||||
}
|
||||
},
|
||||
"@sentry/core": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-0.5.4.tgz",
|
||||
"integrity": "sha1-mwqEK0QhMbOAG65wviyk6cUQV04=",
|
||||
"version": "4.0.0-beta.12",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-4.0.0-beta.12.tgz",
|
||||
"integrity": "sha512-DGZqBOHejHPYP2I0MdF7APEaews7gLrfxHDh9rbwDLJJiuwPE/ridH97amxy/j2g4X4EZEc3sO3Ptv4nMaHK+Q==",
|
||||
"requires": {
|
||||
"@sentry/shim": "0.5.4"
|
||||
"@sentry/hub": "4.0.0-beta.12",
|
||||
"@sentry/minimal": "4.0.0-beta.12",
|
||||
"@sentry/types": "4.0.0-beta.12",
|
||||
"@sentry/utils": "4.0.0-beta.12"
|
||||
}
|
||||
},
|
||||
"@sentry/electron": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/electron/-/electron-0.5.5.tgz",
|
||||
"integrity": "sha1-kInWNC22xr1sCSpTdHcIAx1ft8M=",
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/electron/-/electron-0.8.1.tgz",
|
||||
"integrity": "sha512-y3CJ7547Rhpg+6bnGP0mXLj9pgpjMLaRji704TdzTV0afr8KamBXySNhNHosHLaKm1OLg6p8U4pdVB7xQZ+X3g==",
|
||||
"requires": {
|
||||
"@sentry/browser": "0.5.4",
|
||||
"@sentry/core": "0.5.4",
|
||||
"@sentry/node": "0.5.4",
|
||||
"@sentry/shim": "0.5.4",
|
||||
"@sentry/utils": "0.5.4",
|
||||
"@sentry/browser": "4.0.0-beta.12",
|
||||
"@sentry/core": "4.0.0-beta.12",
|
||||
"@sentry/hub": "4.0.0-beta.12",
|
||||
"@sentry/minimal": "4.0.0-beta.12",
|
||||
"@sentry/node": "4.0.0-beta.12",
|
||||
"@sentry/types": "4.0.0-beta.12",
|
||||
"@sentry/utils": "4.0.0-beta.12",
|
||||
"electron-fetch": "^1.1.0",
|
||||
"form-data": "^2.3.2",
|
||||
"util.promisify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@sentry/node": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-0.5.4.tgz",
|
||||
"integrity": "sha1-s+c0nRs2EjmVkDbqrhnOvzVkw9M=",
|
||||
"@sentry/hub": {
|
||||
"version": "4.0.0-beta.12",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-4.0.0-beta.12.tgz",
|
||||
"integrity": "sha512-fmLaPaD6F/ViWDTz3hRVnNvqgnAmX0foDsUGVVp0Dt2lT9apM5NECKV6761XFVMrbGGulCg9fguv2KV5IbQcIw==",
|
||||
"requires": {
|
||||
"@sentry/core": "0.5.4",
|
||||
"@sentry/shim": "0.5.4",
|
||||
"raven": "^2.6.0"
|
||||
"@sentry/types": "4.0.0-beta.12",
|
||||
"@sentry/utils": "4.0.0-beta.12"
|
||||
}
|
||||
},
|
||||
"@sentry/shim": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/shim/-/shim-0.5.4.tgz",
|
||||
"integrity": "sha1-y4JrGjR2WuXhsh5h3y3vL42pHcE="
|
||||
"@sentry/minimal": {
|
||||
"version": "4.0.0-beta.12",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-4.0.0-beta.12.tgz",
|
||||
"integrity": "sha512-1V3Lrm7wIOOqG+l1uyVZ7iQysPGXszwfsd6DTVDPT19PSey7+KbvPNcQfh+GqMRMz8jzyg9XlwUxckg7qbSztQ==",
|
||||
"requires": {
|
||||
"@sentry/hub": "4.0.0-beta.12",
|
||||
"@sentry/types": "4.0.0-beta.12"
|
||||
}
|
||||
},
|
||||
"@sentry/node": {
|
||||
"version": "4.0.0-beta.12",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-4.0.0-beta.12.tgz",
|
||||
"integrity": "sha512-oekXtdaaElt/lSfyKtAyTLcTofciMRuptsGOTMX4qQ7hoHESB6DUw55Or/RRMaJYm/nckM2VFzWDATd20NVV4w==",
|
||||
"requires": {
|
||||
"@sentry/core": "4.0.0-beta.12",
|
||||
"@sentry/hub": "4.0.0-beta.12",
|
||||
"@sentry/minimal": "4.0.0-beta.12",
|
||||
"@sentry/types": "4.0.0-beta.12",
|
||||
"@sentry/utils": "4.0.0-beta.12",
|
||||
"cookie": "0.3.1",
|
||||
"lsmod": "1.0.0",
|
||||
"md5": "2.2.1",
|
||||
"stack-trace": "0.0.10"
|
||||
}
|
||||
},
|
||||
"@sentry/types": {
|
||||
"version": "4.0.0-beta.12",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-4.0.0-beta.12.tgz",
|
||||
"integrity": "sha512-xRsTfRcb8OvMbLjl64bPNv3feHiXBprtRZqTlVUbDJmSNrm8wg+tKIPYsP90dxKc50CZBk59urIbgvpPg0mCLw=="
|
||||
},
|
||||
"@sentry/utils": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-0.5.4.tgz",
|
||||
"integrity": "sha1-jt54rOlgIW3WMv1WHIP1AGLlruE="
|
||||
"version": "4.0.0-beta.12",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-4.0.0-beta.12.tgz",
|
||||
"integrity": "sha512-lpTE2GlaztATlFfIWMN8RSQFP0z6PkPPoDz0KKRmK4ZxjPxVX2sAGbKJGCpf9fdUG23NVg3FNiqfpUbjhvd9YA==",
|
||||
"requires": {
|
||||
"@sentry/types": "4.0.0-beta.12"
|
||||
}
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
"version": "0.7.0",
|
||||
@@ -437,9 +472,9 @@
|
||||
}
|
||||
},
|
||||
"electron-fetch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-fetch/-/electron-fetch-1.1.0.tgz",
|
||||
"integrity": "sha512-eBtqbB522c/RJwC5v1yF/Y0SMVLiwel98BWGx050GucWbKlejHtPkfpq/vfMxCjg0SGpHGUISYUaMfu65QH+xg==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/electron-fetch/-/electron-fetch-1.2.1.tgz",
|
||||
"integrity": "sha512-pQy0el/vxu30sL9JjXss8yZL+ztRnmioffPQsLL4UYnfSUFTuGBlgCPCxxKYJV7y52WfaIEZQ9tlbac1YHrH0w==",
|
||||
"requires": {
|
||||
"encoding": "^0.1.12"
|
||||
}
|
||||
@@ -538,9 +573,9 @@
|
||||
}
|
||||
},
|
||||
"es-abstract": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
|
||||
"integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.11.0.tgz",
|
||||
"integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==",
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.1.1",
|
||||
"function-bind": "^1.1.1",
|
||||
@@ -829,9 +864,9 @@
|
||||
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
||||
},
|
||||
"is-callable": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
|
||||
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz",
|
||||
"integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI="
|
||||
},
|
||||
"is-date-object": {
|
||||
"version": "1.0.1",
|
||||
@@ -1024,6 +1059,11 @@
|
||||
"yallist": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"lsmod": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lsmod/-/lsmod-1.0.0.tgz",
|
||||
"integrity": "sha1-mgD3bco26yP6BTUK/htYXUKZ5ks="
|
||||
},
|
||||
"md5": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz",
|
||||
@@ -1309,18 +1349,6 @@
|
||||
"strict-uri-encode": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"raven": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/raven/-/raven-2.6.3.tgz",
|
||||
"integrity": "sha512-bKre7qlDW+y1+G2bUtCuntdDYc8o5v1T233t0vmJfbj8ttGOgLrGRlYB8saelVMW9KUAJNLrhFkAKOwFWFJonw==",
|
||||
"requires": {
|
||||
"cookie": "0.3.1",
|
||||
"md5": "^2.2.1",
|
||||
"stack-trace": "0.0.10",
|
||||
"timed-out": "4.0.1",
|
||||
"uuid": "3.0.0"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
@@ -1600,11 +1628,6 @@
|
||||
"object.getownpropertydescriptors": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.0.tgz",
|
||||
"integrity": "sha1-Zyj8BFnEUNeWqZwxg3VpvfZy1yg="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "zulip",
|
||||
"productName": "Zulip",
|
||||
"version": "2.3.5",
|
||||
"version": "2.3.6",
|
||||
"description": "Zulip Desktop App",
|
||||
"license": "Apache-2.0",
|
||||
"copyright": "Kandra Labs, Inc.",
|
||||
@@ -27,7 +27,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@electron-elements/send-feedback": "1.0.7",
|
||||
"@sentry/electron": "0.5.5",
|
||||
"@sentry/electron": "0.8.1",
|
||||
"adm-zip": "0.4.11",
|
||||
"auto-launch": "5.0.5",
|
||||
"electron-is-dev": "0.3.0",
|
||||
|
@@ -21,11 +21,19 @@ function handleExternalLink(event) {
|
||||
if (isWhiteListURL) {
|
||||
event.preventDefault();
|
||||
|
||||
// download txt, pdf, mp3, mp4 etc.. by using downloadURL in the
|
||||
// Show pdf attachments in a new window
|
||||
|
||||
if (LinkUtil.isPDF(url) && isUploadsURL) {
|
||||
ipcRenderer.send('pdf-view', url);
|
||||
return;
|
||||
}
|
||||
|
||||
// download txt, mp3, mp4 etc.. by using downloadURL in the
|
||||
// main process which allows the user to save the files to their desktop
|
||||
// and not trigger webview reload while image in webview will
|
||||
// do nothing and will not save it
|
||||
if (!LinkUtil.isImage(url) && isUploadsURL) {
|
||||
|
||||
if (!LinkUtil.isImage(url) && !LinkUtil.isPDF(url) && isUploadsURL) {
|
||||
ipcRenderer.send('downloadFile', url, downloadPath);
|
||||
ipcRenderer.once('downloadFileCompleted', (event, filePath, fileName) => {
|
||||
const downloadNotification = new Notification('Download Complete', {
|
||||
|
@@ -14,9 +14,9 @@ const ConfigUtil = require(__dirname + '/js/utils/config-util.js');
|
||||
const DNDUtil = require(__dirname + '/js/utils/dnd-util.js');
|
||||
const ReconnectUtil = require(__dirname + '/js/utils/reconnect-util.js');
|
||||
const Logger = require(__dirname + '/js/utils/logger-util.js');
|
||||
const { feedbackHolder } = require(__dirname + '/js/feedback.js');
|
||||
const CommonUtil = require(__dirname + '/js/utils/common-util.js');
|
||||
|
||||
const escape = require('escape-html');
|
||||
const { feedbackHolder } = require(__dirname + '/js/feedback.js');
|
||||
|
||||
const logger = new Logger({
|
||||
file: 'errors.log',
|
||||
@@ -179,7 +179,7 @@ class ServerManagerView {
|
||||
index,
|
||||
tabIndex,
|
||||
url: server.url,
|
||||
name: server.alias,
|
||||
name: CommonUtil.decodeString(server.alias),
|
||||
isActive: () => {
|
||||
return index === this.activeTabIndex;
|
||||
},
|
||||
@@ -253,7 +253,7 @@ class ServerManagerView {
|
||||
}
|
||||
|
||||
onHover(index, serverName) {
|
||||
this.$serverIconTooltip[index].innerHTML = escape(serverName);
|
||||
this.$serverIconTooltip[index].innerHTML = serverName;
|
||||
this.$serverIconTooltip[index].removeAttribute('style');
|
||||
// To handle position of servers' tooltip due to scrolling of list of organizations
|
||||
// This could not be handled using CSS, hence the top of the tooltip is made same
|
||||
|
@@ -24,7 +24,7 @@ class GeneralSection extends BaseSection {
|
||||
<div class="setting-control"></div>
|
||||
</div>
|
||||
<div class="setting-row" id="sidebar-option">
|
||||
<div class="setting-description">Show sidebar (<span class="code">Cmd Or Ctrl+S</span>)</div>
|
||||
<div class="setting-description">Show sidebar (<span class="code">Cmd Or Ctrl+Shift+S</span>)</div>
|
||||
<div class="setting-control"></div>
|
||||
</div>
|
||||
<div class="setting-row" id="badge-option">
|
||||
|
25
app/renderer/js/utils/common-util.js
Normal file
25
app/renderer/js/utils/common-util.js
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
let instance = null;
|
||||
|
||||
class CommonUtil {
|
||||
constructor() {
|
||||
if (instance) {
|
||||
return instance;
|
||||
} else {
|
||||
instance = this;
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// unescape already encoded/escaped strings
|
||||
decodeString(string) {
|
||||
const parser = new DOMParser();
|
||||
const dom = parser.parseFromString(
|
||||
'<!doctype html><body>' + string,
|
||||
'text/html');
|
||||
return dom.body.textContent;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new CommonUtil();
|
@@ -10,6 +10,8 @@ const escape = require('escape-html');
|
||||
const Logger = require('./logger-util');
|
||||
|
||||
const CertificateUtil = require(__dirname + '/certificate-util.js');
|
||||
const ProxyUtil = require(__dirname + '/proxy-util.js');
|
||||
const ConfigUtil = require(__dirname + '/config-util.js');
|
||||
|
||||
const logger = new Logger({
|
||||
file: `domain-util.log`,
|
||||
@@ -119,8 +121,16 @@ class DomainUtil {
|
||||
logger.warn('Error while trying to get certificate: ' + err);
|
||||
}
|
||||
}
|
||||
|
||||
const proxyEnabled = ConfigUtil.getConfigItem('useManualProxy') || ConfigUtil.getConfigItem('useSystemProxy');
|
||||
|
||||
// If certificate for the domain exists add it as a ca key in the request's parameter else consider only domain as the parameter for request
|
||||
const checkDomain = (certificateLocation) ? ({url: domain + '/static/audio/zulip.ogg', ca: certificateLocation}) : domain + '/static/audio/zulip.ogg';
|
||||
// Add proxy as a parameter if it sbeing used.
|
||||
const checkDomain = {
|
||||
url: domain + '/static/audio/zulip.ogg',
|
||||
ca: (certificateLocation) ? certificateLocation : '',
|
||||
proxy: proxyEnabled ? ProxyUtil.getProxy(domain) : ''
|
||||
};
|
||||
|
||||
const serverConf = {
|
||||
icon: defaultIconUrl,
|
||||
@@ -193,9 +203,13 @@ class DomainUtil {
|
||||
}
|
||||
|
||||
getServerSettings(domain) {
|
||||
const serverSettingsUrl = domain + '/api/v1/server_settings';
|
||||
const proxyEnabled = ConfigUtil.getConfigItem('useManualProxy') || ConfigUtil.getConfigItem('useSystemProxy');
|
||||
const serverSettingsOptions = {
|
||||
url: domain + '/api/v1/server_settings',
|
||||
proxy: proxyEnabled ? ProxyUtil.getProxy(domain) : ''
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
request(serverSettingsUrl, (error, response) => {
|
||||
request(serverSettingsOptions, (error, response) => {
|
||||
if (!error && response.statusCode === 200) {
|
||||
const data = JSON.parse(response.body);
|
||||
if (data.hasOwnProperty('realm_icon') && data.realm_icon) {
|
||||
@@ -215,12 +229,17 @@ class DomainUtil {
|
||||
}
|
||||
|
||||
saveServerIcon(url) {
|
||||
const proxyEnabled = ConfigUtil.getConfigItem('useManualProxy') || ConfigUtil.getConfigItem('useSystemProxy');
|
||||
const serverIconOptions = {
|
||||
url,
|
||||
proxy: proxyEnabled ? ProxyUtil.getProxy(url) : ''
|
||||
};
|
||||
// The save will always succeed. If url is invalid, downgrade to default icon.
|
||||
return new Promise(resolve => {
|
||||
const filePath = this.generateFilePath(url);
|
||||
const file = fs.createWriteStream(filePath);
|
||||
try {
|
||||
request(url).on('response', response => {
|
||||
request(serverIconOptions).on('response', response => {
|
||||
response.on('error', err => {
|
||||
logger.log('Could not get server icon.');
|
||||
logger.log(err);
|
||||
|
@@ -34,6 +34,12 @@ class LinkUtil {
|
||||
const isImageUrl = /\.(bmp|gif|jpg|jpeg|png|webp)\?*.*$/i;
|
||||
return isImageUrl.test(url);
|
||||
}
|
||||
|
||||
isPDF(url) {
|
||||
// test for pdf extension
|
||||
const isPDFUrl = /\.(pdf)\?*.*$/i;
|
||||
return isPDFUrl.test(url);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new LinkUtil();
|
||||
|
@@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const url = require('url');
|
||||
const ConfigUtil = require('./config-util.js');
|
||||
|
||||
let instance = null;
|
||||
@@ -15,6 +16,39 @@ class ProxyUtil {
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Return proxy to be used for a particular uri, to be used for request
|
||||
getProxy(uri) {
|
||||
uri = url.parse(uri);
|
||||
const proxyRules = ConfigUtil.getConfigItem('proxyRules', '').split(';');
|
||||
// If SPS is on and system uses no proxy then request should not try to use proxy from
|
||||
// environment. NO_PROXY = '*' makes request ignore all environment proxy variables.
|
||||
if (proxyRules[0] === '') {
|
||||
process.env.NO_PROXY = '*';
|
||||
return;
|
||||
}
|
||||
|
||||
const proxyRule = {};
|
||||
if (uri.protocol === 'http:') {
|
||||
proxyRules.forEach(proxy => {
|
||||
if (proxy.includes('http=')) {
|
||||
proxyRule.hostname = proxy.split('http=')[1].trim().split(':')[0];
|
||||
proxyRule.port = proxy.split('http=')[1].trim().split(':')[1];
|
||||
}
|
||||
});
|
||||
return proxyRule;
|
||||
}
|
||||
|
||||
if (uri.protocol === 'https:') {
|
||||
proxyRules.forEach(proxy => {
|
||||
if (proxy.includes('https=')) {
|
||||
proxyRule.hostname = proxy.split('https=')[1].trim().split(':')[0];
|
||||
proxyRule.port = proxy.split('https=')[1].trim().split(':')[1];
|
||||
}
|
||||
});
|
||||
return proxyRule;
|
||||
}
|
||||
}
|
||||
|
||||
resolveSystemProxy(mainWindow) {
|
||||
const page = mainWindow.webContents;
|
||||
const ses = page.session;
|
||||
|
27
changelog.md
27
changelog.md
@@ -4,6 +4,33 @@
|
||||
|
||||
All notable changes to the Zulip desktop app are documented in this file.
|
||||
|
||||
### v2.3.6 --2018-08-27
|
||||
|
||||
**New features**:
|
||||
* Add proxy details while validating a server. This fixes the server validating issue for users who are using the proxy settings.
|
||||
|
||||
|
||||
**Fixes**:
|
||||
|
||||
* Fix youtube video not playing in lightbox.
|
||||
* Fix realm name not escaped properly.
|
||||
|
||||
<hr>
|
||||
|
||||
### v2.3.5 --2018-08-03
|
||||
|
||||
**New features**:
|
||||
* Add a setting option to show downloaded file in file manager.
|
||||
* Added electron bridge to communicate with webapp in real time.
|
||||
|
||||
**Fixes**:
|
||||
|
||||
* Fix failing attached file downloads.
|
||||
* Fix page_params error.
|
||||
* gulpfile: Update syntax and methods for gulp v4.x.
|
||||
|
||||
<hr>
|
||||
|
||||
### v2.3.4-beta --2018-07-24
|
||||
|
||||
**Fixes**:
|
||||
|
105
help.md
105
help.md
@@ -1,105 +0,0 @@
|
||||
# User Guide
|
||||
|
||||
> Welcome! This guide will walk you through the basics of using Zulip Desktop.
|
||||
|
||||
|
||||
## Get Zulip Desktop
|
||||
|
||||
|
||||
|
||||
## Connect to a Server
|
||||
|
||||
### Connect through a proxy
|
||||
|
||||
It's possible to connect to your server through a proxy.
|
||||
You can enter the proxy settings in the `Network` section of App Settings.
|
||||
There are three fields provided:
|
||||
* `PAC script` - The URL associated with the PAC file.
|
||||
* `Proxy rules` - Rules indicating which proxies to use.
|
||||
* `Proxy bypass rules` - Rules indicating which URLs should
|
||||
bypass the proxy settings.
|
||||
|
||||
For a typical setup where internet access is required to use an HTTP proxy,
|
||||
but URLs on the local network should be accessed directly, configure as follows:
|
||||
|
||||
`Proxy rules = proxy.example.com`
|
||||
|
||||
Your HTTP proxy server
|
||||
`Proxy bypass rules = *.example.com;10.0.0.0/8`
|
||||
|
||||
Directly connect to your own domain and private IP subnet
|
||||
for more complex setups, read below to configure complex proxy rules and proxy bypass rules.
|
||||
|
||||
### Sets the proxy settings.
|
||||
|
||||
When `PAC script` and `Proxy rules` are provided together, the `Proxy rules`
|
||||
option is ignored and `PAC script` configuration is applied.
|
||||
|
||||
The `Proxy rules` has to follow the rules below:
|
||||
|
||||
```
|
||||
proxyRules = schemeProxies[";"<schemeProxies>]
|
||||
schemeProxies = [<urlScheme>"="]<proxyURIList>
|
||||
urlScheme = "http" | "https" | "ftp" | "socks"
|
||||
proxyURIList = <proxyURL>[","<proxyURIList>]
|
||||
proxyURL = [<proxyScheme>"://"]<proxyHost>[":"<proxyPort>]
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
* `http=foopy:80;ftp=foopy2` - Use HTTP proxy `foopy:80` for `http://` URLs, and
|
||||
HTTP proxy `foopy2:80` for `ftp://` URLs.
|
||||
* `foopy:80` - Use HTTP proxy `foopy:80` for all URLs.
|
||||
* `foopy:80,bar,direct://` - Use HTTP proxy `foopy:80` for all URLs, failing
|
||||
over to `bar` if `foopy:80` is unavailable, and after that using no proxy.
|
||||
* `socks4://foopy` - Use SOCKS v4 proxy `foopy:1080` for all URLs.
|
||||
* `http=foopy,socks5://bar.com` - Use HTTP proxy `foopy` for http URLs, and fail
|
||||
over to the SOCKS5 proxy `bar.com` if `foopy` is unavailable.
|
||||
* `http=foopy,direct://` - Use HTTP proxy `foopy` for http URLs, and use no
|
||||
proxy if `foopy` is unavailable.
|
||||
* `http=foopy;socks=foopy2` - Use HTTP proxy `foopy` for http URLs, and use
|
||||
`socks4://foopy2` for all other URLs.
|
||||
|
||||
The `Proxy bypass rules` is a comma separated list of rules described below:
|
||||
|
||||
* `[ URL_SCHEME "://" ] HOSTNAME_PATTERN [ ":" <port> ]`
|
||||
|
||||
Match all hostnames that match the pattern HOSTNAME_PATTERN.
|
||||
|
||||
Examples:
|
||||
"foobar.com", "*foobar.com", "*.foobar.com", "*foobar.com:99",
|
||||
"https://x.*.y.com:99"
|
||||
|
||||
* `"." HOSTNAME_SUFFIX_PATTERN [ ":" PORT ]`
|
||||
|
||||
Match a particular domain suffix.
|
||||
|
||||
Examples:
|
||||
".google.com", ".com", "http://.google.com"
|
||||
|
||||
* `[ SCHEME "://" ] IP_LITERAL [ ":" PORT ]`
|
||||
|
||||
Match URLs which are IP address literals.
|
||||
|
||||
Examples:
|
||||
"127.0.1", "[0:0::1]", "[::1]", "http://[::1]:99"
|
||||
|
||||
* `IP_LITERAL "/" PREFIX_LENGHT_IN_BITS`
|
||||
|
||||
Match any URL that is to an IP literal that falls between the
|
||||
given range. IP range is specified using CIDR notation.
|
||||
|
||||
Examples:
|
||||
"192.168.1.1/16", "fefe:13::abc/33".
|
||||
|
||||
* `<local>`
|
||||
|
||||
Match local addresses. The meaning of `<local>` is whether the
|
||||
host matches one of: "127.0.0.1", "::1", "localhost".
|
||||
|
||||
|
||||
## Change App Preferences
|
||||
|
||||
|
||||
|
||||
## Reporting an Issue
|
14
package-lock.json
generated
14
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "zulip",
|
||||
"version": "2.3.5",
|
||||
"version": "2.3.6",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -11,9 +11,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "8.10.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.21.tgz",
|
||||
"integrity": "sha512-87XkD9qDXm8fIax+5y7drx84cXsu34ZZqfB7Cial3Q/2lxSoJ/+DRaWckkCbxP41wFSIrrb939VhzaNxj4eY1w==",
|
||||
"version": "8.10.26",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.26.tgz",
|
||||
"integrity": "sha512-opk6bLLErLSwyVVJeSH5Ek7ZWOBSsN0JrvXTNVGLXLAXKB9xlTYajrplR44xVyMrmbut94H6uJ9jqzM/12jxkA==",
|
||||
"dev": true
|
||||
},
|
||||
"abbrev": {
|
||||
@@ -2091,9 +2091,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"electron": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-2.0.1.tgz",
|
||||
"integrity": "sha512-piSwY2P7L6NWx672MNdSvtGPdQP/mhwAg8ICN6ofTTItPkd7D6kNHBPkq+DXwZcXVH1EifYR9yD/l3Xw1haVpQ==",
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-2.0.8.tgz",
|
||||
"integrity": "sha512-pbeGFbwijb5V3Xy/KMcwIp59eA9igg2br+7EHbbwQoa3HRDF5JjTrciX7OiscCA52+ze2n4q38S4lXPqRitgIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "^8.0.24",
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "zulip",
|
||||
"productName": "Zulip",
|
||||
"version": "2.3.5",
|
||||
"version": "2.3.6",
|
||||
"main": "./app/main",
|
||||
"description": "Zulip Desktop App",
|
||||
"license": "Apache-2.0",
|
||||
@@ -123,7 +123,7 @@
|
||||
"assert": "1.4.1",
|
||||
"cp-file": "^5.0.0",
|
||||
"devtron": "1.4.0",
|
||||
"electron": "2.0.1",
|
||||
"electron": "2.0.8",
|
||||
"electron-builder": "20.20.4",
|
||||
"electron-connect": "0.6.2",
|
||||
"electron-debug": "1.4.0",
|
||||
|
Reference in New Issue
Block a user