Refactor main window code
This commit is contained in:
parent
b1d586e9da
commit
153bf7ad5f
210
src/main.js
210
src/main.js
|
@ -2,7 +2,6 @@
|
|||
|
||||
const {
|
||||
app,
|
||||
BrowserWindow,
|
||||
Menu,
|
||||
Tray,
|
||||
ipcMain,
|
||||
|
@ -20,7 +19,7 @@ process.on('uncaughtException', (error) => {
|
|||
console.error(error);
|
||||
});
|
||||
|
||||
var willAppQuit = false;
|
||||
global.willAppQuit = false;
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
var cmd = process.argv[1];
|
||||
|
@ -50,16 +49,16 @@ if (process.platform === 'win32') {
|
|||
|
||||
app.setAppUserModelId('com.squirrel.mattermost.Mattermost'); // Use explicit AppUserModelID
|
||||
if (require('electron-squirrel-startup')) {
|
||||
willAppQuit = true;
|
||||
global.willAppQuit = true;
|
||||
}
|
||||
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
|
||||
var settings = require('./common/settings');
|
||||
const osVersion = require('./common/osVersion');
|
||||
var certificateStore = require('./main/certificateStore').load(path.resolve(app.getPath('userData'), 'certificate.json'));
|
||||
const {createMainWindow} = require('./main/mainWindow');
|
||||
const appMenu = require('./main/menus/app');
|
||||
const trayMenu = require('./main/menus/tray');
|
||||
const allowProtocolDialog = require('./main/allowProtocolDialog');
|
||||
|
@ -205,35 +204,6 @@ function clearAppCache() {
|
|||
}
|
||||
}
|
||||
|
||||
function getValidWindowPosition(state) {
|
||||
// Screen cannot be required before app is ready
|
||||
const {screen} = require('electron');
|
||||
|
||||
// Check if the previous position is out of the viewable area
|
||||
// (e.g. because the screen has been plugged off)
|
||||
const displays = screen.getAllDisplays();
|
||||
let minX = 0;
|
||||
let maxX = 0;
|
||||
let minY = 0;
|
||||
let maxY = 0;
|
||||
for (let i = 0; i < displays.length; i++) {
|
||||
const display = displays[i];
|
||||
maxX = Math.max(maxX, display.bounds.x + display.bounds.width);
|
||||
maxY = Math.max(maxY, display.bounds.y + display.bounds.height);
|
||||
minX = Math.min(minX, display.bounds.x);
|
||||
minY = Math.min(minY, display.bounds.y);
|
||||
}
|
||||
|
||||
if (state.x > maxX || state.y > maxY || state.x < minX || state.y < minY) {
|
||||
Reflect.deleteProperty(state, 'x');
|
||||
Reflect.deleteProperty(state, 'y');
|
||||
Reflect.deleteProperty(state, 'width');
|
||||
Reflect.deleteProperty(state, 'height');
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on('window-all-closed', () => {
|
||||
// On OS X it is common for applications and their menu bar
|
||||
|
@ -253,7 +223,7 @@ app.on('before-quit', () => {
|
|||
if (process.platform === 'win32') {
|
||||
trayIcon.destroy();
|
||||
}
|
||||
willAppQuit = true;
|
||||
global.willAppQuit = true;
|
||||
});
|
||||
|
||||
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
|
||||
|
@ -307,7 +277,7 @@ allowProtocolDialog.init(mainWindow);
|
|||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
app.on('ready', () => {
|
||||
if (willAppQuit) {
|
||||
if (global.willAppQuit) {
|
||||
return;
|
||||
}
|
||||
if (global.isDev) {
|
||||
|
@ -316,6 +286,23 @@ app.on('ready', () => {
|
|||
catch((err) => console.log('An error occurred: ', err));
|
||||
}
|
||||
|
||||
mainWindow = createMainWindow(config, {
|
||||
hideOnStartup,
|
||||
linuxAppIcon: path.join(assetsDir, 'appicon.png')
|
||||
});
|
||||
mainWindow.on('closed', () => {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null;
|
||||
});
|
||||
mainWindow.on('unresponsive', () => {
|
||||
console.log('The application has become unresponsive.');
|
||||
});
|
||||
mainWindow.webContents.on('crashed', () => {
|
||||
console.log('The application has crashed.');
|
||||
});
|
||||
|
||||
ipcMain.on('notified', () => {
|
||||
if (process.platform === 'win32' || process.platform === 'linux') {
|
||||
if (config.notifications.flashWindow === 2) {
|
||||
|
@ -393,59 +380,35 @@ app.on('ready', () => {
|
|||
ipcMain.on('update-unread', (event, arg) => {
|
||||
if (process.platform === 'win32') {
|
||||
const overlay = arg.overlayDataURL ? nativeImage.createFromDataURL(arg.overlayDataURL) : null;
|
||||
mainWindow.setOverlayIcon(overlay, arg.description);
|
||||
if (mainWindow) {
|
||||
mainWindow.setOverlayIcon(overlay, arg.description);
|
||||
}
|
||||
}
|
||||
|
||||
if (arg.mentionCount > 0) {
|
||||
trayIcon.setImage(trayImages.mention);
|
||||
if (process.platform === 'darwin') {
|
||||
trayIcon.setPressedImage(trayImages.clicked.mention);
|
||||
if (trayIcon) {
|
||||
if (arg.mentionCount > 0) {
|
||||
trayIcon.setImage(trayImages.mention);
|
||||
if (process.platform === 'darwin') {
|
||||
trayIcon.setPressedImage(trayImages.clicked.mention);
|
||||
}
|
||||
trayIcon.setToolTip(arg.mentionCount + ' unread mentions');
|
||||
} else if (arg.unreadCount > 0) {
|
||||
trayIcon.setImage(trayImages.unread);
|
||||
if (process.platform === 'darwin') {
|
||||
trayIcon.setPressedImage(trayImages.clicked.unread);
|
||||
}
|
||||
trayIcon.setToolTip(arg.unreadCount + ' unread channels');
|
||||
} else {
|
||||
trayIcon.setImage(trayImages.normal);
|
||||
if (process.platform === 'darwin') {
|
||||
trayIcon.setPressedImage(trayImages.clicked.normal);
|
||||
}
|
||||
trayIcon.setToolTip(app.getName());
|
||||
}
|
||||
trayIcon.setToolTip(arg.mentionCount + ' unread mentions');
|
||||
} else if (arg.unreadCount > 0) {
|
||||
trayIcon.setImage(trayImages.unread);
|
||||
if (process.platform === 'darwin') {
|
||||
trayIcon.setPressedImage(trayImages.clicked.unread);
|
||||
}
|
||||
trayIcon.setToolTip(arg.unreadCount + ' unread channels');
|
||||
} else {
|
||||
trayIcon.setImage(trayImages.normal);
|
||||
if (process.platform === 'darwin') {
|
||||
trayIcon.setPressedImage(trayImages.clicked.normal);
|
||||
}
|
||||
trayIcon.setToolTip(app.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Create the browser window.
|
||||
var boundsInfoPath = path.resolve(app.getPath('userData'), 'bounds-info.json');
|
||||
var windowOptions;
|
||||
try {
|
||||
windowOptions = getValidWindowPosition(JSON.parse(fs.readFileSync(boundsInfoPath, 'utf-8')));
|
||||
} catch (e) {
|
||||
// Follow Electron's defaults, except for window dimensions which targets 1024x768 screen resolution.
|
||||
windowOptions = {width: 1000, height: 700};
|
||||
}
|
||||
if (process.platform === 'linux') {
|
||||
windowOptions.icon = path.resolve(assetsDir, 'appicon.png');
|
||||
}
|
||||
Object.assign(windowOptions, {
|
||||
title: app.getName(),
|
||||
fullscreenable: true,
|
||||
show: false,
|
||||
minWidth: 400,
|
||||
minHeight: 240
|
||||
});
|
||||
mainWindow = new BrowserWindow(windowOptions);
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
mainWindow.show();
|
||||
} else if (hideOnStartup !== true) {
|
||||
mainWindow.show();
|
||||
}
|
||||
});
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
session.defaultSession.on('will-download', (event, item) => {
|
||||
var filename = item.getFilename();
|
||||
|
@ -462,35 +425,6 @@ app.on('ready', () => {
|
|||
});
|
||||
}
|
||||
|
||||
mainWindow.webContents.on('crashed', () => {
|
||||
console.log('The application has crashed.');
|
||||
});
|
||||
|
||||
mainWindow.webContents.on('will-attach-webview', (event, webPreferences) => {
|
||||
webPreferences.nodeIntegration = false;
|
||||
});
|
||||
|
||||
mainWindow.on('unresponsive', () => {
|
||||
console.log('The application has become unresponsive.');
|
||||
});
|
||||
|
||||
if (hideOnStartup) {
|
||||
if (windowOptions.maximized) {
|
||||
mainWindow.maximize();
|
||||
}
|
||||
|
||||
// on MacOS, the window is already hidden until 'ready-to-show'
|
||||
if (process.platform !== 'darwin') {
|
||||
mainWindow.minimize();
|
||||
}
|
||||
} else if (windowOptions.maximized) {
|
||||
mainWindow.maximize();
|
||||
}
|
||||
|
||||
// and load the index.html of the app.
|
||||
const indexURL = global.isDev ? 'http://localhost:8080/browser/index.html' : `file://${app.getAppPath()}/browser/index.html`;
|
||||
mainWindow.loadURL(indexURL);
|
||||
|
||||
// Set application menu
|
||||
ipcMain.on('update-menu', (event, configData) => {
|
||||
var aMenu = appMenu.createMenu(mainWindow, configData, global.isDev);
|
||||
|
@ -515,60 +449,4 @@ app.on('ready', () => {
|
|||
|
||||
// Open the DevTools.
|
||||
// mainWindow.openDevTools();
|
||||
|
||||
function saveWindowState(file, window) {
|
||||
var windowState = window.getBounds();
|
||||
windowState.maximized = window.isMaximized();
|
||||
windowState.fullscreen = window.isFullScreen();
|
||||
try {
|
||||
fs.writeFileSync(boundsInfoPath, JSON.stringify(windowState));
|
||||
} catch (e) {
|
||||
// [Linux] error happens only when the window state is changed before the config dir is creatied.
|
||||
}
|
||||
}
|
||||
|
||||
mainWindow.on('close', (event) => {
|
||||
if (willAppQuit) { // when [Ctrl|Cmd]+Q
|
||||
saveWindowState(boundsInfoPath, mainWindow);
|
||||
} else { // Minimize or hide the window for close button.
|
||||
event.preventDefault();
|
||||
function hideWindow(window) {
|
||||
window.blur(); // To move focus to the next top-level window in Windows
|
||||
window.hide();
|
||||
}
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
hideWindow(mainWindow);
|
||||
break;
|
||||
case 'linux':
|
||||
if (config.minimizeToTray) {
|
||||
hideWindow(mainWindow);
|
||||
} else {
|
||||
mainWindow.minimize();
|
||||
}
|
||||
break;
|
||||
case 'darwin':
|
||||
hideWindow(mainWindow);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// App should save bounds when a window is closed.
|
||||
// However, 'close' is not fired in some situations(shutdown, ctrl+c)
|
||||
// because main process is killed in such situations.
|
||||
// 'blur' event was effective in order to avoid this.
|
||||
// Ideally, app should detect that OS is shutting down.
|
||||
mainWindow.on('blur', () => {
|
||||
saveWindowState(boundsInfoPath, mainWindow);
|
||||
});
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', () => {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null;
|
||||
});
|
||||
});
|
||||
|
|
141
src/main/mainWindow.js
Normal file
141
src/main/mainWindow.js
Normal file
|
@ -0,0 +1,141 @@
|
|||
const {app, BrowserWindow} = require('electron');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
function saveWindowState(file, window) {
|
||||
var windowState = window.getBounds();
|
||||
windowState.maximized = window.isMaximized();
|
||||
windowState.fullscreen = window.isFullScreen();
|
||||
try {
|
||||
fs.writeFileSync(file, JSON.stringify(windowState));
|
||||
} catch (e) {
|
||||
// [Linux] error happens only when the window state is changed before the config dir is created.
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
function getValidWindowPosition(state) {
|
||||
// Screen cannot be required before app is ready
|
||||
const {screen} = require('electron'); // eslint-disable-line global-require
|
||||
|
||||
// Check if the previous position is out of the viewable area
|
||||
// (e.g. because the screen has been plugged off)
|
||||
const displays = screen.getAllDisplays();
|
||||
let minX = 0;
|
||||
let maxX = 0;
|
||||
let minY = 0;
|
||||
let maxY = 0;
|
||||
for (let i = 0; i < displays.length; i++) {
|
||||
const display = displays[i];
|
||||
maxX = Math.max(maxX, display.bounds.x + display.bounds.width);
|
||||
maxY = Math.max(maxY, display.bounds.y + display.bounds.height);
|
||||
minX = Math.min(minX, display.bounds.x);
|
||||
minY = Math.min(minY, display.bounds.y);
|
||||
}
|
||||
|
||||
if (state.x > maxX || state.y > maxY || state.x < minX || state.y < minY) {
|
||||
Reflect.deleteProperty(state, 'x');
|
||||
Reflect.deleteProperty(state, 'y');
|
||||
Reflect.deleteProperty(state, 'width');
|
||||
Reflect.deleteProperty(state, 'height');
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function createMainWindow(config, options) {
|
||||
const defaultWindowWidth = 1000;
|
||||
const defaultWindowHeight = 700;
|
||||
const minimumWindowWidth = 400;
|
||||
const minimumWindowHeight = 240;
|
||||
|
||||
// Create the browser window.
|
||||
const boundsInfoPath = path.join(app.getPath('userData'), 'bounds-info.json');
|
||||
var windowOptions;
|
||||
try {
|
||||
windowOptions = getValidWindowPosition(JSON.parse(fs.readFileSync(boundsInfoPath, 'utf-8')));
|
||||
} catch (e) {
|
||||
// Follow Electron's defaults, except for window dimensions which targets 1024x768 screen resolution.
|
||||
windowOptions = {width: defaultWindowWidth, height: defaultWindowHeight};
|
||||
}
|
||||
if (process.platform === 'linux') {
|
||||
windowOptions.icon = options.linuxAppIcon;
|
||||
}
|
||||
Object.assign(windowOptions, {
|
||||
title: app.getName(),
|
||||
fullscreenable: true,
|
||||
show: false,
|
||||
minWidth: minimumWindowWidth,
|
||||
minHeight: minimumWindowHeight
|
||||
});
|
||||
|
||||
const mainWindow = new BrowserWindow(windowOptions);
|
||||
if (options.hideOnStartup) {
|
||||
if (windowOptions.maximized) {
|
||||
mainWindow.maximize();
|
||||
}
|
||||
|
||||
// on MacOS, the window is already hidden until 'ready-to-show'
|
||||
if (process.platform !== 'darwin') {
|
||||
mainWindow.minimize();
|
||||
}
|
||||
} else if (windowOptions.maximized) {
|
||||
mainWindow.maximize();
|
||||
}
|
||||
|
||||
mainWindow.webContents.on('will-attach-webview', (event, webPreferences) => {
|
||||
webPreferences.nodeIntegration = false;
|
||||
});
|
||||
|
||||
const indexURL = global.isDev ? 'http://localhost:8080/browser/index.html' : `file://${app.getAppPath()}/browser/index.html`;
|
||||
mainWindow.loadURL(indexURL);
|
||||
|
||||
mainWindow.once('ready-to-show', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
mainWindow.show();
|
||||
} else if (options.hideOnStartup !== true) {
|
||||
mainWindow.show();
|
||||
}
|
||||
});
|
||||
|
||||
// App should save bounds when a window is closed.
|
||||
// However, 'close' is not fired in some situations(shutdown, ctrl+c)
|
||||
// because main process is killed in such situations.
|
||||
// 'blur' event was effective in order to avoid this.
|
||||
// Ideally, app should detect that OS is shutting down.
|
||||
mainWindow.on('blur', () => {
|
||||
saveWindowState(boundsInfoPath, mainWindow);
|
||||
});
|
||||
|
||||
mainWindow.on('close', (event) => {
|
||||
if (global.willAppQuit) { // when [Ctrl|Cmd]+Q
|
||||
saveWindowState(boundsInfoPath, mainWindow);
|
||||
} else { // Minimize or hide the window for close button.
|
||||
event.preventDefault();
|
||||
function hideWindow(window) {
|
||||
window.blur(); // To move focus to the next top-level window in Windows
|
||||
window.hide();
|
||||
}
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
hideWindow(mainWindow);
|
||||
break;
|
||||
case 'linux':
|
||||
if (config.minimizeToTray) {
|
||||
hideWindow(mainWindow);
|
||||
} else {
|
||||
mainWindow.minimize();
|
||||
}
|
||||
break;
|
||||
case 'darwin':
|
||||
hideWindow(mainWindow);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return mainWindow;
|
||||
}
|
||||
|
||||
module.exports = {createMainWindow};
|
Loading…
Reference in a new issue