resolve package-lock conflicts

This commit is contained in:
Mathias Rasmussen
2019-08-04 18:07:16 +02:00
20 changed files with 2756 additions and 3993 deletions

View File

@@ -1,6 +1,6 @@
# ProBot No Response (https://probot.github.io/apps/no-response/) # ProBot No Response (https://probot.github.io/apps/no-response/)
daysUntilClose: 7 daysUntilClose: 14
responseRequiredLabel: 'need more info' responseRequiredLabel: 'need more info'
closeComment: > closeComment: >
This issue has been automatically closed because there was no response to a This issue has been automatically closed because there was no response to a

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
package-lock=true

View File

@@ -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.

6435
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -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": "^4.2.0", "music-metadata": "^4.2.0",
"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,11 +51,11 @@
"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": "^1.8.8", "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",
"electron-winstaller": "^2.6.4", "electron-winstaller": "^2.6.4",
@@ -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"

View File

@@ -16,6 +16,9 @@ const windows = require('./windows')
let shouldQuit = false let shouldQuit = false
let argv = sliceArgv(process.argv) let argv = sliceArgv(process.argv)
// allow electron/chromium to play startup sounds (without user interaction)
app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required')
// Start the app without showing the main window when auto launching on login // Start the app without showing the main window when auto launching on login
// (On Windows and Linux, we get a flag. On MacOS, we get special API.) // (On Windows and Linux, we get a flag. On MacOS, we get special API.)
const hidden = argv.includes('--hidden') || const hidden = argv.includes('--hidden') ||
@@ -38,17 +41,19 @@ if (!shouldQuit && !config.IS_PORTABLE) {
// signal this instance and quit. Note: This feature creates a lock file in // signal this instance and quit. Note: This feature creates a lock file in
// %APPDATA%\Roaming\WebTorrent so we do not do it for the Portable App since // %APPDATA%\Roaming\WebTorrent so we do not do it for the Portable App since
// we want to be "silent" as well as "portable". // we want to be "silent" as well as "portable".
shouldQuit = app.makeSingleInstance(onAppOpen) if (!app.requestSingleInstanceLock()) {
if (shouldQuit) { shouldQuit = true
app.quit()
} }
} }
if (!shouldQuit) { if (shouldQuit) {
app.quit()
} else {
init() init()
} }
function init () { function init () {
app.on('second-instance', (event, commandLine, workingDirectory) => onAppOpen(commandLine))
if (config.IS_PORTABLE) { if (config.IS_PORTABLE) {
const path = require('path') const path = require('path')
// Put all user data into the "Portable Settings" folder // Put all user data into the "Portable Settings" folder

View File

@@ -120,21 +120,21 @@ function init () {
*/ */
ipc.on('startFolderWatcher', function () { ipc.on('startFolderWatcher', function () {
if (!modules['folderWatcher']) { if (!modules.folderWatcher) {
log('IPC ERR: folderWatcher module is not defined.') log('IPC ERR: folderWatcher module is not defined.')
return return
} }
modules['folderWatcher'].start() modules.folderWatcher.start()
}) })
ipc.on('stopFolderWatcher', function () { ipc.on('stopFolderWatcher', function () {
if (!modules['folderWatcher']) { if (!modules.folderWatcher) {
log('IPC ERR: folderWatcher module is not defined.') log('IPC ERR: folderWatcher module is not defined.')
return return
} }
modules['folderWatcher'].stop() modules.folderWatcher.stop()
}) })
/** /**

View File

@@ -40,7 +40,7 @@ function init (state, options) {
minWidth: config.WINDOW_MIN_WIDTH, minWidth: config.WINDOW_MIN_WIDTH,
show: false, show: false,
title: config.APP_WINDOW_TITLE, title: config.APP_WINDOW_TITLE,
titleBarStyle: 'hidden-inset', // Hide title bar (Mac) titleBarStyle: 'hiddenInset', // Hide title bar (Mac)
useContentSize: true, // Specify web page size without OS chrome useContentSize: true, // Specify web page size without OS chrome
width: initialBounds.width, width: initialBounds.width,
x: initialBounds.x, x: initialBounds.x,
@@ -138,7 +138,7 @@ function setAspectRatio (aspectRatio) {
function setBounds (bounds, maximize) { function setBounds (bounds, maximize) {
// Do nothing in fullscreen // Do nothing in fullscreen
if (!main.win || main.win.isFullScreen()) { if (!main.win || main.win.isFullScreen()) {
log(`setBounds: not setting bounds because we're in full screen`) log('setBounds: not setting bounds because already in full screen mode')
return return
} }
@@ -209,7 +209,7 @@ function toggleDevTools () {
if (main.win.webContents.isDevToolsOpened()) { if (main.win.webContents.isDevToolsOpened()) {
main.win.webContents.closeDevTools() main.win.webContents.closeDevTools()
} else { } else {
main.win.webContents.openDevTools({ detach: true }) main.win.webContents.openDevTools({ mode: 'detach' })
} }
} }

View File

@@ -56,6 +56,6 @@ function toggleDevTools () {
webtorrent.win.webContents.closeDevTools() webtorrent.win.webContents.closeDevTools()
webtorrent.win.hide() webtorrent.win.hide()
} else { } else {
webtorrent.win.webContents.openDevTools({ detach: true }) webtorrent.win.webContents.openDevTools({ mode: 'detach' })
} }
} }

View File

@@ -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()

View File

@@ -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 = {

View File

@@ -543,9 +543,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?

View File

@@ -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) {