Major refactor -- split windows into separate files
This commit is contained in:
@@ -3,7 +3,6 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var electron = require('electron')
|
var electron = require('electron')
|
||||||
var get = require('simple-get')
|
|
||||||
|
|
||||||
var config = require('../config')
|
var config = require('../config')
|
||||||
var log = require('./log')
|
var log = require('./log')
|
||||||
@@ -13,6 +12,7 @@ var ANNOUNCEMENT_URL = config.ANNOUNCEMENT_URL +
|
|||||||
'&platform=' + process.platform
|
'&platform=' + process.platform
|
||||||
|
|
||||||
function init () {
|
function init () {
|
||||||
|
var get = require('simple-get')
|
||||||
get.concat(ANNOUNCEMENT_URL, onResponse)
|
get.concat(ANNOUNCEMENT_URL, onResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
53
main/dialog.js
Normal file
53
main/dialog.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
module.exports = {
|
||||||
|
openSeedFile,
|
||||||
|
openSeedDirectory,
|
||||||
|
openTorrentFile,
|
||||||
|
openTorrentAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
var electron = require('electron')
|
||||||
|
var windows = require('./windows')
|
||||||
|
|
||||||
|
// Prompts the user for a file, then creates a torrent. Only allows a single file
|
||||||
|
// selection.
|
||||||
|
function openSeedFile () {
|
||||||
|
electron.dialog.showOpenDialog({
|
||||||
|
title: 'Select a file for the torrent file.',
|
||||||
|
properties: [ 'openFile' ]
|
||||||
|
}, function (selectedPaths) {
|
||||||
|
if (!Array.isArray(selectedPaths)) return
|
||||||
|
windows.main.send('dispatch', 'showCreateTorrent', selectedPaths)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prompts the user for a file or directory, then creates a torrent. Only allows a
|
||||||
|
// single selection. To create a multi-file torrent, the user must select a
|
||||||
|
// directory.
|
||||||
|
function openSeedDirectory () {
|
||||||
|
electron.dialog.showOpenDialog({
|
||||||
|
title: 'Select a file or folder for the torrent file.',
|
||||||
|
properties: [ 'openFile', 'openDirectory' ]
|
||||||
|
}, function (selectedPaths) {
|
||||||
|
if (!Array.isArray(selectedPaths)) return
|
||||||
|
windows.main.send('dispatch', 'showCreateTorrent', selectedPaths)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prompts the user to choose a torrent file, then adds it.
|
||||||
|
function openTorrentFile () {
|
||||||
|
electron.dialog.showOpenDialog(windows.main.win, {
|
||||||
|
title: 'Select a .torrent file to open.',
|
||||||
|
filters: [{ name: 'Torrent Files', extensions: ['torrent'] }],
|
||||||
|
properties: [ 'openFile', 'multiSelections' ]
|
||||||
|
}, function (selectedPaths) {
|
||||||
|
if (!Array.isArray(selectedPaths)) return
|
||||||
|
selectedPaths.forEach(function (selectedPath) {
|
||||||
|
windows.main.send('dispatch', 'addTorrent', selectedPath)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prompts the user for the URL of a torrent file, then downloads and adds it
|
||||||
|
function openTorrentAddress () {
|
||||||
|
windows.main.send('showOpenTorrentAddress')
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ var ipcMain = electron.ipcMain
|
|||||||
var announcement = require('./announcement')
|
var announcement = require('./announcement')
|
||||||
var config = require('../config')
|
var config = require('../config')
|
||||||
var crashReporter = require('../crash-reporter')
|
var crashReporter = require('../crash-reporter')
|
||||||
|
var dialog = require('./dialog')
|
||||||
var handlers = require('./handlers')
|
var handlers = require('./handlers')
|
||||||
var ipc = require('./ipc')
|
var ipc = require('./ipc')
|
||||||
var log = require('./log')
|
var log = require('./log')
|
||||||
@@ -60,8 +61,8 @@ function init () {
|
|||||||
app.on('ready', function () {
|
app.on('ready', function () {
|
||||||
isReady = true
|
isReady = true
|
||||||
|
|
||||||
windows.createMainWindow()
|
windows.main.create()
|
||||||
windows.createWebTorrentHiddenWindow()
|
windows.webtorrent.create()
|
||||||
menu.init()
|
menu.init()
|
||||||
|
|
||||||
// To keep app startup fast, some code is delayed.
|
// To keep app startup fast, some code is delayed.
|
||||||
@@ -79,13 +80,13 @@ function init () {
|
|||||||
|
|
||||||
app.isQuitting = true
|
app.isQuitting = true
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
windows.main.send('dispatch', 'saveState') /* try to save state on exit */
|
windows.main.send('dispatch', 'saveState') // try to save state on exit
|
||||||
ipcMain.once('savedState', () => app.quit())
|
ipcMain.once('savedState', () => app.quit())
|
||||||
setTimeout(() => app.quit(), 2000) /* quit after 2 secs, at most */
|
setTimeout(() => app.quit(), 2000) // quit after 2 secs, at most
|
||||||
})
|
})
|
||||||
|
|
||||||
app.on('activate', function () {
|
app.on('activate', function () {
|
||||||
if (isReady) windows.createMainWindow()
|
if (isReady) windows.main.create()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,11 +102,11 @@ function onOpen (e, torrentId) {
|
|||||||
|
|
||||||
if (app.ipcReady) {
|
if (app.ipcReady) {
|
||||||
windows.main.send('dispatch', 'onOpen', torrentId)
|
windows.main.send('dispatch', 'onOpen', torrentId)
|
||||||
// Magnet links opened from Chrome won't focus the app without a setTimeout. The
|
// Magnet links opened from Chrome won't focus the app without a setTimeout.
|
||||||
// confirmation dialog Chrome shows causes Chrome to steal back the focus.
|
// The confirmation dialog Chrome shows causes Chrome to steal back the focus.
|
||||||
// Electron issue: https://github.com/atom/electron/issues/4338
|
// Electron issue: https://github.com/atom/electron/issues/4338
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
windows.focusWindow(windows.main)
|
windows.main.focus()
|
||||||
}, 100)
|
}, 100)
|
||||||
} else {
|
} else {
|
||||||
argv.push(torrentId)
|
argv.push(torrentId)
|
||||||
@@ -114,10 +115,11 @@ function onOpen (e, torrentId) {
|
|||||||
|
|
||||||
function onAppOpen (newArgv) {
|
function onAppOpen (newArgv) {
|
||||||
newArgv = sliceArgv(newArgv)
|
newArgv = sliceArgv(newArgv)
|
||||||
|
console.log(newArgv)
|
||||||
|
|
||||||
if (app.ipcReady) {
|
if (app.ipcReady) {
|
||||||
log('Second app instance opened, but was prevented:', newArgv)
|
log('Second app instance opened, but was prevented:', newArgv)
|
||||||
windows.focusWindow(windows.main)
|
windows.main.focus()
|
||||||
|
|
||||||
processArgv(newArgv)
|
processArgv(newArgv)
|
||||||
} else {
|
} else {
|
||||||
@@ -130,27 +132,22 @@ function sliceArgv (argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function processArgv (argv) {
|
function processArgv (argv) {
|
||||||
var pathsToOpen = []
|
var paths = []
|
||||||
argv.forEach(function (arg) {
|
argv.forEach(function (arg) {
|
||||||
if (arg === '-n') {
|
if (arg === '-n') {
|
||||||
menu.showOpenSeedFiles()
|
dialog.openSeedDirectory()
|
||||||
} else if (arg === '-o') {
|
} else if (arg === '-o') {
|
||||||
menu.showOpenTorrentFile()
|
dialog.openTorrentFile()
|
||||||
} else if (arg === '-u') {
|
} else if (arg === '-u') {
|
||||||
menu.showOpenTorrentAddress()
|
dialog.openTorrentAddress()
|
||||||
} else if (arg.startsWith('-psn')) {
|
} else if (arg.startsWith('-psn')) {
|
||||||
// Ignore OS X launchd "process serial number" argument
|
// Ignore OS X launchd "process serial number" argument
|
||||||
// More: https://github.com/feross/webtorrent-desktop/issues/214
|
// Issue: https://github.com/feross/webtorrent-desktop/issues/214
|
||||||
} else {
|
} else {
|
||||||
pathsToOpen.push(arg)
|
paths.push(arg)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (pathsToOpen.length > 0) openFilePaths(pathsToOpen)
|
if (paths.length > 0) {
|
||||||
}
|
windows.main.send('dispatch', 'onOpen', paths)
|
||||||
|
}
|
||||||
// Send files to the renderer process
|
|
||||||
// Opening files means either adding torrents, creating and seeding a torrent
|
|
||||||
// from files, or adding subtitles
|
|
||||||
function openFilePaths (paths) {
|
|
||||||
windows.main.send('dispatch', 'onOpen', paths)
|
|
||||||
}
|
}
|
||||||
|
|||||||
60
main/ipc.js
60
main/ipc.js
@@ -5,24 +5,23 @@ module.exports = {
|
|||||||
var electron = require('electron')
|
var electron = require('electron')
|
||||||
|
|
||||||
var app = electron.app
|
var app = electron.app
|
||||||
var ipcMain = electron.ipcMain
|
|
||||||
|
|
||||||
var log = require('./log')
|
var log = require('./log')
|
||||||
var menu = require('./menu')
|
var menu = require('./menu')
|
||||||
var windows = require('./windows')
|
var powerSaveBlocker = require('./power-save-blocker')
|
||||||
var shortcuts = require('./shortcuts')
|
var shortcuts = require('./shortcuts')
|
||||||
var vlc = require('./vlc')
|
var vlc = require('./vlc')
|
||||||
|
var windows = require('./windows')
|
||||||
|
|
||||||
// has to be a number, not a boolean, and undefined throws an error
|
// Messages from the main process, to be sent once the WebTorrent process starts
|
||||||
var powerSaveBlockerId = 0
|
|
||||||
|
|
||||||
// messages from the main process, to be sent once the WebTorrent process starts
|
|
||||||
var messageQueueMainToWebTorrent = []
|
var messageQueueMainToWebTorrent = []
|
||||||
|
|
||||||
// holds a ChildProcess while we're playing a video in VLC, null otherwise
|
// holds a ChildProcess while we're playing a video in VLC, null otherwise
|
||||||
var vlcProcess
|
var vlcProcess
|
||||||
|
|
||||||
function init () {
|
function init () {
|
||||||
|
var ipcMain = electron.ipcMain
|
||||||
|
|
||||||
ipcMain.on('ipcReady', function (e) {
|
ipcMain.on('ipcReady', function (e) {
|
||||||
windows.main.show()
|
windows.main.show()
|
||||||
app.ipcReady = true
|
app.ipcReady = true
|
||||||
@@ -39,7 +38,7 @@ function init () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('showOpenTorrentFile', menu.showOpenTorrentFile)
|
ipcMain.on('showOpenTorrentFile', () => menu.showOpenTorrentFile())
|
||||||
|
|
||||||
ipcMain.on('setBounds', function (e, bounds, maximize) {
|
ipcMain.on('setBounds', function (e, bounds, maximize) {
|
||||||
setBounds(bounds, maximize)
|
setBounds(bounds, maximize)
|
||||||
@@ -58,11 +57,11 @@ function init () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('toggleFullScreen', function (e, flag) {
|
ipcMain.on('toggleFullScreen', function (e, flag) {
|
||||||
menu.toggleFullScreen(flag)
|
windows.main.toggleFullScreen(flag)
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('setTitle', function (e, title) {
|
ipcMain.on('setTitle', function (e, title) {
|
||||||
windows.main.setTitle(title)
|
windows.main.win.setTitle(title)
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('openItem', function (e, path) {
|
ipcMain.on('openItem', function (e, path) {
|
||||||
@@ -75,9 +74,8 @@ function init () {
|
|||||||
electron.shell.showItemInFolder(path)
|
electron.shell.showItemInFolder(path)
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.on('blockPowerSave', blockPowerSave)
|
ipcMain.on('blockPowerSave', () => powerSaveBlocker.start())
|
||||||
|
ipcMain.on('unblockPowerSave', () => powerSaveBlocker.stop())
|
||||||
ipcMain.on('unblockPowerSave', unblockPowerSave)
|
|
||||||
|
|
||||||
ipcMain.on('onPlayerOpen', function () {
|
ipcMain.on('onPlayerOpen', function () {
|
||||||
menu.onPlayerOpen()
|
menu.onPlayerOpen()
|
||||||
@@ -174,7 +172,7 @@ function init () {
|
|||||||
|
|
||||||
function setBounds (bounds, maximize) {
|
function setBounds (bounds, maximize) {
|
||||||
// Do nothing in fullscreen
|
// Do nothing in fullscreen
|
||||||
if (!windows.main || windows.main.isFullScreen()) {
|
if (!windows.main.win || windows.main.win.isFullScreen()) {
|
||||||
log('setBounds: not setting bounds because we\'re in full screen')
|
log('setBounds: not setting bounds because we\'re in full screen')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -182,19 +180,19 @@ function setBounds (bounds, maximize) {
|
|||||||
// Maximize or minimize, if the second argument is present
|
// Maximize or minimize, if the second argument is present
|
||||||
var willBeMaximized
|
var willBeMaximized
|
||||||
if (maximize === true) {
|
if (maximize === true) {
|
||||||
if (!windows.main.isMaximized()) {
|
if (!windows.main.win.isMaximized()) {
|
||||||
log('setBounds: maximizing')
|
log('setBounds: maximizing')
|
||||||
windows.main.maximize()
|
windows.main.win.maximize()
|
||||||
}
|
}
|
||||||
willBeMaximized = true
|
willBeMaximized = true
|
||||||
} else if (maximize === false) {
|
} else if (maximize === false) {
|
||||||
if (windows.main.isMaximized()) {
|
if (windows.main.win.isMaximized()) {
|
||||||
log('setBounds: unmaximizing')
|
log('setBounds: unmaximizing')
|
||||||
windows.main.unmaximize()
|
windows.main.win.unmaximize()
|
||||||
}
|
}
|
||||||
willBeMaximized = false
|
willBeMaximized = false
|
||||||
} else {
|
} else {
|
||||||
willBeMaximized = windows.main.isMaximized()
|
willBeMaximized = windows.main.win.isMaximized()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assuming we're not maximized or maximizing, set the window size
|
// Assuming we're not maximized or maximizing, set the window size
|
||||||
@@ -202,12 +200,12 @@ function setBounds (bounds, maximize) {
|
|||||||
log('setBounds: setting bounds to ' + JSON.stringify(bounds))
|
log('setBounds: setting bounds to ' + JSON.stringify(bounds))
|
||||||
if (bounds.x === null && bounds.y === null) {
|
if (bounds.x === null && bounds.y === null) {
|
||||||
// X and Y not specified? By default, center on current screen
|
// X and Y not specified? By default, center on current screen
|
||||||
var scr = electron.screen.getDisplayMatching(windows.main.getBounds())
|
var scr = electron.screen.getDisplayMatching(windows.main.win.getBounds())
|
||||||
bounds.x = Math.round(scr.bounds.x + scr.bounds.width / 2 - bounds.width / 2)
|
bounds.x = Math.round(scr.bounds.x + scr.bounds.width / 2 - bounds.width / 2)
|
||||||
bounds.y = Math.round(scr.bounds.y + scr.bounds.height / 2 - bounds.height / 2)
|
bounds.y = Math.round(scr.bounds.y + scr.bounds.height / 2 - bounds.height / 2)
|
||||||
log('setBounds: centered to ' + JSON.stringify(bounds))
|
log('setBounds: centered to ' + JSON.stringify(bounds))
|
||||||
}
|
}
|
||||||
windows.main.setBounds(bounds, true)
|
windows.main.win.setBounds(bounds, true)
|
||||||
} else {
|
} else {
|
||||||
log('setBounds: not setting bounds because of window maximization')
|
log('setBounds: not setting bounds because of window maximization')
|
||||||
}
|
}
|
||||||
@@ -215,9 +213,8 @@ function setBounds (bounds, maximize) {
|
|||||||
|
|
||||||
function setAspectRatio (aspectRatio) {
|
function setAspectRatio (aspectRatio) {
|
||||||
log('setAspectRatio %o', aspectRatio)
|
log('setAspectRatio %o', aspectRatio)
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.setAspectRatio(aspectRatio)
|
windows.main.win.setAspectRatio(aspectRatio)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display string in dock badging area (OS X)
|
// Display string in dock badging area (OS X)
|
||||||
@@ -231,19 +228,6 @@ function setBadge (text) {
|
|||||||
// Show progress bar. Valid range is [0, 1]. Remove when < 0; indeterminate when > 1.
|
// Show progress bar. Valid range is [0, 1]. Remove when < 0; indeterminate when > 1.
|
||||||
function setProgress (progress) {
|
function setProgress (progress) {
|
||||||
log('setProgress %s', progress)
|
log('setProgress %s', progress)
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.setProgressBar(progress)
|
windows.main.win.setProgressBar(progress)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function blockPowerSave () {
|
|
||||||
powerSaveBlockerId = electron.powerSaveBlocker.start('prevent-display-sleep')
|
|
||||||
log('blockPowerSave %d', powerSaveBlockerId)
|
|
||||||
}
|
|
||||||
|
|
||||||
function unblockPowerSave () {
|
|
||||||
if (electron.powerSaveBlocker.isStarted(powerSaveBlockerId)) {
|
|
||||||
electron.powerSaveBlocker.stop(powerSaveBlockerId)
|
|
||||||
log('unblockPowerSave %d', powerSaveBlockerId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,16 @@ module.exports.error = error
|
|||||||
|
|
||||||
var electron = require('electron')
|
var electron = require('electron')
|
||||||
|
|
||||||
|
var config = require('../config')
|
||||||
var windows = require('./windows')
|
var windows = require('./windows')
|
||||||
|
|
||||||
var app = electron.app
|
var app = electron.app
|
||||||
|
|
||||||
function log (...args) {
|
function log (...args) {
|
||||||
|
if (!config.IS_PRODUCTION) {
|
||||||
|
// In development, also log to the console
|
||||||
|
console.log(...args)
|
||||||
|
}
|
||||||
if (app.ipcReady) {
|
if (app.ipcReady) {
|
||||||
windows.main.send('log', ...args)
|
windows.main.send('log', ...args)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
154
main/menu.js
154
main/menu.js
@@ -4,13 +4,7 @@ module.exports = {
|
|||||||
onPlayerOpen,
|
onPlayerOpen,
|
||||||
onToggleFullScreen,
|
onToggleFullScreen,
|
||||||
onWindowHide,
|
onWindowHide,
|
||||||
onWindowShow,
|
onWindowShow
|
||||||
|
|
||||||
// TODO: move these out of menu.js -- they don't belong here
|
|
||||||
showOpenSeedFiles,
|
|
||||||
showOpenTorrentAddress,
|
|
||||||
showOpenTorrentFile,
|
|
||||||
toggleFullScreen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var electron = require('electron')
|
var electron = require('electron')
|
||||||
@@ -18,6 +12,7 @@ var electron = require('electron')
|
|||||||
var app = electron.app
|
var app = electron.app
|
||||||
|
|
||||||
var config = require('../config')
|
var config = require('../config')
|
||||||
|
var dialog = require('./dialog')
|
||||||
var log = require('./log')
|
var log = require('./log')
|
||||||
var windows = require('./windows')
|
var windows = require('./windows')
|
||||||
|
|
||||||
@@ -33,100 +28,76 @@ function init () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleFullScreen (flag) {
|
|
||||||
log('toggleFullScreen %s', flag)
|
|
||||||
if (windows.main && windows.main.isVisible()) {
|
|
||||||
flag = flag != null ? flag : !windows.main.isFullScreen()
|
|
||||||
if (flag) {
|
|
||||||
// Allows the window to use the full screen in fullscreen mode (OS X).
|
|
||||||
windows.main.setAspectRatio(0)
|
|
||||||
}
|
|
||||||
windows.main.setFullScreen(flag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets whether the window should always show on top of other windows
|
// Sets whether the window should always show on top of other windows
|
||||||
function toggleFloatOnTop (flag) {
|
function toggleFloatOnTop (flag) {
|
||||||
|
if (!windows.main.win) return
|
||||||
log('toggleFloatOnTop %s', flag)
|
log('toggleFloatOnTop %s', flag)
|
||||||
if (windows.main) {
|
flag = flag != null ? flag : !windows.main.isAlwaysOnTop()
|
||||||
flag = flag != null ? flag : !windows.main.isAlwaysOnTop()
|
windows.main.setAlwaysOnTop(flag)
|
||||||
windows.main.setAlwaysOnTop(flag)
|
getMenuItem('Float on Top').checked = flag
|
||||||
getMenuItem('Float on Top').checked = flag
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleDevTools () {
|
function toggleDevTools () {
|
||||||
|
if (!windows.main.win) return
|
||||||
log('toggleDevTools')
|
log('toggleDevTools')
|
||||||
if (windows.main) {
|
windows.main.toggleDevTools()
|
||||||
windows.main.toggleDevTools()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showWebTorrentWindow () {
|
function showWebTorrentWindow () {
|
||||||
log('showWebTorrentWindow')
|
log('showWebTorrentWindow')
|
||||||
windows.webtorrent.show()
|
windows.webtorrent.show()
|
||||||
windows.webtorrent.webContents.openDevTools({ detach: true })
|
windows.webtorrent.win.webContents.openDevTools({ detach: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
function playPause () {
|
function playPause () {
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.send('dispatch', 'playPause')
|
windows.main.send('dispatch', 'playPause')
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function increaseVolume () {
|
function increaseVolume () {
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.send('dispatch', 'changeVolume', 0.1)
|
windows.main.send('dispatch', 'changeVolume', 0.1)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function decreaseVolume () {
|
function decreaseVolume () {
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.send('dispatch', 'changeVolume', -0.1)
|
windows.main.send('dispatch', 'changeVolume', -0.1)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function openSubtitles () {
|
function openSubtitles () {
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.send('dispatch', 'openSubtitles')
|
windows.main.send('dispatch', 'openSubtitles')
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function skipForward () {
|
function skipForward () {
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.send('dispatch', 'skip', 1)
|
windows.main.send('dispatch', 'skip', 1)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function skipBack () {
|
function skipBack () {
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.send('dispatch', 'skip', -1)
|
windows.main.send('dispatch', 'skip', -1)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function increasePlaybackRate () {
|
function increasePlaybackRate () {
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.send('dispatch', 'changePlaybackRate', 1)
|
windows.main.send('dispatch', 'changePlaybackRate', 1)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function decreasePlaybackRate () {
|
function decreasePlaybackRate () {
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.send('dispatch', 'changePlaybackRate', -1)
|
windows.main.send('dispatch', 'changePlaybackRate', -1)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the preferences window
|
// Open the preferences window
|
||||||
function showPreferences () {
|
function showPreferences () {
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.send('dispatch', 'preferences')
|
windows.main.send('dispatch', 'preferences')
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function escapeBack () {
|
function escapeBack () {
|
||||||
if (windows.main) {
|
if (!windows.main.win) return
|
||||||
windows.main.send('dispatch', 'escapeBack')
|
windows.main.send('dispatch', 'escapeBack')
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWindowShow () {
|
function onWindowShow () {
|
||||||
@@ -166,8 +137,10 @@ function onPlayerClose () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onToggleFullScreen (isFullScreen) {
|
function onToggleFullScreen (isFullScreen) {
|
||||||
isFullScreen = isFullScreen != null ? isFullScreen : windows.main.isFullScreen()
|
if (isFullScreen == null) {
|
||||||
windows.main.setMenuBarVisibility(!isFullScreen)
|
isFullScreen = windows.main.win.isFullScreen()
|
||||||
|
}
|
||||||
|
windows.main.win.setMenuBarVisibility(!isFullScreen)
|
||||||
getMenuItem('Full Screen').checked = isFullScreen
|
getMenuItem('Full Screen').checked = isFullScreen
|
||||||
windows.main.send('fullscreenChanged', isFullScreen)
|
windows.main.send('fullscreenChanged', isFullScreen)
|
||||||
}
|
}
|
||||||
@@ -181,49 +154,6 @@ function getMenuItem (label) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prompts the user for a file, then creates a torrent. Only allows a single file
|
|
||||||
// selection.
|
|
||||||
function showOpenSeedFile () {
|
|
||||||
electron.dialog.showOpenDialog({
|
|
||||||
title: 'Select a file for the torrent file.',
|
|
||||||
properties: [ 'openFile' ]
|
|
||||||
}, function (selectedPaths) {
|
|
||||||
if (!Array.isArray(selectedPaths)) return
|
|
||||||
windows.main.send('dispatch', 'showCreateTorrent', selectedPaths)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prompts the user for a file or directory, then creates a torrent. Only allows a single
|
|
||||||
// selection. To create a multi-file torrent, the user must select a directory.
|
|
||||||
function showOpenSeedFiles () {
|
|
||||||
electron.dialog.showOpenDialog({
|
|
||||||
title: 'Select a file or folder for the torrent file.',
|
|
||||||
properties: [ 'openFile', 'openDirectory' ]
|
|
||||||
}, function (selectedPaths) {
|
|
||||||
if (!Array.isArray(selectedPaths)) return
|
|
||||||
windows.main.send('dispatch', 'showCreateTorrent', selectedPaths)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prompts the user to choose a torrent file, then adds it to the app
|
|
||||||
function showOpenTorrentFile () {
|
|
||||||
electron.dialog.showOpenDialog(windows.main, {
|
|
||||||
title: 'Select a .torrent file to open.',
|
|
||||||
filters: [{ name: 'Torrent Files', extensions: ['torrent'] }],
|
|
||||||
properties: [ 'openFile', 'multiSelections' ]
|
|
||||||
}, function (selectedPaths) {
|
|
||||||
if (!Array.isArray(selectedPaths)) return
|
|
||||||
selectedPaths.forEach(function (selectedPath) {
|
|
||||||
windows.main.send('dispatch', 'addTorrent', selectedPath)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prompts the user for the URL of a torrent file, then downloads and adds it
|
|
||||||
function showOpenTorrentAddress () {
|
|
||||||
windows.main.send('showOpenTorrentAddress')
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAppMenuTemplate () {
|
function getAppMenuTemplate () {
|
||||||
var template = [
|
var template = [
|
||||||
{
|
{
|
||||||
@@ -234,17 +164,17 @@ function getAppMenuTemplate () {
|
|||||||
? 'Create New Torrent...'
|
? 'Create New Torrent...'
|
||||||
: 'Create New Torrent from Folder...',
|
: 'Create New Torrent from Folder...',
|
||||||
accelerator: 'CmdOrCtrl+N',
|
accelerator: 'CmdOrCtrl+N',
|
||||||
click: showOpenSeedFiles
|
click: () => dialog.openSeedDirectory()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Open Torrent File...',
|
label: 'Open Torrent File...',
|
||||||
accelerator: 'CmdOrCtrl+O',
|
accelerator: 'CmdOrCtrl+O',
|
||||||
click: showOpenTorrentFile
|
click: () => dialog.openTorrentFile()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Open Torrent Address...',
|
label: 'Open Torrent Address...',
|
||||||
accelerator: 'CmdOrCtrl+U',
|
accelerator: 'CmdOrCtrl+U',
|
||||||
click: showOpenTorrentAddress
|
click: () => dialog.openTorrentAddress()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'separator'
|
type: 'separator'
|
||||||
@@ -300,7 +230,7 @@ function getAppMenuTemplate () {
|
|||||||
accelerator: process.platform === 'darwin'
|
accelerator: process.platform === 'darwin'
|
||||||
? 'Ctrl+Command+F'
|
? 'Ctrl+Command+F'
|
||||||
: 'F11',
|
: 'F11',
|
||||||
click: () => toggleFullScreen()
|
click: () => windows.toggleFullScreen()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Float on Top',
|
label: 'Float on Top',
|
||||||
@@ -505,7 +435,7 @@ function getAppMenuTemplate () {
|
|||||||
// File menu (Windows, Linux)
|
// File menu (Windows, Linux)
|
||||||
template[0].submenu.unshift({
|
template[0].submenu.unshift({
|
||||||
label: 'Create New Torrent from File...',
|
label: 'Create New Torrent from File...',
|
||||||
click: showOpenSeedFile
|
click: () => dialog.openSeedFile()
|
||||||
})
|
})
|
||||||
|
|
||||||
// Help menu (Windows, Linux)
|
// Help menu (Windows, Linux)
|
||||||
@@ -515,7 +445,7 @@ function getAppMenuTemplate () {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'About ' + config.APP_NAME,
|
label: 'About ' + config.APP_NAME,
|
||||||
click: windows.createAboutWindow
|
click: () => windows.about.create()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -537,17 +467,17 @@ function getDockMenuTemplate () {
|
|||||||
{
|
{
|
||||||
label: 'Create New Torrent...',
|
label: 'Create New Torrent...',
|
||||||
accelerator: 'CmdOrCtrl+N',
|
accelerator: 'CmdOrCtrl+N',
|
||||||
click: showOpenSeedFiles
|
click: () => dialog.openSeedDirectory()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Open Torrent File...',
|
label: 'Open Torrent File...',
|
||||||
accelerator: 'CmdOrCtrl+O',
|
accelerator: 'CmdOrCtrl+O',
|
||||||
click: showOpenTorrentFile
|
click: () => dialog.openTorrentFile()
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Open Torrent Address...',
|
label: 'Open Torrent Address...',
|
||||||
accelerator: 'CmdOrCtrl+U',
|
accelerator: 'CmdOrCtrl+U',
|
||||||
click: showOpenTorrentAddress
|
click: () => dialog.openTorrentAddress()
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
25
main/power-save-blocker.js
Normal file
25
main/power-save-blocker.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
module.exports = {
|
||||||
|
start,
|
||||||
|
stop
|
||||||
|
}
|
||||||
|
|
||||||
|
var electron = require('electron')
|
||||||
|
var log = require('./log')
|
||||||
|
|
||||||
|
var powerSaveBlockerId = 0
|
||||||
|
|
||||||
|
function start () {
|
||||||
|
// Stop the previous power saver block, if one exists.
|
||||||
|
stop()
|
||||||
|
|
||||||
|
powerSaveBlockerId = electron.powerSaveBlocker.start('prevent-display-sleep')
|
||||||
|
log('powerSaveBlocker.start %d', powerSaveBlockerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
function stop () {
|
||||||
|
if (!electron.powerSaveBlocker.isStarted(powerSaveBlockerId)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
electron.powerSaveBlocker.stop(powerSaveBlockerId)
|
||||||
|
log('powerSaveBlocker.stop %d', powerSaveBlockerId)
|
||||||
|
}
|
||||||
98
main/tray.js
98
main/tray.js
@@ -1,9 +1,10 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
|
hasTray,
|
||||||
init,
|
init,
|
||||||
hasTray
|
onWindowHide,
|
||||||
|
onWindowShow
|
||||||
}
|
}
|
||||||
|
|
||||||
var cp = require('child_process')
|
|
||||||
var electron = require('electron')
|
var electron = require('electron')
|
||||||
|
|
||||||
var app = electron.app
|
var app = electron.app
|
||||||
@@ -11,41 +12,32 @@ var app = electron.app
|
|||||||
var config = require('../config')
|
var config = require('../config')
|
||||||
var windows = require('./windows')
|
var windows = require('./windows')
|
||||||
|
|
||||||
var trayIcon
|
var tray
|
||||||
|
|
||||||
function init () {
|
function init () {
|
||||||
// OS X has no tray icon
|
|
||||||
if (process.platform === 'darwin') return
|
|
||||||
|
|
||||||
// On Linux, asynchronously check for libappindicator1
|
|
||||||
if (process.platform === 'linux') {
|
if (process.platform === 'linux') {
|
||||||
checkLinuxTraySupport(function (supportsTray) {
|
initLinux()
|
||||||
if (supportsTray) createTrayIcon()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
if (process.platform === 'win32') {
|
||||||
// Windows always supports minimize-to-tray
|
initWin32()
|
||||||
if (process.platform === 'win32') createTrayIcon()
|
}
|
||||||
|
// OS X apps generally do not have menu bar icons
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasTray () {
|
function initLinux () {
|
||||||
return !!trayIcon
|
// Check for libappindicator1 support before creating tray icon
|
||||||
|
checkLinuxTraySupport(function (supportsTray) {
|
||||||
|
if (supportsTray) createTray()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTrayIcon () {
|
function initWin32 () {
|
||||||
trayIcon = new electron.Tray(getIconPath())
|
createTray()
|
||||||
|
|
||||||
// On Windows, left click to open the app, right click for context menu
|
|
||||||
// On Linux, any click (right or left) opens the context menu
|
|
||||||
trayIcon.on('click', showApp)
|
|
||||||
|
|
||||||
// Show the tray context menu, and keep the available commands up to date
|
|
||||||
updateTrayMenu()
|
|
||||||
windows.main.on('show', updateTrayMenu)
|
|
||||||
windows.main.on('hide', updateTrayMenu)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkLinuxTraySupport (cb) {
|
function checkLinuxTraySupport (cb) {
|
||||||
|
var cp = require('child_process')
|
||||||
|
|
||||||
// Check that we're on Ubuntu (or another debian system) and that we have
|
// Check that we're on Ubuntu (or another debian system) and that we have
|
||||||
// libappindicator1. If WebTorrent was installed from the deb file, we should
|
// libappindicator1. If WebTorrent was installed from the deb file, we should
|
||||||
// always have it. If it was installed from the zip file, we might not.
|
// always have it. If it was installed from the zip file, we might not.
|
||||||
@@ -57,18 +49,54 @@ function checkLinuxTraySupport (cb) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hasTray () {
|
||||||
|
return !!tray
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTray () {
|
||||||
|
tray = new electron.Tray(getIconPath())
|
||||||
|
|
||||||
|
// On Windows, left click opens the app, right click opens the context menu.
|
||||||
|
// On Linux, any click (left or right) opens the context menu.
|
||||||
|
tray.on('click', showApp)
|
||||||
|
|
||||||
|
// Show the tray context menu, and keep the available commands up to date
|
||||||
|
updateTrayMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWindowHide () {
|
||||||
|
updateTrayMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWindowShow () {
|
||||||
|
updateTrayMenu()
|
||||||
|
}
|
||||||
|
|
||||||
function updateTrayMenu () {
|
function updateTrayMenu () {
|
||||||
var showHideMenuItem
|
if (!tray) return
|
||||||
if (windows.main.isVisible()) {
|
|
||||||
showHideMenuItem = { label: 'Hide to tray', click: hideApp }
|
|
||||||
} else {
|
|
||||||
showHideMenuItem = { label: 'Show', click: showApp }
|
|
||||||
}
|
|
||||||
var contextMenu = electron.Menu.buildFromTemplate([
|
var contextMenu = electron.Menu.buildFromTemplate([
|
||||||
showHideMenuItem,
|
getToggleItem(),
|
||||||
{ label: 'Quit', click: () => app.quit() }
|
{
|
||||||
|
label: 'Quit',
|
||||||
|
click: () => app.quit()
|
||||||
|
}
|
||||||
])
|
])
|
||||||
trayIcon.setContextMenu(contextMenu)
|
tray.setContextMenu(contextMenu)
|
||||||
|
|
||||||
|
function getToggleItem () {
|
||||||
|
if (windows.main.win.isVisible()) {
|
||||||
|
return {
|
||||||
|
label: 'Hide to tray',
|
||||||
|
click: hideApp
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
label: 'Show WebTorrent',
|
||||||
|
click: showApp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showApp () {
|
function showApp () {
|
||||||
|
|||||||
145
main/windows.js
145
main/windows.js
@@ -1,145 +0,0 @@
|
|||||||
var windows = module.exports = {
|
|
||||||
about: null,
|
|
||||||
main: null,
|
|
||||||
createAboutWindow,
|
|
||||||
createWebTorrentHiddenWindow,
|
|
||||||
createMainWindow,
|
|
||||||
focusWindow
|
|
||||||
}
|
|
||||||
|
|
||||||
var electron = require('electron')
|
|
||||||
|
|
||||||
var app = electron.app
|
|
||||||
|
|
||||||
var config = require('../config')
|
|
||||||
var menu = require('./menu')
|
|
||||||
var tray = require('./tray')
|
|
||||||
|
|
||||||
function createAboutWindow () {
|
|
||||||
if (windows.about) {
|
|
||||||
return focusWindow(windows.about)
|
|
||||||
}
|
|
||||||
var win = windows.about = new electron.BrowserWindow({
|
|
||||||
backgroundColor: '#ECECEC',
|
|
||||||
show: false,
|
|
||||||
center: true,
|
|
||||||
resizable: false,
|
|
||||||
icon: getIconPath(),
|
|
||||||
title: process.platform !== 'darwin'
|
|
||||||
? 'About ' + config.APP_WINDOW_TITLE
|
|
||||||
: '',
|
|
||||||
useContentSize: true, // Specify web page size without OS chrome
|
|
||||||
width: 300,
|
|
||||||
height: 170,
|
|
||||||
minimizable: false,
|
|
||||||
maximizable: false,
|
|
||||||
fullscreen: false,
|
|
||||||
skipTaskbar: true
|
|
||||||
})
|
|
||||||
win.loadURL(config.WINDOW_ABOUT)
|
|
||||||
|
|
||||||
// No window menu
|
|
||||||
win.setMenu(null)
|
|
||||||
|
|
||||||
win.webContents.on('did-finish-load', function () {
|
|
||||||
win.show()
|
|
||||||
})
|
|
||||||
|
|
||||||
win.once('closed', function () {
|
|
||||||
windows.about = null
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function createWebTorrentHiddenWindow () {
|
|
||||||
var win = windows.webtorrent = new electron.BrowserWindow({
|
|
||||||
backgroundColor: '#1E1E1E',
|
|
||||||
show: false,
|
|
||||||
center: true,
|
|
||||||
title: 'webtorrent-hidden-window',
|
|
||||||
useContentSize: true,
|
|
||||||
width: 150,
|
|
||||||
height: 150,
|
|
||||||
minimizable: false,
|
|
||||||
maximizable: false,
|
|
||||||
resizable: false,
|
|
||||||
fullscreenable: false,
|
|
||||||
fullscreen: false,
|
|
||||||
skipTaskbar: true
|
|
||||||
})
|
|
||||||
win.loadURL(config.WINDOW_WEBTORRENT)
|
|
||||||
|
|
||||||
// Prevent killing the WebTorrent process
|
|
||||||
win.on('close', function (e) {
|
|
||||||
if (!app.isQuitting) {
|
|
||||||
e.preventDefault()
|
|
||||||
win.hide()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
win.once('closed', function () {
|
|
||||||
windows.webtorrent = null
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var HEADER_HEIGHT = 37
|
|
||||||
var TORRENT_HEIGHT = 100
|
|
||||||
|
|
||||||
function createMainWindow () {
|
|
||||||
if (windows.main) {
|
|
||||||
return focusWindow(windows.main)
|
|
||||||
}
|
|
||||||
var win = windows.main = new electron.BrowserWindow({
|
|
||||||
backgroundColor: '#1E1E1E',
|
|
||||||
darkTheme: true, // Forces dark theme (GTK+3)
|
|
||||||
icon: getIconPath(), // Window icon (Windows, Linux)
|
|
||||||
minWidth: config.WINDOW_MIN_WIDTH,
|
|
||||||
minHeight: config.WINDOW_MIN_HEIGHT,
|
|
||||||
show: false, // Hide window until renderer sends 'ipcReady' event
|
|
||||||
title: config.APP_WINDOW_TITLE,
|
|
||||||
titleBarStyle: 'hidden-inset', // Hide OS chrome, except traffic light buttons (OS X)
|
|
||||||
useContentSize: true, // Specify web page size without OS chrome
|
|
||||||
width: 500,
|
|
||||||
height: HEADER_HEIGHT + (TORRENT_HEIGHT * 6) // header height + 5 torrents
|
|
||||||
})
|
|
||||||
win.loadURL(config.WINDOW_MAIN)
|
|
||||||
if (process.platform === 'darwin') {
|
|
||||||
win.setSheetOffset(HEADER_HEIGHT)
|
|
||||||
}
|
|
||||||
|
|
||||||
win.webContents.on('dom-ready', function () {
|
|
||||||
menu.onToggleFullScreen()
|
|
||||||
})
|
|
||||||
|
|
||||||
win.on('blur', menu.onWindowHide)
|
|
||||||
win.on('focus', menu.onWindowShow)
|
|
||||||
|
|
||||||
win.on('enter-full-screen', () => menu.onToggleFullScreen(true))
|
|
||||||
win.on('leave-full-screen', () => menu.onToggleFullScreen(false))
|
|
||||||
|
|
||||||
win.on('close', function (e) {
|
|
||||||
if (process.platform !== 'darwin' && !tray.hasTray()) {
|
|
||||||
app.quit()
|
|
||||||
} else if (!app.isQuitting) {
|
|
||||||
e.preventDefault()
|
|
||||||
win.hide()
|
|
||||||
win.send('dispatch', 'backToList')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
win.once('closed', function () {
|
|
||||||
windows.main = null
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function focusWindow (win) {
|
|
||||||
if (win.isMinimized()) {
|
|
||||||
win.restore()
|
|
||||||
}
|
|
||||||
win.show() // shows and gives focus
|
|
||||||
}
|
|
||||||
|
|
||||||
function getIconPath () {
|
|
||||||
return process.platform === 'win32'
|
|
||||||
? config.APP_ICON + '.ico'
|
|
||||||
: config.APP_ICON + '.png'
|
|
||||||
}
|
|
||||||
50
main/windows/about.js
Normal file
50
main/windows/about.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
var about = module.exports = {
|
||||||
|
create,
|
||||||
|
win: null
|
||||||
|
}
|
||||||
|
|
||||||
|
var electron = require('electron')
|
||||||
|
|
||||||
|
var config = require('../../config')
|
||||||
|
var util = require('./util')
|
||||||
|
|
||||||
|
function create () {
|
||||||
|
if (about.win) {
|
||||||
|
return util.focusWindow(about.win)
|
||||||
|
}
|
||||||
|
|
||||||
|
var win = about.win = new electron.BrowserWindow({
|
||||||
|
backgroundColor: '#ECECEC',
|
||||||
|
center: true,
|
||||||
|
fullscreen: false,
|
||||||
|
height: 170,
|
||||||
|
icon: getIconPath(),
|
||||||
|
maximizable: false,
|
||||||
|
minimizable: false,
|
||||||
|
resizable: false,
|
||||||
|
show: false,
|
||||||
|
skipTaskbar: true,
|
||||||
|
useContentSize: true,
|
||||||
|
width: 300
|
||||||
|
})
|
||||||
|
|
||||||
|
win.loadURL(config.WINDOW_ABOUT)
|
||||||
|
|
||||||
|
// No menu on the About window
|
||||||
|
win.setMenu(null)
|
||||||
|
|
||||||
|
// TODO: can this be removed?
|
||||||
|
win.webContents.on('did-finish-load', function () {
|
||||||
|
win.show()
|
||||||
|
})
|
||||||
|
|
||||||
|
win.once('closed', function () {
|
||||||
|
about.win = null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIconPath () {
|
||||||
|
return process.platform === 'win32'
|
||||||
|
? config.APP_ICON + '.ico'
|
||||||
|
: config.APP_ICON + '.png'
|
||||||
|
}
|
||||||
3
main/windows/index.js
Normal file
3
main/windows/index.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
exports.about = require('./about')
|
||||||
|
exports.main = require('./main')
|
||||||
|
exports.webtorrent = require('./webtorrent')
|
||||||
115
main/windows/main.js
Normal file
115
main/windows/main.js
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
var main = module.exports = {
|
||||||
|
create,
|
||||||
|
focus,
|
||||||
|
hide,
|
||||||
|
send,
|
||||||
|
show,
|
||||||
|
toggleFullScreen,
|
||||||
|
win: null
|
||||||
|
}
|
||||||
|
|
||||||
|
var electron = require('electron')
|
||||||
|
|
||||||
|
var app = electron.app
|
||||||
|
|
||||||
|
var config = require('../../config')
|
||||||
|
var log = require('../log')
|
||||||
|
var menu = require('../menu')
|
||||||
|
var tray = require('../tray')
|
||||||
|
var util = require('./util')
|
||||||
|
|
||||||
|
var HEADER_HEIGHT = 37
|
||||||
|
var TORRENT_HEIGHT = 100
|
||||||
|
|
||||||
|
function create () {
|
||||||
|
if (main.win) {
|
||||||
|
return util.focusWindow(main.win)
|
||||||
|
}
|
||||||
|
var win = main.win = new electron.BrowserWindow({
|
||||||
|
backgroundColor: '#1E1E1E',
|
||||||
|
darkTheme: true, // Forces dark theme (GTK+3)
|
||||||
|
icon: getIconPath(), // Window icon (Windows, Linux)
|
||||||
|
minWidth: config.WINDOW_MIN_WIDTH,
|
||||||
|
minHeight: config.WINDOW_MIN_HEIGHT,
|
||||||
|
show: false, // Hide window until renderer sends 'ipcReady'
|
||||||
|
title: config.APP_WINDOW_TITLE,
|
||||||
|
titleBarStyle: 'hidden-inset', // Hide title bar (OS X)
|
||||||
|
useContentSize: true, // Specify web page size without OS chrome
|
||||||
|
width: 500,
|
||||||
|
height: HEADER_HEIGHT + (TORRENT_HEIGHT * 6) // header height + 5 torrents
|
||||||
|
})
|
||||||
|
|
||||||
|
win.loadURL(config.WINDOW_MAIN)
|
||||||
|
|
||||||
|
if (win.setSheetOffset) win.setSheetOffset(HEADER_HEIGHT)
|
||||||
|
|
||||||
|
win.webContents.on('dom-ready', function () {
|
||||||
|
menu.onToggleFullScreen()
|
||||||
|
})
|
||||||
|
|
||||||
|
win.on('blur', function () {
|
||||||
|
menu.onWindowHide()
|
||||||
|
tray.onWindowHide()
|
||||||
|
})
|
||||||
|
|
||||||
|
win.on('focus', function () {
|
||||||
|
menu.onWindowShow()
|
||||||
|
tray.onWindowShow()
|
||||||
|
})
|
||||||
|
|
||||||
|
win.on('enter-full-screen', () => menu.onToggleFullScreen(true))
|
||||||
|
win.on('leave-full-screen', () => menu.onToggleFullScreen(false))
|
||||||
|
|
||||||
|
win.on('close', function (e) {
|
||||||
|
if (process.platform !== 'darwin' && !tray.hasTray()) {
|
||||||
|
app.quit()
|
||||||
|
} else if (!app.isQuitting) {
|
||||||
|
e.preventDefault()
|
||||||
|
win.hide()
|
||||||
|
win.send('dispatch', 'backToList')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIconPath () {
|
||||||
|
return process.platform === 'win32'
|
||||||
|
? config.APP_ICON + '.ico'
|
||||||
|
: config.APP_ICON + '.png'
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleFullScreen (flag) {
|
||||||
|
if (!main.win || !main.win.isVisible()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag == null) flag = !main.win.isFullScreen()
|
||||||
|
|
||||||
|
log('toggleFullScreen %s', flag)
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
// Fullscreen behaves oddly unless the aspect ratio is disabled. (OS X)
|
||||||
|
main.win.setAspectRatio(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
main.win.setFullScreen(flag)
|
||||||
|
}
|
||||||
|
|
||||||
|
function send (...args) {
|
||||||
|
if (!main.win) return
|
||||||
|
main.win.send(...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
function show () {
|
||||||
|
if (!main.win) return
|
||||||
|
main.win.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide () {
|
||||||
|
if (!main.win) return
|
||||||
|
main.win.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
function focus () {
|
||||||
|
if (!main.win) return
|
||||||
|
util.focusWindow(main.win)
|
||||||
|
}
|
||||||
11
main/windows/util.js
Normal file
11
main/windows/util.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
module.exports = {
|
||||||
|
focusWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
function focusWindow (win) {
|
||||||
|
if (win.isMinimized()) {
|
||||||
|
// TODO: can this be removed?
|
||||||
|
win.restore()
|
||||||
|
}
|
||||||
|
win.show() // shows and gives focus
|
||||||
|
}
|
||||||
48
main/windows/webtorrent.js
Normal file
48
main/windows/webtorrent.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
var webtorrent = module.exports = {
|
||||||
|
create,
|
||||||
|
send,
|
||||||
|
show,
|
||||||
|
win: null
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = require('../../config')
|
||||||
|
var electron = require('electron')
|
||||||
|
|
||||||
|
function create () {
|
||||||
|
var win = webtorrent.win = new electron.BrowserWindow({
|
||||||
|
backgroundColor: '#1E1E1E',
|
||||||
|
center: true,
|
||||||
|
fullscreen: false,
|
||||||
|
fullscreenable: false,
|
||||||
|
height: 150,
|
||||||
|
maximizable: false,
|
||||||
|
minimizable: false,
|
||||||
|
resizable: false,
|
||||||
|
show: false,
|
||||||
|
skipTaskbar: true,
|
||||||
|
title: 'webtorrent-hidden-window',
|
||||||
|
useContentSize: true,
|
||||||
|
width: 150
|
||||||
|
})
|
||||||
|
|
||||||
|
win.loadURL(config.WINDOW_WEBTORRENT)
|
||||||
|
|
||||||
|
// Prevent killing the WebTorrent process
|
||||||
|
win.on('close', function (e) {
|
||||||
|
if (electron.app.isQuitting) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.preventDefault()
|
||||||
|
win.hide()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function show () {
|
||||||
|
if (!webtorrent.win) return
|
||||||
|
webtorrent.win.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
function send (...args) {
|
||||||
|
if (!webtorrent.win) return
|
||||||
|
webtorrent.win.send(...args)
|
||||||
|
}
|
||||||
@@ -606,7 +606,8 @@ function saveState () {
|
|||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the user drag-drops files onto the app
|
// Called when the user adds files (.torrent, files to seed, subtitles) to the app
|
||||||
|
// via any method (drag-drop, drag to app icon, command line)
|
||||||
function onOpen (files) {
|
function onOpen (files) {
|
||||||
if (!Array.isArray(files)) files = [ files ]
|
if (!Array.isArray(files)) files = [ files ]
|
||||||
|
|
||||||
@@ -674,12 +675,13 @@ function addTorrent (torrentId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addSubtitles (files, autoSelect) {
|
function addSubtitles (files, autoSelect) {
|
||||||
// Subtitles are only supported while playing video
|
// Subtitles are only supported when playing video files
|
||||||
if (state.playing.type !== 'video') return
|
if (state.playing.type !== 'video') return
|
||||||
|
if (files.length === 0) return
|
||||||
|
|
||||||
// Read the files concurrently, then add all resulting subtitle tracks
|
// Read the files concurrently, then add all resulting subtitle tracks
|
||||||
var jobs = files.map((file) => (cb) => loadSubtitle(file, cb))
|
var tasks = files.map((file) => (cb) => loadSubtitle(file, cb))
|
||||||
parallel(jobs, function (err, tracks) {
|
parallel(tasks, function (err, tracks) {
|
||||||
if (err) return onError(err)
|
if (err) return onError(err)
|
||||||
|
|
||||||
for (var i = 0; i < tracks.length; i++) {
|
for (var i = 0; i < tracks.length; i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user