From 0b57961ff7a75ec11c029429523876ecd8062a19 Mon Sep 17 00:00:00 2001 From: David Ernst Date: Fri, 1 May 2020 19:43:47 -0700 Subject: [PATCH 1/7] Basic placeholder UI for scrubbing preview --- .../controllers/playback-controller.js | 12 +++++++ src/renderer/main.js | 2 ++ src/renderer/pages/player-page.js | 35 +++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/src/renderer/controllers/playback-controller.js b/src/renderer/controllers/playback-controller.js index 413ccd2d..b09d0fa2 100644 --- a/src/renderer/controllers/playback-controller.js +++ b/src/renderer/controllers/playback-controller.js @@ -158,6 +158,18 @@ module.exports = class PlaybackController { else this.state.playing.jumpToTime = time } + preview (time, x) { + if (!Number.isFinite(time)) { + console.error('Tried to skip to a non-finite time ' + time) + return console.trace() + } + this.state.playing.preview = { time, x } + } + + clearPreview () { + this.state.playing.preview = null + } + // Change playback speed. 1 = faster, -1 = slower // Playback speed ranges from 16 (fast forward) to 1 (normal playback) // to 0.25 (quarter-speed playback), then goes to -0.25, -0.5, -1, -2, etc diff --git a/src/renderer/main.js b/src/renderer/main.js index be363d6c..ec02ca2c 100644 --- a/src/renderer/main.js +++ b/src/renderer/main.js @@ -277,6 +277,8 @@ const dispatchHandlers = { previousTrack: () => controllers.playback().previousTrack(), skip: (time) => controllers.playback().skip(time), skipTo: (time) => controllers.playback().skipTo(time), + preview: (time, x) => controllers.playback().preview(time, x), + clearPreview: () => controllers.playback().clearPreview(), changePlaybackRate: (dir) => controllers.playback().changePlaybackRate(dir), changeVolume: (delta) => controllers.playback().changeVolume(delta), setVolume: (vol) => controllers.playback().setVolume(vol), diff --git a/src/renderer/pages/player-page.js b/src/renderer/pages/player-page.js index a9a66695..dd233708 100644 --- a/src/renderer/pages/player-page.js +++ b/src/renderer/pages/player-page.js @@ -536,6 +536,8 @@ function renderPlayerControls (state) { const nextClass = Playlist.hasNext(state) ? '' : 'disabled' const elements = [ + renderPreview(state), +
{renderLoadingBar(state)}
+
+

{formatTime(state.playing.preview.time, state.playing.duration)}

+
+ ) +} + // Renders the loading bar. Shows which parts of the torrent are loaded, which // can be 'spongey' / non-contiguous function renderLoadingBar (state) { From 85c0e99e16c70deee0d08496bfe96867d3917e18 Mon Sep 17 00:00:00 2001 From: David Ernst Date: Fri, 1 May 2020 21:05:29 -0700 Subject: [PATCH 2/7] Only show previews for video --- src/renderer/pages/player-page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/pages/player-page.js b/src/renderer/pages/player-page.js index dd233708..a981837b 100644 --- a/src/renderer/pages/player-page.js +++ b/src/renderer/pages/player-page.js @@ -728,7 +728,7 @@ function renderPlayerControls (state) { // Handles a scrub hover (preview another position in the video) function handleScrubPreview (e) { - if (!e.clientX) return + if (!e.clientX || state.playing.type !== 'video') return dispatch('mediaMouseMoved') const windowWidth = document.querySelector('body').clientWidth const fraction = e.clientX / windowWidth From 0716444be55eada47634a1c4a9ebab64a0809558 Mon Sep 17 00:00:00 2001 From: David Ernst Date: Fri, 1 May 2020 21:57:42 -0700 Subject: [PATCH 3/7] Working video scrubbing preview --- src/renderer/pages/player-page.js | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/renderer/pages/player-page.js b/src/renderer/pages/player-page.js index a981837b..783dfaf5 100644 --- a/src/renderer/pages/player-page.js +++ b/src/renderer/pages/player-page.js @@ -549,7 +549,7 @@ function renderPlayerControls (state) { key='scrub-bar' className='scrub-bar' draggable - onMouseOver={handleScrubPreview} + onMouseMove={handleScrubPreview} onMouseOut={clearPreview} onDragStart={handleDragStart} onClick={handleScrub} @@ -779,18 +779,32 @@ function renderPlayerControls (state) { } function renderPreview (state) { - if (!state.playing.preview) { - return null + let { preview } = state.playing + if (!preview) { + preview = { x: 0, time: 0, hide: true } } - const width = 118 + const height = 70 + let width - const xPos = Math.max(state.playing.preview.x - (width / 2), 5) + const previewEl = document.querySelector('video#preview') + if (previewEl !== null && !preview.hide) { + previewEl.currentTime = preview.time + width = (previewEl.videoWidth / previewEl.videoHeight) * height + } + + const windowWidth = document.querySelector('body').clientWidth + const xPos = Math.min(Math.max(preview.x - (width / 2), 5), windowWidth - width - 5) return ( -
-
-

{formatTime(state.playing.preview.time, state.playing.duration)}

+
+
+
+

{formatTime(preview.time, state.playing.duration)}

) } From 24bc40c95e951b37dc28207cd45614fdd89167d9 Mon Sep 17 00:00:00 2001 From: David Ernst Date: Fri, 1 May 2020 22:06:05 -0700 Subject: [PATCH 4/7] Fix preview border rendering --- src/renderer/pages/player-page.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/renderer/pages/player-page.js b/src/renderer/pages/player-page.js index 783dfaf5..f37365b4 100644 --- a/src/renderer/pages/player-page.js +++ b/src/renderer/pages/player-page.js @@ -790,7 +790,7 @@ function renderPreview (state) { const previewEl = document.querySelector('video#preview') if (previewEl !== null && !preview.hide) { previewEl.currentTime = preview.time - width = (previewEl.videoWidth / previewEl.videoHeight) * height + width = Math.floor((previewEl.videoWidth / previewEl.videoHeight) * height) } const windowWidth = document.querySelector('body').clientWidth @@ -798,10 +798,11 @@ function renderPreview (state) { return (
-
+

{formatTime(preview.time, state.playing.duration)}

From d55acf9c1246477fccc9d6f7cf6e5cbe710accd0 Mon Sep 17 00:00:00 2001 From: David Ernst Date: Fri, 1 May 2020 22:41:19 -0700 Subject: [PATCH 5/7] Fix 'extra-lint' errors --- src/renderer/pages/player-page.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/renderer/pages/player-page.js b/src/renderer/pages/player-page.js index f37365b4..9cb679bb 100644 --- a/src/renderer/pages/player-page.js +++ b/src/renderer/pages/player-page.js @@ -797,7 +797,10 @@ function renderPreview (state) { const xPos = Math.min(Math.max(preview.x - (width / 2), 5), windowWidth - width - 5) return ( -
+
-

{formatTime(preview.time, state.playing.duration)}

+

+ {formatTime(preview.time, state.playing.duration)} +

) } From c4b318bd5ff62eeb521450726bf74b010d26fa85 Mon Sep 17 00:00:00 2001 From: David Ernst Date: Sat, 2 May 2020 11:40:00 -0700 Subject: [PATCH 6/7] Clean up code and add better comments --- .../controllers/playback-controller.js | 12 +++--- src/renderer/main.js | 2 +- src/renderer/pages/player-page.js | 39 +++++++++++-------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/renderer/controllers/playback-controller.js b/src/renderer/controllers/playback-controller.js index b09d0fa2..717ee0b0 100644 --- a/src/renderer/controllers/playback-controller.js +++ b/src/renderer/controllers/playback-controller.js @@ -158,16 +158,18 @@ module.exports = class PlaybackController { else this.state.playing.jumpToTime = time } - preview (time, x) { - if (!Number.isFinite(time)) { - console.error('Tried to skip to a non-finite time ' + time) + // Show video preview + preview (x) { + if (!Number.isFinite(x)) { + console.error('Tried to preview a non-finite position ' + x) return console.trace() } - this.state.playing.preview = { time, x } + this.state.playing.previewXCoord = x } + // Hide video preview clearPreview () { - this.state.playing.preview = null + this.state.playing.previewXCoord = null } // Change playback speed. 1 = faster, -1 = slower diff --git a/src/renderer/main.js b/src/renderer/main.js index ec02ca2c..00738ca8 100644 --- a/src/renderer/main.js +++ b/src/renderer/main.js @@ -277,7 +277,7 @@ const dispatchHandlers = { previousTrack: () => controllers.playback().previousTrack(), skip: (time) => controllers.playback().skip(time), skipTo: (time) => controllers.playback().skipTo(time), - preview: (time, x) => controllers.playback().preview(time, x), + preview: (x) => controllers.playback().preview(x), clearPreview: () => controllers.playback().clearPreview(), changePlaybackRate: (dir) => controllers.playback().changePlaybackRate(dir), changeVolume: (delta) => controllers.playback().changeVolume(delta), diff --git a/src/renderer/pages/player-page.js b/src/renderer/pages/player-page.js index 9cb679bb..45c918e2 100644 --- a/src/renderer/pages/player-page.js +++ b/src/renderer/pages/player-page.js @@ -728,12 +728,10 @@ function renderPlayerControls (state) { // Handles a scrub hover (preview another position in the video) function handleScrubPreview (e) { + // Only show for videos if (!e.clientX || state.playing.type !== 'video') return dispatch('mediaMouseMoved') - const windowWidth = document.querySelector('body').clientWidth - const fraction = e.clientX / windowWidth - const position = fraction * state.playing.duration /* seconds */ - dispatch('preview', position, e.clientX) + dispatch('preview', e.clientX) } function clearPreview (e) { @@ -779,27 +777,36 @@ function renderPlayerControls (state) { } function renderPreview (state) { - let { preview } = state.playing - if (!preview) { - preview = { x: 0, time: 0, hide: true } - } + const { previewXCoord = null } = state.playing + + // Calculate time from x-coord as fraction of track width + const windowWidth = document.querySelector('body').clientWidth + const fraction = previewXCoord / windowWidth + const time = fraction * state.playing.duration /* seconds */ const height = 70 - let width + let width = 0 const previewEl = document.querySelector('video#preview') - if (previewEl !== null && !preview.hide) { - previewEl.currentTime = preview.time + if (previewEl !== null && previewXCoord !== null) { + previewEl.currentTime = time + + // Auto adjust width to maintain video aspect ratio width = Math.floor((previewEl.videoWidth / previewEl.videoHeight) * height) } - const windowWidth = document.querySelector('body').clientWidth - const xPos = Math.min(Math.max(preview.x - (width / 2), 5), windowWidth - width - 5) + // Center preview window on mouse cursor, + // while avoiding falling off the left or right edges + const xPos = Math.min(Math.max(previewXCoord - (width / 2), 5), windowWidth - width - 5) return (
) From d3bfccaa6b6cc91172fecb526747ed28bd1d8fbf Mon Sep 17 00:00:00 2001 From: David Ernst Date: Thu, 30 Jul 2020 19:10:14 -0700 Subject: [PATCH 7/7] Check for type === video in clearPreview() --- src/renderer/pages/player-page.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/renderer/pages/player-page.js b/src/renderer/pages/player-page.js index 45c918e2..1d40385f 100644 --- a/src/renderer/pages/player-page.js +++ b/src/renderer/pages/player-page.js @@ -735,6 +735,7 @@ function renderPlayerControls (state) { } function clearPreview (e) { + if (state.playing.type !== 'video') return dispatch('clearPreview') }