Compare commits

..

1 Commits

Author SHA1 Message Date
akashnimare
7194e788e4 Add a setting option to control auto-updates 2017-09-12 21:43:53 +05:30
22 changed files with 96 additions and 329 deletions

View File

@@ -8,7 +8,7 @@ Desktop client for Zulip. Available for Mac, Linux and Windows.
<img src="http://i.imgur.com/ChzTq4F.png"/>
# Download
Please see [installation guide](https://zulipchat.com/help/desktop-app-install-guide).
Please see [installation guide](./how-to-install.md).
# Features
* Sign in to multiple teams

View File

@@ -1,16 +0,0 @@
'use strict';
const { crashReporter } = require('electron');
const crashHandler = () => {
crashReporter.start({
productName: 'zulip-electron',
companyName: 'Kandra Labs, Inc.',
submitURL: 'https://zulip-sentry.herokuapp.com/crashreport',
autoSubmit: true
});
};
module.exports = {
crashHandler
};

View File

@@ -5,8 +5,6 @@ const electronLocalshortcut = require('electron-localshortcut');
const windowStateKeeper = require('electron-window-state');
const appMenu = require('./menu');
const { appUpdater } = require('./autoupdater');
const { crashHandler } = require('./crash-reporter');
const { setAutoLaunch } = require('./startup');
const { app, ipcMain } = electron;
@@ -127,7 +125,7 @@ function createMainWindow() {
function registerLocalShortcuts(page) {
// Somehow, reload action cannot be overwritten by the menu item
electronLocalshortcut.register(mainWindow, 'CommandOrControl+R', () => {
page.send('reload-current-viewer');
page.send('reload-viewer');
});
// Also adding these shortcuts because some users might want to use it instead of CMD/Left-Right
@@ -174,7 +172,6 @@ app.on('ready', () => {
page.once('did-frame-finish-load', () => {
// Initate auto-updates on MacOS and Windows
appUpdater();
crashHandler();
});
electron.powerMonitor.on('resume', () => {

View File

@@ -37,7 +37,7 @@ class AppMenu {
accelerator: 'CommandOrControl+R',
click(item, focusedWindow) {
if (focusedWindow) {
AppMenu.sendAction('reload-current-viewer');
AppMenu.sendAction('reload-viewer');
}
}
}, {
@@ -173,7 +173,7 @@ class AppMenu {
return [{
label: `${app.getName()}`,
submenu: [{
label: 'About Zulip',
label: 'Zulip Desktop',
click(item, focusedWindow) {
if (focusedWindow) {
AppMenu.sendAction('open-about');
@@ -273,7 +273,7 @@ class AppMenu {
return [{
label: 'File',
submenu: [{
label: 'About Zulip',
label: 'Zulip Desktop',
click(item, focusedWindow) {
if (focusedWindow) {
AppMenu.sendAction('open-about');

View File

@@ -1,7 +1,7 @@
{
"name": "zulip",
"productName": "Zulip",
"version": "1.5.0",
"version": "1.4.0",
"description": "Zulip Desktop App",
"license": "Apache-2.0",
"email": "<svnitakash@gmail.com>",

View File

@@ -18,7 +18,7 @@ body {
background-position: center;
}
.toggle-sidebar {
#sidebar {
background: #222c31;
width: 54px;
padding: 27px 0 20px 0;
@@ -27,21 +27,6 @@ body {
flex-direction: column;
-webkit-app-region: drag;
overflow: hidden;
transition: all 0.5s ease;
}
.toggle-sidebar div {
transition: all 0.5s ease-out;
}
.sidebar-hide {
width: 0;
transition: all 0.8s ease;
}
.sidebar-hide div {
transform: translateX(-100%);
transition: all 0.6s ease-out;
}
@font-face {
@@ -53,8 +38,8 @@ body {
/*******************
* Left Sidebar *
*******************/
* Left Sidebar *
*******************/
#tabs-container {
display: flex;
@@ -212,8 +197,8 @@ body {
/*******************
* Webview Area *
*******************/
* Webview Area *
*******************/
#webviews-container {
display: flex;
@@ -273,33 +258,6 @@ webview:focus {
right: 68px;
}
#add-server-tooltip,
.server-tooltip {
font-family: 'arial';
background: #222c31;
left: 56px;
padding: 10px 20px;
position: fixed;
margin-top: 8px;
z-index: 5000 !important;
color: #fff;
border-radius: 4px;
text-align: center;
width: max-content;
font-size: 14px;
}
#add-server-tooltip:after,
.server-tooltip:after {
content: " ";
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
border-right: 8px solid #222c31;
position: absolute;
top: 10px;
left: -5px;
}
#collapse-button {
bottom: 30px;
left: 20px;
@@ -327,9 +285,7 @@ webview:focus {
display: none !important;
}
/* Full screen Popup container */
.popup .popuptext {
visibility: hidden;
background-color: #555;
@@ -362,4 +318,4 @@ webview:focus {
overflow: hidden;
opacity: 1;
}
}
}

View File

@@ -12,33 +12,33 @@ body {
}
kbd {
padding: 0.3em 0.8em;
padding: 0.1em 0.6em;
border: 1px solid #ccc;
font-size: 15px;
font-family: Courier New, Courier, monospace;
background-color: #383430;
color: #ededed;
font-size: 12px;
font-family: Arial,Helvetica,sans-serif;
background-color: #f7f7f7;
color: #333;
-moz-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
-webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
display: inline-block;
margin: 0 0.1em;
font-weight: bold;
text-shadow: 0 1px 0 #fff;
line-height: 1.4;
white-space: nowrap;
}
table, th, td {
border: 1px solid #ddd;
border-collapse: collapse;
color: #383430;
}
table {
width: 100%;
margin-top: 18px;
margin-bottom: 18px;
}
table tr:nth-child(even) { background-color: #f7eee6; }
table tr:nth-child(odd) { background-color: #fff8ef; }
table { width: 85%; }
table tr:nth-child(even) { background-color: #f2f2f2; }
td { padding: 5px; }
@@ -56,11 +56,6 @@ td:nth-child(odd) {
url(../fonts/MaterialIcons-Regular.ttf) format('truetype');
}
@font-face {
font-family: 'Montserrat';
src: url(../fonts/Montserrat-Regular.ttf) format('truetype');
}
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
@@ -83,7 +78,7 @@ td:nth-child(odd) {
#content {
display: flex;
height: 100%;
font-family: 'Montserrat';
font-family: sans-serif;
}
#sidebar {
@@ -121,9 +116,7 @@ td:nth-child(odd) {
#settings-header {
font-size: 22px;
color: #222c31;
font-weight: bold;
text-transform: uppercase;
color: #5c6166;
}
#settings-container {
@@ -141,8 +134,7 @@ td:nth-child(odd) {
.title {
padding: 4px 0 6px 0;
font-weight: bold;
color: #222c31;
text-transform: uppercase;
color: #1e1e1e;
}
.sub-title {
@@ -218,6 +210,7 @@ img.server-info-icon {
display: flex;
align-items: center;
padding: 0 10px;
border-radius: 2px;
margin-right: 10px;
}
@@ -249,8 +242,9 @@ img.server-info-icon {
padding: 12px 30px;
margin: 10px 0 20px 0;
background: #fff;
width: 70%;
border-left: 8px solid #bcbcbc;
border-radius: 2px;
width: 540px;
box-shadow: 1px 2px 4px #bcbcbc;
}
.hidden {
@@ -259,19 +253,15 @@ img.server-info-icon {
}
.red {
color: #ffffff;
background: #ef5350;
padding: 3px;
padding-right: 10px;
padding-left: 10px;
color: #ef5350;
background: #ffebee;
border: 1px solid #ef5350;
}
.blue {
color: #ffffff;
background: #4EBFAC;
padding: 3px;
padding-right: 10px;
padding-left: 10px;
.green {
color: #388E3C;
background: #E8F5E9;
border: 1px solid #388E3C;
}
.grey {
@@ -282,10 +272,9 @@ img.server-info-icon {
.setting-row {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
margin: 6px;
margin: 6px 0;
}
.code {
@@ -300,90 +289,26 @@ i.open-tab-button {
.reset-data-button {
display: inline-block;
border: none;
padding: 10px;
width: 120px;
cursor: pointer;
font-size: 13px;
font-size: 11px;
transition: background-color 0.2s ease;
text-decoration: none;
}
.reset-data-button:hover {
background-color: #3c9f8d;
background-color: #32a692;
color: #fff;
}
#server-info-container {
min-height: calc(100% - 235px);
}
#create-organization-container {
font-size: 1.15em;
margin-bottom: 15px;
}
#create-organization-container i {
position: relative;
top: 3px;
}
#open-create-org-link {
color: #666;
#open-shortcuts-url {
color: #08c;
cursor: pointer;
text-decoration: none;
}
#open-create-org-link:hover {
#open-shortcuts-url:hover {
color: #005580;;
text-decoration: underline;
}
.toggle {
position: absolute;
margin-left: -9999px;
visibility: hidden;
}
.toggle + label {
display: block;
position: relative;
cursor: pointer;
outline: none;
user-select: none;
}
input.toggle-round + label {
padding: 2px;
width: 50px;
height: 25px;
background-color: #dddddd;
border-radius: 25px;
}
input.toggle-round + label:before,
input.toggle-round + label:after {
display: block;
position: absolute;
top: 2px;
left: 2px;
bottom: 2px;
content: "";
}
input.toggle-round + label:before {
right: 2px;
background-color: #f1f1f1;
border-radius: 25px;
transition: background 0.4s;
}
input.toggle-round + label:after {
width: 25px;
height: 25px;
background-color: #fff;
border-radius: 100%;
transition: margin 0.4s;
}
input.toggle-round:checked + label:before {
background-color: #4EBFAC;
}
input.toggle-round:checked + label:after {
margin-left: 25px;
}

View File

@@ -8,7 +8,6 @@ const {ipcRenderer} = require('electron');
class ServerTab extends Tab {
template() {
return `<div class="tab">
<div class="server-tooltip" style="display:none"></div>
<div class="server-tab-badge"></div>
<div class="server-tab">
<img class="server-icons" src='${this.props.icon}'/>

View File

@@ -21,8 +21,6 @@ class Tab extends BaseComponent {
registerListeners() {
this.$el.addEventListener('click', this.props.onClick);
this.$el.addEventListener('mouseover', this.props.onHover);
this.$el.addEventListener('mouseout', this.props.onHoverOut);
}
isLoading() {

View File

@@ -6,7 +6,7 @@ const fs = require('fs');
const DomainUtil = require(__dirname + '/../utils/domain-util.js');
const SystemUtil = require(__dirname + '/../utils/system-util.js');
const LinkUtil = require(__dirname + '/../utils/link-util.js');
const { shell, app } = require('electron').remote;
const {shell} = require('electron').remote;
const BaseComponent = require(__dirname + '/../components/base.js');
@@ -42,7 +42,7 @@ class WebView extends BaseComponent {
registerListeners() {
this.$el.addEventListener('new-window', event => {
const { url } = event;
const {url} = event;
const domainPrefix = DomainUtil.getDomain(this.props.index).url;
if (LinkUtil.isInternal(domainPrefix, url) || url === (domainPrefix + '/')) {
@@ -55,21 +55,11 @@ class WebView extends BaseComponent {
});
this.$el.addEventListener('page-title-updated', event => {
const { title } = event;
const {title} = event;
this.badgeCount = this.getBadgeCount(title);
this.props.onTitleChange();
});
this.$el.addEventListener('page-favicon-updated', event => {
const { favicons } = event;
// This returns a string of favicons URL. If there is a PM counts in unread messages then the URL would be like
// https://chat.zulip.org/static/images/favicon/favicon-pms.png
if (favicons[0].indexOf('favicon-pms') > 0 && process.platform === 'darwin') {
// This api is only supported on macOS
app.dock.setBadge('●');
}
});
this.$el.addEventListener('dom-ready', () => {
if (this.props.role === 'server') {
this.$el.classList.add('onload');
@@ -78,7 +68,7 @@ class WebView extends BaseComponent {
});
this.$el.addEventListener('did-fail-load', event => {
const { errorDescription } = event;
const {errorDescription} = event;
const hasConnectivityErr = (SystemUtil.connectivityERR.indexOf(errorDescription) >= 0);
if (hasConnectivityErr) {
console.error('error', errorDescription);

View File

@@ -21,11 +21,8 @@ class ServerManagerView {
this.$settingsButton = $actionsContainer.querySelector('#settings-action');
this.$webviewsContainer = document.getElementById('webviews-container');
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.$sidebar = document.getElementById('sidebar');
this.$fullscreenPopup = document.getElementById('fullscreen-popup');
@@ -78,11 +75,11 @@ class ServerManagerView {
DomainUtil.updateSavedServer(servers[i].url, i);
this.activateTab(i);
}
// Open last active tab
this.activateTab(ConfigUtil.getConfigItem('lastActiveTab'));
this.activateTab(0);
} else {
this.openSettings('Servers');
}
ipcRenderer.send('local-shortcuts', true);
}
@@ -91,10 +88,8 @@ class ServerManagerView {
role: 'server',
icon: server.icon,
$root: this.$tabsContainer,
onClick: this.activateLastTab.bind(this, index),
onClick: this.activateTab.bind(this, index),
index,
onHover: this.onHover.bind(this, index, server.alias),
onHoverOut: this.onHoverOut.bind(this, index),
webview: new WebView({
$root: this.$webviewsContainer,
index,
@@ -122,7 +117,6 @@ class ServerManagerView {
this.openSettings('General');
});
this.sidebarHoverEvent(this.$addServerButton, this.$addServerTooltip);
this.sidebarHoverEvent(this.$settingsButton, this.$settingsTooltip);
this.sidebarHoverEvent(this.$reloadButton, this.$reloadTooltip);
}
@@ -136,15 +130,6 @@ class ServerManagerView {
});
}
onHover(index, serverName) {
this.$serverIconTooltip[index].innerHTML = serverName;
this.$serverIconTooltip[index].removeAttribute('style');
}
onHoverOut(index) {
this.$serverIconTooltip[index].style.display = 'none';
}
openFunctionalTab(tabProps) {
if (this.functionalTabs[tabProps.name] !== undefined) {
this.activateTab(this.functionalTabs[tabProps.name]);
@@ -203,15 +188,8 @@ class ServerManagerView {
});
}
activateLastTab(index) {
// Open last active tab
ConfigUtil.setConfigItem('lastActiveTab', index);
// Open all the tabs in background
this.activateTab(index);
}
activateTab(index, hideOldTab = true) {
if (!this.tabs[index]) {
if (this.tabs[index].webview.loading) {
return;
}
@@ -263,21 +241,10 @@ class ServerManagerView {
}
reloadView() {
// Save and remember the index of last active tab so that we can use it later
const lastActiveTab = this.tabs[this.activeTabIndex].props.index;
ConfigUtil.setConfigItem('lastActiveTab', lastActiveTab);
// Destroy the current view and re-initiate it
this.destroyView();
this.initTabs();
}
// This will trigger when pressed CTRL/CMD + R [WIP]
// It won't reload the current view properly when you add/delete a server.
reloadCurrentView() {
this.$reloadButton.click();
}
updateBadge() {
let messageCountAll = 0;
for (let i = 0; i < this.tabs.length; i++) {
@@ -293,9 +260,9 @@ class ServerManagerView {
toggleSidebar(show) {
if (show) {
this.$sidebar.classList.remove('sidebar-hide');
this.$sidebar.classList.remove('hidden');
} else {
this.$sidebar.classList.add('sidebar-hide');
this.$sidebar.classList.add('hidden');
}
}
@@ -328,9 +295,7 @@ class ServerManagerView {
ipcRenderer.on('open-about', this.openAbout.bind(this));
ipcRenderer.on('reload-viewer', this.reloadView.bind(this, this.tabs[this.activeTabIndex].props.index));
ipcRenderer.on('reload-current-viewer', this.reloadCurrentView.bind(this));
ipcRenderer.on('reload-viewer', this.reloadView.bind(this));
ipcRenderer.on('hard-reload', () => {
ipcRenderer.send('reload-full-app');

View File

@@ -15,16 +15,10 @@ const NativeNotification = window.Notification;
class baseNotification extends NativeNotification {
constructor(title, opts) {
opts.silent = ConfigUtil.getConfigItem('silent') || false;
super(title, opts);
}
static requestPermission() {
return; // eslint-disable-line no-useless-return
}
// Override default Notification permission
static get permission() {
return ConfigUtil.getConfigItem('showNotification') ? 'granted' : 'denied';
// calling super without passing arguments will fail to constuct Notification
// and will result in no notification. It's a hack (not an ideal way) for deleting the window notification
ConfigUtil.getConfigItem('showNotification') ? super(title, opts) : super(); // eslint-disable-line no-unused-expressions
}
}
window.Notification = baseNotification;

View File

@@ -19,20 +19,14 @@ class BaseSection extends BaseComponent {
generateOptionTemplate(settingOption) {
if (settingOption) {
return `
<div class="action">
<div class="switch">
<input class="toggle toggle-round" type="checkbox" checked>
<label></label>
</div>
<div class="action green">
<span>On</span>
</div>
`;
} else {
return `
<div class="action">
<div class="switch">
<input class="toggle toggle-round" type="checkbox">
<label></label>
</div>
<div class="action red">
<span>Off</span>
</div>
`;
}

View File

@@ -1,37 +0,0 @@
'use strict';
const BaseComponent = require(__dirname + '/../../components/base.js');
const shell = require('electron').shell;
class CreateOrganziation extends BaseComponent {
constructor(props) {
super();
this.props = props;
}
template() {
return `
<div class="setting-row">
<div class="setting-description">
<span id="open-create-org-link">Create a new organization on zulipchat.com<i class="material-icons open-tab-button">open_in_new</i></span>
</div>
<div class="setting-control"></div>
</div>
`;
}
init() {
this.props.$root.innerHTML = this.template();
this.openCreateNewOrgExternalLink();
}
openCreateNewOrgExternalLink() {
const link = 'https://zulipchat.com/beta/';
const externalCreateNewOrgEl = document.getElementById('open-create-org-link');
externalCreateNewOrgEl.addEventListener('click', () => {
shell.openExternal(link);
});
}
}
module.exports = CreateOrganziation;

View File

@@ -25,7 +25,7 @@ class GeneralSection extends BaseSection {
<div class="setting-control"></div>
</div>
<div class="setting-row" id="sidebar-option">
<div class="setting-description">Show sidebar (<span class="code">Cmd Or Ctrl+S</span>)</div>
<div class="setting-description">Show sidebar (<span class="code">CmdOrCtrl+S</span>)</div>
<div class="setting-control"></div>
</div>
<div class="setting-row" id="badge-option">
@@ -50,6 +50,10 @@ class GeneralSection extends BaseSection {
<div class="setting-description">Get beta updates</div>
<div class="setting-control"></div>
</div>
<div class="setting-row" id="autoupdate-option">
<div class="setting-description">Automatically install new updates</div>
<div class="setting-control"></div>
</div>
</div>
<div class="title">Functionality</div>
<div class="settings-card">
@@ -63,7 +67,7 @@ class GeneralSection extends BaseSection {
<div class="setting-row" id="resetdata-option">
<div class="setting-description">This will delete all application data including all added accounts and preferences
</div>
<button class="reset-data-button blue">Reset App Data</button>
<button class="reset-data-button green">Reset App Data</button>
</div>
</div>
</div>
@@ -75,6 +79,7 @@ class GeneralSection extends BaseSection {
this.updateTrayOption();
this.updateBadgeOption();
this.updateUpdateOption();
this.updateAutoUpdateOption();
this.updateSilentOption();
this.updateSidebarOption();
this.updateStartAtLoginOption();
@@ -120,6 +125,18 @@ class GeneralSection extends BaseSection {
});
}
updateAutoUpdateOption() {
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.updateAutoUpdateOption();
}
});
}
updateSilentOption() {
this.generateSettingOption({
$element: document.querySelector('#silent-option .setting-control'),

View File

@@ -34,7 +34,7 @@ class NetworkSection extends BaseSection {
<input class="setting-input-value" placeholder="e.g. foobar.com"/>
</div>
<div class="setting-row">
<div class="action blue" id="proxy-save-action">
<div class="action green" id="proxy-save-action">
<i class="material-icons">check_box</i>
<span>Save</span>
</div>

View File

@@ -14,12 +14,12 @@ class NewServerForm extends BaseComponent {
<div class="settings-card">
<div class="server-info-right">
<div class="server-info-row">
<input class="setting-input-value" autofocus placeholder="Enter the URL of your Zulip organization..."/>
<input class="setting-input-value" autofocus placeholder="Entert the URL of your Zulip organization..."/>
</div>
<div class="server-info-row">
<div class="action blue server-save-action">
<div class="action green server-save-action">
<i class="material-icons">check_box</i>
<span>Add</span>
<span>Save</span>
</div>
</div>
</div>

View File

@@ -4,7 +4,6 @@ const BaseSection = require(__dirname + '/base-section.js');
const DomainUtil = require(__dirname + '/../../utils/domain-util.js');
const ServerInfoForm = require(__dirname + '/server-info-form.js');
const NewServerForm = require(__dirname + '/new-server-form.js');
const CreateOrganziation = require(__dirname + '/create-new-org.js');
class ServersSection extends BaseSection {
constructor(props) {
@@ -19,7 +18,6 @@ class ServersSection extends BaseSection {
<div id="new-server-container"></div>
<div class="title" id="existing-servers"></div>
<div id="server-info-container"></div>
<div id="create-organization-container"></div>
</div>
`;
}
@@ -43,9 +41,6 @@ class ServersSection extends BaseSection {
this.$existingServers.innerHTML = servers.length === 0 ? '' : 'Existing Servers';
this.initNewServerForm();
this.$createOrganizationContainer = document.getElementById('create-organization-container');
this.initCreateNewOrganization();
for (let i = 0; i < servers.length; i++) {
new ServerInfoForm({
$root: this.$serverInfoContainer,
@@ -56,12 +51,6 @@ class ServersSection extends BaseSection {
}
}
initCreateNewOrganization() {
new CreateOrganziation({
$root: this.$createOrganizationContainer
}).init();
}
initNewServerForm() {
new NewServerForm({
$root: this.$newServerContainer,

View File

@@ -166,9 +166,7 @@ class DomainUtil {
const data = JSON.parse(response.body);
if (data.hasOwnProperty('realm_icon') && data.realm_icon) {
resolve({
// Some Zulip Servers use absolute URL for server icon whereas others use relative URL
// Following check handles both the cases
icon: data.realm_icon.startsWith('/') ? data.realm_uri + data.realm_icon : data.realm_icon,
icon: data.realm_uri + data.realm_icon,
url: data.realm_uri,
alias: data.realm_name
});

View File

@@ -13,14 +13,13 @@
<div class="popup">
<span class="popuptext hidden" id="fullscreen-popup"></span>
</div>
<div id="sidebar" class="toggle-sidebar">
<div id="sidebar">
<div id="view-controls-container">
<div id="tabs-container"></div>
<div id="add-tab" class="tab functional-tab">
<div class="server-tab" id="add-action">
<i class="material-icons">add</i>
</div>
<span id="add-server-tooltip" style="display:none">Add organization</span>
</div>
</div>
<div id="actions-container">

View File

@@ -1,7 +1,7 @@
{
"name": "zulip",
"productName": "Zulip",
"version": "1.5.0",
"version": "1.4.0",
"main": "./app/main",
"description": "Zulip Desktop App",
"license": "Apache-2.0",
@@ -20,7 +20,6 @@
},
"scripts": {
"start": "electron app --disable-http-cache",
"reinstall": "rm -rf node_modules; rm -rf app/node_modules; npm install",
"postinstall": "electron-builder install-app-deps",
"test": "xo",
"dev": "gulp dev",
@@ -106,8 +105,8 @@
"devDependencies": {
"assert": "1.4.1",
"devtron": "1.4.0",
"electron-builder": "19.29.1",
"electron": "1.6.14",
"electron-builder": "19.27.3",
"electron": "1.6.11",
"electron-connect": "0.6.2",
"gulp": "3.9.1",
"gulp-mocha": "4.3.1",
@@ -156,4 +155,4 @@
"mocha"
]
}
}
}