Skip to content

Commit

Permalink
feat(FEC-13114): add chapters as segments to seekbar (#776)
Browse files Browse the repository at this point in the history
### Description of the Changes

part of the Advanced Timeline feature.
this PR contains changes and new code for supporting segments on the
seekbar, whenever there are chapters.

- extracting the progress & buffered element to a new comp named
ProgressBar
- add new state `segments` to seekbar
- add new actions for updating the segments

**related PR-** kaltura/playkit-js-timeline#11

Solves FEC-13114

### CheckLists

- [x] changes have been done against master branch, and PR does not
conflict
- [ ] new unit / functional tests have been added (whenever applicable)
- [ ] test are passing in local environment
- [ ] Travis tests are passing (or test results are not worse than on
master branch :))
- [ ] Docs have been updated
  • Loading branch information
lianbenjamin authored Aug 2, 2023
1 parent 5fdc0df commit 5519099
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 52 deletions.
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

0 comments on commit 5519099

Please sign in to comment.