summaryrefslogtreecommitdiffhomepage
path: root/app
diff options
context:
space:
mode:
authorAndrei Mihailov <and.mikhaylov@gmail.com>2017-03-24 09:59:20 +0000
committerGitHub <noreply@github.com>2017-03-24 09:59:20 +0000
commit5caca4f7a9c2d32356542d1ca48bb4738cfb67c2 (patch)
tree2d688f2eaf6e227b75c186fc0823636feba2b7a2 /app
parent27fcbbbfc7709e0b54c04d3f782b5bad5826dd81 (diff)
downloadmullvadvpn-5caca4f7a9c2d32356542d1ca48bb4738cfb67c2.tar.xz
mullvadvpn-5caca4f7a9c2d32356542d1ca48bb4738cfb67c2.zip
Linux compatibility (#2)
* Make app run in window on Linux/Windows * Fix filename case * Show window by default except on macOS * always show dev tools when developing * Adjust content height for other platforms
Diffstat (limited to 'app')
-rw-r--r--app/components/Connect.js2
-rw-r--r--app/components/HeaderBar.css9
-rw-r--r--app/components/HeaderBar.js2
-rw-r--r--app/main.js179
4 files changed, 76 insertions, 116 deletions
diff --git a/app/components/Connect.js b/app/components/Connect.js
index 081aa7f6c2..5f924e92ed 100644
--- a/app/components/Connect.js
+++ b/app/components/Connect.js
@@ -6,7 +6,7 @@ import ReactMapboxGl, { Marker } from 'react-mapbox-gl';
import cheapRuler from 'cheap-ruler';
import { Layout, Container, Header } from './Layout';
import { mapbox as mapboxConfig } from '../config';
-import Backend from '../lib/Backend';
+import Backend from '../lib/backend';
import { ConnectionState } from '../enums';
import ExternalLinkSVG from '../assets/images/icon-extLink.svg';
diff --git a/app/components/HeaderBar.css b/app/components/HeaderBar.css
index 00ef8ef077..22e4011aa4 100644
--- a/app/components/HeaderBar.css
+++ b/app/components/HeaderBar.css
@@ -1,10 +1,15 @@
.headerbar {
- padding: 24px 12px 12px;
+ padding: 12px;
background-color: #294D73;
+ transition: 0.5s background-color ease-in-out;
+}
+
+/* macOS app runs as menubar app so create arrow and add extra padding */
+.headerbar--darwin {
+ padding-top: 24px;
-webkit-mask:
url(../assets/images/app-triangle.svg) 50% 0% no-repeat,
url(../assets/images/app-header-backdrop.svg) no-repeat;
- transition: 0.5s background-color ease-in-out;
}
.headerbar--hidden {
diff --git a/app/components/HeaderBar.js b/app/components/HeaderBar.js
index b7a76757fc..4da1e26562 100644
--- a/app/components/HeaderBar.js
+++ b/app/components/HeaderBar.js
@@ -42,7 +42,7 @@ export default class HeaderBar extends Component {
*/
render() {
const style = this.props.style;
- let containerClass = ['headerbar'];
+ let containerClass = ['headerbar', 'headerbar--' + process.platform];
if(HeaderBar.Style.isValid(style)) {
containerClass.push(`headerbar--style-${style}`);
diff --git a/app/main.js b/app/main.js
index 2b5d9f234b..09da054238 100644
--- a/app/main.js
+++ b/app/main.js
@@ -1,53 +1,20 @@
import path from 'path';
-import { app, crashReporter, BrowserWindow, ipcMain, Tray, Menu, nativeImage } from 'electron';
+import { app, BrowserWindow, ipcMain, Tray, Menu, nativeImage } from 'electron';
import TrayIconManager from './lib/tray-icon-manager';
-// Override appData path to avoid collisions with old client
-// New userData path, i.e on macOS: ~/Library/Application Support/mullvad.vpn
-const applicationSupportPath = app.getPath('appData');
-const userDataPath = path.join(applicationSupportPath, 'mullvad.vpn');
-app.setPath('userData', userDataPath);
-
const isDevelopment = (process.env.NODE_ENV === 'development');
+const isMacOS = (process.platform === 'darwin');
let window = null;
let tray = null;
-let macEventMonitor = null;
-let trayIconManager = null;
-
-const startTrayEventMonitor = (win) => {
- if(process.platform === 'darwin') {
- const { NSEventMonitor, NSEventMask } = require('nseventmonitor');
- if(macEventMonitor === null) {
- macEventMonitor = new NSEventMonitor();
- }
- macEventMonitor.start((NSEventMask.leftMouseDown | NSEventMask.rightMouseDown), () => win.hide());
- }
-};
-
-const stopTrayEventMonitor = () => {
- if(process.platform === 'darwin') {
- macEventMonitor.stop();
- }
-};
-
-ipcMain.on('changeTrayIcon', (event, type) => {
- trayIconManager.iconType = type;
-});
-ipcMain.emit();
-
-// hide dock icon
-if(process.platform === 'darwin') {
- app.dock.hide();
-}
+// Override appData path to avoid collisions with old client
+// New userData path, i.e on macOS: ~/Library/Application Support/mullvad.vpn
+app.setPath('userData', path.join(app.getPath('appData'), 'mullvad.vpn'));
-const installExtensions = async () => {
+const installDevTools = async () => {
const installer = require('electron-devtools-installer');
- const extensions = [
- 'REACT_DEVELOPER_TOOLS',
- 'REDUX_DEVTOOLS'
- ];
+ const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS'];
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
for(const name of extensions) {
try {
@@ -58,77 +25,38 @@ const installExtensions = async () => {
}
};
-const installDevTools = async () => {
- await installExtensions();
-
- // show devtools when ctrl clicked
- tray.on('click', function () {
- if(!window) { return; }
-
- if(window.isDevToolsOpened()) {
- // there is a rare bug when isDevToolsOpened() reports true
- // but dev tools window is not created yet.
- if(window.devToolsWebContents) {
- window.devToolsWebContents.focus();
- }
- } else {
- window.openDevTools({ mode: 'detach' });
- }
- });
-};
-
-const getWindowPosition = () => {
- const windowBounds = window.getBounds();
- const trayBounds = tray.getBounds();
-
- // center window horizontally below the tray icon
- const x = Math.round(trayBounds.x + (trayBounds.width / 2) - (windowBounds.width / 2));
-
- // position window vertically below the tray icon
- const y = Math.round(trayBounds.y + trayBounds.height);
-
- return { x, y };
-};
-
const createWindow = () => {
- window = new BrowserWindow({
+ const contentHeight = 568;
+ let options = {
width: 320,
- height: 568 + 12, // 12 is the size of transparent area around arrow
- frame: false,
+ height: contentHeight,
resizable: false,
maximizable: false,
fullscreenable: false,
- transparent: true,
- show: false,
+ show: true,
webPreferences: {
// prevents renderer process code from not running when window is hidden
backgroundThrottling: false,
-
// Enable experimental features
blinkFeatures: ['CSSBackdropFilter'].join(',')
}
- });
-
- window.loadURL('file://' + path.join(__dirname, 'index.html'));
-
- // hide the window when it loses focus
- window.on('blur', () => {
- if(!window.webContents.isDevToolsOpened()) {
- window.hide();
- }
- });
+ };
- window.on('show', () => {
- startTrayEventMonitor(window);
- });
+ // setup window flags to mimic popover on macOS
+ if(isMacOS) {
+ options = Object.assign({}, options, {
+ height: contentHeight + 12, // 12 is the size of transparent area around arrow
+ frame: false,
+ transparent: true,
+ show: false
+ });
+ }
- window.on('hide', () => {
- stopTrayEventMonitor();
- });
+ window = new BrowserWindow(options);
+ window.loadURL('file://' + path.join(__dirname, 'index.html'));
};
const createAppMenu = () => {
- // Create the Application's main menu
const template = [
{
label: 'Mullvad',
@@ -175,8 +103,7 @@ const createContextMenu = () => {
if(props.isEditable) {
let inputMenu = menuTemplate;
- // mixin "inspect element" into standard menu
- // when in development mode
+ // mixin "inspect element" into standard menu when in development mode
if(isDevelopment) {
inputMenu = menuTemplate.concat([{type: 'separator'}], inspectTemplate);
}
@@ -199,38 +126,66 @@ const toggleWindow = () => {
};
const showWindow = () => {
- const position = getWindowPosition();
- window.setPosition(position.x, position.y, false);
+ // position window based on tray icon location
+ if(tray) {
+ const { x, y } = getWindowPosition();
+ window.setPosition(x, y, false);
+ }
+
window.show();
window.focus();
};
+const getWindowPosition = () => {
+ const windowBounds = window.getBounds();
+ const trayBounds = tray.getBounds();
+
+ // center window horizontally below the tray icon
+ const x = Math.round(trayBounds.x + (trayBounds.width / 2) - (windowBounds.width / 2));
+
+ // position window vertically below the tray icon
+ const y = Math.round(trayBounds.y + trayBounds.height);
+
+ return { x, y };
+};
+
const createTray = () => {
tray = new Tray(nativeImage.createEmpty());
- tray.on('click', toggleWindow);
tray.setHighlightMode('never');
+ tray.on('click', toggleWindow);
- trayIconManager = new TrayIconManager(tray);
-};
+ // setup NSEvent monitor to fix inconsistent window.blur
+ // see https://github.com/electron/electron/issues/8689
+ const { NSEventMonitor, NSEventMask } = require('nseventmonitor');
+ const trayIconManager = new TrayIconManager(tray);
+ const macEventMonitor = new NSEventMonitor();
+ const eventMask = NSEventMask.leftMouseDown | NSEventMask.rightMouseDown;
-crashReporter.start({
- productName: 'YourName',
- companyName: 'YourCompany',
- submitURL: 'https://your-domain.com/url-to-submit',
- uploadToServer: false
-});
+ // add IPC handler to change tray icon from renderer
+ ipcMain.on('changeTrayIcon', (_, type) => trayIconManager.iconType = type);
+
+ // setup event handlers
+ window.on('show', () => macEventMonitor.start(eventMask, () => window.hide()));
+ window.on('hide', () => macEventMonitor.stop());
+ window.on('close', () => window.closeDevTools());
+ window.on('blur', () => !window.isDevToolsOpened() && window.hide());
+};
-app.on('window-all-closed', () => {
+app.on('window-all-closed', () => {
app.quit();
});
-app.on('ready', () => {
- createTray();
+app.on('ready', async () => {
createWindow();
+
+ // create tray icon on macOS
+ isMacOS && createTray();
+
createAppMenu();
createContextMenu();
if(isDevelopment) {
- installDevTools();
+ await installDevTools();
+ window.openDevTools({ mode: 'detach' });
}
});