Major refactor -- split windows into separate files

This commit is contained in:
Feross Aboukhadijeh
2016-05-27 00:01:30 -07:00
parent 3757507b18
commit 001601bc5f
15 changed files with 464 additions and 358 deletions

View File

@@ -3,7 +3,6 @@ module.exports = {
}
var electron = require('electron')
var get = require('simple-get')
var config = require('../config')
var log = require('./log')
@@ -13,6 +12,7 @@ var ANNOUNCEMENT_URL = config.ANNOUNCEMENT_URL +
'&platform=' + process.platform
function init () {
var get = require('simple-get')
get.concat(ANNOUNCEMENT_URL, onResponse)
}

53
main/dialog.js Normal file
View 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')
}

View File

@@ -8,6 +8,7 @@ var ipcMain = electron.ipcMain
var announcement = require('./announcement')
var config = require('../config')
var crashReporter = require('../crash-reporter')
var dialog = require('./dialog')
var handlers = require('./handlers')
var ipc = require('./ipc')
var log = require('./log')
@@ -60,8 +61,8 @@ function init () {
app.on('ready', function () {
isReady = true
windows.createMainWindow()
windows.createWebTorrentHiddenWindow()
windows.main.create()
windows.webtorrent.create()
menu.init()
// To keep app startup fast, some code is delayed.
@@ -79,13 +80,13 @@ function init () {
app.isQuitting = true
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())
setTimeout(() => app.quit(), 2000) /* quit after 2 secs, at most */
setTimeout(() => app.quit(), 2000) // quit after 2 secs, at most
})
app.on('activate', function () {
if (isReady) windows.createMainWindow()
if (isReady) windows.main.create()
})
}
@@ -101,11 +102,11 @@ function onOpen (e, torrentId) {
if (app.ipcReady) {
windows.main.send('dispatch', 'onOpen', torrentId)
// Magnet links opened from Chrome won't focus the app without a setTimeout. The
// confirmation dialog Chrome shows causes Chrome to steal back the focus.
// Magnet links opened from Chrome won't focus the app without a setTimeout.
// The confirmation dialog Chrome shows causes Chrome to steal back the focus.
// Electron issue: https://github.com/atom/electron/issues/4338
setTimeout(function () {
windows.focusWindow(windows.main)
windows.main.focus()
}, 100)
} else {
argv.push(torrentId)
@@ -114,10 +115,11 @@ function onOpen (e, torrentId) {
function onAppOpen (newArgv) {
newArgv = sliceArgv(newArgv)
console.log(newArgv)
if (app.ipcReady) {
log('Second app instance opened, but was prevented:', newArgv)
windows.focusWindow(windows.main)
windows.main.focus()
processArgv(newArgv)
} else {
@@ -130,27 +132,22 @@ function sliceArgv (argv) {
}
function processArgv (argv) {
var pathsToOpen = []
var paths = []
argv.forEach(function (arg) {
if (arg === '-n') {
menu.showOpenSeedFiles()
dialog.openSeedDirectory()
} else if (arg === '-o') {
menu.showOpenTorrentFile()
dialog.openTorrentFile()
} else if (arg === '-u') {
menu.showOpenTorrentAddress()
dialog.openTorrentAddress()
} else if (arg.startsWith('-psn')) {
// 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 {
pathsToOpen.push(arg)
paths.push(arg)
}
})
if (pathsToOpen.length > 0) openFilePaths(pathsToOpen)
}
// 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)
if (paths.length > 0) {
windows.main.send('dispatch', 'onOpen', paths)
}
}

View File

@@ -5,24 +5,23 @@ module.exports = {
var electron = require('electron')
var app = electron.app
var ipcMain = electron.ipcMain
var log = require('./log')
var menu = require('./menu')
var windows = require('./windows')
var powerSaveBlocker = require('./power-save-blocker')
var shortcuts = require('./shortcuts')
var vlc = require('./vlc')
var windows = require('./windows')
// has to be a number, not a boolean, and undefined throws an error
var powerSaveBlockerId = 0
// messages from the main process, to be sent once the WebTorrent process starts
// Messages from the main process, to be sent once the WebTorrent process starts
var messageQueueMainToWebTorrent = []
// holds a ChildProcess while we're playing a video in VLC, null otherwise
var vlcProcess
function init () {
var ipcMain = electron.ipcMain
ipcMain.on('ipcReady', function (e) {
windows.main.show()
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) {
setBounds(bounds, maximize)
@@ -58,11 +57,11 @@ function init () {
})
ipcMain.on('toggleFullScreen', function (e, flag) {
menu.toggleFullScreen(flag)
windows.main.toggleFullScreen(flag)
})
ipcMain.on('setTitle', function (e, title) {
windows.main.setTitle(title)
windows.main.win.setTitle(title)
})
ipcMain.on('openItem', function (e, path) {
@@ -75,9 +74,8 @@ function init () {
electron.shell.showItemInFolder(path)
})
ipcMain.on('blockPowerSave', blockPowerSave)
ipcMain.on('unblockPowerSave', unblockPowerSave)
ipcMain.on('blockPowerSave', () => powerSaveBlocker.start())
ipcMain.on('unblockPowerSave', () => powerSaveBlocker.stop())
ipcMain.on('onPlayerOpen', function () {
menu.onPlayerOpen()
@@ -174,7 +172,7 @@ function init () {
function setBounds (bounds, maximize) {
// 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')
return
}
@@ -182,19 +180,19 @@ function setBounds (bounds, maximize) {
// Maximize or minimize, if the second argument is present
var willBeMaximized
if (maximize === true) {
if (!windows.main.isMaximized()) {
if (!windows.main.win.isMaximized()) {
log('setBounds: maximizing')
windows.main.maximize()
windows.main.win.maximize()
}
willBeMaximized = true
} else if (maximize === false) {
if (windows.main.isMaximized()) {
if (windows.main.win.isMaximized()) {
log('setBounds: unmaximizing')
windows.main.unmaximize()
windows.main.win.unmaximize()
}
willBeMaximized = false
} else {
willBeMaximized = windows.main.isMaximized()
willBeMaximized = windows.main.win.isMaximized()
}
// 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))
if (bounds.x === null && bounds.y === null) {
// 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.y = Math.round(scr.bounds.y + scr.bounds.height / 2 - bounds.height / 2)
log('setBounds: centered to ' + JSON.stringify(bounds))
}
windows.main.setBounds(bounds, true)
windows.main.win.setBounds(bounds, true)
} else {
log('setBounds: not setting bounds because of window maximization')
}
@@ -215,9 +213,8 @@ function setBounds (bounds, maximize) {
function setAspectRatio (aspectRatio) {
log('setAspectRatio %o', aspectRatio)
if (windows.main) {
windows.main.setAspectRatio(aspectRatio)
}
if (!windows.main.win) return
windows.main.win.setAspectRatio(aspectRatio)
}
// 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.
function setProgress (progress) {
log('setProgress %s', progress)
if (windows.main) {
windows.main.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)
}
if (!windows.main.win) return
windows.main.win.setProgressBar(progress)
}

View File

@@ -10,11 +10,16 @@ module.exports.error = error
var electron = require('electron')
var config = require('../config')
var windows = require('./windows')
var app = electron.app
function log (...args) {
if (!config.IS_PRODUCTION) {
// In development, also log to the console
console.log(...args)
}
if (app.ipcReady) {
windows.main.send('log', ...args)
} else {

View File

@@ -4,13 +4,7 @@ module.exports = {
onPlayerOpen,
onToggleFullScreen,
onWindowHide,
onWindowShow,
// TODO: move these out of menu.js -- they don't belong here
showOpenSeedFiles,
showOpenTorrentAddress,
showOpenTorrentFile,
toggleFullScreen
onWindowShow
}
var electron = require('electron')
@@ -18,6 +12,7 @@ var electron = require('electron')
var app = electron.app
var config = require('../config')
var dialog = require('./dialog')
var log = require('./log')
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
function toggleFloatOnTop (flag) {
if (!windows.main.win) return
log('toggleFloatOnTop %s', flag)
if (windows.main) {
flag = flag != null ? flag : !windows.main.isAlwaysOnTop()
windows.main.setAlwaysOnTop(flag)
getMenuItem('Float on Top').checked = flag
}
flag = flag != null ? flag : !windows.main.isAlwaysOnTop()
windows.main.setAlwaysOnTop(flag)
getMenuItem('Float on Top').checked = flag
}
function toggleDevTools () {
if (!windows.main.win) return
log('toggleDevTools')
if (windows.main) {
windows.main.toggleDevTools()
}
windows.main.toggleDevTools()
}
function showWebTorrentWindow () {
log('showWebTorrentWindow')
windows.webtorrent.show()
windows.webtorrent.webContents.openDevTools({ detach: true })
windows.webtorrent.win.webContents.openDevTools({ detach: true })
}
function playPause () {
if (windows.main) {
windows.main.send('dispatch', 'playPause')
}
if (!windows.main.win) return
windows.main.send('dispatch', 'playPause')
}
function increaseVolume () {
if (windows.main) {
windows.main.send('dispatch', 'changeVolume', 0.1)
}
if (!windows.main.win) return
windows.main.send('dispatch', 'changeVolume', 0.1)
}
function decreaseVolume () {
if (windows.main) {
windows.main.send('dispatch', 'changeVolume', -0.1)
}
if (!windows.main.win) return
windows.main.send('dispatch', 'changeVolume', -0.1)
}
function openSubtitles () {
if (windows.main) {
windows.main.send('dispatch', 'openSubtitles')
}
if (!windows.main.win) return
windows.main.send('dispatch', 'openSubtitles')
}
function skipForward () {
if (windows.main) {
windows.main.send('dispatch', 'skip', 1)
}
if (!windows.main.win) return
windows.main.send('dispatch', 'skip', 1)
}
function skipBack () {
if (windows.main) {
windows.main.send('dispatch', 'skip', -1)
}
if (!windows.main.win) return
windows.main.send('dispatch', 'skip', -1)
}
function increasePlaybackRate () {
if (windows.main) {
windows.main.send('dispatch', 'changePlaybackRate', 1)
}
if (!windows.main.win) return
windows.main.send('dispatch', 'changePlaybackRate', 1)
}
function decreasePlaybackRate () {
if (windows.main) {
windows.main.send('dispatch', 'changePlaybackRate', -1)
}
if (!windows.main.win) return
windows.main.send('dispatch', 'changePlaybackRate', -1)
}
// Open the preferences window
function showPreferences () {
if (windows.main) {
windows.main.send('dispatch', 'preferences')
}
if (!windows.main.win) return
windows.main.send('dispatch', 'preferences')
}
function escapeBack () {
if (windows.main) {
windows.main.send('dispatch', 'escapeBack')
}
if (!windows.main.win) return
windows.main.send('dispatch', 'escapeBack')
}
function onWindowShow () {
@@ -166,8 +137,10 @@ function onPlayerClose () {
}
function onToggleFullScreen (isFullScreen) {
isFullScreen = isFullScreen != null ? isFullScreen : windows.main.isFullScreen()
windows.main.setMenuBarVisibility(!isFullScreen)
if (isFullScreen == null) {
isFullScreen = windows.main.win.isFullScreen()
}
windows.main.win.setMenuBarVisibility(!isFullScreen)
getMenuItem('Full Screen').checked = 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 () {
var template = [
{
@@ -234,17 +164,17 @@ function getAppMenuTemplate () {
? 'Create New Torrent...'
: 'Create New Torrent from Folder...',
accelerator: 'CmdOrCtrl+N',
click: showOpenSeedFiles
click: () => dialog.openSeedDirectory()
},
{
label: 'Open Torrent File...',
accelerator: 'CmdOrCtrl+O',
click: showOpenTorrentFile
click: () => dialog.openTorrentFile()
},
{
label: 'Open Torrent Address...',
accelerator: 'CmdOrCtrl+U',
click: showOpenTorrentAddress
click: () => dialog.openTorrentAddress()
},
{
type: 'separator'
@@ -300,7 +230,7 @@ function getAppMenuTemplate () {
accelerator: process.platform === 'darwin'
? 'Ctrl+Command+F'
: 'F11',
click: () => toggleFullScreen()
click: () => windows.toggleFullScreen()
},
{
label: 'Float on Top',
@@ -505,7 +435,7 @@ function getAppMenuTemplate () {
// File menu (Windows, Linux)
template[0].submenu.unshift({
label: 'Create New Torrent from File...',
click: showOpenSeedFile
click: () => dialog.openSeedFile()
})
// Help menu (Windows, Linux)
@@ -515,7 +445,7 @@ function getAppMenuTemplate () {
},
{
label: 'About ' + config.APP_NAME,
click: windows.createAboutWindow
click: () => windows.about.create()
}
)
}
@@ -537,17 +467,17 @@ function getDockMenuTemplate () {
{
label: 'Create New Torrent...',
accelerator: 'CmdOrCtrl+N',
click: showOpenSeedFiles
click: () => dialog.openSeedDirectory()
},
{
label: 'Open Torrent File...',
accelerator: 'CmdOrCtrl+O',
click: showOpenTorrentFile
click: () => dialog.openTorrentFile()
},
{
label: 'Open Torrent Address...',
accelerator: 'CmdOrCtrl+U',
click: showOpenTorrentAddress
click: () => dialog.openTorrentAddress()
}
]
}

View 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)
}

View File

@@ -1,9 +1,10 @@
module.exports = {
hasTray,
init,
hasTray
onWindowHide,
onWindowShow
}
var cp = require('child_process')
var electron = require('electron')
var app = electron.app
@@ -11,41 +12,32 @@ var app = electron.app
var config = require('../config')
var windows = require('./windows')
var trayIcon
var tray
function init () {
// OS X has no tray icon
if (process.platform === 'darwin') return
// On Linux, asynchronously check for libappindicator1
if (process.platform === 'linux') {
checkLinuxTraySupport(function (supportsTray) {
if (supportsTray) createTrayIcon()
})
initLinux()
}
// Windows always supports minimize-to-tray
if (process.platform === 'win32') createTrayIcon()
if (process.platform === 'win32') {
initWin32()
}
// OS X apps generally do not have menu bar icons
}
function hasTray () {
return !!trayIcon
function initLinux () {
// Check for libappindicator1 support before creating tray icon
checkLinuxTraySupport(function (supportsTray) {
if (supportsTray) createTray()
})
}
function createTrayIcon () {
trayIcon = new electron.Tray(getIconPath())
// 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 initWin32 () {
createTray()
}
function checkLinuxTraySupport (cb) {
var cp = require('child_process')
// 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
// 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 () {
var showHideMenuItem
if (windows.main.isVisible()) {
showHideMenuItem = { label: 'Hide to tray', click: hideApp }
} else {
showHideMenuItem = { label: 'Show', click: showApp }
}
if (!tray) return
var contextMenu = electron.Menu.buildFromTemplate([
showHideMenuItem,
{ label: 'Quit', click: () => app.quit() }
getToggleItem(),
{
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 () {

View File

@@ -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
View 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
View File

@@ -0,0 +1,3 @@
exports.about = require('./about')
exports.main = require('./main')
exports.webtorrent = require('./webtorrent')

115
main/windows/main.js Normal file
View 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
View 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
}

View 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)
}

View File

@@ -606,7 +606,8 @@ function saveState () {
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) {
if (!Array.isArray(files)) files = [ files ]
@@ -674,12 +675,13 @@ function addTorrent (torrentId) {
}
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 (files.length === 0) return
// Read the files concurrently, then add all resulting subtitle tracks
var jobs = files.map((file) => (cb) => loadSubtitle(file, cb))
parallel(jobs, function (err, tracks) {
var tasks = files.map((file) => (cb) => loadSubtitle(file, cb))
parallel(tasks, function (err, tracks) {
if (err) return onError(err)
for (var i = 0; i < tracks.length; i++) {