Fix default torrents

Big Buck Bunny playable now, files show correctly even before the user starts torrenting
This commit is contained in:
DC
2016-03-21 01:45:57 -07:00
parent 720c9f4625
commit d520a9e4bc
9 changed files with 87 additions and 36 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

Binary file not shown.

BIN
static/tearsOfSteel.torrent Normal file

Binary file not shown.