mirror of
https://github.com/zulip/zulip-desktop.git
synced 2025-11-04 22:13:13 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6738b7087 |
@@ -15,7 +15,7 @@ addons:
|
|||||||
|
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- '8'
|
- '6'
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- ./scripts/travis-xvfb.sh
|
- ./scripts/travis-xvfb.sh
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const { app, dialog, shell } = require('electron');
|
const { app, dialog } = require('electron');
|
||||||
const { autoUpdater } = require('electron-updater');
|
const { autoUpdater } = require('electron-updater');
|
||||||
const isDev = require('electron-is-dev');
|
const isDev = require('electron-is-dev');
|
||||||
|
|
||||||
const ConfigUtil = require('./../renderer/js/utils/config-util.js');
|
const ConfigUtil = require('./../renderer/js/utils/config-util.js');
|
||||||
|
|
||||||
function appUpdater(updateFromMenu = false) {
|
function appUpdater() {
|
||||||
// Don't initiate auto-updates in development
|
// Don't initiate auto-updates in development
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
return;
|
return;
|
||||||
@@ -17,8 +17,6 @@ function appUpdater(updateFromMenu = false) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let updateAvailable = false;
|
|
||||||
|
|
||||||
// Create Logs directory
|
// Create Logs directory
|
||||||
const LogsDir = `${app.getPath('userData')}/Logs`;
|
const LogsDir = `${app.getPath('userData')}/Logs`;
|
||||||
|
|
||||||
@@ -30,58 +28,7 @@ function appUpdater(updateFromMenu = false) {
|
|||||||
autoUpdater.logger = log;
|
autoUpdater.logger = log;
|
||||||
|
|
||||||
// Handle auto updates for beta/pre releases
|
// Handle auto updates for beta/pre releases
|
||||||
const isBetaUpdate = ConfigUtil.getConfigItem('betaUpdate');
|
autoUpdater.allowPrerelease = ConfigUtil.getConfigItem('betaUpdate') || false;
|
||||||
|
|
||||||
autoUpdater.allowPrerelease = isBetaUpdate || false;
|
|
||||||
|
|
||||||
const eventsListenerRemove = ['update-available', 'update-not-available'];
|
|
||||||
autoUpdater.on('update-available', info => {
|
|
||||||
if (updateFromMenu) {
|
|
||||||
dialog.showMessageBox({
|
|
||||||
message: `A new version ${info.version}, of Zulip Desktop is available`,
|
|
||||||
detail: 'The update will be downloaded in the background. You will be notified when it is ready to be installed.'
|
|
||||||
});
|
|
||||||
|
|
||||||
updateAvailable = true;
|
|
||||||
|
|
||||||
// This is to prevent removal of 'update-downloaded' and 'error' event listener.
|
|
||||||
eventsListenerRemove.forEach(event => {
|
|
||||||
autoUpdater.removeAllListeners(event);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on('update-not-available', () => {
|
|
||||||
if (updateFromMenu) {
|
|
||||||
dialog.showMessageBox({
|
|
||||||
message: 'No updates available',
|
|
||||||
detail: `You are running the latest version of Zulip Desktop.\nVersion: ${app.getVersion()}`
|
|
||||||
});
|
|
||||||
// Remove all autoUpdator listeners so that next time autoUpdator is manually called these
|
|
||||||
// listeners don't trigger multiple times.
|
|
||||||
autoUpdater.removeAllListeners();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on('error', error => {
|
|
||||||
if (updateFromMenu) {
|
|
||||||
const messageText = (updateAvailable) ? ('Unable to download the updates') : ('Unable to check for updates');
|
|
||||||
dialog.showMessageBox({
|
|
||||||
type: 'error',
|
|
||||||
buttons: ['Manual Download', 'Cancel'],
|
|
||||||
message: messageText,
|
|
||||||
detail: (error).toString() + `\n\nThe latest version of Zulip Desktop is available at -\nhttps://zulipchat.com/apps/.\n
|
|
||||||
Current Version: ${app.getVersion()}`
|
|
||||||
}, response => {
|
|
||||||
if (response === 0) {
|
|
||||||
shell.openExternal('https://zulipchat.com/apps/');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Remove all autoUpdator listeners so that next time autoUpdator is manually called these
|
|
||||||
// listeners don't trigger multiple times.
|
|
||||||
autoUpdater.removeAllListeners();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ask the user if update is available
|
// Ask the user if update is available
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const crashHandler = () => {
|
|||||||
productName: 'zulip-electron',
|
productName: 'zulip-electron',
|
||||||
companyName: 'Kandra Labs, Inc.',
|
companyName: 'Kandra Labs, Inc.',
|
||||||
submitURL: 'https://zulip-sentry.herokuapp.com/crashreport',
|
submitURL: 'https://zulip-sentry.herokuapp.com/crashreport',
|
||||||
uploadToServer: true
|
autoSubmit: true
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -131,9 +131,6 @@ function createMainWindow() {
|
|||||||
// Decrease load on GPU (experimental)
|
// Decrease load on GPU (experimental)
|
||||||
app.disableHardwareAcceleration();
|
app.disableHardwareAcceleration();
|
||||||
|
|
||||||
// Temporary fix for Electron render colors differently
|
|
||||||
app.commandLine.appendSwitch('force-color-profile', 'srgb');
|
|
||||||
|
|
||||||
// eslint-disable-next-line max-params
|
// eslint-disable-next-line max-params
|
||||||
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
|
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -164,9 +161,7 @@ app.on('ready', () => {
|
|||||||
|
|
||||||
page.once('did-frame-finish-load', () => {
|
page.once('did-frame-finish-load', () => {
|
||||||
// Initate auto-updates on MacOS and Windows
|
// Initate auto-updates on MacOS and Windows
|
||||||
if (ConfigUtil.getConfigItem('autoUpdate')) {
|
appUpdater();
|
||||||
appUpdater();
|
|
||||||
}
|
|
||||||
crashHandler();
|
crashHandler();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
const os = require('os');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const { app, shell, BrowserWindow, Menu, dialog } = require('electron');
|
const { app, shell, BrowserWindow, Menu, dialog } = require('electron');
|
||||||
|
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const { appUpdater } = require('./autoupdater');
|
|
||||||
|
|
||||||
const ConfigUtil = require(__dirname + '/../renderer/js/utils/config-util.js');
|
const ConfigUtil = require(__dirname + '/../renderer/js/utils/config-util.js');
|
||||||
const DNDUtil = require(__dirname + '/../renderer/js/utils/dnd-util.js');
|
|
||||||
|
|
||||||
const appName = app.getName();
|
const appName = app.getName();
|
||||||
|
|
||||||
@@ -140,11 +139,13 @@ class AppMenu {
|
|||||||
}, {
|
}, {
|
||||||
label: 'Report an Issue...',
|
label: 'Report an Issue...',
|
||||||
click() {
|
click() {
|
||||||
// the goal is to notify the main.html BrowserWindow
|
const body = `
|
||||||
// which may not be the focused window.
|
<!-- Please succinctly describe your issue and steps to reproduce it. -->
|
||||||
BrowserWindow.getAllWindows().forEach(window => {
|
-
|
||||||
window.webContents.send('open-feedback-modal');
|
${app.getName()} ${app.getVersion()}
|
||||||
});
|
Electron ${process.versions.electron}
|
||||||
|
${process.platform} ${process.arch} ${os.release()}`;
|
||||||
|
shell.openExternal(`https://github.com/zulip/zulip-electron/issues/new?body=${encodeURIComponent(body)}`);
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
@@ -196,12 +197,7 @@ class AppMenu {
|
|||||||
AppMenu.sendAction('open-about');
|
AppMenu.sendAction('open-about');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
label: `Check for Update`,
|
|
||||||
click() {
|
|
||||||
AppMenu.checkForUpdate();
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
type: 'separator'
|
type: 'separator'
|
||||||
}, {
|
}, {
|
||||||
label: 'Desktop App Settings',
|
label: 'Desktop App Settings',
|
||||||
@@ -221,13 +217,6 @@ class AppMenu {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
type: 'separator'
|
type: 'separator'
|
||||||
}, {
|
|
||||||
label: 'Toggle Do Not Disturb',
|
|
||||||
accelerator: 'Command+Shift+M',
|
|
||||||
click() {
|
|
||||||
const dndUtil = DNDUtil.toggle();
|
|
||||||
AppMenu.sendAction('toggle-dnd', dndUtil.dnd, dndUtil.newSettings);
|
|
||||||
}
|
|
||||||
}, {
|
}, {
|
||||||
label: 'Reset App Settings',
|
label: 'Reset App Settings',
|
||||||
accelerator: 'Command+Shift+D',
|
accelerator: 'Command+Shift+D',
|
||||||
@@ -308,12 +297,7 @@ class AppMenu {
|
|||||||
AppMenu.sendAction('open-about');
|
AppMenu.sendAction('open-about');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
label: `Check for Update`,
|
|
||||||
click() {
|
|
||||||
AppMenu.checkForUpdate();
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
type: 'separator'
|
type: 'separator'
|
||||||
}, {
|
}, {
|
||||||
label: 'Desktop App Settings',
|
label: 'Desktop App Settings',
|
||||||
@@ -335,13 +319,6 @@ class AppMenu {
|
|||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
type: 'separator'
|
type: 'separator'
|
||||||
}, {
|
|
||||||
label: 'Toggle Do Not Disturb',
|
|
||||||
accelerator: 'Ctrl+Shift+M',
|
|
||||||
click() {
|
|
||||||
const dndUtil = DNDUtil.toggle();
|
|
||||||
AppMenu.sendAction('toggle-dnd', dndUtil.dnd, dndUtil.newSettings);
|
|
||||||
}
|
|
||||||
}, {
|
}, {
|
||||||
label: 'Reset App Settings',
|
label: 'Reset App Settings',
|
||||||
accelerator: 'Ctrl+Shift+D',
|
accelerator: 'Ctrl+Shift+D',
|
||||||
@@ -410,9 +387,6 @@ class AppMenu {
|
|||||||
win.webContents.send(action, ...params);
|
win.webContents.send(action, ...params);
|
||||||
}
|
}
|
||||||
|
|
||||||
static checkForUpdate() {
|
|
||||||
appUpdater(true);
|
|
||||||
}
|
|
||||||
static resetAppSettings() {
|
static resetAppSettings() {
|
||||||
const resetAppSettingsMessage = 'By proceeding you will be removing all connected organizations and preferences from Zulip.';
|
const resetAppSettingsMessage = 'By proceeding you will be removing all connected organizations and preferences from Zulip.';
|
||||||
|
|
||||||
|
|||||||
1411
app/package-lock.json
generated
1411
app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "zulip",
|
"name": "zulip",
|
||||||
"productName": "Zulip",
|
"productName": "Zulip",
|
||||||
"version": "2.3.1",
|
"version": "1.9.0",
|
||||||
"description": "Zulip Desktop App",
|
"description": "Zulip Desktop App",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"copyright": "Kandra Labs, Inc.",
|
"copyright": "Kandra Labs, Inc.",
|
||||||
@@ -26,21 +26,20 @@
|
|||||||
"InstantMessaging"
|
"InstantMessaging"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electron-elements/send-feedback": "1.0.7",
|
"auto-launch": "5.0.1",
|
||||||
"escape-html": "1.0.3",
|
|
||||||
"auto-launch": "5.0.5",
|
|
||||||
"electron-is-dev": "0.3.0",
|
"electron-is-dev": "0.3.0",
|
||||||
"electron-log": "2.2.14",
|
"electron-log": "2.2.7",
|
||||||
"electron-spellchecker": "1.1.2",
|
"electron-spellchecker": "1.1.2",
|
||||||
"electron-updater": "2.21.10",
|
"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.85.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": {
|
||||||
"node-mac-notifier": "0.1.0"
|
"node-mac-notifier": "0.0.13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ body {
|
|||||||
#content {
|
#content {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
background: #fff url(../img/ic_loading.gif) no-repeat;
|
||||||
|
background-size: 60px 60px;
|
||||||
|
background-position: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-sidebar {
|
.toggle-sidebar {
|
||||||
@@ -42,28 +45,6 @@ body {
|
|||||||
transition: all 0.6s ease-out;
|
transition: all 0.6s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#view-controls-container {
|
|
||||||
height: calc(100% - 208px);
|
|
||||||
overflow-y: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
#view-controls-container:hover {
|
|
||||||
overflow-y: overlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
#view-controls-container::-webkit-scrollbar {
|
|
||||||
width: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#view-controls-container::-webkit-scrollbar-track {
|
|
||||||
box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
#view-controls-container::-webkit-scrollbar-thumb {
|
|
||||||
background-color: darkgrey;
|
|
||||||
outline: 1px solid slategrey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Material Icons';
|
font-family: 'Material Icons';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -270,25 +251,6 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Pseudo element for loading indicator*/
|
|
||||||
#webviews-container::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
background: #fff url(../img/ic_loading.gif) no-repeat;
|
|
||||||
background-size: 60px 60px;
|
|
||||||
background-position: center;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*When the active webview is loaded*/
|
|
||||||
#webviews-container.loaded::before {
|
|
||||||
opacity: 0;
|
|
||||||
z-index: -1;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
webview {
|
webview {
|
||||||
/* transition: opacity 0.3s ease-in; */
|
/* transition: opacity 0.3s ease-in; */
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@@ -300,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);
|
||||||
}
|
}
|
||||||
@@ -320,7 +287,6 @@ webview.focus {
|
|||||||
|
|
||||||
/* Tooltip styling */
|
/* Tooltip styling */
|
||||||
|
|
||||||
#dnd-tooltip,
|
|
||||||
#back-tooltip,
|
#back-tooltip,
|
||||||
#reload-tooltip,
|
#reload-tooltip,
|
||||||
#setting-tooltip {
|
#setting-tooltip {
|
||||||
@@ -338,7 +304,6 @@ webview.focus {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#dnd-tooltip:after,
|
|
||||||
#back-tooltip:after,
|
#back-tooltip:after,
|
||||||
#reload-tooltip:after,
|
#reload-tooltip:after,
|
||||||
#setting-tooltip:after {
|
#setting-tooltip:after {
|
||||||
@@ -443,26 +408,3 @@ webview.focus {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
send-feedback {
|
|
||||||
width: 60%;
|
|
||||||
height: 85%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedback-modal {
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: rgba(68, 67, 67, 0.81);
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 2;
|
|
||||||
transition: all 1s ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
#feedback-modal.show {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -557,22 +557,6 @@ input.toggle-round:checked+label:after {
|
|||||||
background: #329588;
|
background: #329588;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tip {
|
|
||||||
background-color: hsl(46,63%,95%);
|
|
||||||
border: 1px solid hsl(46,63%,84%);
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.md-14 {
|
|
||||||
font-size: 14px;
|
|
||||||
vertical-align: middle;
|
|
||||||
padding-right: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#open-hotkeys-link {
|
|
||||||
text-decoration: underline;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* responsive grid */
|
/* responsive grid */
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const { shell } = require('electron').remote;
|
const { shell } = require('electron').remote;
|
||||||
const LinkUtil = require('../utils/link-util');
|
const LinkUtil = require('../utils/link-util');
|
||||||
const DomainUtil = require('../utils/domain-util');
|
const DomainUtil = require('../utils/domain-util');
|
||||||
|
const hiddenWebView = require('../components/hidden-webview');
|
||||||
|
|
||||||
function handleExternalLink(event) {
|
function handleExternalLink(event) {
|
||||||
const { url } = event;
|
const { url } = event;
|
||||||
@@ -15,12 +16,12 @@ function handleExternalLink(event) {
|
|||||||
if (isWhiteListURL) {
|
if (isWhiteListURL) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
// download txt, pdf, mp3, mp4 etc.. by using downloadURL in the
|
// only open the pdf, mp3, mp4 etc.. in hidden webview since opening the
|
||||||
// main process which allows the user to save the files to their desktop
|
// image in webview will do nothing and will not save it
|
||||||
// and not trigger webview reload while image in webview will
|
// whereas the pdf will be saved to user desktop once openened in
|
||||||
// do nothing and will not save it
|
// in the hidden webview and will not trigger webview reload
|
||||||
if (!LinkUtil.isImage(url) && isUploadsURL) {
|
if (!LinkUtil.isImage(url) && isUploadsURL) {
|
||||||
this.$el.downloadURL(url);
|
hiddenWebView.loadURL(url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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;
|
||||||
@@ -18,10 +18,9 @@ class WebView extends BaseComponent {
|
|||||||
this.props = props;
|
this.props = props;
|
||||||
|
|
||||||
this.zoomFactor = 1.0;
|
this.zoomFactor = 1.0;
|
||||||
this.loading = true;
|
this.loading = false;
|
||||||
this.badgeCount = 0;
|
this.badgeCount = 0;
|
||||||
this.customCSS = ConfigUtil.getConfigItem('customCSS');
|
this.customCSS = ConfigUtil.getConfigItem('customCSS');
|
||||||
this.$webviewsContainer = document.querySelector('#webviews-container').classList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template() {
|
template() {
|
||||||
@@ -87,7 +86,6 @@ class WebView extends BaseComponent {
|
|||||||
if (this.props.role === 'server') {
|
if (this.props.role === 'server') {
|
||||||
this.$el.classList.add('onload');
|
this.$el.classList.add('onload');
|
||||||
}
|
}
|
||||||
this.loading = false;
|
|
||||||
this.show();
|
this.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -121,13 +119,6 @@ class WebView extends BaseComponent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// To show or hide the loading indicator in the the active tab
|
|
||||||
if (this.loading) {
|
|
||||||
this.$webviewsContainer.remove('loaded');
|
|
||||||
} else {
|
|
||||||
this.$webviewsContainer.add('loaded');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$el.classList.remove('disabled');
|
this.$el.classList.remove('disabled');
|
||||||
this.$el.classList.add('active');
|
this.$el.classList.add('active');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -136,6 +127,7 @@ class WebView extends BaseComponent {
|
|||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
this.focus();
|
this.focus();
|
||||||
|
this.loading = false;
|
||||||
this.props.onTitleChange();
|
this.props.onTitleChange();
|
||||||
// Injecting preload css in webview to override some css rules
|
// Injecting preload css in webview to override some css rules
|
||||||
this.$el.insertCSS(fs.readFileSync(path.join(__dirname, '/../../css/preload.css'), 'utf8'));
|
this.$el.insertCSS(fs.readFileSync(path.join(__dirname, '/../../css/preload.css'), 'utf8'));
|
||||||
@@ -228,9 +220,6 @@ class WebView extends BaseComponent {
|
|||||||
|
|
||||||
reload() {
|
reload() {
|
||||||
this.hide();
|
this.hide();
|
||||||
// Shows the loading indicator till the webview is reloaded
|
|
||||||
this.$webviewsContainer.remove('loaded');
|
|
||||||
this.loading = true;
|
|
||||||
this.$el.reload();
|
this.$el.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
const { app } = require('electron').remote;
|
|
||||||
const path = require('path');
|
|
||||||
const fs = require('fs');
|
|
||||||
const SendFeedback = require('@electron-elements/send-feedback');
|
|
||||||
|
|
||||||
// make the button color match zulip app's theme
|
|
||||||
SendFeedback.customStyles = `
|
|
||||||
button:hover, button:focus {
|
|
||||||
border-color: #4EBFAC;
|
|
||||||
color: #4EBFAC;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:active {
|
|
||||||
background-color: #f1f1f1;
|
|
||||||
color: #4EBFAC;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
background-color: #4EBFAC;
|
|
||||||
border-color: #4EBFAC;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
customElements.define('send-feedback', SendFeedback);
|
|
||||||
const sendFeedback = document.querySelector('send-feedback');
|
|
||||||
const feedbackHolder = sendFeedback.parentElement;
|
|
||||||
|
|
||||||
// customize the fields of custom elements
|
|
||||||
sendFeedback.title = 'Report Issue';
|
|
||||||
sendFeedback.titleLabel = 'Issue title:';
|
|
||||||
sendFeedback.titlePlaceholder = 'Enter issue title';
|
|
||||||
sendFeedback.textareaLabel = 'Describe the issue:';
|
|
||||||
sendFeedback.textareaPlaceholder = 'Succinctly describe your issue and steps to reproduce it...';
|
|
||||||
sendFeedback.buttonLabel = 'Report Issue';
|
|
||||||
sendFeedback.loaderSuccessText = '';
|
|
||||||
|
|
||||||
sendFeedback.useReporter('emailReporter', {
|
|
||||||
email: 'akash@zulipchat.com'
|
|
||||||
});
|
|
||||||
|
|
||||||
feedbackHolder.addEventListener('click', e => {
|
|
||||||
// only remove the class if the grey out faded
|
|
||||||
// part is clicked and not the feedback element itself
|
|
||||||
if (e.target === e.currentTarget) {
|
|
||||||
feedbackHolder.classList.remove('show');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sendFeedback.addEventListener('feedback-submitted', () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
feedbackHolder.classList.remove('show');
|
|
||||||
}, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
const dataDir = app.getPath('userData');
|
|
||||||
const logsDir = path.join(dataDir, '/Logs');
|
|
||||||
sendFeedback.logs.push(...fs.readdirSync(logsDir).map(file => path.join(logsDir, file)));
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
feedbackHolder,
|
|
||||||
sendFeedback
|
|
||||||
};
|
|
||||||
@@ -11,9 +11,7 @@ const WebView = require(__dirname + '/js/components/webview.js');
|
|||||||
const ServerTab = require(__dirname + '/js/components/server-tab.js');
|
const ServerTab = require(__dirname + '/js/components/server-tab.js');
|
||||||
const FunctionalTab = require(__dirname + '/js/components/functional-tab.js');
|
const FunctionalTab = require(__dirname + '/js/components/functional-tab.js');
|
||||||
const ConfigUtil = require(__dirname + '/js/utils/config-util.js');
|
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 ReconnectUtil = require(__dirname + '/js/utils/reconnect-util.js');
|
||||||
const { feedbackHolder } = require(__dirname + '/js/feedback.js');
|
|
||||||
|
|
||||||
class ServerManagerView {
|
class ServerManagerView {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -25,14 +23,12 @@ class ServerManagerView {
|
|||||||
this.$settingsButton = $actionsContainer.querySelector('#settings-action');
|
this.$settingsButton = $actionsContainer.querySelector('#settings-action');
|
||||||
this.$webviewsContainer = document.getElementById('webviews-container');
|
this.$webviewsContainer = document.getElementById('webviews-container');
|
||||||
this.$backButton = $actionsContainer.querySelector('#back-action');
|
this.$backButton = $actionsContainer.querySelector('#back-action');
|
||||||
this.$dndButton = $actionsContainer.querySelector('#dnd-action');
|
|
||||||
|
|
||||||
this.$addServerTooltip = document.getElementById('add-server-tooltip');
|
this.$addServerTooltip = document.getElementById('add-server-tooltip');
|
||||||
this.$reloadTooltip = $actionsContainer.querySelector('#reload-tooltip');
|
this.$reloadTooltip = $actionsContainer.querySelector('#reload-tooltip');
|
||||||
this.$settingsTooltip = $actionsContainer.querySelector('#setting-tooltip');
|
this.$settingsTooltip = $actionsContainer.querySelector('#setting-tooltip');
|
||||||
this.$serverIconTooltip = document.getElementsByClassName('server-tooltip');
|
this.$serverIconTooltip = document.getElementsByClassName('server-tooltip');
|
||||||
this.$backTooltip = $actionsContainer.querySelector('#back-tooltip');
|
this.$backTooltip = $actionsContainer.querySelector('#back-tooltip');
|
||||||
this.$dndTooltip = $actionsContainer.querySelector('#dnd-tooltip');
|
|
||||||
|
|
||||||
this.$sidebar = document.getElementById('sidebar');
|
this.$sidebar = document.getElementById('sidebar');
|
||||||
|
|
||||||
@@ -89,15 +85,9 @@ class ServerManagerView {
|
|||||||
startMinimized: false,
|
startMinimized: false,
|
||||||
enableSpellchecker: true,
|
enableSpellchecker: true,
|
||||||
showNotification: true,
|
showNotification: true,
|
||||||
autoUpdate: true,
|
|
||||||
betaUpdate: false,
|
betaUpdate: false,
|
||||||
silent: false,
|
silent: false,
|
||||||
lastActiveTab: 0,
|
lastActiveTab: 0
|
||||||
dnd: false,
|
|
||||||
dndPreviousSettings: {
|
|
||||||
showNotification: true,
|
|
||||||
silent: false
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Platform specific settings
|
// Platform specific settings
|
||||||
@@ -105,7 +95,6 @@ class ServerManagerView {
|
|||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
// Only available on Windows
|
// Only available on Windows
|
||||||
settingOptions.flashTaskbarOnMessage = true;
|
settingOptions.flashTaskbarOnMessage = true;
|
||||||
settingOptions.dndPreviousSettings.flashTaskbarOnMessage = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const i in settingOptions) {
|
for (const i in settingOptions) {
|
||||||
@@ -166,11 +155,6 @@ class ServerManagerView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initActions() {
|
initActions() {
|
||||||
this.initDNDButton();
|
|
||||||
this.$dndButton.addEventListener('click', () => {
|
|
||||||
const dndUtil = DNDUtil.toggle();
|
|
||||||
ipcRenderer.send('forward-message', 'toggle-dnd', dndUtil.dnd, dndUtil.newSettings);
|
|
||||||
});
|
|
||||||
this.$reloadButton.addEventListener('click', () => {
|
this.$reloadButton.addEventListener('click', () => {
|
||||||
this.tabs[this.activeTabIndex].webview.reload();
|
this.tabs[this.activeTabIndex].webview.reload();
|
||||||
});
|
});
|
||||||
@@ -191,16 +175,10 @@ class ServerManagerView {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.sidebarHoverEvent(this.$addServerButton, this.$addServerTooltip, true);
|
this.sidebarHoverEvent(this.$addServerButton, this.$addServerTooltip);
|
||||||
this.sidebarHoverEvent(this.$settingsButton, this.$settingsTooltip);
|
this.sidebarHoverEvent(this.$settingsButton, this.$settingsTooltip);
|
||||||
this.sidebarHoverEvent(this.$reloadButton, this.$reloadTooltip);
|
this.sidebarHoverEvent(this.$reloadButton, this.$reloadTooltip);
|
||||||
this.sidebarHoverEvent(this.$backButton, this.$backTooltip);
|
this.sidebarHoverEvent(this.$backButton, this.$backTooltip);
|
||||||
this.sidebarHoverEvent(this.$dndButton, this.$dndTooltip);
|
|
||||||
}
|
|
||||||
|
|
||||||
initDNDButton() {
|
|
||||||
const dnd = ConfigUtil.getConfigItem('dnd', false);
|
|
||||||
this.toggleDNDButton(dnd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getTabIndex() {
|
getTabIndex() {
|
||||||
@@ -209,17 +187,9 @@ class ServerManagerView {
|
|||||||
return currentIndex;
|
return currentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
sidebarHoverEvent(SidebarButton, SidebarTooltip, addServer = false) {
|
sidebarHoverEvent(SidebarButton, SidebarTooltip) {
|
||||||
SidebarButton.addEventListener('mouseover', () => {
|
SidebarButton.addEventListener('mouseover', () => {
|
||||||
SidebarTooltip.removeAttribute('style');
|
SidebarTooltip.removeAttribute('style');
|
||||||
// To handle position of add server tooltip due to scrolling of list of organizations
|
|
||||||
// This could not be handled using CSS, hence the top of the tooltip is made same
|
|
||||||
// as that of its parent element.
|
|
||||||
// This needs to handled only for the add server tooltip and not others.
|
|
||||||
if (addServer) {
|
|
||||||
const { top } = SidebarButton.getBoundingClientRect();
|
|
||||||
SidebarTooltip.style.top = top + 'px';
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
SidebarButton.addEventListener('mouseout', () => {
|
SidebarButton.addEventListener('mouseout', () => {
|
||||||
SidebarTooltip.style.display = 'none';
|
SidebarTooltip.style.display = 'none';
|
||||||
@@ -227,13 +197,8 @@ class ServerManagerView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onHover(index, serverName) {
|
onHover(index, serverName) {
|
||||||
this.$serverIconTooltip[index].innerText = serverName;
|
this.$serverIconTooltip[index].innerHTML = serverName;
|
||||||
this.$serverIconTooltip[index].removeAttribute('style');
|
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
|
|
||||||
// as that of its parent element.
|
|
||||||
const { top } = this.$serverIconTooltip[index].parentElement.getBoundingClientRect();
|
|
||||||
this.$serverIconTooltip[index].style.top = top + 'px';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onHoverOut(index) {
|
onHoverOut(index) {
|
||||||
@@ -273,9 +238,6 @@ class ServerManagerView {
|
|||||||
preload: false
|
preload: false
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
// To show loading indicator the first time a functional tab is opened, indicator is
|
|
||||||
// closed when the functional tab DOM is ready, handled in webview.js
|
|
||||||
this.$webviewsContainer.classList.remove('loaded');
|
|
||||||
this.activateTab(this.functionalTabs[tabProps.name]);
|
this.activateTab(this.functionalTabs[tabProps.name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,15 +324,6 @@ class ServerManagerView {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('toggle-dnd', (event, state, newSettings) => {
|
|
||||||
this.toggleDNDButton(state);
|
|
||||||
ipcRenderer.send('forward-message', 'toggle-silent', newSettings.silent);
|
|
||||||
const selector = 'webview:not([class*=disabled])';
|
|
||||||
const webview = document.querySelector(selector);
|
|
||||||
const webContents = webview.getWebContents();
|
|
||||||
webContents.send('toggle-dnd', state, newSettings);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyTab(name, index) {
|
destroyTab(name, index) {
|
||||||
@@ -390,9 +343,6 @@ class ServerManagerView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroyView() {
|
destroyView() {
|
||||||
// Show loading indicator
|
|
||||||
this.$webviewsContainer.classList.remove('loaded');
|
|
||||||
|
|
||||||
// Clear global variables
|
// Clear global variables
|
||||||
this.activeTabIndex = -1;
|
this.activeTabIndex = -1;
|
||||||
this.tabs = [];
|
this.tabs = [];
|
||||||
@@ -440,12 +390,6 @@ class ServerManagerView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggles the dnd button icon.
|
|
||||||
toggleDNDButton(alert) {
|
|
||||||
this.$dndTooltip.textContent = (alert ? 'Turn Off' : 'Enable') + ' Do Not Disturb';
|
|
||||||
this.$dndButton.querySelector('i').textContent = alert ? 'notifications_off' : 'notifications';
|
|
||||||
}
|
|
||||||
|
|
||||||
registerIpcs() {
|
registerIpcs() {
|
||||||
const webviewListeners = {
|
const webviewListeners = {
|
||||||
'webview-reload': 'reload',
|
'webview-reload': 'reload',
|
||||||
@@ -552,10 +496,6 @@ class ServerManagerView {
|
|||||||
}
|
}
|
||||||
ipcRenderer.send('update-taskbar-icon', createOverlayIcon(messageCount).toDataURL(), String(messageCount));
|
ipcRenderer.send('update-taskbar-icon', createOverlayIcon(messageCount).toDataURL(), String(messageCount));
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('open-feedback-modal', () => {
|
|
||||||
feedbackHolder.classList.add('show');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,11 +48,7 @@ class GeneralSection extends BaseSection {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="title">App Updates</div>
|
<div class="title">App Updates</div>
|
||||||
<div class="settings-card">
|
<div class="settings-card">
|
||||||
<div class="setting-row" id="autoupdate-option">
|
|
||||||
<div class="setting-description">Enable auto updates</div>
|
|
||||||
<div class="setting-control"></div>
|
|
||||||
</div>
|
|
||||||
<div class="setting-row" id="betaupdate-option">
|
<div class="setting-row" id="betaupdate-option">
|
||||||
<div class="setting-description">Get beta updates</div>
|
<div class="setting-description">Get beta updates</div>
|
||||||
<div class="setting-control"></div>
|
<div class="setting-control"></div>
|
||||||
@@ -108,8 +104,7 @@ class GeneralSection extends BaseSection {
|
|||||||
this.updateTrayOption();
|
this.updateTrayOption();
|
||||||
this.updateBadgeOption();
|
this.updateBadgeOption();
|
||||||
this.updateSilentOption();
|
this.updateSilentOption();
|
||||||
this.autoUpdateOption();
|
this.updateUpdateOption();
|
||||||
this.betaUpdateOption();
|
|
||||||
this.updateSidebarOption();
|
this.updateSidebarOption();
|
||||||
this.updateStartAtLoginOption();
|
this.updateStartAtLoginOption();
|
||||||
this.updateResetDataOption();
|
this.updateResetDataOption();
|
||||||
@@ -165,26 +160,14 @@ class GeneralSection extends BaseSection {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
autoUpdateOption() {
|
updateUpdateOption() {
|
||||||
this.generateSettingOption({
|
|
||||||
$element: document.querySelector('#autoupdate-option .setting-control'),
|
|
||||||
value: ConfigUtil.getConfigItem('autoUpdate', true),
|
|
||||||
clickHandler: () => {
|
|
||||||
const newValue = !ConfigUtil.getConfigItem('autoUpdate');
|
|
||||||
ConfigUtil.setConfigItem('autoUpdate', newValue);
|
|
||||||
this.autoUpdateOption();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
betaUpdateOption() {
|
|
||||||
this.generateSettingOption({
|
this.generateSettingOption({
|
||||||
$element: document.querySelector('#betaupdate-option .setting-control'),
|
$element: document.querySelector('#betaupdate-option .setting-control'),
|
||||||
value: ConfigUtil.getConfigItem('betaUpdate', false),
|
value: ConfigUtil.getConfigItem('betaUpdate', false),
|
||||||
clickHandler: () => {
|
clickHandler: () => {
|
||||||
const newValue = !ConfigUtil.getConfigItem('betaUpdate');
|
const newValue = !ConfigUtil.getConfigItem('betaUpdate');
|
||||||
ConfigUtil.setConfigItem('betaUpdate', newValue);
|
ConfigUtil.setConfigItem('betaUpdate', newValue);
|
||||||
this.betaUpdateOption();
|
this.updateUpdateOption();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,15 +97,6 @@ class PreferenceView extends BaseComponent {
|
|||||||
ipcRenderer.on('toggletray', (event, state) => {
|
ipcRenderer.on('toggletray', (event, state) => {
|
||||||
this.handleToggle('tray-option', state);
|
this.handleToggle('tray-option', state);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('toggle-dnd', (event, state, newSettings) => {
|
|
||||||
this.handleToggle('show-notification-option', newSettings.showNotification);
|
|
||||||
this.handleToggle('silent-option', newSettings.silent);
|
|
||||||
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
this.handleToggle('flash-taskbar-option', newSettings.flashTaskbarOnMessage);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const BaseSection = require(__dirname + '/base-section.js');
|
const BaseSection = require(__dirname + '/base-section.js');
|
||||||
const shell = require('electron').shell;
|
|
||||||
|
|
||||||
class ShortcutsSection extends BaseSection {
|
class ShortcutsSection extends BaseSection {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -24,10 +23,6 @@ class ShortcutsSection extends BaseSection {
|
|||||||
<tr>
|
<tr>
|
||||||
<td><kbd>${userOSKey}</kbd><kbd>K</kbd></td>
|
<td><kbd>${userOSKey}</kbd><kbd>K</kbd></td>
|
||||||
<td>Keyboard Shortcuts</td>
|
<td>Keyboard Shortcuts</td>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>M</kbd></td>
|
|
||||||
<td>Toggle Do Not Disturb</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><kbd>Shift</kbd><kbd>${userOSKey}</kbd><kbd>D</kbd></td>
|
<td><kbd>Shift</kbd><kbd>${userOSKey}</kbd><kbd>D</kbd></td>
|
||||||
@@ -160,7 +155,6 @@ class ShortcutsSection extends BaseSection {
|
|||||||
</table>
|
</table>
|
||||||
<div class="setting-control"></div>
|
<div class="setting-control"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-card tip"><b><i class="material-icons md-14">settings</i>Tip: </b>These desktop app shortcuts extend the Zulip webapp's <span id="open-hotkeys-link">keyboard shortcuts</span>.</div>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -180,10 +174,6 @@ class ShortcutsSection extends BaseSection {
|
|||||||
<tr>
|
<tr>
|
||||||
<td><kbd>${userOSKey}</kbd> + <kbd>K</kbd></td>
|
<td><kbd>${userOSKey}</kbd> + <kbd>K</kbd></td>
|
||||||
<td>Keyboard Shortcuts</td>
|
<td>Keyboard Shortcuts</td>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>M</kbd></td>
|
|
||||||
<td>Toggle Do Not Disturb</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><kbd>${userOSKey}</kbd> + <kbd>L</kbd></td>
|
<td><kbd>${userOSKey}</kbd> + <kbd>L</kbd></td>
|
||||||
@@ -300,22 +290,13 @@ class ShortcutsSection extends BaseSection {
|
|||||||
</table>
|
</table>
|
||||||
<div class="setting-control"></div>
|
<div class="setting-control"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tip"><b><i class="material-icons md-14">lightbulb_outline</i>Tip: </b>These desktop app shortcuts extend the Zulip webapp's <span id="open-hotkeys-link">keyboard shortcuts</span>.</div>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
openHotkeysExternalLink() {
|
|
||||||
const link = 'https://zulipchat.com/help/keyboard-shortcuts';
|
|
||||||
const externalCreateNewOrgEl = document.getElementById('open-hotkeys-link');
|
|
||||||
externalCreateNewOrgEl.addEventListener('click', () => {
|
|
||||||
shell.openExternal(link);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
init() {
|
init() {
|
||||||
this.props.$root.innerHTML = (process.platform === 'darwin') ?
|
this.props.$root.innerHTML = (process.platform === 'darwin') ?
|
||||||
this.templateMac() : this.templateWinLin();
|
this.templateMac() : this.templateWinLin();
|
||||||
this.openHotkeysExternalLink();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ const renderNativeImage = function (arg) {
|
|||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => renderCanvas(arg))
|
.then(() => renderCanvas(arg))
|
||||||
.then(canvas => {
|
.then(canvas => {
|
||||||
const pngData = nativeImage.createFromDataURL(canvas.toDataURL('image/png')).toPNG();
|
const pngData = nativeImage.createFromDataURL(canvas.toDataURL('image/png')).toPng();
|
||||||
return Promise.resolve(nativeImage.createFromBuffer(pngData, config.pixelRatio));
|
return Promise.resolve(nativeImage.createFromBuffer(pngData, config.pixelRatio));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const ConfigUtil = require(__dirname + '/config-util.js');
|
|
||||||
|
|
||||||
function toggle() {
|
|
||||||
const dnd = !ConfigUtil.getConfigItem('dnd', false);
|
|
||||||
const dndSettingList = ['showNotification', 'silent'];
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
dndSettingList.push('flashTaskbarOnMessage');
|
|
||||||
}
|
|
||||||
|
|
||||||
let newSettings;
|
|
||||||
if (dnd) {
|
|
||||||
const oldSettings = {};
|
|
||||||
newSettings = {};
|
|
||||||
|
|
||||||
// Iterate through the dndSettingList.
|
|
||||||
for (const settingName of dndSettingList) {
|
|
||||||
// Store the current value of setting.
|
|
||||||
oldSettings[settingName] = ConfigUtil.getConfigItem(settingName);
|
|
||||||
// New value of setting.
|
|
||||||
newSettings[settingName] = (settingName === 'silent');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store old value in oldSettings.
|
|
||||||
ConfigUtil.setConfigItem('dndPreviousSettings', oldSettings);
|
|
||||||
} else {
|
|
||||||
newSettings = ConfigUtil.getConfigItem('dndPreviousSettings');
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const settingName of dndSettingList) {
|
|
||||||
ConfigUtil.setConfigItem(settingName, newSettings[settingName]);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigUtil.setConfigItem('dnd', dnd);
|
|
||||||
return {dnd, newSettings};
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
toggle
|
|
||||||
};
|
|
||||||
@@ -5,8 +5,6 @@ const fs = require('fs');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const JsonDB = require('node-json-db');
|
const JsonDB = require('node-json-db');
|
||||||
const request = require('request');
|
const request = require('request');
|
||||||
const escape = require('escape-html');
|
|
||||||
|
|
||||||
const Logger = require('./logger-util');
|
const Logger = require('./logger-util');
|
||||||
|
|
||||||
const logger = new Logger({
|
const logger = new Logger({
|
||||||
@@ -190,7 +188,7 @@ class DomainUtil {
|
|||||||
// Following check handles both the cases
|
// Following check handles both the cases
|
||||||
icon: data.realm_icon.startsWith('/') ? data.realm_uri + data.realm_icon : data.realm_icon,
|
icon: data.realm_icon.startsWith('/') ? data.realm_uri + data.realm_icon : data.realm_icon,
|
||||||
url: data.realm_uri,
|
url: data.realm_uri,
|
||||||
alias: escape(data.realm_name)
|
alias: data.realm_name
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ class ReconnectUtil {
|
|||||||
pollInternetAndReload() {
|
pollInternetAndReload() {
|
||||||
const pollInterval = setInterval(() => {
|
const pollInterval = setInterval(() => {
|
||||||
this._checkAndReload()
|
this._checkAndReload()
|
||||||
.then(status => {
|
.then(status => {
|
||||||
if (status) {
|
if (status) {
|
||||||
this.alreadyReloaded = true;
|
this.alreadyReloaded = true;
|
||||||
clearInterval(pollInterval);
|
clearInterval(pollInterval);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, 1500);
|
}, 1500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,24 +26,22 @@ class ReconnectUtil {
|
|||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
if (!this.alreadyReloaded) { // eslint-disable-line no-negated-condition
|
if (!this.alreadyReloaded) { // eslint-disable-line no-negated-condition
|
||||||
isOnline()
|
isOnline()
|
||||||
.then(online => {
|
.then(online => {
|
||||||
if (online) {
|
if (online) {
|
||||||
if (!this.alreadyReloaded) {
|
if (!this.alreadyReloaded) {
|
||||||
this.serverManagerView.reloadView();
|
this.serverManagerView.reloadView();
|
||||||
}
|
|
||||||
console.log('You\'re back online.');
|
|
||||||
return resolve(true);
|
|
||||||
}
|
}
|
||||||
|
console.log('You\'re back online.');
|
||||||
|
return resolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
console.log('There is no internet connection, try checking network cables, modem and router.');
|
console.log('There is no internet connection, try checking network cables, modem and router.');
|
||||||
const errMsgHolder = document.querySelector('#description');
|
const errMsgHolder = document.querySelector('#description');
|
||||||
if (errMsgHolder) {
|
errMsgHolder.innerHTML = `
|
||||||
errMsgHolder.innerHTML = `
|
|
||||||
<div>You internet connection does't seem to work properly!</div>
|
<div>You internet connection does't seem to work properly!</div>
|
||||||
</div>Verify that it works and then click try again.</div>`;
|
</div>Verify that it works and then click try again.</div>`;
|
||||||
}
|
return resolve(false);
|
||||||
return resolve(false);
|
});
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
return resolve(true);
|
return resolve(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,10 +24,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="actions-container">
|
<div id="actions-container">
|
||||||
<div class="action-button" id="dnd-action">
|
|
||||||
<i class="material-icons md-48">notifications</i>
|
|
||||||
<span id="dnd-tooltip" style="display:none">Do Not Disturb</span>
|
|
||||||
</div>
|
|
||||||
<div class="action-button" id="reload-action">
|
<div class="action-button" id="reload-action">
|
||||||
<i class="material-icons md-48">refresh</i>
|
<i class="material-icons md-48">refresh</i>
|
||||||
<span id="reload-tooltip" style="display:none">Reload</span>
|
<span id="reload-tooltip" style="display:none">Reload</span>
|
||||||
@@ -46,11 +42,7 @@
|
|||||||
<div id="webviews-container"></div>
|
<div id="webviews-container"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="feedback-modal">
|
|
||||||
<send-feedback></send-feedback>
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
<script>require('./js/shared/preventdrag.js')</script>
|
<script>require('./js/shared/preventdrag.js')</script>
|
||||||
</html>
|
</html>
|
||||||
@@ -6,9 +6,9 @@ os: Previous Visual Studio 2015
|
|||||||
|
|
||||||
cache:
|
cache:
|
||||||
- node_modules
|
- node_modules
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- ps: Install-Product node 8 x64
|
- ps: Install-Product node 6 x64
|
||||||
- git reset --hard HEAD
|
- git reset --hard HEAD
|
||||||
- npm install npm -g
|
- npm install npm -g
|
||||||
- node --version
|
- node --version
|
||||||
@@ -21,4 +21,4 @@ build: off
|
|||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- npm run test
|
- npm run test
|
||||||
# - npm run test-e2e
|
- npm run test-e2e
|
||||||
|
|||||||
BIN
build/appdmg.png
BIN
build/appdmg.png
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 6.2 KiB |
10034
package-lock.json
generated
10034
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
28
package.json
28
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "zulip",
|
"name": "zulip",
|
||||||
"productName": "Zulip",
|
"productName": "Zulip",
|
||||||
"version": "2.3.1",
|
"version": "1.9.0",
|
||||||
"main": "./app/main",
|
"main": "./app/main",
|
||||||
"description": "Zulip Desktop App",
|
"description": "Zulip Desktop App",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
@@ -46,8 +46,7 @@
|
|||||||
],
|
],
|
||||||
"copyright": "©2017 Kandra Labs, Inc.",
|
"copyright": "©2017 Kandra Labs, Inc.",
|
||||||
"mac": {
|
"mac": {
|
||||||
"category": "public.app-category.productivity",
|
"category": "public.app-category.productivity"
|
||||||
"artifactName": "${productName}-${version}-${arch}.${ext}"
|
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"category": "Chat;GNOME;GTK;Network;InstantMessaging",
|
"category": "Chat;GNOME;GTK;Network;InstantMessaging",
|
||||||
@@ -59,8 +58,7 @@
|
|||||||
"AppImage",
|
"AppImage",
|
||||||
"snap"
|
"snap"
|
||||||
],
|
],
|
||||||
"maintainer": "Akash Nimare <svnitakash@gmail.com>",
|
"maintainer": "Akash Nimare <svnitakash@gmail.com>"
|
||||||
"artifactName": "${productName}-${version}-${arch}.${ext}"
|
|
||||||
},
|
},
|
||||||
"deb": {
|
"deb": {
|
||||||
"synopsis": "Zulip Desktop App",
|
"synopsis": "Zulip Desktop App",
|
||||||
@@ -73,24 +71,20 @@
|
|||||||
"dmg": {
|
"dmg": {
|
||||||
"background": "build/appdmg.png",
|
"background": "build/appdmg.png",
|
||||||
"icon": "build/icon.icns",
|
"icon": "build/icon.icns",
|
||||||
"iconSize": 100,
|
"iconSize": 128,
|
||||||
"contents": [
|
"contents": [
|
||||||
{
|
{
|
||||||
"x": 380,
|
"x": 380,
|
||||||
"y": 280,
|
"y": 240,
|
||||||
"type": "link",
|
"type": "link",
|
||||||
"path": "/Applications"
|
"path": "/Applications"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"x": 110,
|
"x": 122,
|
||||||
"y": 280,
|
"y": 240,
|
||||||
"type": "file"
|
"type": "file"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"window": {
|
|
||||||
"width": 500,
|
|
||||||
"height": 500
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"win": {
|
"win": {
|
||||||
"target": [
|
"target": [
|
||||||
@@ -123,12 +117,12 @@
|
|||||||
"assert": "1.4.1",
|
"assert": "1.4.1",
|
||||||
"cp-file": "^5.0.0",
|
"cp-file": "^5.0.0",
|
||||||
"devtron": "1.4.0",
|
"devtron": "1.4.0",
|
||||||
"electron": "2.0.1",
|
"electron": "1.8.4",
|
||||||
"electron-builder": "20.13.4",
|
"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",
|
||||||
"gulp": "^4.0.0",
|
"gulp": "3.9.1",
|
||||||
"gulp-tape": "0.0.9",
|
"gulp-tape": "0.0.9",
|
||||||
"is-ci": "^1.0.10",
|
"is-ci": "^1.0.10",
|
||||||
"nodemon": "^1.14.11",
|
"nodemon": "^1.14.11",
|
||||||
|
|||||||
@@ -15,6 +15,6 @@ fi
|
|||||||
|
|
||||||
npm run test
|
npm run test
|
||||||
|
|
||||||
# if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
# npm run test-e2e
|
npm run test-e2e
|
||||||
# fi
|
fi
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.6 KiB |
@@ -1,10 +1,10 @@
|
|||||||
name: zulip
|
name: zulip
|
||||||
version: 2.0.0
|
version: 1.8.2
|
||||||
summary: Zulip Desktop Client for Linux
|
summary: Zulip
|
||||||
description: Zulip combines the immediacy of Slack with an email threading model. With Zulip, you can catch up on important conversations while ignoring irrelevant ones.
|
description: Zulip Desktop Client for Linux
|
||||||
confinement: strict
|
confinement: strict
|
||||||
grade: stable
|
grade: stable
|
||||||
icon: snap/gui/icon.png
|
icon: ../build/icon.png
|
||||||
apps:
|
apps:
|
||||||
zulip:
|
zulip:
|
||||||
command: env TMPDIR=$XDG_RUNTIME_DIR desktop-launch $SNAP/zulip
|
command: env TMPDIR=$XDG_RUNTIME_DIR desktop-launch $SNAP/zulip
|
||||||
@@ -32,6 +32,6 @@ parts:
|
|||||||
- libpulse0
|
- libpulse0
|
||||||
- libxss1
|
- libxss1
|
||||||
- libxtst6
|
- libxtst6
|
||||||
source: dist/linux-unpacked
|
source: ../dist/linux-unpacked
|
||||||
after:
|
after:
|
||||||
- desktop-gtk2
|
- desktop-gtk2
|
||||||
|
|||||||
Reference in New Issue
Block a user