Compare commits

..

64 Commits

Author SHA1 Message Date
akashnimare
3b6c5ae532 🎉 v1.5.0 2017-10-11 12:47:17 +05:30
akashnimare
40e3ed0f2f Reload current view properly [WIP] 2017-10-10 16:35:43 +05:30
Akash Nimare
5d988858b0 Merge pull request #313 from YJDave/tooltip
Add tooltip for add server button
2017-10-10 15:40:24 +05:30
YJDave
3a974136a3 Tooltip for add organization icon 2017-10-07 14:08:26 +05:30
akashnimare
6ed5a5309c Load correct Active tab
We need to deactivate the tab if it doesn't match with previously loaded active tab.
2017-10-06 02:59:16 +05:30
akashnimare
80c37fabb8 Enable badge api on macOS only
app.dock.setBadge() is supported on macOS only. Added an extra check so that it doesn't throw errors on Win + Linux.
2017-10-05 05:34:16 +05:30
akashnimare
79366e19df Remove unnecessary logging 2017-10-05 05:28:26 +05:30
akashnimare
f409bb0449 Handle reload event correctly
Added the functionality to remember the last active tab. Previously, we used to load the first tab no matter what.
Also, when user adds a new server the same server will be activated.
Reloading the app will now reload the current view/server only.

Fixes #311, #308
2017-10-05 05:21:34 +05:30
akashnimare
45bdde951f Add a red circle over dock icon for PMs
This will show a small red circle over the dock icon.
This is to notify user that they have PMs in unread messages.
2017-10-03 03:29:52 +05:30
akashnimare
6b627780f0 Fetch correct organization icon from server_settings API
Some Zulip Servers use absolute URL for server icon whereas others use relative URL.
I have added an extra check to handle both the cases. Improves #308.
2017-10-03 00:11:41 +05:30
akashnimare
6f67553da5 update electron to v1.6.14 2017-10-02 22:01:28 +05:30
Akash Nimare
2e710a9322 Merge pull request #309 from zulip/org-server-icon
Show server-info on hovering the server-icons
2017-10-01 03:29:29 +05:30
akashnimare
91f3afa8fe Show server-info on hovering the server-icons 2017-10-01 02:51:50 +05:30
akashnimare
f784345495 Fix sidebar tooltip
This commit fixes an issue which was caused by the recent changes in left-sidebar styling.
Due to transform property the tooltip of action-buttons (reload, setting) was hidden on hover.
2017-10-01 02:06:08 +05:30
akashnimare
67da435154 Fix a typo in base notification 2017-09-30 03:34:19 +05:30
akashnimare
c89733610d Fix desktop notification control setting
This commit fixes a bug which was caused by calling the notification constructor without the args (title, opts etc).
2017-09-30 03:26:59 +05:30
akashnimare
8f272a67b5 Update desktop app installation link 2017-09-29 17:37:36 +05:30
Akash Nimare
f6c4a76138 Merge pull request #307 from aklap/change-menu-label
Rename menu label Zulip Desktop as About Zulip.
2017-09-27 18:01:22 +05:30
Alexis La Porte
b90a4c5254 Rename menu label Zulip Desktop as About Zulip.
This fix changes the menu label 'Zulip Desktop' to 'About Zulip' for clarity, ('About' is more descriptive of the content in the view associated with the label). Also to have the menu conform to convention regarding naming menu labels for Mac OS applications.

Fixes #306
2017-09-27 03:41:10 -04:00
akashnimare
a06e09e565 update electron-builder to v19.29.1 2017-09-22 15:28:33 +05:30
akashnimare
ad5bef821e UI: Remove sidebar fluctuation on switching the toggle button
Fixes #301
2017-09-21 00:48:08 +05:30
Akash Nimare
58bbd7bf30 Merge pull request #302 from zulip/revert-301-ui_enchancements
Revert "Removed the sidebar fluctuation on switching the toggle button"
2017-09-20 23:18:59 +05:30
Akash Nimare
90d080dc96 Revert "Removed the sidebar fluctuation on switching the toggle button" 2017-09-20 23:18:35 +05:30
Akash Nimare
ad3fcf585e Merge pull request #301 from Shipragupta14/ui_enchancements
Removed the sidebar fluctuation on switching the toggle button
2017-09-20 02:31:53 +05:30
Shipragupta14
4b8f216bab Removed the sidebar fluctuation on switching the toggle button 2017-09-20 02:03:39 +05:30
Akash Nimare
e620e0c428 Merge pull request #294 from ihsavru/master
Improve UI/UX of setting page
2017-09-19 17:11:18 +05:30
ihsavru
50b3151b5d corrected typos 2017-09-19 15:52:03 +05:30
ihsavru
0c32756485 changed button and switch colour 2017-09-19 10:44:39 +05:30
ihsavru
0c0835e364 changed shortcuts UI 2017-09-17 23:31:53 +05:30
ihsavru
9e962a5c44 improved toggle switches 2017-09-17 11:54:40 +05:30
ihsavru
a218f7ea64 change toggle buttons 2017-09-17 10:45:09 +05:30
ihsavru
13a7f7475a added toggle switches 2017-09-16 19:09:12 +05:30
ihsavru
48b17a1549 made settings page responsive 2017-09-16 17:39:07 +05:30
akashnimare
653598fd9e add a re-install script 2017-09-16 01:54:55 +05:30
Akash Nimare
ddbc282f49 Merge pull request #297 from cedricium/create-new-org
Added 'Create New Organization' link to the Settings page
2017-09-15 21:17:15 +05:30
Cedricium
992d92b06d Changes made based on review
Removed unnecessary comments and changed the 'Save' button in `new-server-form.js`
to 'Add'.
2017-09-15 08:19:39 -07:00
Cedricium
45867ef15e Made changes based on @rishig recommendations
Changes include:

- increasing the font size of the 'Create new organization' link
- adding more bottom margin to the link
- aligning the link text with the external navigation icon
2017-09-14 20:49:40 -07:00
Cedricium
6572c90d49 'Create New Organization' added to Settings page
This fixes #281, which will allow users to open an external link in their default
browser to create a new organization on zulipchat.com.
2017-09-14 15:13:31 -07:00
akashnimare
1ed0011c88 Added crash reported fixes #295 2017-09-13 01:24:02 +05:30
Akash Nimare
6dd79b205c Merge pull request #293 from cedricium/shortcut-settings
Adding keyboard shortcuts to Settings page
2017-09-11 20:23:11 +05:30
Cedricium
538c18fa90 Shorten 'Keyboard Shortcuts' to just 'Shortcuts' 2017-09-11 07:39:19 -07:00
Cedricium
29e347c511 List application-specific shortcuts only 2017-09-10 14:07:04 -07:00
Cedricium
ad37a5e0a6 Changed 'Ctrl/Cmd' to appropriate user OS key
If Windows or Linux, variable `userOSKey` will be 'Ctrl'. For Macs, `userOSKey`
will be '⌘' and these values will show up in place of the previous 'Ctrl/Cmd' keys.
2017-09-10 00:32:06 -07:00
Cedricium
352b775e27 Added all keyboard shortcuts
Finished adding all keyboard shortcuts to the Settings page. Styled the tables
such that they are uniform with their columns being the same
width.

At the bottom of the 'Keyboard Shortcuts' settings page, a link to the
complete keyboard shortcuts documentation
(https://chat.zulip.org/help/keyboard-shortcuts) was also added.
2017-09-09 22:39:34 -07:00
Cedricium
38cec25680 Adding keyboard shortcuts in Settings
This is the initial pass at adding keyboard shortcuts to the Settings page. In
this commit, the `ShortcutsSection` class has been created and is applied to a
newly-added 'Keyboard Shortcuts' nav item. The template for ShortcutsSection
is essentially multiple settings cards containing one table of keyboard short-
cuts organized by their underlying functionality.

The HTML `<kbd>` tag was defined in preference.css which styles the element to
look like a keyboard key, similar to StackOverflow or GitHub.
2017-09-09 19:11:19 -07:00
Akash Nimare
f77ab92202 Merge pull request #287 from vbNETonIce/patch-1
Windows set up instructions
2017-09-08 16:51:20 +05:30
Akash Nimare
e843a29316 Update Windows.md 2017-09-08 16:50:59 +05:30
akashnimare
85837242e7 Add back tray icon on windows #289 2017-09-08 05:17:14 +05:30
akashnimare
9f6da5712e Add show/hide desktop notification setting #192 2017-09-08 04:27:15 +05:30
akashnimare
158685a869 code refactor for mouse events 2017-09-07 22:50:20 +05:30
Akash Nimare
288b1cb3f2 Merge pull request #290 from zulip/clear-settings
Added Clear app settings menu item
2017-09-07 22:36:43 +05:30
akashnimare
e24a966d48 Add shortcut for clearing app data 2017-09-07 03:34:30 +05:30
akashnimare
306feb2eff reset window position 2017-09-07 03:29:04 +05:30
akashnimare
f426c932b0 Relaunch app on clearing app data 2017-09-06 16:23:56 +05:30
Akash Nimare
26172d8508 Merge pull request #288 from vbNETonIce/patch-2
tiny change in wording of new reset data option
2017-09-06 16:07:17 +05:30
vbNETonIce
99da0a338f tiny change in wording of new reset data option 2017-09-06 12:36:20 +02:00
akashnimare
9599249b31 Add reset app settings menu item #286 2017-09-06 15:23:22 +05:30
vbNETonIce
4bdd2564b7 Windows set up instructions 2017-09-06 08:57:13 +02:00
Akash Nimare
4dcf22a53c Merge pull request #285 from zulip/reset-data-setting
Add reset app data setting #192
2017-09-06 04:08:37 +05:30
akashnimare
0dc97648a0 code refactor 2017-09-06 03:54:25 +05:30
akashnimare
787f097cf3 style reset data button 2017-09-06 03:42:39 +05:30
akashnimare
5481d55c66 remove clear cache menu items 2017-09-06 03:26:56 +05:30
akashnimare
2a052b2c38 Added reset app data functionality [WIP] 2017-09-06 03:15:23 +05:30
akashnimare
bcabb615b4 clear app data setting option [WIP] 2017-08-29 04:26:16 +05:30
27 changed files with 853 additions and 87 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](./how-to-install.md).
Please see [installation guide](https://zulipchat.com/help/desktop-app-install-guide).
# Features
* Sign in to multiple teams

View File

@@ -0,0 +1,16 @@
'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,6 +5,8 @@ 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;
@@ -49,6 +51,10 @@ function createMainWindow() {
defaultWidth: 1000,
defaultHeight: 600
});
// Let's keep the window position global so that we can access it in other process
global.mainWindowState = mainWindowState;
const win = new electron.BrowserWindow({
// This settings needs to be saved in config
title: 'Zulip',
@@ -121,7 +127,7 @@ function createMainWindow() {
function registerLocalShortcuts(page) {
// Somehow, reload action cannot be overwritten by the menu item
electronLocalshortcut.register(mainWindow, 'CommandOrControl+R', () => {
page.send('reload-viewer');
page.send('reload-current-viewer');
});
// Also adding these shortcuts because some users might want to use it instead of CMD/Left-Right
@@ -168,6 +174,7 @@ app.on('ready', () => {
page.once('did-frame-finish-load', () => {
// Initate auto-updates on MacOS and Windows
appUpdater();
crashHandler();
});
electron.powerMonitor.on('resume', () => {
@@ -188,6 +195,12 @@ app.on('ready', () => {
page.send('destroytray');
});
ipcMain.on('clear-app-settings', () => {
global.mainWindowState.unmanage(mainWindow);
app.relaunch();
app.exit();
});
ipcMain.on('toggle-app', () => {
if (mainWindow.isVisible()) {
mainWindow.hide();

View File

@@ -1,6 +1,10 @@
'use strict';
const os = require('os');
const {dialog, app, shell, BrowserWindow, Menu} = require('electron');
const path = require('path');
const { app, shell, BrowserWindow, Menu } = require('electron');
const fs = require('fs-extra');
const ConfigUtil = require(__dirname + '/../renderer/js/utils/config-util.js');
@@ -33,7 +37,7 @@ class AppMenu {
accelerator: 'CommandOrControl+R',
click(item, focusedWindow) {
if (focusedWindow) {
AppMenu.sendAction('reload-viewer');
AppMenu.sendAction('reload-current-viewer');
}
}
}, {
@@ -164,12 +168,12 @@ class AppMenu {
}
getDarwinTpl(props) {
const {tabs, activeTabIndex} = props;
const { tabs, activeTabIndex } = props;
return [{
label: `${app.getName()}`,
submenu: [{
label: 'Zulip Desktop',
label: 'About Zulip',
click(item, focusedWindow) {
if (focusedWindow) {
AppMenu.sendAction('open-about');
@@ -196,9 +200,10 @@ class AppMenu {
}, {
type: 'separator'
}, {
label: 'Clear Cache',
label: 'Reset App Settings',
accelerator: 'Command+Shift+D',
click() {
AppMenu.clearCache();
AppMenu.resetAppSettings();
}
}, {
label: 'Log Out',
@@ -263,12 +268,12 @@ class AppMenu {
}
getOtherTpl(props) {
const {tabs, activeTabIndex} = props;
const { tabs, activeTabIndex } = props;
return [{
label: 'File',
submenu: [{
label: 'Zulip Desktop',
label: 'About Zulip',
click(item, focusedWindow) {
if (focusedWindow) {
AppMenu.sendAction('open-about');
@@ -297,9 +302,10 @@ class AppMenu {
}, {
type: 'separator'
}, {
label: 'Clear Cache',
label: 'Reset App Settings',
accelerator: 'Ctrl+Shift+D',
click() {
AppMenu.clearCache();
AppMenu.resetAppSettings();
}
}, {
label: 'Log Out',
@@ -363,11 +369,11 @@ class AppMenu {
win.webContents.send(action, ...params);
}
static clearCache() {
const win = BrowserWindow.getAllWindows()[0];
const ses = win.webContents.session;
ses.clearCache(() => {
dialog.showMessageBox({type: 'info', buttons: [], message: 'Cache cleared!'});
static resetAppSettings() {
const getAppPath = path.join(app.getPath('appData'), appName, 'window-state.json');
fs.unlink(getAppPath, () => {
setTimeout(() => AppMenu.sendAction('clear-app-data'), 1000);
});
}

View File

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

View File

@@ -18,7 +18,7 @@ body {
background-position: center;
}
#sidebar {
.toggle-sidebar {
background: #222c31;
width: 54px;
padding: 27px 0 20px 0;
@@ -27,6 +27,21 @@ 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 {
@@ -38,8 +53,8 @@ body {
/*******************
* Left Sidebar *
*******************/
* Left Sidebar *
*******************/
#tabs-container {
display: flex;
@@ -197,8 +212,8 @@ body {
/*******************
* Webview Area *
*******************/
* Webview Area *
*******************/
#webviews-container {
display: flex;
@@ -258,6 +273,33 @@ 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;
@@ -285,7 +327,9 @@ webview:focus {
display: none !important;
}
/* Full screen Popup container */
.popup .popuptext {
visibility: hidden;
background-color: #555;
@@ -318,4 +362,4 @@ webview:focus {
overflow: hidden;
opacity: 1;
}
}
}

View File

@@ -4,11 +4,49 @@ body {
margin: 0;
cursor: default;
user-select: none;
font-family: menu, "Helvetica Neue", sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 14px;
color: #333;
background: #efefef;
}
kbd {
padding: 0.3em 0.8em;
border: 1px solid #ccc;
font-size: 15px;
font-family: Courier New, Courier, monospace;
background-color: #383430;
color: #ededed;
display: inline-block;
margin: 0 0.1em;
font-weight: bold;
white-space: nowrap;
}
table, th, td {
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; }
td { padding: 5px; }
td:nth-child(odd) {
text-align: right;
width: 50%;
}
@font-face {
font-family: 'Material Icons';
font-style: normal;
@@ -18,6 +56,11 @@ body {
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;
@@ -40,7 +83,7 @@ body {
#content {
display: flex;
height: 100%;
font-family: sans-serif;
font-family: 'Montserrat';
}
#sidebar {
@@ -78,7 +121,9 @@ body {
#settings-header {
font-size: 22px;
color: #5c6166;
color: #222c31;
font-weight: bold;
text-transform: uppercase;
}
#settings-container {
@@ -96,7 +141,8 @@ body {
.title {
padding: 4px 0 6px 0;
font-weight: bold;
color: #1e1e1e;
color: #222c31;
text-transform: uppercase;
}
.sub-title {
@@ -172,7 +218,6 @@ img.server-info-icon {
display: flex;
align-items: center;
padding: 0 10px;
border-radius: 2px;
margin-right: 10px;
}
@@ -204,9 +249,8 @@ img.server-info-icon {
padding: 12px 30px;
margin: 10px 0 20px 0;
background: #fff;
border-radius: 2px;
width: 540px;
box-shadow: 1px 2px 4px #bcbcbc;
width: 70%;
border-left: 8px solid #bcbcbc;
}
.hidden {
@@ -215,15 +259,19 @@ img.server-info-icon {
}
.red {
color: #ef5350;
background: #ffebee;
border: 1px solid #ef5350;
color: #ffffff;
background: #ef5350;
padding: 3px;
padding-right: 10px;
padding-left: 10px;
}
.green {
color: #388E3C;
background: #E8F5E9;
border: 1px solid #388E3C;
.blue {
color: #ffffff;
background: #4EBFAC;
padding: 3px;
padding-right: 10px;
padding-left: 10px;
}
.grey {
@@ -234,9 +282,10 @@ img.server-info-icon {
.setting-row {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
margin: 6px 0;
margin: 6px;
}
.code {
@@ -247,4 +296,94 @@ i.open-tab-button {
padding: 0 5px;
font-size: 18px;
cursor: pointer;
}
.reset-data-button {
display: inline-block;
border: none;
padding: 10px;
width: 120px;
cursor: pointer;
font-size: 13px;
transition: background-color 0.2s ease;
text-decoration: none;
}
.reset-data-button:hover {
background-color: #3c9f8d;
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;
cursor: pointer;
text-decoration: none;
}
#open-create-org-link: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;
}

Binary file not shown.

View File

@@ -8,6 +8,7 @@ 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,6 +21,8 @@ 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} = require('electron').remote;
const { shell, app } = 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,11 +55,21 @@ 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');
@@ -68,7 +78,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

@@ -1,9 +1,9 @@
'use strict';
require(__dirname + '/js/tray.js');
const {ipcRenderer, remote} = require('electron');
const { ipcRenderer, remote } = require('electron');
const {session} = remote;
const { session } = remote;
const DomainUtil = require(__dirname + '/js/utils/domain-util.js');
const WebView = require(__dirname + '/js/components/webview.js');
@@ -21,8 +21,11 @@ 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');
@@ -75,11 +78,11 @@ class ServerManagerView {
DomainUtil.updateSavedServer(servers[i].url, i);
this.activateTab(i);
}
this.activateTab(0);
// Open last active tab
this.activateTab(ConfigUtil.getConfigItem('lastActiveTab'));
} else {
this.openSettings('Servers');
}
ipcRenderer.send('local-shortcuts', true);
}
@@ -88,8 +91,10 @@ class ServerManagerView {
role: 'server',
icon: server.icon,
$root: this.$tabsContainer,
onClick: this.activateTab.bind(this, index),
onClick: this.activateLastTab.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,
@@ -116,20 +121,30 @@ class ServerManagerView {
this.$settingsButton.addEventListener('click', () => {
this.openSettings('General');
});
this.$reloadButton.addEventListener('mouseover', () => {
this.$reloadTooltip.removeAttribute('style');
this.sidebarHoverEvent(this.$addServerButton, this.$addServerTooltip);
this.sidebarHoverEvent(this.$settingsButton, this.$settingsTooltip);
this.sidebarHoverEvent(this.$reloadButton, this.$reloadTooltip);
}
sidebarHoverEvent(SidebarButton, SidebarTooltip) {
SidebarButton.addEventListener('mouseover', () => {
SidebarTooltip.removeAttribute('style');
});
this.$reloadButton.addEventListener('mouseout', () => {
this.$reloadTooltip.style.display = 'none';
});
this.$settingsButton.addEventListener('mouseover', () => {
this.$settingsTooltip.removeAttribute('style');
});
this.$settingsButton.addEventListener('mouseout', () => {
this.$settingsTooltip.style.display = 'none';
SidebarButton.addEventListener('mouseout', () => {
SidebarTooltip.style.display = 'none';
});
}
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]);
@@ -188,8 +203,15 @@ 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].webview.loading) {
if (!this.tabs[index]) {
return;
}
@@ -241,10 +263,21 @@ 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++) {
@@ -260,9 +293,9 @@ class ServerManagerView {
toggleSidebar(show) {
if (show) {
this.$sidebar.classList.remove('hidden');
this.$sidebar.classList.remove('sidebar-hide');
} else {
this.$sidebar.classList.add('hidden');
this.$sidebar.classList.add('sidebar-hide');
}
}
@@ -295,12 +328,18 @@ class ServerManagerView {
ipcRenderer.on('open-about', this.openAbout.bind(this));
ipcRenderer.on('reload-viewer', this.reloadView.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('hard-reload', () => {
ipcRenderer.send('reload-full-app');
});
ipcRenderer.on('clear-app-data', () => {
ipcRenderer.send('clear-app-settings');
});
ipcRenderer.on('switch-server-tab', (event, index) => {
this.activateTab(index);
});

View File

@@ -1,6 +1,6 @@
'use strict';
const {remote} = require('electron');
const { remote } = require('electron');
const ConfigUtil = require(__dirname + '/utils/config-util.js');
@@ -12,11 +12,19 @@ app.setAppUserModelId('org.zulip.zulip-electron');
const NativeNotification = window.Notification;
class SilentNotification extends NativeNotification {
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';
}
}
window.Notification = SilentNotification;
window.Notification = baseNotification;

View File

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

View File

@@ -0,0 +1,37 @@
'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

@@ -1,5 +1,10 @@
'use strict';
const path = require('path');
const { ipcRenderer } = require('electron');
const { app, dialog } = require('electron').remote;
const fs = require('fs-extra');
const BaseSection = require(__dirname + '/base-section.js');
const ConfigUtil = require(__dirname + '/../../utils/config-util.js');
@@ -20,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">CmdOrCtrl+S</span>)</div>
<div class="setting-description">Show sidebar (<span class="code">Cmd Or Ctrl+S</span>)</div>
<div class="setting-control"></div>
</div>
<div class="setting-row" id="badge-option">
@@ -29,9 +34,13 @@ class GeneralSection extends BaseSection {
</div>
</div>
<div class="title">Desktop Notification</div>
<div class="settings-card">
<div class="settings-card">
<div class="setting-row" id="show-notification-option">
<div class="setting-description">Show Desktop Notifications</div>
<div class="setting-control"></div>
</div>
<div class="setting-row" id="silent-option">
<div class="setting-description">Mute all sounds from Zulip (requires reload)</div>
<div class="setting-description">Mute all sounds from Zulip</div>
<div class="setting-control"></div>
</div>
</div>
@@ -49,6 +58,14 @@ class GeneralSection extends BaseSection {
<div class="setting-control"></div>
</div>
</div>
<div class="title">Reset Application Data</div>
<div class="settings-card">
<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>
</div>
</div>
</div>
`;
}
@@ -61,6 +78,8 @@ class GeneralSection extends BaseSection {
this.updateSilentOption();
this.updateSidebarOption();
this.updateStartAtLoginOption();
this.updateResetDataOption();
this.showDesktopNotification();
}
updateTrayOption() {
@@ -113,6 +132,18 @@ class GeneralSection extends BaseSection {
});
}
showDesktopNotification() {
this.generateSettingOption({
$element: document.querySelector('#show-notification-option .setting-control'),
value: ConfigUtil.getConfigItem('showNotification', true),
clickHandler: () => {
const newValue = !ConfigUtil.getConfigItem('showNotification', true);
ConfigUtil.setConfigItem('showNotification', newValue);
this.showDesktopNotification();
}
});
}
updateSidebarOption() {
this.generateSettingOption({
$element: document.querySelector('#sidebar-option .setting-control'),
@@ -139,6 +170,31 @@ class GeneralSection extends BaseSection {
});
}
clearAppDataDialog() {
const clearAppDataMessage = 'By clicking proceed you will be removing all added accounts and preferences from Zulip. When the application restarts, it will be as if you are starting Zulip for the first time.';
const getAppPath = path.join(app.getPath('appData'), app.getName());
dialog.showMessageBox({
type: 'warning',
buttons: ['YES', 'NO'],
defaultId: 0,
message: 'Are you sure',
detail: clearAppDataMessage
}, response => {
if (response === 0) {
fs.remove(getAppPath);
setTimeout(() => ipcRenderer.send('forward-message', 'hard-reload'), 1000);
}
});
}
updateResetDataOption() {
const resetDataButton = document.querySelector('#resetdata-option .reset-data-button');
resetDataButton.addEventListener('click', () => {
this.clearAppDataDialog();
});
}
}
module.exports = GeneralSection;

View File

@@ -8,7 +8,7 @@ class PreferenceNav extends BaseComponent {
this.props = props;
this.navItems = ['General', 'Network', 'Servers'];
this.navItems = ['General', 'Network', 'Servers', 'Shortcuts'];
this.init();
}

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 green" id="proxy-save-action">
<div class="action blue" 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="Entert the URL of your Zulip organization..."/>
<input class="setting-input-value" autofocus placeholder="Enter the URL of your Zulip organization..."/>
</div>
<div class="server-info-row">
<div class="action green server-save-action">
<div class="action blue server-save-action">
<i class="material-icons">check_box</i>
<span>Save</span>
<span>Add</span>
</div>
</div>
</div>

View File

@@ -7,6 +7,7 @@ const Nav = require(__dirname + '/js/pages/preference/nav.js');
const ServersSection = require(__dirname + '/js/pages/preference/servers-section.js');
const GeneralSection = require(__dirname + '/js/pages/preference/general-section.js');
const NetworkSection = require(__dirname + '/js/pages/preference/network-section.js');
const ShortcutsSection = require(__dirname + '/js/pages/preference/shortcuts-section.js');
class PreferenceView extends BaseComponent {
constructor() {
@@ -56,6 +57,12 @@ class PreferenceView extends BaseComponent {
});
break;
}
case 'Shortcuts': {
this.section = new ShortcutsSection({
$root: this.$settingsContainer
});
break;
}
default: break;
}
this.section.init();

View File

@@ -4,6 +4,7 @@ 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) {
@@ -18,6 +19,7 @@ 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>
`;
}
@@ -41,6 +43,9 @@ 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,
@@ -51,6 +56,12 @@ class ServersSection extends BaseSection {
}
}
initCreateNewOrganization() {
new CreateOrganziation({
$root: this.$createOrganizationContainer
}).init();
}
initNewServerForm() {
new NewServerForm({
$root: this.$newServerContainer,

View File

@@ -0,0 +1,311 @@
'use strict';
const BaseSection = require(__dirname + '/base-section.js');
class ShortcutsSection extends BaseSection {
constructor(props) {
super();
this.props = props;
}
templateMac() {
const userOSKey = '⌘';
return `
<div class="settings-pane">
<div class="title">Application Shortcuts</div>
<div class="settings-card">
<table>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>,</kbd></td>
<td>Settings</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>K</kbd></td>
<td>Keyboard Shortcuts</td>
</tr>
<tr>
<td><kbd>Shift</kbd><kbd>${userOSKey}</kbd><kbd>D</kbd></td>
<td>Reset App Settings</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>L</kbd></td>
<td>Log Out</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>H</kbd></td>
<td>Hide Zulip</td>
</tr>
<tr>
<td><kbd>Option</kbd><kbd>${userOSKey}</kbd><kbd>H</kbd></td>
<td>Hide Others</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>Q</kbd></td>
<td>Quit Zulip</td>
</tr>
</table>
<div class="setting-control"></div>
</div>
<div class="title">Edit Shortcuts</div>
<div class="settings-card">
<table>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>Z</kbd></td>
<td>Undo</td>
</tr>
<tr>
<td><kbd>Shift</kbd><kbd>${userOSKey}</kbd><kbd>Z</kbd></td>
<td>Redo</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>X</kbd></td>
<td>Cut</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>C</kbd></td>
<td>Copy</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>V</kbd></td>
<td>Paste</td>
</tr>
<tr>
<td><kbd>Shift</kbd><kbd>${userOSKey}</kbd><kbd>V</kbd></td>
<td>Paste and Match Style</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>A</kbd></td>
<td>Select All</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>F</kbd></td>
<td>Find</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>G</kbd></td>
<td>Find Next</td>
</tr>
<tr>
<td><kbd>Control</kbd><kbd>${userOSKey}</kbd><kbd>Space</kbd></td>
<td>Emoji & Symbols</td>
</tr>
</table>
<div class="setting-control"></div>
</div>
<div class="title">View Shortcuts</div>
<div class="settings-card">
<table>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>R</kbd></td>
<td>Reload</td>
</tr>
<tr>
<td><kbd>Shift</kbd><kbd>${userOSKey}</kbd><kbd>R</kbd></td>
<td>Hard Reload</td>
</tr>
<tr>
<td><kbd>Control</kbd><kbd>${userOSKey}</kbd><kbd>F</kbd></td>
<td>Enter Full Screen</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>=</kbd></td>
<td>Zoom In</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>-</kbd></td>
<td>Zoom Out</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>0</kbd></td>
<td>Actual Size</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>S</kbd></td>
<td>Toggle Sidebar</td>
</tr>
<tr>
<td><kbd>Option</kbd><kbd>${userOSKey}</kbd><kbd>I</kbd></td>
<td>Toggle DevTools for Zulip App</td>
</tr>
<tr>
<td><kbd>Option</kbd><kbd>${userOSKey}</kbd><kbd>U</kbd></td>
<td>Toggle DevTools for Active Tab</td>
</tr>
</table>
<div class="setting-control"></div>
</div>
<div class="title">History Shortcuts</div>
<div class="settings-card">
<table>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>←</kbd></td>
<td>Back</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>→</kbd></td>
<td>Forward</td>
</tr>
</table>
<div class="setting-control"></div>
</div>
<div class="title">Window Shortcuts</div>
<div class="settings-card">
<table>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>M</kbd></td>
<td>Minimize</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd><kbd>W</kbd></td>
<td>Close</td>
</tr>
</table>
<div class="setting-control"></div>
</div>
</div>
`;
}
templateWinLin() {
const userOSKey = 'Ctrl';
return `
<div class="settings-pane">
<div class="title">Application Shortcuts</div>
<div class="settings-card">
<table>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>,</kbd></td>
<td>Settings</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>K</kbd></td>
<td>Keyboard Shortcuts</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>L</kbd></td>
<td>Log Out</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>Q</kbd></td>
<td>Quit Zulip</td>
</tr>
</table>
<div class="setting-control"></div>
</div>
<div class="title">Edit Shortcuts</div>
<div class="settings-card">
<table>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>Z</kbd></td>
<td>Undo</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>Y</kbd></td>
<td>Redo</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>X</kbd></td>
<td>Cut</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>C</kbd></td>
<td>Copy</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>V</kbd></td>
<td>Paste</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>V</kbd></td>
<td>Paste and Match Style</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>A</kbd></td>
<td>Select All</td>
</tr>
</table>
<div class="setting-control"></div>
</div>
<div class="title">View Shortcuts</div>
<div class="settings-card">
<table>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>R</kbd></td>
<td>Reload</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>R</kbd></td>
<td>Hard Reload</td>
</tr>
<tr>
<td><kbd>F11</kbd></td>
<td>Toggle Full Screen</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>=</kbd></td>
<td>Zoom In</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>-</kbd></td>
<td>Zoom Out</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>0</kbd></td>
<td>Actual Size</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>S</kbd></td>
<td>Toggle Sidebar</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>I</kbd></td>
<td>Toggle DevTools for Zulip App</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>U</kbd></td>
<td>Toggle DevTools for Active Tab</td>
</tr>
</table>
<div class="setting-control"></div>
</div>
<div class="title">History Shortcuts</div>
<div class="settings-card">
<table>
<tr>
<td><kbd>Alt</kbd> + <kbd>←</kbd></td>
<td>Back</td>
</tr>
<tr>
<td><kbd>Alt</kbd> + <kbd>→</kbd></td>
<td>Forward</td>
</tr>
</table>
<div class="setting-control"></div>
</div>
<div class="title">Window Shortcuts</div>
<div class="settings-card">
<table>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>M</kbd></td>
<td>Minimize</td>
</tr>
<tr>
<td><kbd>${userOSKey}</kbd> + <kbd>W</kbd></td>
<td>Close</td>
</tr>
</table>
<div class="setting-control"></div>
</div>
</div>
`;
}
init() {
this.props.$root.innerHTML = (process.platform === 'darwin') ?
this.templateMac() : this.templateWinLin();
}
}
module.exports = ShortcutsSection;

View File

@@ -180,11 +180,10 @@ ipcRenderer.on('tray', (event, arg) => {
if (!window.tray) {
return;
}
// We don't want to create tray from unread messages on windows and macOS since these systems already have dock badges and taskbar overlay icon.
if (process.platform === 'linux') {
// We don't want to create tray from unread messages on macOS since it already has dock badges.
if (process.platform === 'linux' || process.platform === 'win32') {
if (arg === 0) {
unread = arg;
// Message Count // console.log("message count is zero.");
window.tray.setImage(iconPath());
window.tray.setToolTip('No unread messages');
} else {
@@ -206,7 +205,7 @@ function toggleTray() {
ConfigUtil.setConfigItem('trayIcon', false);
} else {
createTray();
if (process.platform === 'linux') {
if (process.platform === 'linux' || process.platform === 'win32') {
renderNativeImage(unread).then(image => {
window.tray.setImage(image);
window.tray.setToolTip(unread + ' unread messages');

View File

@@ -166,7 +166,9 @@ class DomainUtil {
const data = JSON.parse(response.body);
if (data.hasOwnProperty('realm_icon') && data.realm_icon) {
resolve({
icon: data.realm_uri + data.realm_icon,
// 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,
url: data.realm_uri,
alias: data.realm_name
});

View File

@@ -13,13 +13,14 @@
<div class="popup">
<span class="popuptext hidden" id="fullscreen-popup"></span>
</div>
<div id="sidebar">
<div id="sidebar" class="toggle-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 +1,58 @@
** Windows Set up instructions **
## Prerequisites
* [Git](http://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
* [Node.js](https://nodejs.org) >= v6.9.0
* [python](https://www.python.org/downloads/release/python-2713/) (v2.7.x recommended)
* [node-gyp](https://github.com/nodejs/node-gyp#installation) (installed via powershell)
## System specific dependencies
* use only 32bit or 64bit for all of the installers, do not mix architectures
* install using default settings
* open Windows Powershell as Admin
```powershell
C:\Windows\system32> npm install --global --production windows-build-tools
```
## Installation
Clone the source locally:
```sh
$ git clone https://github.com/zulip/zulip-electron
$ cd zulip-electron
```
Install project dependencies:
```sh
$ npm install
```
Start the app:
```sh
$ npm start
```
Start and watch changes
```sh
$ npm run dev
```
### Making a release
To package app into an installer use command:
```
npm run pack
npm run dist
```
It will start the packaging process. The ready for distribution file (e.g. dmg, windows installer, deb package) will be outputted to the `dist` directory.
# Troubleshooting
If you have any problems running the app please see the [most common issues](./troubleshooting.md).

View File

@@ -1,7 +1,7 @@
{
"name": "zulip",
"productName": "Zulip",
"version": "1.4.0",
"version": "1.5.0",
"main": "./app/main",
"description": "Zulip Desktop App",
"license": "Apache-2.0",
@@ -20,6 +20,7 @@
},
"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",
@@ -105,8 +106,8 @@
"devDependencies": {
"assert": "1.4.1",
"devtron": "1.4.0",
"electron-builder": "19.27.3",
"electron": "1.6.11",
"electron-builder": "19.29.1",
"electron": "1.6.14",
"electron-connect": "0.6.2",
"gulp": "3.9.1",
"gulp-mocha": "4.3.1",
@@ -155,4 +156,4 @@
"mocha"
]
}
}
}