mirror of
				https://github.com/zulip/zulip-desktop.git
				synced 2025-10-31 12:03:39 +00:00 
			
		
		
		
	Compare commits
	
		
			9 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 4e21ff9d6c | ||
|  | 037cb227da | ||
|  | 88b764dcc9 | ||
|  | 9fe72c0d21 | ||
|  | 31b00ee6a6 | ||
|  | ecec7f8b89 | ||
|  | 139496b716 | ||
|  | f6239132c1 | ||
|  | 6451373ff6 | 
| @@ -254,6 +254,7 @@ app.on('ready', () => { | ||||
| 	ipcMain.on('toggle-menubar', (event, showMenubar) => { | ||||
| 		mainWindow.setAutoHideMenuBar(showMenubar); | ||||
| 		mainWindow.setMenuBarVisibility(!showMenubar); | ||||
| 		page.send('toggle-autohide-menubar', showMenubar, true); | ||||
| 	}); | ||||
|  | ||||
| 	ipcMain.on('update-badge', (event, messageCount) => { | ||||
|   | ||||
| @@ -162,6 +162,20 @@ class AppMenu { | ||||
| 					ConfigUtil.setConfigItem('showSidebar', newValue); | ||||
| 				} | ||||
| 			} | ||||
| 		}, { | ||||
| 			label: 'Auto hide Menu bar', | ||||
| 			checked: ConfigUtil.getConfigItem('autoHideMenubar', false), | ||||
| 			visible: process.platform !== 'darwin', | ||||
| 			click(item, focusedWindow) { | ||||
| 				if (focusedWindow) { | ||||
| 					const newValue = !ConfigUtil.getConfigItem('autoHideMenubar'); | ||||
| 					focusedWindow.setAutoHideMenuBar(newValue); | ||||
| 					focusedWindow.setMenuBarVisibility(!newValue); | ||||
| 					focusedWindow.webContents.send('toggle-autohide-menubar', newValue); | ||||
| 					ConfigUtil.setConfigItem('autoHideMenubar', newValue); | ||||
| 				} | ||||
| 			}, | ||||
| 			type: 'checkbox' | ||||
| 		}]; | ||||
| 	} | ||||
|  | ||||
| @@ -181,8 +195,10 @@ class AppMenu { | ||||
| 			}, | ||||
| 			{ | ||||
| 				label: `Help Center`, | ||||
| 				click() { | ||||
| 					shell.openExternal('https://zulipchat.com/help/'); | ||||
| 				click(focusedWindow) { | ||||
| 					if (focusedWindow) { | ||||
| 						AppMenu.sendAction('open-help'); | ||||
| 					} | ||||
| 				} | ||||
| 			}, { | ||||
| 				label: 'Report an Issue', | ||||
|   | ||||
							
								
								
									
										2
									
								
								app/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								app/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "zulip", | ||||
|   "version": "2.5.0-beta", | ||||
|   "version": "3.0.0", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
|   | ||||
| @@ -267,6 +267,18 @@ body { | ||||
|     margin-bottom: 5px; | ||||
| } | ||||
|  | ||||
| .refresh { | ||||
|     animation: rotate-loader 1s linear infinite; | ||||
| } | ||||
|  | ||||
| @keyframes rotate-loader { | ||||
|     from { | ||||
|         transform: rotate(0); | ||||
|     } | ||||
|     to { | ||||
|         transform: rotate(-360deg); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /******************* | ||||
|   *   Webview Area  * | ||||
| @@ -328,6 +340,7 @@ webview.focus { | ||||
|  | ||||
| /* Tooltip styling */ | ||||
|  | ||||
| #loading-tooltip, | ||||
| #dnd-tooltip, | ||||
| #back-tooltip, | ||||
| #reload-tooltip, | ||||
| @@ -346,6 +359,7 @@ webview.focus { | ||||
|     font-size: 14px; | ||||
| } | ||||
|  | ||||
| #loading-tooltip::after, | ||||
| #dnd-tooltip::after, | ||||
| #back-tooltip::after, | ||||
| #reload-tooltip::after, | ||||
|   | ||||
| @@ -259,6 +259,10 @@ img.server-info-icon { | ||||
|     border: rgba(78, 191, 172, 1.000) 2px solid; | ||||
| } | ||||
|  | ||||
| .invalid-input-value:focus { | ||||
|     border: rgba(239, 83, 80, 1) 2px solid; | ||||
| } | ||||
|  | ||||
| .manual-proxy-block { | ||||
|     width: 96%; | ||||
| } | ||||
|   | ||||
| @@ -94,6 +94,7 @@ class WebView extends BaseComponent { | ||||
| 				this.$el.classList.add('onload'); | ||||
| 			} | ||||
| 			this.loading = false; | ||||
| 			this.props.switchLoading(false, this.props.url); | ||||
| 			this.show(); | ||||
|  | ||||
| 			// Refocus text boxes after reload | ||||
| @@ -112,6 +113,10 @@ class WebView extends BaseComponent { | ||||
| 		}); | ||||
|  | ||||
| 		this.$el.addEventListener('did-start-loading', () => { | ||||
| 			const isSettingPage = this.props.url.includes('renderer/preference.html'); | ||||
| 			if (!isSettingPage) { | ||||
| 				this.props.switchLoading(true, this.props.url); | ||||
| 			} | ||||
| 			let userAgent = SystemUtil.getUserAgent(); | ||||
| 			if (!userAgent) { | ||||
| 				SystemUtil.setUserAgent(this.$el.getUserAgent()); | ||||
| @@ -119,6 +124,10 @@ class WebView extends BaseComponent { | ||||
| 			} | ||||
| 			this.$el.setUserAgent(userAgent); | ||||
| 		}); | ||||
|  | ||||
| 		this.$el.addEventListener('did-stop-loading', () => { | ||||
| 			this.props.switchLoading(false, this.props.url); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	getBadgeCount(title) { | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| 'use strict'; | ||||
|  | ||||
| const { ipcRenderer, remote, clipboard } = require('electron'); | ||||
| const { ipcRenderer, remote, clipboard, shell } = require('electron'); | ||||
| const isDev = require('electron-is-dev'); | ||||
|  | ||||
| const { session, app, Menu, dialog } = remote; | ||||
| @@ -31,6 +31,7 @@ class ServerManagerView { | ||||
|  | ||||
| 		const $actionsContainer = document.getElementById('actions-container'); | ||||
| 		this.$reloadButton = $actionsContainer.querySelector('#reload-action'); | ||||
| 		this.$loadingIndicator = $actionsContainer.querySelector('#loading-action'); | ||||
| 		this.$settingsButton = $actionsContainer.querySelector('#settings-action'); | ||||
| 		this.$webviewsContainer = document.getElementById('webviews-container'); | ||||
| 		this.$backButton = $actionsContainer.querySelector('#back-action'); | ||||
| @@ -38,6 +39,7 @@ class ServerManagerView { | ||||
|  | ||||
| 		this.$addServerTooltip = document.getElementById('add-server-tooltip'); | ||||
| 		this.$reloadTooltip = $actionsContainer.querySelector('#reload-tooltip'); | ||||
| 		this.$loadingTooltip = $actionsContainer.querySelector('#loading-tooltip'); | ||||
| 		this.$settingsTooltip = $actionsContainer.querySelector('#setting-tooltip'); | ||||
| 		this.$serverIconTooltip = document.getElementsByClassName('server-tooltip'); | ||||
| 		this.$backTooltip = $actionsContainer.querySelector('#back-tooltip'); | ||||
| @@ -49,6 +51,7 @@ class ServerManagerView { | ||||
| 		this.$fullscreenEscapeKey = process.platform === 'darwin' ? '^⌘F' : 'F11'; | ||||
| 		this.$fullscreenPopup.innerHTML = `Press ${this.$fullscreenEscapeKey} to exit full screen`; | ||||
|  | ||||
| 		this.loading = {}; | ||||
| 		this.activeTabIndex = -1; | ||||
| 		this.tabs = []; | ||||
| 		this.functionalTabs = {}; | ||||
| @@ -100,6 +103,7 @@ class ServerManagerView { | ||||
| 	initDefaultSettings() { | ||||
| 		// Default settings which should be respected | ||||
| 		const settingOptions = { | ||||
| 			autoHideMenubar: false, | ||||
| 			trayIcon: true, | ||||
| 			useManualProxy: false, | ||||
| 			useSystemProxy: false, | ||||
| @@ -192,12 +196,21 @@ class ServerManagerView { | ||||
| 				isActive: () => { | ||||
| 					return index === this.activeTabIndex; | ||||
| 				}, | ||||
| 				switchLoading: (loading, url) => { | ||||
| 					if (!loading && this.loading[url]) { | ||||
| 						this.loading[url] = false; | ||||
| 					} else if (loading && !this.loading[url]) { | ||||
| 						this.loading[url] = true; | ||||
| 					} | ||||
| 					this.showLoading(this.loading[this.tabs[this.activeTabIndex].webview.props.url]); | ||||
| 				}, | ||||
| 				onNetworkError: this.openNetworkTroubleshooting.bind(this), | ||||
| 				onTitleChange: this.updateBadge.bind(this), | ||||
| 				nodeIntegration: false, | ||||
| 				preload: true | ||||
| 			}) | ||||
| 		})); | ||||
| 		this.loading[server.url] = true; | ||||
| 	} | ||||
|  | ||||
| 	initActions() { | ||||
| @@ -238,6 +251,7 @@ class ServerManagerView { | ||||
| 		}); | ||||
|  | ||||
| 		this.sidebarHoverEvent(this.$addServerButton, this.$addServerTooltip, true); | ||||
| 		this.sidebarHoverEvent(this.$loadingIndicator, this.$loadingTooltip); | ||||
| 		this.sidebarHoverEvent(this.$settingsButton, this.$settingsTooltip); | ||||
| 		this.sidebarHoverEvent(this.$reloadButton, this.$reloadTooltip); | ||||
| 		this.sidebarHoverEvent(this.$backButton, this.$backTooltip); | ||||
| @@ -255,6 +269,10 @@ class ServerManagerView { | ||||
| 		return currentIndex; | ||||
| 	} | ||||
|  | ||||
| 	getCurrentActiveServer() { | ||||
| 		return this.tabs[this.activeTabIndex].webview.props.url; | ||||
| 	} | ||||
|  | ||||
| 	displayInitialCharLogo($img, index) { | ||||
| 		/* | ||||
| 			index parameter needed because webview[data-tab-id] can increment | ||||
| @@ -344,6 +362,14 @@ class ServerManagerView { | ||||
| 				isActive: () => { | ||||
| 					return this.functionalTabs[tabProps.name] === this.activeTabIndex; | ||||
| 				}, | ||||
| 				switchLoading: (loading, url) => { | ||||
| 					if (!loading && this.loading[url]) { | ||||
| 						this.loading[url] = false; | ||||
| 					} else if (loading && !this.loading[url]) { | ||||
| 						this.loading[url] = true; | ||||
| 					} | ||||
| 					this.showLoading(this.loading[this.tabs[this.activeTabIndex].webview.props.url]); | ||||
| 				}, | ||||
| 				onNetworkError: this.openNetworkTroubleshooting.bind(this), | ||||
| 				onTitleChange: this.updateBadge.bind(this), | ||||
| 				nodeIntegration: true, | ||||
| @@ -435,6 +461,8 @@ class ServerManagerView { | ||||
| 		this.activeTabIndex = index; | ||||
| 		this.tabs[index].activate(); | ||||
|  | ||||
| 		this.showLoading(this.loading[this.tabs[this.activeTabIndex].webview.props.url]); | ||||
|  | ||||
| 		ipcRenderer.send('update-menu', { | ||||
| 			// JSON stringify this.tabs to avoid a crash | ||||
| 			// util.inspect is being used to handle circular references | ||||
| @@ -445,6 +473,16 @@ class ServerManagerView { | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	showLoading(loading) { | ||||
| 		if (!loading) { | ||||
| 			this.$reloadButton.removeAttribute('style'); | ||||
| 			this.$loadingIndicator.style.display = 'none'; | ||||
| 		} else if (loading) { | ||||
| 			this.$reloadButton.style.display = 'none'; | ||||
| 			this.$loadingIndicator.removeAttribute('style'); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	destroyTab(name, index) { | ||||
| 		if (this.tabs[index].webview.loading) { | ||||
| 			return; | ||||
| @@ -505,6 +543,15 @@ class ServerManagerView { | ||||
| 		ipcRenderer.send('update-badge', messageCountAll); | ||||
| 	} | ||||
|  | ||||
| 	updateGeneralSettings(setting, value) { | ||||
| 		const selector = 'webview:not([class*=disabled])'; | ||||
| 		const webview = document.querySelector(selector); | ||||
| 		if (webview) { | ||||
| 			const webContents = webview.getWebContents(); | ||||
| 			webContents.send(setting, value); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	toggleSidebar(show) { | ||||
| 		if (show) { | ||||
| 			this.$sidebar.classList.remove('sidebar-hide'); | ||||
| @@ -580,6 +627,12 @@ class ServerManagerView { | ||||
|  | ||||
| 		ipcRenderer.on('open-about', this.openAbout.bind(this)); | ||||
|  | ||||
| 		ipcRenderer.on('open-help', () => { | ||||
| 			// Open help page of current active server | ||||
| 			const helpPage = this.getCurrentActiveServer() + '/help'; | ||||
| 			shell.openExternal(helpPage); | ||||
| 		}); | ||||
|  | ||||
| 		ipcRenderer.on('reload-viewer', this.reloadView.bind(this, this.tabs[this.activeTabIndex].props.index)); | ||||
|  | ||||
| 		ipcRenderer.on('reload-current-viewer', this.reloadCurrentView.bind(this)); | ||||
| @@ -614,10 +667,7 @@ class ServerManagerView { | ||||
| 			this.toggleSidebar(show); | ||||
|  | ||||
| 			// Toggle sidebar switch in the general settings | ||||
| 			const selector = 'webview:not([class*=disabled])'; | ||||
| 			const webview = document.querySelector(selector); | ||||
| 			const webContents = webview.getWebContents(); | ||||
| 			webContents.send('toggle-sidebar-setting', show); | ||||
| 			this.updateGeneralSettings('toggle-sidebar-setting', show); | ||||
| 		}); | ||||
|  | ||||
| 		ipcRenderer.on('toggle-silent', (event, state) => { | ||||
| @@ -634,6 +684,17 @@ class ServerManagerView { | ||||
| 			}); | ||||
| 		}); | ||||
|  | ||||
| 		ipcRenderer.on('toggle-autohide-menubar', (event, autoHideMenubar, updateMenu) => { | ||||
| 			if (updateMenu) { | ||||
| 				ipcRenderer.send('update-menu', { | ||||
| 					tabs: this.tabsForIpc, | ||||
| 					activeTabIndex: this.activeTabIndex | ||||
| 				}); | ||||
| 				return; | ||||
| 			} | ||||
| 			this.updateGeneralSettings('toggle-menubar-setting', autoHideMenubar); | ||||
| 		}); | ||||
|  | ||||
| 		ipcRenderer.on('toggle-dnd', (event, state, newSettings) => { | ||||
| 			this.toggleDNDButton(state); | ||||
| 			ipcRenderer.send('forward-message', 'toggle-silent', newSettings.silent); | ||||
| @@ -735,7 +796,7 @@ class ServerManagerView { | ||||
| 		}); | ||||
|  | ||||
| 		ipcRenderer.on('copy-zulip-url', () => { | ||||
| 			clipboard.writeText(DomainUtil.getDomain(this.activeTabIndex).url); | ||||
| 			clipboard.writeText(this.getCurrentActiveServer()); | ||||
| 		}); | ||||
|  | ||||
| 		ipcRenderer.on('new-server', () => { | ||||
|   | ||||
| @@ -4,6 +4,7 @@ const BaseSection = require(__dirname + '/base-section.js'); | ||||
| const DomainUtil = require(__dirname + '/../../utils/domain-util.js'); | ||||
| const ServerInfoForm = require(__dirname + '/server-info-form.js'); | ||||
| const AddCertificate = require(__dirname + '/add-certificate.js'); | ||||
| const FindAccounts = require(__dirname + '/find-accounts.js'); | ||||
|  | ||||
| class ConnectedOrgSection extends BaseSection { | ||||
| 	constructor(props) { | ||||
| @@ -20,6 +21,8 @@ class ConnectedOrgSection extends BaseSection { | ||||
| 				<div id="new-org-button"><button class="green sea w-250">Connect to another organization</button></div> | ||||
| 				<div class="page-title">Add Custom Certificates</div> | ||||
| 				<div id="add-certificate-container"></div> | ||||
| 				<div class="page-title">Find accounts by email</div> | ||||
| 				<div id="find-accounts-container"></div> | ||||
| 			</div> | ||||
| 		`; | ||||
| 	} | ||||
| @@ -38,6 +41,7 @@ class ConnectedOrgSection extends BaseSection { | ||||
| 		this.$existingServers = document.getElementById('existing-servers'); | ||||
| 		this.$newOrgButton = document.getElementById('new-org-button'); | ||||
| 		this.$addCertificateContainer = document.getElementById('add-certificate-container'); | ||||
| 		this.$findAccountsContainer = document.getElementById('find-accounts-container'); | ||||
|  | ||||
| 		const noServerText = 'All the connected orgnizations will appear here'; | ||||
| 		// Show noServerText if no servers are there otherwise hide it | ||||
| @@ -59,6 +63,7 @@ class ConnectedOrgSection extends BaseSection { | ||||
| 		}); | ||||
|  | ||||
| 		this.initAddCertificate(); | ||||
| 		this.initFindAccounts(); | ||||
| 	} | ||||
|  | ||||
| 	initAddCertificate() { | ||||
| @@ -67,6 +72,11 @@ class ConnectedOrgSection extends BaseSection { | ||||
| 		}).init(); | ||||
| 	} | ||||
|  | ||||
| 	initFindAccounts() { | ||||
| 		new FindAccounts({ | ||||
| 			$root: this.$findAccountsContainer | ||||
| 		}).init(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| module.exports = ConnectedOrgSection; | ||||
|   | ||||
							
								
								
									
										72
									
								
								app/renderer/js/pages/preference/find-accounts.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								app/renderer/js/pages/preference/find-accounts.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| 'use-strict'; | ||||
|  | ||||
| const { shell } = require('electron'); | ||||
|  | ||||
| const BaseComponent = require(__dirname + '/../../components/base.js'); | ||||
|  | ||||
| class FindAccounts extends BaseComponent { | ||||
| 	constructor(props) { | ||||
| 		super(); | ||||
| 		this.props = props; | ||||
| 	} | ||||
|  | ||||
| 	template() { | ||||
| 		return ` | ||||
| 			<div class="settings-card certificate-card"> | ||||
| 				<div class="certificate-input"> | ||||
| 					<div>Organization URL</div> | ||||
| 					<input class="setting-input-value" value="zulipchat.com"/> | ||||
| 				</div> | ||||
| 				<div class="certificate-input"> | ||||
| 					<button class="green w-150" id="find-accounts-button">Find accounts</button> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		`; | ||||
| 	} | ||||
|  | ||||
| 	init() { | ||||
| 		this.$findAccounts = this.generateNodeFromTemplate(this.template()); | ||||
| 		this.props.$root.appendChild(this.$findAccounts); | ||||
| 		this.$findAccountsButton = this.$findAccounts.querySelector('#find-accounts-button'); | ||||
| 		this.$serverUrlField = this.$findAccounts.querySelectorAll('input.setting-input-value')[0]; | ||||
| 		this.initListeners(); | ||||
| 	} | ||||
|  | ||||
| 	findAccounts(url) { | ||||
| 		if (!url) { | ||||
| 			return; | ||||
| 		} | ||||
| 		if (!url.startsWith('http')) { | ||||
| 			url = 'https://' + url; | ||||
| 		} | ||||
| 		shell.openExternal(url + '/accounts/find'); | ||||
| 	} | ||||
|  | ||||
| 	initListeners() { | ||||
| 		this.$findAccountsButton.addEventListener('click', () => { | ||||
| 			this.findAccounts(this.$serverUrlField.value); | ||||
| 		}); | ||||
|  | ||||
| 		this.$serverUrlField.addEventListener('click', () => { | ||||
| 			if (this.$serverUrlField.value === 'zulipchat.com') { | ||||
| 				this.$serverUrlField.setSelectionRange(0, 0); | ||||
| 			} | ||||
| 		}); | ||||
|  | ||||
| 		this.$serverUrlField.addEventListener('keypress', event => { | ||||
| 			if (event.keyCode === 13) { | ||||
| 				this.findAccounts(this.$serverUrlField.value); | ||||
| 			} | ||||
| 		}); | ||||
|  | ||||
| 		this.$serverUrlField.addEventListener('input', () => { | ||||
| 			if (this.$serverUrlField.value) { | ||||
| 				this.$serverUrlField.classList.remove('invalid-input-value'); | ||||
| 			} else { | ||||
| 				this.$serverUrlField.classList.add('invalid-input-value'); | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| module.exports = FindAccounts; | ||||
| @@ -94,6 +94,10 @@ class PreferenceView extends BaseComponent { | ||||
| 			this.handleToggle('sidebar-option', state); | ||||
| 		}); | ||||
|  | ||||
| 		ipcRenderer.on('toggle-menubar-setting', (event, state) => { | ||||
| 			this.handleToggle('menubar-option', state); | ||||
| 		}); | ||||
|  | ||||
| 		ipcRenderer.on('toggletray', (event, state) => { | ||||
| 			this.handleToggle('tray-option', state); | ||||
| 		}); | ||||
|   | ||||
| @@ -10,6 +10,7 @@ const escape = require('escape-html'); | ||||
| const Logger = require('./logger-util'); | ||||
|  | ||||
| const RequestUtil = require(__dirname + '/../utils/request-util.js'); | ||||
| const Messages = require(__dirname + '/../../../resources/messages.js'); | ||||
|  | ||||
| const logger = new Logger({ | ||||
| 	file: `domain-util.log`, | ||||
| @@ -101,19 +102,50 @@ class DomainUtil { | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	async checkCertError(domain, serverConf, error, silent) { | ||||
| 		if (silent) { | ||||
| 			// since getting server settings has already failed | ||||
| 			return serverConf; | ||||
| 		} else { | ||||
| 			// Report error to sentry to get idea of possible certificate errors | ||||
| 			// users get when adding the servers | ||||
| 			logger.reportSentry(new Error(error)); | ||||
| 			const certErrorMessage = Messages.certErrorMessage(domain, error); | ||||
| 			const certErrorDetail = Messages.certErrorDetail(); | ||||
|  | ||||
| 			const response = await dialog.showMessageBox({ | ||||
| 				type: 'warning', | ||||
| 				buttons: ['Yes', 'No'], | ||||
| 				defaultId: 1, | ||||
| 				message: certErrorMessage, | ||||
| 				detail: certErrorDetail | ||||
| 			}); | ||||
| 			if (response === 0) { | ||||
| 				// set ignoreCerts parameter to true in case user responds with yes | ||||
| 				serverConf.ignoreCerts = true; | ||||
| 				try { | ||||
| 					return await this.getServerSettings(domain, serverConf.ignoreCerts); | ||||
| 				} catch (err) { | ||||
| 					if (error === Messages.noOrgsError(domain)) { | ||||
| 						throw new Error(error); | ||||
| 					} | ||||
| 					return serverConf; | ||||
| 				} | ||||
| 			} else { | ||||
| 				throw new Error('Untrusted certificate.'); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// ignoreCerts parameter helps in fetching server icon and | ||||
| 	// other server details when user chooses to ignore certificate warnings | ||||
| 	checkDomain(domain, ignoreCerts = false, silent = false) { | ||||
| 	async checkDomain(domain, ignoreCerts = false, silent = false) { | ||||
| 		if (!silent && this.duplicateDomain(domain)) { | ||||
| 			// Do not check duplicate in silent mode | ||||
| 			return Promise.reject('This server has been added.'); | ||||
| 			throw new Error('This server has been added.'); | ||||
| 		} | ||||
|  | ||||
| 		domain = this.formatUrl(domain); | ||||
| 		const checkDomain = { | ||||
| 			url: domain + '/static/audio/zulip.ogg', | ||||
| 			...RequestUtil.requestOptions(domain, ignoreCerts) | ||||
| 		}; | ||||
|  | ||||
| 		const serverConf = { | ||||
| 			icon: defaultIconUrl, | ||||
| @@ -122,8 +154,9 @@ class DomainUtil { | ||||
| 			ignoreCerts | ||||
| 		}; | ||||
|  | ||||
| 		return new Promise((resolve, reject) => { | ||||
| 			request(checkDomain, (error, response) => { | ||||
| 		try { | ||||
| 			return await this.getServerSettings(domain, serverConf.ignoreCerts); | ||||
| 		} catch (err) { | ||||
| 			// If the domain contains following strings we just bypass the server | ||||
| 			const whitelistDomains = [ | ||||
| 				'zulipdev.org' | ||||
| @@ -131,61 +164,19 @@ class DomainUtil { | ||||
|  | ||||
| 			// make sure that error is an error or string not undefined | ||||
| 			// so validation does not throw error. | ||||
| 				error = error || ''; | ||||
| 			const error = err || ''; | ||||
|  | ||||
| 			const certsError = error.toString().includes('certificate'); | ||||
| 				if (!error && response.statusCode < 400) { | ||||
| 					// Correct | ||||
| 					this.getServerSettings(domain, serverConf.ignoreCerts).then(serverSettings => { | ||||
| 						resolve(serverSettings); | ||||
| 					}, () => { | ||||
| 						resolve(serverConf); | ||||
| 					}); | ||||
| 				} else if (domain.indexOf(whitelistDomains) >= 0 || certsError) { | ||||
| 					if (silent) { | ||||
| 						this.getServerSettings(domain, serverConf.ignoreCerts).then(serverSettings => { | ||||
| 							resolve(serverSettings); | ||||
| 						}, () => { | ||||
| 							resolve(serverConf); | ||||
| 						}); | ||||
| 					} else { | ||||
| 						// Report error to sentry to get idea of possible certificate errors | ||||
| 						// users get when adding the servers | ||||
| 						logger.reportSentry(new Error(error)); | ||||
| 						const certErrorMessage = `Do you trust certificate from ${domain}? \n ${error}`; | ||||
| 						const certErrorDetail = `The organization you're connecting to is either someone impersonating the Zulip server you entered, or the server you're trying to connect to is configured in an insecure way. | ||||
| 						\nIf you have a valid certificate please add it from Settings>Organizations and try to add the organization again. | ||||
| 						\nUnless you have a good reason to believe otherwise, you should not proceed. | ||||
| 						\nYou can click here if you'd like to proceed with the connection.`; | ||||
|  | ||||
| 						dialog.showMessageBox({ | ||||
| 							type: 'warning', | ||||
| 							buttons: ['Yes', 'No'], | ||||
| 							defaultId: 1, | ||||
| 							message: certErrorMessage, | ||||
| 							detail: certErrorDetail | ||||
| 						}, response => { | ||||
| 							if (response === 0) { | ||||
| 								// set ignoreCerts parameter to true in case user responds with yes | ||||
| 								serverConf.ignoreCerts = true; | ||||
| 								this.getServerSettings(domain, serverConf.ignoreCerts).then(serverSettings => { | ||||
| 									resolve(serverSettings); | ||||
| 								}, () => { | ||||
| 									resolve(serverConf); | ||||
| 								}); | ||||
| 							} else { | ||||
| 								reject('Untrusted Certificate.'); | ||||
| 							} | ||||
| 						}); | ||||
| 			if (domain.indexOf(whitelistDomains) >= 0 || certsError) { | ||||
| 				try { | ||||
| 					return await this.checkCertError(domain, serverConf, error, silent); | ||||
| 				} catch (err) { | ||||
| 					throw err; | ||||
| 				} | ||||
| 			} else { | ||||
| 					const invalidZulipServerError = `${domain} does not appear to be a valid Zulip server. Make sure that \ | ||||
| 					\n (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 \n (3) its a zulip server \ | ||||
| 					\n (4) the server has a valid certificate, you can add custom certificates in Settings>Organizations`; | ||||
| 					reject(invalidZulipServerError); | ||||
| 				throw Messages.invalidZulipServerError(domain); | ||||
| 			} | ||||
| 		} | ||||
| 			}); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	getServerSettings(domain, ignoreCerts = false) { | ||||
| @@ -207,9 +198,11 @@ class DomainUtil { | ||||
| 							alias: escape(data.realm_name), | ||||
| 							ignoreCerts | ||||
| 						}); | ||||
| 					} else { | ||||
| 						reject(Messages.noOrgsError(domain)); | ||||
| 					} | ||||
| 				} else { | ||||
| 					reject('Zulip server version < 1.6.'); | ||||
| 					reject(response); | ||||
| 				} | ||||
| 			}); | ||||
| 		}); | ||||
|   | ||||
| @@ -32,6 +32,10 @@ | ||||
|                         <i class="material-icons md-48">refresh</i> | ||||
|                         <span id="reload-tooltip" style="display:none">Reload</span> | ||||
|                     </div> | ||||
|                     <div class="action-button" id="loading-action"> | ||||
|                         <i class="refresh material-icons md-48">loop</i> | ||||
|                         <span id="loading-tooltip" style="display:none">Loading</span> | ||||
|                     </div> | ||||
|                     <div class="action-button disable" id="back-action"> | ||||
|                         <i class="material-icons md-48">arrow_back</i> | ||||
|                         <span id="back-tooltip" style="display:none">Go Back</span> | ||||
|   | ||||
							
								
								
									
										27
									
								
								app/resources/messages.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								app/resources/messages.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| class Messages { | ||||
| 	invalidZulipServerError(domain) { | ||||
| 		return `${domain} does not appear to be a valid Zulip server. Make sure that | ||||
| 			\n • You can connect to that URL in a web browser.\ | ||||
| 			\n • If you need a proxy to connect to the Internet, that you've configured your proxy in the Network settings.\ | ||||
| 			\n • It's a Zulip server. (The oldest supported version is 1.6).\ | ||||
| 			\n • The server has a valid certificate. (You can add custom certificates in Settings > Organizations).`; | ||||
| 	} | ||||
|  | ||||
| 	noOrgsError(domain) { | ||||
| 		return `${domain} does not have any organizations added.\ | ||||
| 		\nPlease contact your server administrator.`; | ||||
| 	} | ||||
|  | ||||
| 	certErrorMessage(domain, error) { | ||||
| 		return `Do you trust certificate from ${domain}? \n ${error}`; | ||||
| 	} | ||||
|  | ||||
| 	certErrorDetail() { | ||||
| 		return `The organization you're connecting to is either someone impersonating the Zulip server you entered, or the server you're trying to connect to is configured in an insecure way. | ||||
| 		\nIf you have a valid certificate please add it from Settings>Organizations and try to add the organization again. | ||||
| 		\nUnless you have a good reason to believe otherwise, you should not proceed. | ||||
| 		\nYou can click here if you'd like to proceed with the connection.`; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| module.exports = new Messages(); | ||||
							
								
								
									
										71
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								changelog.md
									
									
									
									
									
								
							| @@ -2,6 +2,77 @@ | ||||
|  | ||||
| All notable changes to the Zulip desktop app are documented in this file. | ||||
|  | ||||
| ### v3.0.0 --2019-05-20 | ||||
|  | ||||
| **New features**: | ||||
| * Add context menu in left sidebar. | ||||
| * Enable per-user installation on Windows. | ||||
| * Switch to next server on Ctrl+Tab. | ||||
| * Add option to copy zulip URL. | ||||
| * Allow zoom options from numpad. | ||||
| * Use server language for spellchecker for all platforms. | ||||
| * Allow installing app without admin privileges. | ||||
| * Allow insecure requests on user request. | ||||
| * Unify case across menus and settings. | ||||
|  | ||||
| **Enhancements**: | ||||
| * Remove Found bug button. | ||||
| * Set custom css to false by default. | ||||
| * Disable beta updates if auto updates disabled | ||||
| * Update menu items on setting page. | ||||
| * Include certificates in all requests for icon. | ||||
| * Document show sidebar shortcut properly. | ||||
| * Improve organization page. | ||||
| * Improve wording of adding a new org button. | ||||
| * Increase width of add a new org button. | ||||
| * Add eol for linebreaks on windows. | ||||
| * Teach git to ignore unnecessary binary files. | ||||
| * Send user-agent with request. | ||||
| * Minimize to tray on startup. | ||||
| * Update test config files. | ||||
| * Ensure backward compatibility when using narrow.by_topic. | ||||
| * Use path.sep for path separator to support Windows. | ||||
| * Change the window title to contain active Realm's name. | ||||
| * Use path.basename to get certificate file name. | ||||
| * Disable pdf-viewer window. | ||||
| * Default to starting app on login. | ||||
| * Modify reset app data button. | ||||
| * Add requestOptions to replace request instances. | ||||
| * Workaround buggy focus switching in Electron 3.0.10. | ||||
| * Reorder file menu and add option to Add Organization. | ||||
| * Improve development guide. | ||||
| * Implement CSS linting with stylelint. | ||||
| * Add "role" key to webview property. | ||||
| * Implement HTML Linting with htmlhint and fix indent. | ||||
| * Limit the number of lines in log files. | ||||
| * Fix focus after clicking back button. | ||||
| * Remove minimize and close from File menu. | ||||
| * Add config for installer name. | ||||
|  | ||||
| **Fixes**: | ||||
| * Fix `request` ecdhCurve mismatch errors | ||||
| * Fix typo in network error message. | ||||
| * Fix context menu not working on adding new org. | ||||
| * Fix reply from notification. | ||||
| * Fix shorcut section horizontal alignment. | ||||
| * Fix broken link in docs. | ||||
| * Fix grammatical errors. | ||||
| * Fix typo error in issue template. | ||||
| * Fix text for Toggle DND in sidebar on hover. | ||||
| * Fix focus after soft reload. | ||||
| * Fix tip's place for Windows & Linux. | ||||
|  | ||||
|  | ||||
| **Module updates**: | ||||
| * Update node-json-db to v0.9.1. | ||||
| * Update sentry to v0.12.1. | ||||
| * Update electron-window-state to v5.0.3. | ||||
| * Update electron to v3.0.10. | ||||
| * Update electron-builder to v20.40.2. | ||||
| * Update electron-sentry to v0.14.0. | ||||
| * Update dependencies to fix minor dev security alerts. | ||||
| * Update snap config. | ||||
|  | ||||
| ### v2.3.82 --2018-09-25 | ||||
|  | ||||
| **New features**: | ||||
|   | ||||
							
								
								
									
										202
									
								
								development.md
									
									
									
									
									
								
							
							
						
						
									
										202
									
								
								development.md
									
									
									
									
									
								
							| @@ -1,152 +1,114 @@ | ||||
| # Improve development guide | ||||
| # Development Setup | ||||
|  | ||||
| # Development setup | ||||
| This is a guide to running the Zulip desktop app from source, | ||||
| in order to contribute to developing it. | ||||
|  | ||||
| This is a guide to running the Zulip desktop app from a source tree, in order to contribute to developing it. The Zulip electron development environment can be installed on **macOS, Windows, and Linux** (Debian or Ubuntu recommended). You’ll need at least **2GB of available RAM**. Installing the Zulip electron development environment requires downloading several hundred megabytes of dependencies, so you will need an **active, reasonably fast, internet connection throughout the entire installation processes.** | ||||
| ## Prerequisites | ||||
|  | ||||
| # Set up Git & GitHub | ||||
| To build and run the app from source, you'll need the following: | ||||
|  | ||||
| You can skip this step if you already have Git, GitHub. | ||||
| * [Git](http://git-scm.com/book/en/v2/Getting-Started-Installing-Git) | ||||
|   * Use our [Git Guide](https://zulip.readthedocs.io/en/latest/git/setup.html) to get started with Git and GitHub. | ||||
| * [Node.js](https://nodejs.org) >= v6.9.0 | ||||
|   * [NPM](https://www.npmjs.com/get-npm) and | ||||
|     [node-gyp](https://github.com/nodejs/node-gyp#installation), | ||||
|     if they don't come bundled with your Node.js installation | ||||
| * [Python](https://www.python.org/downloads/release/python-2713/) | ||||
|   (v2.7.x recommended) | ||||
| * A C++ compiler compatible with C++11 | ||||
| * Development headers for the libXext, libXtst, and libxkbfile libraries, which can be installed using apt on Ubuntu using | ||||
|   ```sh | ||||
|   $ sudo apt install libxext-dev libxtst-dev libxkbfile-dev libgconf-2-4 | ||||
|   ``` | ||||
|  | ||||
| Follow our [Git Guide](https://zulip.readthedocs.io/en/latest/git/setup.html) in order to install Git, set up a GitHub account | ||||
| ### Ubuntu/Linux and other Debian-based distributions | ||||
|  | ||||
| On a system running Debian, Ubuntu, or another Debian-based Linux | ||||
| distribution, you can install all dependencies through the package | ||||
| manager (see [here][node-debian] for more on the first command): | ||||
|  | ||||
| # Install Prerequisites | ||||
| ```sh | ||||
| $ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - | ||||
| $ sudo apt install git nodejs python build-essential snapcraft libxext-dev libxtst-dev libxkbfile-dev libgconf-2-4 | ||||
| ``` | ||||
|  | ||||
| Jump to: | ||||
| [node-debian]: https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions | ||||
|  | ||||
| - [MacOS](https://github.com/zulip/zulip-desktop/blob/master/development.md#macos) | ||||
| - [Ubuntu/Debian](https://github.com/zulip/zulip-desktop/blob/master/development.md#ubuntudebian) | ||||
| - [Windows](https://github.com/zulip/zulip-desktop/blob/master/development.md#windows) | ||||
| ### MacOS | ||||
|  | ||||
| On a system running MacOS, you can refer to [official nodejs docs][node-mac] to | ||||
| install nodejs. To ensure Node.js has been installed, run  ```node -v``` in terminal to know your node version. | ||||
|  | ||||
| ## MacOS | ||||
| [node-mac]: https://nodejs.org/en/download/package-manager/#macos | ||||
|  | ||||
| If [NPM](https://www.npmjs.com/get-npm) and [node-gyp](https://github.com/nodejs/node-gyp#installation) don't come bundled with your Node.js installation, you will need to install them manually.  | ||||
|  | ||||
|   **Node JS** | ||||
|   Go to the [Node.js Downloads page](https://nodejs.org/en/download/). Download Node.js for MacOS (`v6.9.0` or above recommended). Run the downloaded Node.js `.pkg` Installer. You're finished! To ensure Node.js has been installed, run `node -v` in your terminal - you should get something like `v6.9.0` or above | ||||
| ### Windows | ||||
|  | ||||
| - Download Node.js for Windows and install it. You can refer to the official docs [here][node-windows] to do so. To ensure Node.js has been installed, run  ```node -v``` in Git Bash to know your node version. | ||||
|  | ||||
|   **if** [**NPM**](https://www.npmjs.com/get-npm) **and** [**node-gyp**](https://github.com/nodejs/node-gyp#installation) **don't come bundled with your Node.js installation, Download manually** | ||||
| [node-windows]: https://nodejs.org/en/download/package-manager/#windows | ||||
|  | ||||
| - Also, install install Windows-Build-Tools to compile native node modules by using | ||||
|   ```sh | ||||
|   $ npm install --global windows-build-tools | ||||
|   ``` | ||||
|  | ||||
|   Now you are ready for next step [: Get Zulip Desktop Code.](https://github.com/zulip/zulip-desktop/blob/master/development.md#get-zulip-desktop-code) | ||||
| ## Download, build, and run | ||||
|  | ||||
| Clone the source locally: | ||||
| ```sh | ||||
| $ git clone https://github.com/zulip/zulip-desktop | ||||
| $ cd zulip-desktop | ||||
| ``` | ||||
|  | ||||
| ## Ubuntu/Debian | ||||
| Install project dependencies: | ||||
| ```sh | ||||
| $ npm install | ||||
| ``` | ||||
|  | ||||
| Start the app: | ||||
| ```sh | ||||
| $ npm start | ||||
| ``` | ||||
|  | ||||
| If you’re in a hurry, you can copy and paste the following into your terminal | ||||
| Start and watch changes: | ||||
| ```sh | ||||
| $ npm run dev | ||||
| ``` | ||||
|  | ||||
|     sudo apt install git nodejs node-gyp python build-essential snapcraft libxext-dev libxtst-dev lib   xkbfile-dev libgconf-2-4 | ||||
| Run tests: | ||||
| ```sh | ||||
| $ npm test | ||||
| ``` | ||||
|  | ||||
| after pasting you can jump to next step [: Get Zulip Desktop Code](https://github.com/zulip/zulip-desktop/blob/master/development.md#get-zulip-desktop-code). | ||||
| ## How to contribute? | ||||
|  | ||||
| Feel free to fork this repository, test it locally and then report any bugs | ||||
| you find in the [issue tracker](https://github.com/zulip/zulip-desktop/issues).  | ||||
|  | ||||
| **For a step-by-step explanation, read on.** | ||||
| You can read more about making contributions in our [Contributing Guide](./CONTRIBUTING.md). | ||||
|  | ||||
| 1. **Node JS** | ||||
| ## Troubleshooting | ||||
|  | ||||
| 	`$ sudo apt-get install nodejs` | ||||
| If you have any problems running the app, see the [most common | ||||
| issues](./troubleshooting.md). | ||||
|  | ||||
| 2. **Install** [**Node-gyp**](https://github.com/nodejs/node-gyp#installation) | ||||
| ## Making a release | ||||
|  | ||||
| 3. **Python (v2.7.x recommended)** | ||||
| To package the app into an installer: | ||||
| ``` | ||||
| npm run dist | ||||
| ``` | ||||
|  | ||||
| 	`$ sudo apt install python2.7` | ||||
| This command will produce distributable packages or installers for the | ||||
| operating system you're running on: | ||||
| * on Windows, a .7z nsis file and a .exe WebSetup file  | ||||
| * on macOS, a `.dmg` file | ||||
| * on Linux, a plain `.zip` file as well as a `.deb` file, `.snap` file and an | ||||
|   `AppImage` file. | ||||
|  | ||||
| 4. **C++ compiler compatible with C++11** | ||||
| To generate all three types of files, you will need all three operating | ||||
| systems. | ||||
|  | ||||
| 	`$ sudo apt install build-essential` | ||||
|  | ||||
| 5. **Snapcraft** | ||||
|  | ||||
| 	`$ sudo apt install snapcraft` | ||||
|  | ||||
| 6. **Development** **headers** | ||||
|  | ||||
| 	`$ sudo apt install libxext-dev libxtst-dev libxkbfile-dev libgconf-2-4` | ||||
|  | ||||
|  | ||||
| **if** [**NPM**](https://www.npmjs.com/get-npm) **don't come bundled with your Node.js installation, Download manually** | ||||
|  | ||||
|  | ||||
| Now you are ready for next step [: Get Zulip Desktop Code.](https://github.com/zulip/zulip-desktop/blob/master/development.md#get-zulip-desktop-code) | ||||
|  | ||||
|  | ||||
| ## Windows | ||||
|  | ||||
|   **Node JS** | ||||
|   Go to the [Node.js Downloads page](https://nodejs.org/en/download/). Download Node.js for windows (`v6.9.0` or above recommended). Run the downloaded Node.js `.msi` Installer. You're finished! To ensure Node.js has been installed, run `node -v` in your terminal - you should get something like `v6.9.0` or above | ||||
|  | ||||
|  | ||||
| **Followings are optional yet recommended prerequisites -** | ||||
|  | ||||
|   **Cmder** | ||||
|   1. Download the [latest release](https://github.com/cmderdev/cmder/releases/) | ||||
|   2. Extract the archive. *Note: This path should not be* `C:\Program Files` *or anywhere else that would require Administrator access for modifying configuration files* | ||||
|   3. (optional) Place your own executable files into the `%cmder_root%\bin` folder to be injected into your PATH. | ||||
|   4. Run `Cmder.exe` | ||||
|  | ||||
|   **Chocolatey** | ||||
|   You can download chocolatey from here https://chocolatey.org/ and for Installing Chocolatey on your machine follow this steps | ||||
|   1. First, ensure that you are using an administrative shell. | ||||
|   2. Copy the text specific to your command shell - [cmd.exe](https://chocolatey.org/install#install-with-cmdexe) or [powershell.exe](https://chocolatey.org/install#install-with-powershellexe). | ||||
|   3. Paste the copied text into your shell and press Enter. | ||||
|   4. Wait a few seconds for the command to complete. | ||||
|   5. If you don't see any errors, you are ready to use Chocolatey! Type `choco` or `choco -?` | ||||
|  | ||||
|  | ||||
| **System specific dependencies** | ||||
|  | ||||
| - use only 32bit or 64bit for all of the installers, do not mix architectures | ||||
| - install using default settings | ||||
| - open Windows Powershell as Admin and paste this | ||||
|     C:\Windows\system32> npm install --global --production windows-build-tools | ||||
|  | ||||
|  | ||||
| **if** [**NPM**](https://www.npmjs.com/get-npm) **and** [**node-gyp**](https://github.com/nodejs/node-gyp#installation) **don't come bundled with your Node.js installation, Download manually** | ||||
|  | ||||
| Now you are ready for next step [: Get Zulip Desktop Code.](https://github.com/zulip/zulip-desktop/blob/master/development.md#get-zulip-desktop-code) | ||||
|  | ||||
|  | ||||
| # Get Zulip Desktop Code | ||||
|  | ||||
| 1. In your browser, visit https://github.com/zulip/zulip-desktop and click the `fork` button. You will need to be logged in to GitHub to do this. | ||||
| 2. Open Terminal (macOS/Ubuntu) or Git BASH (Windows; must **run as an Administrator**). | ||||
| 3. In Terminal/Git BASH, [clone your fork of the zulip-desktop repository](https://github.com/zulip/zulip-desktop/blob/master/development.md#clone-to-your-machine) and [connect the zulip-desktop upstream repository](https://github.com/zulip/zulip-desktop/blob/master/development.md#connect-your-fork-to-zulip-desktop-upstream) | ||||
|  | ||||
|  | ||||
| ## Clone to your machine | ||||
|   1. On GitHub, navigate to the main page of your fork repository. | ||||
|   2. Under the repository name, click **Clone or download**. | ||||
|   3. In the Clone with HTTPs section, click to copy the clone URL for the repository. | ||||
|   4. Open Terminal, Change the current working directory to the location where you want the cloned directory to be made. | ||||
|  | ||||
|           git clone https://github.com/YOURUSERNAME/zulip-desktop.git | ||||
|  | ||||
| Don’t forget to replace YOURUSERNAME with your git username | ||||
|  | ||||
|  | ||||
| ## Connect your fork to zulip-desktop upstream | ||||
|  | ||||
|     cd zulip-desktop | ||||
|     git remote add -f upstream https://github.com/zulip/zulip-desktop.git | ||||
|  | ||||
|  | ||||
| # build and run | ||||
|  | ||||
|  | ||||
| ## Install project dependencies: | ||||
|     $ npm install | ||||
|  | ||||
|  | ||||
| ## There two ways to start the app: | ||||
|  | ||||
| **vanilla method** | ||||
|  | ||||
|      $ npm start | ||||
|  | ||||
| **start and watch changes recommended for dev’s** | ||||
|  | ||||
|       $ npm run dev | ||||
| The output distributable packages appear in the `dist/` directory. | ||||
							
								
								
									
										8
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "zulip", | ||||
|   "version": "2.5.0-beta", | ||||
|   "version": "3.0.0", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
| @@ -2838,9 +2838,9 @@ | ||||
|       "dev": true | ||||
|     }, | ||||
|     "electron": { | ||||
|       "version": "3.0.10", | ||||
|       "resolved": "https://registry.npmjs.org/electron/-/electron-3.0.10.tgz", | ||||
|       "integrity": "sha512-I39IeQP3NOlbjKzTDK8uK2JdiHDfhV5SruCS2Gttkn2MaKCY+yIzQ6Wr4DyBXLeTEkL1sbZxbqQVhCavAliv5w==", | ||||
|       "version": "3.1.10", | ||||
|       "resolved": "https://registry.npmjs.org/electron/-/electron-3.1.10.tgz", | ||||
|       "integrity": "sha512-IORdmdD5gWHmp3ffa+ZRD9kESJwdmQz8carDTeza6+W76dG447AUn7GmKk4cun31bLYTKb56D8pPhxa9S7kOZQ==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "@types/node": "^8.0.24", | ||||
|   | ||||
| @@ -127,7 +127,7 @@ | ||||
|     "assert": "1.4.1", | ||||
|     "cp-file": "5.0.0", | ||||
|     "devtron": "1.4.0", | ||||
|     "electron": "3.0.10", | ||||
|     "electron": "3.1.10", | ||||
|     "electron-builder": "20.40.2", | ||||
|     "electron-connect": "0.6.2", | ||||
|     "electron-debug": "1.4.0", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user