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: Rebased. #1013

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1236beb
BrowserView: Add View wrapper Class for BrowserView.
vsvipul Jul 18, 2019
b9ddcd9
BrowserView: Add ViewManager for managing multiple Views.
vsvipul Jul 18, 2019
ed4203e
BrowserView: Add BrowserView to index.ts.
vsvipul Jul 18, 2019
a6c1819
BrowserView: Remove webview props from tab.ts.
vsvipul Jul 18, 2019
15c74c2
BrowserView: Remove webview usage and initialize BrowserView.
vsvipul Jul 19, 2019
3d2683b
BrowserView: Add logic for badgeCount update.
vsvipul Jul 22, 2019
96cb004
BrowserView: Remove tooltips and use title instead.
vsvipul Jul 22, 2019
700fb67
BrowserView: Add favicon-update event and fix view function calls.
vsvipul Jul 23, 2019
b9fd00a
BrowserView: Destroy all views during reload-app.
vsvipul Jul 25, 2019
ee6d155
BrowserView: Improvements to loading indicator.
vsvipul Jul 25, 2019
b983008
BrowserView: Improve ipc names.
vsvipul Jul 26, 2019
4d2d930
BrowserView: Add logic to handle external links.
vsvipul Jul 27, 2019
e9e40bf
BrowserView: Add logic to show network error page.
vsvipul Jul 30, 2019
147059f
BrowserView: Call fixBounds before setting view.
vsvipul Jul 31, 2019
080d6b4
gitignore: Add .vscode to gitignore.
vsvipul Aug 4, 2019
4319303
BrowserView: Show views only when dom content loaded.
vsvipul Aug 4, 2019
7cbc93b
BrowserView: Rename webview instances to view and handle tray toggle.
vsvipul Aug 7, 2019
4f245f9
BrowserView: Make separate callViewFunction.
vsvipul Aug 11, 2019
f58c78e
BrowserView: Fix focus switching.
vsvipul Aug 12, 2019
d924e19
BrowserView: Remove show dom content on load.
vsvipul Aug 15, 2019
9459d06
BrowserView: Add documentation and fix fullScreen.
vsvipul Aug 16, 2019
8e2835b
BrowserView: Port reconnection logic to BV.
vsvipul Sep 2, 2019
d17e744
BrowserView: Get enabled flag for notifs settings.
kanishk98 Oct 9, 2019
cc95947
BrowserView: Port notification settings to BV.
kanishk98 Oct 9, 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 @@ -42,3 +42,6 @@ config.gypi

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

# text editor files
.vscode/
17 changes: 13 additions & 4 deletions app/main/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ViewManager = require('./viewmanager');

import electron, {app, dialog, ipcMain, session} from 'electron';
import fs from 'fs';
Expand All @@ -19,7 +20,8 @@ import {setAutoLaunch} from './startup';
let mainWindowState: windowStateKeeper.State;

// 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 @@ -121,10 +123,12 @@ function createMainWindow(): Electron.BrowserWindow {
win.setTitle('Zulip');

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

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

Expand Down Expand Up @@ -302,7 +306,7 @@ ${error}`
// height: mainWindowState.height - paddingHeight,
// webPreferences: {
// plugins: true,
// partition: 'persist:webviewsession'
// partition: 'persist:viewsession'
// }
// });
// pdfWindow.loadURL(url);
Expand All @@ -311,8 +315,9 @@ ${error}`
// 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 All @@ -337,6 +342,10 @@ ${error}`
page.send('toggle-autohide-menubar', showMenubar, true);
});

ipcMain.on('fix-bounds', () => {
ViewManager.fixBounds();
});

ipcMain.on('update-badge', (_event: Electron.IpcMainEvent, messageCount: number) => {
badgeCount = messageCount;
BadgeSettings.updateBadge(badgeCount, mainWindow);
Expand All @@ -355,7 +364,7 @@ ${error}`
AppMenu.setMenu(props);
const activeTab = props.tabs[props.activeTabIndex];
if (activeTab) {
mainWindow.setTitle(`Zulip - ${activeTab.webviewName}`);
mainWindow.setTitle(`Zulip - ${activeTab.name}`);
}
});

Expand Down
205 changes: 205 additions & 0 deletions app/main/view.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
'use strict';

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

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;
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();
}

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.canGoBackButton();
});

this.webContents.addListener('did-navigate', () => {
const url = this.webContents.getURL();
const loggedIn = !url.endsWith('/login/');
this.sendAction('set-logged-in', loggedIn, this.index);
this.canGoBackButton();
});

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

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

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-stop-loading', () => {
this.switchLoadingIndicator(false);
});

this.webContents.addListener('page-title-updated', (e: Event, title: string) => {
const badgeCount = this.getBadgeCount(title);
this.sendAction('update-badge-count', badgeCount, this.url);
});

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);
});
}

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()');
}

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

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

canGoBackButton(): 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