Send only needed data from tabs over IPC.

Fixes exceptions from the structured clone algorithm raised by
Electron 9.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg
2020-07-24 00:36:45 -07:00
parent 5fe5989710
commit ec205f68a6
3 changed files with 28 additions and 27 deletions

View File

@@ -355,7 +355,7 @@ ${error}`
AppMenu.setMenu(props); AppMenu.setMenu(props);
const activeTab = props.tabs[props.activeTabIndex]; const activeTab = props.tabs[props.activeTabIndex];
if (activeTab) { if (activeTab) {
mainWindow.setTitle(`Zulip - ${activeTab.webview.props.name}`); mainWindow.setTitle(`Zulip - ${activeTab.webviewName}`);
} }
}); });

View File

@@ -2,7 +2,7 @@ import {app, shell, BrowserWindow, Menu} from 'electron';
import AdmZip from 'adm-zip'; import AdmZip from 'adm-zip';
import type {ServerOrFunctionalTab} from '../renderer/js/main'; import type {TabData} from '../renderer/js/main';
import * as ConfigUtil from '../renderer/js/utils/config-util'; import * as ConfigUtil from '../renderer/js/utils/config-util';
import * as DNDUtil from '../renderer/js/utils/dnd-util'; import * as DNDUtil from '../renderer/js/utils/dnd-util';
import * as LinkUtil from '../renderer/js/utils/link-util'; import * as LinkUtil from '../renderer/js/utils/link-util';
@@ -11,7 +11,7 @@ import * as t from '../renderer/js/utils/translation-util';
import {appUpdater} from './autoupdater'; import {appUpdater} from './autoupdater';
export interface MenuProps { export interface MenuProps {
tabs: ServerOrFunctionalTab[]; tabs: TabData[];
activeTabIndex?: number; activeTabIndex?: number;
enableMenu?: boolean; enableMenu?: boolean;
} }
@@ -215,7 +215,7 @@ function getHelpSubmenu(): Electron.MenuItemConstructorOptions[] {
]; ];
} }
function getWindowSubmenu(tabs: ServerOrFunctionalTab[], activeTabIndex: number): Electron.MenuItemConstructorOptions[] { function getWindowSubmenu(tabs: TabData[], activeTabIndex: number): Electron.MenuItemConstructorOptions[] {
const initialSubmenu: Electron.MenuItemConstructorOptions[] = [{ const initialSubmenu: Electron.MenuItemConstructorOptions[] = [{
label: t.__('Minimize'), label: t.__('Minimize'),
role: 'minimize' role: 'minimize'
@@ -231,17 +231,17 @@ function getWindowSubmenu(tabs: ServerOrFunctionalTab[], activeTabIndex: number)
}); });
tabs.forEach(tab => { tabs.forEach(tab => {
// Do not add functional tab settings to list of windows in menu bar // Do not add functional tab settings to list of windows in menu bar
if (tab.props.role === 'function' && tab.props.name === 'Settings') { if (tab.role === 'function' && tab.name === 'Settings') {
return; return;
} }
initialSubmenu.push({ initialSubmenu.push({
label: tab.props.name, label: tab.name,
accelerator: tab.props.role === 'function' ? '' : `${ShortcutKey} + ${tab.props.index + 1}`, accelerator: tab.role === 'function' ? '' : `${ShortcutKey} + ${tab.index + 1}`,
checked: tab.props.index === activeTabIndex, checked: tab.index === activeTabIndex,
click(_item, focusedWindow) { click(_item, focusedWindow) {
if (focusedWindow) { if (focusedWindow) {
sendAction('switch-server-tab', tab.props.index); sendAction('switch-server-tab', tab.index);
} }
}, },
type: 'checkbox' type: 'checkbox'
@@ -547,20 +547,20 @@ async function checkForUpdate(): Promise<void> {
await appUpdater(true); await appUpdater(true);
} }
function getNextServer(tabs: ServerOrFunctionalTab[], activeTabIndex: number): number { function getNextServer(tabs: TabData[], activeTabIndex: number): number {
do { do {
activeTabIndex = (activeTabIndex + 1) % tabs.length; activeTabIndex = (activeTabIndex + 1) % tabs.length;
} }
while (tabs[activeTabIndex].props.role !== 'server'); while (tabs[activeTabIndex].role !== 'server');
return activeTabIndex; return activeTabIndex;
} }
function getPreviousServer(tabs: ServerOrFunctionalTab[], activeTabIndex: number): number { function getPreviousServer(tabs: TabData[], activeTabIndex: number): number {
do { do {
activeTabIndex = (activeTabIndex - 1 + tabs.length) % tabs.length; activeTabIndex = (activeTabIndex - 1 + tabs.length) % tabs.length;
} }
while (tabs[activeTabIndex].props.role !== 'server'); while (tabs[activeTabIndex].role !== 'server');
return activeTabIndex; return activeTabIndex;
} }

View File

@@ -61,7 +61,14 @@ const logger = new Logger({
}); });
const rendererDirectory = path.resolve(__dirname, '..'); const rendererDirectory = path.resolve(__dirname, '..');
export type ServerOrFunctionalTab = ServerTab | FunctionalTab; type ServerOrFunctionalTab = ServerTab | FunctionalTab;
export interface TabData {
role: string;
name: string;
index: number;
webviewName: string;
}
class ServerManagerView { class ServerManagerView {
$addServerButton: HTMLButtonElement; $addServerButton: HTMLButtonElement;
@@ -592,19 +599,13 @@ class ServerManagerView {
// not crash app when this.tabs is passed into // not crash app when this.tabs is passed into
// ipcRenderer. Something about webview, and props.webview // ipcRenderer. Something about webview, and props.webview
// properties in ServerTab causes the app to crash. // properties in ServerTab causes the app to crash.
get tabsForIpc(): ServerOrFunctionalTab[] { get tabsForIpc(): TabData[] {
const tabs: ServerOrFunctionalTab[] = []; return this.tabs.map(tab => ({
this.tabs.forEach((tab: ServerOrFunctionalTab) => { role: tab.props.role,
const proto = Object.create(Object.getPrototypeOf(tab)); name: tab.props.name,
const tabClone = Object.assign(proto, tab); index: tab.props.index,
webviewName: tab.webview.props.name
tabClone.webview = {props: {}}; }));
tabClone.webview.props.name = tab.webview.props.name;
delete tabClone.props.webview;
tabs.push(tabClone);
});
return tabs;
} }
activateTab(index: number, hideOldTab = true): void { activateTab(index: number, hideOldTab = true): void {