mirror of
https://github.com/zulip/zulip-desktop.git
synced 2025-11-06 06:53:18 +00:00
Compare commits
28 Commits
v1.5.0
...
v1.6.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dcd2abca6e | ||
|
|
2fb9efb981 | ||
|
|
7245b6a110 | ||
|
|
bcb8ffb55f | ||
|
|
77094596a5 | ||
|
|
06ad44bdd7 | ||
|
|
e719ba139c | ||
|
|
9853e9226c | ||
|
|
f2c76b5ca3 | ||
|
|
e6dbff995b | ||
|
|
4578d4a5f7 | ||
|
|
4b895a2312 | ||
|
|
53c0428a3a | ||
|
|
0a1866abb5 | ||
|
|
ce862a4890 | ||
|
|
1b1ad2cd61 | ||
|
|
ead7a06308 | ||
|
|
6659dd5097 | ||
|
|
ed1f0f6d5b | ||
|
|
79acf8a6e1 | ||
|
|
8e0033f03e | ||
|
|
9144c2630d | ||
|
|
fae05fc3b1 | ||
|
|
73603a4fd2 | ||
|
|
a498ffc7d6 | ||
|
|
7afcf13401 | ||
|
|
89a292559d | ||
|
|
be14517caf |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -23,4 +23,6 @@ yarn-error.log*
|
||||
|
||||
# miscellaneous
|
||||
.idea
|
||||
config.gypi
|
||||
config.gypi
|
||||
.python-version
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
2.7.9
|
||||
@@ -7,9 +7,8 @@ const isDev = require('electron-is-dev');
|
||||
const ConfigUtil = require('./../renderer/js/utils/config-util.js');
|
||||
|
||||
function appUpdater() {
|
||||
// Don't initiate auto-updates in development and on Linux system
|
||||
// since autoUpdater doesn't work on Linux
|
||||
if (isDev || process.platform === 'linux') {
|
||||
// Don't initiate auto-updates in development
|
||||
if (isDev) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
const path = require('path');
|
||||
const electron = require('electron');
|
||||
const electronLocalshortcut = require('electron-localshortcut');
|
||||
const windowStateKeeper = require('electron-window-state');
|
||||
const isDev = require('electron-is-dev');
|
||||
const appMenu = require('./menu');
|
||||
const { appUpdater } = require('./autoupdater');
|
||||
const { crashHandler } = require('./crash-reporter');
|
||||
@@ -14,7 +14,10 @@ const { app, ipcMain } = electron;
|
||||
const BadgeSettings = require('./../renderer/js/pages/preference/badge-settings.js');
|
||||
|
||||
// Adds debug features like hotkeys for triggering dev tools and reload
|
||||
require('electron-debug')();
|
||||
// in development mode
|
||||
if (isDev) {
|
||||
require('electron-debug')();
|
||||
}
|
||||
|
||||
// Prevent window being garbage collected
|
||||
let mainWindow;
|
||||
@@ -94,9 +97,6 @@ function createMainWindow() {
|
||||
win.hide();
|
||||
}
|
||||
}
|
||||
|
||||
// Unregister all the shortcuts so that they don't interfare with other apps
|
||||
electronLocalshortcut.unregisterAll(mainWindow);
|
||||
});
|
||||
|
||||
win.setTitle('Zulip');
|
||||
@@ -124,33 +124,12 @@ function createMainWindow() {
|
||||
return win;
|
||||
}
|
||||
|
||||
function registerLocalShortcuts(page) {
|
||||
// Somehow, reload action cannot be overwritten by the menu item
|
||||
electronLocalshortcut.register(mainWindow, 'CommandOrControl+R', () => {
|
||||
page.send('reload-current-viewer');
|
||||
});
|
||||
|
||||
// Also adding these shortcuts because some users might want to use it instead of CMD/Left-Right
|
||||
electronLocalshortcut.register(mainWindow, 'CommandOrControl+[', () => {
|
||||
page.send('back');
|
||||
});
|
||||
|
||||
electronLocalshortcut.register(mainWindow, 'CommandOrControl+]', () => {
|
||||
page.send('forward');
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line max-params
|
||||
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
|
||||
event.preventDefault();
|
||||
callback(true);
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
// Unregister all the shortcuts so that they don't interfare with other apps
|
||||
electronLocalshortcut.unregisterAll(mainWindow);
|
||||
});
|
||||
|
||||
app.on('activate', () => {
|
||||
if (!mainWindow) {
|
||||
mainWindow = createMainWindow();
|
||||
@@ -165,8 +144,6 @@ app.on('ready', () => {
|
||||
|
||||
const page = mainWindow.webContents;
|
||||
|
||||
registerLocalShortcuts(page);
|
||||
|
||||
page.on('dom-ready', () => {
|
||||
mainWindow.show();
|
||||
});
|
||||
@@ -232,18 +209,8 @@ app.on('ready', () => {
|
||||
});
|
||||
|
||||
ipcMain.on('register-server-tab-shortcut', (event, index) => {
|
||||
electronLocalshortcut.register(mainWindow, `CommandOrControl+${index}`, () => {
|
||||
// Array index == Shown index - 1
|
||||
page.send('switch-server-tab', index - 1);
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on('local-shortcuts', (event, enable) => {
|
||||
if (enable) {
|
||||
registerLocalShortcuts(page);
|
||||
} else {
|
||||
electronLocalshortcut.unregisterAll(mainWindow);
|
||||
}
|
||||
// Array index == Shown index - 1
|
||||
page.send('switch-server-tab', index - 1);
|
||||
});
|
||||
|
||||
ipcMain.on('toggleAutoLauncher', (event, AutoLaunchValue) => {
|
||||
@@ -251,11 +218,6 @@ app.on('ready', () => {
|
||||
});
|
||||
});
|
||||
|
||||
app.on('will-quit', () => {
|
||||
// Unregister all the shortcuts so that they don't interfare with other apps
|
||||
electronLocalshortcut.unregisterAll(mainWindow);
|
||||
});
|
||||
|
||||
app.on('before-quit', () => {
|
||||
isQuitting = true;
|
||||
});
|
||||
|
||||
@@ -370,10 +370,20 @@ class AppMenu {
|
||||
}
|
||||
|
||||
static resetAppSettings() {
|
||||
const getAppPath = path.join(app.getPath('appData'), appName, 'window-state.json');
|
||||
// We save App's settings/configurations in following files
|
||||
const settingFiles = ['window-state.json', 'domain.json', 'settings.json'];
|
||||
|
||||
fs.unlink(getAppPath, () => {
|
||||
setTimeout(() => AppMenu.sendAction('clear-app-data'), 1000);
|
||||
settingFiles.forEach(settingFileName => {
|
||||
const getSettingFilesPath = path.join(app.getPath('appData'), appName, settingFileName);
|
||||
fs.access(getSettingFilesPath, error => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
} else {
|
||||
fs.unlink(getSettingFilesPath, () => {
|
||||
AppMenu.sendAction('clear-app-data');
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "zulip",
|
||||
"productName": "Zulip",
|
||||
"version": "1.5.0",
|
||||
"version": "1.6.0-beta",
|
||||
"description": "Zulip Desktop App",
|
||||
"license": "Apache-2.0",
|
||||
"email": "<svnitakash@gmail.com>",
|
||||
@@ -27,12 +27,10 @@
|
||||
"InstantMessaging"
|
||||
],
|
||||
"dependencies": {
|
||||
"electron-debug": "1.4.0",
|
||||
"electron-is-dev": "0.3.0",
|
||||
"electron-localshortcut": "2.0.2",
|
||||
"electron-log": "2.2.7",
|
||||
"electron-spellchecker": "1.2.0",
|
||||
"electron-updater": "2.8.9",
|
||||
"electron-spellchecker": "1.1.2",
|
||||
"electron-updater": "2.16.2",
|
||||
"node-json-db": "0.7.3",
|
||||
"request": "2.81.0",
|
||||
"wurl": "2.5.0",
|
||||
|
||||
@@ -83,7 +83,6 @@ class ServerManagerView {
|
||||
} else {
|
||||
this.openSettings('Servers');
|
||||
}
|
||||
ipcRenderer.send('local-shortcuts', true);
|
||||
}
|
||||
|
||||
initServer(server, index) {
|
||||
@@ -257,9 +256,6 @@ class ServerManagerView {
|
||||
// Clear DOM elements
|
||||
this.$tabsContainer.innerHTML = '';
|
||||
this.$webviewsContainer.innerHTML = '';
|
||||
|
||||
// Destroy shortcuts
|
||||
ipcRenderer.send('local-shortcuts', false);
|
||||
}
|
||||
|
||||
reloadView() {
|
||||
|
||||
@@ -45,7 +45,7 @@ class BadgeSettings {
|
||||
|
||||
updateOverlayIcon(messageCount, mainWindow) {
|
||||
if (!mainWindow.isFocused()) {
|
||||
mainWindow.flashFrame(true);
|
||||
mainWindow.flashFrame(ConfigUtil.getConfigItem('flashTaskbarOnMessage'));
|
||||
}
|
||||
if (messageCount === 0) {
|
||||
mainWindow.setOverlayIcon(null, '');
|
||||
|
||||
@@ -29,9 +29,13 @@ class GeneralSection extends BaseSection {
|
||||
<div class="setting-control"></div>
|
||||
</div>
|
||||
<div class="setting-row" id="badge-option">
|
||||
<div class="setting-description">Show app unread badge</div>
|
||||
<div class="setting-control"></div>
|
||||
</div>
|
||||
<div class="setting-description">Show app unread badge</div>
|
||||
<div class="setting-control"></div>
|
||||
</div>
|
||||
<div class="setting-row" id="flash-taskbar-option" style= "display:${process.platform === 'win32' ? '' : 'none'}">
|
||||
<div class="setting-description">Flash taskbar on new message</div>
|
||||
<div class="setting-control"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title">Desktop Notification</div>
|
||||
<div class="settings-card">
|
||||
@@ -57,6 +61,10 @@ class GeneralSection extends BaseSection {
|
||||
<div class="setting-description">Start app at login</div>
|
||||
<div class="setting-control"></div>
|
||||
</div>
|
||||
<div class="setting-row" id="enable-spellchecker-option">
|
||||
<div class="setting-description">Enable Spellchecker (requires restart)</div>
|
||||
<div class="setting-control"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title">Reset Application Data</div>
|
||||
<div class="settings-card">
|
||||
@@ -74,12 +82,19 @@ class GeneralSection extends BaseSection {
|
||||
this.props.$root.innerHTML = this.template();
|
||||
this.updateTrayOption();
|
||||
this.updateBadgeOption();
|
||||
this.updateUpdateOption();
|
||||
this.updateSilentOption();
|
||||
this.updateUpdateOption();
|
||||
this.updateSidebarOption();
|
||||
this.updateStartAtLoginOption();
|
||||
this.updateResetDataOption();
|
||||
this.showDesktopNotification();
|
||||
this.enableSpellchecker();
|
||||
|
||||
// Platform specific settings
|
||||
// Flashing taskbar on Windows
|
||||
if (process.platform === 'win32') {
|
||||
this.updateFlashTaskbar();
|
||||
}
|
||||
}
|
||||
|
||||
updateTrayOption() {
|
||||
@@ -108,6 +123,18 @@ class GeneralSection extends BaseSection {
|
||||
});
|
||||
}
|
||||
|
||||
updateFlashTaskbar() {
|
||||
this.generateSettingOption({
|
||||
$element: document.querySelector('#flash-taskbar-option .setting-control'),
|
||||
value: ConfigUtil.getConfigItem('flashTaskbarOnMessage', true),
|
||||
clickHandler: () => {
|
||||
const newValue = !ConfigUtil.getConfigItem('flashTaskbarOnMessage');
|
||||
ConfigUtil.setConfigItem('flashTaskbarOnMessage', newValue);
|
||||
this.updateFlashTaskbar();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateUpdateOption() {
|
||||
this.generateSettingOption({
|
||||
$element: document.querySelector('#betaupdate-option .setting-control'),
|
||||
@@ -170,6 +197,18 @@ class GeneralSection extends BaseSection {
|
||||
});
|
||||
}
|
||||
|
||||
enableSpellchecker() {
|
||||
this.generateSettingOption({
|
||||
$element: document.querySelector('#enable-spellchecker-option .setting-control'),
|
||||
value: ConfigUtil.getConfigItem('enableSpellchecker', true),
|
||||
clickHandler: () => {
|
||||
const newValue = !ConfigUtil.getConfigItem('enableSpellchecker');
|
||||
ConfigUtil.setConfigItem('enableSpellchecker', newValue);
|
||||
this.enableSpellchecker();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
clearAppDataDialog() {
|
||||
const clearAppDataMessage = 'By clicking proceed you will be removing all added accounts and preferences from Zulip. When the application restarts, it will be as if you are starting Zulip for the first time.';
|
||||
const getAppPath = path.join(app.getPath('appData'), app.getName());
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const BaseComponent = require(__dirname + '/js/components/base.js');
|
||||
const {ipcRenderer} = require('electron');
|
||||
const { ipcRenderer } = require('electron');
|
||||
|
||||
const ConfigUtil = require(__dirname + '/js/utils/config-util.js');
|
||||
|
||||
const Nav = require(__dirname + '/js/pages/preference/nav.js');
|
||||
const ServersSection = require(__dirname + '/js/pages/preference/servers-section.js');
|
||||
@@ -25,6 +27,7 @@ class PreferenceView extends BaseComponent {
|
||||
|
||||
this.setDefaultView();
|
||||
this.registerIpcs();
|
||||
this.setDefaultSettings();
|
||||
}
|
||||
|
||||
setDefaultView() {
|
||||
@@ -36,6 +39,30 @@ class PreferenceView extends BaseComponent {
|
||||
this.handleNavigation(nav);
|
||||
}
|
||||
|
||||
// Settings are initialized only when user clicks on General/Server/Network section settings
|
||||
// In case, user doesn't visit these section, those values set to be null automatically
|
||||
// This will make sure the default settings are correctly set to either true or false
|
||||
setDefaultSettings() {
|
||||
// Default settings which should be respected
|
||||
const settingOptions = {
|
||||
trayIcon: true,
|
||||
useProxy: false,
|
||||
showSidebar: true,
|
||||
badgeOption: true,
|
||||
startAtLogin: false,
|
||||
enableSpellchecker: true,
|
||||
showNotification: true,
|
||||
betaUpdate: false,
|
||||
silent: false
|
||||
};
|
||||
|
||||
for (const i in settingOptions) {
|
||||
if (ConfigUtil.getConfigItem(i) === null) {
|
||||
ConfigUtil.setConfigItem(i, settingOptions[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleNavigation(navItem) {
|
||||
this.nav.select(navItem);
|
||||
switch (navItem) {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const { ipcRenderer } = require('electron');
|
||||
const { spellChecker } = require('./spellchecker');
|
||||
const SetupSpellChecker = require('./spellchecker');
|
||||
|
||||
const ConfigUtil = require(__dirname + '/utils/config-util.js');
|
||||
|
||||
// eslint-disable-next-line import/no-unassigned-import
|
||||
require('./notification');
|
||||
|
||||
@@ -32,8 +35,15 @@ process.once('loaded', () => {
|
||||
|
||||
// To prevent failing this script on linux we need to load it after the document loaded
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Init spellchecker
|
||||
spellChecker();
|
||||
// Get the default language of the server
|
||||
const serverLanguage = page_params.default_language; // eslint-disable-line no-undef, camelcase
|
||||
|
||||
if (serverLanguage) {
|
||||
// Set spellcheker language
|
||||
ConfigUtil.setConfigItem('spellcheckerLanguage', serverLanguage);
|
||||
// Init spellchecker
|
||||
SetupSpellChecker.init();
|
||||
}
|
||||
|
||||
// redirect users to network troubleshooting page
|
||||
const getRestartButton = document.querySelector('.restart_get_events_button');
|
||||
@@ -43,3 +53,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Clean up spellchecker events after you navigate away from this page;
|
||||
// otherwise, you may experience errors
|
||||
window.addEventListener('beforeunload', () => {
|
||||
SetupSpellChecker.unsubscribeSpellChecker();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,29 +1,56 @@
|
||||
'use strict';
|
||||
|
||||
const {SpellCheckHandler, ContextMenuListener, ContextMenuBuilder} = require('electron-spellchecker');
|
||||
const { SpellCheckHandler, ContextMenuListener, ContextMenuBuilder } = require('electron-spellchecker');
|
||||
|
||||
function spellChecker() {
|
||||
// Implement spellcheck using electron api
|
||||
window.spellCheckHandler = new SpellCheckHandler();
|
||||
window.spellCheckHandler.attachToInput();
|
||||
const ConfigUtil = require(__dirname + '/utils/config-util.js');
|
||||
|
||||
// Start off as US English
|
||||
window.spellCheckHandler.switchLanguage('en-US');
|
||||
class SetupSpellChecker {
|
||||
init() {
|
||||
if (ConfigUtil.getConfigItem('enableSpellchecker')) {
|
||||
this.enableSpellChecker();
|
||||
}
|
||||
this.enableContextMenu();
|
||||
}
|
||||
|
||||
const contextMenuBuilder = new ContextMenuBuilder(window.spellCheckHandler);
|
||||
const contextMenuListener = new ContextMenuListener(info => {
|
||||
contextMenuBuilder.showPopupMenu(info);
|
||||
});
|
||||
enableSpellChecker() {
|
||||
try {
|
||||
this.SpellCheckHandler = new SpellCheckHandler();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up events after you navigate away from this page;
|
||||
// otherwise, you may experience errors
|
||||
window.addEventListener('beforeunload', () => {
|
||||
// eslint-disable-next-line no-undef
|
||||
spellCheckHandler.unsubscribe();
|
||||
contextMenuListener.unsubscribe();
|
||||
});
|
||||
enableContextMenu() {
|
||||
if (this.SpellCheckHandler) {
|
||||
this.SpellCheckHandler.attachToInput();
|
||||
|
||||
const userLanguage = ConfigUtil.getConfigItem('spellcheckerLanguage');
|
||||
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
process.platform === 'darwin' ?
|
||||
// On macOS, spellchecker fails to auto-detect the lanugage user is typing in
|
||||
// that's why we need to mention it explicitly
|
||||
this.SpellCheckHandler.switchLanguage(userLanguage) :
|
||||
// On Linux and Windows, spellchecker can automatically detects the language the user is typing in
|
||||
// and silently switches on the fly; thus we can start off as US English
|
||||
this.SpellCheckHandler.switchLanguage('en-US');
|
||||
}
|
||||
|
||||
const contextMenuBuilder = new ContextMenuBuilder(this.SpellCheckHandler);
|
||||
this.contextMenuListener = new ContextMenuListener(info => {
|
||||
contextMenuBuilder.showPopupMenu(info);
|
||||
});
|
||||
}
|
||||
|
||||
unsubscribeSpellChecker() {
|
||||
// eslint-disable-next-line no-undef
|
||||
if (this.SpellCheckHandler) {
|
||||
this.SpellCheckHandler.unsubscribe();
|
||||
}
|
||||
if (this.contextMenuListener) {
|
||||
this.contextMenuListener.unsubscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
spellChecker
|
||||
};
|
||||
module.exports = new SetupSpellChecker();
|
||||
|
||||
@@ -110,8 +110,10 @@ class DomainUtil {
|
||||
return new Promise((resolve, reject) => {
|
||||
request(checkDomain, (error, response) => {
|
||||
const certsError =
|
||||
['Error: self signed certificate',
|
||||
'Error: unable to verify the first certificate'
|
||||
[
|
||||
'Error: self signed certificate',
|
||||
'Error: unable to verify the first certificate',
|
||||
'Error: unable to get local issuer certificate'
|
||||
];
|
||||
if (!error && response.statusCode !== 404) {
|
||||
// Correct
|
||||
@@ -152,7 +154,9 @@ class DomainUtil {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
reject('Not a valid Zulip server');
|
||||
const invalidZulipServerError = `${domain} does not appear to be a valid Zulip server. Make sure that \
|
||||
(1) you can connect to that URL in a web browser and \n (2) if you need a proxy to connect to the Internet, that you've configured your proxy in the Network settings`;
|
||||
reject(invalidZulipServerError);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
BIN
app/resources/tray/trayosx@2x.png
Normal file
BIN
app/resources/tray/trayosx@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
app/resources/tray/trayosx@3x.png
Normal file
BIN
app/resources/tray/trayosx@3x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/resources/tray/trayosx@4x.png
Normal file
BIN
app/resources/tray/trayosx@4x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "zulip",
|
||||
"productName": "Zulip",
|
||||
"version": "1.5.0",
|
||||
"version": "1.6.0-beta",
|
||||
"main": "./app/main",
|
||||
"description": "Zulip Desktop App",
|
||||
"license": "Apache-2.0",
|
||||
@@ -106,7 +106,7 @@
|
||||
"devDependencies": {
|
||||
"assert": "1.4.1",
|
||||
"devtron": "1.4.0",
|
||||
"electron-builder": "19.29.1",
|
||||
"electron-builder": "19.45.5",
|
||||
"electron": "1.6.14",
|
||||
"electron-connect": "0.6.2",
|
||||
"gulp": "3.9.1",
|
||||
@@ -115,7 +115,8 @@
|
||||
"chai": "4.1.1",
|
||||
"spectron": "3.7.2",
|
||||
"xo": "0.18.2",
|
||||
"pre-commit": "1.2.2"
|
||||
"pre-commit": "1.2.2",
|
||||
"electron-debug": "1.4.0"
|
||||
},
|
||||
"xo": {
|
||||
"parserOptions": {
|
||||
|
||||
Reference in New Issue
Block a user