Show video position on circular progress bars
This commit is contained in:
@@ -535,6 +535,11 @@ input {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.torrent .buttons .play.resume-position {
|
||||||
|
position: relative;
|
||||||
|
-webkit-clip-path: circle(18px at center);
|
||||||
|
}
|
||||||
|
|
||||||
.torrent .buttons .delete {
|
.torrent .buttons .delete {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
@@ -543,6 +548,10 @@ input {
|
|||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.torrent .buttons .radial-progress {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
.torrent .name {
|
.torrent .name {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -631,6 +640,12 @@ body.drag .app::after {
|
|||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.torrent-details td.col-icon .radial-progress {
|
||||||
|
position: absolute;
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-left: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
.torrent-details td.col-name {
|
.torrent-details td.col-name {
|
||||||
width: auto;
|
width: auto;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@@ -1015,3 +1030,66 @@ video::-webkit-media-text-track-container {
|
|||||||
.error-text {
|
.error-text {
|
||||||
color: #c44;
|
color: #c44;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RADIAL PROGRESS BAR
|
||||||
|
*/
|
||||||
|
|
||||||
|
.radial-progress {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radial-progress .circle .mask,
|
||||||
|
.radial-progress .circle .fill {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
-webkit-backface-visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radial-progress .circle .mask {
|
||||||
|
clip: rect(0px, 16px, 16px, 8px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.radial-progress .circle .fill {
|
||||||
|
clip: rect(0px, 8px, 16px, 0px);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radial-progress .inset {
|
||||||
|
position: absolute;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
margin: 2px 0 0 2px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radial-progress-large {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radial-progress-large .circle .mask,
|
||||||
|
.radial-progress-large .circle .fill {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
.radial-progress-large .circle .mask {
|
||||||
|
clip: rect(0px, 40px, 40px, 20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.radial-progress-large .circle .fill {
|
||||||
|
clip: rect(0px, 20px, 40px, 0px);
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radial-progress-large .inset {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin: 4px 0 0 4px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -562,7 +562,7 @@ function saveState () {
|
|||||||
if (key === 'progress' || key === 'torrentKey') {
|
if (key === 'progress' || key === 'torrentKey') {
|
||||||
continue // Don't save progress info or key for the webtorrent process
|
continue // Don't save progress info or key for the webtorrent process
|
||||||
}
|
}
|
||||||
if (key === 'playStatus' && x.playStatus !== 'unplayable') {
|
if (key === 'playStatus') {
|
||||||
continue // Don't save whether a torrent is playing / pending
|
continue // Don't save whether a torrent is playing / pending
|
||||||
}
|
}
|
||||||
torrent[key] = x[key]
|
torrent[key] = x[key]
|
||||||
@@ -878,6 +878,7 @@ function torrentMetadata (torrentKey, torrentInfo) {
|
|||||||
if (!torrentSummary.selections) {
|
if (!torrentSummary.selections) {
|
||||||
torrentSummary.selections = torrentSummary.files.map((x) => true)
|
torrentSummary.selections = torrentSummary.files.map((x) => true)
|
||||||
}
|
}
|
||||||
|
torrentSummary.defaultPlayFileIndex = pickFileToPlay(torrentInfo.files)
|
||||||
update()
|
update()
|
||||||
|
|
||||||
// Save the .torrent file, if it hasn't been saved already
|
// Save the .torrent file, if it hasn't been saved already
|
||||||
@@ -991,7 +992,7 @@ function openPlayer (infoHash, index, cb) {
|
|||||||
var torrentSummary = getTorrentSummary(infoHash)
|
var torrentSummary = getTorrentSummary(infoHash)
|
||||||
|
|
||||||
// automatically choose which file in the torrent to play, if necessary
|
// automatically choose which file in the torrent to play, if necessary
|
||||||
if (index === undefined) index = pickFileToPlay(torrentSummary.files)
|
if (index === undefined) index = torrentSummary.defaultPlayFileIndex
|
||||||
if (index === undefined) return cb(new errors.UnplayableError())
|
if (index === undefined) return cb(new errors.UnplayableError())
|
||||||
|
|
||||||
// update UI to show pending playback
|
// update UI to show pending playback
|
||||||
|
|||||||
@@ -118,12 +118,7 @@ function TorrentList (state) {
|
|||||||
var infoHash = torrentSummary.infoHash
|
var infoHash = torrentSummary.infoHash
|
||||||
|
|
||||||
var playIcon, playTooltip, playClass
|
var playIcon, playTooltip, playClass
|
||||||
if (torrentSummary.playStatus === 'unplayable') {
|
if (torrentSummary.playStatus === 'timeout') {
|
||||||
playIcon = 'play_arrow'
|
|
||||||
playClass = 'disabled'
|
|
||||||
playTooltip = 'Sorry, WebTorrent can\'t play any of the files in this torrent. ' +
|
|
||||||
'View details and click on individual files to open them in another program.'
|
|
||||||
} else if (torrentSummary.playStatus === 'timeout') {
|
|
||||||
playIcon = 'warning'
|
playIcon = 'warning'
|
||||||
playTooltip = 'Playback timed out. No seeds? No internet? Click to try again.'
|
playTooltip = 'Playback timed out. No seeds? No internet? Click to try again.'
|
||||||
} else {
|
} else {
|
||||||
@@ -143,6 +138,17 @@ function TorrentList (state) {
|
|||||||
downloadTooltip = 'Click to start torrenting.'
|
downloadTooltip = 'Click to start torrenting.'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do we have a saved position? Show it using a radial progress bar on top
|
||||||
|
// of the play button, unless already showing a spinner there:
|
||||||
|
var positionElem
|
||||||
|
var willShowSpinner = torrentSummary.playStatus === 'requested'
|
||||||
|
var defaultFile = torrentSummary.files[torrentSummary.defaultPlayFileIndex]
|
||||||
|
if (defaultFile && defaultFile.currentTime && !willShowSpinner) {
|
||||||
|
var fraction = defaultFile.currentTime / defaultFile.duration
|
||||||
|
positionElem = renderRadialProgressBar(fraction, 'radial-progress-large')
|
||||||
|
playClass = 'resume-position'
|
||||||
|
}
|
||||||
|
|
||||||
// Only show the play button for torrents that contain playable media
|
// Only show the play button for torrents that contain playable media
|
||||||
var playButton
|
var playButton
|
||||||
if (TorrentPlayer.isPlayableTorrent(torrentSummary)) {
|
if (TorrentPlayer.isPlayableTorrent(torrentSummary)) {
|
||||||
@@ -158,6 +164,7 @@ function TorrentList (state) {
|
|||||||
|
|
||||||
return hx`
|
return hx`
|
||||||
<div class='buttons'>
|
<div class='buttons'>
|
||||||
|
${positionElem}
|
||||||
${playButton}
|
${playButton}
|
||||||
<i.button-round.icon.download
|
<i.button-round.icon.download
|
||||||
class=${torrentSummary.status}
|
class=${torrentSummary.status}
|
||||||
@@ -216,13 +223,20 @@ function TorrentList (state) {
|
|||||||
progress = Math.round(100 * fileProg.numPiecesPresent / fileProg.numPieces) + '%'
|
progress = Math.round(100 * fileProg.numPiecesPresent / fileProg.numPieces) + '%'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second, render the file as a table row
|
// Second, for media files where we saved our position, show how far we got
|
||||||
|
var positionElem
|
||||||
|
if (file.currentTime) {
|
||||||
|
// Radial progress bar. 0% = start from 0:00, 270% = 3/4 of the way thru
|
||||||
|
positionElem = renderRadialProgressBar(file.currentTime / file.duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, render the file as a table row
|
||||||
var isPlayable = TorrentPlayer.isPlayable(file)
|
var isPlayable = TorrentPlayer.isPlayable(file)
|
||||||
var infoHash = torrentSummary.infoHash
|
var infoHash = torrentSummary.infoHash
|
||||||
var icon
|
var icon
|
||||||
var handleClick
|
var handleClick
|
||||||
if (isPlayable) {
|
if (isPlayable) {
|
||||||
icon = 'play_circle_outline' /* playable? add option to play */
|
icon = 'play_arrow' /* playable? add option to play */
|
||||||
handleClick = dispatcher('play', infoHash, index)
|
handleClick = dispatcher('play', infoHash, index)
|
||||||
} else {
|
} else {
|
||||||
icon = 'description' /* file icon, opens in OS default app */
|
icon = 'description' /* file icon, opens in OS default app */
|
||||||
@@ -234,6 +248,7 @@ function TorrentList (state) {
|
|||||||
return hx`
|
return hx`
|
||||||
<tr onclick=${handleClick}>
|
<tr onclick=${handleClick}>
|
||||||
<td class='col-icon ${rowClass}'>
|
<td class='col-icon ${rowClass}'>
|
||||||
|
${positionElem}
|
||||||
<i class='icon'>${icon}</i>
|
<i class='icon'>${icon}</i>
|
||||||
</td>
|
</td>
|
||||||
<td class='col-name ${rowClass}'>
|
<td class='col-name ${rowClass}'>
|
||||||
@@ -253,3 +268,24 @@ function TorrentList (state) {
|
|||||||
`
|
`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderRadialProgressBar (fraction, cssClass) {
|
||||||
|
var rotation = 360 * fraction
|
||||||
|
var transformFill = {transform: 'rotate(' + (rotation / 2) + 'deg)'}
|
||||||
|
var transformFix = {transform: 'rotate(' + rotation + 'deg)'}
|
||||||
|
|
||||||
|
return hx`
|
||||||
|
<div class="radial-progress ${cssClass}">
|
||||||
|
<div class="circle">
|
||||||
|
<div class="mask full" style=${transformFill}>
|
||||||
|
<div class="fill" style=${transformFill}></div>
|
||||||
|
</div>
|
||||||
|
<div class="mask half">
|
||||||
|
<div class="fill" style=${transformFill}></div>
|
||||||
|
<div class="fill fix" style=${transformFix}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="inset"></div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user