Merge branch 'master' of github.com:webtorrent/webtorrent-desktop

This commit is contained in:
BlueManCZ
2021-01-31 10:40:05 +01:00
40 changed files with 4384 additions and 2517 deletions

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@ node_modules/
build/
dist/
npm-debug.log*
.vscode/
# JetBrains IntelliJ IDEA project files
.idea

View File

@@ -1,3 +1,5 @@
language: node_js
node_js:
- lts/*
cache:
npm: false

View File

@@ -19,7 +19,7 @@
## v0.23.0 - 2020-07-15
🔒 This release contains a critical security fix. Please update as soon as possible.
🔒 This release contains a critical security fix. Please update as soon as possible. [\#1837](https://github.com/webtorrent/webtorrent-desktop/issues/1837#issuecomment-729320901)
### Added

View File

@@ -1,39 +0,0 @@
#!/usr/bin/env node
const walkSync = require('walk-sync')
const fs = require('fs')
const path = require('path')
let hasErrors = false
// Find all Javascript source files
const files = walkSync('src', { globs: ['**/*.js'] })
console.log('Running extra-lint on ' + files.length + ' files...')
// Read each file, line by line
files.forEach(function (file) {
const filepath = path.join('src', file)
const lines = fs.readFileSync(filepath, 'utf8').split('\n')
lines.forEach(function (line, i) {
let error
// No lines over 100 characters
if (line.length > 100) {
error = 'Line >100 chars'
}
if (line.match(/^var /) || line.match(/ var /)) {
error = 'Use const or let'
}
if (error) {
const name = path.basename(file)
console.log('%s:%d - %s:\n%s', name, i + 1, error, line)
hasErrors = true
}
})
})
if (hasErrors) process.exit(1)
else console.log('Looks good!')

View File

@@ -545,7 +545,17 @@ function buildLinux (cb) {
},
categories: ['Network', 'FileTransfer', 'P2P'],
mimeType: ['application/x-bittorrent', 'x-scheme-handler/magnet', 'x-scheme-handler/stream-magnet'],
desktopTemplate: path.join(config.STATIC_PATH, 'linux/webtorrent-desktop.ejs')
desktopTemplate: path.join(config.STATIC_PATH, 'linux/webtorrent-desktop.ejs'),
lintianOverrides: [
'unstripped-binary-or-object',
'embedded-library',
'missing-dependency-on-libc',
'changelog-file-missing-in-native-package',
'description-synopsis-is-duplicated',
'setuid-binary',
'binary-without-manpage',
'shlib-with-executable-bit'
]
}
installer(options).then(

6222
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,66 +7,77 @@
"email": "feross@webtorrent.io",
"url": "https://webtorrent.io"
},
"babel": {
"plugins": [
[
"@babel/plugin-transform-react-jsx",
{
"useBuiltIns": true
}
]
]
},
"bugs": {
"url": "https://github.com/webtorrent/webtorrent-desktop/issues"
},
"dependencies": {
"airplayer": "github:webtorrent/airplayer#fix-security",
"application-config": "^2.0.0",
"arch": "^2.1.2",
"arch": "^2.2.0",
"auto-launch": "^5.0.5",
"bitfield": "^3.0.0",
"bitfield": "^4.0.0",
"capture-frame": "^4.0.0",
"chokidar": "^3.4.2",
"chokidar": "^3.4.3",
"chromecasts": "^1.9.1",
"create-torrent": "^4.4.2",
"debounce": "^1.2.0",
"dlnacasts": "^0.1.0",
"drag-drop": "^6.0.2",
"drag-drop": "^6.1.0",
"es6-error": "^4.1.1",
"fn-getter": "^1.0.0",
"iso-639-1": "^2.1.4",
"languagedetect": "^2.0.0",
"location-history": "^1.1.2",
"material-ui": "^0.20.2",
"music-metadata": "^7.0.2",
"music-metadata": "^7.5.0",
"network-address": "^1.1.2",
"parse-torrent": "^7.1.3",
"parse-torrent": "^9.1.0",
"prettier-bytes": "^1.0.4",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"rimraf": "^3.0.2",
"run-parallel": "^1.1.9",
"run-parallel": "^1.1.10",
"semver": "^7.3.2",
"simple-concat": "^1.0.1",
"simple-get": "^4.0.0",
"srt-to-vtt": "^1.1.3",
"vlc-command": "^1.2.0",
"webtorrent": ">=0.108.6",
"webtorrent": ">=0.111.0",
"winreg": "^1.2.4"
},
"devDependencies": {
"babel-eslint": "^10.1.0",
"buble": "^0.20.0",
"cross-zip": "^3.1.0",
"depcheck": "^1.2.0",
"electron": "~10.1.0",
"@babel/cli": "^7.12.8",
"@babel/core": "^7.12.9",
"@babel/eslint-parser": "^7.12.1",
"@babel/plugin-transform-react-jsx": "^7.12.7",
"cross-zip": "^4.0.0",
"depcheck": "^1.3.1",
"electron": "~11.0.3",
"electron-notarize": "^1.0.0",
"electron-osx-sign": "^0.4.17",
"electron-osx-sign": "^0.5.0",
"electron-packager": "^15.1.0",
"electron-winstaller": "^4.0.1",
"gh-release": "^3.5.0",
"gh-release": "^4.0.3",
"minimist": "^1.2.5",
"nodemon": "^2.0.4",
"open": "^7.2.1",
"nodemon": "^2.0.6",
"open": "^7.3.0",
"plist": "^3.0.1",
"pngjs": "^5.0.0",
"run-series": "^1.1.8",
"spectron": "~11.1.0",
"pngjs": "^6.0.0",
"run-series": "^1.1.9",
"spectron": "~12.0.0",
"standard": "*",
"tape": "^5.0.1",
"walk-sync": "^2.2.0"
"tape": "^5.0.1"
},
"engines": {
"node": ">=4.0.0"
@@ -96,19 +107,19 @@
"url": "git://github.com/webtorrent/webtorrent-desktop.git"
},
"scripts": {
"build": "buble src --target chrome:71 --output build",
"build": "babel src --out-dir build",
"clean": "node ./bin/clean.js",
"gh-release": "gh-release",
"install-system-deps": "brew install fakeroot dpkg rpm",
"open-config": "node ./bin/open-config.js",
"package": "node ./bin/package.js",
"start": "npm run build && electron --no-sandbox .",
"test": "standard && depcheck --ignores=standard,babel-eslint --ignore-dirs=build,dist && node ./bin/extra-lint.js",
"test": "standard && depcheck --ignores=standard,@babel/eslint-parser --ignore-dirs=build,dist",
"test-integration": "npm run build && node ./test",
"update-authors": "./bin/update-authors.sh",
"watch": "nodemon --exec \"npm run start\" --ext js,css --ignore build/ --ignore dist/"
},
"standard": {
"parser": "babel-eslint"
"parser": "@babel/eslint-parser"
}
}

View File

@@ -1,6 +1,6 @@
const appConfig = require('application-config')('WebTorrent')
const path = require('path')
const electron = require('electron')
const { app, remote } = require('electron')
const arch = require('arch')
const APP_NAME = 'WebTorrent'
@@ -126,10 +126,10 @@ function getPath (key) {
return ''
} else if (process.type === 'renderer') {
// Electron renderer process
return electron.remote.app.getPath(key)
return remote.app.getPath(key)
} else {
// Electron main process
return electron.app.getPath(key)
return app.getPath(key)
}
}

View File

@@ -4,9 +4,9 @@ module.exports = {
function init () {
const config = require('./config')
const electron = require('electron')
const { crashReporter } = require('electron')
electron.crashReporter.start({
crashReporter.start({
productName: config.APP_NAME,
submitURL: config.CRASH_REPORT_URL,
globalExtra: { _companyName: config.APP_NAME },

View File

@@ -2,7 +2,7 @@ module.exports = {
init
}
const electron = require('electron')
const { dialog } = require('electron')
const config = require('../config')
const log = require('./log')
@@ -44,7 +44,7 @@ function onResponse (err, res, data) {
}
}
electron.dialog.showMessageBox({
dialog.showMessageBox({
type: 'info',
buttons: ['OK'],
title: data.title,

View File

@@ -6,7 +6,7 @@ module.exports = {
openFiles
}
const electron = require('electron')
const { dialog } = require('electron')
const log = require('./log')
const windows = require('./windows')
@@ -61,7 +61,7 @@ function openFiles () {
properties: ['openFile']
}
setTitle(opts.title)
const selectedPaths = electron.dialog.showOpenDialogSync(windows.main.win, opts)
const selectedPaths = dialog.showOpenDialogSync(windows.main.win, opts)
resetTitle()
if (!Array.isArray(selectedPaths)) return
windows.main.dispatch('onOpen', selectedPaths)
@@ -79,7 +79,7 @@ function openTorrentFile () {
properties: ['openFile', 'multiSelections']
}
setTitle(opts.title)
const selectedPaths = electron.dialog.showOpenDialogSync(windows.main.win, opts)
const selectedPaths = dialog.showOpenDialogSync(windows.main.win, opts)
resetTitle()
if (!Array.isArray(selectedPaths)) return
selectedPaths.forEach(function (selectedPath) {
@@ -114,7 +114,7 @@ function resetTitle () {
*/
function showOpenSeed (opts) {
setTitle(opts.title)
const selectedPaths = electron.dialog.showOpenDialogSync(windows.main.win, opts)
const selectedPaths = dialog.showOpenDialogSync(windows.main.win, opts)
resetTitle()
if (!Array.isArray(selectedPaths)) return
windows.main.dispatch('showCreateTorrent', selectedPaths)

View File

@@ -25,8 +25,7 @@ function uninstall () {
}
function installDarwin () {
const electron = require('electron')
const app = electron.app
const { app } = require('electron')
// On Mac, only protocols that are listed in `Info.plist` can be set as the
// default handler at runtime.

View File

@@ -1,7 +1,6 @@
console.time('init')
const electron = require('electron')
const app = electron.app
const { app, ipcMain } = require('electron')
// Start crash reporter early, so it takes effect for child processes
const crashReporter = require('../crash-reporter')
@@ -67,8 +66,6 @@ function init () {
app.setPath('temp', path.join(config.CONFIG_PATH, 'Temp'))
}
const ipcMain = electron.ipcMain
let isReady = false // app ready, windows can be created
app.ipcReady = false // main window has finished loading and IPC is ready
app.isQuitting = false
@@ -198,9 +195,13 @@ function onAppOpen (newArgv) {
// Development: 2 args, eg: electron .
// Test: 4 args, eg: electron -r .../mocks.js .
function sliceArgv (argv) {
return argv.slice(config.IS_PRODUCTION ? 1
: config.IS_TEST ? 4
: 2)
return argv.slice(
config.IS_PRODUCTION
? 1
: config.IS_TEST
? 4
: 2
)
}
function processArgv (argv) {

View File

@@ -3,9 +3,7 @@ module.exports = {
setModule
}
const electron = require('electron')
const app = electron.app
const { app, ipcMain } = require('electron')
const log = require('./log')
const menu = require('./menu')
@@ -23,14 +21,12 @@ function setModule (name, module) {
}
function init () {
const ipc = electron.ipcMain
ipc.once('ipcReady', function (e) {
ipcMain.once('ipcReady', function (e) {
app.ipcReady = true
app.emit('ipcReady')
})
ipc.once('ipcReadyWebTorrent', function (e) {
ipcMain.once('ipcReadyWebTorrent', function (e) {
app.ipcReadyWebTorrent = true
log('sending %d queued messages from the main win to the webtorrent window',
messageQueueMainToWebTorrent.length)
@@ -44,11 +40,11 @@ function init () {
* Dialog
*/
ipc.on('openTorrentFile', () => {
ipcMain.on('openTorrentFile', () => {
const dialog = require('./dialog')
dialog.openTorrentFile()
})
ipc.on('openFiles', () => {
ipcMain.on('openFiles', () => {
const dialog = require('./dialog')
dialog.openFiles()
})
@@ -57,11 +53,11 @@ function init () {
* Dock
*/
ipc.on('setBadge', (e, ...args) => {
ipcMain.on('setBadge', (e, ...args) => {
const dock = require('./dock')
dock.setBadge(...args)
})
ipc.on('downloadFinished', (e, ...args) => {
ipcMain.on('downloadFinished', (e, ...args) => {
const dock = require('./dock')
dock.downloadFinished(...args)
})
@@ -70,7 +66,7 @@ function init () {
* Player Events
*/
ipc.on('onPlayerOpen', function () {
ipcMain.on('onPlayerOpen', function () {
const powerSaveBlocker = require('./power-save-blocker')
const shortcuts = require('./shortcuts')
const thumbar = require('./thumbar')
@@ -81,14 +77,14 @@ function init () {
thumbar.enable()
})
ipc.on('onPlayerUpdate', function (e, ...args) {
ipcMain.on('onPlayerUpdate', function (e, ...args) {
const thumbar = require('./thumbar')
menu.onPlayerUpdate(...args)
thumbar.onPlayerUpdate(...args)
})
ipc.on('onPlayerClose', function () {
ipcMain.on('onPlayerClose', function () {
const powerSaveBlocker = require('./power-save-blocker')
const shortcuts = require('./shortcuts')
const thumbar = require('./thumbar')
@@ -99,7 +95,7 @@ function init () {
thumbar.disable()
})
ipc.on('onPlayerPlay', function () {
ipcMain.on('onPlayerPlay', function () {
const powerSaveBlocker = require('./power-save-blocker')
const thumbar = require('./thumbar')
@@ -107,7 +103,7 @@ function init () {
thumbar.onPlayerPlay()
})
ipc.on('onPlayerPause', function () {
ipcMain.on('onPlayerPause', function () {
const powerSaveBlocker = require('./power-save-blocker')
const thumbar = require('./thumbar')
@@ -119,7 +115,7 @@ function init () {
* Folder Watcher Events
*/
ipc.on('startFolderWatcher', function () {
ipcMain.on('startFolderWatcher', function () {
if (!modules.folderWatcher) {
log('IPC ERR: folderWatcher module is not defined.')
return
@@ -128,7 +124,7 @@ function init () {
modules.folderWatcher.start()
})
ipc.on('stopFolderWatcher', function () {
ipcMain.on('stopFolderWatcher', function () {
if (!modules.folderWatcher) {
log('IPC ERR: folderWatcher module is not defined.')
return
@@ -141,15 +137,15 @@ function init () {
* Shell
*/
ipc.on('openPath', (e, ...args) => {
ipcMain.on('openPath', (e, ...args) => {
const shell = require('./shell')
shell.openPath(...args)
})
ipc.on('showItemInFolder', (e, ...args) => {
ipcMain.on('showItemInFolder', (e, ...args) => {
const shell = require('./shell')
shell.showItemInFolder(...args)
})
ipc.on('moveItemToTrash', (e, ...args) => {
ipcMain.on('moveItemToTrash', (e, ...args) => {
const shell = require('./shell')
shell.moveItemToTrash(...args)
})
@@ -158,7 +154,7 @@ function init () {
* File handlers
*/
ipc.on('setDefaultFileHandler', (e, flag) => {
ipcMain.on('setDefaultFileHandler', (e, flag) => {
const handlers = require('./handlers')
if (flag) handlers.install()
@@ -169,7 +165,7 @@ function init () {
* Auto start on login
*/
ipc.on('setStartup', (e, flag) => {
ipcMain.on('setStartup', (e, flag) => {
const startup = require('./startup')
if (flag) startup.install()
@@ -182,19 +178,19 @@ function init () {
const main = windows.main
ipc.on('setAspectRatio', (e, ...args) => main.setAspectRatio(...args))
ipc.on('setBounds', (e, ...args) => main.setBounds(...args))
ipc.on('setProgress', (e, ...args) => main.setProgress(...args))
ipc.on('setTitle', (e, ...args) => main.setTitle(...args))
ipc.on('show', () => main.show())
ipc.on('toggleFullScreen', (e, ...args) => main.toggleFullScreen(...args))
ipc.on('setAllowNav', (e, ...args) => menu.setAllowNav(...args))
ipcMain.on('setAspectRatio', (e, ...args) => main.setAspectRatio(...args))
ipcMain.on('setBounds', (e, ...args) => main.setBounds(...args))
ipcMain.on('setProgress', (e, ...args) => main.setProgress(...args))
ipcMain.on('setTitle', (e, ...args) => main.setTitle(...args))
ipcMain.on('show', () => main.show())
ipcMain.on('toggleFullScreen', (e, ...args) => main.toggleFullScreen(...args))
ipcMain.on('setAllowNav', (e, ...args) => menu.setAllowNav(...args))
/**
* External Media Player
*/
ipc.on('checkForExternalPlayer', function (e, path) {
ipcMain.on('checkForExternalPlayer', function (e, path) {
const externalPlayer = require('./external-player')
externalPlayer.checkInstall(path, function (err) {
@@ -202,7 +198,7 @@ function init () {
})
})
ipc.on('openExternalPlayer', (e, ...args) => {
ipcMain.on('openExternalPlayer', (e, ...args) => {
const externalPlayer = require('./external-player')
const thumbar = require('./thumbar')
@@ -211,7 +207,7 @@ function init () {
externalPlayer.spawn(...args)
})
ipc.on('quitExternalPlayer', () => {
ipcMain.on('quitExternalPlayer', () => {
const externalPlayer = require('./external-player')
externalPlayer.kill()
})
@@ -220,8 +216,8 @@ function init () {
* Message passing
*/
const oldEmit = ipc.emit
ipc.emit = function (name, e, ...args) {
const oldEmit = ipcMain.emit
ipcMain.emit = function (name, e, ...args) {
// Relay messages between the main window and the WebTorrent hidden window
if (name.startsWith('wt-') && !app.isQuitting) {
if (e.sender.browserWindowOptions.title === 'webtorrent-hidden-window') {
@@ -244,6 +240,6 @@ function init () {
}
// Emit all other events normally
oldEmit.call(ipc, name, e, ...args)
oldEmit.call(ipcMain, name, e, ...args)
}
}

View File

@@ -8,11 +8,9 @@ module.exports.error = error
* where they can be viewed in Developer Tools.
*/
const electron = require('electron')
const { app } = require('electron')
const windows = require('./windows')
const app = electron.app
function log (...args) {
if (app.ipcReady) {
windows.main.send('log', ...args)

View File

@@ -8,9 +8,7 @@ module.exports = {
onToggleFullScreen
}
const electron = require('electron')
const app = electron.app
const { app, Menu } = require('electron')
const config = require('../config')
const windows = require('./windows')
@@ -18,8 +16,8 @@ const windows = require('./windows')
let menu = null
function init () {
menu = electron.Menu.buildFromTemplate(getMenuTemplate())
electron.Menu.setApplicationMenu(menu)
menu = Menu.buildFromTemplate(getMenuTemplate())
Menu.setApplicationMenu(menu)
}
function togglePlaybackControls (flag) {

View File

@@ -3,7 +3,7 @@ module.exports = {
disable
}
const electron = require('electron')
const { powerSaveBlocker } = require('electron')
const log = require('./log')
let blockId = 0
@@ -13,11 +13,11 @@ let blockId = 0
* display.
*/
function enable () {
if (electron.powerSaveBlocker.isStarted(blockId)) {
if (powerSaveBlocker.isStarted(blockId)) {
// If a power saver block already exists, do nothing.
return
}
blockId = electron.powerSaveBlocker.start('prevent-display-sleep')
blockId = powerSaveBlocker.start('prevent-display-sleep')
log(`powerSaveBlocker.enable: ${blockId}`)
}
@@ -25,10 +25,10 @@ function enable () {
* Stop blocking the system from entering low-power mode.
*/
function disable () {
if (!electron.powerSaveBlocker.isStarted(blockId)) {
if (!powerSaveBlocker.isStarted(blockId)) {
// If a power saver block does not exist, do nothing.
return
}
electron.powerSaveBlocker.stop(blockId)
powerSaveBlocker.stop(blockId)
log(`powerSaveBlocker.disable: ${blockId}`)
}

View File

@@ -5,7 +5,7 @@ module.exports = {
moveItemToTrash
}
const electron = require('electron')
const { shell } = require('electron')
const log = require('./log')
/**
@@ -13,15 +13,16 @@ const log = require('./log')
*/
function openExternal (url) {
log(`openExternal: ${url}`)
electron.shell.openExternal(url)
shell.openExternal(url)
}
/**
* Open the given file in the desktops default manner.
*/
function openPath (path) {
log(`openPath: ${path}`)
electron.shell.openPath(path)
shell.openPath(path)
}
/**
@@ -29,7 +30,7 @@ function openPath (path) {
*/
function showItemInFolder (path) {
log(`showItemInFolder: ${path}`)
electron.shell.showItemInFolder(path)
shell.showItemInFolder(path)
}
/**
@@ -37,5 +38,5 @@ function showItemInFolder (path) {
*/
function moveItemToTrash (path) {
log(`moveItemToTrash: ${path}`)
electron.shell.moveItemToTrash(path)
shell.moveItemToTrash(path)
}

View File

@@ -3,20 +3,20 @@ module.exports = {
enable
}
const electron = require('electron')
const { globalShortcut } = require('electron')
const windows = require('./windows')
function enable () {
// Register play/pause media key, available on some keyboards.
electron.globalShortcut.register(
globalShortcut.register(
'MediaPlayPause',
() => windows.main.dispatch('playPause')
)
electron.globalShortcut.register(
globalShortcut.register(
'MediaNextTrack',
() => windows.main.dispatch('nextTrack')
)
electron.globalShortcut.register(
globalShortcut.register(
'MediaPreviousTrack',
() => windows.main.dispatch('previousTrack')
)
@@ -24,7 +24,7 @@ function enable () {
function disable () {
// Return the media key to the OS, so other apps can use it.
electron.globalShortcut.unregister('MediaPlayPause')
electron.globalShortcut.unregister('MediaNextTrack')
electron.globalShortcut.unregister('MediaPreviousTrack')
globalShortcut.unregister('MediaPlayPause')
globalShortcut.unregister('MediaNextTrack')
globalShortcut.unregister('MediaPreviousTrack')
}

View File

@@ -2,11 +2,10 @@ module.exports = {
handleEvent
}
const { app } = require('electron')
const path = require('path')
const spawn = require('child_process').spawn
const electron = require('electron')
const app = electron.app
const handlers = require('./handlers')

View File

@@ -4,9 +4,7 @@ module.exports = {
setWindowFocus
}
const electron = require('electron')
const app = electron.app
const { app, Tray, Menu } = require('electron')
const config = require('../config')
const windows = require('./windows')
@@ -67,7 +65,7 @@ function checkLinuxTraySupport (cb) {
}
function createTray () {
tray = new electron.Tray(getIconPath())
tray = new 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.
@@ -78,7 +76,7 @@ function createTray () {
}
function updateTrayMenu () {
const contextMenu = electron.Menu.buildFromTemplate(getMenuTemplate())
const contextMenu = Menu.buildFromTemplate(getMenuTemplate())
tray.setContextMenu(contextMenu)
}

View File

@@ -2,7 +2,7 @@ module.exports = {
init
}
const electron = require('electron')
const { autoUpdater } = require('electron')
const get = require('simple-get')
const config = require('../config')
@@ -47,31 +47,31 @@ function onResponse (err, res, data) {
}
function initDarwinWin32 () {
electron.autoUpdater.on(
autoUpdater.on(
'error',
(err) => log.error(`Update error: ${err.message}`)
)
electron.autoUpdater.on(
autoUpdater.on(
'checking-for-update',
() => log('Checking for update')
)
electron.autoUpdater.on(
autoUpdater.on(
'update-available',
() => log('Update available')
)
electron.autoUpdater.on(
autoUpdater.on(
'update-not-available',
() => log('No update available')
)
electron.autoUpdater.on(
autoUpdater.on(
'update-downloaded',
(e, notes, name, date, url) => log(`Update downloaded: ${name}: ${url}`)
)
electron.autoUpdater.setFeedURL({ url: AUTO_UPDATE_URL })
electron.autoUpdater.checkForUpdates()
autoUpdater.setFeedURL({ url: AUTO_UPDATE_URL })
autoUpdater.checkForUpdates()
}

View File

@@ -2,9 +2,7 @@ module.exports = {
init
}
const electron = require('electron')
const app = electron.app
const { app } = require('electron')
/**
* Add a user task menu to the app icon on right-click. (Windows)

View File

@@ -4,14 +4,14 @@ const about = module.exports = {
}
const config = require('../../config')
const electron = require('electron')
const { BrowserWindow } = require('electron')
function init () {
if (about.win) {
return about.win.show()
}
const win = about.win = new electron.BrowserWindow({
const win = about.win = new BrowserWindow({
backgroundColor: '#ECECEC',
center: true,
fullscreen: false,
@@ -27,7 +27,8 @@ function init () {
webPreferences: {
nodeIntegration: true,
enableBlinkFeatures: 'AudioVideoTracks',
enableRemoteModule: true
enableRemoteModule: true,
backgroundThrottling: false
},
width: 300
})

View File

@@ -14,11 +14,9 @@ const main = module.exports = {
win: null
}
const electron = require('electron')
const { app, BrowserWindow, screen } = require('electron')
const debounce = require('debounce')
const app = electron.app
const config = require('../../config')
const log = require('../log')
const menu = require('../menu')
@@ -30,7 +28,7 @@ function init (state, options) {
const initialBounds = Object.assign(config.WINDOW_INITIAL_BOUNDS, state.saved.bounds)
const win = main.win = new electron.BrowserWindow({
const win = main.win = new BrowserWindow({
backgroundColor: '#282828',
darkTheme: true, // Forces dark theme (GTK+3)
height: initialBounds.height,
@@ -45,7 +43,8 @@ function init (state, options) {
webPreferences: {
nodeIntegration: true,
enableBlinkFeatures: 'AudioVideoTracks',
enableRemoteModule: true
enableRemoteModule: true,
backgroundThrottling: false
},
x: initialBounds.x,
y: initialBounds.y
@@ -161,7 +160,7 @@ 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
const scr = electron.screen.getDisplayMatching(main.win.getBounds())
const scr = screen.getDisplayMatching(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)}`)

View File

@@ -6,12 +6,12 @@ const webtorrent = module.exports = {
win: null
}
const electron = require('electron')
const { app, BrowserWindow } = require('electron')
const config = require('../../config')
function init () {
const win = webtorrent.win = new electron.BrowserWindow({
const win = webtorrent.win = new BrowserWindow({
backgroundColor: '#1E1E1E',
center: true,
fullscreen: false,
@@ -27,7 +27,8 @@ function init () {
webPreferences: {
nodeIntegration: true,
enableBlinkFeatures: 'AudioVideoTracks',
enableRemoteModule: true
enableRemoteModule: true,
backgroundThrottling: false
},
width: 150
})
@@ -36,7 +37,7 @@ function init () {
// Prevent killing the WebTorrent process
win.on('close', function (e) {
if (electron.app.isQuitting) {
if (app.isQuitting) {
return
}
e.preventDefault()

View File

@@ -1,12 +1,10 @@
const path = require('path')
const colors = require('material-ui/styles/colors')
const electron = require('electron')
const { remote } = require('electron')
const React = require('react')
const PropTypes = require('prop-types')
const remote = electron.remote
const RaisedButton = require('material-ui/RaisedButton').default
const TextField = require('material-ui/TextField').default

View File

@@ -1,5 +1,5 @@
const React = require('react')
const electron = require('electron')
const { shell } = require('electron')
const ModalOKCancel = require('./modal-ok-cancel')
const { dispatcher } = require('../lib/dispatcher')
@@ -36,7 +36,7 @@ module.exports = class UnsupportedMediaModal extends React.Component {
}
onInstall () {
electron.shell.openExternal('http://www.videolan.org/vlc/')
shell.openExternal('http://www.videolan.org/vlc/')
// TODO: dcposch send a dispatch rather than modifying state directly
const state = this.props.state

View File

@@ -1,5 +1,5 @@
const React = require('react')
const electron = require('electron')
const { shell } = require('electron')
const ModalOKCancel = require('./modal-ok-cancel')
const { dispatch } = require('../lib/dispatcher')
@@ -25,7 +25,7 @@ module.exports = class UpdateAvailableModal extends React.Component {
function handleShow () {
// TODO: use the GitHub urls from config.js
electron.shell.openExternal('https://github.com/webtorrent/webtorrent-desktop/releases')
shell.openExternal('https://github.com/webtorrent/webtorrent-desktop/releases')
dispatch('exitModal')
}

View File

@@ -1,4 +1,4 @@
const electron = require('electron')
const { ipcRenderer } = require('electron')
const path = require('path')
const Cast = require('../lib/cast')
@@ -11,8 +11,6 @@ const TorrentSummary = require('../lib/torrent-summary')
const Playlist = require('../lib/playlist')
const State = require('../lib/state')
const ipcRenderer = electron.ipcRenderer
// Controls playback of torrents and files within torrents
// both local (<video>,<audio>,external player) and remote (cast)
module.exports = class PlaybackController {
@@ -158,6 +156,20 @@ module.exports = class PlaybackController {
else this.state.playing.jumpToTime = time
}
// Show video preview
preview (x) {
if (!Number.isFinite(x)) {
console.error('Tried to preview a non-finite position ' + x)
return console.trace()
}
this.state.playing.previewXCoord = x
}
// Hide video preview
clearPreview () {
this.state.playing.previewXCoord = null
}
// Change playback speed. 1 = faster, -1 = slower
// Playback speed ranges from 16 (fast forward) to 1 (normal playback)
// to 0.25 (quarter-speed playback), then goes to -0.25, -0.5, -1, -2, etc
@@ -270,8 +282,10 @@ module.exports = class PlaybackController {
state.playing.infoHash = infoHash
state.playing.fileIndex = index
state.playing.fileName = fileSummary.name
state.playing.type = TorrentPlayer.isVideo(fileSummary) ? 'video'
: TorrentPlayer.isAudio(fileSummary) ? 'audio'
state.playing.type = TorrentPlayer.isVideo(fileSummary)
? 'video'
: TorrentPlayer.isAudio(fileSummary)
? 'audio'
: 'other'
// pick up where we left off

View File

@@ -1,5 +1,5 @@
const { dispatch } = require('../lib/dispatcher')
const ipcRenderer = require('electron').ipcRenderer
const { ipcRenderer } = require('electron')
// Controls the Preferences screen
module.exports = class PrefsController {

View File

@@ -1,10 +1,8 @@
const electron = require('electron')
const { remote } = require('electron')
const fs = require('fs')
const path = require('path')
const parallel = require('run-parallel')
const remote = electron.remote
const { dispatch } = require('../lib/dispatcher')
module.exports = class SubtitlesController {

View File

@@ -1,5 +1,5 @@
const path = require('path')
const ipcRenderer = require('electron').ipcRenderer
const { ipcRenderer } = require('electron')
const TorrentSummary = require('../lib/torrent-summary')
const sound = require('../lib/sound')

View File

@@ -1,14 +1,12 @@
const fs = require('fs')
const path = require('path')
const electron = require('electron')
const { ipcRenderer, remote, clipboard } = require('electron')
const { dispatch } = require('../lib/dispatcher')
const { TorrentKeyNotFoundError } = require('../lib/errors')
const sound = require('../lib/sound')
const TorrentSummary = require('../lib/torrent-summary')
const ipcRenderer = electron.ipcRenderer
const instantIoRegex = /^(https:\/\/)?instant\.io\/#/
// Controls the torrent list: creating, adding, deleting, & manipulating torrents
@@ -160,7 +158,7 @@ module.exports = class TorrentListController {
.filter((torrent) => { // We're interested in active torrents only.
return (['downloading', 'seeding'].indexOf(torrent.status) !== -1)
})
.map((torrent) => { // Pause all active torrents except the one that started playing.
.forEach((torrent) => { // Pause all active torrents except the one that started playing.
if (infoHash === torrent.infoHash) return
// Pause torrent without playing sounds.
@@ -175,7 +173,7 @@ module.exports = class TorrentListController {
resumePausedTorrents () {
console.log('Playback Priority: resuming paused torrents')
if (!this.state.saved.torrentsToResume || !this.state.saved.torrentsToResume.length) return
this.state.saved.torrentsToResume.map((infoHash) => {
this.state.saved.torrentsToResume.forEach((infoHash) => {
this.toggleTorrent(infoHash)
})
@@ -249,59 +247,59 @@ module.exports = class TorrentListController {
openTorrentContextMenu (infoHash) {
const torrentSummary = TorrentSummary.getByKey(this.state, infoHash)
const menu = new electron.remote.Menu()
const menu = new remote.Menu()
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: 'Remove From List',
click: () => dispatch('confirmDeleteTorrent', torrentSummary.infoHash, false)
}))
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: 'Remove Data File',
click: () => dispatch('confirmDeleteTorrent', torrentSummary.infoHash, true)
}))
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
type: 'separator'
}))
if (torrentSummary.files) {
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: process.platform === 'darwin' ? 'Show in Finder' : 'Show in Folder',
click: () => showItemInFolder(torrentSummary)
}))
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
type: 'separator'
}))
}
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: 'Copy Magnet Link to Clipboard',
click: () => electron.clipboard.writeText(torrentSummary.magnetURI)
click: () => clipboard.writeText(torrentSummary.magnetURI)
}))
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: 'Copy Instant.io Link to Clipboard',
click: () => electron.clipboard.writeText(`https://instant.io/#${torrentSummary.infoHash}`)
click: () => clipboard.writeText(`https://instant.io/#${torrentSummary.infoHash}`)
}))
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: 'Save Torrent File As...',
click: () => dispatch('saveTorrentFileAs', torrentSummary.torrentKey),
enabled: torrentSummary.torrentFileName != null
}))
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
type: 'separator'
}))
const sortedByName = this.state.saved.prefs.sortByName
menu.append(new electron.remote.MenuItem({
menu.append(new remote.MenuItem({
label: `${sortedByName ? '✓ ' : ''}Sort by Name`,
click: () => dispatch('updatePreferences', 'sortByName', !sortedByName)
}))
menu.popup({ window: electron.remote.getCurrentWindow() })
menu.popup({ window: remote.getCurrentWindow() })
}
// Takes a torrentSummary or torrentKey
@@ -311,7 +309,7 @@ module.exports = class TorrentListController {
if (!torrentSummary) throw new TorrentKeyNotFoundError(torrentKey)
const downloadPath = this.state.saved.prefs.downloadPath
const newFileName = path.parse(torrentSummary.name).name + '.torrent'
const win = electron.remote.getCurrentWindow()
const win = remote.getCurrentWindow()
const opts = {
title: 'Save Torrent File',
defaultPath: path.join(downloadPath, newFileName),
@@ -322,7 +320,7 @@ module.exports = class TorrentListController {
buttonLabel: 'Save'
}
const savePath = electron.remote.dialog.showSaveDialogSync(win, opts)
const savePath = remote.dialog.showSaveDialogSync(win, opts)
if (!savePath) return // They clicked Cancel
console.log('Saving torrent ' + torrentKey + ' to ' + savePath)

View File

@@ -7,7 +7,7 @@ module.exports = {
logPlayAttempt
}
const electron = require('electron')
const { remote } = require('electron')
const config = require('../../config')
@@ -74,7 +74,7 @@ function reset () {
// Track screen resolution
function getScreenInfo () {
return electron.remote.screen.getAllDisplays().map((screen) => ({
return remote.screen.getAllDisplays().map((screen) => ({
width: screen.size.width,
height: screen.size.height,
scaleFactor: screen.scaleFactor

View File

@@ -130,7 +130,10 @@ function onState (err, _state) {
resumeTorrents()
// Initialize ReactDOM
app = ReactDOM.render(<App state={state} />, document.querySelector('#body'))
ReactDOM.render(
<App state={state} ref={elem => { app = elem }} />,
document.querySelector('#body')
)
// Calling update() updates the UI given the current state
// Do this at least once a second to give every file in every torrentSummary
@@ -274,6 +277,8 @@ const dispatchHandlers = {
previousTrack: () => controllers.playback().previousTrack(),
skip: (time) => controllers.playback().skip(time),
skipTo: (time) => controllers.playback().skipTo(time),
preview: (x) => controllers.playback().preview(x),
clearPreview: () => controllers.playback().clearPreview(),
changePlaybackRate: (dir) => controllers.playback().changePlaybackRate(dir),
changeVolume: (delta) => controllers.playback().changeVolume(delta),
setVolume: (vol) => controllers.playback().setVolume(vol),

View File

@@ -1,5 +1,5 @@
const React = require('react')
const Bitfield = require('bitfield')
const BitField = require('bitfield').default
const prettyBytes = require('prettier-bytes')
const TorrentSummary = require('../lib/torrent-summary')
@@ -427,22 +427,77 @@ function renderCastScreen (state) {
const isStarting = state.playing.location.endsWith('-pending')
const castName = state.playing.castName
const fileName = state.getPlayingFileSummary().name || ''
let castStatus
if (isCast && isStarting) castStatus = 'Connecting to ' + castName + '...'
else if (isCast && !isStarting) castStatus = 'Connected to ' + castName
else castStatus = ''
const prog = state.getPlayingTorrentSummary().progress || {}
// Show a nice title image, if possible
const style = {
backgroundImage: cssBackgroundImagePoster(state)
}
function renderEta (total, downloaded) {
const missing = (total || 0) - (downloaded || 0)
const downloadSpeed = prog.downloadSpeed || 0
if (downloadSpeed === 0 || missing === 0) return
const rawEta = missing / downloadSpeed
const hours = Math.floor(rawEta / 3600) % 24
const minutes = Math.floor(rawEta / 60) % 60
const seconds = Math.floor(rawEta % 60)
const hoursStr = hours ? hours + 'h' : ''
const minutesStr = (hours || minutes) ? minutes + 'm' : ''
const secondsStr = seconds + 's'
return (<span>{hoursStr} {minutesStr} {secondsStr} remaining</span>)
}
function renderDownloadProgress () {
if (!prog.files) return
const fileProg = prog.files[state.playing.fileIndex]
const fileProgress = fileProg.numPiecesPresent / fileProg.numPieces
const fileLength = state.getPlayingFileSummary().length
const fileDownloaded = fileProgress * fileLength
const progress = Math.round(100 * fileProgress)
const total = prettyBytes(fileLength)
const completed = prettyBytes(fileDownloaded)
const downloadSpeed = prettyBytes(prog.downloadSpeed || 0)
const uploadSpeed = prettyBytes(prog.uploadSpeed || 0)
let sizes
if (fileProgress < 1) {
sizes = <span> | {completed} / {total}</span>
} else {
sizes = <span> | {completed}</span>
}
return (
<div key='download-progress'>
<span className='progress'>{progress}% downloaded {sizes}</span>
<br />
<span>↓ {downloadSpeed}/s ↑ {uploadSpeed}/s | {prog.numPeers || 0} peer(s)</span>
<br />
{renderEta(fileLength, fileDownloaded)}
</div>
)
}
return (
<div key='cast' className='letterbox' style={style}>
<div className='cast-screen'>
<i className='icon'>{castIcon}</i>
<div key='type' className='cast-type'>{castType}</div>
<div key='status' className='cast-status'>{castStatus}</div>
<div key='name' className='name'>{fileName}</div>
{renderDownloadProgress()}
</div>
</div>
)
@@ -536,6 +591,8 @@ function renderPlayerControls (state) {
const nextClass = Playlist.hasNext(state) ? '' : 'disabled'
const elements = [
renderPreview(state),
<div key='playback-bar' className='playback-bar'>
{renderLoadingBar(state)}
<div
@@ -547,6 +604,8 @@ function renderPlayerControls (state) {
key='scrub-bar'
className='scrub-bar'
draggable
onMouseMove={handleScrubPreview}
onMouseOut={clearPreview}
onDragStart={handleDragStart}
onClick={handleScrub}
onDrag={handleScrub}
@@ -655,10 +714,14 @@ function renderPlayerControls (state) {
// Render volume slider
const volume = state.playing.volume
const volumeIcon = 'volume_' + (
volume === 0 ? 'off'
: volume < 0.3 ? 'mute'
: volume < 0.6 ? 'down'
: 'up')
volume === 0
? 'off'
: volume < 0.3
? 'mute'
: volume < 0.6
? 'down'
: 'up'
)
const volumeStyle = {
background: '-webkit-gradient(linear, left top, right top, ' +
'color-stop(' + (volume * 100) + '%, #eee), ' +
@@ -722,6 +785,19 @@ function renderPlayerControls (state) {
}
}
// Handles a scrub hover (preview another position in the video)
function handleScrubPreview (e) {
// Only show for videos
if (!e.clientX || state.playing.type !== 'video') return
dispatch('mediaMouseMoved')
dispatch('preview', e.clientX)
}
function clearPreview (e) {
if (state.playing.type !== 'video') return
dispatch('clearPreview')
}
// Handles a click or drag to scrub (jump to another position in the video)
function handleScrub (e) {
if (!e.clientX) return
@@ -760,6 +836,56 @@ function renderPlayerControls (state) {
}
}
function renderPreview (state) {
const { previewXCoord = null } = state.playing
// Calculate time from x-coord as fraction of track width
const windowWidth = document.querySelector('body').clientWidth
const fraction = previewXCoord / windowWidth
const time = fraction * state.playing.duration /* seconds */
const height = 70
let width = 0
const previewEl = document.querySelector('video#preview')
if (previewEl !== null && previewXCoord !== null) {
previewEl.currentTime = time
// Auto adjust width to maintain video aspect ratio
width = Math.floor((previewEl.videoWidth / previewEl.videoHeight) * height)
}
// Center preview window on mouse cursor,
// while avoiding falling off the left or right edges
const xPos = Math.min(Math.max(previewXCoord - (width / 2), 5), windowWidth - width - 5)
return (
<div
key='preview' style={{
position: 'absolute',
bottom: 50,
left: xPos,
display: previewXCoord == null && 'none' // Hide preview when XCoord unset
}}
>
<div style={{ width, height, backgroundColor: 'black' }}>
<video
src={Playlist.getCurrentLocalURL(state)}
id='preview'
style={{ border: '1px solid lightgrey', borderRadius: 2 }}
/>
</div>
<p
style={{
textAlign: 'center', margin: 5, textShadow: '0 0 2px rgba(0,0,0,.5)', color: '#eee'
}}
>
{formatTime(time, state.playing.duration)}
</p>
</div>
)
}
// Renders the loading bar. Shows which parts of the torrent are loaded, which
// can be 'spongey' / non-contiguous
function renderLoadingBar (state) {
@@ -779,7 +905,7 @@ function renderLoadingBar (state) {
const parts = []
let lastPiecePresent = false
for (let i = fileProg.startPiece; i <= fileProg.endPiece; i++) {
const partPresent = Bitfield.prototype.get.call(prog.bitfield, i)
const partPresent = BitField.prototype.get.call(prog.bitfield, i)
if (partPresent && !lastPiecePresent) {
parts.push({ start: i - fileProg.startPiece, count: 1 })
} else if (partPresent) {

View File

@@ -5,7 +5,7 @@ console.time('init')
const crypto = require('crypto')
const util = require('util')
const defaultAnnounceList = require('create-torrent').announceList
const electron = require('electron')
const { ipcRenderer } = require('electron')
const fs = require('fs')
const mm = require('music-metadata')
const networkAddress = require('network-address')
@@ -16,9 +16,6 @@ const config = require('../config')
const { TorrentKeyNotFoundError } = require('./lib/errors')
const torrentPoster = require('./lib/torrent-poster')
// Send & receive messages from the main window
const ipc = electron.ipcRenderer
// Force use of webtorrent trackers on all torrents
global.WEBTORRENT_ANNOUNCE = defaultAnnounceList
.map((arr) => arr[0])
@@ -68,29 +65,29 @@ init()
function init () {
listenToClientEvents()
ipc.on('wt-start-torrenting', (e, torrentKey, torrentID, path, fileModtimes, selections) =>
ipcRenderer.on('wt-start-torrenting', (e, torrentKey, torrentID, path, fileModtimes, selections) =>
startTorrenting(torrentKey, torrentID, path, fileModtimes, selections))
ipc.on('wt-stop-torrenting', (e, infoHash) =>
ipcRenderer.on('wt-stop-torrenting', (e, infoHash) =>
stopTorrenting(infoHash))
ipc.on('wt-create-torrent', (e, torrentKey, options) =>
ipcRenderer.on('wt-create-torrent', (e, torrentKey, options) =>
createTorrent(torrentKey, options))
ipc.on('wt-save-torrent-file', (e, torrentKey) =>
ipcRenderer.on('wt-save-torrent-file', (e, torrentKey) =>
saveTorrentFile(torrentKey))
ipc.on('wt-generate-torrent-poster', (e, torrentKey) =>
ipcRenderer.on('wt-generate-torrent-poster', (e, torrentKey) =>
generateTorrentPoster(torrentKey))
ipc.on('wt-get-audio-metadata', (e, infoHash, index) =>
ipcRenderer.on('wt-get-audio-metadata', (e, infoHash, index) =>
getAudioMetadata(infoHash, index))
ipc.on('wt-start-server', (e, infoHash) =>
ipcRenderer.on('wt-start-server', (e, infoHash) =>
startServer(infoHash))
ipc.on('wt-stop-server', (e) =>
ipcRenderer.on('wt-stop-server', (e) =>
stopServer())
ipc.on('wt-select-files', (e, infoHash, selections) =>
ipcRenderer.on('wt-select-files', (e, infoHash, selections) =>
selectFiles(infoHash, selections))
ipc.send('ipcReadyWebTorrent')
ipcRenderer.send('ipcReadyWebTorrent')
window.addEventListener('error', (e) =>
ipc.send('wt-uncaught-error', { message: e.error.message, stack: e.error.stack }),
ipcRenderer.send('wt-uncaught-error', { message: e.error.message, stack: e.error.stack }),
true)
setInterval(updateTorrentProgress, 1000)
@@ -98,8 +95,8 @@ function init () {
}
function listenToClientEvents () {
client.on('warning', (err) => ipc.send('wt-warning', null, err.message))
client.on('error', (err) => ipc.send('wt-error', null, err.message))
client.on('warning', (err) => ipcRenderer.send('wt-warning', null, err.message))
client.on('error', (err) => ipcRenderer.send('wt-error', null, err.message))
}
// Starts a given TorrentID, which can be an infohash, magnet URI, etc.
@@ -133,44 +130,44 @@ function createTorrent (torrentKey, options) {
const torrent = client.seed(paths, options)
torrent.key = torrentKey
addTorrentEvents(torrent)
ipc.send('wt-new-torrent')
ipcRenderer.send('wt-new-torrent')
}
function addTorrentEvents (torrent) {
torrent.on('warning', (err) =>
ipc.send('wt-warning', torrent.key, err.message))
ipcRenderer.send('wt-warning', torrent.key, err.message))
torrent.on('error', (err) =>
ipc.send('wt-error', torrent.key, err.message))
ipcRenderer.send('wt-error', torrent.key, err.message))
torrent.on('infoHash', () =>
ipc.send('wt-parsed', torrent.key, torrent.infoHash, torrent.magnetURI))
ipcRenderer.send('wt-parsed', torrent.key, torrent.infoHash, torrent.magnetURI))
torrent.on('metadata', torrentMetadata)
torrent.on('ready', torrentReady)
torrent.on('done', torrentDone)
function torrentMetadata () {
const info = getTorrentInfo(torrent)
ipc.send('wt-metadata', torrent.key, info)
ipcRenderer.send('wt-metadata', torrent.key, info)
updateTorrentProgress()
}
function torrentReady () {
const info = getTorrentInfo(torrent)
ipc.send('wt-ready', torrent.key, info)
ipc.send('wt-ready-' + torrent.infoHash, torrent.key, info)
ipcRenderer.send('wt-ready', torrent.key, info)
ipcRenderer.send('wt-ready-' + torrent.infoHash, torrent.key, info)
updateTorrentProgress()
}
function torrentDone () {
const info = getTorrentInfo(torrent)
ipc.send('wt-done', torrent.key, info)
ipcRenderer.send('wt-done', torrent.key, info)
updateTorrentProgress()
torrent.getFileModtimes(function (err, fileModtimes) {
if (err) return onError(err)
ipc.send('wt-file-modtimes', torrent.key, fileModtimes)
ipcRenderer.send('wt-file-modtimes', torrent.key, fileModtimes)
})
}
}
@@ -207,7 +204,7 @@ function saveTorrentFile (torrentKey) {
const fileName = torrent.infoHash + '.torrent'
if (!err) {
// We've already saved the file
return ipc.send('wt-file-saved', torrentKey, fileName)
return ipcRenderer.send('wt-file-saved', torrentKey, fileName)
}
// Otherwise, save the .torrent file, under the app config folder
@@ -215,7 +212,7 @@ function saveTorrentFile (torrentKey) {
fs.writeFile(torrentPath, torrent.torrentFile, function (err) {
if (err) return console.log('error saving torrent file %s: %o', torrentPath, err)
console.log('saved torrent file %s', torrentPath)
return ipc.send('wt-file-saved', torrentKey, fileName)
return ipcRenderer.send('wt-file-saved', torrentKey, fileName)
})
})
})
@@ -235,7 +232,7 @@ function generateTorrentPoster (torrentKey) {
fs.writeFile(posterFilePath, buf, function (err) {
if (err) return console.log('error saving poster: %o', err)
// show the poster
ipc.send('wt-poster', torrentKey, posterFileName)
ipcRenderer.send('wt-poster', torrentKey, posterFileName)
})
})
})
@@ -247,7 +244,7 @@ function updateTorrentProgress () {
if (prevProgress && util.isDeepStrictEqual(progress, prevProgress)) {
return /* don't send heavy object if it hasn't changed */
}
ipc.send('wt-progress', progress)
ipcRenderer.send('wt-progress', progress)
prevProgress = progress
}
@@ -317,8 +314,8 @@ function startServerFromReadyTorrent (torrent, cb) {
networkAddress: networkAddress()
}
ipc.send('wt-server-running', info)
ipc.send('wt-server-' + torrent.infoHash, info)
ipcRenderer.send('wt-server-running', info)
ipcRenderer.send('wt-server-' + torrent.infoHash, info)
})
}
@@ -336,14 +333,14 @@ function getAudioMetadata (infoHash, index) {
// Set initial matadata to display the filename first.
const metadata = { title: file.name }
ipc.send('wt-audio-metadata', infoHash, index, metadata)
ipcRenderer.send('wt-audio-metadata', infoHash, index, metadata)
const options = {
native: false,
skipCovers: true,
fileSize: file.length,
observer: event => {
ipc.send('wt-audio-metadata', infoHash, index, {
ipcRenderer.send('wt-audio-metadata', infoHash, index, {
common: metadata.common,
format: metadata.format
})
@@ -358,7 +355,7 @@ function getAudioMetadata (infoHash, index) {
onMetadata
.then(
metadata => {
ipc.send('wt-audio-metadata', infoHash, index, metadata)
ipcRenderer.send('wt-audio-metadata', infoHash, index, metadata)
console.log(`metadata for file='${file.name}' completed.`)
},
err => {

View File

@@ -10,7 +10,7 @@ Actions=CreateNewTorrent;OpenTorrentFile;OpenTorrentAddress;
<% if (mimeType && mimeType.length) { %>MimeType=<%= mimeType.join(';') %>;<% } %>
<% if (categories && categories.length) { %>Categories=<%= categories.join(';') %>;<% } %>
StartupNotify=true
<% if (name) { %>StartupWMClass=<%= name %> <% } %>
StartupWMClass=<%= productName %>
[Desktop Action CreateNewTorrent]
Name=Create New Torrent...

View File

@@ -558,6 +558,13 @@ body.drag .app::after {
width: 100%;
}
.player .name {
font-size: 20px;
font-weight: bold;
line-height: 1.5em;
margin-bottom: 6px;
}
/*
* PLAYER CONTROLS
*/