mirror of
https://github.com/zulip/zulip-desktop.git
synced 2025-10-28 18:43:50 +00:00
Merge pull request #180 from geeeeeeeeek/issue/refinements-on-server-side
Refinements on the main process
This commit is contained in:
@@ -7,24 +7,10 @@ function appUpdater() {
|
||||
const log = require('electron-log');
|
||||
log.transports.file.level = 'info';
|
||||
autoUpdater.logger = log;
|
||||
/*
|
||||
AutoUpdater.on('error', err => log.info(err));
|
||||
autoUpdater.on('checking-for-update', () => log.info('checking-for-update'));
|
||||
autoUpdater.on('update-available', () => log.info('update-available'));
|
||||
autoUpdater.on('update-not-available', () => log.info('update-not-available'));
|
||||
*/
|
||||
|
||||
// Ask the user if update is available
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
autoUpdater.on('update-downloaded', (event, info) => {
|
||||
// Let message = app.getName() + ' ' + info.releaseName + ' is now available. It will be installed the next time you restart the application.';
|
||||
// if (info.releaseNotes) {
|
||||
// const splitNotes = info.releaseNotes.split(/[^\r]\n/);
|
||||
// message += '\n\nRelease notes:\n';
|
||||
// splitNotes.forEach(notes => {
|
||||
// message += notes + '\n\n';
|
||||
// });
|
||||
// }
|
||||
// Ask user to update the app
|
||||
dialog.showMessageBox({
|
||||
type: 'question',
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
const wurl = require('wurl');
|
||||
|
||||
// Check link if it's internal/external
|
||||
function linkIsInternal(currentUrl, newUrl) {
|
||||
const currentDomain = wurl('hostname', currentUrl);
|
||||
const newDomain = wurl('hostname', newUrl);
|
||||
return currentDomain === newDomain;
|
||||
}
|
||||
|
||||
// We'll be needing this to open images in default browser
|
||||
const skipImages = '.jpg|.gif|.png|.jpeg|.JPG|.PNG';
|
||||
|
||||
module.exports = {
|
||||
linkIsInternal,
|
||||
skipImages
|
||||
};
|
||||
@@ -9,8 +9,6 @@ const BrowserWindow = electron.BrowserWindow;
|
||||
const shell = electron.shell;
|
||||
const appName = app.getName();
|
||||
|
||||
const {about} = require('./windowmanager');
|
||||
|
||||
function sendAction(action) {
|
||||
const win = BrowserWindow.getAllWindows()[0];
|
||||
|
||||
@@ -135,8 +133,10 @@ const darwinTpl = [
|
||||
submenu: [
|
||||
{
|
||||
label: 'Zulip desktop',
|
||||
click() {
|
||||
about();
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
sendAction('open-about');
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -270,8 +270,10 @@ const otherTpl = [
|
||||
submenu: [
|
||||
{
|
||||
label: 'Zulip desktop',
|
||||
click() {
|
||||
about();
|
||||
click(item, focusedWindow) {
|
||||
if (focusedWindow) {
|
||||
sendAction('open-about');
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
'use strict';
|
||||
const path = require('path');
|
||||
const electron = require('electron');
|
||||
const ipc = require('electron').ipcMain;
|
||||
|
||||
const APP_ICON = path.join(__dirname, '../resources', 'Icon');
|
||||
|
||||
const iconPath = () => {
|
||||
return APP_ICON + (process.platform === 'win32' ? '.ico' : '.png');
|
||||
};
|
||||
let domainWindow;
|
||||
let aboutWindow;
|
||||
|
||||
function onClosed() {
|
||||
// Dereference the window
|
||||
domainWindow = null;
|
||||
aboutWindow = null;
|
||||
}
|
||||
|
||||
// Change Zulip server Window
|
||||
function createdomainWindow() {
|
||||
const domainwin = new electron.BrowserWindow({
|
||||
title: 'Switch Server',
|
||||
frame: false,
|
||||
height: 300,
|
||||
resizable: false,
|
||||
width: 400,
|
||||
show: false,
|
||||
icon: iconPath()
|
||||
|
||||
});
|
||||
const domainURL = 'file://' + path.join(__dirname, '../renderer', 'pref.html');
|
||||
domainwin.loadURL(domainURL);
|
||||
domainwin.on('closed', onClosed);
|
||||
|
||||
return domainwin;
|
||||
}
|
||||
// Call this window onClick addDomain in tray
|
||||
function addDomain() {
|
||||
domainWindow = createdomainWindow();
|
||||
domainWindow.once('ready-to-show', () => {
|
||||
domainWindow.show();
|
||||
});
|
||||
setTimeout(() => {
|
||||
if (domainWindow !== null) {
|
||||
if (!domainWindow.isDestroyed()) {
|
||||
domainWindow.destroy();
|
||||
}
|
||||
}
|
||||
}, 15000);
|
||||
}
|
||||
// About window
|
||||
function createAboutWindow() {
|
||||
const aboutwin = new electron.BrowserWindow({
|
||||
width: 500,
|
||||
height: 500,
|
||||
title: 'About Zulip Desktop',
|
||||
show: false,
|
||||
center: true,
|
||||
fullscreen: false,
|
||||
fullscreenable: false,
|
||||
resizable: false
|
||||
});
|
||||
const aboutURL = 'file://' + path.join(__dirname, '../renderer', 'about.html');
|
||||
aboutwin.loadURL(aboutURL);
|
||||
aboutwin.on('closed', onClosed);
|
||||
|
||||
// Stop page to update it's title
|
||||
aboutwin.on('page-title-updated', e => {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
aboutwin.on('closed', onClosed);
|
||||
|
||||
return aboutwin;
|
||||
}
|
||||
|
||||
// Call this onClick About in tray
|
||||
function about() {
|
||||
aboutWindow = createAboutWindow();
|
||||
aboutWindow.once('ready-to-show', () => {
|
||||
aboutWindow.show();
|
||||
});
|
||||
}
|
||||
|
||||
ipc.on('trayabout', event => {
|
||||
if (event) {
|
||||
about();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
addDomain,
|
||||
about
|
||||
};
|
||||
@@ -116,11 +116,11 @@ html, body {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.tab .settings-tab {
|
||||
.tab .functional-tab {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.tab .settings-tab i {
|
||||
.tab .functional-tab i {
|
||||
font-size: 28px;
|
||||
line-height: 36px;
|
||||
}
|
||||
@@ -151,6 +151,17 @@ html, body {
|
||||
.tab .server-tab-badge {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab .server-tab-badge.close-button {
|
||||
width: 16px;
|
||||
padding: 0 0 0 1px;
|
||||
}
|
||||
|
||||
.tab .server-tab-badge.close-button i {
|
||||
font-size: 13px;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
/*******************
|
||||
* Webview Area *
|
||||
*******************/
|
||||
|
||||
BIN
app/renderer/img/icon.png
Normal file
BIN
app/renderer/img/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
43
app/renderer/js/components/functional-tab.js
Normal file
43
app/renderer/js/components/functional-tab.js
Normal file
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
const Tab = require(__dirname + '/../components/tab.js');
|
||||
|
||||
class FunctionalTab extends Tab {
|
||||
template() {
|
||||
return `<div class="tab">
|
||||
<div class="server-tab-badge close-button">
|
||||
<i class="material-icons">close</i>
|
||||
</div>
|
||||
<div class="server-tab functional-tab">
|
||||
<i class="material-icons">${this.props.materialIcon}</i>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
init() {
|
||||
this.$el = this.generateNodeFromTemplate(this.template());
|
||||
this.props.$root.appendChild(this.$el);
|
||||
|
||||
this.$closeButton = this.$el.getElementsByClassName('server-tab-badge')[0];
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
registerListeners() {
|
||||
super.registerListeners();
|
||||
|
||||
this.$el.addEventListener('mouseover', () => {
|
||||
this.$closeButton.classList.add('active');
|
||||
});
|
||||
|
||||
this.$el.addEventListener('mouseout', () => {
|
||||
this.$closeButton.classList.remove('active');
|
||||
});
|
||||
|
||||
this.$closeButton.addEventListener('click', e => {
|
||||
this.props.onDestroy();
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FunctionalTab;
|
||||
31
app/renderer/js/components/server-tab.js
Normal file
31
app/renderer/js/components/server-tab.js
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const Tab = require(__dirname + '/../components/tab.js');
|
||||
|
||||
class ServerTab extends Tab {
|
||||
template() {
|
||||
return `<div class="tab">
|
||||
<div class="server-tab-badge"></div>
|
||||
<div class="server-tab" style="background-image: url(${this.props.icon});"></div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
init() {
|
||||
super.init();
|
||||
|
||||
this.$badge = this.$el.getElementsByClassName('server-tab-badge')[0];
|
||||
}
|
||||
|
||||
updateBadge(count) {
|
||||
if (count > 0) {
|
||||
const formattedCount = count > 999 ? '1K+' : count;
|
||||
|
||||
this.$badge.innerHTML = formattedCount;
|
||||
this.$badge.classList.add('active');
|
||||
} else {
|
||||
this.$badge.classList.remove('active');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ServerTab;
|
||||
@@ -3,65 +3,43 @@
|
||||
const BaseComponent = require(__dirname + '/../components/base.js');
|
||||
|
||||
class Tab extends BaseComponent {
|
||||
constructor(params) {
|
||||
constructor(props) {
|
||||
super();
|
||||
|
||||
const {url, icon, name, type, $root, onClick} = params;
|
||||
this.url = url;
|
||||
this.name = name;
|
||||
this.icon = icon;
|
||||
this.type = type;
|
||||
this.$root = $root;
|
||||
this.onClick = onClick;
|
||||
this.props = props;
|
||||
this.webview = this.props.webview;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
template() {
|
||||
if (this.type === Tab.SERVER_TAB) {
|
||||
return `<div class="tab" domain="${this.url}">
|
||||
<div class="server-tab-badge"></div>
|
||||
<div class="server-tab" style="background-image: url(${this.icon});"></div>
|
||||
</div>`;
|
||||
} else {
|
||||
return `<div class="tab" domain="${this.url}">
|
||||
<div class="server-tab-badge"></div>
|
||||
<div class="server-tab settings-tab">
|
||||
<i class="material-icons md-48">settings</i>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
this.$el = this.generateNodeFromTemplate(this.template());
|
||||
this.$badge = this.$el.getElementsByClassName('server-tab-badge')[0];
|
||||
this.$root.appendChild(this.$el);
|
||||
this.props.$root.appendChild(this.$el);
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
updateBadge(count) {
|
||||
if (count > 0) {
|
||||
const formattedCount = count > 999 ? '1K+' : count;
|
||||
|
||||
this.$badge.innerHTML = formattedCount;
|
||||
this.$badge.classList.add('active');
|
||||
} else {
|
||||
this.$badge.classList.remove('active');
|
||||
}
|
||||
registerListeners() {
|
||||
this.$el.addEventListener('click', this.props.onClick);
|
||||
}
|
||||
|
||||
registerListeners() {
|
||||
this.$el.addEventListener('click', this.onClick);
|
||||
isLoading() {
|
||||
return this.webview.isLoading;
|
||||
}
|
||||
|
||||
activate() {
|
||||
this.$el.classList.add('active');
|
||||
this.webview.load();
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
this.$el.classList.remove('active');
|
||||
this.webview.hide();
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.$el.parentNode.removeChild(this.$el);
|
||||
this.webview.$el.parentNode.removeChild(this.webview.$el);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,38 +2,28 @@
|
||||
|
||||
const DomainUtil = require(__dirname + '/../utils/domain-util.js');
|
||||
const SystemUtil = require(__dirname + '/../utils/system-util.js');
|
||||
const {linkIsInternal, skipImages} = require(__dirname + '/../../../main/link-helper');
|
||||
const LinkUtil = require(__dirname + '/../utils/link-util.js');
|
||||
const {app, dialog, shell} = require('electron').remote;
|
||||
const {ipcRenderer} = require('electron');
|
||||
|
||||
const BaseComponent = require(__dirname + '/../components/base.js');
|
||||
|
||||
class WebView extends BaseComponent {
|
||||
constructor(params) {
|
||||
constructor(props) {
|
||||
super();
|
||||
|
||||
const {$root, url, index, name, isActive, onTitleChange, nodeIntegration} = params;
|
||||
this.$root = $root;
|
||||
this.index = index;
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
this.nodeIntegration = nodeIntegration;
|
||||
this.props = props;
|
||||
|
||||
this.onTitleChange = onTitleChange;
|
||||
this.zoomFactor = 1.0;
|
||||
this.loading = false;
|
||||
this.isActive = isActive;
|
||||
this.domainUtil = new DomainUtil();
|
||||
this.systemUtil = new SystemUtil();
|
||||
this.badgeCount = 0;
|
||||
}
|
||||
|
||||
template() {
|
||||
return `<webview
|
||||
id="webview-${this.index}"
|
||||
class="disabled"
|
||||
src="${this.url}"
|
||||
${this.nodeIntegration ? 'nodeIntegration' : ''}
|
||||
src="${this.props.url}"
|
||||
${this.props.nodeIntegration ? 'nodeIntegration' : ''}
|
||||
disablewebsecurity
|
||||
preload="js/preload.js"
|
||||
webpreferences="allowRunningInsecureContent, javascript=yes">
|
||||
@@ -42,7 +32,7 @@ class WebView extends BaseComponent {
|
||||
|
||||
init() {
|
||||
this.$el = this.generateNodeFromTemplate(this.template());
|
||||
this.$root.appendChild(this.$el);
|
||||
this.props.$root.appendChild(this.$el);
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
@@ -50,9 +40,9 @@ class WebView extends BaseComponent {
|
||||
registerListeners() {
|
||||
this.$el.addEventListener('new-window', event => {
|
||||
const {url} = event;
|
||||
const domainPrefix = this.domainUtil.getDomain(this.index).url;
|
||||
const domainPrefix = DomainUtil.getDomain(this.props.index).url;
|
||||
|
||||
if (linkIsInternal(domainPrefix, url) && url.match(skipImages) === null) {
|
||||
if (LinkUtil.isInternal(domainPrefix, url)) {
|
||||
event.preventDefault();
|
||||
this.$el.loadURL(url);
|
||||
} else {
|
||||
@@ -64,14 +54,14 @@ class WebView extends BaseComponent {
|
||||
this.$el.addEventListener('page-title-updated', event => {
|
||||
const {title} = event;
|
||||
this.badgeCount = this.getBadgeCount(title);
|
||||
this.onTitleChange();
|
||||
this.props.onTitleChange();
|
||||
});
|
||||
|
||||
this.$el.addEventListener('dom-ready', this.show.bind(this));
|
||||
|
||||
this.$el.addEventListener('did-fail-load', event => {
|
||||
const {errorDescription} = event;
|
||||
const hasConnectivityErr = (this.systemUtil.connectivityERR.indexOf(errorDescription) >= 0);
|
||||
const hasConnectivityErr = (SystemUtil.connectivityERR.indexOf(errorDescription) >= 0);
|
||||
if (hasConnectivityErr) {
|
||||
console.error('error', errorDescription);
|
||||
this.checkConnectivity();
|
||||
@@ -79,10 +69,10 @@ class WebView extends BaseComponent {
|
||||
});
|
||||
|
||||
this.$el.addEventListener('did-start-loading', () => {
|
||||
let userAgent = this.systemUtil.getUserAgent();
|
||||
let userAgent = SystemUtil.getUserAgent();
|
||||
if (!userAgent) {
|
||||
this.systemUtil.setUserAgent(this.$el.getUserAgent());
|
||||
userAgent = this.systemUtil.getUserAgent();
|
||||
SystemUtil.setUserAgent(this.$el.getUserAgent());
|
||||
userAgent = SystemUtil.getUserAgent();
|
||||
}
|
||||
this.$el.setUserAgent(userAgent);
|
||||
});
|
||||
@@ -95,14 +85,14 @@ class WebView extends BaseComponent {
|
||||
|
||||
show() {
|
||||
// Do not show WebView if another tab was selected and this tab should be in background.
|
||||
if (!this.isActive()) {
|
||||
if (!this.props.isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$el.classList.remove('disabled');
|
||||
this.focus();
|
||||
this.loading = false;
|
||||
this.onTitleChange(this.$el.getTitle());
|
||||
this.props.onTitleChange(this.$el.getTitle());
|
||||
}
|
||||
|
||||
focus() {
|
||||
|
||||
@@ -5,7 +5,8 @@ const {ipcRenderer} = require('electron');
|
||||
|
||||
const DomainUtil = require(__dirname + '/js/utils/domain-util.js');
|
||||
const WebView = require(__dirname + '/js/components/webview.js');
|
||||
const Tab = require(__dirname + '/js/components/tab.js');
|
||||
const ServerTab = require(__dirname + '/js/components/server-tab.js');
|
||||
const FunctionalTab = require(__dirname + '/js/components/functional-tab.js');
|
||||
|
||||
class ServerManagerView {
|
||||
constructor() {
|
||||
@@ -17,21 +18,19 @@ class ServerManagerView {
|
||||
this.$settingsButton = $actionsContainer.querySelector('#settings-action');
|
||||
this.$content = document.getElementById('content');
|
||||
|
||||
this.settingsTabIndex = -1;
|
||||
this.activeTabIndex = -1;
|
||||
this.webviews = [];
|
||||
this.tabs = [];
|
||||
this.functionalTabs = {};
|
||||
}
|
||||
|
||||
init() {
|
||||
this.domainUtil = new DomainUtil();
|
||||
this.initTabs();
|
||||
this.initActions();
|
||||
this.registerIpcs();
|
||||
}
|
||||
|
||||
initTabs() {
|
||||
const servers = this.domainUtil.getDomains();
|
||||
const servers = DomainUtil.getDomains();
|
||||
if (servers.length > 0) {
|
||||
for (let i = 0; i < servers.length; i++) {
|
||||
this.initServer(servers[i], i);
|
||||
@@ -43,94 +42,115 @@ class ServerManagerView {
|
||||
}
|
||||
|
||||
initServer(server, index) {
|
||||
this.tabs.push(new Tab({
|
||||
url: server.url,
|
||||
name: server.alias,
|
||||
this.tabs.push(new ServerTab({
|
||||
icon: server.icon,
|
||||
type: Tab.SERVER_TAB,
|
||||
$root: this.$tabsContainer,
|
||||
onClick: this.activateTab.bind(this, index)
|
||||
}));
|
||||
this.webviews.push(new WebView({
|
||||
$root: this.$content,
|
||||
index,
|
||||
url: server.url,
|
||||
name: server.alias,
|
||||
isActive: () => {
|
||||
return index === this.activeTabIndex;
|
||||
},
|
||||
onTitleChange: this.updateBadge.bind(this),
|
||||
nodeIntegration: false
|
||||
onClick: this.activateTab.bind(this, index),
|
||||
webview: new WebView({
|
||||
$root: this.$content,
|
||||
index,
|
||||
url: server.url,
|
||||
name: server.alias,
|
||||
isActive: () => {
|
||||
return index === this.activeTabIndex;
|
||||
},
|
||||
onTitleChange: this.updateBadge.bind(this),
|
||||
nodeIntegration: false
|
||||
})
|
||||
}));
|
||||
}
|
||||
|
||||
initActions() {
|
||||
this.$reloadButton.addEventListener('click', () => {
|
||||
this.webviews[this.activeTabIndex].reload();
|
||||
this.tabs[this.activeTabIndex].webview.reload();
|
||||
});
|
||||
this.$addServerButton.addEventListener('click', this.openSettings.bind(this));
|
||||
this.$settingsButton.addEventListener('click', this.openSettings.bind(this));
|
||||
}
|
||||
|
||||
openSettings() {
|
||||
if (this.settingsTabIndex !== -1) {
|
||||
this.activateTab(this.settingsTabIndex);
|
||||
openFunctionalTab(tabProps) {
|
||||
if (this.functionalTabs[tabProps.name]) {
|
||||
this.activateTab(this.functionalTabs[tabProps.name]);
|
||||
return;
|
||||
}
|
||||
const url = 'file://' + __dirname + '/preference.html';
|
||||
|
||||
this.settingsTabIndex = this.webviews.length;
|
||||
this.functionalTabs[tabProps.name] = this.tabs.length;
|
||||
|
||||
this.tabs.push(new Tab({
|
||||
url,
|
||||
name: 'Settings',
|
||||
type: Tab.SETTINGS_TAB,
|
||||
this.tabs.push(new FunctionalTab({
|
||||
materialIcon: tabProps.materialIcon,
|
||||
$root: this.$tabsContainer,
|
||||
onClick: this.activateTab.bind(this, this.settingsTabIndex)
|
||||
onClick: this.activateTab.bind(this, this.functionalTabs[tabProps.name]),
|
||||
onDestroy: this.destroyTab.bind(this, tabProps.name, this.functionalTabs[tabProps.name]),
|
||||
webview: new WebView({
|
||||
$root: this.$content,
|
||||
index: this.functionalTabs[tabProps.name],
|
||||
url: tabProps.url,
|
||||
name: tabProps.name,
|
||||
isActive: () => {
|
||||
return this.functionalTabs[tabProps.name] === this.activeTabIndex;
|
||||
},
|
||||
onTitleChange: this.updateBadge.bind(this),
|
||||
nodeIntegration: true
|
||||
})
|
||||
}));
|
||||
|
||||
this.webviews.push(new WebView({
|
||||
$root: this.$content,
|
||||
index: this.settingsTabIndex,
|
||||
url,
|
||||
name: 'Settings',
|
||||
isActive: () => {
|
||||
return this.settingsTabIndex === this.activeTabIndex;
|
||||
},
|
||||
onTitleChange: this.updateBadge.bind(this),
|
||||
nodeIntegration: true
|
||||
}));
|
||||
|
||||
this.activateTab(this.settingsTabIndex);
|
||||
this.activateTab(this.functionalTabs[tabProps.name]);
|
||||
}
|
||||
|
||||
activateTab(index) {
|
||||
if (this.webviews[index].loading) {
|
||||
openSettings() {
|
||||
this.openFunctionalTab({
|
||||
name: 'Settings',
|
||||
materialIcon: 'settings',
|
||||
url: `file://${__dirname}/preference.html`
|
||||
});
|
||||
}
|
||||
|
||||
openAbout() {
|
||||
this.openFunctionalTab({
|
||||
name: 'About',
|
||||
materialIcon: 'sentiment_very_satisfied',
|
||||
url: `file://${__dirname}/about.html`
|
||||
});
|
||||
}
|
||||
|
||||
activateTab(index, hideOldTab = true) {
|
||||
if (this.tabs[index].loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.activeTabIndex !== -1) {
|
||||
if (this.activeTabIndex === index) {
|
||||
return;
|
||||
} else {
|
||||
} else if (hideOldTab) {
|
||||
this.tabs[this.activeTabIndex].deactivate();
|
||||
this.webviews[this.activeTabIndex].hide();
|
||||
}
|
||||
}
|
||||
|
||||
this.tabs[index].activate();
|
||||
|
||||
this.activeTabIndex = index;
|
||||
this.webviews[index].load();
|
||||
this.tabs[index].activate();
|
||||
}
|
||||
|
||||
destroyTab(name, index) {
|
||||
if (this.tabs[index].loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.tabs[index].destroy();
|
||||
|
||||
delete this.tabs[index];
|
||||
delete this.functionalTabs[name];
|
||||
|
||||
this.activateTab(0, false);
|
||||
}
|
||||
|
||||
updateBadge() {
|
||||
let messageCountAll = 0;
|
||||
for (let i = 0; i < this.webviews.length; i++) {
|
||||
const count = this.webviews[i].badgeCount;
|
||||
messageCountAll += count;
|
||||
|
||||
this.tabs[i].updateBadge(count);
|
||||
for (let i = 0; i < this.tabs.length; i++) {
|
||||
if (this.tabs[i] && this.tabs[i].updateBadge) {
|
||||
const count = this.tabs[i].webview.badgeCount;
|
||||
messageCountAll += count;
|
||||
this.tabs[i].updateBadge(count);
|
||||
}
|
||||
}
|
||||
|
||||
ipcRenderer.send('update-badge', messageCountAll);
|
||||
@@ -152,7 +172,7 @@ class ServerManagerView {
|
||||
|
||||
for (const key in webviewListeners) {
|
||||
ipcRenderer.on(key, () => {
|
||||
const activeWebview = this.webviews[this.activeTabIndex];
|
||||
const activeWebview = this.tabs[this.activeTabIndex].webview;
|
||||
if (activeWebview) {
|
||||
activeWebview[webviewListeners[key]]();
|
||||
}
|
||||
@@ -160,6 +180,7 @@ class ServerManagerView {
|
||||
}
|
||||
|
||||
ipcRenderer.on('open-settings', this.openSettings.bind(this));
|
||||
ipcRenderer.on('open-about', this.openAbout.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,12 @@ class PreferenceView {
|
||||
}
|
||||
|
||||
init() {
|
||||
this.domainUtil = new DomainUtil();
|
||||
this.initServers();
|
||||
this.initActions();
|
||||
}
|
||||
|
||||
initServers() {
|
||||
const servers = this.domainUtil.getDomains();
|
||||
const servers = DomainUtil.getDomains();
|
||||
this.$serverInfoContainer.innerHTML = servers.length ? '' : 'Add your first server to get started!';
|
||||
|
||||
this.initNewServerForm();
|
||||
@@ -64,7 +63,7 @@ class PreferenceView {
|
||||
</div>`;
|
||||
this.$serverInfoContainer.appendChild(this.insertNode(serverInfoTemplate));
|
||||
document.getElementById(`delete-server-action-${index}`).addEventListener('click', () => {
|
||||
this.domainUtil.removeDomain(index);
|
||||
DomainUtil.removeDomain(index);
|
||||
this.initServers();
|
||||
// alert('Success. Reload to apply changes.');
|
||||
ipcRenderer.send('reload-main');
|
||||
@@ -109,13 +108,13 @@ class PreferenceView {
|
||||
this.$newServerButton.classList.add('hidden');
|
||||
});
|
||||
this.$saveServerButton.addEventListener('click', () => {
|
||||
this.domainUtil.checkDomain(this.$newServerUrl.value).then(domain => {
|
||||
DomainUtil.checkDomain(this.$newServerUrl.value).then(domain => {
|
||||
const server = {
|
||||
alias: this.$newServerAlias.value,
|
||||
url: domain,
|
||||
icon: this.$newServerIcon.value
|
||||
};
|
||||
this.domainUtil.addDomain(server);
|
||||
DomainUtil.addDomain(server);
|
||||
this.$saveServerButton.classList.add('hidden');
|
||||
this.$newServerButton.classList.remove('hidden');
|
||||
this.$newServerForm.classList.add('hidden');
|
||||
@@ -117,7 +117,7 @@ const createTray = function () {
|
||||
const contextMenu = Menu.buildFromTemplate([{
|
||||
label: 'About',
|
||||
click() {
|
||||
ipcRenderer.send('trayabout');
|
||||
sendAction('open-about');
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -4,9 +4,17 @@ const {app} = require('electron').remote;
|
||||
const JsonDB = require('node-json-db');
|
||||
const request = require('request');
|
||||
|
||||
const defaultIconUrl = 'https://chat.zulip.org/static/images/logo/zulip-icon-128x128.271d0f6a0ca2.png';
|
||||
let instance = null;
|
||||
|
||||
const defaultIconUrl = __dirname + '../../../img/icon.png';
|
||||
class DomainUtil {
|
||||
constructor() {
|
||||
if (instance) {
|
||||
return instance;
|
||||
} else {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
this.db = new JsonDB(app.getPath('userData') + '/domain.json', true, true);
|
||||
// Migrate from old schema
|
||||
if (this.db.getData('/').domain) {
|
||||
@@ -16,6 +24,8 @@ class DomainUtil {
|
||||
});
|
||||
this.db.delete('/domain');
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
getDomains() {
|
||||
@@ -69,4 +79,4 @@ class DomainUtil {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DomainUtil;
|
||||
module.exports = new DomainUtil();
|
||||
|
||||
29
app/renderer/js/utils/link-util.js
Normal file
29
app/renderer/js/utils/link-util.js
Normal file
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
const wurl = require('wurl');
|
||||
|
||||
let instance = null;
|
||||
|
||||
class LinkUtil {
|
||||
constructor() {
|
||||
if (instance) {
|
||||
return instance;
|
||||
} else {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
isInternal(currentUrl, newUrl) {
|
||||
const currentDomain = wurl('hostname', currentUrl);
|
||||
const newDomain = wurl('hostname', newUrl);
|
||||
|
||||
const skipImages = '.jpg|.gif|.png|.jpeg|.JPG|.PNG';
|
||||
|
||||
// We'll be needing this to open images in default browser
|
||||
return (currentDomain === newDomain) && !newUrl.match(skipImages);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new LinkUtil();
|
||||
@@ -52,4 +52,4 @@ class SystemUtil {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SystemUtil;
|
||||
module.exports = new SystemUtil();
|
||||
|
||||
@@ -41,5 +41,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script src="js/preference.js"></script>
|
||||
<script src="js/pages/preference.js"></script>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user