Compare commits

..

1 Commits

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

View File

@@ -15,7 +15,7 @@ addons:
language: node_js
node_js:
- '8'
- '6'
before_install:
- ./scripts/travis-xvfb.sh

View File

@@ -12,7 +12,7 @@ Zulip-Desktop app is built on top of [Electron](http://electron.atom.io/). If yo
* The whole Zulip documentation, such as setting up a development environment, setting up with the Zulip webapp project, and testing, can be read [here](https://zulip.readthedocs.io).
* If you have any questions regarding zulip-electron, open an [issue](https://github.com/zulip/zulip-electron/issues/new/) or ask it on [chat.zulip.org](https://chat.zulip.org/#narrow/stream/16-desktop).
* If you have any questions regarding zulip-electron, open an [issue](https://github.com/zulip/zulip-electron/issues/new/) or ask it on [chat.zulip.org](https://chat.zulip.org/#narrow/stream/electron).
## Issue
Ensure the bug was not already reported by searching on GitHub under [issues](https://github.com/zulip/zulip-electron/issues). If you're unable to find an open issue addressing the bug, open a [new issue](https://github.com/zulip/zulip-electron/issues/new).

View File

@@ -1,11 +1,11 @@
'use strict';
const { app, dialog, shell } = require('electron');
const { app, dialog } = require('electron');
const { autoUpdater } = require('electron-updater');
const isDev = require('electron-is-dev');
const ConfigUtil = require('./../renderer/js/utils/config-util.js');
function appUpdater(updateFromMenu = false) {
function appUpdater() {
// Don't initiate auto-updates in development
if (isDev) {
return;
@@ -17,8 +17,6 @@ function appUpdater(updateFromMenu = false) {
return;
}
let updateAvailable = false;
// Create Logs directory
const LogsDir = `${app.getPath('userData')}/Logs`;
@@ -30,58 +28,7 @@ function appUpdater(updateFromMenu = false) {
autoUpdater.logger = log;
// Handle auto updates for beta/pre releases
const isBetaUpdate = ConfigUtil.getConfigItem('betaUpdate');
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();
}
});
autoUpdater.allowPrerelease = ConfigUtil.getConfigItem('betaUpdate') || false;
// Ask the user if update is available
// eslint-disable-next-line no-unused-vars

View File

@@ -7,7 +7,7 @@ const crashHandler = () => {
productName: 'zulip-electron',
companyName: 'Kandra Labs, Inc.',
submitURL: 'https://zulip-sentry.herokuapp.com/crashreport',
uploadToServer: true
autoSubmit: true
});
};

View File

@@ -131,10 +131,6 @@ function createMainWindow() {
// Decrease load on GPU (experimental)
app.disableHardwareAcceleration();
// Temporary fix for Electron render colors differently
// More info here - https://github.com/electron/electron/issues/10732
app.commandLine.appendSwitch('force-color-profile', 'srgb');
// eslint-disable-next-line max-params
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
event.preventDefault();
@@ -165,9 +161,7 @@ app.on('ready', () => {
page.once('did-frame-finish-load', () => {
// Initate auto-updates on MacOS and Windows
if (ConfigUtil.getConfigItem('autoUpdate')) {
appUpdater();
}
appUpdater();
crashHandler();
});

View File

@@ -1,13 +1,12 @@
'use strict';
const os = require('os');
const path = require('path');
const { app, shell, BrowserWindow, Menu, dialog } = require('electron');
const fs = require('fs-extra');
const { appUpdater } = require('./autoupdater');
const ConfigUtil = require(__dirname + '/../renderer/js/utils/config-util.js');
const DNDUtil = require(__dirname + '/../renderer/js/utils/dnd-util.js');
const appName = app.getName();
@@ -140,11 +139,13 @@ class AppMenu {
}, {
label: 'Report an Issue...',
click() {
// the goal is to notify the main.html BrowserWindow
// which may not be the focused window.
BrowserWindow.getAllWindows().forEach(window => {
window.webContents.send('open-feedback-modal');
});
const body = `
<!-- Please succinctly describe your issue and steps to reproduce it. -->
-
${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');
}
}
}, {
label: `Check for Update`,
click() {
AppMenu.checkForUpdate();
}
}, {
}, {
type: 'separator'
}, {
label: 'Desktop App Settings',
@@ -221,13 +217,6 @@ class AppMenu {
}
}, {
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',
accelerator: 'Command+Shift+D',
@@ -308,12 +297,7 @@ class AppMenu {
AppMenu.sendAction('open-about');
}
}
}, {
label: `Check for Update`,
click() {
AppMenu.checkForUpdate();
}
}, {
}, {
type: 'separator'
}, {
label: 'Desktop App Settings',
@@ -335,13 +319,6 @@ class AppMenu {
}
}, {
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',
accelerator: 'Ctrl+Shift+D',
@@ -410,9 +387,6 @@ class AppMenu {
win.webContents.send(action, ...params);
}
static checkForUpdate() {
appUpdater(true);
}
static resetAppSettings() {
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",
"productName": "Zulip",
"version": "2.3.2",
"version": "1.9.0",
"description": "Zulip Desktop App",
"license": "Apache-2.0",
"copyright": "Kandra Labs, Inc.",
@@ -26,21 +26,20 @@
"InstantMessaging"
],
"dependencies": {
"@electron-elements/send-feedback": "1.0.7",
"escape-html": "1.0.3",
"auto-launch": "5.0.5",
"auto-launch": "5.0.1",
"electron-is-dev": "0.3.0",
"electron-log": "2.2.14",
"electron-log": "2.2.7",
"electron-spellchecker": "1.1.2",
"electron-updater": "2.21.10",
"electron-updater": "2.21.4",
"electron-window-state": "4.1.1",
"is-online": "7.0.0",
"node-json-db": "0.7.3",
"request": "2.85.0",
"request": "2.81.0",
"semver": "5.4.1",
"@sentry/electron": "0.5.0",
"wurl": "2.5.0"
},
"optionalDependencies": {
"node-mac-notifier": "0.1.0"
"node-mac-notifier": "0.0.13"
}
}

View File

@@ -13,6 +13,9 @@ body {
#content {
display: flex;
height: 100%;
background: #fff url(../img/ic_loading.gif) no-repeat;
background-size: 60px 60px;
background-position: center;
}
.toggle-sidebar {
@@ -42,28 +45,6 @@ body {
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-family: 'Material Icons';
font-style: normal;
@@ -270,25 +251,6 @@ body {
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 {
/* transition: opacity 0.3s ease-in; */
flex-grow: 1;
@@ -300,6 +262,11 @@ webview {
flex-direction: column;
}
webview.download-webview {
z-index: -1;
pointer-events: none;
}
webview.onload {
transition: opacity 1s cubic-bezier(0.95, 0.05, 0.795, 0.035);
}
@@ -320,7 +287,6 @@ webview.focus {
/* Tooltip styling */
#dnd-tooltip,
#back-tooltip,
#reload-tooltip,
#setting-tooltip {
@@ -338,7 +304,6 @@ webview.focus {
font-size: 14px;
}
#dnd-tooltip:after,
#back-tooltip:after,
#reload-tooltip:after,
#setting-tooltip:after {
@@ -443,26 +408,3 @@ webview.focus {
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;
}
.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 */

View File

@@ -1,6 +1,7 @@
const { shell } = require('electron').remote;
const LinkUtil = require('../utils/link-util');
const DomainUtil = require('../utils/domain-util');
const hiddenWebView = require('../components/hidden-webview');
function handleExternalLink(event) {
const { url } = event;
@@ -15,12 +16,12 @@ function handleExternalLink(event) {
if (isWhiteListURL) {
event.preventDefault();
// download txt, pdf, mp3, mp4 etc.. by using downloadURL in the
// main process which allows the user to save the files to their desktop
// and not trigger webview reload while image in webview will
// do nothing and will not save it
// only open the pdf, mp3, mp4 etc.. in hidden webview since opening the
// image in webview will do nothing and will not save it
// whereas the pdf will be saved to user desktop once openened in
// in the hidden webview and will not trigger webview reload
if (!LinkUtil.isImage(url) && isUploadsURL) {
this.$el.downloadURL(url);
hiddenWebView.loadURL(url);
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.zoomFactor = 1.0;
this.loading = true;
this.loading = false;
this.badgeCount = 0;
this.customCSS = ConfigUtil.getConfigItem('customCSS');
this.$webviewsContainer = document.querySelector('#webviews-container').classList;
}
template() {
@@ -87,7 +86,6 @@ class WebView extends BaseComponent {
if (this.props.role === 'server') {
this.$el.classList.add('onload');
}
this.loading = false;
this.show();
});
@@ -121,13 +119,6 @@ class WebView extends BaseComponent {
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.add('active');
setTimeout(() => {
@@ -136,6 +127,7 @@ class WebView extends BaseComponent {
}
}, 1000);
this.focus();
this.loading = false;
this.props.onTitleChange();
// Injecting preload css in webview to override some css rules
this.$el.insertCSS(fs.readFileSync(path.join(__dirname, '/../../css/preload.css'), 'utf8'));
@@ -228,9 +220,6 @@ class WebView extends BaseComponent {
reload() {
this.hide();
// Shows the loading indicator till the webview is reloaded
this.$webviewsContainer.remove('loaded');
this.loading = true;
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 FunctionalTab = require(__dirname + '/js/components/functional-tab.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 { feedbackHolder } = require(__dirname + '/js/feedback.js');
class ServerManagerView {
constructor() {
@@ -25,14 +23,12 @@ class ServerManagerView {
this.$settingsButton = $actionsContainer.querySelector('#settings-action');
this.$webviewsContainer = document.getElementById('webviews-container');
this.$backButton = $actionsContainer.querySelector('#back-action');
this.$dndButton = $actionsContainer.querySelector('#dnd-action');
this.$addServerTooltip = document.getElementById('add-server-tooltip');
this.$reloadTooltip = $actionsContainer.querySelector('#reload-tooltip');
this.$settingsTooltip = $actionsContainer.querySelector('#setting-tooltip');
this.$serverIconTooltip = document.getElementsByClassName('server-tooltip');
this.$backTooltip = $actionsContainer.querySelector('#back-tooltip');
this.$dndTooltip = $actionsContainer.querySelector('#dnd-tooltip');
this.$sidebar = document.getElementById('sidebar');
@@ -89,15 +85,9 @@ class ServerManagerView {
startMinimized: false,
enableSpellchecker: true,
showNotification: true,
autoUpdate: true,
betaUpdate: false,
silent: false,
lastActiveTab: 0,
dnd: false,
dndPreviousSettings: {
showNotification: true,
silent: false
}
lastActiveTab: 0
};
// Platform specific settings
@@ -105,7 +95,6 @@ class ServerManagerView {
if (process.platform === 'win32') {
// Only available on Windows
settingOptions.flashTaskbarOnMessage = true;
settingOptions.dndPreviousSettings.flashTaskbarOnMessage = true;
}
for (const i in settingOptions) {
@@ -166,11 +155,6 @@ class ServerManagerView {
}
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.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.$reloadButton, this.$reloadTooltip);
this.sidebarHoverEvent(this.$backButton, this.$backTooltip);
this.sidebarHoverEvent(this.$dndButton, this.$dndTooltip);
}
initDNDButton() {
const dnd = ConfigUtil.getConfigItem('dnd', false);
this.toggleDNDButton(dnd);
}
getTabIndex() {
@@ -209,17 +187,9 @@ class ServerManagerView {
return currentIndex;
}
sidebarHoverEvent(SidebarButton, SidebarTooltip, addServer = false) {
sidebarHoverEvent(SidebarButton, SidebarTooltip) {
SidebarButton.addEventListener('mouseover', () => {
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', () => {
SidebarTooltip.style.display = 'none';
@@ -227,13 +197,8 @@ class ServerManagerView {
}
onHover(index, serverName) {
this.$serverIconTooltip[index].innerText = serverName;
this.$serverIconTooltip[index].innerHTML = serverName;
this.$serverIconTooltip[index].removeAttribute('style');
// To handle position of servers' tooltip due to scrolling of list of organizations
// This could not be handled using CSS, hence the top of the tooltip is made same
// as that of its parent element.
const { top } = this.$serverIconTooltip[index].parentElement.getBoundingClientRect();
this.$serverIconTooltip[index].style.top = top + 'px';
}
onHoverOut(index) {
@@ -273,9 +238,6 @@ class ServerManagerView {
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]);
}
@@ -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) {
@@ -390,9 +343,6 @@ class ServerManagerView {
}
destroyView() {
// Show loading indicator
this.$webviewsContainer.classList.remove('loaded');
// Clear global variables
this.activeTabIndex = -1;
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() {
const webviewListeners = {
'webview-reload': 'reload',
@@ -552,10 +496,6 @@ class ServerManagerView {
}
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 class="title">App Updates</div>
<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="settings-card">
<div class="setting-row" id="betaupdate-option">
<div class="setting-description">Get beta updates</div>
<div class="setting-control"></div>
@@ -108,8 +104,7 @@ class GeneralSection extends BaseSection {
this.updateTrayOption();
this.updateBadgeOption();
this.updateSilentOption();
this.autoUpdateOption();
this.betaUpdateOption();
this.updateUpdateOption();
this.updateSidebarOption();
this.updateStartAtLoginOption();
this.updateResetDataOption();
@@ -165,26 +160,14 @@ class GeneralSection extends BaseSection {
});
}
autoUpdateOption() {
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() {
updateUpdateOption() {
this.generateSettingOption({
$element: document.querySelector('#betaupdate-option .setting-control'),
value: ConfigUtil.getConfigItem('betaUpdate', false),
clickHandler: () => {
const newValue = !ConfigUtil.getConfigItem('betaUpdate');
ConfigUtil.setConfigItem('betaUpdate', newValue);
this.betaUpdateOption();
this.updateUpdateOption();
}
});
}

View File

@@ -97,15 +97,6 @@ class PreferenceView extends BaseComponent {
ipcRenderer.on('toggletray', (event, 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';
const BaseSection = require(__dirname + '/base-section.js');
const shell = require('electron').shell;
class ShortcutsSection extends BaseSection {
constructor(props) {
@@ -24,10 +23,6 @@ class ShortcutsSection extends BaseSection {
<tr>
<td><kbd>${userOSKey}</kbd><kbd>K</kbd></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>
<td><kbd>Shift</kbd><kbd>${userOSKey}</kbd><kbd>D</kbd></td>
@@ -160,7 +155,6 @@ class ShortcutsSection extends BaseSection {
</table>
<div class="setting-control"></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>
`;
}
@@ -180,10 +174,6 @@ class ShortcutsSection extends BaseSection {
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>K</kbd></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>
<td><kbd>${userOSKey}</kbd> + <kbd>L</kbd></td>
@@ -300,22 +290,13 @@ class ShortcutsSection extends BaseSection {
</table>
<div class="setting-control"></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>
`;
}
openHotkeysExternalLink() {
const link = 'https://zulipchat.com/help/keyboard-shortcuts';
const externalCreateNewOrgEl = document.getElementById('open-hotkeys-link');
externalCreateNewOrgEl.addEventListener('click', () => {
shell.openExternal(link);
});
}
init() {
this.props.$root.innerHTML = (process.platform === 'darwin') ?
this.templateMac() : this.templateWinLin();
this.openHotkeysExternalLink();
}
}

View File

@@ -98,7 +98,7 @@ const renderNativeImage = function (arg) {
return Promise.resolve()
.then(() => renderCanvas(arg))
.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));
});
};

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 JsonDB = require('node-json-db');
const request = require('request');
const escape = require('escape-html');
const Logger = require('./logger-util');
const logger = new Logger({
@@ -190,7 +188,7 @@ class DomainUtil {
// Following check handles both the cases
icon: data.realm_icon.startsWith('/') ? data.realm_uri + data.realm_icon : data.realm_icon,
url: data.realm_uri,
alias: escape(data.realm_name)
alias: data.realm_name
});
}
} else {

View File

@@ -13,12 +13,12 @@ class ReconnectUtil {
pollInternetAndReload() {
const pollInterval = setInterval(() => {
this._checkAndReload()
.then(status => {
if (status) {
this.alreadyReloaded = true;
clearInterval(pollInterval);
}
});
.then(status => {
if (status) {
this.alreadyReloaded = true;
clearInterval(pollInterval);
}
});
}, 1500);
}
@@ -26,24 +26,22 @@ class ReconnectUtil {
return new Promise(resolve => {
if (!this.alreadyReloaded) { // eslint-disable-line no-negated-condition
isOnline()
.then(online => {
if (online) {
if (!this.alreadyReloaded) {
this.serverManagerView.reloadView();
}
console.log('You\'re back online.');
return resolve(true);
.then(online => {
if (online) {
if (!this.alreadyReloaded) {
this.serverManagerView.reloadView();
}
console.log('You\'re back online.');
return resolve(true);
}
console.log('There is no internet connection, try checking network cables, modem and router.');
const errMsgHolder = document.querySelector('#description');
if (errMsgHolder) {
errMsgHolder.innerHTML = `
console.log('There is no internet connection, try checking network cables, modem and router.');
const errMsgHolder = document.querySelector('#description');
errMsgHolder.innerHTML = `
<div>You internet connection does't seem to work properly!</div>
</div>Verify that it works and then click try again.</div>`;
}
return resolve(false);
});
return resolve(false);
});
} else {
return resolve(true);
}

View File

@@ -24,10 +24,6 @@
</div>
</div>
<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">
<i class="material-icons md-48">refresh</i>
<span id="reload-tooltip" style="display:none">Reload</span>
@@ -46,11 +42,7 @@
<div id="webviews-container"></div>
</div>
</div>
<div id="feedback-modal">
<send-feedback></send-feedback>
</div>
</body>
<script src="js/main.js"></script>
<script>require('./js/shared/preventdrag.js')</script>
</html>
</html>

View File

@@ -6,9 +6,9 @@ os: Previous Visual Studio 2015
cache:
- node_modules
install:
- ps: Install-Product node 8 x64
- ps: Install-Product node 6 x64
- git reset --hard HEAD
- npm install npm -g
- node --version
@@ -21,4 +21,4 @@ build: off
test_script:
- 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

10087
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "zulip",
"productName": "Zulip",
"version": "2.3.2",
"version": "1.9.0",
"main": "./app/main",
"description": "Zulip Desktop App",
"license": "Apache-2.0",
@@ -46,8 +46,7 @@
],
"copyright": "©2017 Kandra Labs, Inc.",
"mac": {
"category": "public.app-category.productivity",
"artifactName": "${productName}-${version}-${arch}.${ext}"
"category": "public.app-category.productivity"
},
"linux": {
"category": "Chat;GNOME;GTK;Network;InstantMessaging",
@@ -59,8 +58,7 @@
"AppImage",
"snap"
],
"maintainer": "Akash Nimare <svnitakash@gmail.com>",
"artifactName": "${productName}-${version}-${arch}.${ext}"
"maintainer": "Akash Nimare <svnitakash@gmail.com>"
},
"deb": {
"synopsis": "Zulip Desktop App",
@@ -73,24 +71,20 @@
"dmg": {
"background": "build/appdmg.png",
"icon": "build/icon.icns",
"iconSize": 100,
"iconSize": 128,
"contents": [
{
"x": 380,
"y": 280,
"y": 240,
"type": "link",
"path": "/Applications"
},
{
"x": 110,
"y": 280,
"x": 122,
"y": 240,
"type": "file"
}
],
"window": {
"width": 500,
"height": 500
}
]
},
"win": {
"target": [
@@ -123,12 +117,12 @@
"assert": "1.4.1",
"cp-file": "^5.0.0",
"devtron": "1.4.0",
"electron": "2.0.1",
"electron-builder": "20.15.1",
"electron": "1.8.4",
"electron-builder": "20.8.1",
"electron-connect": "0.6.2",
"electron-debug": "1.4.0",
"google-translate-api": "2.3.0",
"gulp": "^4.0.0",
"gulp": "3.9.1",
"gulp-tape": "0.0.9",
"is-ci": "^1.0.10",
"nodemon": "^1.14.11",

View File

@@ -15,6 +15,6 @@ fi
npm run test
# if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
# npm run test-e2e
# fi
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
npm run test-e2e
fi

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1,10 +1,10 @@
name: zulip
version: 2.0.0
summary: Zulip Desktop Client for Linux
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.
version: 1.8.2
summary: Zulip
description: Zulip Desktop Client for Linux
confinement: strict
grade: stable
icon: snap/gui/icon.png
icon: ../build/icon.png
apps:
zulip:
command: env TMPDIR=$XDG_RUNTIME_DIR desktop-launch $SNAP/zulip
@@ -32,6 +32,6 @@ parts:
- libpulse0
- libxss1
- libxtst6
source: dist/linux-unpacked
source: ../dist/linux-unpacked
after:
- desktop-gtk2