More consistent controls, delete verbose css
This commit is contained in:
@@ -39,7 +39,8 @@
|
|||||||
"virtual-dom": "^2.1.1",
|
"virtual-dom": "^2.1.1",
|
||||||
"vlc-command": "^1.0.1",
|
"vlc-command": "^1.0.1",
|
||||||
"webtorrent": "0.x",
|
"webtorrent": "0.x",
|
||||||
"winreg": "^1.2.0"
|
"winreg": "^1.2.0",
|
||||||
|
"zero-fill": "^2.2.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-zip": "^2.0.1",
|
"cross-zip": "^2.0.1",
|
||||||
|
|||||||
@@ -94,11 +94,20 @@ table {
|
|||||||
word-wrap: normal;
|
word-wrap: normal;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
|
opacity: 0.85;
|
||||||
|
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon.disabled {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon:not(.disabled):hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UTILITY CLASSES
|
* UTILITY CLASSES
|
||||||
*/
|
*/
|
||||||
@@ -109,8 +118,8 @@ table {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.disabled {
|
.float-left {
|
||||||
opacity: 0.3;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.float-right {
|
.float-right {
|
||||||
@@ -144,8 +153,8 @@ table {
|
|||||||
.header {
|
.header {
|
||||||
background: rgb(40, 40, 40);
|
background: rgb(40, 40, 40);
|
||||||
border-bottom: 1px solid rgb(20, 20, 20);
|
border-bottom: 1px solid rgb(20, 20, 20);
|
||||||
height: 37px; /* vertically center OS menu buttons (OS X) */
|
height: 38px; /* vertically center OS menu buttons (OS X) */
|
||||||
padding-top: 6px;
|
padding-top: 7px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -164,7 +173,13 @@ table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.app.view-player .header {
|
.app.view-player .header {
|
||||||
opacity: 0.8;
|
background: rgba(40, 40, 40, 0.8);
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app.view-player.is-win32 .header,
|
||||||
|
.app.view-player.is-linux .header {
|
||||||
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app.hide-video-controls.view-player .header {
|
.app.hide-video-controls.view-player .header {
|
||||||
@@ -172,12 +187,8 @@ table {
|
|||||||
cursor: none;
|
cursor: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app.hide-header .header {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header .title {
|
.header .title {
|
||||||
opacity: 0.6;
|
opacity: 0.7;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
padding: 0 150px 0 150px;
|
padding: 0 150px 0 150px;
|
||||||
@@ -188,35 +199,22 @@ table {
|
|||||||
|
|
||||||
.header .nav {
|
.header .nav {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-right: 9px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header .nav.left {
|
.header .nav.left {
|
||||||
float: left;
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header .nav.right {
|
||||||
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app.is-darwin:not(.is-fullscreen) .header .nav.left {
|
.app.is-darwin:not(.is-fullscreen) .header .nav.left {
|
||||||
margin-left: 78px;
|
margin-left: 78px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header .nav.right {
|
.header .back,
|
||||||
float: right;
|
.header .forward {
|
||||||
}
|
|
||||||
|
|
||||||
.header .nav * {
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header .nav .disabled {
|
|
||||||
opacity: 0.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header .nav *:not(.disabled):hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header .nav .back,
|
|
||||||
.header .nav .forward {
|
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
margin-top: -3px;
|
margin-top: -3px;
|
||||||
}
|
}
|
||||||
@@ -695,7 +693,7 @@ body.drag .app::after {
|
|||||||
* PLAYER CONTROLS
|
* PLAYER CONTROLS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.player-controls {
|
.player .controls {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
background: rgba(40, 40, 40, 0.8);
|
background: rgba(40, 40, 40, 0.8);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -704,7 +702,62 @@ body.drag .app::after {
|
|||||||
transition: opacity 0.15s ease-out;
|
transition: opacity 0.15s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app.hide-video-controls .player-controls {
|
.player .controls .icon {
|
||||||
|
display: block;
|
||||||
|
margin: 8px;
|
||||||
|
font-size: 22px;
|
||||||
|
opacity: 0.85;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fix for overflowing captions icon
|
||||||
|
* https://github.com/feross/webtorrent-desktop/issues/467
|
||||||
|
*/
|
||||||
|
max-width: 23px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player .controls .icon:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player .controls .play-pause {
|
||||||
|
font-size: 28px;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player .controls .volume-slider {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
|
width: 60px;
|
||||||
|
height: 3px;
|
||||||
|
margin: 18px 8px 8px 0;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
opacity: 0.85;
|
||||||
|
vertical-align: sub;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player .controls .time {
|
||||||
|
font-weight: 100;
|
||||||
|
font-size: 13px;
|
||||||
|
margin: 9px 8px 8px 8px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player .controls .icon.closed-captions {
|
||||||
|
font-size: 26px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player .controls .icon.fullscreen {
|
||||||
|
font-size: 26px;
|
||||||
|
margin-right: 15px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app.hide-video-controls .player .controls {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,13 +765,16 @@ body.drag .app::after {
|
|||||||
cursor: none;
|
cursor: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app.hide-video-controls .player .player-controls:hover {
|
/* TODO: find better way to handle this (that also
|
||||||
|
* keeps the header visible too).
|
||||||
|
*/
|
||||||
|
.app.hide-video-controls .player .controls:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* invisible click target for scrubbing */
|
/* invisible click target for scrubbing */
|
||||||
.player-controls .scrub-bar {
|
.player .controls .scrub-bar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 23px; /* 3px .loading-bar plus 10px above and below */
|
height: 23px; /* 3px .loading-bar plus 10px above and below */
|
||||||
@@ -727,7 +783,7 @@ body.drag .app::after {
|
|||||||
-webkit-app-region: no-drag;
|
-webkit-app-region: no-drag;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-controls .loading-bar {
|
.player .controls .loading-bar {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
top: -3px;
|
top: -3px;
|
||||||
@@ -737,14 +793,14 @@ body.drag .app::after {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-controls .loading-bar-part {
|
.player .controls .loading-bar-part {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: #dd0000;
|
background-color: #dd0000;
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-controls .playback-cursor {
|
.player .controls .playback-cursor {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -3px;
|
top: -3px;
|
||||||
background-color: #FFF;
|
background-color: #FFF;
|
||||||
@@ -758,104 +814,31 @@ body.drag .app::after {
|
|||||||
transition-timing-function: ease-out;
|
transition-timing-function: ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-controls .play-pause {
|
.player .controls .closed-captions.active,
|
||||||
display: block;
|
.player .controls .device.active {
|
||||||
width: 30px;
|
color: #9af;
|
||||||
height: 30px;
|
|
||||||
padding: 5px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-controls .rate {
|
.player-controls .rate {
|
||||||
display: inline;
|
display: inline;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
float: left;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-controls .device,
|
.player .controls .volume-slider::-webkit-slider-thumb {
|
||||||
.player-controls .fullscreen,
|
|
||||||
.player-controls .closed-captions,
|
|
||||||
.player-controls .volume-icon,
|
|
||||||
.player-controls .back {
|
|
||||||
display: block;
|
|
||||||
height: 20px;
|
|
||||||
margin: 5px;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fix for overflowing captions icon
|
|
||||||
* https://github.com/feross/webtorrent-desktop/issues/467
|
|
||||||
*/
|
|
||||||
max-width: 22px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-controls .volume,
|
|
||||||
.player-controls .back {
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-controls .device,
|
|
||||||
.player-controls .closed-captions,
|
|
||||||
.player-controls .fullscreen {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-controls .fullscreen {
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-controls .volume-icon,
|
|
||||||
.player-controls .device {
|
|
||||||
font-size: 18px; /* make the cast icons less huge */
|
|
||||||
margin-top: 8px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-controls .closed-captions.active,
|
|
||||||
.player-controls .device.active {
|
|
||||||
color: #9af;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-controls .volume {
|
|
||||||
display: block;
|
|
||||||
width: 90px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-controls .volume-icon {
|
|
||||||
float: left;
|
|
||||||
margin-right: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player-controls .volume-slider {
|
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
width: 50px;
|
|
||||||
height: 3px;
|
|
||||||
border: none;
|
|
||||||
padding: 0;
|
|
||||||
vertical-align: sub;
|
|
||||||
-webkit-app-region: no-drag;
|
-webkit-app-region: no-drag;
|
||||||
}
|
|
||||||
|
|
||||||
.player-controls .volume-slider::-webkit-slider-thumb {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
opacity: 1.0;
|
width: 13px;
|
||||||
width: 10px;
|
height: 13px;
|
||||||
height: 10px;
|
|
||||||
border: 1px solid #303233;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
-webkit-app-region: no-drag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-controls .volume-slider:focus {
|
.player .controls .volume-slider:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.player-controls .time {
|
|
||||||
float: left;
|
|
||||||
line-height: 33px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.player .playback-bar:hover .loading-bar {
|
.player .playback-bar:hover .loading-bar {
|
||||||
height: 5px;
|
height: 5px;
|
||||||
}
|
}
|
||||||
@@ -999,10 +982,6 @@ video::-webkit-media-text-track-container {
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app.hide-header .error-popover {
|
|
||||||
top: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-popover.hidden {
|
.error-popover.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,6 @@ function App (state) {
|
|||||||
state.playing.location === 'local' &&
|
state.playing.location === 'local' &&
|
||||||
state.playing.playbackRate === 1
|
state.playing.playbackRate === 1
|
||||||
|
|
||||||
// Hide the header on Windows/Linux when in the player
|
|
||||||
// On OSX, the header appears as part of the title bar
|
|
||||||
var hideHeader = process.platform !== 'darwin' && state.location.url() === 'player'
|
|
||||||
|
|
||||||
var cls = [
|
var cls = [
|
||||||
'view-' + state.location.url(), /* e.g. view-home, view-player */
|
'view-' + state.location.url(), /* e.g. view-home, view-player */
|
||||||
'is-' + process.platform /* e.g. is-darwin, is-win32, is-linux */
|
'is-' + process.platform /* e.g. is-darwin, is-win32, is-linux */
|
||||||
@@ -40,7 +36,6 @@ function App (state) {
|
|||||||
if (state.window.isFullScreen) cls.push('is-fullscreen')
|
if (state.window.isFullScreen) cls.push('is-fullscreen')
|
||||||
if (state.window.isFocused) cls.push('is-focused')
|
if (state.window.isFocused) cls.push('is-focused')
|
||||||
if (hideControls) cls.push('hide-video-controls')
|
if (hideControls) cls.push('hide-video-controls')
|
||||||
if (hideHeader) cls.push('hide-header')
|
|
||||||
|
|
||||||
return hx`
|
return hx`
|
||||||
<div class='app ${cls.join(' ')}'>
|
<div class='app ${cls.join(' ')}'>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ function Header (state) {
|
|||||||
return hx`
|
return hx`
|
||||||
<div class='header'>
|
<div class='header'>
|
||||||
${getTitle()}
|
${getTitle()}
|
||||||
<div class='nav left'>
|
<div class='nav left float-left'>
|
||||||
<i.icon.back
|
<i.icon.back
|
||||||
class=${state.location.hasBack() ? '' : 'disabled'}
|
class=${state.location.hasBack() ? '' : 'disabled'}
|
||||||
title='Back'
|
title='Back'
|
||||||
@@ -24,7 +24,7 @@ function Header (state) {
|
|||||||
chevron_right
|
chevron_right
|
||||||
</i>
|
</i>
|
||||||
</div>
|
</div>
|
||||||
<div class='nav right'>
|
<div class='nav right float-right'>
|
||||||
${getAddButton()}
|
${getAddButton()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ var h = require('virtual-dom/h')
|
|||||||
var hyperx = require('hyperx')
|
var hyperx = require('hyperx')
|
||||||
var hx = hyperx(h)
|
var hx = hyperx(h)
|
||||||
|
|
||||||
var prettyBytes = require('prettier-bytes')
|
|
||||||
var Bitfield = require('bitfield')
|
var Bitfield = require('bitfield')
|
||||||
|
var prettyBytes = require('prettier-bytes')
|
||||||
|
var zeroFill = require('zero-fill')
|
||||||
|
|
||||||
var TorrentSummary = require('../lib/torrent-summary')
|
var TorrentSummary = require('../lib/torrent-summary')
|
||||||
var {dispatch, dispatcher} = require('../lib/dispatcher')
|
var {dispatch, dispatcher} = require('../lib/dispatcher')
|
||||||
@@ -313,15 +314,26 @@ function renderPlayerControls (state) {
|
|||||||
hx`
|
hx`
|
||||||
<div class='playback-bar'>
|
<div class='playback-bar'>
|
||||||
${renderLoadingBar(state)}
|
${renderLoadingBar(state)}
|
||||||
<div class='playback-cursor' style=${playbackCursorStyle}></div>
|
<div
|
||||||
<div class='scrub-bar'
|
class='playback-cursor'
|
||||||
|
style=${playbackCursorStyle}>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class='scrub-bar'
|
||||||
draggable='true'
|
draggable='true'
|
||||||
onclick=${handleScrub},
|
onclick=${handleScrub},
|
||||||
ondrag=${handleScrub}></div>
|
ondrag=${handleScrub}>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
hx`
|
hx`
|
||||||
<i class='icon fullscreen'
|
<i class='icon play-pause float-left' onclick=${dispatcher('playPause')}>
|
||||||
|
${state.playing.isPaused ? 'play_arrow' : 'pause'}
|
||||||
|
</i>
|
||||||
|
`,
|
||||||
|
hx`
|
||||||
|
<i
|
||||||
|
class='icon fullscreen float-right'
|
||||||
onclick=${dispatcher('toggleFullScreen')}>
|
onclick=${dispatcher('toggleFullScreen')}>
|
||||||
${state.window.isFullScreen ? 'fullscreen_exit' : 'fullscreen'}
|
${state.window.isFullScreen ? 'fullscreen_exit' : 'fullscreen'}
|
||||||
</i>
|
</i>
|
||||||
@@ -331,7 +343,7 @@ function renderPlayerControls (state) {
|
|||||||
if (state.playing.type === 'video') {
|
if (state.playing.type === 'video') {
|
||||||
// show closed captions icon
|
// show closed captions icon
|
||||||
elements.push(hx`
|
elements.push(hx`
|
||||||
<i.icon.closed-captions
|
<i.icon.closed-captions.float-right
|
||||||
class=${captionsClass}
|
class=${captionsClass}
|
||||||
onclick=${handleSubtitles}>
|
onclick=${handleSubtitles}>
|
||||||
closed_captions
|
closed_captions
|
||||||
@@ -376,7 +388,7 @@ function renderPlayerControls (state) {
|
|||||||
if (state.devices.chromecast || isOnChromecast) {
|
if (state.devices.chromecast || isOnChromecast) {
|
||||||
var castIcon = isOnChromecast ? 'cast_connected' : 'cast'
|
var castIcon = isOnChromecast ? 'cast_connected' : 'cast'
|
||||||
elements.push(hx`
|
elements.push(hx`
|
||||||
<i.icon.device
|
<i.icon.device.float-right
|
||||||
class=${chromecastClass}
|
class=${chromecastClass}
|
||||||
onclick=${chromecastHandler}>
|
onclick=${chromecastHandler}>
|
||||||
${castIcon}
|
${castIcon}
|
||||||
@@ -385,7 +397,7 @@ function renderPlayerControls (state) {
|
|||||||
}
|
}
|
||||||
if (state.devices.airplay || isOnAirplay) {
|
if (state.devices.airplay || isOnAirplay) {
|
||||||
elements.push(hx`
|
elements.push(hx`
|
||||||
<i.icon.device
|
<i.icon.device.float-right
|
||||||
class=${airplayClass}
|
class=${airplayClass}
|
||||||
onclick=${airplayHandler}>
|
onclick=${airplayHandler}>
|
||||||
airplay
|
airplay
|
||||||
@@ -394,7 +406,8 @@ function renderPlayerControls (state) {
|
|||||||
}
|
}
|
||||||
if (state.devices.dlna || isOnDlna) {
|
if (state.devices.dlna || isOnDlna) {
|
||||||
elements.push(hx`
|
elements.push(hx`
|
||||||
<i.icon.device
|
<i
|
||||||
|
class='icon device float-right'
|
||||||
class=${dlnaClass}
|
class=${dlnaClass}
|
||||||
onclick=${dlnaHandler}>
|
onclick=${dlnaHandler}>
|
||||||
tv
|
tv
|
||||||
@@ -402,17 +415,6 @@ function renderPlayerControls (state) {
|
|||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// On OSX, the back button is in the title bar of the window; see app.js
|
|
||||||
// On other platforms, we render one over the video on mouseover
|
|
||||||
if (process.platform !== 'darwin') {
|
|
||||||
elements.push(hx`
|
|
||||||
<i.icon.back
|
|
||||||
onclick=${dispatcher('back')}>
|
|
||||||
chevron_left
|
|
||||||
</i>
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// render volume
|
// render volume
|
||||||
var volume = state.playing.volume
|
var volume = state.playing.volume
|
||||||
var volumeIcon = 'volume_' + (volume === 0 ? 'off' : volume < 0.3 ? 'mute' : volume < 0.6 ? 'down' : 'up')
|
var volumeIcon = 'volume_' + (volume === 0 ? 'off' : volume < 0.3 ? 'mute' : volume < 0.6 ? 'down' : 'up')
|
||||||
@@ -422,43 +424,41 @@ function renderPlayerControls (state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
elements.push(hx`
|
elements.push(hx`
|
||||||
<div.volume>
|
<div class='volume float-left'>
|
||||||
<i.icon.volume-icon onmousedown=${handleVolumeMute}>
|
<i
|
||||||
${volumeIcon}
|
class='icon volume-icon float-left'
|
||||||
</i>
|
onmousedown=${handleVolumeMute}>
|
||||||
<input.volume-slider
|
${volumeIcon}
|
||||||
type='range' min='0' max='1' step='0.05' value=${volumeChanging !== false ? volumeChanging : volume}
|
</i>
|
||||||
onmousedown=${handleVolumeScrub}
|
<input
|
||||||
onmouseup=${handleVolumeScrub}
|
class='volume-slider float-right'
|
||||||
onmousemove=${handleVolumeScrub}
|
type='range' min='0' max='1' step='0.05' value=${volumeChanging !== false ? volumeChanging : volume}
|
||||||
style=${volumeStyle}
|
onmousedown=${handleVolumeScrub}
|
||||||
/>
|
onmouseup=${handleVolumeScrub}
|
||||||
|
onmousemove=${handleVolumeScrub}
|
||||||
|
style=${volumeStyle}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
`)
|
`)
|
||||||
|
|
||||||
// Show video playback progress
|
// Show video playback progress
|
||||||
var videoProgress = formatPlaybackProgress(state.playing.currentTime, state.playing.duration)
|
|
||||||
elements.push(hx`
|
elements.push(hx`
|
||||||
<span.time>
|
<span class='time float-left'>
|
||||||
${videoProgress[0]} / ${videoProgress[1]}
|
${formatTime(state.playing.currentTime)} / ${formatTime(state.playing.duration)}
|
||||||
</span>
|
</span>
|
||||||
`)
|
`)
|
||||||
|
|
||||||
// render playback rate
|
// render playback rate
|
||||||
if (state.playing.playbackRate !== 1) {
|
if (state.playing.playbackRate !== 1) {
|
||||||
elements.push(hx`
|
elements.push(hx`
|
||||||
<span class="rate">speed: ${state.playing.playbackRate}X</span>
|
<span class='rate float-left'>
|
||||||
|
speed: ${state.playing.playbackRate}X
|
||||||
|
</span>
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
// Finally, the big button in the center plays or pauses the video
|
|
||||||
elements.push(hx`
|
|
||||||
<i class='icon play-pause' onclick=${dispatcher('playPause')}>
|
|
||||||
${state.playing.isPaused ? 'play_arrow' : 'pause'}
|
|
||||||
</i>
|
|
||||||
`)
|
|
||||||
|
|
||||||
return hx`
|
return hx`
|
||||||
<div class='player-controls'>
|
<div class='controls'>
|
||||||
${elements}
|
${elements}
|
||||||
${renderSubtitlesOptions(state)}
|
${renderSubtitlesOptions(state)}
|
||||||
</div>
|
</div>
|
||||||
@@ -565,39 +565,17 @@ function cssBackgroundImageDarkGradient () {
|
|||||||
'rgba(0,0,0,0.4) 0%, rgba(0,0,0,1) 100%)'
|
'rgba(0,0,0,0.4) 0%, rgba(0,0,0,1) 100%)'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the playback time of the video
|
function formatTime (time) {
|
||||||
function formatPlaybackProgress (currentTime, duration) {
|
if (typeof time !== 'number' || Number.isNaN(time)) {
|
||||||
if (
|
return '0:00'
|
||||||
typeof currentTime !== 'number' || typeof duration !== 'number' ||
|
|
||||||
isNaN(currentTime) || isNaN(duration)
|
|
||||||
) {
|
|
||||||
return ['00:00', '00:00']
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var durationHours = formatTimePart(duration / 3600)
|
var hours = Math.floor(time / 3600)
|
||||||
var durationMinutes = formatTimePart(duration % 3600 / 60)
|
var minutes = Math.floor(time % 3600 / 60)
|
||||||
var durationSeconds = formatTimePart(duration % 60)
|
if (hours > 0) {
|
||||||
|
minutes = zeroFill(2, minutes)
|
||||||
|
}
|
||||||
|
var seconds = zeroFill(2, Math.floor(time % 60))
|
||||||
|
|
||||||
var durationString =
|
return (hours > 0 ? hours + ':' : '') + minutes + ':' + seconds
|
||||||
(durationHours !== '00' ? durationHours + ':' : '') +
|
|
||||||
durationMinutes + ':' +
|
|
||||||
durationSeconds
|
|
||||||
|
|
||||||
var currentTimeHours = durationHours !== '00' && formatTimePart(currentTime / 3600)
|
|
||||||
var currentTimeMinutes = formatTimePart(currentTime % 3600 / 60)
|
|
||||||
var currentTimeSeconds = formatTimePart(currentTime % 60)
|
|
||||||
|
|
||||||
var currentTimeString =
|
|
||||||
(currentTimeHours ? currentTimeHours + ':' : '') +
|
|
||||||
currentTimeMinutes + ':' +
|
|
||||||
currentTimeSeconds
|
|
||||||
|
|
||||||
return [currentTimeString, durationString]
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatTimePart (num) {
|
|
||||||
num = Math.floor(num)
|
|
||||||
return num < 100
|
|
||||||
? ('00' + num).slice(-2)
|
|
||||||
: num
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user