Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(FEC-13114): add chapters as segments to seekbar #776

Merged
merged 6 commits into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/components/progress-indicator/_progress-indicator.scss
Original file line number Diff line number Diff line change
@@ -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);
}
}
}



1 change: 1 addition & 0 deletions src/components/progress-indicator/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {ProgressIndicator} from './progress-indicator';
65 changes: 65 additions & 0 deletions src/components/progress-indicator/progress-indicator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//@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
});

/**
* ProgressBar component
*
* @class ProgressIndicator
* @extends {Component}
*/
@connect(mapStateToProps)
@withPlayer
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 ProgressIndicator
*/
render(props: any): React$Element<any> {
const bufferedWidth = `${Math.round(this.getBufferedPercent())}%`;
const progressWidth = `${props.player.isLive() && props.player.isOnLiveEdge() ? 100 : (props.currentTime / props.duration) * 100}%`;
return (
<Fragment>
<div className={style.buffered} style={{width: bufferedWidth}} />
{props.dataLoaded ? <div className={style.progress} style={{width: progressWidth}} /> : undefined}
</Fragment>
);
}
}

ProgressIndicator.displayName = 'ProgressIndicator';
export {ProgressIndicator};
33 changes: 8 additions & 25 deletions src/components/seekbar/_seekbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -40,19 +30,16 @@
border-radius: $progress-bar-border-radius;
position: absolute;
transition: height 200ms ease, transform 200ms ease;

.progress {
position: absolute;
top: 0;
left: 0;
height: 100%;
border-radius: inherit;
background-color: $primary-color;
&.chapters {
background-color: transparent;
.virtual-progress-indicator {
height: 8px;
transform: translateY(-2px);
}
}
.virtual-progress {
display: none;
}
.buffered,
.virtual-progress {
position: absolute;
top: 0;
Expand All @@ -61,10 +48,6 @@
border-radius: inherit;
}

.buffered {
background-color: rgba(255, 255, 255, 0.3);
}

.virtual-progress-indicator {
width: 1px;
height: 100%;
Expand All @@ -77,7 +60,7 @@
cursor: pointer;
display: block;
top: -8px + calc($progress-bar-height / 2);
right: -8px;
left: -6px;
border-radius: 8px;
height: 16px;
width: 16px;
Expand Down Expand Up @@ -132,7 +115,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));
Expand Down
33 changes: 9 additions & 24 deletions src/components/seekbar/seekbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {ProgressIndicator} from '../progress-indicator';

/**
* mapping state to props
Expand All @@ -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';
Expand Down Expand Up @@ -448,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
*
Expand Down Expand Up @@ -561,8 +547,7 @@ class SeekBar extends Component {
*/
render(props: any, state: Object): React$Element<any> {
const virtualProgressWidth = `${(props.virtualTime / props.duration) * 100}%`;
const progressWidth = `${props.forceFullProgress ? 100 : (props.currentTime / props.duration) * 100}%`;
const bufferedWidth = `${Math.round(this.getBufferedPercent())}%`;
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);
Expand Down Expand Up @@ -593,12 +578,12 @@ class SeekBar extends Component {
<PlayerArea name={'SeekBar'} shouldUpdate={true}>
{this.renderFramePreview()}
{this.renderTimeBubble()}
<div className={style.buffered} style={{width: bufferedWidth}} />
{props.dataLoaded ? (
<div className={style.progress} style={{width: progressWidth}}>
{props.adBreak ? undefined : <a className={style.scrubber} />}
<ProgressIndicator />
{props.adBreak ? undefined : (
<div id={'scrubber-container'} style={`transform: translateX(${scrubberProgressPosition})`}>
<div id={'scrubber'} className={style.scrubber} />
</div>
) : undefined}
)}
<div className={style.virtualProgress} style={{width: virtualProgressWidth}}>
<div className={style.virtualProgressIndicator} />
</div>
Expand Down
31 changes: 28 additions & 3 deletions src/reducers/seekbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -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) => {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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})
};
1 change: 1 addition & 0 deletions src/styles/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down