diff options
| author | Andrei Mihailov <and.mikhaylov@gmail.com> | 2017-03-24 09:59:20 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-03-24 09:59:20 +0000 |
| commit | 5caca4f7a9c2d32356542d1ca48bb4738cfb67c2 (patch) | |
| tree | 2d688f2eaf6e227b75c186fc0823636feba2b7a2 | |
| parent | 27fcbbbfc7709e0b54c04d3f782b5bad5826dd81 (diff) | |
| download | mullvadvpn-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
| -rw-r--r-- | app/components/Connect.js | 2 | ||||
| -rw-r--r-- | app/components/HeaderBar.css | 9 | ||||
| -rw-r--r-- | app/components/HeaderBar.js | 2 | ||||
| -rw-r--r-- | app/main.js | 179 |
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' }); } }); |
