Merge branch 'master' into update-electron
# Conflicts: # package-lock.json # package.json
This commit is contained in:
12
README.md
12
README.md
@@ -158,6 +158,18 @@ The Mac app can only be packaged from **macOS**.
|
|||||||
|
|
||||||
The Linux app can be packaged from **any** platform.
|
The Linux app can be packaged from **any** platform.
|
||||||
|
|
||||||
|
|
||||||
|
#### Recommended readings to start working in the app
|
||||||
|
|
||||||
|
Electron (Framework to make native apps for Windows, OSX and Linux in Javascript):
|
||||||
|
https://electronjs.org/docs/tutorial/quick-start
|
||||||
|
|
||||||
|
React.js (Framework to work with Frontend UI):
|
||||||
|
https://reactjs.org/docs/getting-started.html
|
||||||
|
|
||||||
|
Material UI (React components that implement Google's Material Design.):
|
||||||
|
https://material-ui.com/getting-started
|
||||||
|
|
||||||
### Privacy
|
### Privacy
|
||||||
|
|
||||||
WebTorrent Desktop collects some basic usage stats to help us make the app better.
|
WebTorrent Desktop collects some basic usage stats to help us make the app better.
|
||||||
|
|||||||
@@ -198,16 +198,16 @@ function buildDarwin (cb) {
|
|||||||
|
|
||||||
infoPlist.CFBundleDocumentTypes = [
|
infoPlist.CFBundleDocumentTypes = [
|
||||||
{
|
{
|
||||||
CFBundleTypeExtensions: [ 'torrent' ],
|
CFBundleTypeExtensions: ['torrent'],
|
||||||
CFBundleTypeIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
|
CFBundleTypeIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
|
||||||
CFBundleTypeName: 'BitTorrent Document',
|
CFBundleTypeName: 'BitTorrent Document',
|
||||||
CFBundleTypeRole: 'Editor',
|
CFBundleTypeRole: 'Editor',
|
||||||
LSHandlerRank: 'Owner',
|
LSHandlerRank: 'Owner',
|
||||||
LSItemContentTypes: [ 'org.bittorrent.torrent' ]
|
LSItemContentTypes: ['org.bittorrent.torrent']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
CFBundleTypeName: 'Any',
|
CFBundleTypeName: 'Any',
|
||||||
CFBundleTypeOSTypes: [ '****' ],
|
CFBundleTypeOSTypes: ['****'],
|
||||||
CFBundleTypeRole: 'Editor',
|
CFBundleTypeRole: 'Editor',
|
||||||
LSHandlerRank: 'Owner',
|
LSHandlerRank: 'Owner',
|
||||||
LSTypeIsPackage: false
|
LSTypeIsPackage: false
|
||||||
@@ -219,13 +219,13 @@ function buildDarwin (cb) {
|
|||||||
CFBundleTypeRole: 'Editor',
|
CFBundleTypeRole: 'Editor',
|
||||||
CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
|
CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
|
||||||
CFBundleURLName: 'BitTorrent Magnet URL',
|
CFBundleURLName: 'BitTorrent Magnet URL',
|
||||||
CFBundleURLSchemes: [ 'magnet' ]
|
CFBundleURLSchemes: ['magnet']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
CFBundleTypeRole: 'Editor',
|
CFBundleTypeRole: 'Editor',
|
||||||
CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
|
CFBundleURLIconFile: path.basename(config.APP_FILE_ICON) + '.icns',
|
||||||
CFBundleURLName: 'BitTorrent Stream-Magnet URL',
|
CFBundleURLName: 'BitTorrent Stream-Magnet URL',
|
||||||
CFBundleURLSchemes: [ 'stream-magnet' ]
|
CFBundleURLSchemes: ['stream-magnet']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -242,7 +242,7 @@ function buildDarwin (cb) {
|
|||||||
UTTypeReferenceURL: 'http://www.bittorrent.org/beps/bep_0000.html',
|
UTTypeReferenceURL: 'http://www.bittorrent.org/beps/bep_0000.html',
|
||||||
UTTypeTagSpecification: {
|
UTTypeTagSpecification: {
|
||||||
'com.apple.ostype': 'TORR',
|
'com.apple.ostype': 'TORR',
|
||||||
'public.filename-extension': [ 'torrent' ],
|
'public.filename-extension': ['torrent'],
|
||||||
'public.mime-type': 'application/x-bittorrent'
|
'public.mime-type': 'application/x-bittorrent'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
687
package-lock.json
generated
687
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -16,11 +16,11 @@
|
|||||||
"arch": "^2.0.0",
|
"arch": "^2.0.0",
|
||||||
"auto-launch": "^5.0.5",
|
"auto-launch": "^5.0.5",
|
||||||
"bitfield": "^1.0.2",
|
"bitfield": "^1.0.2",
|
||||||
"capture-frame": "^2.0.0",
|
"capture-frame": "^3.0.0",
|
||||||
"chokidar": "^2.0.4",
|
"chokidar": "^2.0.4",
|
||||||
"chromecasts": "^1.9.1",
|
"chromecasts": "^1.9.1",
|
||||||
"cp-file": "^7.0.0",
|
"cp-file": "^7.0.0",
|
||||||
"create-torrent": "^3.33.0",
|
"create-torrent": "^4.0.0",
|
||||||
"debounce": "^1.0.0",
|
"debounce": "^1.0.0",
|
||||||
"deep-equal": "^1.0.1",
|
"deep-equal": "^1.0.1",
|
||||||
"dlnacasts": "^0.1.0",
|
"dlnacasts": "^0.1.0",
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
"music-metadata": "^3.6.1",
|
"music-metadata": "^3.6.1",
|
||||||
"network-address": "^1.1.0",
|
"network-address": "^1.1.0",
|
||||||
"parse-torrent": "^6.0.1",
|
"parse-torrent": "^7.0.0",
|
||||||
"prettier-bytes": "^1.0.1",
|
"prettier-bytes": "^1.0.1",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.5.2",
|
"react": "^16.5.2",
|
||||||
@@ -51,10 +51,10 @@
|
|||||||
"zero-fill": "^2.2.3"
|
"zero-fill": "^2.2.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-eslint": "^9.0.0",
|
"babel-eslint": "^10.0.2",
|
||||||
"buble": "^0.19.6",
|
"buble": "^0.19.6",
|
||||||
"cross-zip": "^2.0.1",
|
"cross-zip": "^2.0.1",
|
||||||
"depcheck": "^0.7.2",
|
"depcheck": "^0.8.0",
|
||||||
"electron": "^4.0.0",
|
"electron": "^4.0.0",
|
||||||
"electron-osx-sign": "^0.4.11",
|
"electron-osx-sign": "^0.4.11",
|
||||||
"electron-packager": "~8.5.1",
|
"electron-packager": "~8.5.1",
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
"spectron": "^3.3.0",
|
"spectron": "^3.3.0",
|
||||||
"standard": "*",
|
"standard": "*",
|
||||||
"tape": "^4.9.1",
|
"tape": "^4.9.1",
|
||||||
"walk-sync": "^1.1.3"
|
"walk-sync": "^2.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4.0.0"
|
"node": ">=4.0.0"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ function openSeedFile () {
|
|||||||
log('openSeedFile')
|
log('openSeedFile')
|
||||||
const opts = {
|
const opts = {
|
||||||
title: 'Select a file for the torrent.',
|
title: 'Select a file for the torrent.',
|
||||||
properties: [ 'openFile' ]
|
properties: ['openFile']
|
||||||
}
|
}
|
||||||
showOpenSeed(opts)
|
showOpenSeed(opts)
|
||||||
}
|
}
|
||||||
@@ -35,11 +35,11 @@ function openSeedDirectory () {
|
|||||||
const opts = process.platform === 'darwin'
|
const opts = process.platform === 'darwin'
|
||||||
? {
|
? {
|
||||||
title: 'Select a file or folder for the torrent.',
|
title: 'Select a file or folder for the torrent.',
|
||||||
properties: [ 'openFile', 'openDirectory' ]
|
properties: ['openFile', 'openDirectory']
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
title: 'Select a folder for the torrent.',
|
title: 'Select a folder for the torrent.',
|
||||||
properties: [ 'openDirectory' ]
|
properties: ['openDirectory']
|
||||||
}
|
}
|
||||||
showOpenSeed(opts)
|
showOpenSeed(opts)
|
||||||
}
|
}
|
||||||
@@ -54,11 +54,11 @@ function openFiles () {
|
|||||||
const opts = process.platform === 'darwin'
|
const opts = process.platform === 'darwin'
|
||||||
? {
|
? {
|
||||||
title: 'Select a file or folder to add.',
|
title: 'Select a file or folder to add.',
|
||||||
properties: [ 'openFile', 'openDirectory' ]
|
properties: ['openFile', 'openDirectory']
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
title: 'Select a file to add.',
|
title: 'Select a file to add.',
|
||||||
properties: [ 'openFile' ]
|
properties: ['openFile']
|
||||||
}
|
}
|
||||||
setTitle(opts.title)
|
setTitle(opts.title)
|
||||||
electron.dialog.showOpenDialog(windows.main.win, opts, function (selectedPaths) {
|
electron.dialog.showOpenDialog(windows.main.win, opts, function (selectedPaths) {
|
||||||
@@ -77,7 +77,7 @@ function openTorrentFile () {
|
|||||||
const opts = {
|
const opts = {
|
||||||
title: 'Select a .torrent file.',
|
title: 'Select a .torrent file.',
|
||||||
filters: [{ name: 'Torrent Files', extensions: ['torrent'] }],
|
filters: [{ name: 'Torrent Files', extensions: ['torrent'] }],
|
||||||
properties: [ 'openFile', 'multiSelections' ]
|
properties: ['openFile', 'multiSelections']
|
||||||
}
|
}
|
||||||
setTitle(opts.title)
|
setTitle(opts.title)
|
||||||
electron.dialog.showOpenDialog(windows.main.win, opts, function (selectedPaths) {
|
electron.dialog.showOpenDialog(windows.main.win, opts, function (selectedPaths) {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ function installDarwin () {
|
|||||||
|
|
||||||
function uninstallDarwin () {}
|
function uninstallDarwin () {}
|
||||||
|
|
||||||
const EXEC_COMMAND = [ process.execPath, '--' ]
|
const EXEC_COMMAND = [process.execPath, '--']
|
||||||
|
|
||||||
if (!config.IS_PRODUCTION) {
|
if (!config.IS_PRODUCTION) {
|
||||||
EXEC_COMMAND.push(config.ROOT_PATH)
|
EXEC_COMMAND.push(config.ROOT_PATH)
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ function onOpen (e, torrentId) {
|
|||||||
// Electron issue: https://github.com/atom/electron/issues/4338
|
// Electron issue: https://github.com/atom/electron/issues/4338
|
||||||
setTimeout(() => windows.main.show(), 100)
|
setTimeout(() => windows.main.show(), 100)
|
||||||
|
|
||||||
processArgv([ torrentId ])
|
processArgv([torrentId])
|
||||||
} else {
|
} else {
|
||||||
argv.push(torrentId)
|
argv.push(torrentId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ function onPlayerPlay () {
|
|||||||
|
|
||||||
function onPlayerUpdate (state) {
|
function onPlayerUpdate (state) {
|
||||||
if (!isEnabled()) return
|
if (!isEnabled()) return
|
||||||
buttons[PREV].flags = [ state.hasPrevious ? 'enabled' : 'disabled' ]
|
buttons[PREV].flags = [state.hasPrevious ? 'enabled' : 'disabled']
|
||||||
buttons[NEXT].flags = [ state.hasNext ? 'enabled' : 'disabled' ]
|
buttons[NEXT].flags = [state.hasNext ? 'enabled' : 'disabled']
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class PathSelector extends React.Component {
|
|||||||
handleClick () {
|
handleClick () {
|
||||||
const opts = Object.assign({
|
const opts = Object.assign({
|
||||||
defaultPath: this.props.value,
|
defaultPath: this.props.value,
|
||||||
properties: [ 'openFile', 'openDirectory' ]
|
properties: ['openFile', 'openDirectory']
|
||||||
}, this.props.dialog)
|
}, this.props.dialog)
|
||||||
|
|
||||||
remote.dialog.showOpenDialog(
|
remote.dialog.showOpenDialog(
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ module.exports = class SubtitlesController {
|
|||||||
openSubtitles () {
|
openSubtitles () {
|
||||||
remote.dialog.showOpenDialog({
|
remote.dialog.showOpenDialog({
|
||||||
title: 'Select a subtitles file.',
|
title: 'Select a subtitles file.',
|
||||||
filters: [ { name: 'Subtitles', extensions: ['vtt', 'srt'] } ],
|
filters: [{ name: 'Subtitles', extensions: ['vtt', 'srt'] }],
|
||||||
properties: [ 'openFile' ]
|
properties: ['openFile']
|
||||||
}, (filenames) => {
|
}, (filenames) => {
|
||||||
if (!Array.isArray(filenames)) return
|
if (!Array.isArray(filenames)) return
|
||||||
this.addSubtitles(filenames, true)
|
this.addSubtitles(filenames, true)
|
||||||
|
|||||||
@@ -235,100 +235,100 @@ function updateElectron () {
|
|||||||
|
|
||||||
const dispatchHandlers = {
|
const dispatchHandlers = {
|
||||||
// Torrent list: creating, deleting, selecting torrents
|
// Torrent list: creating, deleting, selecting torrents
|
||||||
'openTorrentFile': () => ipcRenderer.send('openTorrentFile'),
|
openTorrentFile: () => ipcRenderer.send('openTorrentFile'),
|
||||||
'openFiles': () => ipcRenderer.send('openFiles'), /* shows the open file dialog */
|
openFiles: () => ipcRenderer.send('openFiles'), /* shows the open file dialog */
|
||||||
'openTorrentAddress': () => { state.modal = { id: 'open-torrent-address-modal' } },
|
openTorrentAddress: () => { state.modal = { id: 'open-torrent-address-modal' } },
|
||||||
|
|
||||||
'addTorrent': (torrentId) => controllers.torrentList().addTorrent(torrentId),
|
addTorrent: (torrentId) => controllers.torrentList().addTorrent(torrentId),
|
||||||
'showCreateTorrent': (paths) => controllers.torrentList().showCreateTorrent(paths),
|
showCreateTorrent: (paths) => controllers.torrentList().showCreateTorrent(paths),
|
||||||
'createTorrent': (options) => controllers.torrentList().createTorrent(options),
|
createTorrent: (options) => controllers.torrentList().createTorrent(options),
|
||||||
'toggleTorrent': (infoHash) => controllers.torrentList().toggleTorrent(infoHash),
|
toggleTorrent: (infoHash) => controllers.torrentList().toggleTorrent(infoHash),
|
||||||
'pauseAllTorrents': () => controllers.torrentList().pauseAllTorrents(),
|
pauseAllTorrents: () => controllers.torrentList().pauseAllTorrents(),
|
||||||
'resumeAllTorrents': () => controllers.torrentList().resumeAllTorrents(),
|
resumeAllTorrents: () => controllers.torrentList().resumeAllTorrents(),
|
||||||
'toggleTorrentFile': (infoHash, index) =>
|
toggleTorrentFile: (infoHash, index) =>
|
||||||
controllers.torrentList().toggleTorrentFile(infoHash, index),
|
controllers.torrentList().toggleTorrentFile(infoHash, index),
|
||||||
'confirmDeleteTorrent': (infoHash, deleteData) =>
|
confirmDeleteTorrent: (infoHash, deleteData) =>
|
||||||
controllers.torrentList().confirmDeleteTorrent(infoHash, deleteData),
|
controllers.torrentList().confirmDeleteTorrent(infoHash, deleteData),
|
||||||
'deleteTorrent': (infoHash, deleteData) =>
|
deleteTorrent: (infoHash, deleteData) =>
|
||||||
controllers.torrentList().deleteTorrent(infoHash, deleteData),
|
controllers.torrentList().deleteTorrent(infoHash, deleteData),
|
||||||
'toggleSelectTorrent': (infoHash) =>
|
toggleSelectTorrent: (infoHash) =>
|
||||||
controllers.torrentList().toggleSelectTorrent(infoHash),
|
controllers.torrentList().toggleSelectTorrent(infoHash),
|
||||||
'openTorrentContextMenu': (infoHash) =>
|
openTorrentContextMenu: (infoHash) =>
|
||||||
controllers.torrentList().openTorrentContextMenu(infoHash),
|
controllers.torrentList().openTorrentContextMenu(infoHash),
|
||||||
'startTorrentingSummary': (torrentKey) =>
|
startTorrentingSummary: (torrentKey) =>
|
||||||
controllers.torrentList().startTorrentingSummary(torrentKey),
|
controllers.torrentList().startTorrentingSummary(torrentKey),
|
||||||
'saveTorrentFileAs': (torrentKey) =>
|
saveTorrentFileAs: (torrentKey) =>
|
||||||
controllers.torrentList().saveTorrentFileAs(torrentKey),
|
controllers.torrentList().saveTorrentFileAs(torrentKey),
|
||||||
'prioritizeTorrent': (infoHash) => controllers.torrentList().prioritizeTorrent(infoHash),
|
prioritizeTorrent: (infoHash) => controllers.torrentList().prioritizeTorrent(infoHash),
|
||||||
'resumePausedTorrents': () => controllers.torrentList().resumePausedTorrents(),
|
resumePausedTorrents: () => controllers.torrentList().resumePausedTorrents(),
|
||||||
|
|
||||||
// Playback
|
// Playback
|
||||||
'playFile': (infoHash, index) => controllers.playback().playFile(infoHash, index),
|
playFile: (infoHash, index) => controllers.playback().playFile(infoHash, index),
|
||||||
'playPause': () => controllers.playback().playPause(),
|
playPause: () => controllers.playback().playPause(),
|
||||||
'nextTrack': () => controllers.playback().nextTrack(),
|
nextTrack: () => controllers.playback().nextTrack(),
|
||||||
'previousTrack': () => controllers.playback().previousTrack(),
|
previousTrack: () => controllers.playback().previousTrack(),
|
||||||
'skip': (time) => controllers.playback().skip(time),
|
skip: (time) => controllers.playback().skip(time),
|
||||||
'skipTo': (time) => controllers.playback().skipTo(time),
|
skipTo: (time) => controllers.playback().skipTo(time),
|
||||||
'changePlaybackRate': (dir) => controllers.playback().changePlaybackRate(dir),
|
changePlaybackRate: (dir) => controllers.playback().changePlaybackRate(dir),
|
||||||
'changeVolume': (delta) => controllers.playback().changeVolume(delta),
|
changeVolume: (delta) => controllers.playback().changeVolume(delta),
|
||||||
'setVolume': (vol) => controllers.playback().setVolume(vol),
|
setVolume: (vol) => controllers.playback().setVolume(vol),
|
||||||
'openItem': (infoHash, index) => controllers.playback().openItem(infoHash, index),
|
openItem: (infoHash, index) => controllers.playback().openItem(infoHash, index),
|
||||||
|
|
||||||
// Subtitles
|
// Subtitles
|
||||||
'openSubtitles': () => controllers.subtitles().openSubtitles(),
|
openSubtitles: () => controllers.subtitles().openSubtitles(),
|
||||||
'selectSubtitle': (index) => controllers.subtitles().selectSubtitle(index),
|
selectSubtitle: (index) => controllers.subtitles().selectSubtitle(index),
|
||||||
'toggleSubtitlesMenu': () => controllers.subtitles().toggleSubtitlesMenu(),
|
toggleSubtitlesMenu: () => controllers.subtitles().toggleSubtitlesMenu(),
|
||||||
'checkForSubtitles': () => controllers.subtitles().checkForSubtitles(),
|
checkForSubtitles: () => controllers.subtitles().checkForSubtitles(),
|
||||||
'addSubtitles': (files, autoSelect) => controllers.subtitles().addSubtitles(files, autoSelect),
|
addSubtitles: (files, autoSelect) => controllers.subtitles().addSubtitles(files, autoSelect),
|
||||||
|
|
||||||
// Local media: <video>, <audio>, external players
|
// Local media: <video>, <audio>, external players
|
||||||
'mediaStalled': () => controllers.media().mediaStalled(),
|
mediaStalled: () => controllers.media().mediaStalled(),
|
||||||
'mediaError': (err) => controllers.media().mediaError(err),
|
mediaError: (err) => controllers.media().mediaError(err),
|
||||||
'mediaSuccess': () => controllers.media().mediaSuccess(),
|
mediaSuccess: () => controllers.media().mediaSuccess(),
|
||||||
'mediaTimeUpdate': () => controllers.media().mediaTimeUpdate(),
|
mediaTimeUpdate: () => controllers.media().mediaTimeUpdate(),
|
||||||
'mediaMouseMoved': () => controllers.media().mediaMouseMoved(),
|
mediaMouseMoved: () => controllers.media().mediaMouseMoved(),
|
||||||
'mediaControlsMouseEnter': () => controllers.media().controlsMouseEnter(),
|
mediaControlsMouseEnter: () => controllers.media().controlsMouseEnter(),
|
||||||
'mediaControlsMouseLeave': () => controllers.media().controlsMouseLeave(),
|
mediaControlsMouseLeave: () => controllers.media().controlsMouseLeave(),
|
||||||
'openExternalPlayer': () => controllers.media().openExternalPlayer(),
|
openExternalPlayer: () => controllers.media().openExternalPlayer(),
|
||||||
'externalPlayerNotFound': () => controllers.media().externalPlayerNotFound(),
|
externalPlayerNotFound: () => controllers.media().externalPlayerNotFound(),
|
||||||
|
|
||||||
// Remote casting: Chromecast, Airplay, etc
|
// Remote casting: Chromecast, Airplay, etc
|
||||||
'toggleCastMenu': (deviceType) => lazyLoadCast().toggleMenu(deviceType),
|
toggleCastMenu: (deviceType) => lazyLoadCast().toggleMenu(deviceType),
|
||||||
'selectCastDevice': (index) => lazyLoadCast().selectDevice(index),
|
selectCastDevice: (index) => lazyLoadCast().selectDevice(index),
|
||||||
'stopCasting': () => lazyLoadCast().stop(),
|
stopCasting: () => lazyLoadCast().stop(),
|
||||||
|
|
||||||
// Preferences screen
|
// Preferences screen
|
||||||
'preferences': () => controllers.prefs().show(),
|
preferences: () => controllers.prefs().show(),
|
||||||
'updatePreferences': (key, value) => controllers.prefs().update(key, value),
|
updatePreferences: (key, value) => controllers.prefs().update(key, value),
|
||||||
'checkDownloadPath': checkDownloadPath,
|
checkDownloadPath: checkDownloadPath,
|
||||||
'startFolderWatcher': () => controllers.folderWatcher().start(),
|
startFolderWatcher: () => controllers.folderWatcher().start(),
|
||||||
'stopFolderWatcher': () => controllers.folderWatcher().stop(),
|
stopFolderWatcher: () => controllers.folderWatcher().stop(),
|
||||||
|
|
||||||
// Update (check for new versions on Linux, where there's no auto updater)
|
// Update (check for new versions on Linux, where there's no auto updater)
|
||||||
'updateAvailable': (version) => controllers.update().updateAvailable(version),
|
updateAvailable: (version) => controllers.update().updateAvailable(version),
|
||||||
'skipVersion': (version) => controllers.update().skipVersion(version),
|
skipVersion: (version) => controllers.update().skipVersion(version),
|
||||||
|
|
||||||
// Navigation between screens (back, forward, ESC, etc)
|
// Navigation between screens (back, forward, ESC, etc)
|
||||||
'exitModal': () => { state.modal = null },
|
exitModal: () => { state.modal = null },
|
||||||
'backToList': backToList,
|
backToList: backToList,
|
||||||
'escapeBack': escapeBack,
|
escapeBack: escapeBack,
|
||||||
'back': () => state.location.back(),
|
back: () => state.location.back(),
|
||||||
'forward': () => state.location.forward(),
|
forward: () => state.location.forward(),
|
||||||
'cancel': () => state.location.cancel(),
|
cancel: () => state.location.cancel(),
|
||||||
|
|
||||||
// Controlling the window
|
// Controlling the window
|
||||||
'setDimensions': setDimensions,
|
setDimensions: setDimensions,
|
||||||
'toggleFullScreen': (setTo) => ipcRenderer.send('toggleFullScreen', setTo),
|
toggleFullScreen: (setTo) => ipcRenderer.send('toggleFullScreen', setTo),
|
||||||
'setTitle': (title) => { state.window.title = title },
|
setTitle: (title) => { state.window.title = title },
|
||||||
'resetTitle': () => { state.window.title = config.APP_WINDOW_TITLE },
|
resetTitle: () => { state.window.title = config.APP_WINDOW_TITLE },
|
||||||
|
|
||||||
// Everything else
|
// Everything else
|
||||||
'onOpen': onOpen,
|
onOpen: onOpen,
|
||||||
'error': onError,
|
error: onError,
|
||||||
'uncaughtError': (proc, err) => telemetry.logUncaughtError(proc, err),
|
uncaughtError: (proc, err) => telemetry.logUncaughtError(proc, err),
|
||||||
'stateSave': () => State.save(state),
|
stateSave: () => State.save(state),
|
||||||
'stateSaveImmediate': () => State.saveImmediate(state),
|
stateSaveImmediate: () => State.saveImmediate(state),
|
||||||
'update': () => {} // No-op, just trigger an update
|
update: () => {} // No-op, just trigger an update
|
||||||
}
|
}
|
||||||
|
|
||||||
// Events from the UI never modify state directly. Instead they call dispatch()
|
// Events from the UI never modify state directly. Instead they call dispatch()
|
||||||
@@ -458,7 +458,7 @@ function setDimensions (dimensions) {
|
|||||||
// Called when the user adds files (.torrent, files to seed, subtitles) to 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)
|
// 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]
|
||||||
|
|
||||||
// File API seems to transform "magnet:?foo" in "magnet:///?foo"
|
// File API seems to transform "magnet:?foo" in "magnet:///?foo"
|
||||||
// this is a sanitization
|
// this is a sanitization
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ const Header = require('../components/header')
|
|||||||
const TorrentListPage = require('./torrent-list-page')
|
const TorrentListPage = require('./torrent-list-page')
|
||||||
|
|
||||||
const Views = {
|
const Views = {
|
||||||
'home': createGetter(() => TorrentListPage),
|
home: createGetter(() => TorrentListPage),
|
||||||
'player': createGetter(() => require('./player-page')),
|
player: createGetter(() => require('./player-page')),
|
||||||
'create-torrent': createGetter(() => require('./create-torrent-page')),
|
'create-torrent': createGetter(() => require('./create-torrent-page')),
|
||||||
'preferences': createGetter(() => require('./preferences-page'))
|
preferences: createGetter(() => require('./preferences-page'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const Modals = {
|
const Modals = {
|
||||||
|
|||||||
@@ -539,9 +539,9 @@ function renderPlayerControls (state) {
|
|||||||
|
|
||||||
// Add the cast buttons. Icons for each cast type, connected/disconnected:
|
// Add the cast buttons. Icons for each cast type, connected/disconnected:
|
||||||
const buttonIcons = {
|
const buttonIcons = {
|
||||||
'chromecast': { true: 'cast_connected', false: 'cast' },
|
chromecast: { true: 'cast_connected', false: 'cast' },
|
||||||
'airplay': { true: 'airplay', false: 'airplay' },
|
airplay: { true: 'airplay', false: 'airplay' },
|
||||||
'dlna': { true: 'tv', false: 'tv' }
|
dlna: { true: 'tv', false: 'tv' }
|
||||||
}
|
}
|
||||||
castTypes.forEach(function (castType) {
|
castTypes.forEach(function (castType) {
|
||||||
// Do we show this button (eg. the Chromecast button) at all?
|
// Do we show this button (eg. the Chromecast button) at all?
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class PreferencesPage extends React.Component {
|
|||||||
<PathSelector
|
<PathSelector
|
||||||
dialog={{
|
dialog={{
|
||||||
title: 'Select download directory',
|
title: 'Select download directory',
|
||||||
properties: [ 'openDirectory' ]
|
properties: ['openDirectory']
|
||||||
}}
|
}}
|
||||||
onChange={this.handleDownloadPathChange}
|
onChange={this.handleDownloadPathChange}
|
||||||
title='Download location'
|
title='Download location'
|
||||||
@@ -98,7 +98,7 @@ class PreferencesPage extends React.Component {
|
|||||||
<PathSelector
|
<PathSelector
|
||||||
dialog={{
|
dialog={{
|
||||||
title: 'Select media player app',
|
title: 'Select media player app',
|
||||||
properties: [ 'openFile' ]
|
properties: ['openFile']
|
||||||
}}
|
}}
|
||||||
displayValue={playerName}
|
displayValue={playerName}
|
||||||
onChange={this.handleExternalPlayerPathChange}
|
onChange={this.handleExternalPlayerPathChange}
|
||||||
@@ -151,7 +151,7 @@ class PreferencesPage extends React.Component {
|
|||||||
<PathSelector
|
<PathSelector
|
||||||
dialog={{
|
dialog={{
|
||||||
title: 'Select folder to watch for new torrents',
|
title: 'Select folder to watch for new torrents',
|
||||||
properties: [ 'openDirectory' ]
|
properties: ['openDirectory']
|
||||||
}}
|
}}
|
||||||
displayValue={torrentsFolderPath || ''}
|
displayValue={torrentsFolderPath || ''}
|
||||||
onChange={this.handletorrentsFolderPathChange}
|
onChange={this.handletorrentsFolderPathChange}
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ function compareTorrentFile (t, pathActual, fieldsExpected) {
|
|||||||
function extractImportantFields (parsedTorrent) {
|
function extractImportantFields (parsedTorrent) {
|
||||||
const { infoHash, name, announce, urlList, comment } = parsedTorrent
|
const { infoHash, name, announce, urlList, comment } = parsedTorrent
|
||||||
const priv = parsedTorrent.private // private is a reserved word in JS
|
const priv = parsedTorrent.private // private is a reserved word in JS
|
||||||
return { infoHash, name, announce, urlList, comment, 'private': priv }
|
return { infoHash, name, announce, urlList, comment, private: priv }
|
||||||
}
|
}
|
||||||
|
|
||||||
function copy (pathFrom, pathTo) {
|
function copy (pathFrom, pathTo) {
|
||||||
|
|||||||
Reference in New Issue
Block a user