1
0
mirror of https://github.com/rhysd/Mstdn.git synced 2025-01-21 20:52:11 +01:00

recreate browser window to switch session partition

This commit is contained in:
rhysd 2017-04-18 20:29:07 +09:00
parent 8395159007
commit bf680a4b89
5 changed files with 63 additions and 44 deletions

View File

@ -11,7 +11,7 @@ export default class AccountSwitcher extends EventEmitter {
accounts: Account[]; accounts: Account[];
current: Account; current: Account;
constructor(private win: Electron.BrowserWindow, accounts: Account[]) { constructor(accounts: Account[]) {
super(); super();
const submenu = [] as Electron.MenuItemOptions[]; const submenu = [] as Electron.MenuItemOptions[];
@ -25,7 +25,7 @@ export default class AccountSwitcher extends EventEmitter {
label: name, label: name,
type: 'radio', type: 'radio',
checked: false, checked: false,
click: () => this.switchAccountTo(account), click: () => this.switchTo(account),
}); });
} }
@ -49,18 +49,13 @@ export default class AccountSwitcher extends EventEmitter {
Menu.setApplicationMenu(menu); Menu.setApplicationMenu(menu);
} }
switchAccountTo(account: Account) { switchTo(account: Account) {
if (this.current.name === account.name && this.current.host === account.host) { if (this.current.name === account.name && this.current.host === account.host) {
log.debug('Current account is already @' + account.name); log.debug('Current account is already @' + account.name);
return; return;
} }
log.debug('Switch to account', account); log.debug('Switch to account', account);
this.emit('will-switch', account); this.emit('switch', account, this.current);
log.error('TODO: Switch partition');
this.win.webContents.send('mstdn:change-account', account);
this.emit('did-switch', account);
this.current = account; this.current = account;
} }
} }

View File

@ -1,7 +1,7 @@
import * as path from 'path'; import * as path from 'path';
import {app, Menu} from 'electron'; import {app, Menu, globalShortcut} from 'electron';
import log from './log'; import log from './log';
import {Config} from './config'; import {Config, Account} from './config';
import AccountSwitcher from './account_switcher'; import AccountSwitcher from './account_switcher';
import defaultMenu from './default_menu'; import defaultMenu from './default_menu';
import Window from './window'; import Window from './window';
@ -20,17 +20,30 @@ export class App {
app.dock.setIcon(APP_ICON); app.dock.setIcon(APP_ICON);
} }
Menu.setApplicationMenu(defaultMenu()); Menu.setApplicationMenu(defaultMenu());
this.switcher = new AccountSwitcher(win.browser, this.config.accounts); this.switcher = new AccountSwitcher(this.config.accounts);
this.switcher.on('did-switch', () => this.open()); this.switcher.on('switch', this.onAccountSwitch);
} }
open() { start() {
const url = `https://${this.switcher.current.host}${this.switcher.current.default_page}`; const url = `https://${this.switcher.current.host}${this.switcher.current.default_page}`;
this.win.open(url); this.win.open(url);
log.debug('Open URL: ', url); log.debug('Open URL: ', url);
} }
private onAccountSwitch = (next: Account) => {
this.win.close();
if (this.config.hot_key) {
globalShortcut.unregister(this.config.hot_key);
}
Window.create(next, this.config, this.win.menubar) .then(win => {
this.win = win;
this.start();
});
}
} }
export default function startApp(config: Config) { export default function startApp(config: Config) {
return Window.create(config).then(win => new App(win, config)); const default_account = config.accounts[0];
return Window.create(default_account, config)
.then(win => new App(win, config));
} }

View File

@ -3,6 +3,10 @@ import log from './log';
import startApp from './app'; import startApp from './app';
import loadConfig from './config'; import loadConfig from './config';
// default_app sets app.on('all-window-closed', () => app.quit()) before
// loading this application. We need to disable the callback.
app.removeAllListeners();
const appReady = new Promise<void>(resolve => app.once('ready', resolve)); const appReady = new Promise<void>(resolve => app.once('ready', resolve));
process.on('unhandledRejection', (reason: string) => { process.on('unhandledRejection', (reason: string) => {
@ -16,7 +20,7 @@ app.on('will-quit', () => {
Promise.all([ Promise.all([
loadConfig(), loadConfig(),
appReady appReady
]).then(([config, _]) => startApp(config)).then(win => { ]).then(([config, _]) => startApp(config)).then(mstdn => {
win.open(); mstdn.start();
log.debug('Application launched!'); log.debug('Application launched!');
}); });

View File

@ -12,12 +12,17 @@ const APP_ICON = path.join(__dirname, '..', 'resources', 'icon', 'icon.png');
const PRELOAD_JS = path.join(__dirname, '..', 'renderer', 'preload.js'); const PRELOAD_JS = path.join(__dirname, '..', 'renderer', 'preload.js');
export default class Window { export default class Window {
static create(config: Config) { static create(account: Account, config: Config, mb: Menubar.MenubarApp | null = null) {
return (config.normal_window ? startNormalWindow : startMenuBar)(config); if (config.normal_window) {
return startNormalWindow(account, config);
} else {
return startMenuBar(account, config, mb);
}
} }
constructor( constructor(
public browser: Electron.BrowserWindow, public browser: Electron.BrowserWindow,
public state: any /*XXX: ElectronWindowState.WindowState */,
public account: Account, public account: Account,
public menubar: Menubar.MenubarApp | null, public menubar: Menubar.MenubarApp | null,
) { ) {
@ -60,12 +65,16 @@ export default class Window {
this.browser.loadURL(url); this.browser.loadURL(url);
} }
isMenubar() {
return this.menubar !== null;
}
close() { close() {
log.error('TODO: close window'); this.state.unmanage();
this.browser.webContents.removeAllListeners();
this.browser.removeAllListeners();
if (this.menubar) {
// Note:
// menubar.windowClear() won't be called because all listners was removed
delete this.menubar.window;
}
this.browser.close();
} }
} }
@ -75,14 +84,13 @@ function trayIcon(color: string) {
}@2x.png`); }@2x.png`);
} }
function startNormalWindow(config: Config): Promise<Window> { function startNormalWindow(account: Account, config: Config): Promise<Window> {
log.debug('Setup a normal window'); log.debug('Setup a normal window');
return new Promise<Window>(resolve => { return new Promise<Window>(resolve => {
const state = windowState({ const state = windowState({
defaultWidth: 600, defaultWidth: 600,
defaultHeight: 800, defaultHeight: 800,
}); });
const account = config.accounts[0];
const win = new BrowserWindow({ const win = new BrowserWindow({
width: state.width, width: state.width,
height: state.height, height: state.height,
@ -129,7 +137,7 @@ function startNormalWindow(config: Config): Promise<Window> {
win.webContents.on('dom-ready', () => { win.webContents.on('dom-ready', () => {
log.debug('Send config to renderer procress'); log.debug('Send config to renderer procress');
win.webContents.send('mstdn:config', config); win.webContents.send('mstdn:config', config, account);
}); });
win.webContents.once('dom-ready', () => { win.webContents.once('dom-ready', () => {
log.debug('Normal window application was launched'); log.debug('Normal window application was launched');
@ -150,20 +158,19 @@ function startNormalWindow(config: Config): Promise<Window> {
tray.setHighlightMode('never'); tray.setHighlightMode('never');
} }
resolve(new Window(win, account, null)); resolve(new Window(win, state, account, null));
}); });
} }
function startMenuBar(config: Config): Promise<Window> { function startMenuBar(account: Account, config: Config, bar: Menubar.MenubarApp | null): Promise<Window> {
log.debug('Setup a menubar window'); log.debug('Setup a menubar window');
return new Promise<Window>(resolve => { return new Promise<Window>(resolve => {
const state = windowState({ const state = windowState({
defaultWidth: 350, defaultWidth: 350,
defaultHeight: 420, defaultHeight: 420,
}); });
const account = config.accounts[0];
const icon = trayIcon(config.icon_color); const icon = trayIcon(config.icon_color);
const mb = menubar({ const mb = bar || menubar({
icon, icon,
width: state.width, width: state.width,
height: state.height, height: state.height,
@ -180,7 +187,6 @@ function startMenuBar(config: Config): Promise<Window> {
partition: partitionForAccount(account), partition: partitionForAccount(account),
}, },
}); });
mb.once('ready', () => mb.showWindow());
mb.once('after-create-window', () => { mb.once('after-create-window', () => {
log.debug('Menubar application was launched'); log.debug('Menubar application was launched');
if (config.hot_key) { if (config.hot_key) {
@ -200,15 +206,24 @@ function startMenuBar(config: Config): Promise<Window> {
} }
mb.window.webContents.on('dom-ready', () => { mb.window.webContents.on('dom-ready', () => {
log.debug('Send config to renderer procress'); log.debug('Send config to renderer procress');
mb.window.webContents.send('mstdn:config', config); mb.window.webContents.send('mstdn:config', config, account);
}); });
state.manage(mb.window); state.manage(mb.window);
resolve(new Window(mb.window, account, mb)); resolve(new Window(mb.window, state, account, mb));
}); });
mb.once('after-close', () => { mb.once('after-close', () => {
app.quit(); app.quit();
}); });
if (bar) {
log.debug('recreate menubar window with different partition:', account);
const pref = mb.getOption('webPreferences');
pref.partition = partitionForAccount(account);
mb.setOption('webPreferences', pref);
mb.showWindow();
} else {
mb.once('ready', () => mb.showWindow());
}
}); });
} }

View File

@ -54,16 +54,8 @@ function setupKeybinds(keybinds: {[key: string]: string}, host: string) {
let config: Config | null = null; let config: Config | null = null;
Ipc.on('mstdn:config', (c: Config) => { Ipc.on('mstdn:config', (c: Config, a: Account) => {
config = c; config = c;
const host = config.accounts[0].host; const host = a.host;
setupKeybinds(config.keymaps, host); setupKeybinds(config.keymaps, host);
}); });
Ipc.on('mstdn:change-account', (account: Account) => {
if (config === null) {
log.error('FATAL: config is null at receiving mstdn:change-account');
return;
}
setupKeybinds(config.keymaps, account.host);
});