mirror of
https://github.com/zulip/zulip-desktop.git
synced 2025-11-03 05:23:17 +00:00
@@ -140,17 +140,16 @@ class ServerManagerView {
|
||||
this.tabIndex = 0;
|
||||
}
|
||||
|
||||
init(): void {
|
||||
this.loadProxy().then(() => {
|
||||
this.initDefaultSettings();
|
||||
this.initSidebar();
|
||||
if (EnterpriseUtil.configFile) {
|
||||
this.initPresetOrgs();
|
||||
}
|
||||
this.initTabs();
|
||||
this.initActions();
|
||||
this.registerIpcs();
|
||||
});
|
||||
async init(): Promise<void> {
|
||||
await this.loadProxy();
|
||||
this.initDefaultSettings();
|
||||
this.initSidebar();
|
||||
if (EnterpriseUtil.configFile) {
|
||||
this.initPresetOrgs();
|
||||
}
|
||||
this.initTabs();
|
||||
this.initActions();
|
||||
this.registerIpcs();
|
||||
}
|
||||
|
||||
async loadProxy(): Promise<void> {
|
||||
@@ -867,13 +866,12 @@ class ServerManagerView {
|
||||
this.openSettings('AddServer');
|
||||
});
|
||||
|
||||
ipcRenderer.on('reload-proxy', (event: Event, showAlert: boolean) => {
|
||||
this.loadProxy().then(() => {
|
||||
if (showAlert) {
|
||||
alert('Proxy settings saved!');
|
||||
ipcRenderer.send('reload-full-app');
|
||||
}
|
||||
});
|
||||
ipcRenderer.on('reload-proxy', async (event: Event, showAlert: boolean) => {
|
||||
await this.loadProxy();
|
||||
if (showAlert) {
|
||||
alert('Proxy settings saved!');
|
||||
ipcRenderer.send('reload-full-app');
|
||||
}
|
||||
});
|
||||
|
||||
ipcRenderer.on('toggle-sidebar', (event: Event, show: boolean) => {
|
||||
@@ -942,17 +940,15 @@ class ServerManagerView {
|
||||
|
||||
ipcRenderer.on('update-realm-icon', (event: Event, serverURL: string, iconURL: string) => {
|
||||
// TODO: TypeScript - Type annotate getDomains() or this domain paramter.
|
||||
DomainUtil.getDomains().forEach((domain: any, index: number) => {
|
||||
DomainUtil.getDomains().forEach(async (domain: any, index: number) => {
|
||||
if (domain.url.includes(serverURL)) {
|
||||
DomainUtil.saveServerIcon(iconURL).then((localIconUrl: string) => {
|
||||
const serverImgsSelector = '.tab .server-icons';
|
||||
const serverImgs: NodeListOf<HTMLImageElement> = document.querySelectorAll(serverImgsSelector);
|
||||
serverImgs[index].src = localIconUrl;
|
||||
|
||||
domain.icon = localIconUrl;
|
||||
DomainUtil.db.push(`/domains[${index}]`, domain, true);
|
||||
DomainUtil.reloadDB();
|
||||
});
|
||||
const localIconUrl: string = await DomainUtil.saveServerIcon(iconURL);
|
||||
const serverImgsSelector = '.tab .server-icons';
|
||||
const serverImgs: NodeListOf<HTMLImageElement> = document.querySelectorAll(serverImgsSelector);
|
||||
serverImgs[index].src = localIconUrl;
|
||||
domain.icon = localIconUrl;
|
||||
DomainUtil.db.push(`/domains[${index}]`, domain, true);
|
||||
DomainUtil.reloadDB();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -58,16 +58,18 @@ class NewServerForm extends BaseComponent {
|
||||
this.$newServerUrl = this.$newServerForm.querySelectorAll('input.setting-input-value')[0] as HTMLInputElement;
|
||||
}
|
||||
|
||||
submitFormHandler(): void {
|
||||
async submitFormHandler(): Promise<void> {
|
||||
this.$saveServerButton.innerHTML = 'Connecting...';
|
||||
DomainUtil.checkDomain(this.$newServerUrl.value).then(serverConf => {
|
||||
DomainUtil.addDomain(serverConf).then(() => {
|
||||
this.props.onChange(this.props.index);
|
||||
});
|
||||
}, errorMessage => {
|
||||
let serverConf;
|
||||
try {
|
||||
serverConf = await DomainUtil.checkDomain(this.$newServerUrl.value);
|
||||
} catch (errorMessage) {
|
||||
this.$saveServerButton.innerHTML = 'Connect';
|
||||
alert(errorMessage);
|
||||
});
|
||||
return;
|
||||
}
|
||||
await DomainUtil.addDomain(serverConf);
|
||||
this.props.onChange(this.props.index);
|
||||
}
|
||||
|
||||
openCreateNewOrgExternalLink(): void {
|
||||
|
||||
@@ -51,69 +51,59 @@ const config = {
|
||||
thick: process.platform === 'win32'
|
||||
};
|
||||
|
||||
const renderCanvas = function (arg: number): Promise<HTMLCanvasElement> {
|
||||
const renderCanvas = function (arg: number): HTMLCanvasElement {
|
||||
config.unreadCount = arg;
|
||||
|
||||
return new Promise(resolve => {
|
||||
const SIZE = config.size * config.pixelRatio;
|
||||
const PADDING = SIZE * 0.05;
|
||||
const CENTER = SIZE / 2;
|
||||
const HAS_COUNT = config.showUnreadCount && config.unreadCount;
|
||||
const color = config.unreadCount ? config.unreadColor : config.readColor;
|
||||
const backgroundColor = config.unreadCount ? config.unreadBackgroundColor : config.readBackgroundColor;
|
||||
const SIZE = config.size * config.pixelRatio;
|
||||
const PADDING = SIZE * 0.05;
|
||||
const CENTER = SIZE / 2;
|
||||
const HAS_COUNT = config.showUnreadCount && config.unreadCount;
|
||||
const color = config.unreadCount ? config.unreadColor : config.readColor;
|
||||
const backgroundColor = config.unreadCount ? config.unreadBackgroundColor : config.readBackgroundColor;
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = SIZE;
|
||||
canvas.height = SIZE;
|
||||
const ctx = canvas.getContext('2d');
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = SIZE;
|
||||
canvas.height = SIZE;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// Circle
|
||||
// If (!config.thick || config.thick && HAS_COUNT) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(CENTER, CENTER, (SIZE / 2) - PADDING, 0, 2 * Math.PI, false);
|
||||
ctx.fillStyle = backgroundColor;
|
||||
ctx.fill();
|
||||
ctx.lineWidth = SIZE / (config.thick ? 10 : 20);
|
||||
ctx.strokeStyle = backgroundColor;
|
||||
ctx.stroke();
|
||||
// Count or Icon
|
||||
if (HAS_COUNT) {
|
||||
ctx.fillStyle = color;
|
||||
ctx.textAlign = 'center';
|
||||
if (config.unreadCount > 99) {
|
||||
ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.4}px Helvetica`;
|
||||
ctx.fillText('99+', CENTER, CENTER + (SIZE * 0.15));
|
||||
} else if (config.unreadCount < 10) {
|
||||
ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.5}px Helvetica`;
|
||||
ctx.fillText(String(config.unreadCount), CENTER, CENTER + (SIZE * 0.2));
|
||||
} else {
|
||||
ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.5}px Helvetica`;
|
||||
ctx.fillText(String(config.unreadCount), CENTER, CENTER + (SIZE * 0.15));
|
||||
}
|
||||
|
||||
resolve(canvas);
|
||||
// Circle
|
||||
// If (!config.thick || config.thick && HAS_COUNT) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(CENTER, CENTER, (SIZE / 2) - PADDING, 0, 2 * Math.PI, false);
|
||||
ctx.fillStyle = backgroundColor;
|
||||
ctx.fill();
|
||||
ctx.lineWidth = SIZE / (config.thick ? 10 : 20);
|
||||
ctx.strokeStyle = backgroundColor;
|
||||
ctx.stroke();
|
||||
// Count or Icon
|
||||
if (HAS_COUNT) {
|
||||
ctx.fillStyle = color;
|
||||
ctx.textAlign = 'center';
|
||||
if (config.unreadCount > 99) {
|
||||
ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.4}px Helvetica`;
|
||||
ctx.fillText('99+', CENTER, CENTER + (SIZE * 0.15));
|
||||
} else if (config.unreadCount < 10) {
|
||||
ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.5}px Helvetica`;
|
||||
ctx.fillText(String(config.unreadCount), CENTER, CENTER + (SIZE * 0.2));
|
||||
} else {
|
||||
ctx.font = `${config.thick ? 'bold ' : ''}${SIZE * 0.5}px Helvetica`;
|
||||
ctx.fillText(String(config.unreadCount), CENTER, CENTER + (SIZE * 0.15));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return canvas;
|
||||
};
|
||||
/**
|
||||
* Renders the tray icon as a native image
|
||||
* @param arg: Unread count
|
||||
* @return the native image
|
||||
*/
|
||||
const renderNativeImage = function (arg: number): Promise<NativeImage> {
|
||||
return Promise.resolve()
|
||||
.then(() => renderCanvas(arg))
|
||||
.then(canvas => {
|
||||
const pngData = nativeImage.createFromDataURL(canvas.toDataURL('image/png')).toPNG();
|
||||
|
||||
// TODO: Fix the function to correctly use Promise correctly.
|
||||
// the Promise.resolve().then(...) above is useless we should
|
||||
// start with renderCanvas(arg).then
|
||||
// eslint-disable-next-line promise/no-return-wrap
|
||||
return Promise.resolve(nativeImage.createFromBuffer(pngData, {
|
||||
scaleFactor: config.pixelRatio
|
||||
}));
|
||||
});
|
||||
const renderNativeImage = function (arg: number): NativeImage {
|
||||
const canvas = renderCanvas(arg);
|
||||
const pngData = nativeImage.createFromDataURL(canvas.toDataURL('image/png')).toPNG();
|
||||
return nativeImage.createFromBuffer(pngData, {
|
||||
scaleFactor: config.pixelRatio
|
||||
});
|
||||
};
|
||||
|
||||
function sendAction(action: string): void {
|
||||
@@ -187,10 +177,9 @@ ipcRenderer.on('tray', (_event: Event, arg: number): void => {
|
||||
window.tray.setToolTip('No unread messages');
|
||||
} else {
|
||||
unread = arg;
|
||||
renderNativeImage(arg).then(image => {
|
||||
window.tray.setImage(image);
|
||||
window.tray.setToolTip(arg + ' unread messages');
|
||||
});
|
||||
const image = renderNativeImage(arg);
|
||||
window.tray.setImage(image);
|
||||
window.tray.setToolTip(arg + ' unread messages');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -208,10 +197,9 @@ function toggleTray(): void {
|
||||
state = true;
|
||||
createTray();
|
||||
if (process.platform === 'linux' || process.platform === 'win32') {
|
||||
renderNativeImage(unread).then(image => {
|
||||
window.tray.setImage(image);
|
||||
window.tray.setToolTip(unread + ' unread messages');
|
||||
});
|
||||
const image = renderNativeImage(unread);
|
||||
window.tray.setImage(image);
|
||||
window.tray.setToolTip(unread + ' unread messages');
|
||||
}
|
||||
ConfigUtil.setConfigItem('trayIcon', true);
|
||||
}
|
||||
|
||||
@@ -75,23 +75,18 @@ class DomainUtil {
|
||||
this.db.push(`/domains[${index}]`, server, true);
|
||||
}
|
||||
|
||||
addDomain(server: any): Promise<void> {
|
||||
async addDomain(server: any): Promise<void> {
|
||||
const { ignoreCerts } = server;
|
||||
return new Promise(resolve => {
|
||||
if (server.icon) {
|
||||
this.saveServerIcon(server, ignoreCerts).then(localIconUrl => {
|
||||
server.icon = localIconUrl;
|
||||
this.db.push('/domains[]', server, true);
|
||||
this.reloadDB();
|
||||
resolve();
|
||||
});
|
||||
} else {
|
||||
server.icon = defaultIconUrl;
|
||||
this.db.push('/domains[]', server, true);
|
||||
this.reloadDB();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
if (server.icon) {
|
||||
const localIconUrl = await this.saveServerIcon(server, ignoreCerts);
|
||||
server.icon = localIconUrl;
|
||||
this.db.push('/domains[]', server, true);
|
||||
this.reloadDB();
|
||||
} else {
|
||||
server.icon = defaultIconUrl;
|
||||
this.db.push('/domains[]', server, true);
|
||||
this.reloadDB();
|
||||
}
|
||||
}
|
||||
|
||||
removeDomains(): void {
|
||||
@@ -189,7 +184,7 @@ class DomainUtil {
|
||||
}
|
||||
}
|
||||
|
||||
getServerSettings(domain: any, ignoreCerts = false): Promise<object | string> {
|
||||
async getServerSettings(domain: any, ignoreCerts = false): Promise<object | string> {
|
||||
const serverSettingsOptions = {
|
||||
url: domain + '/api/v1/server_settings',
|
||||
...RequestUtil.requestOptions(domain, ignoreCerts)
|
||||
@@ -218,7 +213,7 @@ class DomainUtil {
|
||||
});
|
||||
}
|
||||
|
||||
saveServerIcon(server: any, ignoreCerts = false): Promise<string> {
|
||||
async saveServerIcon(server: any, ignoreCerts = false): Promise<string> {
|
||||
const url = server.icon;
|
||||
const domain = server.url;
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ class ProxyUtil {
|
||||
}
|
||||
|
||||
// TODO: Refactor to async function
|
||||
resolveSystemProxy(mainWindow: Electron.BrowserWindow): void {
|
||||
async resolveSystemProxy(mainWindow: Electron.BrowserWindow): Promise<void> {
|
||||
const page = mainWindow.webContents;
|
||||
const ses = page.session;
|
||||
const resolveProxyUrl = 'www.example.com';
|
||||
@@ -121,17 +121,16 @@ class ProxyUtil {
|
||||
return socksString;
|
||||
})();
|
||||
|
||||
Promise.all([httpProxy, httpsProxy, ftpProxy, socksProxy]).then(values => {
|
||||
let proxyString = '';
|
||||
values.forEach(proxy => {
|
||||
proxyString += proxy;
|
||||
});
|
||||
ConfigUtil.setConfigItem('systemProxyRules', proxyString);
|
||||
const useSystemProxy = ConfigUtil.getConfigItem('useSystemProxy');
|
||||
if (useSystemProxy) {
|
||||
ConfigUtil.setConfigItem('proxyRules', proxyString);
|
||||
}
|
||||
const values = await Promise.all([httpProxy, httpsProxy, ftpProxy, socksProxy]);
|
||||
let proxyString = '';
|
||||
values.forEach(proxy => {
|
||||
proxyString += proxy;
|
||||
});
|
||||
ConfigUtil.setConfigItem('systemProxyRules', proxyString);
|
||||
const useSystemProxy = ConfigUtil.getConfigItem('useSystemProxy');
|
||||
if (useSystemProxy) {
|
||||
ConfigUtil.setConfigItem('proxyRules', proxyString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class ReconnectUtil {
|
||||
});
|
||||
}
|
||||
|
||||
isOnline(): Promise<boolean> {
|
||||
async isOnline(): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
try {
|
||||
const ignoreCerts = DomainUtil.shouldIgnoreCerts(this.url);
|
||||
@@ -60,42 +60,32 @@ class ReconnectUtil {
|
||||
|
||||
pollInternetAndReload(): void {
|
||||
this.fibonacciBackoff.backoff();
|
||||
this.fibonacciBackoff.on('ready', () => {
|
||||
this._checkAndReload().then(status => {
|
||||
if (status) {
|
||||
this.fibonacciBackoff.reset();
|
||||
} else {
|
||||
this.fibonacciBackoff.backoff();
|
||||
}
|
||||
});
|
||||
this.fibonacciBackoff.on('ready', async () => {
|
||||
if (await this._checkAndReload()) {
|
||||
this.fibonacciBackoff.reset();
|
||||
} else {
|
||||
this.fibonacciBackoff.backoff();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Make this a async function
|
||||
_checkAndReload(): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
if (!this.alreadyReloaded) { // eslint-disable-line no-negated-condition
|
||||
this.isOnline()
|
||||
.then((online: boolean) => {
|
||||
if (online) {
|
||||
ipcRenderer.send('forward-message', 'reload-viewer');
|
||||
logger.log('You\'re back online.');
|
||||
return resolve(true);
|
||||
}
|
||||
|
||||
logger.log('There is no internet connection, try checking network cables, modem and router.');
|
||||
const errMsgHolder = document.querySelector('#description');
|
||||
if (errMsgHolder) {
|
||||
errMsgHolder.innerHTML = `
|
||||
<div>Your internet connection doesn't seem to work properly!</div>
|
||||
<div>Verify that it works and then click try again.</div>`;
|
||||
}
|
||||
return resolve(false);
|
||||
});
|
||||
} else {
|
||||
return resolve(true);
|
||||
}
|
||||
});
|
||||
async _checkAndReload(): Promise<boolean> {
|
||||
if (this.alreadyReloaded) {
|
||||
return true;
|
||||
}
|
||||
if (await this.isOnline()) {
|
||||
ipcRenderer.send('forward-message', 'reload-viewer');
|
||||
logger.log('You\'re back online.');
|
||||
return true;
|
||||
}
|
||||
logger.log('There is no internet connection, try checking network cables, modem and router.');
|
||||
const errMsgHolder = document.querySelector('#description');
|
||||
if (errMsgHolder) {
|
||||
errMsgHolder.innerHTML = `
|
||||
<div>Your internet connection doesn't seem to work properly!</div>
|
||||
<div>Verify that it works and then click try again.</div>`;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -255,7 +255,6 @@
|
||||
"node/no-deprecated-api": 0,
|
||||
"@typescript-eslint/member-ordering": "off",
|
||||
"@typescript-eslint/no-dynamic-delete": "off",
|
||||
"@typescript-eslint/promise-function-async": "off",
|
||||
"@typescript-eslint/restrict-plus-operands": "off",
|
||||
"@typescript-eslint/restrict-template-expressions": "off",
|
||||
"import/default": 0,
|
||||
|
||||
Reference in New Issue
Block a user