Fix default torrents
Big Buck Bunny playable now, files show correctly even before the user starts torrenting
This commit is contained in:
@@ -545,6 +545,10 @@ body.drag .torrent-placeholder span {
|
|||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.torrent-details tr {
|
||||||
|
height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
.torrent-details tr:hover,
|
.torrent-details tr:hover,
|
||||||
.torrent-details .open-folder:hover {
|
.torrent-details .open-folder:hover {
|
||||||
background-color: rgba(200, 200, 200, 0.3);
|
background-color: rgba(200, 200, 200, 0.3);
|
||||||
@@ -553,6 +557,7 @@ body.drag .torrent-placeholder span {
|
|||||||
.torrent-details td {
|
.torrent-details td {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
vertical-align: bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
.torrent-details td.col-icon {
|
.torrent-details td.col-icon {
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ function init () {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
resumeTorrents() /* restart everything we were torrenting last time the app ran */
|
resumeTorrents() /* restart everything we were torrenting last time the app ran */
|
||||||
|
setInterval(updateTorrentProgress, 1000)
|
||||||
|
|
||||||
// The UI is built with virtual-dom, a minimalist library extracted from React
|
// The UI is built with virtual-dom, a minimalist library extracted from React
|
||||||
// The concepts--one way data flow, a pure function that renders state to a
|
// The concepts--one way data flow, a pure function that renders state to a
|
||||||
@@ -421,6 +422,7 @@ function startTorrentingSummary (torrentSummary) {
|
|||||||
// Starts a given TorrentID, which can be an infohash, magnet URI, etc. Returns WebTorrent object
|
// Starts a given TorrentID, which can be an infohash, magnet URI, etc. Returns WebTorrent object
|
||||||
// See https://github.com/feross/webtorrent/blob/master/docs/api.md#clientaddtorrentid-opts-function-ontorrent-torrent-
|
// See https://github.com/feross/webtorrent/blob/master/docs/api.md#clientaddtorrentid-opts-function-ontorrent-torrent-
|
||||||
function startTorrentingID (torrentID) {
|
function startTorrentingID (torrentID) {
|
||||||
|
console.log('Starting torrent ' + torrentID)
|
||||||
var torrent = state.client.add(torrentID, {
|
var torrent = state.client.add(torrentID, {
|
||||||
path: state.saved.downloadPath // Use downloads folder
|
path: state.saved.downloadPath // Use downloads folder
|
||||||
})
|
})
|
||||||
@@ -448,35 +450,67 @@ function addTorrentEvents (torrent) {
|
|||||||
torrent.on('done', torrentDone)
|
torrent.on('done', torrentDone)
|
||||||
|
|
||||||
function torrentReady () {
|
function torrentReady () {
|
||||||
|
// Summarize torrent
|
||||||
var torrentSummary = getTorrentSummary(torrent.infoHash)
|
var torrentSummary = getTorrentSummary(torrent.infoHash)
|
||||||
torrentSummary.status = 'downloading'
|
torrentSummary.status = 'downloading'
|
||||||
torrentSummary.ready = true
|
torrentSummary.ready = true
|
||||||
torrentSummary.name = torrentSummary.displayName || torrent.name
|
torrentSummary.name = torrentSummary.displayName || torrent.name
|
||||||
torrentSummary.infoHash = torrent.infoHash
|
torrentSummary.infoHash = torrent.infoHash
|
||||||
|
|
||||||
|
// Summarize torrent files
|
||||||
torrentSummary.files = torrent.files.map(summarizeFileInTorrent)
|
torrentSummary.files = torrent.files.map(summarizeFileInTorrent)
|
||||||
|
updateTorrentProgress()
|
||||||
|
|
||||||
saveTorrentFile(torrentSummary, torrent)
|
// Save the .torrent file, if it hasn't been saved already
|
||||||
|
if (!torrentSummary.torrentPath) saveTorrentFile(torrentSummary, torrent)
|
||||||
|
|
||||||
if (!torrentSummary.posterURL) {
|
// Auto-generate a poster image, if it hasn't been generated already
|
||||||
generateTorrentPoster(torrent, torrentSummary)
|
if (!torrentSummary.posterURL) generateTorrentPoster(torrent, torrentSummary)
|
||||||
}
|
|
||||||
|
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
function torrentDone () {
|
function torrentDone () {
|
||||||
|
// UPdate the torrent summary
|
||||||
var torrentSummary = getTorrentSummary(torrent.infoHash)
|
var torrentSummary = getTorrentSummary(torrent.infoHash)
|
||||||
torrentSummary.status = 'seeding'
|
torrentSummary.status = 'seeding'
|
||||||
|
updateTorrentProgress()
|
||||||
|
|
||||||
|
// Notify the user that a torrent finished
|
||||||
if (!state.window.isFocused) {
|
if (!state.window.isFocused) {
|
||||||
state.dock.badge += 1
|
state.dock.badge += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
showDoneNotification(torrent)
|
showDoneNotification(torrent)
|
||||||
|
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateTorrentProgress () {
|
||||||
|
// TODO: ideally this would be tracked by WebTorrent, which could do it
|
||||||
|
// more efficiently than looping over torrent.bitfield
|
||||||
|
var changed = false
|
||||||
|
state.client.torrents.forEach(function (torrent) {
|
||||||
|
var torrentSummary = getTorrentSummary(torrent.infoHash)
|
||||||
|
torrent.files.forEach(function (file, index) {
|
||||||
|
var numPieces = file._endPiece - file._startPiece + 1
|
||||||
|
var numPiecesPresent = 0
|
||||||
|
for (var piece = file._startPiece; piece <= file._endPiece; piece++) {
|
||||||
|
if (torrent.bitfield.get(piece)) numPiecesPresent++
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileSummary = torrentSummary.files[index]
|
||||||
|
if (fileSummary.numPiecesPresent !== numPiecesPresent || fileSummary.numPieces !== numPieces) {
|
||||||
|
fileSummary.numPieces = numPieces
|
||||||
|
fileSummary.numPiecesPresent = numPiecesPresent
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if (changed) update()
|
||||||
|
}
|
||||||
|
|
||||||
function generateTorrentPoster (torrent, torrentSummary) {
|
function generateTorrentPoster (torrent, torrentSummary) {
|
||||||
torrentPoster(torrent, function (err, buf) {
|
torrentPoster(torrent, function (err, buf) {
|
||||||
if (err) return onWarning(err)
|
if (err) return onWarning(err)
|
||||||
@@ -499,7 +533,8 @@ function summarizeFileInTorrent (file) {
|
|||||||
return {
|
return {
|
||||||
name: file.name,
|
name: file.name,
|
||||||
length: file.length,
|
length: file.length,
|
||||||
isDownloaded: false
|
numPiecesPresent: 0,
|
||||||
|
numPieces: null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ function init (callback) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
var browser = airplay.createBrowser()
|
var browser = airplay.createBrowser()
|
||||||
var devices = browser.getDevices(true)
|
|
||||||
console.log('TODO GET DEVICES RET %o', devices)
|
|
||||||
browser.on('deviceOn', function (player) {
|
browser.on('deviceOn', function (player) {
|
||||||
state.devices.airplay = player
|
state.devices.airplay = player
|
||||||
addAirplayEvents()
|
addAirplayEvents()
|
||||||
|
|||||||
@@ -63,21 +63,48 @@ module.exports = {
|
|||||||
torrents: [
|
torrents: [
|
||||||
{
|
{
|
||||||
status: 'paused',
|
status: 'paused',
|
||||||
infoHash: 'f84b51f0d2c3455ab5dabb6643b4340234cd036e',
|
infoHash: '88594aaacbde40ef3e2510c47374ec0aa396c08e',
|
||||||
displayName: 'Big Buck Bunny',
|
displayName: 'Big Buck Bunny',
|
||||||
posterURL: path.join(__dirname, '..', 'static', 'bigBuckBunny.jpg')
|
posterURL: path.join(__dirname, '..', 'static', 'bigBuckBunny.jpg'),
|
||||||
|
torrentPath: path.join(__dirname, '..', 'static', 'bigBuckBunny.torrent'),
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
'name': 'bbb_sunflower_1080p_30fps_normal.mp4',
|
||||||
|
'length': 276134947,
|
||||||
|
'numPiecesPresent': 0,
|
||||||
|
'numPieces': 527
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: 'paused',
|
status: 'paused',
|
||||||
infoHash: '6a9759bffd5c0af65319979fb7832189f4f3c35d',
|
infoHash: '6a9759bffd5c0af65319979fb7832189f4f3c35d',
|
||||||
displayName: 'Sintel',
|
displayName: 'Sintel',
|
||||||
posterURL: path.join(__dirname, '..', 'static', 'sintel.jpg')
|
posterURL: path.join(__dirname, '..', 'static', 'sintel.jpg'),
|
||||||
|
torrentPath: path.join(__dirname, '..', 'static', 'sintel.torrent'),
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
'name': 'sintel.mp4',
|
||||||
|
'length': 129241752,
|
||||||
|
'numPiecesPresent': 0,
|
||||||
|
'numPieces': 987
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: 'paused',
|
status: 'paused',
|
||||||
infoHash: '02767050e0be2fd4db9a2ad6c12416ac806ed6ed',
|
infoHash: '02767050e0be2fd4db9a2ad6c12416ac806ed6ed',
|
||||||
displayName: 'Tears of Steel',
|
displayName: 'Tears of Steel',
|
||||||
posterURL: path.join(__dirname, '..', 'static', 'tearsOfSteel.jpg')
|
posterURL: path.join(__dirname, '..', 'static', 'tearsOfSteel.jpg'),
|
||||||
|
torrentPath: path.join(__dirname, '..', 'static', 'tearsOfSteel.torrent'),
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
'name': 'tears_of_steel_1080p.webm',
|
||||||
|
'length': 571346576,
|
||||||
|
'numPiecesPresent': 0,
|
||||||
|
'numPieces': 2180
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
downloadPath: path.join(os.homedir(), 'Downloads')
|
downloadPath: path.join(os.homedir(), 'Downloads')
|
||||||
|
|||||||
@@ -131,11 +131,8 @@ function TorrentList (state, dispatch) {
|
|||||||
|
|
||||||
// Show files, per-file download status and play buttons, and so on
|
// Show files, per-file download status and play buttons, and so on
|
||||||
function renderTorrentDetails (torrent, torrentSummary) {
|
function renderTorrentDetails (torrent, torrentSummary) {
|
||||||
// If we're currently torrenting, show details directly from WebTorrent, including % downloaded
|
|
||||||
// Otherwise, show a summary of files in the torrent, if available
|
|
||||||
var files = (torrent && torrent.files) || torrentSummary.files
|
|
||||||
var filesElement
|
var filesElement
|
||||||
if (!files) {
|
if (!torrentSummary.files) {
|
||||||
// We don't know what files this torrent contains
|
// We don't know what files this torrent contains
|
||||||
var message = torrent
|
var message = torrent
|
||||||
? 'Downloading torrent data using magnet link...'
|
? 'Downloading torrent data using magnet link...'
|
||||||
@@ -143,7 +140,8 @@ function TorrentList (state, dispatch) {
|
|||||||
filesElement = hx`<div class='files warning'>${message}</div>`
|
filesElement = hx`<div class='files warning'>${message}</div>`
|
||||||
} else {
|
} else {
|
||||||
// We do know the files. List them and show download stats for each one
|
// We do know the files. List them and show download stats for each one
|
||||||
var fileRows = files.map((file, index) => renderFileRow(torrent, torrentSummary, file, index))
|
var fileRows = torrentSummary.files.map(
|
||||||
|
(file, index) => renderFileRow(torrent, torrentSummary, file, index))
|
||||||
filesElement = hx`
|
filesElement = hx`
|
||||||
<div class='files'>
|
<div class='files'>
|
||||||
<strong>Files</strong>
|
<strong>Files</strong>
|
||||||
@@ -167,39 +165,27 @@ function TorrentList (state, dispatch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show a single file in the details view for a single torrent
|
// Show a single torrentSummary file in the details view for a single torrent
|
||||||
// File can either be a WebTorrent file (if we're currently torrenting it) or an element of torrentSummary.files
|
|
||||||
function renderFileRow (torrent, torrentSummary, file, index) {
|
function renderFileRow (torrent, torrentSummary, file, index) {
|
||||||
// First, find out how much of the file we've downloaded
|
// First, find out how much of the file we've downloaded
|
||||||
// (If we're not currently torrenting, just say whether we have the file or not)
|
var isDone = file.numPiecesPresent === file.numPieces
|
||||||
if (file._startPiece) {
|
var progress = Math.round(100 * file.numPiecesPresent / (file.numPieces || 0)) + '%'
|
||||||
var numPieces = file._endPiece - file._startPiece + 1
|
|
||||||
var numPiecesPresent = 0
|
|
||||||
for (var piece = file._startPiece; piece <= file._endPiece; piece++) {
|
|
||||||
if (torrent.bitfield.get(piece)) numPiecesPresent++
|
|
||||||
}
|
|
||||||
var progress = Math.round(100 * numPiecesPresent / numPieces) + '%'
|
|
||||||
var isDone = numPieces === numPiecesPresent
|
|
||||||
} else {
|
|
||||||
var isDone = file.isDownloaded
|
|
||||||
var progress = hx`<i.icon>${isDone ? 'check' : 'close'}</i>`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second, render the file as a table row
|
// Second, render the file as a table row
|
||||||
var icon
|
var icon
|
||||||
var iconClass = ''
|
var rowClass = ''
|
||||||
if (state.playing.infoHash === torrentSummary.infoHash && state.playing.fileIndex === index) {
|
if (state.playing.infoHash === torrentSummary.infoHash && state.playing.fileIndex === index) {
|
||||||
icon = 'pause_arrow' /* playing? add option to pause */
|
icon = 'pause_arrow' /* playing? add option to pause */
|
||||||
} else if (TorrentPlayer.isPlayable(file)) {
|
} else if (TorrentPlayer.isPlayable(file)) {
|
||||||
icon = 'play_arrow' /* playable? add option to play */
|
icon = 'play_arrow' /* playable? add option to play */
|
||||||
} else {
|
} else {
|
||||||
icon = 'description' /* file icon, opens in OS default app */
|
icon = 'description' /* file icon, opens in OS default app */
|
||||||
iconClass = isDone ? '' : 'disabled'
|
rowClass = isDone ? '' : 'disabled'
|
||||||
}
|
}
|
||||||
return hx`
|
return hx`
|
||||||
<tr onclick=${handleClick}>
|
<tr onclick=${handleClick} class='${rowClass}'>
|
||||||
<td class='col-icon'>
|
<td class='col-icon'>
|
||||||
<i class='icon ${iconClass}'>${icon}</i>
|
<i class='icon'>${icon}</i>
|
||||||
</td>
|
</td>
|
||||||
<td class='col-name'>${file.name}</td>
|
<td class='col-name'>${file.name}</td>
|
||||||
<td class='col-progress'>${progress}</td>
|
<td class='col-progress'>${progress}</td>
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 316 KiB |
BIN
static/bigBuckBunny.torrent
Normal file
BIN
static/bigBuckBunny.torrent
Normal file
Binary file not shown.
Binary file not shown.
BIN
static/tearsOfSteel.torrent
Normal file
BIN
static/tearsOfSteel.torrent
Normal file
Binary file not shown.
Reference in New Issue
Block a user