From 279c621d23d56f3b3b77467b821ddd9daa96cb81 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Sun, 22 May 2016 21:34:49 -0700 Subject: [PATCH] More consistent controls, delete verbose css --- package.json | 3 +- renderer/index.css | 223 ++++++++++++++++++--------------------- renderer/views/app.js | 5 - renderer/views/header.js | 4 +- renderer/views/player.js | 126 +++++++++------------- 5 files changed, 157 insertions(+), 204 deletions(-) diff --git a/package.json b/package.json index 7b6e6b10..17b27cf3 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,8 @@ "virtual-dom": "^2.1.1", "vlc-command": "^1.0.1", "webtorrent": "0.x", - "winreg": "^1.2.0" + "winreg": "^1.2.0", + "zero-fill": "^2.2.3" }, "devDependencies": { "cross-zip": "^2.0.1", diff --git a/renderer/index.css b/renderer/index.css index 2a19fa6e..b1ad7177 100644 --- a/renderer/index.css +++ b/renderer/index.css @@ -94,11 +94,20 @@ table { word-wrap: normal; white-space: nowrap; direction: ltr; + opacity: 0.85; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; } +.icon.disabled { + opacity: 0.3; +} + +.icon:not(.disabled):hover { + opacity: 1; +} + /* * UTILITY CLASSES */ @@ -109,8 +118,8 @@ table { white-space: nowrap; } -.disabled { - opacity: 0.3; +.float-left { + float: left; } .float-right { @@ -144,8 +153,8 @@ table { .header { background: rgb(40, 40, 40); border-bottom: 1px solid rgb(20, 20, 20); - height: 37px; /* vertically center OS menu buttons (OS X) */ - padding-top: 6px; + height: 38px; /* vertically center OS menu buttons (OS X) */ + padding-top: 7px; overflow: hidden; flex: 0 1 auto; opacity: 1; @@ -164,7 +173,13 @@ table { } .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 { @@ -172,12 +187,8 @@ table { cursor: none; } -.app.hide-header .header { - display: none; -} - .header .title { - opacity: 0.6; + opacity: 0.7; position: absolute; margin-top: 1px; padding: 0 150px 0 150px; @@ -188,35 +199,22 @@ table { .header .nav { font-weight: bold; - margin-right: 9px; } .header .nav.left { - float: left; + margin-left: 10px; +} + +.header .nav.right { + margin-right: 10px; } .app.is-darwin:not(.is-fullscreen) .header .nav.left { margin-left: 78px; } -.header .nav.right { - float: right; -} - -.header .nav * { - opacity: 0.6; -} - -.header .nav .disabled { - opacity: 0.1; -} - -.header .nav *:not(.disabled):hover { - opacity: 1; -} - -.header .nav .back, -.header .nav .forward { +.header .back, +.header .forward { font-size: 30px; margin-top: -3px; } @@ -695,7 +693,7 @@ body.drag .app::after { * PLAYER CONTROLS */ -.player-controls { +.player .controls { position: fixed; background: rgba(40, 40, 40, 0.8); width: 100%; @@ -704,7 +702,62 @@ body.drag .app::after { 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; } @@ -712,13 +765,16 @@ body.drag .app::after { 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; cursor: default; } /* invisible click target for scrubbing */ -.player-controls .scrub-bar { +.player .controls .scrub-bar { position: absolute; width: 100%; height: 23px; /* 3px .loading-bar plus 10px above and below */ @@ -727,7 +783,7 @@ body.drag .app::after { -webkit-app-region: no-drag; } -.player-controls .loading-bar { +.player .controls .loading-bar { position: relative; width: 100%; top: -3px; @@ -737,14 +793,14 @@ body.drag .app::after { position: absolute; } -.player-controls .loading-bar-part { +.player .controls .loading-bar-part { position: absolute; background-color: #dd0000; top: 0; height: 100%; } -.player-controls .playback-cursor { +.player .controls .playback-cursor { position: absolute; top: -3px; background-color: #FFF; @@ -758,104 +814,31 @@ body.drag .app::after { transition-timing-function: ease-out; } -.player-controls .play-pause { - display: block; - width: 30px; - height: 30px; - padding: 5px; - margin: 0 auto; +.player .controls .closed-captions.active, +.player .controls .device.active { + color: #9af; } + .player-controls .rate { display: inline; height: 30px; padding: 5px; margin-left: 20px; - float: left; } -.player-controls .device, -.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 { +.player .controls .volume-slider::-webkit-slider-thumb { -webkit-appearance: none; - width: 50px; - height: 3px; - border: none; - padding: 0; - vertical-align: sub; -webkit-app-region: no-drag; -} - -.player-controls .volume-slider::-webkit-slider-thumb { - -webkit-appearance: none; background-color: #fff; - opacity: 1.0; - width: 10px; - height: 10px; - border: 1px solid #303233; + width: 13px; + height: 13px; border-radius: 50%; - -webkit-app-region: no-drag; } -.player-controls .volume-slider:focus { +.player .controls .volume-slider:focus { outline: none; } -.player-controls .time { - float: left; - line-height: 33px; -} - .player .playback-bar:hover .loading-bar { height: 5px; } @@ -999,10 +982,6 @@ video::-webkit-media-text-track-container { z-index: 1; } -.app.hide-header .error-popover { - top: 0px; -} - .error-popover.hidden { display: none; } diff --git a/renderer/views/app.js b/renderer/views/app.js index 28085500..4722e059 100644 --- a/renderer/views/app.js +++ b/renderer/views/app.js @@ -29,10 +29,6 @@ function App (state) { state.playing.location === 'local' && 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 = [ 'view-' + state.location.url(), /* e.g. view-home, view-player */ '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.isFocused) cls.push('is-focused') if (hideControls) cls.push('hide-video-controls') - if (hideHeader) cls.push('hide-header') return hx`
diff --git a/renderer/views/header.js b/renderer/views/header.js index 49ff6e3f..5dd302af 100644 --- a/renderer/views/header.js +++ b/renderer/views/header.js @@ -10,7 +10,7 @@ function Header (state) { return hx`
${getTitle()} - `, hx` - + ${state.playing.isPaused ? 'play_arrow' : 'pause'} + + `, + hx` + ${state.window.isFullScreen ? 'fullscreen_exit' : 'fullscreen'} @@ -331,7 +343,7 @@ function renderPlayerControls (state) { if (state.playing.type === 'video') { // show closed captions icon elements.push(hx` - closed_captions @@ -376,7 +388,7 @@ function renderPlayerControls (state) { if (state.devices.chromecast || isOnChromecast) { var castIcon = isOnChromecast ? 'cast_connected' : 'cast' elements.push(hx` - ${castIcon} @@ -385,7 +397,7 @@ function renderPlayerControls (state) { } if (state.devices.airplay || isOnAirplay) { elements.push(hx` - airplay @@ -394,7 +406,8 @@ function renderPlayerControls (state) { } if (state.devices.dlna || isOnDlna) { elements.push(hx` - 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` - - chevron_left - - `) - } - // render volume var volume = state.playing.volume 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` - - - ${volumeIcon} - - +
+ + ${volumeIcon} + +
`) // Show video playback progress - var videoProgress = formatPlaybackProgress(state.playing.currentTime, state.playing.duration) elements.push(hx` - - ${videoProgress[0]} / ${videoProgress[1]} + + ${formatTime(state.playing.currentTime)} / ${formatTime(state.playing.duration)} `) // render playback rate if (state.playing.playbackRate !== 1) { elements.push(hx` - speed: ${state.playing.playbackRate}X + + speed: ${state.playing.playbackRate}X + `) } - // Finally, the big button in the center plays or pauses the video - elements.push(hx` - - ${state.playing.isPaused ? 'play_arrow' : 'pause'} - - `) return hx` -
+
${elements} ${renderSubtitlesOptions(state)}
@@ -565,39 +565,17 @@ function cssBackgroundImageDarkGradient () { 'rgba(0,0,0,0.4) 0%, rgba(0,0,0,1) 100%)' } -// Format the playback time of the video -function formatPlaybackProgress (currentTime, duration) { - if ( - typeof currentTime !== 'number' || typeof duration !== 'number' || - isNaN(currentTime) || isNaN(duration) - ) { - return ['00:00', '00:00'] +function formatTime (time) { + if (typeof time !== 'number' || Number.isNaN(time)) { + return '0:00' } - var durationHours = formatTimePart(duration / 3600) - var durationMinutes = formatTimePart(duration % 3600 / 60) - var durationSeconds = formatTimePart(duration % 60) + var hours = Math.floor(time / 3600) + var minutes = Math.floor(time % 3600 / 60) + if (hours > 0) { + minutes = zeroFill(2, minutes) + } + var seconds = zeroFill(2, Math.floor(time % 60)) - var durationString = - (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 + return (hours > 0 ? hours + ':' : '') + minutes + ':' + seconds }