Skip to content

Commit

Permalink
Merge pull request #197 from feross/autoupdater
Browse files Browse the repository at this point in the history
OS X: Add auto-updater, sign app, build .DMG and .ZIP assets
  • Loading branch information
feross committed Mar 22, 2016
2 parents 13902da + 02ad7f9 commit 9d47cf1
Show file tree
Hide file tree
Showing 13 changed files with 184 additions and 52 deletions.
105 changes: 77 additions & 28 deletions bin/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,25 @@ var electronPackager = require('electron-packager')
var fs = require('fs')
var path = require('path')
var pkg = require('../package.json')
var plist = require('plist')

var BUILD_NAME = config.APP_NAME + '-v' + config.APP_VERSION

function build () {
var platform = process.argv[2]
if (platform === '--darwin') {
buildDarwin()
buildDarwin(printDone)
} else if (platform === '--win32') {
buildWin32()
buildWin32(printDone)
} else if (platform === '--linux') {
buildLinux()
buildLinux(printDone)
} else {
buildDarwin(() => buildWin32(() => buildLinux())) // Build all
buildDarwin(function (err, buildPath) {
printDone(err, buildPath)
buildWin32(function (err, buildPath) {
printDone(err, buildPath)
buildLinux(printDone)
})
})
}
}

Expand All @@ -30,7 +37,7 @@ var all = {
arch: 'x64',

// The application source directory.
dir: path.join(__dirname, '..'),
dir: config.ROOT_PATH,

// The release version of the application. Maps to the `ProductVersion` metadata
// property on Windows, and `CFBundleShortVersionString` on OS X.
Expand Down Expand Up @@ -58,7 +65,7 @@ var all = {
name: config.APP_NAME,

// The base directory where the finished package(s) are created.
out: path.join(__dirname, '..', 'dist'),
out: path.join(config.ROOT_PATH, 'dist'),

// Replace an already existing output directory.
overwrite: true,
Expand Down Expand Up @@ -130,18 +137,15 @@ var linux = {
build()

function buildDarwin (cb) {
electronPackager(Object.assign({}, all, darwin), function (err, appPath) {
printDone(err, appPath)
var appDmg = require('appdmg')
var plist = require('plist')
var sign = require('electron-osx-sign')

electronPackager(Object.assign({}, all, darwin), function (err, buildPath) {
if (err) return cb(err)

var contentsPath = path.join(
__dirname,
'..',
'dist',
`${config.APP_NAME}-darwin-x64`,
`${config.APP_NAME}.app`,
'Contents'
)
var appPath = path.join(buildPath[0], config.APP_NAME + '.app')
var contentsPath = path.join(appPath, 'Contents')
var resourcesPath = path.join(contentsPath, 'Resources')
var infoPlistPath = path.join(contentsPath, 'Info.plist')
var infoPlist = plist.parse(fs.readFileSync(infoPlistPath, 'utf8'))
Expand Down Expand Up @@ -178,25 +182,70 @@ function buildDarwin (cb) {
fs.writeFileSync(infoPlistPath, plist.build(infoPlist))
cp.execSync(`cp ${config.APP_FILE_ICON + '.icns'} ${resourcesPath}`)

if (cb) cb(null)
var zipPath = path.join(buildPath[0], BUILD_NAME + '.zip')
cp.execSync(`zip -r -y ${zipPath} ${appPath}`)

/*
* Signing OS X apps for distribution outside the App Store requires:
*
* - Xcode
* - Xcode Command Line Tools (xcode-select --install)
* - Membership in the Apple Developer Program
*/
if (process.platform === 'darwin') {
var signOpts = {
app: appPath,
platform: 'darwin',
verbose: true
}

var dmgPath = path.join(buildPath[0], BUILD_NAME + '.dmg')
var dmgOpts = {
basepath: config.ROOT_PATH,
target: dmgPath,
specification: {
title: config.APP_NAME,
icon: config.APP_ICON + '.icns',
background: path.join(config.STATIC_PATH, 'appdmg.png'),
'icon-size': 128,
contents: [
{ x: 122, y: 240, type: 'file', path: appPath },
{ x: 380, y: 240, type: 'link', path: '/Applications' },
// Hide hidden icons out of view, for users who have hidden files shown.
// https://github.com/LinusU/node-appdmg/issues/45#issuecomment-153924954
{ x: 50, y: 500, type: 'position', path: '.background' },
{ x: 100, y: 500, type: 'position', path: '.DS_Store' },
{ x: 150, y: 500, type: 'position', path: '.Trashes' },
{ x: 200, y: 500, type: 'position', path: '.VolumeIcon.icns' }
]
}
}

sign(signOpts, function (err) {
if (err) return cb(err)

var dmg = appDmg(dmgOpts)
dmg.on('error', cb)
dmg.on('progress', function (info) {
if (info.type === 'step-begin') console.log(info.title + '...')
})
dmg.on('finish', function (info) {
cb(null, buildPath)
})
})
}
})
}

function buildWin32 (cb) {
electronPackager(Object.assign({}, all, win32), function (err, appPath) {
printDone(err, appPath)
if (cb) cb(err)
})
electronPackager(Object.assign({}, all, win32), cb)
}

function buildLinux (cb) {
electronPackager(Object.assign({}, all, linux), function (err, appPath) {
printDone(err, appPath)
if (cb) cb(err)
})
electronPackager(Object.assign({}, all, linux), cb)
}

function printDone (err, appPath) {
function printDone (err, buildPath) {
if (err) console.error(err.message || err)
else console.log('Built ' + appPath)
else console.log('Built ' + buildPath[0])
}
16 changes: 12 additions & 4 deletions config.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
var applicationConfigPath = require('application-config-path')
var path = require('path')

var APP_NAME = 'WebTorrent'
var APP_VERSION = require('./package.json').version

module.exports = {
APP_COPYRIGHT: 'Copyright © 2014-2016 The WebTorrent Project',
APP_FILE_ICON: path.join(__dirname, 'static', 'WebTorrentFile'),
APP_ICON: path.join(__dirname, 'static', 'WebTorrent'),
APP_NAME: 'WebTorrent',
APP_NAME: APP_NAME,
APP_VERSION: APP_VERSION,

AUTO_UPDATE_URL: 'https://webtorrent.io/app/update?version=' + APP_VERSION,
AUTO_UPDATE_CHECK_STARTUP_DELAY: 60 * 1000 /* 1 minute */,

CONFIG_PATH: applicationConfigPath('WebTorrent'),
CONFIG_POSTER_PATH: path.join(applicationConfigPath('WebTorrent'), 'Posters'),
CONFIG_TORRENT_PATH: path.join(applicationConfigPath('WebTorrent'), 'Torrents'),
CONFIG_PATH: applicationConfigPath(APP_NAME),
CONFIG_POSTER_PATH: path.join(applicationConfigPath(APP_NAME), 'Posters'),
CONFIG_TORRENT_PATH: path.join(applicationConfigPath(APP_NAME), 'Torrents'),

INDEX: 'file://' + path.join(__dirname, 'renderer', 'index.html'),

IS_PRODUCTION: isProduction(),

ROOT_PATH: __dirname,
STATIC_PATH: path.join(__dirname, 'static'),

SOUND_ADD: 'file://' + path.join(__dirname, 'static', 'sound', 'add.wav'),
Expand Down
8 changes: 0 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,2 @@
console.time('init')
require('./main')

// report crashes
// require('crash-reporter').start({
// productName: 'WebTorrent',
// companyName: 'WebTorrent',
// submitURL: 'https://webtorrent.io/crash-report',
// autoSubmit: true
// })
31 changes: 31 additions & 0 deletions main/auto-updater.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module.exports = {
init
}

var electron = require('electron')

var config = require('../config')
var log = require('./log')

var autoUpdater = electron.autoUpdater

function init () {
autoUpdater.on('error', function (err) {
log.error('App update error: ' + err.message || err)
})

autoUpdater.setFeedURL(config.AUTO_UPDATE_URL)

/*
* We always check for updates on app startup. To keep app startup fast, we delay this
* first check so it happens when there is less going on.
*/
setTimeout(() => autoUpdater.checkForUpdates(), config.AUTO_UPDATE_CHECK_STARTUP_DELAY)

autoUpdater.on('checking-for-update', () => log('Checking for app update'))
autoUpdater.on('update-available', () => log('App update available'))
autoUpdater.on('update-not-available', () => log('App update not available'))
autoUpdater.on('update-downloaded', function (e, releaseNotes, releaseName, releaseDate, updateURL) {
log('App update downloaded: ', releaseName, updateURL)
})
}
21 changes: 18 additions & 3 deletions main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ var electron = require('electron')

var app = electron.app

var autoUpdater = require('./auto-updater')
var config = require('../config')
var ipc = require('./ipc')
var log = require('./log')
var menu = require('./menu')
var registerProtocolHandler = require('./register-handlers')
var shortcuts = require('./shortcuts')
Expand All @@ -15,7 +17,7 @@ var shouldQuit = app.makeSingleInstance(function (newArgv) {
newArgv = sliceArgv(newArgv)

if (app.ipcReady) {
windows.main.send('log', 'Second app instance attempted to open but was prevented')
log('Second app instance attempted to open but was prevented')

newArgv.forEach(function (torrentId) {
windows.main.send('dispatch', 'onOpen', torrentId)
Expand All @@ -38,6 +40,10 @@ var argv = sliceArgv(process.argv)

app.on('open-file', onOpen)
app.on('open-url', onOpen)
app.on('will-finish-launching', function () {
autoUpdater.init()
setupCrashReporter()
})

app.ipcReady = false // main window has finished loading and IPC is ready
app.isQuitting = false
Expand All @@ -50,9 +56,9 @@ app.on('ready', function () {
})

app.on('ipcReady', function () {
windows.main.send('log', 'IS_PRODUCTION:', config.IS_PRODUCTION)
log('IS_PRODUCTION:', config.IS_PRODUCTION)
if (argv.length) {
windows.main.send('log', 'command line args:', process.argv)
log('command line args:', process.argv)
}
argv.forEach(function (torrentId) {
windows.main.send('dispatch', 'onOpen', torrentId)
Expand Down Expand Up @@ -91,3 +97,12 @@ function onOpen (e, torrentId) {
function sliceArgv (argv) {
return argv.slice(config.IS_PRODUCTION ? 1 : 2)
}

function setupCrashReporter () {
// require('crash-reporter').start({
// productName: 'WebTorrent',
// companyName: 'WebTorrent',
// submitURL: 'https://webtorrent.io/crash-report',
// autoSubmit: true
// })
}
3 changes: 2 additions & 1 deletion main/ipc.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var app = electron.app
var ipcMain = electron.ipcMain
var powerSaveBlocker = electron.powerSaveBlocker

var log = require('./log')
var menu = require('./menu')
var windows = require('./windows')

Expand Down Expand Up @@ -51,7 +52,7 @@ function init () {
})

ipcMain.on('openItem', function (e, path) {
console.log('opening file or folder: ' + path)
log('opening file or folder: ' + path)
electron.shell.openItem(path)
})

Expand Down
31 changes: 31 additions & 0 deletions main/log.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module.exports = log
module.exports.error = error

/**
* In the main electron process, we do not use console.log() statements because they do
* not show up in a convenient location when running the packaged (i.e. production)
* version of the app. Instead use this module, which sends the logs to the main window
* where they can be viewed in Developer Tools.
*/

var electron = require('electron')

var windows = require('./windows')

var app = electron.app

function log (...args) {
if (app.ipcReady) {
windows.main.send('log', ...args)
} else {
app.on('ipcReady', () => windows.main.send('log', ...args))
}
}

function error (...args) {
if (app.ipcReady) {
windows.main.send('error', ...args)
} else {
app.on('ipcReady', () => windows.main.send('error', ...args))
}
}
6 changes: 4 additions & 2 deletions main/register-handlers.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var log = require('./log')

module.exports = function () {
if (process.platform === 'win32') {
var path = require('path')
Expand Down Expand Up @@ -86,7 +88,7 @@ function registerProtocolHandlerWin32 (protocol, name, icon, command) {
commandKey.set('', Registry.REG_SZ, '"' + command + '" "%1"', callback)

function callback (err) {
if (err) console.error(err.message || err)
if (err) log.error(err.message || err)
}
}

Expand Down Expand Up @@ -118,6 +120,6 @@ function registerFileHandlerWin32 (ext, id, name, icon, command) {
commandKey.set('', Registry.REG_SZ, '"' + command + '" "%1"', callback)

function callback (err) {
if (err) console.error(err.message || err)
if (err) log.error(err.message || err)
}
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
"winreg": "^1.0.1"
},
"devDependencies": {
"appdmg": "^0.3.6",
"electron-osx-sign": "^0.3.0",
"electron-packager": "^5.0.0",
"electron-prebuilt": "0.37.2",
"path-exists": "^2.1.0",
Expand Down
1 change: 1 addition & 0 deletions renderer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ function setupIpc () {
ipcRenderer.send('ipcReady')

ipcRenderer.on('log', (e, ...args) => console.log(...args))
ipcRenderer.on('error', (e, ...args) => console.error(...args))

ipcRenderer.on('dispatch', (e, ...args) => dispatch(...args))

Expand Down
Loading

0 comments on commit 9d47cf1

Please sign in to comment.