Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BrowserView: Remove webview and initialize BrowserView. #793

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a674aa9
BrowserView: Add View wrapper Class for BrowserView.
vsvipul Jul 18, 2019
6ce25b9
BrowserView: Add ViewManager for managing multiple Views.
vsvipul Jul 18, 2019
b87f697
BrowserView: Add BrowserView to index.ts.
vsvipul Jul 18, 2019
de2752f
BrowserView: Remove webview props from tab.ts.
vsvipul Jul 18, 2019
de48c22
BrowserView: Remove webview usage and initialize BrowserView.
vsvipul Jul 19, 2019
713f9f0
BrowserView: Add logic for badgeCount update.
vsvipul Jul 22, 2019
b58fa62
BrowserView: Remove tooltips and use title instead.
vsvipul Jul 22, 2019
8d35f29
BrowserView: Add favicon-update event and fix view function calls.
vsvipul Jul 23, 2019
a5eedd3
BrowserView: Destroy all views during reload-app.
vsvipul Jul 25, 2019
c76fa3b
BrowserView: Improvements to loading indicator.
vsvipul Jul 25, 2019
bb1c0a7
BrowserView: Improve ipc names.
vsvipul Jul 26, 2019
2321503
BrowserView: Add logic to handle external links.
vsvipul Jul 27, 2019
86e4f41
BrowserView: Rename canGoBackButton to maybeEnableGoBackButton.
vsvipul Jul 27, 2019
af79ff6
BrowserView: Implement userAgent and updateBadge onload.
vsvipul Jul 29, 2019
593b07c
BrowserView: Add logic to show network error page.
vsvipul Jul 30, 2019
c49d2d9
BrowserView: Add logic for custom CSS.
vsvipul Jul 30, 2019
d3383dc
BrowserView: Call fixBounds before setting view.
vsvipul Jul 31, 2019
1bd3fa8
BrowserView: Update deps.
vsvipul Jul 31, 2019
decf47e
gitignore: Add .vscode to gitignore.
vsvipul Aug 4, 2019
10a2050
BrowserView: Show views only when dom content loaded.
vsvipul Aug 4, 2019
2d0153d
BrowserView: Rename webview instances to view and handle tray toggle.
vsvipul Aug 7, 2019
ad6ceae
BrowserView: Add decoded server name when pushing to tabs.
vsvipul Aug 11, 2019
6feda14
BrowserView: Make separate callViewFunction.
vsvipul Aug 11, 2019
181ac44
BrowserView: Fix focus switching.
vsvipul Aug 12, 2019
b1ca530
Remove unnecessary translation-util.js file.
vsvipul Aug 15, 2019
9c4a3de
BrowserView: Remove show dom content on load.
vsvipul Aug 15, 2019
ca5b45f
BrowserView: Add documentation and fix fullScreen.
vsvipul Aug 16, 2019
3b6c356
Add integer check for messageCountAll
vsvipul Sep 2, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ config.gypi

# Ignore all the typescript compiled files
app/**/*.js

# text editor files
.vscode/
19 changes: 14 additions & 5 deletions app/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import AppMenu = require('./menu');
import BadgeSettings = require('../renderer/js/pages/preference/badge-settings');
import ConfigUtil = require('../renderer/js/utils/config-util');
import ProxyUtil = require('../renderer/js/utils/proxy-util');
import ViewManager = require('./viewmanager');

interface PatchedGlobal extends NodeJS.Global {
mainWindowState: windowStateKeeper.State;
Expand All @@ -28,7 +29,8 @@ if (isDev) {
}

// Prevent window being garbage collected
let mainWindow: Electron.BrowserWindow;
// eslint-disable-next-line import/no-mutable-exports
export let mainWindow: Electron.BrowserWindow;
let badgeCount: number;

let isQuitting = false;
Expand Down Expand Up @@ -81,7 +83,7 @@ function createMainWindow(): Electron.BrowserWindow {
webPreferences: {
plugins: true,
nodeIntegration: true,
partition: 'persist:webviewsession'
partition: 'persist:viewsession'
},
show: false
});
Expand All @@ -108,10 +110,12 @@ function createMainWindow(): Electron.BrowserWindow {
win.setTitle('Zulip');

win.on('enter-full-screen', () => {
ViewManager.fixBounds();
akashnimare marked this conversation as resolved.
Show resolved Hide resolved
win.webContents.send('enter-fullscreen');
});

win.on('leave-full-screen', () => {
ViewManager.fixBounds();
win.webContents.send('leave-fullscreen');
});

Expand Down Expand Up @@ -222,7 +226,7 @@ app.on('ready', () => {
// height: mainWindowState.height - paddingHeight,
// webPreferences: {
// plugins: true,
// partition: 'persist:webviewsession'
// partition: 'persist:viewsession'
// }
// });
// pdfWindow.loadURL(url);
Expand All @@ -231,8 +235,9 @@ app.on('ready', () => {
// pdfWindow.setMenu(null);
// });

// Reload full app not just webview, useful in debugging
// Reload full app not just view, useful in debugging
ipcMain.on('reload-full-app', () => {
ViewManager.destroyAll();
mainWindow.reload();
page.send('destroytray');
});
Expand Down Expand Up @@ -261,6 +266,10 @@ app.on('ready', () => {
page.send('toggle-autohide-menubar', showMenubar, true);
});

ipcMain.on('fix-bounds', () => {
vsvipul marked this conversation as resolved.
Show resolved Hide resolved
ViewManager.fixBounds();
});

ipcMain.on('update-badge', (_event: Electron.IpcMessageEvent, messageCount: number) => {
badgeCount = messageCount;
BadgeSettings.updateBadge(badgeCount, mainWindow);
Expand All @@ -279,7 +288,7 @@ app.on('ready', () => {
AppMenu.setMenu(props);
const activeTab = props.tabs[props.activeTabIndex];
if (activeTab) {
mainWindow.setTitle(`Zulip - ${activeTab.webview.props.name}`);
mainWindow.setTitle(`Zulip - ${activeTab.props.name}`);
vsvipul marked this conversation as resolved.
Show resolved Hide resolved
}
});

Expand Down
236 changes: 236 additions & 0 deletions app/main/view.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
'use strict';
vsvipul marked this conversation as resolved.
Show resolved Hide resolved

import { BrowserView, BrowserWindow, app, dialog } from 'electron';

import path = require('path');
import fs = require('fs');
import ConfigUtil = require('../renderer/js/utils/config-util');
import SystemUtil = require('../renderer/js/utils/system-util');
const shouldSilentView = ConfigUtil.getConfigItem('silent');

export interface ViewProps {
index: number;
url: string;
name: string;
nodeIntegration: boolean;
preload: boolean;
}

// Class View is a wrapper around electron's BrowserView
// Multiples views are handled by ViewManager
export class View extends BrowserView {
index: number;
priyank-p marked this conversation as resolved.
Show resolved Hide resolved
url: string;
zoomFactor: number;
customCSS: string | null;
loading: boolean;

constructor(public props: ViewProps) {
super({
webPreferences: {
preload: props.preload ? `${__dirname}/../renderer/js/preload.js` : '',
nodeIntegration: props.nodeIntegration,
partition: 'persist:view',
plugins: true
}
});
this.index = props.index;
this.url = props.url;
this.zoomFactor = 1.0;
this.loading = false;
this.customCSS = ConfigUtil.getConfigItem('customCSS');
this.registerListeners();
this.setUserAgent();
}

registerListeners(): void {
if (shouldSilentView) {
this.webContents.addListener('dom-ready', () => {
this.webContents.setAudioMuted(true);
});
}

this.webContents.addListener('did-navigate-in-page', () => {
const isSettingsPage = this.url.includes('renderer/preference.html');
if (isSettingsPage) {
return;
}
this.maybeEnableGoBackButton();
});

this.webContents.addListener('did-navigate', () => {
this.maybeEnableGoBackButton();
});

this.webContents.addListener('did-start-loading', () => {
this.switchLoadingIndicator(true);
});

this.webContents.addListener('dom-ready', () => {
this.switchLoadingIndicator(false);
this.handleCSS();
});

this.webContents.addListener('did-fail-load', (e: Event, errorCode: number, errorDescription: string) => {
const hasConnectivityErr = SystemUtil.connectivityERR.includes(errorDescription);
if (hasConnectivityErr) {
console.error('error', errorDescription);
this.sendAction('network-error');
}
});

this.webContents.addListener('did-finish-load', () => {
const title = this.webContents.getTitle();
this.updateBadgeCount(title);
});

this.webContents.addListener('did-stop-loading', () => {
this.switchLoadingIndicator(false);
});

this.webContents.addListener('page-title-updated', (e: Event, title: string) => {
this.updateBadgeCount(title);
});

this.webContents.addListener('page-favicon-updated', (e: Event, favicons: string[]) => {
// This returns a string of favicons URL. If there is a PM counts in unread messages then the URL would be like
// https://chat.zulip.org/static/images/favicon/favicon-pms.png
if (favicons[0].indexOf('favicon-pms') > 0 && process.platform === 'darwin') {
// This api is only supported on macOS
app.dock.setBadge('●');
// bounce the dock
if (ConfigUtil.getConfigItem('dockBouncing')) {
app.dock.bounce();
}
}
});

this.webContents.addListener('new-window', (e: Event, urlToOpen: string) => {
e.preventDefault();
this.sendAction('handle-link', this.index, urlToOpen);
});
}

handleCSS(): void {
// Injecting preload css in view to override some css rules
this.webContents.insertCSS(fs.readFileSync(path.join(__dirname, '../renderer/css/preload.css'), 'utf8'));

// get customCSS again from config util to avoid warning user again
this.customCSS = ConfigUtil.getConfigItem('customCSS');
if (this.customCSS) {
if (!fs.existsSync(this.customCSS)) {
this.customCSS = null;
ConfigUtil.setConfigItem('customCSS', null);
const errMsg = 'The custom css previously set is deleted!';
dialog.showErrorBox('custom css file deleted!', errMsg);
return;
}

this.webContents.insertCSS(fs.readFileSync(path.resolve(__dirname, this.customCSS), 'utf8'));
}
}

setUserAgent(): void {
let userAgent = SystemUtil.getUserAgent();
if (!userAgent) {
const viewUserAgent = this.webContents.getUserAgent();
SystemUtil.setUserAgent(viewUserAgent);
userAgent = SystemUtil.getUserAgent();
}
this.webContents.setUserAgent(userAgent);
}

zoomIn(): void {
this.zoomFactor += 0.1;
this.webContents.setZoomFactor(this.zoomFactor);
}

zoomOut(): void {
this.zoomFactor -= 0.1;
this.webContents.setZoomFactor(this.zoomFactor);
}

zoomActualSize(): void {
this.zoomFactor = 1.0;
this.webContents.setZoomFactor(this.zoomFactor);
}

focus(): void {
this.webContents.focus();
}

reload(): void {
this.switchLoadingIndicator(true);
this.webContents.reload();
}

switchLoadingIndicator(state: boolean): void {
this.loading = state;
const isSettingsPage = this.url.includes('renderer/preference.html');
if (!isSettingsPage) {
this.sendAction('switch-loading', state, this.url);
}
}

forward(): void {
if (this.webContents.canGoForward()) {
this.webContents.goForward();
}
}

back(): void {
if (this.webContents.canGoBack()) {
this.webContents.goBack();
}
}

logOut(): void {
this.webContents.executeJavaScript('logout()');
}

showShortcut(): void {
this.webContents.executeJavaScript('shortcut()');
}

toggleDevTools(): void {
this.webContents.toggleDevTools();
}

// If page can go back, enables back button, otherwise disables it.
maybeEnableGoBackButton(): void {
if (this.webContents.canGoBack()) {
this.sendAction('switch-back', true);
} else {
this.sendAction('switch-back', false);
}
}

getBadgeCount(title: string): number {
const messageCountInTitle = (/\((\d+)\)/).exec(title);
return messageCountInTitle ? Number(messageCountInTitle[1]) : 0;
}

downloadUrl(url: string): void {
this.webContents.downloadURL(url);
}

loadUrl(url: string): void {
this.webContents.loadURL(url);
}

updateBadgeCount(title: string): void {
const badgeCount = this.getBadgeCount(title);
this.sendAction('update-badge-count', badgeCount, this.url);
}

// Send an action to renderer process.
sendAction(action: any, ...params: any[]): void {
const win = BrowserWindow.getAllWindows()[0];

if (process.platform === 'darwin') {
win.restore();
}

win.webContents.send(action, ...params);
}
}
Loading