Progress
This commit is contained in:
@@ -4,7 +4,7 @@ import { List as ImmutableList } from 'immutable'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { expandAccountFeaturedTimeline, expandAccountTimeline } from '../../actions/timelines'
|
||||
import { fetchAccountIdentityProofs } from '../../actions/identity_proofs'
|
||||
import StatusList from '../../components/status_list/status_list'
|
||||
import StatusList from '../../components/status_list'
|
||||
|
||||
const messages = defineMessages({
|
||||
empty: { id: 'empty_column.account_timeline', defaultMessage: 'No gabs here!' },
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { changeValue, submit, reset } from '../actions/group_editor'
|
||||
import isObject from 'lodash.isobject'
|
||||
import { changeValue, submit, setUp, reset } from '../actions/group_editor'
|
||||
import ColumnIndicator from '../components/column_indicator';
|
||||
import Button from '../components/button'
|
||||
import Divider from '../components/divider'
|
||||
import Input from '../components/input'
|
||||
@@ -13,14 +17,25 @@ const messages = defineMessages({
|
||||
coverImage: { id: 'groups.form.coverImage', defaultMessage: 'Upload a banner image' },
|
||||
coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' },
|
||||
create: { id: 'groups.form.create', defaultMessage: 'Create group' },
|
||||
update: { id: 'groups.form.update', defaultMessage: 'Update group' },
|
||||
})
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
title: state.getIn(['group_editor', 'title']),
|
||||
description: state.getIn(['group_editor', 'description']),
|
||||
coverImage: state.getIn(['group_editor', 'coverImage']),
|
||||
disabled: state.getIn(['group_editor', 'isSubmitting']),
|
||||
})
|
||||
const mapStateToProps = (state, { params }) => {
|
||||
|
||||
console.log('params:', params)
|
||||
|
||||
const groupId = isObject(params) ? params['id'] : null
|
||||
const group = state.getIn(['groups', groupId])
|
||||
|
||||
return {
|
||||
group,
|
||||
error: groupId && !group,
|
||||
title: state.getIn(['group_editor', 'title']),
|
||||
description: state.getIn(['group_editor', 'description']),
|
||||
coverImage: state.getIn(['group_editor', 'coverImage']),
|
||||
disabled: state.getIn(['group_editor', 'isSubmitting']),
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onTitleChange: value => dispatch(changeValue('title', value)),
|
||||
@@ -28,18 +43,20 @@ const mapDispatchToProps = dispatch => ({
|
||||
onCoverImageChange: value => dispatch(changeValue('coverImage', value)),
|
||||
onSubmit: routerHistory => dispatch(submit(routerHistory)),
|
||||
reset: () => dispatch(reset()),
|
||||
setUp: group => dispatch(setUp(group)),
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class Create extends PureComponent {
|
||||
class Create extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
router: PropTypes.object
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
group: ImmutablePropTypes.map,
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
coverImage: PropTypes.object,
|
||||
@@ -50,7 +67,17 @@ class Create extends PureComponent {
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.props.reset()
|
||||
if (!this.props.group) {
|
||||
this.props.reset()
|
||||
} else {
|
||||
this.props.setUp(this.props.group)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.group !== nextProps.group && !!nextProps.group) {
|
||||
this.props.setUp(nextProps.group)
|
||||
}
|
||||
}
|
||||
|
||||
handleTitleChange = e => {
|
||||
@@ -72,6 +99,8 @@ class Create extends PureComponent {
|
||||
|
||||
render() {
|
||||
const {
|
||||
group,
|
||||
error,
|
||||
title,
|
||||
description,
|
||||
coverImage,
|
||||
@@ -79,6 +108,10 @@ class Create extends PureComponent {
|
||||
intl
|
||||
} = this.props
|
||||
|
||||
if (!group && error) {
|
||||
return <ColumnIndicator type='missing' />
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<Input
|
||||
@@ -115,7 +148,7 @@ class Create extends PureComponent {
|
||||
className={_s.marginLeft10PX}
|
||||
>
|
||||
<Text color='white'>
|
||||
{intl.formatMessage(messages.create)}
|
||||
{intl.formatMessage(!!group ? messages.update : messages.create)}
|
||||
</Text>
|
||||
</Button>
|
||||
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { changeValue, submit, setUp } from '../../actions/group_editor';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ColumnIndicator from '../../components/column_indicator';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'groups.form.title', defaultMessage: 'Title' },
|
||||
description: { id: 'groups.form.description', defaultMessage: 'Description' },
|
||||
coverImage: { id: 'groups.form.coverImage', defaultMessage: 'Upload new banner image (optional)' },
|
||||
coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' },
|
||||
update: { id: 'groups.form.update', defaultMessage: 'Update group' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
group: state.getIn(['groups', props.params.id]),
|
||||
title: state.getIn(['group_editor', 'title']),
|
||||
description: state.getIn(['group_editor', 'description']),
|
||||
coverImage: state.getIn(['group_editor', 'coverImage']),
|
||||
disabled: state.getIn(['group_editor', 'isSubmitting']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onTitleChange: value => dispatch(changeValue('title', value)),
|
||||
onDescriptionChange: value => dispatch(changeValue('description', value)),
|
||||
onCoverImageChange: value => dispatch(changeValue('coverImage', value)),
|
||||
onSubmit: routerHistory => dispatch(submit(routerHistory)),
|
||||
setUp: group => dispatch(setUp(group)),
|
||||
});
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class Edit extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
router: PropTypes.object,
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
group: ImmutablePropTypes.map,
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
coverImage: PropTypes.object,
|
||||
disabled: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onTitleChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount(nextProps) {
|
||||
if (this.props.group) {
|
||||
this.props.setUp(this.props.group);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!this.props.group && nextProps.group) {
|
||||
this.props.setUp(nextProps.group);
|
||||
}
|
||||
}
|
||||
|
||||
handleTitleChange = e => {
|
||||
this.props.onTitleChange(e.target.value);
|
||||
}
|
||||
|
||||
handleDescriptionChange = e => {
|
||||
this.props.onDescriptionChange(e.target.value);
|
||||
}
|
||||
|
||||
handleCoverImageChange = e => {
|
||||
this.props.onCoverImageChange(e.target.files[0]);
|
||||
}
|
||||
|
||||
handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
this.props.onSubmit(this.context.router.history);
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onSubmit(this.context.router.history);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { group, title, description, coverImage, disabled, intl } = this.props;
|
||||
|
||||
if (typeof group === 'undefined') {
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (group === false) {
|
||||
return <ColumnIndicator type='missing' />
|
||||
}
|
||||
|
||||
return (
|
||||
<form className='group-form' onSubmit={this.handleSubmit}>
|
||||
<div>
|
||||
<input
|
||||
className='standard'
|
||||
type='text'
|
||||
value={title}
|
||||
disabled={disabled}
|
||||
onChange={this.handleTitleChange}
|
||||
placeholder={intl.formatMessage(messages.title)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<textarea
|
||||
className='standard'
|
||||
type='text'
|
||||
value={description}
|
||||
disabled={disabled}
|
||||
onChange={this.handleDescriptionChange}
|
||||
placeholder={intl.formatMessage(messages.description)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor='group_cover_image' className={classNames('group-form__file-label', { 'group-form__file-label--selected': coverImage !== null })}>
|
||||
{intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
|
||||
</label>
|
||||
|
||||
<input
|
||||
type='file'
|
||||
className='group-form__file'
|
||||
id='group_cover_image'
|
||||
disabled={disabled}
|
||||
onChange={this.handleCoverImageChange}
|
||||
/>
|
||||
|
||||
<button>{intl.formatMessage(messages.update)}</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { changeListEditorTitle, submitListEditor } from '../../../../actions/lists';
|
||||
import ColumnInlineForm from '../../../../components/column_inline_form';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'lists.edit.submit', defaultMessage: 'Change title' },
|
||||
@@ -33,16 +32,18 @@ class ListForm extends PureComponent {
|
||||
render () {
|
||||
const { value, disabled, intl, onSubmit, onChange } = this.props;
|
||||
|
||||
return (
|
||||
<ColumnInlineForm
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onSubmit={onSubmit}
|
||||
label={intl.formatMessage(messages.title)}
|
||||
btnTitle={intl.formatMessage(messages.save)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
return null;
|
||||
|
||||
// return (
|
||||
// <ColumnInlineForm
|
||||
// value={value}
|
||||
// onChange={onChange}
|
||||
// onSubmit={onSubmit}
|
||||
// label={intl.formatMessage(messages.title)}
|
||||
// btnTitle={intl.formatMessage(messages.save)}
|
||||
// disabled={disabled}
|
||||
// />
|
||||
// );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ import {
|
||||
GettingStarted,
|
||||
GroupsCollection,
|
||||
GroupCreate,
|
||||
GroupEdit,
|
||||
GroupMembers,
|
||||
GroupRemovedAccounts,
|
||||
GroupTimeline,
|
||||
@@ -151,7 +150,7 @@ class SwitchingArea extends PureComponent {
|
||||
<WrappedRoute path='/groups/create' page={ModalPage} component={GroupCreate} content={children} componentParams={{ title: 'Create Group' }} />
|
||||
<WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} />
|
||||
<WrappedRoute path='/groups/:id/removed_accounts' page={GroupPage} component={GroupRemovedAccounts} content={children} />
|
||||
<WrappedRoute path='/groups/:id/edit' page={ModalPage} component={GroupEdit} content={children} componentParams={{ title: 'Edit Group' }} />
|
||||
<WrappedRoute path='/groups/:id/edit' page={ModalPage} component={GroupCreate} content={children} componentParams={{ title: 'Edit Group' }} />
|
||||
<WrappedRoute path='/groups/:id' page={GroupPage} component={GroupTimeline} content={children} />
|
||||
|
||||
<WrappedRoute path='/tags/:id' publicRoute page={BasicPage} component={HashtagTimeline} content={children} componentParams={{ title: 'Hashtag' }} />
|
||||
|
||||
@@ -58,10 +58,6 @@ export function GroupCreate() {
|
||||
return import(/* webpackChunkName: "features/group_create" */'../../group_create')
|
||||
}
|
||||
|
||||
export function GroupEdit() {
|
||||
return import(/* webpackChunkName: "features/group_edit" */'../../group_edit')
|
||||
}
|
||||
|
||||
export function GroupMembers() {
|
||||
return import(/* webpackChunkName: "features/group_members" */'../../group_members')
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import { fromJS, is } from 'immutable';
|
||||
import { throttle } from 'lodash';
|
||||
import classNames from 'classnames';
|
||||
import { decode } from 'blurhash';
|
||||
import { isFullscreen, requestFullscreen, exitFullscreen } from '../../utils/fullscreen';
|
||||
import { isPanoramic, isPortrait, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio';
|
||||
import { displayMedia } from '../../initial_state';
|
||||
import Icon from '../../components/icon';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||
import { fromJS, is } from 'immutable'
|
||||
import { throttle } from 'lodash'
|
||||
import classNames from 'classnames/bind'
|
||||
import { decode } from 'blurhash'
|
||||
import { isFullscreen, requestFullscreen, exitFullscreen } from '../../utils/fullscreen'
|
||||
import { isPanoramic, isPortrait, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio'
|
||||
import { displayMedia } from '../../initial_state'
|
||||
import Button from '../../components/button'
|
||||
import Icon from '../../components/icon'
|
||||
import Text from '../../components/text'
|
||||
|
||||
const cx = classNames.bind(_s)
|
||||
|
||||
const messages = defineMessages({
|
||||
play: { id: 'video.play', defaultMessage: 'Play' },
|
||||
@@ -14,8 +18,6 @@ const messages = defineMessages({
|
||||
mute: { id: 'video.mute', defaultMessage: 'Mute sound' },
|
||||
unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' },
|
||||
hide: { id: 'video.hide', defaultMessage: 'Hide video' },
|
||||
expand: { id: 'video.expand', defaultMessage: 'Expand video' },
|
||||
close: { id: 'video.close', defaultMessage: 'Close video' },
|
||||
fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' },
|
||||
exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
|
||||
});
|
||||
@@ -106,7 +108,6 @@ class Video extends PureComponent {
|
||||
onToggleVisibility: PropTypes.func,
|
||||
intl: PropTypes.object.isRequired,
|
||||
blurhash: PropTypes.string,
|
||||
link: PropTypes.node,
|
||||
aspectRatio: PropTypes.number,
|
||||
};
|
||||
|
||||
@@ -302,7 +303,7 @@ class Video extends PureComponent {
|
||||
const hash = this.props.blurhash;
|
||||
const pixels = decode(hash, 32, 32);
|
||||
|
||||
if (pixels) {
|
||||
if (pixels && this.canvas) {
|
||||
const ctx = this.canvas.getContext('2d');
|
||||
const imageData = new ImageData(pixels, 32, 32);
|
||||
|
||||
@@ -353,30 +354,35 @@ class Video extends PureComponent {
|
||||
this.setState({ volume: this.video.volume, muted: this.video.muted });
|
||||
}
|
||||
|
||||
handleOpenVideo = () => {
|
||||
const { src, preview, width, height, alt } = this.props;
|
||||
|
||||
const media = fromJS({
|
||||
type: 'video',
|
||||
url: src,
|
||||
preview_url: preview,
|
||||
description: alt,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
|
||||
this.video.pause();
|
||||
this.props.onOpenVideo(media, this.video.currentTime);
|
||||
}
|
||||
|
||||
handleCloseVideo = () => {
|
||||
this.video.pause();
|
||||
this.props.onCloseVideo();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed, sensitive, link, aspectRatio } = this.props;
|
||||
const { containerWidth, currentTime, duration, volume, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
|
||||
const {
|
||||
preview,
|
||||
src,
|
||||
inline,
|
||||
startTime,
|
||||
onOpenVideo,
|
||||
onCloseVideo,
|
||||
intl,
|
||||
alt,
|
||||
detailed,
|
||||
sensitive,
|
||||
aspectRatio
|
||||
} = this.props
|
||||
|
||||
const {
|
||||
containerWidth,
|
||||
currentTime,
|
||||
duration,
|
||||
volume,
|
||||
buffer,
|
||||
dragging,
|
||||
paused,
|
||||
fullscreen,
|
||||
hovered,
|
||||
muted,
|
||||
revealed
|
||||
} = this.state
|
||||
|
||||
const progress = (currentTime / duration) * 100;
|
||||
|
||||
const volumeWidth = (muted) ? 0 : volume * this.volWidth;
|
||||
@@ -385,6 +391,8 @@ class Video extends PureComponent {
|
||||
|
||||
let { width, height } = this.props;
|
||||
|
||||
console.log("buffer, progress:", buffer, progress)
|
||||
|
||||
if (inline && containerWidth) {
|
||||
width = containerWidth;
|
||||
const minSize = containerWidth / (16 / 9);
|
||||
@@ -418,10 +426,40 @@ class Video extends PureComponent {
|
||||
warning = <FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' />;
|
||||
}
|
||||
|
||||
// console.log("width, height:", width, height)
|
||||
|
||||
// className={classNames('video-player', {
|
||||
// inactive: !revealed,
|
||||
// detailed,
|
||||
// inline: inline && !fullscreen,
|
||||
// fullscreen
|
||||
// })}
|
||||
|
||||
const seekHandleClasses = cx({
|
||||
default: 1,
|
||||
positionAbsolute: 1,
|
||||
circle: 1,
|
||||
paddingHorizontal10PX: 1,
|
||||
paddingVertical10PX: 1,
|
||||
backgroundColorBrand: 1,
|
||||
marginLeftNeg5PX: 1,
|
||||
z3: 1,
|
||||
opacity0: !dragging,
|
||||
opacity1: dragging || hovered,
|
||||
})
|
||||
|
||||
const progressClasses = cx({
|
||||
default: 1,
|
||||
radiusSmall: 1,
|
||||
marginTop10PX: 1,
|
||||
positionAbsolute: 1,
|
||||
height4PX: 1,
|
||||
})
|
||||
|
||||
return (
|
||||
<div
|
||||
role='menuitem'
|
||||
className={classNames('video-player', { inactive: !revealed, detailed, inline: inline && !fullscreen, fullscreen })}
|
||||
className={[_s.default].join(' ')}
|
||||
style={playerStyle}
|
||||
ref={this.setPlayerRef}
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
@@ -429,81 +467,129 @@ class Video extends PureComponent {
|
||||
onClick={this.handleClickRoot}
|
||||
tabIndex={0}
|
||||
>
|
||||
<canvas width={32} height={32} ref={this.setCanvasRef} className={classNames('media-gallery__preview', { 'media-gallery__preview--hidden': revealed })} />
|
||||
|
||||
{revealed && <video
|
||||
playsInline
|
||||
ref={this.setVideoRef}
|
||||
src={src}
|
||||
poster={preview}
|
||||
preload={preload}
|
||||
loop
|
||||
role='button'
|
||||
tabIndex='0'
|
||||
aria-label={alt}
|
||||
title={alt}
|
||||
width={width}
|
||||
height={height}
|
||||
volume={volume}
|
||||
onClick={this.togglePlay}
|
||||
onPlay={this.handlePlay}
|
||||
onPause={this.handlePause}
|
||||
onTimeUpdate={this.handleTimeUpdate}
|
||||
onLoadedData={this.handleLoadedData}
|
||||
onProgress={this.handleProgress}
|
||||
onVolumeChange={this.handleVolumeChange}
|
||||
/>}
|
||||
{
|
||||
!revealed &&
|
||||
<canvas
|
||||
width={32}
|
||||
height={32}
|
||||
ref={this.setCanvasRef}
|
||||
className={[_s.default, _s.positionAbsolute, _s.height100PC, _s.width100PC, _s.top0, _s.left0].join(' ')}
|
||||
/>
|
||||
}
|
||||
|
||||
<div className={classNames('spoiler-button', { 'spoiler-button--hidden': revealed })}>
|
||||
|
||||
{
|
||||
revealed &&
|
||||
<video
|
||||
className={[_s.default, _s.height100PC, _s.width100PC, _s.outlineNone].join(' ')}
|
||||
playsInline
|
||||
ref={this.setVideoRef}
|
||||
src={src}
|
||||
poster={preview}
|
||||
preload={preload}
|
||||
loop
|
||||
role='button'
|
||||
tabIndex='0'
|
||||
aria-label={alt}
|
||||
title={alt}
|
||||
width={width}
|
||||
height={height}
|
||||
volume={volume}
|
||||
onClick={this.togglePlay}
|
||||
onPlay={this.handlePlay}
|
||||
onPause={this.handlePause}
|
||||
onTimeUpdate={this.handleTimeUpdate}
|
||||
onLoadedData={this.handleLoadedData}
|
||||
onProgress={this.handleProgress}
|
||||
onVolumeChange={this.handleVolumeChange}
|
||||
/>
|
||||
}
|
||||
|
||||
{ /* <div className={classNames('spoiler-button', { 'spoiler-button--hidden': revealed })}>
|
||||
<button type='button' className='spoiler-button__overlay' onClick={this.toggleReveal}>
|
||||
<span className='spoiler-button__overlay__label'>{warning}</span>
|
||||
</button>
|
||||
</div> */ }
|
||||
|
||||
<div className='video-player__volume' onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}>
|
||||
<div className='video-player__volume__current' style={{ height: `${volumeWidth}px` }} />
|
||||
<span
|
||||
className={classNames('video-player__volume__handle')}
|
||||
tabIndex='0'
|
||||
style={{ left: `${volumeHandleLoc}px` }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={classNames('video-player__controls', { active: paused || hovered })}>
|
||||
<div className='video-player__seek' onMouseDown={this.handleMouseDown} ref={this.setSeekRef}>
|
||||
<div className='video-player__seek__buffer' style={{ width: `${buffer}%` }} />
|
||||
<div className='video-player__seek__progress' style={{ width: `${progress}%` }} />
|
||||
<div className={[_s.default, _s.z2, _s.paddingHorizontal15PX, _s.videoPlayerControlsBackground, _s.positionAbsolute, _s.bottom0, _s.right0, _s.left0].join(' ')}>
|
||||
|
||||
<div
|
||||
className={[_s.default, _s.cursorPointer, _s.height22PX, _s.videoPlayerSeek].join(' ')}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
ref={this.setSeekRef}
|
||||
>
|
||||
|
||||
<div className={[progressClasses, _s.backgroundPanel, _s.width100PC].join(' ')} />
|
||||
<div className={[progressClasses, _s.backgroundSubtle].join(' ')} style={{ width: `${buffer}%` }} />
|
||||
<div className={[progressClasses, _s.backgroundColorBrand].join(' ')} style={{ width: `${progress}%` }} />
|
||||
|
||||
<span
|
||||
className={classNames('video-player__seek__handle', { active: dragging })}
|
||||
className={seekHandleClasses}
|
||||
tabIndex='0'
|
||||
style={{ left: `${progress}%` }}
|
||||
style={{
|
||||
left: `${progress}%`
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='video-player__buttons-bar'>
|
||||
<div className='video-player__buttons left'>
|
||||
<button type='button' aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><Icon id={paused ? 'play' : 'pause'} fixedWidth /></button>
|
||||
<button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><Icon id={muted ? 'volume-off' : 'volume-up'} fixedWidth /></button>
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter, _s.paddingBottom5PX, _s.noSelect].join(' ')}>
|
||||
<Button
|
||||
narrow
|
||||
backgroundColor='none'
|
||||
aria-label={intl.formatMessage(paused ? messages.play : messages.pause)}
|
||||
onClick={this.togglePlay}
|
||||
icon={paused ? 'play' : 'pause'}
|
||||
iconWidth='16px'
|
||||
iconHeight='16px'
|
||||
iconClassName={_s.fillColorWhite}
|
||||
className={_s.paddingLeft0}
|
||||
/>
|
||||
|
||||
<div className='video-player__volume' onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}>
|
||||
<div className='video-player__volume__current' style={{ width: `${volumeWidth}px` }} />
|
||||
<span
|
||||
className={classNames('video-player__volume__handle')}
|
||||
tabIndex='0'
|
||||
style={{ left: `${volumeHandleLoc}px` }}
|
||||
/>
|
||||
</div>
|
||||
<div className={[_s.default, _s.marginLeftAuto, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||
<Text color='white' size='small'>
|
||||
{formatTime(currentTime)}
|
||||
/
|
||||
{formatTime(duration)}
|
||||
</Text>
|
||||
|
||||
{(detailed || fullscreen) && (
|
||||
<span>
|
||||
<span className='video-player__time-current'>{formatTime(currentTime)}</span>
|
||||
<span className='video-player__time-sep'>/</span>
|
||||
<span className='video-player__time-total'>{formatTime(duration)}</span>
|
||||
</span>
|
||||
)}
|
||||
|
||||
{link && <span className='video-player__link'>{link}</span>}
|
||||
</div>
|
||||
<Button
|
||||
narrow
|
||||
backgroundColor='none'
|
||||
type='button'
|
||||
aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)}
|
||||
onClick={this.toggleMute}
|
||||
icon={muted ? 'audio-mute' : 'audio'}
|
||||
iconWidth='24px'
|
||||
iconHeight='24px'
|
||||
iconClassName={_s.fillColorWhite}
|
||||
className={[_s.paddingHorizontal10PX, _s.marginLeft10PX].join(' ')}
|
||||
/>
|
||||
|
||||
<div className='video-player__buttons right'>
|
||||
{!onCloseVideo && <button type='button' aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><Icon id='eye-slash' fixedWidth /></button>}
|
||||
{(!fullscreen && onOpenVideo) && <button type='button' aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><Icon id='expand' fixedWidth /></button>}
|
||||
{onCloseVideo && <button type='button' aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><Icon id='compress' fixedWidth /></button>}
|
||||
<button type='button' aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><Icon id={fullscreen ? 'compress' : 'arrows-alt'} fixedWidth /></button>
|
||||
<Button
|
||||
narrow
|
||||
backgroundColor='none'
|
||||
aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)}
|
||||
onClick={this.toggleFullscreen}
|
||||
icon={fullscreen ? 'minimize-fullscreen' : 'fullscreen'}
|
||||
iconWidth='20px'
|
||||
iconHeight='20px'
|
||||
iconClassName={_s.fillColorWhite}
|
||||
className={[_s.paddingHorizontal10PX, _s.paddingRight0].join(' ')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -218,37 +218,6 @@
|
||||
@include size(100%, 40x);
|
||||
}
|
||||
|
||||
&__progress,
|
||||
&__buffer {
|
||||
display: block;
|
||||
height: 4px;
|
||||
border-radius: 4px;
|
||||
background: lighten($ui-highlight-color, 8%);
|
||||
|
||||
@include abs-position(10px);
|
||||
}
|
||||
|
||||
&__buffer {
|
||||
background: rgba($white, 0.2);
|
||||
}
|
||||
|
||||
&__handle {
|
||||
z-index: 3;
|
||||
opacity: 0;
|
||||
margin-left: -6px;
|
||||
transition: opacity .1s ease;
|
||||
background: lighten($ui-highlight-color, 8%);
|
||||
box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2);
|
||||
pointer-events: none;
|
||||
|
||||
@include circle(12px);
|
||||
@include abs-position(6px);
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.video-player__seek__handle {
|
||||
opacity: 1;
|
||||
|
||||
Reference in New Issue
Block a user