mirror of
				https://github.com/zulip/zulip-desktop.git
				synced 2025-11-04 05:53:21 +00:00 
			
		
		
		
	Compare commits
	
		
			28 Commits
		
	
	
		
			v1.5.0
			...
			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 | 
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -23,4 +23,6 @@ yarn-error.log*
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# miscellaneous
 | 
					# miscellaneous
 | 
				
			||||||
.idea
 | 
					.idea
 | 
				
			||||||
config.gypi
 | 
					config.gypi
 | 
				
			||||||
 | 
					.python-version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
2.7.9
 | 
					 | 
				
			||||||
@@ -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;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
'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 { crashHandler } = require('./crash-reporter');
 | 
				
			||||||
@@ -14,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;
 | 
				
			||||||
@@ -94,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');
 | 
				
			||||||
@@ -124,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-current-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();
 | 
				
			||||||
@@ -165,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();
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
@@ -232,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) => {
 | 
				
			||||||
@@ -251,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;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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.5.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",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,7 +83,6 @@ class ServerManagerView {
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			this.openSettings('Servers');
 | 
								this.openSettings('Servers');
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ipcRenderer.send('local-shortcuts', true);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	initServer(server, index) {
 | 
						initServer(server, index) {
 | 
				
			||||||
@@ -257,9 +256,6 @@ 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() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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, '');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,9 +29,13 @@ class GeneralSection extends BaseSection {
 | 
				
			|||||||
						<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">
 | 
				
			||||||
@@ -57,6 +61,10 @@ 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">
 | 
				
			||||||
@@ -74,12 +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.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() {
 | 
				
			||||||
@@ -108,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'),
 | 
				
			||||||
@@ -170,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());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											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  | 
@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "zulip",
 | 
					  "name": "zulip",
 | 
				
			||||||
  "productName": "Zulip",
 | 
					  "productName": "Zulip",
 | 
				
			||||||
  "version": "1.5.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",
 | 
				
			||||||
@@ -106,7 +106,7 @@
 | 
				
			|||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "assert": "1.4.1",
 | 
					    "assert": "1.4.1",
 | 
				
			||||||
    "devtron": "1.4.0",
 | 
					    "devtron": "1.4.0",
 | 
				
			||||||
    "electron-builder": "19.29.1",
 | 
					    "electron-builder": "19.45.5",
 | 
				
			||||||
    "electron": "1.6.14",
 | 
					    "electron": "1.6.14",
 | 
				
			||||||
    "electron-connect": "0.6.2",
 | 
					    "electron-connect": "0.6.2",
 | 
				
			||||||
    "gulp": "3.9.1",
 | 
					    "gulp": "3.9.1",
 | 
				
			||||||
@@ -115,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