Compare commits

..

1 Commits

Author SHA1 Message Date
Akash Nimare
d6738b7087 sentry: Init sentry-electron. 2018-04-13 17:02:57 +05:30
29 changed files with 99 additions and 11930 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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
}); });
}; };

View File

@@ -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();
}); });

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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"
} }
} }

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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;
} }

View 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;

View File

@@ -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();
} }

View File

@@ -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
};

View File

@@ -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');
});
} }
} }

View File

@@ -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();
} }
}); });
} }

View File

@@ -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);
}
});
} }
} }

View File

@@ -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();
} }
} }

View File

@@ -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));
}); });
}; };

View File

@@ -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
};

View File

@@ -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 {

View File

@@ -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);
} }

View File

@@ -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>

View File

@@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

10034
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -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",

View File

@@ -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

View File

@@ -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