mirror of
				https://github.com/zulip/zulip-desktop.git
				synced 2025-11-04 05:53:21 +00:00 
			
		
		
		
	Compare commits
	
		
			24 Commits
		
	
	
		
			sentry
			...
			v2.2.0-bet
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					51e414a508 | ||
| 
						 | 
					8e7a9bf230 | ||
| 
						 | 
					6493ddb8ec | ||
| 
						 | 
					31edbe0d67 | ||
| 
						 | 
					9980fee785 | ||
| 
						 | 
					ff9986ec6b | ||
| 
						 | 
					f3423d394c | ||
| 
						 | 
					a1da199627 | ||
| 
						 | 
					537fbe8f9e | ||
| 
						 | 
					3fccb33fca | ||
| 
						 | 
					5638590c8b | ||
| 
						 | 
					29ed00981d | ||
| 
						 | 
					d7638c0b95 | ||
| 
						 | 
					7fadbe877b | ||
| 
						 | 
					32a21889fb | ||
| 
						 | 
					c4a961f9da | ||
| 
						 | 
					ceaa898570 | ||
| 
						 | 
					73fe17041d | ||
| 
						 | 
					9f756cad3e | ||
| 
						 | 
					6db6b7c482 | ||
| 
						 | 
					09c45e75e8 | ||
| 
						 | 
					120b80cf65 | ||
| 
						 | 
					22f705960d | ||
| 
						 | 
					ca8ce1deaa | 
@@ -7,7 +7,7 @@ const crashHandler = () => {
 | 
				
			|||||||
		productName: 'zulip-electron',
 | 
							productName: 'zulip-electron',
 | 
				
			||||||
		companyName: 'Kandra Labs, Inc.',
 | 
							companyName: 'Kandra Labs, Inc.',
 | 
				
			||||||
		submitURL: 'https://zulip-sentry.herokuapp.com/crashreport',
 | 
							submitURL: 'https://zulip-sentry.herokuapp.com/crashreport',
 | 
				
			||||||
		autoSubmit: true
 | 
							uploadToServer: true
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
'use strict';
 | 
					'use strict';
 | 
				
			||||||
const os = require('os');
 | 
					 | 
				
			||||||
const path = require('path');
 | 
					const path = require('path');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { app, shell, BrowserWindow, Menu, dialog } = require('electron');
 | 
					const { app, shell, BrowserWindow, Menu, dialog } = require('electron');
 | 
				
			||||||
@@ -7,6 +6,7 @@ const { app, shell, BrowserWindow, Menu, dialog } = require('electron');
 | 
				
			|||||||
const fs = require('fs-extra');
 | 
					const fs = require('fs-extra');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ConfigUtil = require(__dirname + '/../renderer/js/utils/config-util.js');
 | 
					const ConfigUtil = require(__dirname + '/../renderer/js/utils/config-util.js');
 | 
				
			||||||
 | 
					const DNDUtil = require(__dirname + '/../renderer/js/utils/dnd-util.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const appName = app.getName();
 | 
					const appName = app.getName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -139,13 +139,11 @@ class AppMenu {
 | 
				
			|||||||
			}, {
 | 
								}, {
 | 
				
			||||||
				label: 'Report an Issue...',
 | 
									label: 'Report an Issue...',
 | 
				
			||||||
				click() {
 | 
									click() {
 | 
				
			||||||
					const body = `
 | 
					          // the goal is to notify the main.html BrowserWindow
 | 
				
			||||||
					<!-- Please succinctly describe your issue and steps to reproduce it. -->
 | 
					          // which may not be the focused window.
 | 
				
			||||||
					-
 | 
										BrowserWindow.getAllWindows().forEach(window => {
 | 
				
			||||||
					${app.getName()} ${app.getVersion()}
 | 
											window.webContents.send('open-feedback-modal');
 | 
				
			||||||
					Electron ${process.versions.electron}
 | 
										});
 | 
				
			||||||
					${process.platform} ${process.arch} ${os.release()}`;
 | 
					 | 
				
			||||||
					shell.openExternal(`https://github.com/zulip/zulip-electron/issues/new?body=${encodeURIComponent(body)}`);
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}];
 | 
								}];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -217,6 +215,13 @@ class AppMenu {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			}, {
 | 
								}, {
 | 
				
			||||||
				type: 'separator'
 | 
									type: 'separator'
 | 
				
			||||||
 | 
								}, {
 | 
				
			||||||
 | 
									label: 'Toggle Do Not Disturb',
 | 
				
			||||||
 | 
									accelerator: 'Command+Shift+M',
 | 
				
			||||||
 | 
									click() {
 | 
				
			||||||
 | 
										const dndUtil = DNDUtil.toggle();
 | 
				
			||||||
 | 
										AppMenu.sendAction('toggle-dnd', dndUtil.dnd, dndUtil.newSettings);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}, {
 | 
								}, {
 | 
				
			||||||
				label: 'Reset App Settings',
 | 
									label: 'Reset App Settings',
 | 
				
			||||||
				accelerator: 'Command+Shift+D',
 | 
									accelerator: 'Command+Shift+D',
 | 
				
			||||||
@@ -319,6 +324,13 @@ class AppMenu {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			}, {
 | 
								}, {
 | 
				
			||||||
				type: 'separator'
 | 
									type: 'separator'
 | 
				
			||||||
 | 
								}, {
 | 
				
			||||||
 | 
									label: 'Toggle Do Not Disturb',
 | 
				
			||||||
 | 
									accelerator: 'Ctrl+Shift+M',
 | 
				
			||||||
 | 
									click() {
 | 
				
			||||||
 | 
										const dndUtil = DNDUtil.toggle();
 | 
				
			||||||
 | 
										AppMenu.sendAction('toggle-dnd', dndUtil.dnd, dndUtil.newSettings);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}, {
 | 
								}, {
 | 
				
			||||||
				label: 'Reset App Settings',
 | 
									label: 'Reset App Settings',
 | 
				
			||||||
				accelerator: 'Ctrl+Shift+D',
 | 
									accelerator: 'Ctrl+Shift+D',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "zulip",
 | 
					  "name": "zulip",
 | 
				
			||||||
  "productName": "Zulip",
 | 
					  "productName": "Zulip",
 | 
				
			||||||
  "version": "1.9.0",
 | 
					  "version": "2.2.0-beta",
 | 
				
			||||||
  "description": "Zulip Desktop App",
 | 
					  "description": "Zulip Desktop App",
 | 
				
			||||||
  "license": "Apache-2.0",
 | 
					  "license": "Apache-2.0",
 | 
				
			||||||
  "copyright": "Kandra Labs, Inc.",
 | 
					  "copyright": "Kandra Labs, Inc.",
 | 
				
			||||||
@@ -26,20 +26,20 @@
 | 
				
			|||||||
    "InstantMessaging"
 | 
					    "InstantMessaging"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "auto-launch": "5.0.1",
 | 
					    "@electron-elements/send-feedback": "1.0.7",
 | 
				
			||||||
 | 
					    "auto-launch": "5.0.5",
 | 
				
			||||||
    "electron-is-dev": "0.3.0",
 | 
					    "electron-is-dev": "0.3.0",
 | 
				
			||||||
    "electron-log": "2.2.7",
 | 
					    "electron-log": "2.2.14",
 | 
				
			||||||
    "electron-spellchecker": "1.1.2",
 | 
					    "electron-spellchecker": "1.1.2",
 | 
				
			||||||
    "electron-updater": "2.21.4",
 | 
					    "electron-updater": "2.21.10",
 | 
				
			||||||
    "electron-window-state": "4.1.1",
 | 
					    "electron-window-state": "4.1.1",
 | 
				
			||||||
    "is-online": "7.0.0",
 | 
					    "is-online": "7.0.0",
 | 
				
			||||||
    "node-json-db": "0.7.3",
 | 
					    "node-json-db": "0.7.3",
 | 
				
			||||||
    "request": "2.81.0",
 | 
					    "request": "2.85.0",
 | 
				
			||||||
    "semver": "5.4.1",
 | 
					    "semver": "5.4.1",
 | 
				
			||||||
    "@sentry/electron": "0.5.0",
 | 
					 | 
				
			||||||
    "wurl": "2.5.0"
 | 
					    "wurl": "2.5.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "optionalDependencies": {
 | 
					  "optionalDependencies": {
 | 
				
			||||||
    "node-mac-notifier": "0.0.13"
 | 
					    "node-mac-notifier": "0.1.0"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,9 +13,6 @@ body {
 | 
				
			|||||||
#content {
 | 
					#content {
 | 
				
			||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
    height: 100%;
 | 
					    height: 100%;
 | 
				
			||||||
    background: #fff url(../img/ic_loading.gif) no-repeat;
 | 
					 | 
				
			||||||
    background-size: 60px 60px;
 | 
					 | 
				
			||||||
    background-position: center;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.toggle-sidebar {
 | 
					.toggle-sidebar {
 | 
				
			||||||
@@ -45,6 +42,28 @@ body {
 | 
				
			|||||||
    transition: all 0.6s ease-out;
 | 
					    transition: all 0.6s ease-out;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#view-controls-container {
 | 
				
			||||||
 | 
						height: calc(100% - 208px);
 | 
				
			||||||
 | 
						overflow-y: hidden;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#view-controls-container:hover {
 | 
				
			||||||
 | 
						overflow-y: overlay;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#view-controls-container::-webkit-scrollbar {
 | 
				
			||||||
 | 
						width: 4px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#view-controls-container::-webkit-scrollbar-track {
 | 
				
			||||||
 | 
					    box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#view-controls-container::-webkit-scrollbar-thumb {
 | 
				
			||||||
 | 
					  background-color: darkgrey;
 | 
				
			||||||
 | 
					  outline: 1px solid slategrey;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@font-face {
 | 
					@font-face {
 | 
				
			||||||
    font-family: 'Material Icons';
 | 
					    font-family: 'Material Icons';
 | 
				
			||||||
    font-style: normal;
 | 
					    font-style: normal;
 | 
				
			||||||
@@ -251,6 +270,25 @@ body {
 | 
				
			|||||||
    width: 100%;
 | 
					    width: 100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*Pseudo element for loading indicator*/
 | 
				
			||||||
 | 
					#webviews-container::before {
 | 
				
			||||||
 | 
					    content: "";
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    z-index: 1;
 | 
				
			||||||
 | 
					    background: #fff url(../img/ic_loading.gif) no-repeat;
 | 
				
			||||||
 | 
					    background-size: 60px 60px;
 | 
				
			||||||
 | 
					    background-position: center;
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    height: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*When the active webview is loaded*/
 | 
				
			||||||
 | 
					#webviews-container.loaded::before {
 | 
				
			||||||
 | 
					    opacity: 0;
 | 
				
			||||||
 | 
					    z-index: -1;
 | 
				
			||||||
 | 
					    visibility: hidden;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
webview {
 | 
					webview {
 | 
				
			||||||
    /* transition: opacity 0.3s ease-in; */
 | 
					    /* transition: opacity 0.3s ease-in; */
 | 
				
			||||||
    flex-grow: 1;
 | 
					    flex-grow: 1;
 | 
				
			||||||
@@ -262,11 +300,6 @@ webview {
 | 
				
			|||||||
    flex-direction: column;
 | 
					    flex-direction: column;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
webview.download-webview {
 | 
					 | 
				
			||||||
  z-index: -1;
 | 
					 | 
				
			||||||
  pointer-events: none;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
webview.onload {
 | 
					webview.onload {
 | 
				
			||||||
    transition: opacity 1s cubic-bezier(0.95, 0.05, 0.795, 0.035);
 | 
					    transition: opacity 1s cubic-bezier(0.95, 0.05, 0.795, 0.035);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -287,6 +320,7 @@ webview.focus {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Tooltip styling */
 | 
					/* Tooltip styling */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#dnd-tooltip,
 | 
				
			||||||
#back-tooltip,
 | 
					#back-tooltip,
 | 
				
			||||||
#reload-tooltip,
 | 
					#reload-tooltip,
 | 
				
			||||||
#setting-tooltip {
 | 
					#setting-tooltip {
 | 
				
			||||||
@@ -304,6 +338,7 @@ webview.focus {
 | 
				
			|||||||
    font-size: 14px;
 | 
					    font-size: 14px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#dnd-tooltip:after,
 | 
				
			||||||
#back-tooltip:after,
 | 
					#back-tooltip:after,
 | 
				
			||||||
#reload-tooltip:after,
 | 
					#reload-tooltip:after,
 | 
				
			||||||
#setting-tooltip:after {
 | 
					#setting-tooltip:after {
 | 
				
			||||||
@@ -408,3 +443,26 @@ webview.focus {
 | 
				
			|||||||
        opacity: 1;
 | 
					        opacity: 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					send-feedback {
 | 
				
			||||||
 | 
					  width: 60%;
 | 
				
			||||||
 | 
					  height: 85%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#feedback-modal {
 | 
				
			||||||
 | 
					  display: none;
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  top: 0;
 | 
				
			||||||
 | 
					  left: 0;
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  background-color: rgba(68, 67, 67, 0.81);
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  z-index: 2;
 | 
				
			||||||
 | 
					  transition: all 1s ease-out;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#feedback-modal.show {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,6 @@
 | 
				
			|||||||
const { shell } = require('electron').remote;
 | 
					const { shell } = require('electron').remote;
 | 
				
			||||||
const LinkUtil = require('../utils/link-util');
 | 
					const LinkUtil = require('../utils/link-util');
 | 
				
			||||||
const DomainUtil = require('../utils/domain-util');
 | 
					const DomainUtil = require('../utils/domain-util');
 | 
				
			||||||
const hiddenWebView = require('../components/hidden-webview');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
function handleExternalLink(event) {
 | 
					function handleExternalLink(event) {
 | 
				
			||||||
	const { url } = event;
 | 
						const { url } = event;
 | 
				
			||||||
@@ -16,12 +15,12 @@ function handleExternalLink(event) {
 | 
				
			|||||||
	if (isWhiteListURL) {
 | 
						if (isWhiteListURL) {
 | 
				
			||||||
		event.preventDefault();
 | 
							event.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // only open the  pdf, mp3, mp4 etc.. in hidden webview since opening the
 | 
					    // download txt, pdf, mp3, mp4 etc.. by using downloadURL in the
 | 
				
			||||||
    // image in webview will do nothing and will not save it
 | 
					    // main process which allows the user to save the files to their desktop
 | 
				
			||||||
    // whereas the pdf will be saved to user desktop once openened in
 | 
					    // and not trigger webview reload while image in webview will
 | 
				
			||||||
    // in the hidden webview and will not trigger webview reload
 | 
					    // do nothing and will not save it
 | 
				
			||||||
		if (!LinkUtil.isImage(url) && isUploadsURL) {
 | 
							if (!LinkUtil.isImage(url) && isUploadsURL) {
 | 
				
			||||||
			hiddenWebView.loadURL(url);
 | 
								this.$el.downloadURL(url);
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +0,0 @@
 | 
				
			|||||||
// this hidden webview will be used to open pdf url and
 | 
					 | 
				
			||||||
// save it to user's computer without triggering a reload
 | 
					 | 
				
			||||||
// when navigating to pdf url to download it.
 | 
					 | 
				
			||||||
const hiddenWebView = document.createElement('webview');
 | 
					 | 
				
			||||||
hiddenWebView.classList.add('download-webview');
 | 
					 | 
				
			||||||
hiddenWebView.src = 'about:blank';
 | 
					 | 
				
			||||||
document.querySelector('#webviews-container').appendChild(hiddenWebView);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = hiddenWebView;
 | 
					 | 
				
			||||||
@@ -18,9 +18,10 @@ class WebView extends BaseComponent {
 | 
				
			|||||||
		this.props = props;
 | 
							this.props = props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.zoomFactor = 1.0;
 | 
							this.zoomFactor = 1.0;
 | 
				
			||||||
		this.loading = false;
 | 
							this.loading = true;
 | 
				
			||||||
		this.badgeCount = 0;
 | 
							this.badgeCount = 0;
 | 
				
			||||||
		this.customCSS = ConfigUtil.getConfigItem('customCSS');
 | 
							this.customCSS = ConfigUtil.getConfigItem('customCSS');
 | 
				
			||||||
 | 
							this.$webviewsContainer = document.querySelector('#webviews-container').classList;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	template() {
 | 
						template() {
 | 
				
			||||||
@@ -86,6 +87,7 @@ class WebView extends BaseComponent {
 | 
				
			|||||||
			if (this.props.role === 'server') {
 | 
								if (this.props.role === 'server') {
 | 
				
			||||||
				this.$el.classList.add('onload');
 | 
									this.$el.classList.add('onload');
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								this.loading = false;
 | 
				
			||||||
			this.show();
 | 
								this.show();
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -119,6 +121,13 @@ class WebView extends BaseComponent {
 | 
				
			|||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// To show or hide the loading indicator in the the active tab
 | 
				
			||||||
 | 
							if (this.loading) {
 | 
				
			||||||
 | 
								this.$webviewsContainer.remove('loaded');
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								this.$webviewsContainer.add('loaded');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.$el.classList.remove('disabled');
 | 
							this.$el.classList.remove('disabled');
 | 
				
			||||||
		this.$el.classList.add('active');
 | 
							this.$el.classList.add('active');
 | 
				
			||||||
		setTimeout(() => {
 | 
							setTimeout(() => {
 | 
				
			||||||
@@ -127,7 +136,6 @@ class WebView extends BaseComponent {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}, 1000);
 | 
							}, 1000);
 | 
				
			||||||
		this.focus();
 | 
							this.focus();
 | 
				
			||||||
		this.loading = false;
 | 
					 | 
				
			||||||
		this.props.onTitleChange();
 | 
							this.props.onTitleChange();
 | 
				
			||||||
		// Injecting preload css in webview to override some css rules
 | 
							// Injecting preload css in webview to override some css rules
 | 
				
			||||||
		this.$el.insertCSS(fs.readFileSync(path.join(__dirname, '/../../css/preload.css'), 'utf8'));
 | 
							this.$el.insertCSS(fs.readFileSync(path.join(__dirname, '/../../css/preload.css'), 'utf8'));
 | 
				
			||||||
@@ -220,6 +228,9 @@ class WebView extends BaseComponent {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	reload() {
 | 
						reload() {
 | 
				
			||||||
		this.hide();
 | 
							this.hide();
 | 
				
			||||||
 | 
							// Shows the loading indicator till the webview is reloaded
 | 
				
			||||||
 | 
							this.$webviewsContainer.remove('loaded');
 | 
				
			||||||
 | 
							this.loading = true;
 | 
				
			||||||
		this.$el.reload();
 | 
							this.$el.reload();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										62
									
								
								app/renderer/js/feedback.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								app/renderer/js/feedback.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					const { app } = require('electron').remote;
 | 
				
			||||||
 | 
					const path = require('path');
 | 
				
			||||||
 | 
					const fs = require('fs');
 | 
				
			||||||
 | 
					const SendFeedback = require('@electron-elements/send-feedback');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// make the button color match zulip app's theme
 | 
				
			||||||
 | 
					SendFeedback.customStyles = `
 | 
				
			||||||
 | 
					button:hover, button:focus {
 | 
				
			||||||
 | 
					  border-color: #4EBFAC;
 | 
				
			||||||
 | 
					  color: #4EBFAC;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					button:active {
 | 
				
			||||||
 | 
					  background-color: #f1f1f1;
 | 
				
			||||||
 | 
					  color: #4EBFAC;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					button {
 | 
				
			||||||
 | 
					  background-color: #4EBFAC;
 | 
				
			||||||
 | 
					  border-color: #4EBFAC;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					customElements.define('send-feedback', SendFeedback);
 | 
				
			||||||
 | 
					const sendFeedback = document.querySelector('send-feedback');
 | 
				
			||||||
 | 
					const feedbackHolder = sendFeedback.parentElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// customize the fields of custom elements
 | 
				
			||||||
 | 
					sendFeedback.title = 'Report Issue';
 | 
				
			||||||
 | 
					sendFeedback.titleLabel = 'Issue title:';
 | 
				
			||||||
 | 
					sendFeedback.titlePlaceholder = 'Enter issue title';
 | 
				
			||||||
 | 
					sendFeedback.textareaLabel = 'Describe the issue:';
 | 
				
			||||||
 | 
					sendFeedback.textareaPlaceholder = 'Succinctly describe your issue and steps to reproduce it...';
 | 
				
			||||||
 | 
					sendFeedback.buttonLabel = 'Report Issue';
 | 
				
			||||||
 | 
					sendFeedback.loaderSuccessText = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sendFeedback.useReporter('emailReporter', {
 | 
				
			||||||
 | 
						email: 'akash@zulipchat.com'
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					feedbackHolder.addEventListener('click', e => {
 | 
				
			||||||
 | 
					  // only remove the class if the grey out faded
 | 
				
			||||||
 | 
					  // part is clicked and not the feedback element itself
 | 
				
			||||||
 | 
						if (e.target === e.currentTarget) {
 | 
				
			||||||
 | 
							feedbackHolder.classList.remove('show');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sendFeedback.addEventListener('feedback-submitted', () => {
 | 
				
			||||||
 | 
						setTimeout(() => {
 | 
				
			||||||
 | 
							feedbackHolder.classList.remove('show');
 | 
				
			||||||
 | 
						}, 1000);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const dataDir = app.getPath('userData');
 | 
				
			||||||
 | 
					const logsDir = path.join(dataDir, '/Logs');
 | 
				
			||||||
 | 
					sendFeedback.logs.push(...fs.readdirSync(logsDir).map(file => path.join(logsDir, file)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						feedbackHolder,
 | 
				
			||||||
 | 
						sendFeedback
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -11,7 +11,9 @@ const WebView = require(__dirname + '/js/components/webview.js');
 | 
				
			|||||||
const ServerTab = require(__dirname + '/js/components/server-tab.js');
 | 
					const ServerTab = require(__dirname + '/js/components/server-tab.js');
 | 
				
			||||||
const FunctionalTab = require(__dirname + '/js/components/functional-tab.js');
 | 
					const FunctionalTab = require(__dirname + '/js/components/functional-tab.js');
 | 
				
			||||||
const ConfigUtil = require(__dirname + '/js/utils/config-util.js');
 | 
					const ConfigUtil = require(__dirname + '/js/utils/config-util.js');
 | 
				
			||||||
 | 
					const DNDUtil = require(__dirname + '/js/utils/dnd-util.js');
 | 
				
			||||||
const ReconnectUtil = require(__dirname + '/js/utils/reconnect-util.js');
 | 
					const ReconnectUtil = require(__dirname + '/js/utils/reconnect-util.js');
 | 
				
			||||||
 | 
					const { feedbackHolder } = require(__dirname + '/js/feedback.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ServerManagerView {
 | 
					class ServerManagerView {
 | 
				
			||||||
	constructor() {
 | 
						constructor() {
 | 
				
			||||||
@@ -23,12 +25,14 @@ 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.$backButton = $actionsContainer.querySelector('#back-action');
 | 
							this.$backButton = $actionsContainer.querySelector('#back-action');
 | 
				
			||||||
 | 
							this.$dndButton = $actionsContainer.querySelector('#dnd-action');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.$addServerTooltip = document.getElementById('add-server-tooltip');
 | 
							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.$serverIconTooltip = document.getElementsByClassName('server-tooltip');
 | 
				
			||||||
		this.$backTooltip = $actionsContainer.querySelector('#back-tooltip');
 | 
							this.$backTooltip = $actionsContainer.querySelector('#back-tooltip');
 | 
				
			||||||
 | 
							this.$dndTooltip = $actionsContainer.querySelector('#dnd-tooltip');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.$sidebar = document.getElementById('sidebar');
 | 
							this.$sidebar = document.getElementById('sidebar');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -87,7 +91,12 @@ class ServerManagerView {
 | 
				
			|||||||
			showNotification: true,
 | 
								showNotification: true,
 | 
				
			||||||
			betaUpdate: false,
 | 
								betaUpdate: false,
 | 
				
			||||||
			silent: false,
 | 
								silent: false,
 | 
				
			||||||
			lastActiveTab: 0
 | 
								lastActiveTab: 0,
 | 
				
			||||||
 | 
								dnd: false,
 | 
				
			||||||
 | 
								dndPreviousSettings: {
 | 
				
			||||||
 | 
									showNotification: true,
 | 
				
			||||||
 | 
									silent: false
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Platform specific settings
 | 
							// Platform specific settings
 | 
				
			||||||
@@ -95,6 +104,7 @@ class ServerManagerView {
 | 
				
			|||||||
		if (process.platform === 'win32') {
 | 
							if (process.platform === 'win32') {
 | 
				
			||||||
			// Only available on Windows
 | 
								// Only available on Windows
 | 
				
			||||||
			settingOptions.flashTaskbarOnMessage = true;
 | 
								settingOptions.flashTaskbarOnMessage = true;
 | 
				
			||||||
 | 
								settingOptions.dndPreviousSettings.flashTaskbarOnMessage = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (const i in settingOptions) {
 | 
							for (const i in settingOptions) {
 | 
				
			||||||
@@ -155,6 +165,11 @@ class ServerManagerView {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	initActions() {
 | 
						initActions() {
 | 
				
			||||||
 | 
							this.initDNDButton();
 | 
				
			||||||
 | 
							this.$dndButton.addEventListener('click', () => {
 | 
				
			||||||
 | 
								const dndUtil = DNDUtil.toggle();
 | 
				
			||||||
 | 
								ipcRenderer.send('forward-message', 'toggle-dnd', dndUtil.dnd, dndUtil.newSettings);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
		this.$reloadButton.addEventListener('click', () => {
 | 
							this.$reloadButton.addEventListener('click', () => {
 | 
				
			||||||
			this.tabs[this.activeTabIndex].webview.reload();
 | 
								this.tabs[this.activeTabIndex].webview.reload();
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
@@ -175,10 +190,16 @@ class ServerManagerView {
 | 
				
			|||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.sidebarHoverEvent(this.$addServerButton, this.$addServerTooltip);
 | 
							this.sidebarHoverEvent(this.$addServerButton, this.$addServerTooltip, true);
 | 
				
			||||||
		this.sidebarHoverEvent(this.$settingsButton, this.$settingsTooltip);
 | 
							this.sidebarHoverEvent(this.$settingsButton, this.$settingsTooltip);
 | 
				
			||||||
		this.sidebarHoverEvent(this.$reloadButton, this.$reloadTooltip);
 | 
							this.sidebarHoverEvent(this.$reloadButton, this.$reloadTooltip);
 | 
				
			||||||
		this.sidebarHoverEvent(this.$backButton, this.$backTooltip);
 | 
							this.sidebarHoverEvent(this.$backButton, this.$backTooltip);
 | 
				
			||||||
 | 
							this.sidebarHoverEvent(this.$dndButton, this.$dndTooltip);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initDNDButton() {
 | 
				
			||||||
 | 
							const dnd = ConfigUtil.getConfigItem('dnd', false);
 | 
				
			||||||
 | 
							this.toggleDNDButton(dnd);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	getTabIndex() {
 | 
						getTabIndex() {
 | 
				
			||||||
@@ -187,9 +208,17 @@ class ServerManagerView {
 | 
				
			|||||||
		return currentIndex;
 | 
							return currentIndex;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sidebarHoverEvent(SidebarButton, SidebarTooltip) {
 | 
						sidebarHoverEvent(SidebarButton, SidebarTooltip, addServer = false) {
 | 
				
			||||||
		SidebarButton.addEventListener('mouseover', () => {
 | 
							SidebarButton.addEventListener('mouseover', () => {
 | 
				
			||||||
			SidebarTooltip.removeAttribute('style');
 | 
								SidebarTooltip.removeAttribute('style');
 | 
				
			||||||
 | 
								// To handle position of add server tooltip due to scrolling of list of organizations
 | 
				
			||||||
 | 
								// This could not be handled using CSS, hence the top of the tooltip is made same
 | 
				
			||||||
 | 
								// as that of its parent element.
 | 
				
			||||||
 | 
								// This needs to handled only for the add server tooltip and not others.
 | 
				
			||||||
 | 
								if (addServer) {
 | 
				
			||||||
 | 
									const { top } = SidebarButton.getBoundingClientRect();
 | 
				
			||||||
 | 
									SidebarTooltip.style.top = top + 'px';
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		SidebarButton.addEventListener('mouseout', () => {
 | 
							SidebarButton.addEventListener('mouseout', () => {
 | 
				
			||||||
			SidebarTooltip.style.display = 'none';
 | 
								SidebarTooltip.style.display = 'none';
 | 
				
			||||||
@@ -199,6 +228,11 @@ class ServerManagerView {
 | 
				
			|||||||
	onHover(index, serverName) {
 | 
						onHover(index, serverName) {
 | 
				
			||||||
		this.$serverIconTooltip[index].innerHTML = serverName;
 | 
							this.$serverIconTooltip[index].innerHTML = serverName;
 | 
				
			||||||
		this.$serverIconTooltip[index].removeAttribute('style');
 | 
							this.$serverIconTooltip[index].removeAttribute('style');
 | 
				
			||||||
 | 
							// To handle position of servers' tooltip due to scrolling of list of organizations
 | 
				
			||||||
 | 
							// This could not be handled using CSS, hence the top of the tooltip is made same
 | 
				
			||||||
 | 
							// as that of its parent element.
 | 
				
			||||||
 | 
							const { top } = this.$serverIconTooltip[index].parentElement.getBoundingClientRect();
 | 
				
			||||||
 | 
							this.$serverIconTooltip[index].style.top = top + 'px';
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	onHoverOut(index) {
 | 
						onHoverOut(index) {
 | 
				
			||||||
@@ -238,6 +272,9 @@ class ServerManagerView {
 | 
				
			|||||||
				preload: false
 | 
									preload: false
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		}));
 | 
							}));
 | 
				
			||||||
 | 
							// To show loading indicator the first time a functional tab is opened, indicator is
 | 
				
			||||||
 | 
							// closed when the functional tab DOM is ready, handled in webview.js
 | 
				
			||||||
 | 
							this.$webviewsContainer.classList.remove('loaded');
 | 
				
			||||||
		this.activateTab(this.functionalTabs[tabProps.name]);
 | 
							this.activateTab(this.functionalTabs[tabProps.name]);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -324,6 +361,15 @@ class ServerManagerView {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ipcRenderer.on('toggle-dnd', (event, state, newSettings) => {
 | 
				
			||||||
 | 
								this.toggleDNDButton(state);
 | 
				
			||||||
 | 
								ipcRenderer.send('forward-message', 'toggle-silent', newSettings.silent);
 | 
				
			||||||
 | 
								const selector = 'webview:not([class*=disabled])';
 | 
				
			||||||
 | 
								const webview = document.querySelector(selector);
 | 
				
			||||||
 | 
								const webContents = webview.getWebContents();
 | 
				
			||||||
 | 
								webContents.send('toggle-dnd', state, newSettings);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	destroyTab(name, index) {
 | 
						destroyTab(name, index) {
 | 
				
			||||||
@@ -343,6 +389,9 @@ class ServerManagerView {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	destroyView() {
 | 
						destroyView() {
 | 
				
			||||||
 | 
							// Show loading indicator
 | 
				
			||||||
 | 
							this.$webviewsContainer.classList.remove('loaded');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Clear global variables
 | 
							// Clear global variables
 | 
				
			||||||
		this.activeTabIndex = -1;
 | 
							this.activeTabIndex = -1;
 | 
				
			||||||
		this.tabs = [];
 | 
							this.tabs = [];
 | 
				
			||||||
@@ -390,6 +439,12 @@ class ServerManagerView {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Toggles the dnd button icon.
 | 
				
			||||||
 | 
						toggleDNDButton(alert) {
 | 
				
			||||||
 | 
							this.$dndTooltip.textContent = (alert ? 'Turn Off' : 'Enable') + ' Do Not Disturb';
 | 
				
			||||||
 | 
							this.$dndButton.querySelector('i').textContent = alert ? 'notifications_off' : 'notifications';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	registerIpcs() {
 | 
						registerIpcs() {
 | 
				
			||||||
		const webviewListeners = {
 | 
							const webviewListeners = {
 | 
				
			||||||
			'webview-reload': 'reload',
 | 
								'webview-reload': 'reload',
 | 
				
			||||||
@@ -496,6 +551,10 @@ class ServerManagerView {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			ipcRenderer.send('update-taskbar-icon', createOverlayIcon(messageCount).toDataURL(), String(messageCount));
 | 
								ipcRenderer.send('update-taskbar-icon', createOverlayIcon(messageCount).toDataURL(), String(messageCount));
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ipcRenderer.on('open-feedback-modal', () => {
 | 
				
			||||||
 | 
								feedbackHolder.classList.add('show');
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -97,6 +97,15 @@ class PreferenceView extends BaseComponent {
 | 
				
			|||||||
		ipcRenderer.on('toggletray', (event, state) => {
 | 
							ipcRenderer.on('toggletray', (event, state) => {
 | 
				
			||||||
			this.handleToggle('tray-option', state);
 | 
								this.handleToggle('tray-option', state);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ipcRenderer.on('toggle-dnd', (event, state, newSettings) => {
 | 
				
			||||||
 | 
								this.handleToggle('show-notification-option', newSettings.showNotification);
 | 
				
			||||||
 | 
								this.handleToggle('silent-option', newSettings.silent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (process.platform === 'win32') {
 | 
				
			||||||
 | 
									this.handleToggle('flash-taskbar-option', newSettings.flashTaskbarOnMessage);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,10 @@ class ShortcutsSection extends BaseSection {
 | 
				
			|||||||
                  <tr>
 | 
					                  <tr>
 | 
				
			||||||
                    <td><kbd>${userOSKey}</kbd><kbd>K</kbd></td>
 | 
					                    <td><kbd>${userOSKey}</kbd><kbd>K</kbd></td>
 | 
				
			||||||
                    <td>Keyboard Shortcuts</td>
 | 
					                    <td>Keyboard Shortcuts</td>
 | 
				
			||||||
 | 
					                  </tr>
 | 
				
			||||||
 | 
														<tr>
 | 
				
			||||||
 | 
					                    <td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>M</kbd></td>
 | 
				
			||||||
 | 
					                    <td>Toggle Do Not Disturb</td>
 | 
				
			||||||
                  </tr>
 | 
					                  </tr>
 | 
				
			||||||
                  <tr>
 | 
					                  <tr>
 | 
				
			||||||
                    <td><kbd>Shift</kbd><kbd>${userOSKey}</kbd><kbd>D</kbd></td>
 | 
					                    <td><kbd>Shift</kbd><kbd>${userOSKey}</kbd><kbd>D</kbd></td>
 | 
				
			||||||
@@ -174,6 +178,10 @@ class ShortcutsSection extends BaseSection {
 | 
				
			|||||||
                  <tr>
 | 
					                  <tr>
 | 
				
			||||||
                    <td><kbd>${userOSKey}</kbd> + <kbd>K</kbd></td>
 | 
					                    <td><kbd>${userOSKey}</kbd> + <kbd>K</kbd></td>
 | 
				
			||||||
                    <td>Keyboard Shortcuts</td>
 | 
					                    <td>Keyboard Shortcuts</td>
 | 
				
			||||||
 | 
					                  </tr>
 | 
				
			||||||
 | 
														<tr>
 | 
				
			||||||
 | 
					                    <td><kbd>${userOSKey}</kbd> + <kbd>Shift</kbd> + <kbd>M</kbd></td>
 | 
				
			||||||
 | 
					                    <td>Toggle Do Not Disturb</td>
 | 
				
			||||||
                  </tr>
 | 
					                  </tr>
 | 
				
			||||||
                  <tr>
 | 
					                  <tr>
 | 
				
			||||||
                    <td><kbd>${userOSKey}</kbd> + <kbd>L</kbd></td>
 | 
					                    <td><kbd>${userOSKey}</kbd> + <kbd>L</kbd></td>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -98,7 +98,7 @@ const renderNativeImage = function (arg) {
 | 
				
			|||||||
	return Promise.resolve()
 | 
						return Promise.resolve()
 | 
				
			||||||
		.then(() => renderCanvas(arg))
 | 
							.then(() => renderCanvas(arg))
 | 
				
			||||||
		.then(canvas => {
 | 
							.then(canvas => {
 | 
				
			||||||
			const pngData = nativeImage.createFromDataURL(canvas.toDataURL('image/png')).toPng();
 | 
								const pngData = nativeImage.createFromDataURL(canvas.toDataURL('image/png')).toPNG();
 | 
				
			||||||
			return Promise.resolve(nativeImage.createFromBuffer(pngData, config.pixelRatio));
 | 
								return Promise.resolve(nativeImage.createFromBuffer(pngData, config.pixelRatio));
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										41
									
								
								app/renderer/js/utils/dnd-util.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								app/renderer/js/utils/dnd-util.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ConfigUtil = require(__dirname + '/config-util.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function toggle() {
 | 
				
			||||||
 | 
						const dnd = !ConfigUtil.getConfigItem('dnd', false);
 | 
				
			||||||
 | 
						const dndSettingList = ['showNotification', 'silent'];
 | 
				
			||||||
 | 
						if (process.platform === 'win32') {
 | 
				
			||||||
 | 
							dndSettingList.push('flashTaskbarOnMessage');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						let newSettings;
 | 
				
			||||||
 | 
						if (dnd) {
 | 
				
			||||||
 | 
							const oldSettings = {};
 | 
				
			||||||
 | 
							newSettings = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Iterate through the dndSettingList.
 | 
				
			||||||
 | 
							for (const settingName of dndSettingList) {
 | 
				
			||||||
 | 
								// Store the current value of setting.
 | 
				
			||||||
 | 
								oldSettings[settingName] = ConfigUtil.getConfigItem(settingName);
 | 
				
			||||||
 | 
								// New value of setting.
 | 
				
			||||||
 | 
								newSettings[settingName] = (settingName === 'silent');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Store old value in oldSettings.
 | 
				
			||||||
 | 
							ConfigUtil.setConfigItem('dndPreviousSettings', oldSettings);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							newSettings = ConfigUtil.getConfigItem('dndPreviousSettings');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (const settingName of dndSettingList) {
 | 
				
			||||||
 | 
							ConfigUtil.setConfigItem(settingName, newSettings[settingName]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ConfigUtil.setConfigItem('dnd', dnd);
 | 
				
			||||||
 | 
						return {dnd, newSettings};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						toggle
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -37,9 +37,11 @@ class ReconnectUtil {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
						console.log('There is no internet connection, try checking network cables, modem and router.');
 | 
											console.log('There is no internet connection, try checking network cables, modem and router.');
 | 
				
			||||||
						const errMsgHolder = document.querySelector('#description');
 | 
											const errMsgHolder = document.querySelector('#description');
 | 
				
			||||||
 | 
											if (errMsgHolder) {
 | 
				
			||||||
							errMsgHolder.innerHTML = `
 | 
												errMsgHolder.innerHTML = `
 | 
				
			||||||
										<div>You internet connection does't seem to work properly!</div>
 | 
															<div>You internet connection does't seem to work properly!</div>
 | 
				
			||||||
										</div>Verify that it works and then click try again.</div>`;
 | 
															</div>Verify that it works and then click try again.</div>`;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
						return resolve(false);
 | 
											return resolve(false);
 | 
				
			||||||
					});
 | 
										});
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,10 @@
 | 
				
			|||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div id="actions-container">
 | 
					    <div id="actions-container">
 | 
				
			||||||
 | 
					      <div class="action-button" id="dnd-action">
 | 
				
			||||||
 | 
					        <i class="material-icons md-48">notifications</i>
 | 
				
			||||||
 | 
					        <span id="dnd-tooltip" style="display:none">Do Not Disturb</span>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
      <div class="action-button" id="reload-action">
 | 
					      <div class="action-button" id="reload-action">
 | 
				
			||||||
        <i class="material-icons md-48">refresh</i>
 | 
					        <i class="material-icons md-48">refresh</i>
 | 
				
			||||||
        <span id="reload-tooltip" style="display:none">Reload</span>
 | 
					        <span id="reload-tooltip" style="display:none">Reload</span>
 | 
				
			||||||
@@ -42,6 +46,10 @@
 | 
				
			|||||||
    <div id="webviews-container"></div>
 | 
					    <div id="webviews-container"></div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <div id="feedback-modal">
 | 
				
			||||||
 | 
					    <send-feedback></send-feedback>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
</body>
 | 
					</body>
 | 
				
			||||||
<script src="js/main.js"></script>
 | 
					<script src="js/main.js"></script>
 | 
				
			||||||
<script>require('./js/shared/preventdrag.js')</script>
 | 
					<script>require('./js/shared/preventdrag.js')</script>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								build/appdmg.png
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								build/appdmg.png
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 12 KiB  | 
							
								
								
									
										26
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								package.json
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "zulip",
 | 
					  "name": "zulip",
 | 
				
			||||||
  "productName": "Zulip",
 | 
					  "productName": "Zulip",
 | 
				
			||||||
  "version": "1.9.0",
 | 
					  "version": "2.2.0-beta",
 | 
				
			||||||
  "main": "./app/main",
 | 
					  "main": "./app/main",
 | 
				
			||||||
  "description": "Zulip Desktop App",
 | 
					  "description": "Zulip Desktop App",
 | 
				
			||||||
  "license": "Apache-2.0",
 | 
					  "license": "Apache-2.0",
 | 
				
			||||||
@@ -46,7 +46,8 @@
 | 
				
			|||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "copyright": "©2017 Kandra Labs, Inc.",
 | 
					    "copyright": "©2017 Kandra Labs, Inc.",
 | 
				
			||||||
    "mac": {
 | 
					    "mac": {
 | 
				
			||||||
      "category": "public.app-category.productivity"
 | 
					      "category": "public.app-category.productivity",
 | 
				
			||||||
 | 
					      "artifactName": "${productName}-${version}-${arch}.${ext}"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "linux": {
 | 
					    "linux": {
 | 
				
			||||||
      "category": "Chat;GNOME;GTK;Network;InstantMessaging",
 | 
					      "category": "Chat;GNOME;GTK;Network;InstantMessaging",
 | 
				
			||||||
@@ -58,7 +59,8 @@
 | 
				
			|||||||
        "AppImage",
 | 
					        "AppImage",
 | 
				
			||||||
        "snap"
 | 
					        "snap"
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      "maintainer": "Akash Nimare <svnitakash@gmail.com>"
 | 
					      "maintainer": "Akash Nimare <svnitakash@gmail.com>",
 | 
				
			||||||
 | 
					      "artifactName": "${productName}-${version}-${arch}.${ext}"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "deb": {
 | 
					    "deb": {
 | 
				
			||||||
      "synopsis": "Zulip Desktop App",
 | 
					      "synopsis": "Zulip Desktop App",
 | 
				
			||||||
@@ -71,20 +73,24 @@
 | 
				
			|||||||
    "dmg": {
 | 
					    "dmg": {
 | 
				
			||||||
      "background": "build/appdmg.png",
 | 
					      "background": "build/appdmg.png",
 | 
				
			||||||
      "icon": "build/icon.icns",
 | 
					      "icon": "build/icon.icns",
 | 
				
			||||||
      "iconSize": 128,
 | 
					      "iconSize": 100,
 | 
				
			||||||
      "contents": [
 | 
					      "contents": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "x": 380,
 | 
					          "x": 380,
 | 
				
			||||||
          "y": 240,
 | 
					          "y": 280,
 | 
				
			||||||
          "type": "link",
 | 
					          "type": "link",
 | 
				
			||||||
          "path": "/Applications"
 | 
					          "path": "/Applications"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "x": 122,
 | 
					          "x": 110,
 | 
				
			||||||
          "y": 240,
 | 
					          "y": 280,
 | 
				
			||||||
          "type": "file"
 | 
					          "type": "file"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ]
 | 
					      ],
 | 
				
			||||||
 | 
					      "window": {
 | 
				
			||||||
 | 
					          "width": 500,
 | 
				
			||||||
 | 
					          "height": 500
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "win": {
 | 
					    "win": {
 | 
				
			||||||
      "target": [
 | 
					      "target": [
 | 
				
			||||||
@@ -117,8 +123,8 @@
 | 
				
			|||||||
    "assert": "1.4.1",
 | 
					    "assert": "1.4.1",
 | 
				
			||||||
    "cp-file": "^5.0.0",
 | 
					    "cp-file": "^5.0.0",
 | 
				
			||||||
    "devtron": "1.4.0",
 | 
					    "devtron": "1.4.0",
 | 
				
			||||||
    "electron": "1.8.4",
 | 
					    "electron": "2.0.0",
 | 
				
			||||||
    "electron-builder": "20.8.1",
 | 
					    "electron-builder": "20.11.1",
 | 
				
			||||||
    "electron-connect": "0.6.2",
 | 
					    "electron-connect": "0.6.2",
 | 
				
			||||||
    "electron-debug": "1.4.0",
 | 
					    "electron-debug": "1.4.0",
 | 
				
			||||||
    "google-translate-api": "2.3.0",
 | 
					    "google-translate-api": "2.3.0",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								snap/gui/icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								snap/gui/icon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 2.6 KiB  | 
@@ -1,10 +1,10 @@
 | 
				
			|||||||
name: zulip
 | 
					name: zulip
 | 
				
			||||||
version: 1.8.2
 | 
					version: 2.0.0
 | 
				
			||||||
summary: Zulip
 | 
					summary: Zulip Desktop Client for Linux
 | 
				
			||||||
description: Zulip Desktop Client for Linux
 | 
					description: Zulip combines the immediacy of Slack with an email threading model. With Zulip, you can catch up on important conversations while ignoring irrelevant ones.
 | 
				
			||||||
confinement: strict
 | 
					confinement: strict
 | 
				
			||||||
grade: stable
 | 
					grade: stable
 | 
				
			||||||
icon: ../build/icon.png
 | 
					icon: snap/gui/icon.png
 | 
				
			||||||
apps:
 | 
					apps:
 | 
				
			||||||
  zulip:
 | 
					  zulip:
 | 
				
			||||||
    command: env TMPDIR=$XDG_RUNTIME_DIR desktop-launch $SNAP/zulip
 | 
					    command: env TMPDIR=$XDG_RUNTIME_DIR desktop-launch $SNAP/zulip
 | 
				
			||||||
@@ -32,6 +32,6 @@ parts:
 | 
				
			|||||||
      - libpulse0
 | 
					      - libpulse0
 | 
				
			||||||
      - libxss1
 | 
					      - libxss1
 | 
				
			||||||
      - libxtst6
 | 
					      - libxtst6
 | 
				
			||||||
    source: ../dist/linux-unpacked
 | 
					    source: dist/linux-unpacked
 | 
				
			||||||
    after:
 | 
					    after:
 | 
				
			||||||
      - desktop-gtk2
 | 
					      - desktop-gtk2
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user