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.
|
||||||
|
|||||||
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"
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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?
|
||||||
|
|||||||
@@ -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