Keep all torrent files and poster images in app config folder
Fixes #402
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
"drag-drop": "^2.11.0",
|
"drag-drop": "^2.11.0",
|
||||||
"electron-localshortcut": "^0.6.0",
|
"electron-localshortcut": "^0.6.0",
|
||||||
"electron-prebuilt": "0.37.6",
|
"electron-prebuilt": "0.37.6",
|
||||||
|
"fs-extra": "^0.27.0",
|
||||||
"hyperx": "^2.0.2",
|
"hyperx": "^2.0.2",
|
||||||
"languagedetect": "^1.1.1",
|
"languagedetect": "^1.1.1",
|
||||||
"main-loop": "^3.2.0",
|
"main-loop": "^3.2.0",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ var appConfig = require('application-config')('WebTorrent')
|
|||||||
var concat = require('concat-stream')
|
var concat = require('concat-stream')
|
||||||
var dragDrop = require('drag-drop')
|
var dragDrop = require('drag-drop')
|
||||||
var electron = require('electron')
|
var electron = require('electron')
|
||||||
var fs = require('fs')
|
var fs = require('fs-extra')
|
||||||
var mainLoop = require('main-loop')
|
var mainLoop = require('main-loop')
|
||||||
var path = require('path')
|
var path = require('path')
|
||||||
var srtToVtt = require('srt-to-vtt')
|
var srtToVtt = require('srt-to-vtt')
|
||||||
@@ -21,7 +21,7 @@ var errors = require('./lib/errors')
|
|||||||
var sound = require('./lib/sound')
|
var sound = require('./lib/sound')
|
||||||
var State = require('./state')
|
var State = require('./state')
|
||||||
var TorrentPlayer = require('./lib/torrent-player')
|
var TorrentPlayer = require('./lib/torrent-player')
|
||||||
var util = require('./util')
|
var TorrentSummary = require('./lib/torrent-summary')
|
||||||
|
|
||||||
var {setDispatch} = require('./lib/dispatcher')
|
var {setDispatch} = require('./lib/dispatcher')
|
||||||
setDispatch(dispatch)
|
setDispatch(dispatch)
|
||||||
@@ -61,6 +61,9 @@ loadState(init)
|
|||||||
* the dock icon and drag+drop.
|
* the dock icon and drag+drop.
|
||||||
*/
|
*/
|
||||||
function init () {
|
function init () {
|
||||||
|
// Clean up the freshly-loaded config file, which may be from an older version
|
||||||
|
cleanUpConfig()
|
||||||
|
|
||||||
// Push the first page into the location history
|
// Push the first page into the location history
|
||||||
state.location.go({ url: 'home' })
|
state.location.go({ url: 'home' })
|
||||||
|
|
||||||
@@ -114,6 +117,46 @@ function delayedInit () {
|
|||||||
sound.preload()
|
sound.preload()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change `state.saved` (which will be saved back to config.json on exit) as
|
||||||
|
// needed, for example to deal with config.json format changes across versions
|
||||||
|
function cleanUpConfig () {
|
||||||
|
state.saved.torrents.forEach(function (ts) {
|
||||||
|
var infoHash = ts.infoHash
|
||||||
|
|
||||||
|
// Migration: replace torrentPath with torrentFileName
|
||||||
|
var src, dst
|
||||||
|
if (ts.torrentPath) {
|
||||||
|
console.log('migration: replacing torrentPath %s', ts.torrentPath)
|
||||||
|
src = path.isAbsolute(ts.torrentPath)
|
||||||
|
? ts.torrentPath
|
||||||
|
: path.join(config.STATIC_PATH, ts.torrentPath)
|
||||||
|
dst = path.join(config.CONFIG_TORRENT_PATH, infoHash + '.torrent')
|
||||||
|
// Synchronous FS calls aren't ideal, but probably OK in a migration
|
||||||
|
// that only runs once
|
||||||
|
if (src !== dst) fs.copySync(src, dst)
|
||||||
|
|
||||||
|
delete ts.torrentPath
|
||||||
|
ts.torrentFileName = infoHash + '.torrent'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Migration: replace posterURL with posterFileName
|
||||||
|
if (ts.posterURL) {
|
||||||
|
console.log('migration: replacing posterURL %s', ts.posterURL)
|
||||||
|
var extension = path.extname(ts.posterURL)
|
||||||
|
src = path.isAbsolute(ts.posterURL)
|
||||||
|
? ts.posterURL
|
||||||
|
: path.join(config.STATIC_PATH, ts.posterURL)
|
||||||
|
dst = path.join(config.CONFIG_POSTER_PATH, infoHash + extension)
|
||||||
|
// Synchronous FS calls aren't ideal, but probably OK in a migration
|
||||||
|
// that only runs once
|
||||||
|
if (src !== dst) fs.copySync(src, dst)
|
||||||
|
|
||||||
|
delete ts.posterURL
|
||||||
|
ts.posterFileName = infoHash + extension
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Lazily loads Chromecast and Airplay support
|
// Lazily loads Chromecast and Airplay support
|
||||||
function lazyLoadCast () {
|
function lazyLoadCast () {
|
||||||
if (!Cast) {
|
if (!Cast) {
|
||||||
@@ -574,8 +617,8 @@ function startTorrentingSummary (torrentSummary) {
|
|||||||
var path = s.path || state.saved.downloadPath
|
var path = s.path || state.saved.downloadPath
|
||||||
|
|
||||||
var torrentID
|
var torrentID
|
||||||
if (s.torrentPath) { // Load torrent file from disk
|
if (s.torrentFileName) { // Load torrent file from disk
|
||||||
torrentID = util.getAbsoluteStaticPath(s.torrentPath)
|
torrentID = TorrentSummary.getTorrentPath(torrentSummary)
|
||||||
} else { // Load torrent from DHT
|
} else { // Load torrent from DHT
|
||||||
torrentID = s.magnetURI || s.infoHash
|
torrentID = s.magnetURI || s.infoHash
|
||||||
}
|
}
|
||||||
@@ -696,10 +739,10 @@ function torrentMetadata (torrentKey, torrentInfo) {
|
|||||||
update()
|
update()
|
||||||
|
|
||||||
// Save the .torrent file, if it hasn't been saved already
|
// Save the .torrent file, if it hasn't been saved already
|
||||||
if (!torrentSummary.torrentPath) ipcRenderer.send('wt-save-torrent-file', torrentKey)
|
if (!torrentSummary.torrentFileName) ipcRenderer.send('wt-save-torrent-file', torrentKey)
|
||||||
|
|
||||||
// Auto-generate a poster image, if it hasn't been generated already
|
// Auto-generate a poster image, if it hasn't been generated already
|
||||||
if (!torrentSummary.posterURL) ipcRenderer.send('wt-generate-torrent-poster', torrentKey)
|
if (!torrentSummary.posterFileName) ipcRenderer.send('wt-generate-torrent-poster', torrentKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
function torrentDone (torrentKey, torrentInfo) {
|
function torrentDone (torrentKey, torrentInfo) {
|
||||||
@@ -752,16 +795,16 @@ function torrentFileModtimes (torrentKey, fileModtimes) {
|
|||||||
saveStateThrottled()
|
saveStateThrottled()
|
||||||
}
|
}
|
||||||
|
|
||||||
function torrentFileSaved (torrentKey, torrentPath) {
|
function torrentFileSaved (torrentKey, torrentFileName) {
|
||||||
console.log('torrent file saved %s: %s', torrentKey, torrentPath)
|
console.log('torrent file saved %s: %s', torrentKey, torrentFileName)
|
||||||
var torrentSummary = getTorrentSummary(torrentKey)
|
var torrentSummary = getTorrentSummary(torrentKey)
|
||||||
torrentSummary.torrentPath = torrentPath
|
torrentSummary.torrentFileName = torrentFileName
|
||||||
saveStateThrottled()
|
saveStateThrottled()
|
||||||
}
|
}
|
||||||
|
|
||||||
function torrentPosterSaved (torrentKey, posterPath) {
|
function torrentPosterSaved (torrentKey, posterFileName) {
|
||||||
var torrentSummary = getTorrentSummary(torrentKey)
|
var torrentSummary = getTorrentSummary(torrentKey)
|
||||||
torrentSummary.posterURL = posterPath
|
torrentSummary.posterFileName = posterFileName
|
||||||
saveStateThrottled()
|
saveStateThrottled()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -967,7 +1010,7 @@ function saveTorrentFileAs (torrentSummary) {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
dialog.showSaveDialog(remote.getCurrentWindow(), opts, function (savePath) {
|
dialog.showSaveDialog(remote.getCurrentWindow(), opts, function (savePath) {
|
||||||
var torrentPath = util.getAbsoluteStaticPath(torrentSummary.torrentPath)
|
var torrentPath = TorrentSummary.getTorrentPath(torrentSummary)
|
||||||
fs.readFile(torrentPath, function (err, torrentFile) {
|
fs.readFile(torrentPath, function (err, torrentFile) {
|
||||||
if (err) return onError(err)
|
if (err) return onError(err)
|
||||||
fs.writeFile(savePath, torrentFile, function (err) {
|
fs.writeFile(savePath, torrentFile, function (err) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ function torrentPoster (torrent, cb) {
|
|||||||
|
|
||||||
function getLargestFileByExtension (torrent, extensions) {
|
function getLargestFileByExtension (torrent, extensions) {
|
||||||
var files = torrent.files.filter(function (file) {
|
var files = torrent.files.filter(function (file) {
|
||||||
var extname = path.extname(file.name)
|
var extname = path.extname(file.name).toLowerCase()
|
||||||
return extensions.indexOf(extname) !== -1
|
return extensions.indexOf(extname) !== -1
|
||||||
})
|
})
|
||||||
if (files.length === 0) return undefined
|
if (files.length === 0) return undefined
|
||||||
|
|||||||
24
renderer/lib/torrent-summary.js
Normal file
24
renderer/lib/torrent-summary.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
module.exports = {
|
||||||
|
getPosterPath,
|
||||||
|
getTorrentPath
|
||||||
|
}
|
||||||
|
|
||||||
|
var path = require('path')
|
||||||
|
var config = require('../../config')
|
||||||
|
|
||||||
|
// Expects a torrentSummary
|
||||||
|
// Returns an absolute path to the torrent file, or null if unavailable
|
||||||
|
function getTorrentPath (torrentSummary) {
|
||||||
|
if (!torrentSummary || !torrentSummary.torrentFileName) return null
|
||||||
|
return path.join(config.CONFIG_TORRENT_PATH, torrentSummary.torrentFileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expects a torrentSummary
|
||||||
|
// Returns an absolute path to the poster image, or null if unavailable
|
||||||
|
function getPosterPath (torrentSummary) {
|
||||||
|
if (!torrentSummary || !torrentSummary.posterFileName) return null
|
||||||
|
var posterPath = path.join(config.CONFIG_POSTER_PATH, torrentSummary.posterFileName)
|
||||||
|
// Work around a Chrome bug (reproduced in vanilla Chrome, not just Electron):
|
||||||
|
// Backslashes in URLS in CSS cause bizarre string encoding issues
|
||||||
|
return posterPath.replace(/\\/g, '/')
|
||||||
|
}
|
||||||
@@ -45,6 +45,7 @@ function getInitialState () {
|
|||||||
/*
|
/*
|
||||||
* Saved state is read from and written to a file every time the app runs.
|
* Saved state is read from and written to a file every time the app runs.
|
||||||
* It should be simple and minimal and must be JSON.
|
* It should be simple and minimal and must be JSON.
|
||||||
|
* It must never contain absolute paths since we have a portable app.
|
||||||
*
|
*
|
||||||
* Config path:
|
* Config path:
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
var path = require('path')
|
|
||||||
|
|
||||||
var config = require('../config')
|
|
||||||
|
|
||||||
exports.getAbsoluteStaticPath = function (filePath) {
|
|
||||||
return path.isAbsolute(filePath)
|
|
||||||
? filePath
|
|
||||||
: path.join(config.STATIC_PATH, filePath)
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,7 @@ var hx = hyperx(h)
|
|||||||
var prettyBytes = require('prettier-bytes')
|
var prettyBytes = require('prettier-bytes')
|
||||||
var Bitfield = require('bitfield')
|
var Bitfield = require('bitfield')
|
||||||
|
|
||||||
var util = require('../util')
|
var TorrentSummary = require('../lib/torrent-summary')
|
||||||
var {dispatch, dispatcher} = require('../lib/dispatcher')
|
var {dispatch, dispatcher} = require('../lib/dispatcher')
|
||||||
|
|
||||||
// Shows a streaming video player. Standard features + Chromecast + Airplay
|
// Shows a streaming video player. Standard features + Chromecast + Airplay
|
||||||
@@ -499,10 +499,9 @@ function renderLoadingBar (state) {
|
|||||||
// Returns the CSS background-image string for a poster image + dark vignette
|
// Returns the CSS background-image string for a poster image + dark vignette
|
||||||
function cssBackgroundImagePoster (state) {
|
function cssBackgroundImagePoster (state) {
|
||||||
var torrentSummary = getPlayingTorrentSummary(state)
|
var torrentSummary = getPlayingTorrentSummary(state)
|
||||||
if (!torrentSummary || !torrentSummary.posterURL) return ''
|
var posterPath = TorrentSummary.getPosterPath(torrentSummary)
|
||||||
var posterURL = util.getAbsoluteStaticPath(torrentSummary.posterURL)
|
if (!posterPath) return ''
|
||||||
var cleanURL = posterURL.replace(/\\/g, '/')
|
return cssBackgroundImageDarkGradient() + `, url(${posterPath})`
|
||||||
return cssBackgroundImageDarkGradient() + `, url(${cleanURL})`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function cssBackgroundImageDarkGradient () {
|
function cssBackgroundImageDarkGradient () {
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ var hyperx = require('hyperx')
|
|||||||
var hx = hyperx(h)
|
var hx = hyperx(h)
|
||||||
var prettyBytes = require('prettier-bytes')
|
var prettyBytes = require('prettier-bytes')
|
||||||
|
|
||||||
var util = require('../util')
|
var TorrentSummary = require('../lib/torrent-summary')
|
||||||
|
|
||||||
var TorrentPlayer = require('../lib/torrent-player')
|
var TorrentPlayer = require('../lib/torrent-player')
|
||||||
var {dispatcher} = require('../lib/dispatcher')
|
var {dispatcher} = require('../lib/dispatcher')
|
||||||
|
|
||||||
@@ -31,15 +30,12 @@ function TorrentList (state) {
|
|||||||
|
|
||||||
// Background image: show some nice visuals, like a frame from the movie, if possible
|
// Background image: show some nice visuals, like a frame from the movie, if possible
|
||||||
var style = {}
|
var style = {}
|
||||||
if (torrentSummary.posterURL) {
|
if (torrentSummary.posterFileName) {
|
||||||
var gradient = isSelected
|
var gradient = isSelected
|
||||||
? 'linear-gradient(to bottom, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.4) 100%)'
|
? 'linear-gradient(to bottom, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.4) 100%)'
|
||||||
: 'linear-gradient(to bottom, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 100%)'
|
: 'linear-gradient(to bottom, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 100%)'
|
||||||
var posterURL = util.getAbsoluteStaticPath(torrentSummary.posterURL)
|
var posterPath = TorrentSummary.getPosterPath(torrentSummary)
|
||||||
// Work around a Chrome bug (reproduced in vanilla Chrome, not just Electron):
|
style.backgroundImage = gradient + `, url('${posterPath}')`
|
||||||
// Backslashes in URLS in CSS cause bizarre string encoding issues
|
|
||||||
var cleanURL = posterURL.replace(/\\/g, '/')
|
|
||||||
style.backgroundImage = gradient + `, url('${cleanURL}')`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Foreground: name of the torrent, basic info like size, play button,
|
// Foreground: name of the torrent, basic info like size, play button,
|
||||||
|
|||||||
@@ -159,9 +159,10 @@ function getTorrentFileInfo (file) {
|
|||||||
function saveTorrentFile (torrentKey) {
|
function saveTorrentFile (torrentKey) {
|
||||||
var torrent = getTorrent(torrentKey)
|
var torrent = getTorrent(torrentKey)
|
||||||
checkIfTorrentFileExists(torrent.infoHash, function (torrentPath, exists) {
|
checkIfTorrentFileExists(torrent.infoHash, function (torrentPath, exists) {
|
||||||
|
var fileName = torrent.infoHash + '.torrent'
|
||||||
if (exists) {
|
if (exists) {
|
||||||
// We've already saved the file
|
// We've already saved the file
|
||||||
return ipc.send('wt-file-saved', torrentKey, torrentPath)
|
return ipc.send('wt-file-saved', torrentKey, fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, save the .torrent file, under the app config folder
|
// Otherwise, save the .torrent file, under the app config folder
|
||||||
@@ -169,7 +170,7 @@ function saveTorrentFile (torrentKey) {
|
|||||||
fs.writeFile(torrentPath, torrent.torrentFile, function (err) {
|
fs.writeFile(torrentPath, torrent.torrentFile, function (err) {
|
||||||
if (err) return console.log('error saving torrent file %s: %o', torrentPath, err)
|
if (err) return console.log('error saving torrent file %s: %o', torrentPath, err)
|
||||||
console.log('saved torrent file %s', torrentPath)
|
console.log('saved torrent file %s', torrentPath)
|
||||||
return ipc.send('wt-file-saved', torrentKey, torrentPath)
|
return ipc.send('wt-file-saved', torrentKey, fileName)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -193,11 +194,12 @@ function generateTorrentPoster (torrentKey) {
|
|||||||
// save it for next time
|
// save it for next time
|
||||||
mkdirp(config.CONFIG_POSTER_PATH, function (err) {
|
mkdirp(config.CONFIG_POSTER_PATH, function (err) {
|
||||||
if (err) return console.log('error creating poster dir: %o', err)
|
if (err) return console.log('error creating poster dir: %o', err)
|
||||||
var posterFilePath = path.join(config.CONFIG_POSTER_PATH, torrent.infoHash + extension)
|
var posterFileName = torrent.infoHash + extension
|
||||||
|
var posterFilePath = path.join(config.CONFIG_POSTER_PATH, posterFileName)
|
||||||
fs.writeFile(posterFilePath, buf, function (err) {
|
fs.writeFile(posterFilePath, buf, function (err) {
|
||||||
if (err) return console.log('error saving poster: %o', err)
|
if (err) return console.log('error saving poster: %o', err)
|
||||||
// show the poster
|
// show the poster
|
||||||
ipc.send('wt-poster', torrentKey, posterFilePath)
|
ipc.send('wt-poster', torrentKey, posterFileName)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user