Skip to content
This repository has been archived by the owner on Jun 4, 2023. It is now read-only.

fix: BrowserView dialogs recycling #456

Merged
merged 25 commits into from
May 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions src/main/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { WindowsService } from './windows-service';
import { StorageService } from './services/storage';
import { getMainMenu } from './menus/main';
import { runAutoUpdaterService } from './services';
import { DialogsService } from './services/dialogs-service';

export class Application {
public static instance = new Application();
Expand All @@ -21,6 +22,8 @@ export class Application {

public windows = new WindowsService();

public dialogs = new DialogsService();

public start() {
const gotTheLock = app.requestSingleInstanceLock();

Expand Down Expand Up @@ -83,6 +86,7 @@ export class Application {
checkFiles();

this.storage.run();
this.dialogs.run();

this.windows.open();

Expand Down
81 changes: 31 additions & 50 deletions src/main/dialogs/add-bookmark.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,46 @@
import { AppWindow } from '../windows';
import { Dialog } from '.';
import { DIALOG_MARGIN, DIALOG_MARGIN_TOP } from '~/constants/design';
import { BrowserWindow } from 'electron';
import { Application } from '../application';
import { DIALOG_MARGIN_TOP, DIALOG_MARGIN } from '~/constants/design';
import { IBookmark } from '~/interfaces';

const WIDTH = 366;

export class AddBookmarkDialog extends Dialog {
public visible = false;

public left = 0;
public top = 0;

constructor(appWindow: AppWindow) {
super(appWindow, {
name: 'add-bookmark',
bounds: {
width: WIDTH,
height: 240,
},
});
}

public rearrange() {
super.rearrange({
x: Math.round(this.left - WIDTH + DIALOG_MARGIN),
y: Math.round(this.top - DIALOG_MARGIN_TOP),
});
}

public async show() {
await super.show();
export const showAddBookmarkDialog = (
browserWindow: BrowserWindow,
x: number,
y: number,
data?: {
url: string;
title: string;
bookmark?: IBookmark;
favicon?: string;
},
) => {
if (!data) {
const {
url,
title,
bookmark,
favicon,
} = Application.instance.windows.current.viewManager.selected;

this.send('visible', true, {
data = {
url,
title,
bookmark,
favicon,
});
};
}

public async showForBookmark(data: {
url: string;
title: string;
bookmark?: IBookmark;
favicon?: string;
}) {
await super.show();
const { url, title, bookmark, favicon } = data;

this.send('visible', true, {
url,
title,
bookmark,
favicon,
});
}
}
const dialog = Application.instance.dialogs.show({
name: 'add-bookmark',
browserWindow,
getBounds: () => ({
width: 366,
height: 240,
x: x - 366 + DIALOG_MARGIN,
y: y - DIALOG_MARGIN_TOP,
}),
});

dialog.on('loaded', (e) => {
e.reply('data', data);
});
};
60 changes: 27 additions & 33 deletions src/main/dialogs/dialog.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { BrowserView, app, ipcMain } from 'electron';
import { BrowserView, app, ipcMain, BrowserWindow } from 'electron';
import { join } from 'path';
import { AppWindow } from '../windows';

interface IOptions {
name: string;
Expand All @@ -18,8 +17,8 @@ interface IRectangle {
height?: number;
}

export class Dialog {
public appWindow: AppWindow;
export class PersistentDialog {
public browserWindow: BrowserWindow;
public browserView: BrowserView;

public visible = false;
Expand All @@ -31,19 +30,21 @@ export class Dialog {
height: 0,
};

public name: string;

private timeout: any;
private hideTimeout: number;
private name: string;

public tabIds: number[] = [];

private loaded = false;
private showCallback: any = null;

public constructor(
appWindow: AppWindow,
{ bounds, name, devtools, hideTimeout, webPreferences }: IOptions,
) {
public constructor({
bounds,
name,
devtools,
hideTimeout,
webPreferences,
}: IOptions) {
this.browserView = new BrowserView({
webPreferences: {
nodeIntegration: true,
Expand All @@ -53,7 +54,6 @@ export class Dialog {
},
});

this.appWindow = appWindow;
this.bounds = { ...this.bounds, ...bounds };
this.hideTimeout = hideTimeout;
this.name = name;
Expand All @@ -62,9 +62,6 @@ export class Dialog {

ipcMain.on(`hide-${webContents.id}`, () => {
this.hide(false, false);
this.tabIds = this.tabIds.filter(
(x) => x !== appWindow.viewManager.selectedId,
);
});

webContents.once('dom-ready', () => {
Expand All @@ -77,13 +74,10 @@ export class Dialog {
});

if (process.env.NODE_ENV === 'development') {
webContents.loadURL(`http://localhost:4444/${name}.html`);
if (devtools) {
webContents.openDevTools({ mode: 'detach' });
}
this.webContents.loadURL(`http://localhost:4444/${this.name}.html`);
} else {
webContents.loadURL(
join('file://', app.getAppPath(), `build/${name}.html`),
this.webContents.loadURL(
join('file://', app.getAppPath(), `build/${this.name}.html`),
);
}
}
Expand All @@ -109,15 +103,13 @@ export class Dialog {
}
}

public toggle() {
if (!this.visible) this.show();
}

public show(focus = true, waitForLoad = true) {
public show(browserWindow: BrowserWindow, focus = true, waitForLoad = true) {
return new Promise((resolve) => {
this.browserWindow = browserWindow;

clearTimeout(this.timeout);

this.appWindow.webContents.send(
browserWindow.webContents.send(
'dialog-visibility-change',
this.name,
true,
Expand All @@ -131,7 +123,7 @@ export class Dialog {

this.visible = true;

this.appWindow.win.addBrowserView(this.browserView);
browserWindow.addBrowserView(this.browserView);
this.rearrange();

if (focus) this.webContents.focus();
Expand All @@ -157,11 +149,13 @@ export class Dialog {
}

public hide(bringToTop = false, hideVisually = true) {
if (!this.browserWindow) return;

if (hideVisually) this.hideVisually();

if (!this.visible) return;

this.appWindow.webContents.send(
this.browserWindow.webContents.send(
'dialog-visibility-change',
this.name,
false,
Expand All @@ -175,10 +169,10 @@ export class Dialog {

if (this.hideTimeout) {
this.timeout = setTimeout(() => {
this.appWindow.win.removeBrowserView(this.browserView);
this.browserWindow.removeBrowserView(this.browserView);
}, this.hideTimeout);
} else {
this.appWindow.win.removeBrowserView(this.browserView);
this.browserWindow.removeBrowserView(this.browserView);
}

this.visible = false;
Expand All @@ -187,8 +181,8 @@ export class Dialog {
}

public bringToTop() {
this.appWindow.win.removeBrowserView(this.browserView);
this.appWindow.win.addBrowserView(this.browserView);
this.browserWindow.removeBrowserView(this.browserView);
this.browserWindow.addBrowserView(this.browserView);
}

public destroy() {
Expand Down
88 changes: 40 additions & 48 deletions src/main/dialogs/downloads.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,45 @@
import { AppWindow } from '../windows';
import { Dialog } from '.';
import { ipcMain } from 'electron';
import { BrowserWindow } from 'electron';
import { Application } from '../application';
import {
DIALOG_MARGIN_TOP,
DIALOG_MARGIN,
DIALOG_TOP,
DIALOG_MARGIN_TOP,
} from '~/constants/design';

const WIDTH = 350;

export class DownloadsDialog extends Dialog {
public visible = false;

private height = 0;

public left = 0;
public top = 0;

constructor(appWindow: AppWindow) {
super(appWindow, {
name: 'downloads-dialog',
bounds: {
width: WIDTH,
height: 0,
},
});

ipcMain.on(`height-${this.id}`, (e, height) => {
this.height = height;
this.rearrange();
});
}

public rearrange() {
const { height } = this.appWindow.win.getContentBounds();

const maxHeight = height - DIALOG_TOP - 16;

super.rearrange({
x: Math.round(this.left - WIDTH + DIALOG_MARGIN),
height: Math.round(Math.min(height, this.height + 28)),
y: Math.round(this.top - DIALOG_MARGIN_TOP),
});

this.send(`max-height`, Math.min(maxHeight, this.height));
}

public async show() {
await super.show();
this.send('visible', true);
}
}
export const showDownloadsDialog = (
browserWindow: BrowserWindow,
x: number,
y: number,
) => {
let height = 0;

const dialog = Application.instance.dialogs.show({
name: 'downloads-dialog',
browserWindow,
getBounds: () => {
const winBounds = browserWindow.getContentBounds();
const maxHeight = winBounds.height - DIALOG_TOP - 16;

height = Math.round(Math.min(winBounds.height, height + 28));

dialog.browserView.webContents.send(
`max-height`,
Math.min(maxHeight, height),
);

return {
x: x - 350 + DIALOG_MARGIN,
y: y - DIALOG_MARGIN_TOP,
width: 350,
height,
};
},
});

if (!dialog) return;

dialog.on('height', (e, h) => {
height = h;
dialog.rearrange();
});
};
Loading