Progress
accounts approved, video player testing, bookmark collections
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import ModalLayout from './modal_layout'
|
||||
import BookmarkCollectionEdit from '../../features/bookmark_collection_edit'
|
||||
|
||||
class BookmarkCollectionEditModal extends React.PureComponent {
|
||||
|
||||
render() {
|
||||
const { onClose } = this.props
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
title='Edit Bookmark Collection'
|
||||
width={500}
|
||||
onClose={onClose}
|
||||
>
|
||||
<BookmarkCollectionEdit isModal />
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BookmarkCollectionEditModal.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
export default BookmarkCollectionEditModal
|
||||
@@ -164,6 +164,7 @@ class EditProfileModal extends ImmutablePureComponent {
|
||||
<Input
|
||||
id='display-name'
|
||||
title='Display name'
|
||||
maxLength={30}
|
||||
value={displayNameValue}
|
||||
onChange={this.handleDisplayNameChange}
|
||||
onBlur={this.handleDisplayNameBlur}
|
||||
@@ -176,6 +177,7 @@ class EditProfileModal extends ImmutablePureComponent {
|
||||
title='Bio'
|
||||
value={bioValue}
|
||||
disabled={false}
|
||||
maxLength={500}
|
||||
onChange={this.handleBioChange}
|
||||
placeholder='Add your bio...'
|
||||
/>
|
||||
|
||||
@@ -33,7 +33,7 @@ class ProfileNavigationBar extends React.PureComponent {
|
||||
<Button
|
||||
icon='ellipsis'
|
||||
iconSize='26px'
|
||||
iconClassName={_s.inheritFill}
|
||||
iconClassName={_s.colorNavigation}
|
||||
color='brand'
|
||||
backgroundColor='none'
|
||||
className={[_s.jcCenter, _s.aiCenter, _s.ml10, _s.px10].join(' ')}
|
||||
|
||||
@@ -40,7 +40,8 @@ class ShopPanel extends React.PureComponent {
|
||||
isError,
|
||||
} = this.props
|
||||
|
||||
if (!items || isError || !Array.isArray(items)) return null
|
||||
if (!items || isError || !Array.isArray(items)) return <div />
|
||||
if (items.length <= 0) return <div />
|
||||
|
||||
return (
|
||||
<PanelLayout
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
} from '../../constants'
|
||||
import PopoverLayout from './popover_layout'
|
||||
import List from '../list'
|
||||
import Text from '../text'
|
||||
|
||||
class ChatConversationExpirationOptionsPopover extends React.PureComponent {
|
||||
|
||||
@@ -94,7 +95,7 @@ class ChatConversationExpirationOptionsPopover extends React.PureComponent {
|
||||
isXS={isXS}
|
||||
onClose={this.handleOnClosePopover}
|
||||
>
|
||||
<Text className={[_s.d, _s.px15, _s.py10, _s.bgSecondary].join(' ')}>This chats delete after:</Text>
|
||||
<Text className={[_s.d, _s.px15, _s.py10, _s.bgSecondary].join(' ')}>Chats delete after:</Text>
|
||||
<List
|
||||
scrollKey='chat_conversation_expiration'
|
||||
items={listItems}
|
||||
|
||||
@@ -106,7 +106,7 @@ class ComposePostDesinationPopover extends ImmutablePureComponent {
|
||||
<div className={[_s.d, _s.w100PC, _s.overflowYScroll, _s.maxH340PX].join(' ')}>
|
||||
<List
|
||||
scrollKey='groups-post-destination-add'
|
||||
showLoading={groups.size === 0}
|
||||
showLoading={groups.length === 0}
|
||||
emptyMessage="You are not a member of any groups yet."
|
||||
items={groupItems}
|
||||
/>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
BREAKPOINT_EXTRA_SMALL,
|
||||
POPOVER_CHAT_CONVERSATION_EXPIRATION_OPTIONS,
|
||||
POPOVER_CHAT_CONVERSATION_OPTIONS,
|
||||
POPOVER_CHAT_MESSAGE_OPTIONS,
|
||||
POPOVER_COMMENT_SORTING_OPTIONS,
|
||||
@@ -23,6 +24,7 @@ import {
|
||||
POPOVER_VIDEO_STATS,
|
||||
} from '../../constants'
|
||||
import {
|
||||
ChatConversationExpirationOptionsPopover,
|
||||
ChatConversationOptionsPopover,
|
||||
ChatMessageOptionsPopover,
|
||||
CommentSortingOptionsPopover,
|
||||
@@ -60,6 +62,7 @@ import LoadingPopover from './loading_popover'
|
||||
const initialState = getWindowDimension()
|
||||
|
||||
const POPOVER_COMPONENTS = {
|
||||
[POPOVER_CHAT_CONVERSATION_EXPIRATION_OPTIONS]: ChatConversationExpirationOptionsPopover,
|
||||
[POPOVER_CHAT_CONVERSATION_OPTIONS]: ChatConversationOptionsPopover,
|
||||
[POPOVER_CHAT_MESSAGE_OPTIONS]: ChatMessageOptionsPopover,
|
||||
[POPOVER_COMMENT_SORTING_OPTIONS]: CommentSortingOptionsPopover,
|
||||
|
||||
@@ -21,6 +21,10 @@ import {
|
||||
editStatus,
|
||||
} from '../../actions/statuses';
|
||||
import { quoteCompose } from '../../actions/compose'
|
||||
import {
|
||||
fetchBookmarkCollections,
|
||||
updateBookmarkCollectionStatus,
|
||||
} from '../../actions/bookmarks'
|
||||
import {
|
||||
fetchGroupRelationships,
|
||||
createRemovedAccount,
|
||||
@@ -40,7 +44,9 @@ import {
|
||||
POPOVER_STATUS_SHARE,
|
||||
} from '../../constants'
|
||||
import PopoverLayout from './popover_layout'
|
||||
import Button from '../button'
|
||||
import List from '../list'
|
||||
import Text from '../text'
|
||||
|
||||
class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
|
||||
@@ -48,11 +54,9 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
router: PropTypes.object,
|
||||
}
|
||||
|
||||
updateOnProps = [
|
||||
'status',
|
||||
'groupRelationships',
|
||||
'isXS',
|
||||
]
|
||||
state = {
|
||||
showingBookmarkCollections: false,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
@@ -109,6 +113,7 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
handleBookmarkClick = () => {
|
||||
// : todo : add to specific bookmark collection
|
||||
if (this.props.isPro) {
|
||||
this.props.onBookmark(this.props.status)
|
||||
} else {
|
||||
@@ -116,6 +121,19 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
handleBookmarkChangeClick = () => {
|
||||
if (!this.props.bookmarkCollectionsIsFetched) this.props.onFetchBookmarkCollections()
|
||||
this.setState({ showingBookmarkCollections: true })
|
||||
}
|
||||
|
||||
handleBookmarkChangeBackClick = () => {
|
||||
this.setState({ showingBookmarkCollections: false })
|
||||
}
|
||||
|
||||
handleBookmarkChangeSelectClick = (bookmarkCollectionId) => {
|
||||
this.props.onUpdateBookmarkCollectionStatus(this.props.status.get('id'), bookmarkCollectionId)
|
||||
}
|
||||
|
||||
handleDeleteClick = () => {
|
||||
this.props.onDelete(this.props.status)
|
||||
}
|
||||
@@ -142,11 +160,13 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
|
||||
render() {
|
||||
const {
|
||||
status,
|
||||
intl,
|
||||
groupRelationships,
|
||||
isXS,
|
||||
intl,
|
||||
status,
|
||||
groupRelationships,
|
||||
bookmarkCollections,
|
||||
} = this.props
|
||||
const { showingBookmarkCollections } = this.state
|
||||
|
||||
if (!status) return <div />
|
||||
|
||||
@@ -155,8 +175,6 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
const isReply = !!status.get('in_reply_to_id')
|
||||
const withGroupAdmin = !!groupRelationships ? (groupRelationships.get('admin') || groupRelationships.get('moderator')) : false
|
||||
|
||||
console.log("publicStatus:", status, publicStatus)
|
||||
|
||||
let menu = []
|
||||
|
||||
if (me) {
|
||||
@@ -171,11 +189,19 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
|
||||
menu.push({
|
||||
icon: 'bookmark',
|
||||
hideArrow: true,
|
||||
hideArrow: status.get('bookmarked'),
|
||||
title: intl.formatMessage(status.get('bookmarked') ? messages.unbookmark : messages.bookmark),
|
||||
onClick: this.handleBookmarkClick,
|
||||
})
|
||||
|
||||
|
||||
if (status.get('bookmarked')) {
|
||||
menu.push({
|
||||
icon: 'bookmark',
|
||||
title: 'Update bookmark collection',
|
||||
onClick: this.handleBookmarkChangeClick,
|
||||
})
|
||||
}
|
||||
|
||||
if (status.getIn(['account', 'id']) === me) {
|
||||
if (publicStatus) {
|
||||
menu.push({
|
||||
@@ -264,16 +290,62 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
})
|
||||
}
|
||||
|
||||
const popoverWidth = !isStaff ? 260 : 362
|
||||
|
||||
let bookmarkCollectionItems = !!bookmarkCollections ? bookmarkCollections.map((bookmarkCollection) => ({
|
||||
hideArrow: true,
|
||||
onClick: () => this.handleBookmarkChangeSelectClick(bookmarkCollection.get('id')),
|
||||
title: bookmarkCollection.get('title'),
|
||||
isActive: bookmarkCollection.get('id') === status.get('bookmark_collection_id'),
|
||||
})) : []
|
||||
bookmarkCollectionItems = bookmarkCollectionItems.unshift({
|
||||
hideArrow: true,
|
||||
onClick: () => this.handleBookmarkChangeSelectClick('saved'),
|
||||
title: 'Saved',
|
||||
isActive: !status.get('bookmark_collection_id'),
|
||||
})
|
||||
|
||||
return (
|
||||
<PopoverLayout
|
||||
isXS={isXS}
|
||||
onClose={this.handleClosePopover}
|
||||
width={popoverWidth}
|
||||
>
|
||||
<List
|
||||
scrollKey='profile_options'
|
||||
items={menu}
|
||||
size={isXS ? 'large' : 'small'}
|
||||
/>
|
||||
{
|
||||
!showingBookmarkCollections &&
|
||||
<List
|
||||
scrollKey='profile_options'
|
||||
items={menu}
|
||||
size={isXS ? 'large' : 'small'}
|
||||
/>
|
||||
}
|
||||
{
|
||||
showingBookmarkCollections &&
|
||||
<div className={[_s.d, _s.w100PC].join(' ')}>
|
||||
<div className={[_s.d, _s.flexRow, _s.bgSecondary].join(' ')}>
|
||||
<Button
|
||||
isText
|
||||
icon='back'
|
||||
color='primary'
|
||||
backgroundColor='none'
|
||||
className={[_s.aiCenter, _s.jcCenter, _s.pl15, _s.pr5].join(' ')}
|
||||
onClick={this.handleBookmarkChangeBackClick}
|
||||
/>
|
||||
<Text className={[_s.d, _s.pl5, _s.py10].join(' ')}>
|
||||
Select bookmark collection:
|
||||
</Text>
|
||||
</div>
|
||||
<div className={[_s.d, _s.w100PC, _s.overflowYScroll, _s.maxH340PX].join(' ')}>
|
||||
<List
|
||||
scrollKey='status_options_bookmark_collections'
|
||||
showLoading={bookmarkCollectionItems.length === 0}
|
||||
emptyMessage="You have no bookmark collections yet."
|
||||
items={bookmarkCollectionItems}
|
||||
size={isXS ? 'large' : 'small'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</PopoverLayout>
|
||||
)
|
||||
}
|
||||
@@ -323,6 +395,8 @@ const mapStateToProps = (state, { statusId }) => {
|
||||
groupId,
|
||||
groupRelationships,
|
||||
isPro: state.getIn(['accounts', me, 'is_pro']),
|
||||
bookmarkCollectionsIsFetched: state.getIn(['bookmark_collections', 'isFetched']),
|
||||
bookmarkCollections: state.getIn(['bookmark_collections', 'items']),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,7 +528,6 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
dispatch(closePopover())
|
||||
dispatch(openModal(MODAL_PRO_UPGRADE))
|
||||
},
|
||||
|
||||
onPinGroupStatus(status) {
|
||||
dispatch(closePopover())
|
||||
|
||||
@@ -464,7 +537,13 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
dispatch(pinGroupStatus(status.getIn(['group', 'id']), status.get('id')))
|
||||
}
|
||||
},
|
||||
|
||||
onFetchBookmarkCollections() {
|
||||
dispatch(fetchBookmarkCollections())
|
||||
},
|
||||
onUpdateBookmarkCollectionStatus(statusId, bookmarkCollectionId) {
|
||||
dispatch(updateBookmarkCollectionStatus(statusId, bookmarkCollectionId))
|
||||
dispatch(closePopover())
|
||||
},
|
||||
onClosePopover: () => dispatch(closePopover()),
|
||||
})
|
||||
|
||||
@@ -487,6 +566,8 @@ StatusOptionsPopover.propTypes = {
|
||||
fetchIsPinnedGroupStatus: PropTypes.func.isRequired,
|
||||
fetchIsBookmark: PropTypes.func.isRequired,
|
||||
fetchIsPin: PropTypes.func.isRequired,
|
||||
onFetchBookmarkCollections: PropTypes.func.isRequired,
|
||||
onUpdateBookmarkCollectionStatus: PropTypes.func.isRequired,
|
||||
isXS: PropTypes.bool,
|
||||
isPro: PropTypes.bool,
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import PopoverLayout from './popover_layout'
|
||||
import AccountActionButton from '../account_action_button'
|
||||
import Avatar from '../avatar'
|
||||
import DisplayName from '../display_name'
|
||||
import Text from '../text'
|
||||
import UserStat from '../user_stat'
|
||||
|
||||
class UserInfoPopover extends ImmutablePureComponent {
|
||||
|
||||
@@ -47,28 +47,19 @@ class UserInfoPopover extends ImmutablePureComponent {
|
||||
</div>
|
||||
|
||||
<div className={[_s.d, _s.flexRow, _s.mt10].join(' ')}>
|
||||
<NavLink
|
||||
to={`${to}/followers`}
|
||||
className={[_s.d, _s.flexRow, _s.mr10, _s.noUnderline, _s.cPrimary, _s.underline_onHover].join(' ')}
|
||||
>
|
||||
<Text weight='extraBold' color='primary'>
|
||||
{shortNumberFormat(account.get('followers_count'))}
|
||||
</Text>
|
||||
<Text color='secondary'>
|
||||
<FormattedMessage id='account.followers' defaultMessage='Followers' />
|
||||
</Text>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
to={`${to}/following`}
|
||||
className={[_s.d, _s.flexRow, _s.noUnderline, _s.cPrimary, _s.underline_onHover].join(' ')}
|
||||
>
|
||||
<Text weight='extraBold' color='primary'>
|
||||
{shortNumberFormat(account.get('following_count'))}
|
||||
</Text>
|
||||
<Text color='secondary'>
|
||||
<FormattedMessage id='account.follows' defaultMessage='Following' />
|
||||
</Text>
|
||||
</NavLink>
|
||||
<UserStat
|
||||
title={<FormattedMessage id='account.followers' defaultMessage='Followers' />}
|
||||
value={shortNumberFormat(account.get('followers_count'))}
|
||||
to={`/${account.get('acct')}/followers`}
|
||||
isInline
|
||||
/>
|
||||
<UserStat
|
||||
isLast
|
||||
title={<FormattedMessage id='account.follows' defaultMessage='Following' />}
|
||||
value={shortNumberFormat(account.get('following_count'))}
|
||||
to={`/${account.get('acct')}/following`}
|
||||
isInline
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -424,4 +424,8 @@ StatusList.propTypes = {
|
||||
promotedStatuses: PropTypes.object,
|
||||
}
|
||||
|
||||
StatusList.defaultProps = {
|
||||
statusIds: ImmutableList(),
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(StatusList)
|
||||
@@ -19,6 +19,7 @@ class Textarea extends React.PureComponent {
|
||||
onBlur,
|
||||
title,
|
||||
isRequired,
|
||||
maxLength,
|
||||
} = this.props
|
||||
|
||||
const inputClasses = CX({
|
||||
@@ -58,6 +59,7 @@ class Textarea extends React.PureComponent {
|
||||
onKeyUp={onKeyUp}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
maxLength={maxLength}
|
||||
required={isRequired ? true : undefined}
|
||||
/>
|
||||
|
||||
@@ -77,6 +79,7 @@ Textarea.propTypes = {
|
||||
onBlur: PropTypes.func,
|
||||
title: PropTypes.string,
|
||||
isRequired: PropTypes.bool,
|
||||
maxLength: PropTypes.number,
|
||||
}
|
||||
|
||||
export default Textarea
|
||||
@@ -27,6 +27,7 @@ class ShopInjection extends React.PureComponent {
|
||||
} = this.props
|
||||
|
||||
if (!items || isError || !Array.isArray(items)) return <div />
|
||||
if (items.length <= 0) return <div />
|
||||
|
||||
return (
|
||||
<TimelineInjectionLayout
|
||||
|
||||
@@ -38,8 +38,11 @@ class UserStat extends React.PureComponent {
|
||||
|
||||
const align = isCentered ? 'center' : 'left'
|
||||
const titleSize = isInline ? 'normal' : 'extraLarge'
|
||||
const subtitleSize = isInline ? 'normal' : 'small'
|
||||
const titleColor = isInline ? 'primary' : 'brand'
|
||||
const titleWeight = isInline ? 'extraBold' : 'bold'
|
||||
|
||||
const subtitleSize = isInline ? 'normal' : 'small'
|
||||
|
||||
const containerClasses = CX({
|
||||
d: 1,
|
||||
cursorPointer: 1,
|
||||
@@ -64,7 +67,7 @@ class UserStat extends React.PureComponent {
|
||||
onMouseEnter={this.handleOnMouseEnter}
|
||||
onMouseLeave={this.handleOnMouseLeave}
|
||||
>
|
||||
<Text size={titleSize} weight='bold' color='brand' align={align}>
|
||||
<Text size={titleSize} weight={titleWeight} color={titleColor} align={align}>
|
||||
{value}
|
||||
</Text>
|
||||
<Text size={subtitleSize} weight='medium' color='secondary' hasUnderline={hovering} align={align} className={subtitleClasses}>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { is } from 'immutable'
|
||||
import throttle from 'lodash.throttle'
|
||||
import { decode } from 'blurhash'
|
||||
import videojs from 'video.js'
|
||||
import { isFullscreen, requestFullscreen, exitFullscreen } from '../utils/fullscreen'
|
||||
import { isPanoramic, isPortrait, minimumAspectRatio, maximumAspectRatio } from '../utils/media_aspect_ratio'
|
||||
import {
|
||||
@@ -24,10 +25,24 @@ import Icon from './icon'
|
||||
import SensitiveMediaItem from './sensitive_media_item'
|
||||
import Text from './text'
|
||||
|
||||
import '!style-loader!css-loader!video.js/dist/video-js.min.css'
|
||||
|
||||
// check every 100 ms for buffer
|
||||
const checkInterval = 100
|
||||
const FIXED_VAR = 6
|
||||
|
||||
const videoJsOptions = {
|
||||
autoplay: false,
|
||||
playbackRates: [0.5, 1, 1.25, 1.5, 2],
|
||||
width: 720,
|
||||
height: 300,
|
||||
controls: true,
|
||||
sources: [{
|
||||
// src: '//vjs.zencdn.net/v/oceans.mp4',
|
||||
type: 'video/mp4',
|
||||
}],
|
||||
};
|
||||
|
||||
const formatTime = (secondsNum) => {
|
||||
if (isNaN(secondsNum)) secondsNum = 0
|
||||
|
||||
@@ -135,6 +150,13 @@ class Video extends ImmutablePureComponent {
|
||||
if ('pictureInPictureEnabled' in document) {
|
||||
this.setState({ pipAvailable: true })
|
||||
}
|
||||
|
||||
videoJsOptions.sources = [{ src: this.props.src }]
|
||||
console.log("videoJsOptions:", videoJsOptions)
|
||||
// instantiate video.js
|
||||
this.videoPlayer = videojs(this.videoNode, videoJsOptions, function onPlayerReady() {
|
||||
console.log('onPlayerReady', this)
|
||||
})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@@ -144,6 +166,10 @@ class Video extends ImmutablePureComponent {
|
||||
document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange, true)
|
||||
|
||||
clearInterval(this.bufferCheckInterval)
|
||||
|
||||
if (this.videoPlayer) {
|
||||
this.videoPlayer.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
@@ -199,6 +225,7 @@ class Video extends ImmutablePureComponent {
|
||||
|
||||
setVideoRef = (n) => {
|
||||
this.video = n
|
||||
this.videoNode = n
|
||||
|
||||
if (this.video) {
|
||||
const { volume, muted } = this.video
|
||||
@@ -581,175 +608,34 @@ class Video extends ImmutablePureComponent {
|
||||
>
|
||||
|
||||
<div className={overlayClasses} id='overlay'>
|
||||
{
|
||||
paused && !isBuffering &&
|
||||
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||
<button
|
||||
onClick={this.togglePlay}
|
||||
className={[_s.d, _s.outlineNone, _s.cursorPointer, _s.aiCenter, _s.jcCenter, _s.posAbs, _s.bgBlackOpaque, _s.circle, _s.h60PX, _s.w60PX].join(' ')}
|
||||
>
|
||||
<Icon id='play' size='24px' className={_s.cWhite} />
|
||||
</button>
|
||||
</Responsive>
|
||||
}
|
||||
{
|
||||
!paused && true &&
|
||||
<Icon id='loading' size='60px' className={[_s.d, _s.posAbs].join(' ')} />
|
||||
}
|
||||
</div>
|
||||
|
||||
<video
|
||||
className={[_s.d, _s.h100PC, _s.w100PC, _s.outlineNone].join(' ')}
|
||||
playsInline
|
||||
ref={this.setVideoRef}
|
||||
src={src}
|
||||
poster={preview}
|
||||
preload={preload}
|
||||
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={volumeControlClasses}
|
||||
onMouseDown={this.handleVolumeMouseDown}
|
||||
onMouseEnter={this.handleMouseEnterVolumeControl}
|
||||
onMouseLeave={this.handleMouseLeaveVolumeControl}
|
||||
ref={this.setVolumeRef}
|
||||
>
|
||||
<div
|
||||
className={[_s.d, _s.radiusSmall, _s.my10, _s.posAbs, _s.w4PX, _s.ml10, _s.bgPrimaryOpaque].join(' ')}
|
||||
style={{
|
||||
height: '102px',
|
||||
}}
|
||||
<div data-vjs-player>
|
||||
<video
|
||||
className={[_s.d, _s.h100PC, _s.w100PC, _s.outlineNone, 'video-js'].join(' ')}
|
||||
ref={this.setVideoRef}
|
||||
// playsInline
|
||||
// poster={preview}
|
||||
// preload={preload}
|
||||
// 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={[_s.d, _s.radiusSmall, _s.my10, _s.bottom0, _s.posAbs, _s.w4PX, _s.ml10, _s.bgPrimary].join(' ')}
|
||||
style={{
|
||||
height: `${volumeHeight}px`
|
||||
}}
|
||||
/>
|
||||
<span
|
||||
className={[_s.d, _s.cursorPointer, _s.posAbs, _s.circle, _s.px5, _s.boxShadow1, _s.mbNeg5PX, _s.py5, _s.bgPrimary, _s.z3].join(' ')}
|
||||
tabIndex='0'
|
||||
style={{
|
||||
marginLeft: '7px',
|
||||
bottom: `${volumeHandleLoc}px`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={videoControlsBackgroundClasses}>
|
||||
|
||||
<div
|
||||
className={[_s.d, _s.cursorPointer, _s.h22PX, _s.videoPlayerSeek].join(' ')}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
ref={this.setSeekRef}
|
||||
>
|
||||
|
||||
<div className={[progressClasses, _s.bgLoading, _s.w100PC].join(' ')} />
|
||||
<div className={[progressClasses, _s.bgSubtle].join(' ')} style={{ width: `${buffer}%` }} />
|
||||
<div className={[progressClasses, _s.bgBrand].join(' ')} style={{ width: `${progress}%` }} />
|
||||
|
||||
<span
|
||||
className={seekHandleClasses}
|
||||
tabIndex='0'
|
||||
style={{
|
||||
left: `${progress}%`
|
||||
}}
|
||||
>
|
||||
<span className={seekInnerHandleClasses} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className={[_s.d, _s.flexRow, _s.aiCenter, _s.pb5, _s.noSelect].join(' ')}>
|
||||
<Button
|
||||
isNarrow
|
||||
backgroundColor='none'
|
||||
aria-label={intl.formatMessage(paused ? messages.play : messages.pause)}
|
||||
onClick={this.togglePlay}
|
||||
icon={paused ? 'play' : 'pause'}
|
||||
title={paused ? 'Play' : 'Pause'}
|
||||
iconSize='16px'
|
||||
iconClassName={_s.cWhite}
|
||||
className={_s.pl0}
|
||||
/>
|
||||
|
||||
<Button
|
||||
isNarrow
|
||||
backgroundColor='none'
|
||||
type='button'
|
||||
aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)}
|
||||
onClick={this.toggleMute}
|
||||
icon={muted ? 'audio-mute' : 'audio'}
|
||||
iconSize='24px'
|
||||
iconClassName={_s.cWhite}
|
||||
className={[_s.px10, _s.mr10].join(' ')}
|
||||
title='Volume'
|
||||
onMouseEnter={this.handleMouseEnterAudio}
|
||||
onMouseLeave={this.handleMouseLeaveAudio}
|
||||
/>
|
||||
|
||||
<Text color='white' size='small'>
|
||||
{formatTime(currentTime)}
|
||||
/
|
||||
{formatTime(duration)}
|
||||
</Text>
|
||||
|
||||
<div className={[_s.d, _s.mlAuto, _s.flexRow, _s.aiCenter].join(' ')}>
|
||||
<Button
|
||||
isNarrow
|
||||
backgroundColor='none'
|
||||
aria-label={intl.formatMessage(messages.video_stats)}
|
||||
onClick={this.handleOnClickSettings}
|
||||
icon='cog'
|
||||
iconSize='20px'
|
||||
iconClassName={_s.cWhite}
|
||||
className={[_s.px10, _s.pr0].join(' ')}
|
||||
buttonRef={this.setSettingsBtnRef}
|
||||
title='Video stats'
|
||||
/>
|
||||
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||
{
|
||||
pipAvailable &&
|
||||
<Button
|
||||
isNarrow
|
||||
backgroundColor='none'
|
||||
aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)}
|
||||
onClick={this.togglePip}
|
||||
icon='copy'
|
||||
iconSize='20px'
|
||||
iconClassName={_s.cWhite}
|
||||
className={[_s.px10, _s.pr0].join(' ')}
|
||||
title='Picture in Picture'
|
||||
/>
|
||||
}
|
||||
</Responsive>
|
||||
<Button
|
||||
isNarrow
|
||||
backgroundColor='none'
|
||||
aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)}
|
||||
onClick={this.toggleFullscreen}
|
||||
icon={fullscreen ? 'minimize-fullscreen' : 'fullscreen'}
|
||||
title={fullscreen ? 'Minimize fullscreen' : 'Fullscreen'}
|
||||
iconSize='20px'
|
||||
iconClassName={_s.cWhite}
|
||||
className={[_s.px10, _s.pr0].join(' ')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user