mirror of
				https://github.com/zulip/zulip-desktop.git
				synced 2025-11-04 05:53:21 +00:00 
			
		
		
		
	Compare commits
	
		
			67 Commits
		
	
	
		
			disable-au
			...
			v1.6.0-bet
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					dcd2abca6e | ||
| 
						 | 
					2fb9efb981 | ||
| 
						 | 
					7245b6a110 | ||
| 
						 | 
					bcb8ffb55f | ||
| 
						 | 
					77094596a5 | ||
| 
						 | 
					06ad44bdd7 | ||
| 
						 | 
					e719ba139c | ||
| 
						 | 
					9853e9226c | ||
| 
						 | 
					f2c76b5ca3 | ||
| 
						 | 
					e6dbff995b | ||
| 
						 | 
					4578d4a5f7 | ||
| 
						 | 
					4b895a2312 | ||
| 
						 | 
					53c0428a3a | ||
| 
						 | 
					0a1866abb5 | ||
| 
						 | 
					ce862a4890 | ||
| 
						 | 
					1b1ad2cd61 | ||
| 
						 | 
					ead7a06308 | ||
| 
						 | 
					6659dd5097 | ||
| 
						 | 
					ed1f0f6d5b | ||
| 
						 | 
					79acf8a6e1 | ||
| 
						 | 
					8e0033f03e | ||
| 
						 | 
					9144c2630d | ||
| 
						 | 
					fae05fc3b1 | ||
| 
						 | 
					73603a4fd2 | ||
| 
						 | 
					a498ffc7d6 | ||
| 
						 | 
					7afcf13401 | ||
| 
						 | 
					89a292559d | ||
| 
						 | 
					be14517caf | ||
| 
						 | 
					3b6c5ae532 | ||
| 
						 | 
					40e3ed0f2f | ||
| 
						 | 
					5d988858b0 | ||
| 
						 | 
					3a974136a3 | ||
| 
						 | 
					6ed5a5309c | ||
| 
						 | 
					80c37fabb8 | ||
| 
						 | 
					79366e19df | ||
| 
						 | 
					f409bb0449 | ||
| 
						 | 
					45bdde951f | ||
| 
						 | 
					6b627780f0 | ||
| 
						 | 
					6f67553da5 | ||
| 
						 | 
					2e710a9322 | ||
| 
						 | 
					91f3afa8fe | ||
| 
						 | 
					f784345495 | ||
| 
						 | 
					67da435154 | ||
| 
						 | 
					c89733610d | ||
| 
						 | 
					8f272a67b5 | ||
| 
						 | 
					f6c4a76138 | ||
| 
						 | 
					b90a4c5254 | ||
| 
						 | 
					a06e09e565 | ||
| 
						 | 
					ad5bef821e | ||
| 
						 | 
					58bbd7bf30 | ||
| 
						 | 
					90d080dc96 | ||
| 
						 | 
					ad3fcf585e | ||
| 
						 | 
					4b8f216bab | ||
| 
						 | 
					e620e0c428 | ||
| 
						 | 
					50b3151b5d | ||
| 
						 | 
					0c32756485 | ||
| 
						 | 
					0c0835e364 | ||
| 
						 | 
					9e962a5c44 | ||
| 
						 | 
					a218f7ea64 | ||
| 
						 | 
					13a7f7475a | ||
| 
						 | 
					48b17a1549 | ||
| 
						 | 
					653598fd9e | ||
| 
						 | 
					ddbc282f49 | ||
| 
						 | 
					992d92b06d | ||
| 
						 | 
					45867ef15e | ||
| 
						 | 
					6572c90d49 | ||
| 
						 | 
					1ed0011c88 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -24,3 +24,5 @@ yarn-error.log*
 | 
				
			|||||||
# miscellaneous
 | 
					# miscellaneous
 | 
				
			||||||
.idea
 | 
					.idea
 | 
				
			||||||
config.gypi
 | 
					config.gypi
 | 
				
			||||||
 | 
					.python-version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
2.7.9
 | 
					 | 
				
			||||||
@@ -8,7 +8,7 @@ Desktop client for Zulip. Available for Mac, Linux and Windows.
 | 
				
			|||||||
<img src="http://i.imgur.com/ChzTq4F.png"/>
 | 
					<img src="http://i.imgur.com/ChzTq4F.png"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Download
 | 
					# Download
 | 
				
			||||||
Please see [installation guide](./how-to-install.md).
 | 
					Please see [installation guide](https://zulipchat.com/help/desktop-app-install-guide).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Features
 | 
					# Features
 | 
				
			||||||
* Sign in to multiple teams
 | 
					* Sign in to multiple teams
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,9 +7,8 @@ const isDev = require('electron-is-dev');
 | 
				
			|||||||
const ConfigUtil = require('./../renderer/js/utils/config-util.js');
 | 
					const ConfigUtil = require('./../renderer/js/utils/config-util.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function appUpdater() {
 | 
					function appUpdater() {
 | 
				
			||||||
	// Don't initiate auto-updates in development and on Linux system
 | 
						// Don't initiate auto-updates in development
 | 
				
			||||||
	// since autoUpdater doesn't work on Linux
 | 
						if (isDev) {
 | 
				
			||||||
	if (isDev || process.platform === 'linux') {
 | 
					 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								app/main/crash-reporter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/main/crash-reporter.js
									
									
									
									
									
										Normal 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
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,10 +1,12 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
const path = require('path');
 | 
					const path = require('path');
 | 
				
			||||||
const electron = require('electron');
 | 
					const electron = require('electron');
 | 
				
			||||||
const electronLocalshortcut = require('electron-localshortcut');
 | 
					 | 
				
			||||||
const windowStateKeeper = require('electron-window-state');
 | 
					const windowStateKeeper = require('electron-window-state');
 | 
				
			||||||
 | 
					const isDev = require('electron-is-dev');
 | 
				
			||||||
const appMenu = require('./menu');
 | 
					const appMenu = require('./menu');
 | 
				
			||||||
const { appUpdater } = require('./autoupdater');
 | 
					const { appUpdater } = require('./autoupdater');
 | 
				
			||||||
 | 
					const { crashHandler } = require('./crash-reporter');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { setAutoLaunch } = require('./startup');
 | 
					const { setAutoLaunch } = require('./startup');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { app, ipcMain } = electron;
 | 
					const { app, ipcMain } = electron;
 | 
				
			||||||
@@ -12,7 +14,10 @@ const { app, ipcMain } = electron;
 | 
				
			|||||||
const BadgeSettings = require('./../renderer/js/pages/preference/badge-settings.js');
 | 
					const BadgeSettings = require('./../renderer/js/pages/preference/badge-settings.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Adds debug features like hotkeys for triggering dev tools and reload
 | 
					// Adds debug features like hotkeys for triggering dev tools and reload
 | 
				
			||||||
require('electron-debug')();
 | 
					// in development mode
 | 
				
			||||||
 | 
					if (isDev) {
 | 
				
			||||||
 | 
						require('electron-debug')();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Prevent window being garbage collected
 | 
					// Prevent window being garbage collected
 | 
				
			||||||
let mainWindow;
 | 
					let mainWindow;
 | 
				
			||||||
@@ -92,9 +97,6 @@ function createMainWindow() {
 | 
				
			|||||||
				win.hide();
 | 
									win.hide();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Unregister all the shortcuts so that they don't interfare with other apps
 | 
					 | 
				
			||||||
		electronLocalshortcut.unregisterAll(mainWindow);
 | 
					 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	win.setTitle('Zulip');
 | 
						win.setTitle('Zulip');
 | 
				
			||||||
@@ -122,33 +124,12 @@ function createMainWindow() {
 | 
				
			|||||||
	return win;
 | 
						return win;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function registerLocalShortcuts(page) {
 | 
					 | 
				
			||||||
	// Somehow, reload action cannot be overwritten by the menu item
 | 
					 | 
				
			||||||
	electronLocalshortcut.register(mainWindow, 'CommandOrControl+R', () => {
 | 
					 | 
				
			||||||
		page.send('reload-viewer');
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Also adding these shortcuts because some users might want to use it instead of CMD/Left-Right
 | 
					 | 
				
			||||||
	electronLocalshortcut.register(mainWindow, 'CommandOrControl+[', () => {
 | 
					 | 
				
			||||||
		page.send('back');
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	electronLocalshortcut.register(mainWindow, 'CommandOrControl+]', () => {
 | 
					 | 
				
			||||||
		page.send('forward');
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// eslint-disable-next-line max-params
 | 
					// eslint-disable-next-line max-params
 | 
				
			||||||
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
 | 
					app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
 | 
				
			||||||
	event.preventDefault();
 | 
						event.preventDefault();
 | 
				
			||||||
	callback(true);
 | 
						callback(true);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.on('window-all-closed', () => {
 | 
					 | 
				
			||||||
	// Unregister all the shortcuts so that they don't interfare with other apps
 | 
					 | 
				
			||||||
	electronLocalshortcut.unregisterAll(mainWindow);
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app.on('activate', () => {
 | 
					app.on('activate', () => {
 | 
				
			||||||
	if (!mainWindow) {
 | 
						if (!mainWindow) {
 | 
				
			||||||
		mainWindow = createMainWindow();
 | 
							mainWindow = createMainWindow();
 | 
				
			||||||
@@ -163,8 +144,6 @@ app.on('ready', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	const page = mainWindow.webContents;
 | 
						const page = mainWindow.webContents;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	registerLocalShortcuts(page);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	page.on('dom-ready', () => {
 | 
						page.on('dom-ready', () => {
 | 
				
			||||||
		mainWindow.show();
 | 
							mainWindow.show();
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
@@ -172,6 +151,7 @@ app.on('ready', () => {
 | 
				
			|||||||
	page.once('did-frame-finish-load', () => {
 | 
						page.once('did-frame-finish-load', () => {
 | 
				
			||||||
		// Initate auto-updates on MacOS and Windows
 | 
							// Initate auto-updates on MacOS and Windows
 | 
				
			||||||
		appUpdater();
 | 
							appUpdater();
 | 
				
			||||||
 | 
							crashHandler();
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	electron.powerMonitor.on('resume', () => {
 | 
						electron.powerMonitor.on('resume', () => {
 | 
				
			||||||
@@ -229,18 +209,8 @@ app.on('ready', () => {
 | 
				
			|||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ipcMain.on('register-server-tab-shortcut', (event, index) => {
 | 
						ipcMain.on('register-server-tab-shortcut', (event, index) => {
 | 
				
			||||||
		electronLocalshortcut.register(mainWindow, `CommandOrControl+${index}`, () => {
 | 
							// Array index == Shown index - 1
 | 
				
			||||||
			// Array index == Shown index - 1
 | 
							page.send('switch-server-tab', index - 1);
 | 
				
			||||||
			page.send('switch-server-tab', index - 1);
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ipcMain.on('local-shortcuts', (event, enable) => {
 | 
					 | 
				
			||||||
		if (enable) {
 | 
					 | 
				
			||||||
			registerLocalShortcuts(page);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			electronLocalshortcut.unregisterAll(mainWindow);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ipcMain.on('toggleAutoLauncher', (event, AutoLaunchValue) => {
 | 
						ipcMain.on('toggleAutoLauncher', (event, AutoLaunchValue) => {
 | 
				
			||||||
@@ -248,11 +218,6 @@ app.on('ready', () => {
 | 
				
			|||||||
	});
 | 
						});
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.on('will-quit', () => {
 | 
					 | 
				
			||||||
	// Unregister all the shortcuts so that they don't interfare with other apps
 | 
					 | 
				
			||||||
	electronLocalshortcut.unregisterAll(mainWindow);
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
app.on('before-quit', () => {
 | 
					app.on('before-quit', () => {
 | 
				
			||||||
	isQuitting = true;
 | 
						isQuitting = true;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,7 +37,7 @@ class AppMenu {
 | 
				
			|||||||
			accelerator: 'CommandOrControl+R',
 | 
								accelerator: 'CommandOrControl+R',
 | 
				
			||||||
			click(item, focusedWindow) {
 | 
								click(item, focusedWindow) {
 | 
				
			||||||
				if (focusedWindow) {
 | 
									if (focusedWindow) {
 | 
				
			||||||
					AppMenu.sendAction('reload-viewer');
 | 
										AppMenu.sendAction('reload-current-viewer');
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}, {
 | 
							}, {
 | 
				
			||||||
@@ -173,7 +173,7 @@ class AppMenu {
 | 
				
			|||||||
		return [{
 | 
							return [{
 | 
				
			||||||
			label: `${app.getName()}`,
 | 
								label: `${app.getName()}`,
 | 
				
			||||||
			submenu: [{
 | 
								submenu: [{
 | 
				
			||||||
				label: 'Zulip Desktop',
 | 
									label: 'About Zulip',
 | 
				
			||||||
				click(item, focusedWindow) {
 | 
									click(item, focusedWindow) {
 | 
				
			||||||
					if (focusedWindow) {
 | 
										if (focusedWindow) {
 | 
				
			||||||
						AppMenu.sendAction('open-about');
 | 
											AppMenu.sendAction('open-about');
 | 
				
			||||||
@@ -273,7 +273,7 @@ class AppMenu {
 | 
				
			|||||||
		return [{
 | 
							return [{
 | 
				
			||||||
			label: 'File',
 | 
								label: 'File',
 | 
				
			||||||
			submenu: [{
 | 
								submenu: [{
 | 
				
			||||||
				label: 'Zulip Desktop',
 | 
									label: 'About Zulip',
 | 
				
			||||||
				click(item, focusedWindow) {
 | 
									click(item, focusedWindow) {
 | 
				
			||||||
					if (focusedWindow) {
 | 
										if (focusedWindow) {
 | 
				
			||||||
						AppMenu.sendAction('open-about');
 | 
											AppMenu.sendAction('open-about');
 | 
				
			||||||
@@ -370,10 +370,20 @@ class AppMenu {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static resetAppSettings() {
 | 
						static resetAppSettings() {
 | 
				
			||||||
		const getAppPath = path.join(app.getPath('appData'), appName, 'window-state.json');
 | 
							// We save App's settings/configurations in following files
 | 
				
			||||||
 | 
							const settingFiles = ['window-state.json', 'domain.json', 'settings.json'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fs.unlink(getAppPath, () => {
 | 
							settingFiles.forEach(settingFileName => {
 | 
				
			||||||
			setTimeout(() => AppMenu.sendAction('clear-app-data'), 1000);
 | 
								const getSettingFilesPath = path.join(app.getPath('appData'), appName, settingFileName);
 | 
				
			||||||
 | 
								fs.access(getSettingFilesPath, error => {
 | 
				
			||||||
 | 
									if (error) {
 | 
				
			||||||
 | 
										console.log(error);
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										fs.unlink(getSettingFilesPath, () => {
 | 
				
			||||||
 | 
											AppMenu.sendAction('clear-app-data');
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "zulip",
 | 
					  "name": "zulip",
 | 
				
			||||||
  "productName": "Zulip",
 | 
					  "productName": "Zulip",
 | 
				
			||||||
  "version": "1.4.0",
 | 
					  "version": "1.6.0-beta",
 | 
				
			||||||
  "description": "Zulip Desktop App",
 | 
					  "description": "Zulip Desktop App",
 | 
				
			||||||
  "license": "Apache-2.0",
 | 
					  "license": "Apache-2.0",
 | 
				
			||||||
  "email": "<svnitakash@gmail.com>",
 | 
					  "email": "<svnitakash@gmail.com>",
 | 
				
			||||||
@@ -27,12 +27,10 @@
 | 
				
			|||||||
    "InstantMessaging"
 | 
					    "InstantMessaging"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "electron-debug": "1.4.0",
 | 
					 | 
				
			||||||
    "electron-is-dev": "0.3.0",
 | 
					    "electron-is-dev": "0.3.0",
 | 
				
			||||||
    "electron-localshortcut": "2.0.2",
 | 
					 | 
				
			||||||
    "electron-log": "2.2.7",
 | 
					    "electron-log": "2.2.7",
 | 
				
			||||||
    "electron-spellchecker": "1.2.0",
 | 
					    "electron-spellchecker": "1.1.2",
 | 
				
			||||||
    "electron-updater": "2.8.9",
 | 
					    "electron-updater": "2.16.2",
 | 
				
			||||||
    "node-json-db": "0.7.3",
 | 
					    "node-json-db": "0.7.3",
 | 
				
			||||||
    "request": "2.81.0",
 | 
					    "request": "2.81.0",
 | 
				
			||||||
    "wurl": "2.5.0",
 | 
					    "wurl": "2.5.0",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@ body {
 | 
				
			|||||||
    background-position: center;
 | 
					    background-position: center;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#sidebar {
 | 
					.toggle-sidebar {
 | 
				
			||||||
    background: #222c31;
 | 
					    background: #222c31;
 | 
				
			||||||
    width: 54px;
 | 
					    width: 54px;
 | 
				
			||||||
    padding: 27px 0 20px 0;
 | 
					    padding: 27px 0 20px 0;
 | 
				
			||||||
@@ -27,6 +27,21 @@ body {
 | 
				
			|||||||
    flex-direction: column;
 | 
					    flex-direction: column;
 | 
				
			||||||
    -webkit-app-region: drag;
 | 
					    -webkit-app-region: drag;
 | 
				
			||||||
    overflow: hidden;
 | 
					    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 {
 | 
					@font-face {
 | 
				
			||||||
@@ -38,8 +53,8 @@ body {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*******************
 | 
					/*******************
 | 
				
			||||||
 *   Left Sidebar  *
 | 
					  *   Left Sidebar  *
 | 
				
			||||||
 *******************/
 | 
					  *******************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#tabs-container {
 | 
					#tabs-container {
 | 
				
			||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
@@ -197,8 +212,8 @@ body {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*******************
 | 
					/*******************
 | 
				
			||||||
 *   Webview Area  *
 | 
					  *   Webview Area  *
 | 
				
			||||||
 *******************/
 | 
					  *******************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#webviews-container {
 | 
					#webviews-container {
 | 
				
			||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
@@ -258,6 +273,33 @@ webview:focus {
 | 
				
			|||||||
    right: 68px;
 | 
					    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 {
 | 
					#collapse-button {
 | 
				
			||||||
    bottom: 30px;
 | 
					    bottom: 30px;
 | 
				
			||||||
    left: 20px;
 | 
					    left: 20px;
 | 
				
			||||||
@@ -285,7 +327,9 @@ webview:focus {
 | 
				
			|||||||
    display: none !important;
 | 
					    display: none !important;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Full screen Popup container  */
 | 
					/* Full screen Popup container  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.popup .popuptext {
 | 
					.popup .popuptext {
 | 
				
			||||||
    visibility: hidden;
 | 
					    visibility: hidden;
 | 
				
			||||||
    background-color: #555;
 | 
					    background-color: #555;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,33 +12,33 @@ body {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
kbd {
 | 
					kbd {
 | 
				
			||||||
    padding: 0.1em 0.6em;
 | 
					    padding: 0.3em 0.8em;
 | 
				
			||||||
    border: 1px solid #ccc;
 | 
					    border: 1px solid #ccc;
 | 
				
			||||||
    font-size: 12px;
 | 
					    font-size: 15px;
 | 
				
			||||||
    font-family: Arial,Helvetica,sans-serif;
 | 
					    font-family: Courier New, Courier, monospace;
 | 
				
			||||||
    background-color: #f7f7f7;
 | 
					    background-color: #383430;
 | 
				
			||||||
    color: #333;
 | 
					    color: #ededed;
 | 
				
			||||||
    -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;
 | 
					    display: inline-block;
 | 
				
			||||||
    margin: 0 0.1em;
 | 
					    margin: 0 0.1em;
 | 
				
			||||||
    text-shadow: 0 1px 0 #fff;
 | 
					    font-weight: bold;
 | 
				
			||||||
    line-height: 1.4;
 | 
					 | 
				
			||||||
    white-space: nowrap;
 | 
					    white-space: nowrap;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
table, th, td {
 | 
					table, th, td {
 | 
				
			||||||
    border: 1px solid #ddd;
 | 
					 | 
				
			||||||
    border-collapse: collapse;
 | 
					    border-collapse: collapse;
 | 
				
			||||||
 | 
					    color: #383430;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
table { width: 85%; }
 | 
					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 tr:nth-child(even) { background-color: #f2f2f2; }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
td { padding: 5px; }
 | 
					td { padding: 5px; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -56,6 +56,11 @@ td:nth-child(odd) {
 | 
				
			|||||||
       url(../fonts/MaterialIcons-Regular.ttf) format('truetype');
 | 
					       url(../fonts/MaterialIcons-Regular.ttf) format('truetype');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@font-face {
 | 
				
			||||||
 | 
					  font-family: 'Montserrat';
 | 
				
			||||||
 | 
					  src: url(../fonts/Montserrat-Regular.ttf) format('truetype');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.material-icons {
 | 
					.material-icons {
 | 
				
			||||||
  font-family: 'Material Icons';
 | 
					  font-family: 'Material Icons';
 | 
				
			||||||
  font-weight: normal;
 | 
					  font-weight: normal;
 | 
				
			||||||
@@ -78,7 +83,7 @@ td:nth-child(odd) {
 | 
				
			|||||||
#content {
 | 
					#content {
 | 
				
			||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
    height: 100%;
 | 
					    height: 100%;
 | 
				
			||||||
    font-family: sans-serif;
 | 
					    font-family: 'Montserrat';
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#sidebar {
 | 
					#sidebar {
 | 
				
			||||||
@@ -116,7 +121,9 @@ td:nth-child(odd) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#settings-header {
 | 
					#settings-header {
 | 
				
			||||||
    font-size: 22px;
 | 
					    font-size: 22px;
 | 
				
			||||||
    color: #5c6166;
 | 
					    color: #222c31;
 | 
				
			||||||
 | 
					    font-weight: bold;
 | 
				
			||||||
 | 
					    text-transform: uppercase;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#settings-container {
 | 
					#settings-container {
 | 
				
			||||||
@@ -134,7 +141,8 @@ td:nth-child(odd) {
 | 
				
			|||||||
.title {
 | 
					.title {
 | 
				
			||||||
    padding: 4px 0 6px 0;
 | 
					    padding: 4px 0 6px 0;
 | 
				
			||||||
    font-weight: bold;
 | 
					    font-weight: bold;
 | 
				
			||||||
    color: #1e1e1e;
 | 
					    color: #222c31;
 | 
				
			||||||
 | 
					    text-transform: uppercase;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.sub-title {
 | 
					.sub-title {
 | 
				
			||||||
@@ -210,7 +218,6 @@ img.server-info-icon {
 | 
				
			|||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
    align-items: center;
 | 
					    align-items: center;
 | 
				
			||||||
    padding: 0 10px;
 | 
					    padding: 0 10px;
 | 
				
			||||||
    border-radius: 2px;
 | 
					 | 
				
			||||||
    margin-right: 10px;
 | 
					    margin-right: 10px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -242,9 +249,8 @@ img.server-info-icon {
 | 
				
			|||||||
    padding: 12px 30px;
 | 
					    padding: 12px 30px;
 | 
				
			||||||
    margin: 10px 0 20px 0;
 | 
					    margin: 10px 0 20px 0;
 | 
				
			||||||
    background: #fff;
 | 
					    background: #fff;
 | 
				
			||||||
    border-radius: 2px;
 | 
					    width: 70%;
 | 
				
			||||||
    width: 540px;
 | 
					    border-left: 8px solid #bcbcbc;
 | 
				
			||||||
    box-shadow: 1px 2px 4px #bcbcbc;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.hidden {
 | 
					.hidden {
 | 
				
			||||||
@@ -253,15 +259,19 @@ img.server-info-icon {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.red {
 | 
					.red {
 | 
				
			||||||
    color: #ef5350;
 | 
					    color: #ffffff;
 | 
				
			||||||
    background: #ffebee;
 | 
					    background: #ef5350;
 | 
				
			||||||
    border: 1px solid #ef5350;
 | 
					    padding: 3px;
 | 
				
			||||||
 | 
					    padding-right: 10px;
 | 
				
			||||||
 | 
					    padding-left: 10px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.green {
 | 
					.blue {
 | 
				
			||||||
    color: #388E3C;
 | 
					    color: #ffffff;
 | 
				
			||||||
    background: #E8F5E9;
 | 
					    background: #4EBFAC;
 | 
				
			||||||
    border: 1px solid #388E3C;
 | 
					    padding: 3px;
 | 
				
			||||||
 | 
					    padding-right: 10px;
 | 
				
			||||||
 | 
					    padding-left: 10px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.grey {
 | 
					.grey {
 | 
				
			||||||
@@ -272,9 +282,10 @@ img.server-info-icon {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.setting-row {
 | 
					.setting-row {
 | 
				
			||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
    justify-content: space-between;
 | 
					    justify-content: space-between;
 | 
				
			||||||
    width: 100%;
 | 
					    width: 100%;
 | 
				
			||||||
    margin: 6px 0;
 | 
					    margin: 6px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.code {
 | 
					.code {
 | 
				
			||||||
@@ -289,26 +300,90 @@ i.open-tab-button {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.reset-data-button {
 | 
					.reset-data-button {
 | 
				
			||||||
    display: inline-block;
 | 
					    display: inline-block;
 | 
				
			||||||
 | 
					    border: none;
 | 
				
			||||||
 | 
					    padding: 10px;
 | 
				
			||||||
    width: 120px;
 | 
					    width: 120px;
 | 
				
			||||||
    cursor: pointer;
 | 
					    cursor: pointer;
 | 
				
			||||||
    font-size: 11px;
 | 
					    font-size: 13px;
 | 
				
			||||||
    transition: background-color 0.2s ease;
 | 
					    transition: background-color 0.2s ease;
 | 
				
			||||||
    text-decoration: none;
 | 
					    text-decoration: none;
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.reset-data-button:hover {
 | 
					.reset-data-button:hover {
 | 
				
			||||||
    background-color: #32a692;
 | 
					    background-color: #3c9f8d;
 | 
				
			||||||
    color: #fff;
 | 
					    color: #fff;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#open-shortcuts-url {
 | 
					#server-info-container {
 | 
				
			||||||
		color: #08c;
 | 
							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;
 | 
							cursor: pointer;
 | 
				
			||||||
		text-decoration: none;
 | 
							text-decoration: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#open-shortcuts-url:hover {
 | 
					#open-create-org-link:hover {
 | 
				
			||||||
		color: #005580;;
 | 
							color: #005580;;
 | 
				
			||||||
		text-decoration: underline;
 | 
							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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								app/renderer/fonts/Montserrat-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/renderer/fonts/Montserrat-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -8,6 +8,7 @@ const {ipcRenderer} = require('electron');
 | 
				
			|||||||
class ServerTab extends Tab {
 | 
					class ServerTab extends Tab {
 | 
				
			||||||
	template() {
 | 
						template() {
 | 
				
			||||||
		return `<div class="tab">
 | 
							return `<div class="tab">
 | 
				
			||||||
 | 
										<div class="server-tooltip" style="display:none"></div>
 | 
				
			||||||
					<div class="server-tab-badge"></div>
 | 
										<div class="server-tab-badge"></div>
 | 
				
			||||||
					<div class="server-tab">
 | 
										<div class="server-tab">
 | 
				
			||||||
					<img class="server-icons" src='${this.props.icon}'/>
 | 
										<img class="server-icons" src='${this.props.icon}'/>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,8 @@ class Tab extends BaseComponent {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	registerListeners() {
 | 
						registerListeners() {
 | 
				
			||||||
		this.$el.addEventListener('click', this.props.onClick);
 | 
							this.$el.addEventListener('click', this.props.onClick);
 | 
				
			||||||
 | 
							this.$el.addEventListener('mouseover', this.props.onHover);
 | 
				
			||||||
 | 
							this.$el.addEventListener('mouseout', this.props.onHoverOut);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	isLoading() {
 | 
						isLoading() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@ const fs = require('fs');
 | 
				
			|||||||
const DomainUtil = require(__dirname + '/../utils/domain-util.js');
 | 
					const DomainUtil = require(__dirname + '/../utils/domain-util.js');
 | 
				
			||||||
const SystemUtil = require(__dirname + '/../utils/system-util.js');
 | 
					const SystemUtil = require(__dirname + '/../utils/system-util.js');
 | 
				
			||||||
const LinkUtil = require(__dirname + '/../utils/link-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');
 | 
					const BaseComponent = require(__dirname + '/../components/base.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -42,7 +42,7 @@ class WebView extends BaseComponent {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	registerListeners() {
 | 
						registerListeners() {
 | 
				
			||||||
		this.$el.addEventListener('new-window', event => {
 | 
							this.$el.addEventListener('new-window', event => {
 | 
				
			||||||
			const {url} = event;
 | 
								const { url } = event;
 | 
				
			||||||
			const domainPrefix = DomainUtil.getDomain(this.props.index).url;
 | 
								const domainPrefix = DomainUtil.getDomain(this.props.index).url;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (LinkUtil.isInternal(domainPrefix, url) || url === (domainPrefix + '/')) {
 | 
								if (LinkUtil.isInternal(domainPrefix, url) || url === (domainPrefix + '/')) {
 | 
				
			||||||
@@ -55,11 +55,21 @@ class WebView extends BaseComponent {
 | 
				
			|||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.$el.addEventListener('page-title-updated', event => {
 | 
							this.$el.addEventListener('page-title-updated', event => {
 | 
				
			||||||
			const {title} = event;
 | 
								const { title } = event;
 | 
				
			||||||
			this.badgeCount = this.getBadgeCount(title);
 | 
								this.badgeCount = this.getBadgeCount(title);
 | 
				
			||||||
			this.props.onTitleChange();
 | 
								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', () => {
 | 
							this.$el.addEventListener('dom-ready', () => {
 | 
				
			||||||
			if (this.props.role === 'server') {
 | 
								if (this.props.role === 'server') {
 | 
				
			||||||
				this.$el.classList.add('onload');
 | 
									this.$el.classList.add('onload');
 | 
				
			||||||
@@ -68,7 +78,7 @@ class WebView extends BaseComponent {
 | 
				
			|||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.$el.addEventListener('did-fail-load', event => {
 | 
							this.$el.addEventListener('did-fail-load', event => {
 | 
				
			||||||
			const {errorDescription} = event;
 | 
								const { errorDescription } = event;
 | 
				
			||||||
			const hasConnectivityErr = (SystemUtil.connectivityERR.indexOf(errorDescription) >= 0);
 | 
								const hasConnectivityErr = (SystemUtil.connectivityERR.indexOf(errorDescription) >= 0);
 | 
				
			||||||
			if (hasConnectivityErr) {
 | 
								if (hasConnectivityErr) {
 | 
				
			||||||
				console.error('error', errorDescription);
 | 
									console.error('error', errorDescription);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,8 +21,11 @@ class ServerManagerView {
 | 
				
			|||||||
		this.$settingsButton = $actionsContainer.querySelector('#settings-action');
 | 
							this.$settingsButton = $actionsContainer.querySelector('#settings-action');
 | 
				
			||||||
		this.$webviewsContainer = document.getElementById('webviews-container');
 | 
							this.$webviewsContainer = document.getElementById('webviews-container');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.$addServerTooltip = document.getElementById('add-server-tooltip');
 | 
				
			||||||
		this.$reloadTooltip = $actionsContainer.querySelector('#reload-tooltip');
 | 
							this.$reloadTooltip = $actionsContainer.querySelector('#reload-tooltip');
 | 
				
			||||||
		this.$settingsTooltip = $actionsContainer.querySelector('#setting-tooltip');
 | 
							this.$settingsTooltip = $actionsContainer.querySelector('#setting-tooltip');
 | 
				
			||||||
 | 
							this.$serverIconTooltip = document.getElementsByClassName('server-tooltip');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.$sidebar = document.getElementById('sidebar');
 | 
							this.$sidebar = document.getElementById('sidebar');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.$fullscreenPopup = document.getElementById('fullscreen-popup');
 | 
							this.$fullscreenPopup = document.getElementById('fullscreen-popup');
 | 
				
			||||||
@@ -75,12 +78,11 @@ class ServerManagerView {
 | 
				
			|||||||
				DomainUtil.updateSavedServer(servers[i].url, i);
 | 
									DomainUtil.updateSavedServer(servers[i].url, i);
 | 
				
			||||||
				this.activateTab(i);
 | 
									this.activateTab(i);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			this.activateTab(0);
 | 
								// Open last active tab
 | 
				
			||||||
 | 
								this.activateTab(ConfigUtil.getConfigItem('lastActiveTab'));
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			this.openSettings('Servers');
 | 
								this.openSettings('Servers');
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		ipcRenderer.send('local-shortcuts', true);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	initServer(server, index) {
 | 
						initServer(server, index) {
 | 
				
			||||||
@@ -88,8 +90,10 @@ class ServerManagerView {
 | 
				
			|||||||
			role: 'server',
 | 
								role: 'server',
 | 
				
			||||||
			icon: server.icon,
 | 
								icon: server.icon,
 | 
				
			||||||
			$root: this.$tabsContainer,
 | 
								$root: this.$tabsContainer,
 | 
				
			||||||
			onClick: this.activateTab.bind(this, index),
 | 
								onClick: this.activateLastTab.bind(this, index),
 | 
				
			||||||
			index,
 | 
								index,
 | 
				
			||||||
 | 
								onHover: this.onHover.bind(this, index, server.alias),
 | 
				
			||||||
 | 
								onHoverOut: this.onHoverOut.bind(this, index),
 | 
				
			||||||
			webview: new WebView({
 | 
								webview: new WebView({
 | 
				
			||||||
				$root: this.$webviewsContainer,
 | 
									$root: this.$webviewsContainer,
 | 
				
			||||||
				index,
 | 
									index,
 | 
				
			||||||
@@ -117,6 +121,7 @@ class ServerManagerView {
 | 
				
			|||||||
			this.openSettings('General');
 | 
								this.openSettings('General');
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.sidebarHoverEvent(this.$addServerButton, this.$addServerTooltip);
 | 
				
			||||||
		this.sidebarHoverEvent(this.$settingsButton, this.$settingsTooltip);
 | 
							this.sidebarHoverEvent(this.$settingsButton, this.$settingsTooltip);
 | 
				
			||||||
		this.sidebarHoverEvent(this.$reloadButton, this.$reloadTooltip);
 | 
							this.sidebarHoverEvent(this.$reloadButton, this.$reloadTooltip);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -130,6 +135,15 @@ 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) {
 | 
						openFunctionalTab(tabProps) {
 | 
				
			||||||
		if (this.functionalTabs[tabProps.name] !== undefined) {
 | 
							if (this.functionalTabs[tabProps.name] !== undefined) {
 | 
				
			||||||
			this.activateTab(this.functionalTabs[tabProps.name]);
 | 
								this.activateTab(this.functionalTabs[tabProps.name]);
 | 
				
			||||||
@@ -188,8 +202,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) {
 | 
						activateTab(index, hideOldTab = true) {
 | 
				
			||||||
		if (this.tabs[index].webview.loading) {
 | 
							if (!this.tabs[index]) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -235,16 +256,24 @@ class ServerManagerView {
 | 
				
			|||||||
		// Clear DOM elements
 | 
							// Clear DOM elements
 | 
				
			||||||
		this.$tabsContainer.innerHTML = '';
 | 
							this.$tabsContainer.innerHTML = '';
 | 
				
			||||||
		this.$webviewsContainer.innerHTML = '';
 | 
							this.$webviewsContainer.innerHTML = '';
 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Destroy shortcuts
 | 
					 | 
				
			||||||
		ipcRenderer.send('local-shortcuts', false);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reloadView() {
 | 
						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.destroyView();
 | 
				
			||||||
		this.initTabs();
 | 
							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() {
 | 
						updateBadge() {
 | 
				
			||||||
		let messageCountAll = 0;
 | 
							let messageCountAll = 0;
 | 
				
			||||||
		for (let i = 0; i < this.tabs.length; i++) {
 | 
							for (let i = 0; i < this.tabs.length; i++) {
 | 
				
			||||||
@@ -260,9 +289,9 @@ class ServerManagerView {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	toggleSidebar(show) {
 | 
						toggleSidebar(show) {
 | 
				
			||||||
		if (show) {
 | 
							if (show) {
 | 
				
			||||||
			this.$sidebar.classList.remove('hidden');
 | 
								this.$sidebar.classList.remove('sidebar-hide');
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			this.$sidebar.classList.add('hidden');
 | 
								this.$sidebar.classList.add('sidebar-hide');
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -295,7 +324,9 @@ class ServerManagerView {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		ipcRenderer.on('open-about', this.openAbout.bind(this));
 | 
							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.on('hard-reload', () => {
 | 
				
			||||||
			ipcRenderer.send('reload-full-app');
 | 
								ipcRenderer.send('reload-full-app');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,10 +15,16 @@ const NativeNotification = window.Notification;
 | 
				
			|||||||
class baseNotification extends NativeNotification {
 | 
					class baseNotification extends NativeNotification {
 | 
				
			||||||
	constructor(title, opts) {
 | 
						constructor(title, opts) {
 | 
				
			||||||
		opts.silent = ConfigUtil.getConfigItem('silent') || false;
 | 
							opts.silent = ConfigUtil.getConfigItem('silent') || false;
 | 
				
			||||||
		// calling super without passing arguments will fail to constuct Notification
 | 
							super(title, opts);
 | 
				
			||||||
		// 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
 | 
						static requestPermission() {
 | 
				
			||||||
 | 
							return; // eslint-disable-line no-useless-return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Override default Notification permission
 | 
				
			||||||
 | 
						static get permission() {
 | 
				
			||||||
 | 
							return ConfigUtil.getConfigItem('showNotification') ? 'granted' : 'denied';
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
window.Notification = baseNotification;
 | 
					window.Notification = baseNotification;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,7 +45,7 @@ class BadgeSettings {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	updateOverlayIcon(messageCount, mainWindow) {
 | 
						updateOverlayIcon(messageCount, mainWindow) {
 | 
				
			||||||
		if (!mainWindow.isFocused()) {
 | 
							if (!mainWindow.isFocused()) {
 | 
				
			||||||
			mainWindow.flashFrame(true);
 | 
								mainWindow.flashFrame(ConfigUtil.getConfigItem('flashTaskbarOnMessage'));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (messageCount === 0) {
 | 
							if (messageCount === 0) {
 | 
				
			||||||
			mainWindow.setOverlayIcon(null, '');
 | 
								mainWindow.setOverlayIcon(null, '');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,14 +19,20 @@ class BaseSection extends BaseComponent {
 | 
				
			|||||||
	generateOptionTemplate(settingOption) {
 | 
						generateOptionTemplate(settingOption) {
 | 
				
			||||||
		if (settingOption) {
 | 
							if (settingOption) {
 | 
				
			||||||
			return `
 | 
								return `
 | 
				
			||||||
				<div class="action green">
 | 
									<div class="action">
 | 
				
			||||||
					<span>On</span>
 | 
										<div class="switch">
 | 
				
			||||||
 | 
										  <input class="toggle toggle-round" type="checkbox" checked>
 | 
				
			||||||
 | 
										  <label></label>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			`;
 | 
								`;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			return `
 | 
								return `
 | 
				
			||||||
				<div class="action red">
 | 
									<div class="action">
 | 
				
			||||||
					<span>Off</span>
 | 
										<div class="switch">
 | 
				
			||||||
 | 
										  <input class="toggle toggle-round" type="checkbox">
 | 
				
			||||||
 | 
										  <label></label>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			`;
 | 
								`;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								app/renderer/js/pages/preference/create-new-org.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/renderer/js/pages/preference/create-new-org.js
									
									
									
									
									
										Normal 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;
 | 
				
			||||||
@@ -25,13 +25,17 @@ class GeneralSection extends BaseSection {
 | 
				
			|||||||
						<div class="setting-control"></div>
 | 
											<div class="setting-control"></div>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
					<div class="setting-row" id="sidebar-option">
 | 
										<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 class="setting-control"></div>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
					<div class="setting-row" id="badge-option">
 | 
										<div class="setting-row" id="badge-option">
 | 
				
			||||||
					<div class="setting-description">Show app unread badge</div>
 | 
											<div class="setting-description">Show app unread badge</div>
 | 
				
			||||||
					<div class="setting-control"></div>
 | 
											<div class="setting-control"></div>
 | 
				
			||||||
				</div>
 | 
										</div>
 | 
				
			||||||
 | 
										<div class="setting-row" id="flash-taskbar-option" style= "display:${process.platform === 'win32' ? '' : 'none'}">
 | 
				
			||||||
 | 
											<div class="setting-description">Flash taskbar on new message</div>
 | 
				
			||||||
 | 
											<div class="setting-control"></div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
				<div class="title">Desktop Notification</div>
 | 
									<div class="title">Desktop Notification</div>
 | 
				
			||||||
				<div class="settings-card">
 | 
									<div class="settings-card">
 | 
				
			||||||
@@ -50,10 +54,6 @@ class GeneralSection extends BaseSection {
 | 
				
			|||||||
						<div class="setting-description">Get beta updates</div>
 | 
											<div class="setting-description">Get beta updates</div>
 | 
				
			||||||
						<div class="setting-control"></div>
 | 
											<div class="setting-control"></div>
 | 
				
			||||||
					</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>
 | 
				
			||||||
				<div class="title">Functionality</div>
 | 
									<div class="title">Functionality</div>
 | 
				
			||||||
                <div class="settings-card">
 | 
					                <div class="settings-card">
 | 
				
			||||||
@@ -61,13 +61,17 @@ class GeneralSection extends BaseSection {
 | 
				
			|||||||
						<div class="setting-description">Start app at login</div>
 | 
											<div class="setting-description">Start app at login</div>
 | 
				
			||||||
						<div class="setting-control"></div>
 | 
											<div class="setting-control"></div>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
 | 
										<div class="setting-row" id="enable-spellchecker-option">
 | 
				
			||||||
 | 
										<div class="setting-description">Enable Spellchecker (requires restart)</div>
 | 
				
			||||||
 | 
										<div class="setting-control"></div>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
				<div class="title">Reset Application Data</div>
 | 
									<div class="title">Reset Application Data</div>
 | 
				
			||||||
                <div class="settings-card">
 | 
					                <div class="settings-card">
 | 
				
			||||||
					<div class="setting-row" id="resetdata-option">
 | 
										<div class="setting-row" id="resetdata-option">
 | 
				
			||||||
						<div class="setting-description">This will delete all application data including all added accounts and preferences
 | 
											<div class="setting-description">This will delete all application data including all added accounts and preferences
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
						<button class="reset-data-button green">Reset App Data</button>
 | 
											<button class="reset-data-button blue">Reset App Data</button>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
@@ -78,13 +82,19 @@ class GeneralSection extends BaseSection {
 | 
				
			|||||||
		this.props.$root.innerHTML = this.template();
 | 
							this.props.$root.innerHTML = this.template();
 | 
				
			||||||
		this.updateTrayOption();
 | 
							this.updateTrayOption();
 | 
				
			||||||
		this.updateBadgeOption();
 | 
							this.updateBadgeOption();
 | 
				
			||||||
		this.updateUpdateOption();
 | 
					 | 
				
			||||||
		this.updateAutoUpdateOption();
 | 
					 | 
				
			||||||
		this.updateSilentOption();
 | 
							this.updateSilentOption();
 | 
				
			||||||
 | 
							this.updateUpdateOption();
 | 
				
			||||||
		this.updateSidebarOption();
 | 
							this.updateSidebarOption();
 | 
				
			||||||
		this.updateStartAtLoginOption();
 | 
							this.updateStartAtLoginOption();
 | 
				
			||||||
		this.updateResetDataOption();
 | 
							this.updateResetDataOption();
 | 
				
			||||||
		this.showDesktopNotification();
 | 
							this.showDesktopNotification();
 | 
				
			||||||
 | 
							this.enableSpellchecker();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Platform specific settings
 | 
				
			||||||
 | 
							// Flashing taskbar on Windows
 | 
				
			||||||
 | 
							if (process.platform === 'win32') {
 | 
				
			||||||
 | 
								this.updateFlashTaskbar();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	updateTrayOption() {
 | 
						updateTrayOption() {
 | 
				
			||||||
@@ -113,6 +123,18 @@ class GeneralSection extends BaseSection {
 | 
				
			|||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						updateFlashTaskbar() {
 | 
				
			||||||
 | 
							this.generateSettingOption({
 | 
				
			||||||
 | 
								$element: document.querySelector('#flash-taskbar-option .setting-control'),
 | 
				
			||||||
 | 
								value: ConfigUtil.getConfigItem('flashTaskbarOnMessage', true),
 | 
				
			||||||
 | 
								clickHandler: () => {
 | 
				
			||||||
 | 
									const newValue = !ConfigUtil.getConfigItem('flashTaskbarOnMessage');
 | 
				
			||||||
 | 
									ConfigUtil.setConfigItem('flashTaskbarOnMessage', newValue);
 | 
				
			||||||
 | 
									this.updateFlashTaskbar();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	updateUpdateOption() {
 | 
						updateUpdateOption() {
 | 
				
			||||||
		this.generateSettingOption({
 | 
							this.generateSettingOption({
 | 
				
			||||||
			$element: document.querySelector('#betaupdate-option .setting-control'),
 | 
								$element: document.querySelector('#betaupdate-option .setting-control'),
 | 
				
			||||||
@@ -125,18 +147,6 @@ 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() {
 | 
						updateSilentOption() {
 | 
				
			||||||
		this.generateSettingOption({
 | 
							this.generateSettingOption({
 | 
				
			||||||
			$element: document.querySelector('#silent-option .setting-control'),
 | 
								$element: document.querySelector('#silent-option .setting-control'),
 | 
				
			||||||
@@ -187,6 +197,18 @@ class GeneralSection extends BaseSection {
 | 
				
			|||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						enableSpellchecker() {
 | 
				
			||||||
 | 
							this.generateSettingOption({
 | 
				
			||||||
 | 
								$element: document.querySelector('#enable-spellchecker-option .setting-control'),
 | 
				
			||||||
 | 
								value: ConfigUtil.getConfigItem('enableSpellchecker', true),
 | 
				
			||||||
 | 
								clickHandler: () => {
 | 
				
			||||||
 | 
									const newValue = !ConfigUtil.getConfigItem('enableSpellchecker');
 | 
				
			||||||
 | 
									ConfigUtil.setConfigItem('enableSpellchecker', newValue);
 | 
				
			||||||
 | 
									this.enableSpellchecker();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clearAppDataDialog() {
 | 
						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 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());
 | 
							const getAppPath = path.join(app.getPath('appData'), app.getName());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,7 @@ class NetworkSection extends BaseSection {
 | 
				
			|||||||
							<input class="setting-input-value" placeholder="e.g. foobar.com"/>
 | 
												<input class="setting-input-value" placeholder="e.g. foobar.com"/>
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
						<div class="setting-row">
 | 
											<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>
 | 
													<i class="material-icons">check_box</i>
 | 
				
			||||||
								<span>Save</span>
 | 
													<span>Save</span>
 | 
				
			||||||
							</div>
 | 
												</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,12 +14,12 @@ class NewServerForm extends BaseComponent {
 | 
				
			|||||||
			<div class="settings-card">
 | 
								<div class="settings-card">
 | 
				
			||||||
				<div class="server-info-right">
 | 
									<div class="server-info-right">
 | 
				
			||||||
					<div class="server-info-row">
 | 
										<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>
 | 
				
			||||||
					<div class="server-info-row">
 | 
										<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>
 | 
												<i class="material-icons">check_box</i>
 | 
				
			||||||
							<span>Save</span>
 | 
												<span>Add</span>
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,9 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const BaseComponent = require(__dirname + '/js/components/base.js');
 | 
					const BaseComponent = require(__dirname + '/js/components/base.js');
 | 
				
			||||||
const {ipcRenderer} = require('electron');
 | 
					const { ipcRenderer } = require('electron');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ConfigUtil = require(__dirname + '/js/utils/config-util.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const Nav = require(__dirname + '/js/pages/preference/nav.js');
 | 
					const Nav = require(__dirname + '/js/pages/preference/nav.js');
 | 
				
			||||||
const ServersSection = require(__dirname + '/js/pages/preference/servers-section.js');
 | 
					const ServersSection = require(__dirname + '/js/pages/preference/servers-section.js');
 | 
				
			||||||
@@ -25,6 +27,7 @@ class PreferenceView extends BaseComponent {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		this.setDefaultView();
 | 
							this.setDefaultView();
 | 
				
			||||||
		this.registerIpcs();
 | 
							this.registerIpcs();
 | 
				
			||||||
 | 
							this.setDefaultSettings();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setDefaultView() {
 | 
						setDefaultView() {
 | 
				
			||||||
@@ -36,6 +39,30 @@ class PreferenceView extends BaseComponent {
 | 
				
			|||||||
		this.handleNavigation(nav);
 | 
							this.handleNavigation(nav);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Settings are initialized only when user clicks on General/Server/Network section settings
 | 
				
			||||||
 | 
						// In case, user doesn't visit these section, those values set to be null automatically
 | 
				
			||||||
 | 
						// This will make sure the default settings are correctly set to either true or false
 | 
				
			||||||
 | 
						setDefaultSettings() {
 | 
				
			||||||
 | 
							// Default settings which should be respected
 | 
				
			||||||
 | 
							const settingOptions = {
 | 
				
			||||||
 | 
								trayIcon: true,
 | 
				
			||||||
 | 
								useProxy: false,
 | 
				
			||||||
 | 
								showSidebar: true,
 | 
				
			||||||
 | 
								badgeOption: true,
 | 
				
			||||||
 | 
								startAtLogin: false,
 | 
				
			||||||
 | 
								enableSpellchecker: true,
 | 
				
			||||||
 | 
								showNotification: true,
 | 
				
			||||||
 | 
								betaUpdate: false,
 | 
				
			||||||
 | 
								silent: false
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (const i in settingOptions) {
 | 
				
			||||||
 | 
								if (ConfigUtil.getConfigItem(i) === null) {
 | 
				
			||||||
 | 
									ConfigUtil.setConfigItem(i, settingOptions[i]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	handleNavigation(navItem) {
 | 
						handleNavigation(navItem) {
 | 
				
			||||||
		this.nav.select(navItem);
 | 
							this.nav.select(navItem);
 | 
				
			||||||
		switch (navItem) {
 | 
							switch (navItem) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@ const BaseSection = require(__dirname + '/base-section.js');
 | 
				
			|||||||
const DomainUtil = require(__dirname + '/../../utils/domain-util.js');
 | 
					const DomainUtil = require(__dirname + '/../../utils/domain-util.js');
 | 
				
			||||||
const ServerInfoForm = require(__dirname + '/server-info-form.js');
 | 
					const ServerInfoForm = require(__dirname + '/server-info-form.js');
 | 
				
			||||||
const NewServerForm = require(__dirname + '/new-server-form.js');
 | 
					const NewServerForm = require(__dirname + '/new-server-form.js');
 | 
				
			||||||
 | 
					const CreateOrganziation = require(__dirname + '/create-new-org.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ServersSection extends BaseSection {
 | 
					class ServersSection extends BaseSection {
 | 
				
			||||||
	constructor(props) {
 | 
						constructor(props) {
 | 
				
			||||||
@@ -18,6 +19,7 @@ class ServersSection extends BaseSection {
 | 
				
			|||||||
				<div id="new-server-container"></div>
 | 
									<div id="new-server-container"></div>
 | 
				
			||||||
				<div class="title" id="existing-servers"></div>
 | 
									<div class="title" id="existing-servers"></div>
 | 
				
			||||||
				<div id="server-info-container"></div>
 | 
									<div id="server-info-container"></div>
 | 
				
			||||||
 | 
									<div id="create-organization-container"></div>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		`;
 | 
							`;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -41,6 +43,9 @@ class ServersSection extends BaseSection {
 | 
				
			|||||||
		this.$existingServers.innerHTML = servers.length === 0 ? '' : 'Existing Servers';
 | 
							this.$existingServers.innerHTML = servers.length === 0 ? '' : 'Existing Servers';
 | 
				
			||||||
		this.initNewServerForm();
 | 
							this.initNewServerForm();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.$createOrganizationContainer = document.getElementById('create-organization-container');
 | 
				
			||||||
 | 
							this.initCreateNewOrganization();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (let i = 0; i < servers.length; i++) {
 | 
							for (let i = 0; i < servers.length; i++) {
 | 
				
			||||||
			new ServerInfoForm({
 | 
								new ServerInfoForm({
 | 
				
			||||||
				$root: this.$serverInfoContainer,
 | 
									$root: this.$serverInfoContainer,
 | 
				
			||||||
@@ -51,6 +56,12 @@ class ServersSection extends BaseSection {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initCreateNewOrganization() {
 | 
				
			||||||
 | 
							new CreateOrganziation({
 | 
				
			||||||
 | 
								$root: this.$createOrganizationContainer
 | 
				
			||||||
 | 
							}).init();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	initNewServerForm() {
 | 
						initNewServerForm() {
 | 
				
			||||||
		new NewServerForm({
 | 
							new NewServerForm({
 | 
				
			||||||
			$root: this.$newServerContainer,
 | 
								$root: this.$newServerContainer,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,10 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { ipcRenderer } = require('electron');
 | 
					const { ipcRenderer } = require('electron');
 | 
				
			||||||
const { spellChecker } = require('./spellchecker');
 | 
					const SetupSpellChecker = require('./spellchecker');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ConfigUtil = require(__dirname + '/utils/config-util.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// eslint-disable-next-line import/no-unassigned-import
 | 
					// eslint-disable-next-line import/no-unassigned-import
 | 
				
			||||||
require('./notification');
 | 
					require('./notification');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,8 +35,15 @@ process.once('loaded', () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// To prevent failing this script on linux we need to load it after the document loaded
 | 
					// To prevent failing this script on linux we need to load it after the document loaded
 | 
				
			||||||
document.addEventListener('DOMContentLoaded', () => {
 | 
					document.addEventListener('DOMContentLoaded', () => {
 | 
				
			||||||
	// Init spellchecker
 | 
						// Get the default language of the server
 | 
				
			||||||
	spellChecker();
 | 
						const serverLanguage = page_params.default_language; // eslint-disable-line no-undef, camelcase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (serverLanguage) {
 | 
				
			||||||
 | 
							// Set spellcheker language
 | 
				
			||||||
 | 
							ConfigUtil.setConfigItem('spellcheckerLanguage', serverLanguage);
 | 
				
			||||||
 | 
							// Init spellchecker
 | 
				
			||||||
 | 
							SetupSpellChecker.init();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// redirect users to network troubleshooting page
 | 
						// redirect users to network troubleshooting page
 | 
				
			||||||
	const getRestartButton = document.querySelector('.restart_get_events_button');
 | 
						const getRestartButton = document.querySelector('.restart_get_events_button');
 | 
				
			||||||
@@ -43,3 +53,10 @@ document.addEventListener('DOMContentLoaded', () => {
 | 
				
			|||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Clean up spellchecker events after you navigate away from this page;
 | 
				
			||||||
 | 
					// otherwise, you may experience errors
 | 
				
			||||||
 | 
					window.addEventListener('beforeunload', () => {
 | 
				
			||||||
 | 
						SetupSpellChecker.unsubscribeSpellChecker();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,29 +1,56 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const {SpellCheckHandler, ContextMenuListener, ContextMenuBuilder} = require('electron-spellchecker');
 | 
					const { SpellCheckHandler, ContextMenuListener, ContextMenuBuilder } = require('electron-spellchecker');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function spellChecker() {
 | 
					const ConfigUtil = require(__dirname + '/utils/config-util.js');
 | 
				
			||||||
	// Implement spellcheck using electron api
 | 
					 | 
				
			||||||
	window.spellCheckHandler = new SpellCheckHandler();
 | 
					 | 
				
			||||||
	window.spellCheckHandler.attachToInput();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Start off as US English
 | 
					class SetupSpellChecker {
 | 
				
			||||||
	window.spellCheckHandler.switchLanguage('en-US');
 | 
						init() {
 | 
				
			||||||
 | 
							if (ConfigUtil.getConfigItem('enableSpellchecker')) {
 | 
				
			||||||
 | 
								this.enableSpellChecker();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							this.enableContextMenu();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const contextMenuBuilder = new ContextMenuBuilder(window.spellCheckHandler);
 | 
						enableSpellChecker() {
 | 
				
			||||||
	const contextMenuListener = new ContextMenuListener(info => {
 | 
							try {
 | 
				
			||||||
		contextMenuBuilder.showPopupMenu(info);
 | 
								this.SpellCheckHandler = new SpellCheckHandler();
 | 
				
			||||||
	});
 | 
							} catch (err) {
 | 
				
			||||||
 | 
								console.log(err);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Clean up events after you navigate away from this page;
 | 
						enableContextMenu() {
 | 
				
			||||||
	// otherwise, you may experience errors
 | 
							if (this.SpellCheckHandler) {
 | 
				
			||||||
	window.addEventListener('beforeunload', () => {
 | 
								this.SpellCheckHandler.attachToInput();
 | 
				
			||||||
	// eslint-disable-next-line no-undef
 | 
					
 | 
				
			||||||
		spellCheckHandler.unsubscribe();
 | 
								const userLanguage = ConfigUtil.getConfigItem('spellcheckerLanguage');
 | 
				
			||||||
		contextMenuListener.unsubscribe();
 | 
					
 | 
				
			||||||
	});
 | 
								// eslint-disable-next-line no-unused-expressions
 | 
				
			||||||
 | 
								process.platform === 'darwin' ?
 | 
				
			||||||
 | 
									// On macOS, spellchecker fails to auto-detect the lanugage user is typing in
 | 
				
			||||||
 | 
									// that's why we need to mention it explicitly
 | 
				
			||||||
 | 
									this.SpellCheckHandler.switchLanguage(userLanguage) :
 | 
				
			||||||
 | 
									// On Linux and Windows, spellchecker can automatically detects the language the user is typing in
 | 
				
			||||||
 | 
									// and silently switches on the fly; thus we can start off as US English
 | 
				
			||||||
 | 
									this.SpellCheckHandler.switchLanguage('en-US');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const contextMenuBuilder = new ContextMenuBuilder(this.SpellCheckHandler);
 | 
				
			||||||
 | 
							this.contextMenuListener = new ContextMenuListener(info => {
 | 
				
			||||||
 | 
								contextMenuBuilder.showPopupMenu(info);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unsubscribeSpellChecker() {
 | 
				
			||||||
 | 
							// eslint-disable-next-line no-undef
 | 
				
			||||||
 | 
							if (this.SpellCheckHandler) {
 | 
				
			||||||
 | 
								this.SpellCheckHandler.unsubscribe();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (this.contextMenuListener) {
 | 
				
			||||||
 | 
								this.contextMenuListener.unsubscribe();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = new SetupSpellChecker();
 | 
				
			||||||
	spellChecker
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -110,8 +110,10 @@ class DomainUtil {
 | 
				
			|||||||
		return new Promise((resolve, reject) => {
 | 
							return new Promise((resolve, reject) => {
 | 
				
			||||||
			request(checkDomain, (error, response) => {
 | 
								request(checkDomain, (error, response) => {
 | 
				
			||||||
				const certsError =
 | 
									const certsError =
 | 
				
			||||||
					['Error: self signed certificate',
 | 
										[
 | 
				
			||||||
						'Error: unable to verify the first certificate'
 | 
											'Error: self signed certificate',
 | 
				
			||||||
 | 
											'Error: unable to verify the first certificate',
 | 
				
			||||||
 | 
											'Error: unable to get local issuer certificate'
 | 
				
			||||||
					];
 | 
										];
 | 
				
			||||||
				if (!error && response.statusCode !== 404) {
 | 
									if (!error && response.statusCode !== 404) {
 | 
				
			||||||
					// Correct
 | 
										// Correct
 | 
				
			||||||
@@ -152,7 +154,9 @@ class DomainUtil {
 | 
				
			|||||||
						});
 | 
											});
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					reject('Not a valid Zulip server');
 | 
										const invalidZulipServerError = `${domain} does not appear to be a valid Zulip server. Make sure that \
 | 
				
			||||||
 | 
										(1) you can connect to that URL in a web browser and \n (2) if you need a proxy to connect to the Internet, that you've configured your proxy in the Network settings`;
 | 
				
			||||||
 | 
										reject(invalidZulipServerError);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
@@ -166,7 +170,9 @@ class DomainUtil {
 | 
				
			|||||||
					const data = JSON.parse(response.body);
 | 
										const data = JSON.parse(response.body);
 | 
				
			||||||
					if (data.hasOwnProperty('realm_icon') && data.realm_icon) {
 | 
										if (data.hasOwnProperty('realm_icon') && data.realm_icon) {
 | 
				
			||||||
						resolve({
 | 
											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,
 | 
												url: data.realm_uri,
 | 
				
			||||||
							alias: data.realm_name
 | 
												alias: data.realm_name
 | 
				
			||||||
						});
 | 
											});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,13 +13,14 @@
 | 
				
			|||||||
    <div class="popup">
 | 
					    <div class="popup">
 | 
				
			||||||
      <span class="popuptext hidden" id="fullscreen-popup"></span>
 | 
					      <span class="popuptext hidden" id="fullscreen-popup"></span>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
  <div id="sidebar">
 | 
					  <div id="sidebar" class="toggle-sidebar">
 | 
				
			||||||
    <div id="view-controls-container">
 | 
					    <div id="view-controls-container">
 | 
				
			||||||
      <div id="tabs-container"></div>
 | 
					      <div id="tabs-container"></div>
 | 
				
			||||||
      <div id="add-tab" class="tab functional-tab">
 | 
					      <div id="add-tab" class="tab functional-tab">
 | 
				
			||||||
        <div class="server-tab" id="add-action">
 | 
					        <div class="server-tab" id="add-action">
 | 
				
			||||||
          <i class="material-icons">add</i>
 | 
					          <i class="material-icons">add</i>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					        <span id="add-server-tooltip" style="display:none">Add organization</span>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div id="actions-container">
 | 
					    <div id="actions-container">
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								app/resources/tray/trayosx@2x.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/resources/tray/trayosx@2x.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/resources/tray/trayosx@3x.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/resources/tray/trayosx@3x.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								app/resources/tray/trayosx@4x.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/resources/tray/trayosx@4x.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 3.8 KiB  | 
							
								
								
									
										10
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								package.json
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "zulip",
 | 
					  "name": "zulip",
 | 
				
			||||||
  "productName": "Zulip",
 | 
					  "productName": "Zulip",
 | 
				
			||||||
  "version": "1.4.0",
 | 
					  "version": "1.6.0-beta",
 | 
				
			||||||
  "main": "./app/main",
 | 
					  "main": "./app/main",
 | 
				
			||||||
  "description": "Zulip Desktop App",
 | 
					  "description": "Zulip Desktop App",
 | 
				
			||||||
  "license": "Apache-2.0",
 | 
					  "license": "Apache-2.0",
 | 
				
			||||||
@@ -20,6 +20,7 @@
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "start": "electron app --disable-http-cache",
 | 
					    "start": "electron app --disable-http-cache",
 | 
				
			||||||
 | 
					    "reinstall": "rm -rf node_modules; rm -rf app/node_modules; npm install",
 | 
				
			||||||
    "postinstall": "electron-builder install-app-deps",
 | 
					    "postinstall": "electron-builder install-app-deps",
 | 
				
			||||||
    "test": "xo",
 | 
					    "test": "xo",
 | 
				
			||||||
    "dev": "gulp dev",
 | 
					    "dev": "gulp dev",
 | 
				
			||||||
@@ -105,8 +106,8 @@
 | 
				
			|||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "assert": "1.4.1",
 | 
					    "assert": "1.4.1",
 | 
				
			||||||
    "devtron": "1.4.0",
 | 
					    "devtron": "1.4.0",
 | 
				
			||||||
    "electron-builder": "19.27.3",
 | 
					    "electron-builder": "19.45.5",
 | 
				
			||||||
    "electron": "1.6.11",
 | 
					    "electron": "1.6.14",
 | 
				
			||||||
    "electron-connect": "0.6.2",
 | 
					    "electron-connect": "0.6.2",
 | 
				
			||||||
    "gulp": "3.9.1",
 | 
					    "gulp": "3.9.1",
 | 
				
			||||||
    "gulp-mocha": "4.3.1",
 | 
					    "gulp-mocha": "4.3.1",
 | 
				
			||||||
@@ -114,7 +115,8 @@
 | 
				
			|||||||
    "chai": "4.1.1",
 | 
					    "chai": "4.1.1",
 | 
				
			||||||
    "spectron": "3.7.2",
 | 
					    "spectron": "3.7.2",
 | 
				
			||||||
    "xo": "0.18.2",
 | 
					    "xo": "0.18.2",
 | 
				
			||||||
    "pre-commit": "1.2.2"
 | 
					    "pre-commit": "1.2.2",
 | 
				
			||||||
 | 
					    "electron-debug": "1.4.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "xo": {
 | 
					  "xo": {
 | 
				
			||||||
    "parserOptions": {
 | 
					    "parserOptions": {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user