diff --git a/config.js b/config.js index 55d501a3..ea891229 100644 --- a/config.js +++ b/config.js @@ -28,8 +28,11 @@ module.exports = { CONFIG_TORRENT_PATH: path.join(getConfigPath(), 'Torrents'), GITHUB_URL: 'https://github.com/feross/webtorrent-desktop', + GITHUB_URL_ISSUES: 'https://github.com/feross/webtorrent-desktop/issues', GITHUB_URL_RAW: 'https://raw.githubusercontent.com/feross/webtorrent-desktop/master', + HOME_PAGE_URL: 'https://webtorrent.io', + IS_PORTABLE: isPortable(), IS_PRODUCTION: isProduction(), diff --git a/main/ipc.js b/main/ipc.js index 56ea5884..ed3c59c6 100644 --- a/main/ipc.js +++ b/main/ipc.js @@ -82,12 +82,12 @@ function init () { ipcMain.on('onPlayerOpen', function () { menu.onPlayerOpen() - shortcuts.registerPlayerShortcuts() + shortcuts.onPlayerOpen() }) ipcMain.on('onPlayerClose', function () { menu.onPlayerClose() - shortcuts.unregisterPlayerShortcuts() + shortcuts.onPlayerOpen() }) ipcMain.on('focusWindow', function (e, windowName) { diff --git a/main/menu.js b/main/menu.js index 644ae4e5..be02e166 100644 --- a/main/menu.js +++ b/main/menu.js @@ -5,6 +5,8 @@ module.exports = { onToggleFullScreen, onWindowHide, onWindowShow, + + // TODO: move these out of menu.js -- they don't belong here showOpenSeedFiles, showOpenTorrentAddress, showOpenTorrentFile, @@ -47,6 +49,25 @@ function toggleFloatOnTop (flag) { } } +function toggleDevTools () { + log('toggleDevTools') + if (windows.main) { + windows.main.toggleDevTools() + } +} + +function showWebTorrentWindow () { + log('showWebTorrentWindow') + windows.webtorrent.show() + windows.webtorrent.webContents.openDevTools({ detach: true }) +} + +function playPause () { + if (windows.main) { + windows.main.send('dispatch', 'playPause') + } +} + function increaseVolume () { if (windows.main) { windows.main.send('dispatch', 'changeVolume', 0.1) @@ -59,18 +80,6 @@ function decreaseVolume () { } } -function toggleDevTools () { - log('toggleDevTools') - if (windows.main) { - windows.main.toggleDevTools() - } -} - -function showWebTorrentWindow () { - windows.webtorrent.show() - windows.webtorrent.webContents.openDevTools({ detach: true }) -} - function onWindowShow () { log('onWindowShow') getMenuItem('Full Screen').enabled = true @@ -84,11 +93,15 @@ function onWindowHide () { } function onPlayerOpen () { + log('onPlayerOpen') + getMenuItem('Play/Pause').enabled = true getMenuItem('Increase Volume').enabled = true getMenuItem('Decrease Volume').enabled = true } function onPlayerClose () { + log('onPlayerClose') + getMenuItem('Play/Pause').enabled = false getMenuItem('Increase Volume').enabled = false getMenuItem('Decrease Volume').enabled = false } @@ -109,29 +122,29 @@ function getMenuItem (label) { } } -// Prompts the user for a file, then makes a torrent out of the data +// 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 (filenames) { - if (!Array.isArray(filenames)) return - var file = filenames[0] - windows.main.send('dispatch', 'showCreateTorrent', file) + }, function (selectedPaths) { + if (!Array.isArray(selectedPaths)) return + var selectedPath = selectedPaths[0] + windows.main.send('dispatch', 'showCreateTorrent', selectedPath) }) } -// Prompts the user for a file or folder, then makes a torrent out of the data +// 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 () { - // Allow only a single selection - // To create a multi-file torrent, the user must select a folder electron.dialog.showOpenDialog({ title: 'Select a file or folder for the torrent file.', properties: [ 'openFile', 'openDirectory' ] - }, function (filenames) { - if (!Array.isArray(filenames)) return - var fileOrFolder = filenames[0] - windows.main.send('dispatch', 'showCreateTorrent', fileOrFolder) + }, function (selectedPaths) { + if (!Array.isArray(selectedPaths)) return + var selectedPath = selectedPaths[0] + windows.main.send('dispatch', 'showCreateTorrent', selectedPath) }) } @@ -141,10 +154,10 @@ function showOpenTorrentFile () { title: 'Select a .torrent file to open.', filters: [{ name: 'Torrent Files', extensions: ['torrent'] }], properties: [ 'openFile', 'multiSelections' ] - }, function (filenames) { - if (!Array.isArray(filenames)) return - filenames.forEach(function (filename) { - windows.main.send('dispatch', 'addTorrent', filename) + }, function (selectedPaths) { + if (!Array.isArray(selectedPaths)) return + selectedPaths.forEach(function (selectedPath) { + windows.main.send('dispatch', 'addTorrent', selectedPath) }) }) } @@ -155,51 +168,38 @@ function showOpenTorrentAddress () { } function getAppMenuTemplate () { - var fileMenu = [ - { - label: process.platform === 'darwin' ? 'Create New Torrent...' : 'Create New Torrent from Folder...', - accelerator: 'CmdOrCtrl+N', - click: showOpenSeedFiles - }, - { - label: 'Open Torrent File...', - accelerator: 'CmdOrCtrl+O', - click: showOpenTorrentFile - }, - { - label: 'Open Torrent Address...', - accelerator: 'CmdOrCtrl+U', - click: showOpenTorrentAddress - }, - { - type: 'separator' - }, - { - label: process.platform === 'windows' ? 'Close' : 'Close Window', - accelerator: 'CmdOrCtrl+W', - role: 'close' - } - ] - - // In Linux and Windows it is not possible to open both folders and files - if (process.platform !== 'darwin') { - fileMenu.unshift({ - label: 'Create New Torrent from File...', - click: showOpenSeedFile - }) - } - // File > Quit for Linux users with distros where the system tray is broken - if (process.platform === 'linux') { - fileMenu.push({ - label: 'Quit', - click: () => app.quit() - }) - } - var template = [ { label: 'File', - submenu: fileMenu + submenu: [ + { + label: process.platform === 'darwin' + ? 'Create New Torrent...' + : 'Create New Torrent from Folder...', + accelerator: 'CmdOrCtrl+N', + click: showOpenSeedFiles + }, + { + label: 'Open Torrent File...', + accelerator: 'CmdOrCtrl+O', + click: showOpenTorrentFile + }, + { + label: 'Open Torrent Address...', + accelerator: 'CmdOrCtrl+U', + click: showOpenTorrentAddress + }, + { + type: 'separator' + }, + { + label: process.platform === 'windows' + ? 'Close' + : 'Close Window', + accelerator: 'CmdOrCtrl+W', + role: 'close' + } + ] }, { label: 'Edit', @@ -245,21 +245,6 @@ function getAppMenuTemplate () { { type: 'separator' }, - { - label: 'Increase Volume', - accelerator: 'CmdOrCtrl+Up', - click: increaseVolume, - enabled: false - }, - { - label: 'Decrease Volume', - accelerator: 'CmdOrCtrl+Down', - click: decreaseVolume, - enabled: false - }, - { - type: 'separator' - }, { label: 'Developer', submenu: [ @@ -282,13 +267,28 @@ function getAppMenuTemplate () { ] }, { - label: 'Window', - role: 'window', + label: 'Playback', submenu: [ { - label: 'Minimize', - accelerator: 'CmdOrCtrl+M', - role: 'minimize' + label: 'Play/Pause', + accelerator: 'CmdOrCtrl+P', + click: playPause, + enabled: false + }, + { + type: 'separator' + }, + { + label: 'Increase Volume', + accelerator: 'CmdOrCtrl+Up', + click: increaseVolume, + enabled: false + }, + { + label: 'Decrease Volume', + accelerator: 'CmdOrCtrl+Down', + click: decreaseVolume, + enabled: false } ] }, @@ -298,7 +298,7 @@ function getAppMenuTemplate () { submenu: [ { label: 'Learn more about ' + config.APP_NAME, - click: () => electron.shell.openExternal('https://webtorrent.io') + click: () => electron.shell.openExternal(config.HOME_PAGE_URL) }, { label: 'Contribute on GitHub', @@ -309,14 +309,14 @@ function getAppMenuTemplate () { }, { label: 'Report an Issue...', - click: () => electron.shell.openExternal(config.GITHUB_URL + '/issues') + click: () => electron.shell.openExternal(config.GITHUB_URL_ISSUES) } ] } ] if (process.platform === 'darwin') { - // WebTorrent menu (OS X) + // Add WebTorrent app menu (OS X) template.unshift({ label: config.APP_NAME, submenu: [ @@ -360,17 +360,35 @@ function getAppMenuTemplate () { ] }) - // Window menu (OS X) - template[4].submenu.push( - { - type: 'separator' - }, - { - label: 'Bring All to Front', - role: 'front' - } - ) - } else { + // Add Window menu (OS X) + template.splice(5, 0, { + label: 'Window', + role: 'window', + submenu: [ + { + label: 'Minimize', + accelerator: 'CmdOrCtrl+M', + role: 'minimize' + }, + { + type: 'separator' + }, + { + label: 'Bring All to Front', + role: 'front' + } + ] + }) + } + + // In Linux and Windows it is not possible to open both folders and files + if (process.platform === 'linux' || process.platform === 'windows') { + // File menu (Windows, Linux) + template[0].unshift({ + label: 'Create New Torrent from File...', + click: showOpenSeedFile + }) + // Help menu (Windows, Linux) template[4].submenu.push( { @@ -382,6 +400,15 @@ function getAppMenuTemplate () { } ) } + // Add "File > Quit" menu item so Linux distros where the system tray icon is missing + // will have a way to quit the app. + if (process.platform === 'linux') { + // File menu (Linux) + template[0].push({ + label: 'Quit', + click: () => app.quit() + }) + } return template } diff --git a/main/shortcuts.js b/main/shortcuts.js index 664d5fc3..739f72eb 100644 --- a/main/shortcuts.js +++ b/main/shortcuts.js @@ -1,7 +1,7 @@ module.exports = { init, - registerPlayerShortcuts, - unregisterPlayerShortcuts + onPlayerClose, + onPlayerOpen } var electron = require('electron') @@ -13,17 +13,23 @@ var menu = require('./menu') var windows = require('./windows') function init () { - // ⌘+Shift+F is an alternative fullscreen shortcut to the ones defined in menu.js. - // Electron does not support multiple accelerators for a single menu item, so this - // is registered separately here. + // Alternate shortcuts. Most shortcuts are registered in menu,js, but Electron does not + // support multiple shortcuts for a single menu item. localShortcut.register('CmdOrCtrl+Shift+F', menu.toggleFullScreen) + localShortcut.register('Space', () => windows.main.send('dispatch', 'playPause')) + + // Hidden shortcuts, i.e. not shown in the menu + localShortcut.register('Esc', () => windows.main.send('dispatch', 'escapeBack')) } -function registerPlayerShortcuts () { - // Special "media key" for play/pause, available on some keyboards - globalShortcut.register('MediaPlayPause', () => windows.main.send('dispatch', 'playPause')) +function onPlayerOpen () { + // Register special "media key" for play/pause, available on some keyboards + globalShortcut.register( + 'MediaPlayPause', + () => windows.main.send('dispatch', 'playPause') + ) } -function unregisterPlayerShortcuts () { +function onPlayerClose () { globalShortcut.unregister('MediaPlayPause') } diff --git a/renderer/index.js b/renderer/index.js index f7e076a9..1e35e07f 100644 --- a/renderer/index.js +++ b/renderer/index.js @@ -96,9 +96,6 @@ function init () { // ...same thing if you paste a torrent document.addEventListener('paste', onPaste) - // ...keyboard shortcuts - document.addEventListener('keydown', onKeyDown) - // ...focus and blur. Needed to show correct dock icon text ("badge") in OSX window.addEventListener('focus', onFocus) window.addEventListener('blur', onBlur) @@ -256,6 +253,15 @@ function dispatch (action, ...args) { var mediaTag = document.querySelector('video,audio') if (mediaTag) mediaTag.pause() } + if (action === 'escapeBack') { + if (state.modal) { + dispatch('exitModal') + } else if (state.window.isFullScreen) { + dispatch('toggleFullScreen') + } else { + dispatch('back') + } + } if (action === 'back') { state.location.back() } @@ -378,6 +384,7 @@ function pause () { } function playPause () { + if (state.location.current().url !== 'player') return if (state.playing.isPaused) { play() } else { @@ -1145,20 +1152,6 @@ function onPaste (e) { }) } -function onKeyDown (e) { - if (e.which === 27) { /* ESC means either exit fullscreen or go back */ - if (state.modal) { - dispatch('exitModal') - } else if (state.window.isFullScreen) { - dispatch('toggleFullScreen') - } else { - dispatch('back') - } - } else if (e.which === 32) { /* spacebar pauses or plays the video */ - dispatch('playPause') - } -} - function onFocus (e) { state.window.isFocused = true state.dock.badge = 0