From 86f22e1230dd8e5c3a10ea12b3918c2e0aaeddb8 Mon Sep 17 00:00:00 2001 From: lianbenjamin <79077248+lianbenjamin@users.noreply.github.com> Date: Mon, 31 Jul 2023 14:59:20 +0300 Subject: [PATCH 1/5] feat(FEC-13114): add chapters as segments to seekbar --- src/components/progress-bar.js | 49 ++++++++++++++++++++++++++++ src/components/seekbar/_seekbar.scss | 12 +++++-- src/components/seekbar/seekbar.js | 18 +++++----- src/reducers/seekbar.js | 31 ++++++++++++++++-- 4 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 src/components/progress-bar.js diff --git a/src/components/progress-bar.js b/src/components/progress-bar.js new file mode 100644 index 000000000..0f1d0dc1e --- /dev/null +++ b/src/components/progress-bar.js @@ -0,0 +1,49 @@ +//@flow +import {h, Fragment, Component} from 'preact'; +import style from '../styles/style.scss'; +import {connect} from 'react-redux'; +import {withPlayer} from './player'; + +/** + * mapping state to props + * @param {*} state - redux store state + * @returns {Object} - mapped state to this component + */ +const mapStateToProps = state => ({ + dataLoaded: state.engine.dataLoaded, + currentTime: state.seekbar.currentTime, + duration: state.engine.duration, + isMobile: state.shell.isMobile, + adBreak: state.engine.adBreak +}); + +/** + * SeekBar component + * + * @class SeekBar + * @extends {Component} + */ +@connect(mapStateToProps) +@withPlayer +class ProgressBar extends Component { + /** + * render component + * + * @param {*} props - component props + * @returns {React$Element} - component + * @memberof ProgressBar + */ + render(props: any): React$Element { + const bufferedWidth = `${Math.round(props.getBufferedPercent())}%`; + const progressWidth = `${props.player.isLive() && props.player.isOnLiveEdge() ? 100 : (props.currentTime / props.duration) * 100}%`; + return ( + <> +
+ {props.dataLoaded ?
: undefined} + + ); + } +} + +ProgressBar.displayName = 'ProgressBar'; +export {ProgressBar}; diff --git a/src/components/seekbar/_seekbar.scss b/src/components/seekbar/_seekbar.scss index 40b14fac4..1701b5fd1 100644 --- a/src/components/seekbar/_seekbar.scss +++ b/src/components/seekbar/_seekbar.scss @@ -40,7 +40,13 @@ border-radius: $progress-bar-border-radius; position: absolute; transition: height 200ms ease, transform 200ms ease; - + &.chapters { + background-color: transparent; + .virtual-progress-indicator { + height: 8px; + transform: translateY(-2px); + } + } .progress { position: absolute; top: 0; @@ -77,7 +83,7 @@ cursor: pointer; display: block; top: -8px + calc($progress-bar-height / 2); - right: -8px; + left: -6px; border-radius: 8px; height: 16px; width: 16px; @@ -132,7 +138,7 @@ .player:not(.touch):not(.size-ty) .seek-bar { &:hover, &.hover { - .progress-bar { + .progress-bar:not(.chapters) { height: 2 * $progress-bar-height; border-radius: 2 * $progress-bar-border-radius; transform: translateY(calc($progress-bar-height / -2)); diff --git a/src/components/seekbar/seekbar.js b/src/components/seekbar/seekbar.js index b1087301d..befc6e5e1 100644 --- a/src/components/seekbar/seekbar.js +++ b/src/components/seekbar/seekbar.js @@ -15,6 +15,7 @@ import {PlayerArea} from '../player-area'; import {withEventManager} from 'event/with-event-manager'; import {FakeEvent} from 'event/fake-event'; import {SeekBarPreview} from '../seekbar-preview'; +import {ProgressBar} from '../progress-bar'; /** * mapping state to props @@ -26,7 +27,8 @@ const mapStateToProps = state => ({ isMobile: state.shell.isMobile, previewHoverActive: state.seekbar.previewHoverActive, hidePreview: state.seekbar.hidePreview, - hideTimeBubble: state.seekbar.hideTimeBubble + hideTimeBubble: state.seekbar.hideTimeBubble, + segments: state.seekbar.segments }); const COMPONENT_NAME = 'SeekBar'; @@ -561,8 +563,6 @@ class SeekBar extends Component { */ render(props: any, state: Object): React$Element { const virtualProgressWidth = `${(props.virtualTime / props.duration) * 100}%`; - const progressWidth = `${props.forceFullProgress ? 100 : (props.currentTime / props.duration) * 100}%`; - const bufferedWidth = `${Math.round(this.getBufferedPercent())}%`; const seekbarStyleClass = [style.seekBar]; if (props.adBreak) seekbarStyleClass.push(style.adBreak); if (props.isDvr) seekbarStyleClass.push(style.live); @@ -593,12 +593,14 @@ class SeekBar extends Component { {this.renderFramePreview()} {this.renderTimeBubble()} -
- {props.dataLoaded ? ( -
- {props.adBreak ? undefined : } + this.getBufferedPercent} /> + {props.adBreak ? undefined : ( +
+
- ) : undefined} + )}
diff --git a/src/reducers/seekbar.js b/src/reducers/seekbar.js index 47d799e01..162035875 100644 --- a/src/reducers/seekbar.js +++ b/src/reducers/seekbar.js @@ -7,7 +7,10 @@ export const types = { UPDATE_HIDE_SEEKBAR_PREVIEW: 'seekbar/UPDATE_HIDE_SEEKBAR_PREVIEW', UPDATE_HIDE_SEEKBAR_TIME_BUBBLE: 'seekbar/UPDATE_HIDE_SEEKBAR_TIME_BUBBLE', UPDATE_CURRENT_TIME: 'seekbar/UPDATE_CURRENT_TIME', - UPDATE_VIRTUAL_TIME: 'seekbar/UPDATE_VIRTUAL_TIME' + UPDATE_VIRTUAL_TIME: 'seekbar/UPDATE_VIRTUAL_TIME', + UPDATE_HOVERED_SEGMENT: 'seekbar/UPDATE_HOVERED_SEGMENT', + UPDATE_SEEKBAR_SEGMENTS: 'seekbar/UPDATE_SEEKBAR_SEGMENTS', + UPDATE_SEGMENT_END_TIME: 'seekbar/UPDATE_SEGMENT_END_TIME' }; export const initialState = { @@ -18,7 +21,8 @@ export const initialState = { previewHoverActive: false, clientRect: {x: 0, y: 0, width: 0, height: 0, top: 0, right: 0, bottom: 0, left: 0}, hidePreview: false, - hideTimeBubble: false + hideTimeBubble: false, + segments: [] }; export default (state: Object = initialState, action: Object) => { @@ -71,6 +75,24 @@ export default (state: Object = initialState, action: Object) => { virtualTime: action.virtualTime }; + case types.UPDATE_HOVERED_SEGMENT: + return { + ...state, + segments: state.segments.map(segment => (segment.id === action.id ? {...segment, isHovered: action.isHovered} : segment)) + }; + + case types.UPDATE_SEEKBAR_SEGMENTS: + return { + ...state, + segments: action.segments + }; + + case types.UPDATE_SEGMENT_END_TIME: + return { + ...state, + segments: state.segments.map(segment => (segment.id === action.id ? {...segment, endTime: action.endTime} : segment)) + }; + default: return state; } @@ -99,5 +121,8 @@ export const actions = { hideTimeBubble }), updateCurrentTime: (currentTime: number) => ({type: types.UPDATE_CURRENT_TIME, currentTime}), - updateVirtualTime: (virtualTime: number) => ({type: types.UPDATE_VIRTUAL_TIME, virtualTime}) + updateVirtualTime: (virtualTime: number) => ({type: types.UPDATE_VIRTUAL_TIME, virtualTime}), + updateHoveredSegment: (id: string, isHovered: boolean) => ({type: types.UPDATE_HOVERED_SEGMENT, id, isHovered}), + updateSegmentEndTime: (id: string, endTime: number) => ({type: types.UPDATE_SEGMENT_END_TIME, id, endTime}), + updateSeekbarSegments: (segments: any[]) => ({type: types.UPDATE_SEEKBAR_SEGMENTS, segments}) }; From 959bd00b11f905365e61baa6eff9b7ab3093f8e1 Mon Sep 17 00:00:00 2001 From: lianbenjamin <79077248+lianbenjamin@users.noreply.github.com> Date: Mon, 31 Jul 2023 15:20:21 +0300 Subject: [PATCH 2/5] fix lint --- src/components/progress-bar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/progress-bar.js b/src/components/progress-bar.js index 0f1d0dc1e..9fd03716d 100644 --- a/src/components/progress-bar.js +++ b/src/components/progress-bar.js @@ -37,10 +37,10 @@ class ProgressBar extends Component { const bufferedWidth = `${Math.round(props.getBufferedPercent())}%`; const progressWidth = `${props.player.isLive() && props.player.isOnLiveEdge() ? 100 : (props.currentTime / props.duration) * 100}%`; return ( - <> +
{props.dataLoaded ?
: undefined} - + ); } } From 7a6301c37dc6767f215bf412f38571bf4fc267e9 Mon Sep 17 00:00:00 2001 From: lianbenjamin <79077248+lianbenjamin@users.noreply.github.com> Date: Mon, 31 Jul 2023 18:53:19 +0300 Subject: [PATCH 3/5] extracts scrubber position calculation to a variable --- src/components/seekbar/seekbar.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/seekbar/seekbar.js b/src/components/seekbar/seekbar.js index befc6e5e1..ec5801743 100644 --- a/src/components/seekbar/seekbar.js +++ b/src/components/seekbar/seekbar.js @@ -563,6 +563,7 @@ class SeekBar extends Component { */ render(props: any, state: Object): React$Element { const virtualProgressWidth = `${(props.virtualTime / props.duration) * 100}%`; + const scrubberProgressPosition = `${(props.currentTime / props.duration) * this._seekBarElement?.clientWidth}px`; const seekbarStyleClass = [style.seekBar]; if (props.adBreak) seekbarStyleClass.push(style.adBreak); if (props.isDvr) seekbarStyleClass.push(style.live); @@ -597,7 +598,7 @@ class SeekBar extends Component { {props.adBreak ? undefined : (
+ style={`transform: translateX(${scrubberProgressPosition})`}>
)} From 1b805d20fb235d69e0818024dd3a23996ba58cf4 Mon Sep 17 00:00:00 2001 From: lianbenjamin <79077248+lianbenjamin@users.noreply.github.com> Date: Mon, 31 Jul 2023 18:57:29 +0300 Subject: [PATCH 4/5] fix documentation --- src/components/progress-bar.js | 4 ++-- src/components/seekbar/seekbar.js | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/progress-bar.js b/src/components/progress-bar.js index 9fd03716d..6e024a8b6 100644 --- a/src/components/progress-bar.js +++ b/src/components/progress-bar.js @@ -18,9 +18,9 @@ const mapStateToProps = state => ({ }); /** - * SeekBar component + * ProgressBar component * - * @class SeekBar + * @class ProgressBar * @extends {Component} */ @connect(mapStateToProps) diff --git a/src/components/seekbar/seekbar.js b/src/components/seekbar/seekbar.js index ec5801743..9966c4c2e 100644 --- a/src/components/seekbar/seekbar.js +++ b/src/components/seekbar/seekbar.js @@ -596,9 +596,7 @@ class SeekBar extends Component { {this.renderTimeBubble()} this.getBufferedPercent} /> {props.adBreak ? undefined : ( -
+
)} From fe676ae88f92647ad794a3e419c785585ebae316 Mon Sep 17 00:00:00 2001 From: lianbenjamin <79077248+lianbenjamin@users.noreply.github.com> Date: Wed, 2 Aug 2023 12:07:32 +0300 Subject: [PATCH 5/5] extract progress indicator comp and styling to a new folder --- .../_progress-indicator.scss | 37 +++++++++++++++++++ src/components/progress-indicator/index.js | 1 + .../progress-indicator.js} | 32 ++++++++++++---- src/components/seekbar/_seekbar.scss | 23 ------------ src/components/seekbar/seekbar.js | 20 +--------- src/styles/style.scss | 1 + 6 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 src/components/progress-indicator/_progress-indicator.scss create mode 100644 src/components/progress-indicator/index.js rename src/components/{progress-bar.js => progress-indicator/progress-indicator.js} (54%) diff --git a/src/components/progress-indicator/_progress-indicator.scss b/src/components/progress-indicator/_progress-indicator.scss new file mode 100644 index 000000000..b9ae98143 --- /dev/null +++ b/src/components/progress-indicator/_progress-indicator.scss @@ -0,0 +1,37 @@ +.player .seek-bar { + &.ad-break { + cursor: initial; + + .progress-bar .progress { + background-color: $ads-color; + } + } + + &.live { + .progress-bar .progress { + background-color: $live-color; + } + } + + .progress-bar { + .progress { + position: absolute; + top: 0; + left: 0; + height: 100%; + border-radius: inherit; + background-color: $primary-color; + } + .buffered { + position: absolute; + top: 0; + left: 0; + height: 100%; + border-radius: inherit; + background-color: rgba(255, 255, 255, 0.3); + } + } +} + + + diff --git a/src/components/progress-indicator/index.js b/src/components/progress-indicator/index.js new file mode 100644 index 000000000..0208925d3 --- /dev/null +++ b/src/components/progress-indicator/index.js @@ -0,0 +1 @@ +export {ProgressIndicator} from './progress-indicator'; diff --git a/src/components/progress-bar.js b/src/components/progress-indicator/progress-indicator.js similarity index 54% rename from src/components/progress-bar.js rename to src/components/progress-indicator/progress-indicator.js index 6e024a8b6..0044033a4 100644 --- a/src/components/progress-bar.js +++ b/src/components/progress-indicator/progress-indicator.js @@ -1,8 +1,8 @@ //@flow import {h, Fragment, Component} from 'preact'; -import style from '../styles/style.scss'; +import style from '../../styles/style.scss'; import {connect} from 'react-redux'; -import {withPlayer} from './player'; +import {withPlayer} from '../player'; /** * mapping state to props @@ -20,21 +20,37 @@ const mapStateToProps = state => ({ /** * ProgressBar component * - * @class ProgressBar + * @class ProgressIndicator * @extends {Component} */ @connect(mapStateToProps) @withPlayer -class ProgressBar extends Component { +class ProgressIndicator extends Component { + /** + * get current buffered percent from the player + * + * @returns {number} - current buffered percent + * @memberof ProgressIndicator + */ + getBufferedPercent(): number { + const {player} = this.props; + if (this.props.duration > 0 && player.buffered.length > 0) { + const buffered = player.isLive() ? player.buffered.end(0) - player.getStartTimeOfDvrWindow() : player.buffered.end(0); + const bufferedPercent = (buffered / this.props.duration) * 100; + return bufferedPercent < 100 ? bufferedPercent : 100; + } + return 0; + } + /** * render component * * @param {*} props - component props * @returns {React$Element} - component - * @memberof ProgressBar + * @memberof ProgressIndicator */ render(props: any): React$Element { - const bufferedWidth = `${Math.round(props.getBufferedPercent())}%`; + const bufferedWidth = `${Math.round(this.getBufferedPercent())}%`; const progressWidth = `${props.player.isLive() && props.player.isOnLiveEdge() ? 100 : (props.currentTime / props.duration) * 100}%`; return ( @@ -45,5 +61,5 @@ class ProgressBar extends Component { } } -ProgressBar.displayName = 'ProgressBar'; -export {ProgressBar}; +ProgressIndicator.displayName = 'ProgressIndicator'; +export {ProgressIndicator}; diff --git a/src/components/seekbar/_seekbar.scss b/src/components/seekbar/_seekbar.scss index 1701b5fd1..9bb2df92f 100644 --- a/src/components/seekbar/_seekbar.scss +++ b/src/components/seekbar/_seekbar.scss @@ -21,16 +21,6 @@ &.ad-break { cursor: initial; - - .progress-bar .progress { - background-color: $ads-color; - } - } - - &.live { - .progress-bar .progress { - background-color: $live-color; - } } .progress-bar { @@ -47,18 +37,9 @@ transform: translateY(-2px); } } - .progress { - position: absolute; - top: 0; - left: 0; - height: 100%; - border-radius: inherit; - background-color: $primary-color; - } .virtual-progress { display: none; } - .buffered, .virtual-progress { position: absolute; top: 0; @@ -67,10 +48,6 @@ border-radius: inherit; } - .buffered { - background-color: rgba(255, 255, 255, 0.3); - } - .virtual-progress-indicator { width: 1px; height: 100%; diff --git a/src/components/seekbar/seekbar.js b/src/components/seekbar/seekbar.js index 9966c4c2e..bf50d3777 100644 --- a/src/components/seekbar/seekbar.js +++ b/src/components/seekbar/seekbar.js @@ -15,7 +15,7 @@ import {PlayerArea} from '../player-area'; import {withEventManager} from 'event/with-event-manager'; import {FakeEvent} from 'event/fake-event'; import {SeekBarPreview} from '../seekbar-preview'; -import {ProgressBar} from '../progress-bar'; +import {ProgressIndicator} from '../progress-indicator'; /** * mapping state to props @@ -450,22 +450,6 @@ class SeekBar extends Component { return time; } - /** - * get current buffered percent from the player - * - * @returns {number} - current buffered percent - * @memberof SeekBar - */ - getBufferedPercent(): number { - const {player} = this.props; - if (this.props.duration > 0 && player.buffered.length > 0) { - const buffered = player.isLive() ? player.buffered.end(0) - player.getStartTimeOfDvrWindow() : player.buffered.end(0); - const bufferedPercent = (buffered / this.props.duration) * 100; - return bufferedPercent < 100 ? bufferedPercent : 100; - } - return 0; - } - /** * get the left position the frame preview element should be in * @@ -594,7 +578,7 @@ class SeekBar extends Component { {this.renderFramePreview()} {this.renderTimeBubble()} - this.getBufferedPercent} /> + {props.adBreak ? undefined : (
diff --git a/src/styles/style.scss b/src/styles/style.scss index b01e46bb4..224b6bac5 100644 --- a/src/styles/style.scss +++ b/src/styles/style.scss @@ -21,6 +21,7 @@ @import '../components/volume/volume'; @import '../components/fullscreen/fullscreen'; @import '../components/seekbar/seekbar'; +@import '../components/progress-indicator/progress-indicator'; @import '../components/seekbar-preview/seekbar-preview'; @import '../components/time-display/time-display'; @import '../components/video-playing-title/video-playing-title';