Progress
This commit is contained in:
parent
da3d0c3462
commit
557c6470f5
@ -157,7 +157,7 @@ export const expandPublicTimeline = ({ maxId, onlyMedia } = {}, done = noOp) =>
|
|||||||
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done);
|
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done);
|
||||||
export const expandAccountTimeline = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId });
|
export const expandAccountTimeline = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId });
|
||||||
export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true });
|
export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true });
|
||||||
export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 20 });
|
export const expandAccountMediaTimeline = (accountId, { maxId, limit } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: limit || 20 });
|
||||||
export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
|
export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
|
||||||
export const expandGroupTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { max_id: maxId }, done);
|
export const expandGroupTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`group:${id}`, `/api/v1/timelines/group/${id}`, { max_id: maxId }, done);
|
||||||
export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noOp) => {
|
export const expandHashtagTimeline = (hashtag, { maxId, tags } = {}, done = noOp) => {
|
||||||
|
26
app/javascript/gabsocial/assets/happy_icon.js
Normal file
26
app/javascript/gabsocial/assets/happy_icon.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
const HappyIcon = ({
|
||||||
|
className = '',
|
||||||
|
width = '16px',
|
||||||
|
height = '16px',
|
||||||
|
viewBox = '0 0 64 64',
|
||||||
|
title = '',
|
||||||
|
}) => (
|
||||||
|
<svg
|
||||||
|
className={className}
|
||||||
|
version='1.1'
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
x='0px'
|
||||||
|
y='0px'
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
viewBox={viewBox}
|
||||||
|
xmlSpace='preserve'
|
||||||
|
aria-label={title}
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<path d='M 54.667969 9.371094 C 42.179688 -3.121094 21.855469 -3.121094 9.367188 9.367188 C -3.125 21.855469 -3.121094 42.179688 9.367188 54.667969 C 21.855469 67.160156 42.179688 67.160156 54.667969 54.667969 C 67.15625 42.179688 67.15625 21.855469 54.667969 9.371094 Z M 51.175781 51.175781 C 40.613281 61.738281 23.425781 61.738281 12.863281 51.175781 C 2.296875 40.613281 2.296875 23.421875 12.863281 12.859375 C 23.425781 2.296875 40.609375 2.296875 51.175781 12.863281 C 61.738281 23.425781 61.738281 40.613281 51.175781 51.175781 Z M 20.070312 23.347656 C 20.070312 21.28125 21.746094 19.605469 23.8125 19.605469 C 25.878906 19.605469 27.558594 21.28125 27.558594 23.347656 C 27.558594 25.417969 25.878906 27.09375 23.8125 27.09375 C 21.746094 27.09375 20.070312 25.417969 20.070312 23.347656 Z M 37.046875 23.347656 C 37.046875 21.28125 38.722656 19.605469 40.789062 19.605469 C 42.859375 19.605469 44.535156 21.28125 44.535156 23.347656 C 44.535156 25.417969 42.859375 27.09375 40.789062 27.09375 C 38.722656 27.09375 37.046875 25.417969 37.046875 23.347656 Z M 45.898438 38.683594 C 43.578125 44.046875 38.144531 47.515625 32.054688 47.515625 C 25.835938 47.515625 20.367188 44.03125 18.128906 38.636719 C 17.746094 37.714844 18.183594 36.65625 19.105469 36.269531 C 19.335938 36.175781 19.570312 36.132812 19.800781 36.132812 C 20.511719 36.132812 21.183594 36.550781 21.472656 37.25 C 23.152344 41.285156 27.304688 43.894531 32.054688 43.894531 C 36.699219 43.894531 40.824219 41.285156 42.570312 37.246094 C 42.96875 36.328125 44.035156 35.902344 44.953125 36.300781 C 45.871094 36.699219 46.292969 37.765625 45.898438 38.683594 Z M 45.898438 38.683594' />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default HappyIcon
|
@ -15,6 +15,7 @@ import ErrorIcon from './error_icon'
|
|||||||
import FullscreenIcon from './fullscreen_icon'
|
import FullscreenIcon from './fullscreen_icon'
|
||||||
import GlobeIcon from './globe_icon'
|
import GlobeIcon from './globe_icon'
|
||||||
import GroupIcon from './group_icon'
|
import GroupIcon from './group_icon'
|
||||||
|
import HappyIcon from './happy_icon'
|
||||||
import HomeIcon from './home_icon'
|
import HomeIcon from './home_icon'
|
||||||
import LikeIcon from './like_icon'
|
import LikeIcon from './like_icon'
|
||||||
import LinkIcon from './link_icon'
|
import LinkIcon from './link_icon'
|
||||||
@ -57,6 +58,7 @@ export {
|
|||||||
FullscreenIcon,
|
FullscreenIcon,
|
||||||
GlobeIcon,
|
GlobeIcon,
|
||||||
GroupIcon,
|
GroupIcon,
|
||||||
|
HappyIcon,
|
||||||
HomeIcon,
|
HomeIcon,
|
||||||
LikeIcon,
|
LikeIcon,
|
||||||
LinkIcon,
|
LinkIcon,
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { Fragment } from 'react'
|
import { Fragment } from 'react'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import Textarea from 'react-textarea-autosize';
|
import Textarea from 'react-textarea-autosize'
|
||||||
import { isRtl } from '../../utils/rtl';
|
import { isRtl } from '../../utils/rtl'
|
||||||
import { textAtCursorMatchesToken } from '../../utils/cursor_token_match';
|
import { textAtCursorMatchesToken } from '../../utils/cursor_token_match'
|
||||||
import AutosuggestAccount from '../autosuggest_account';
|
import AutosuggestAccount from '../autosuggest_account'
|
||||||
import AutosuggestEmoji from '../autosuggest_emoji';
|
import AutosuggestEmoji from '../autosuggest_emoji'
|
||||||
|
import Input from '../input'
|
||||||
|
|
||||||
const cx = classNames.bind(_s)
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
@ -191,12 +192,24 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { value, small, suggestions, disabled, placeholder, onKeyUp, autoFocus, children, className, id, maxLength, textarea } = this.props;
|
const {
|
||||||
const { suggestionsHidden } = this.state;
|
value,
|
||||||
const style = { direction: 'ltr' };
|
small,
|
||||||
|
suggestions,
|
||||||
|
disabled,
|
||||||
|
placeholder,
|
||||||
|
onKeyUp,
|
||||||
|
autoFocus,
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
id,
|
||||||
|
maxLength,
|
||||||
|
textarea
|
||||||
|
} = this.props
|
||||||
|
|
||||||
if (isRtl(value)) {
|
const { suggestionsHidden } = this.state
|
||||||
style.direction = 'rtl';
|
const style = {
|
||||||
|
direction: isRtl(value) ? 'rtl' : 'ltr',
|
||||||
}
|
}
|
||||||
|
|
||||||
const textClasses = cx({
|
const textClasses = cx({
|
||||||
@ -249,11 +262,11 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='autosuggest-input'>
|
<div className={[_s.default, _s.flexGrow1].join(' ')}>
|
||||||
<label>
|
<label className={[_s.default].join(' ')}>
|
||||||
<span style={{ display: 'none' }}>{placeholder}</span>
|
<span style={{ display: 'none' }}>{placeholder}</span>
|
||||||
|
|
||||||
<input
|
<Input
|
||||||
type='text'
|
type='text'
|
||||||
ref={this.setTextbox}
|
ref={this.setTextbox}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
@ -79,11 +79,14 @@ export default class Button extends PureComponent {
|
|||||||
...otherProps
|
...otherProps
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const theIcon = !!icon ? <Icon id={icon} width={iconWidth} height={iconWidth} className={iconClassName} /> : undefined
|
const theIcon = !!icon ? (
|
||||||
|
<Icon
|
||||||
if (backgroundColor === 'tertiary') {
|
id={icon}
|
||||||
console.log("className:", className)
|
width={iconWidth}
|
||||||
}
|
height={iconWidth}
|
||||||
|
className={iconClassName}
|
||||||
|
/>
|
||||||
|
) : undefined
|
||||||
|
|
||||||
// : todo :
|
// : todo :
|
||||||
const classes = cx(className, {
|
const classes = cx(className, {
|
||||||
@ -93,6 +96,7 @@ export default class Button extends PureComponent {
|
|||||||
cursorPointer: 1,
|
cursorPointer: 1,
|
||||||
textAlignCenter: 1,
|
textAlignCenter: 1,
|
||||||
outlineNone: 1,
|
outlineNone: 1,
|
||||||
|
flexRow: !!children && !!icon,
|
||||||
|
|
||||||
backgroundColorPrimary: backgroundColor === COLORS.white,
|
backgroundColorPrimary: backgroundColor === COLORS.white,
|
||||||
backgroundColorBrand: backgroundColor === COLORS.brand,
|
backgroundColorBrand: backgroundColor === COLORS.brand,
|
||||||
@ -143,6 +147,7 @@ export default class Button extends PureComponent {
|
|||||||
to: to || undefined,
|
to: to || undefined,
|
||||||
href: href || undefined,
|
href: href || undefined,
|
||||||
onClick: this.handleClick || undefined,
|
onClick: this.handleClick || undefined,
|
||||||
|
...otherProps,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tagName === 'NavLink' && !!to) {
|
if (tagName === 'NavLink' && !!to) {
|
||||||
|
@ -1,67 +1,53 @@
|
|||||||
import { injectIntl, defineMessages } from 'react-intl'
|
|
||||||
import TabBar from './tab_bar'
|
import TabBar from './tab_bar'
|
||||||
import Icon from './icon'
|
|
||||||
import Button from './button'
|
import Button from './button'
|
||||||
import Heading from './heading'
|
import Heading from './heading'
|
||||||
|
|
||||||
const messages = defineMessages({
|
export default class ColumnHeader extends PureComponent {
|
||||||
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
|
||||||
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
|
|
||||||
})
|
|
||||||
|
|
||||||
export default
|
|
||||||
@injectIntl
|
|
||||||
class ColumnHeader extends PureComponent {
|
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
router: PropTypes.object,
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
title: PropTypes.node,
|
title: PropTypes.node,
|
||||||
icon: PropTypes.string,
|
|
||||||
active: PropTypes.bool,
|
|
||||||
children: PropTypes.node,
|
|
||||||
showBackBtn: PropTypes.bool,
|
showBackBtn: PropTypes.bool,
|
||||||
actions: PropTypes.array,
|
actions: PropTypes.array,
|
||||||
tabs: PropTypes.array,
|
tabs: PropTypes.array,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
|
||||||
collapsed: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
historyBack = () => {
|
historyBack = () => {
|
||||||
if (window.history && window.history.length === 1) {
|
if (window.history && window.history.length === 1) {
|
||||||
this.context.router.history.push('/home') // homehack
|
this.context.router.history.push('/home')
|
||||||
} else {
|
} else {
|
||||||
this.context.router.history.goBack()
|
this.context.router.history.goBack()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleToggleClick = (e) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
this.setState({
|
|
||||||
collapsed: !this.state.collapsed,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
handleBackClick = () => {
|
handleBackClick = () => {
|
||||||
this.historyBack()
|
this.historyBack()
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { title, showBackBtn, tabs, icon, active, children, actions, intl: { formatMessage } } = this.props
|
const {
|
||||||
const { collapsed } = this.state
|
title,
|
||||||
|
showBackBtn,
|
||||||
|
tabs,
|
||||||
|
actions
|
||||||
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.default, _s.height100PC, _s.flexRow].join(' ')}>
|
<div className={[_s.default, _s.height100PC, _s.flexRow].join(' ')}>
|
||||||
{
|
{
|
||||||
showBackBtn &&
|
showBackBtn &&
|
||||||
<button className={[_s.default, _s.cursorPointer, _s.backgroundTransparent, _s.alignItemsCenter, _s.marginRight10PX, _s.justifyContentCenter].join(' ')}>
|
<Button
|
||||||
<Icon className={[_s.marginRight5PX, _s.fillColorPrimary].join(' ')} id='back' width='20px' height='20px' />
|
backgroundColor='none'
|
||||||
</button>
|
className={[_s.alignItemsCenter, _s.paddingLeft0, _s.justifyContentCenter].join(' ')}
|
||||||
|
icon='back'
|
||||||
|
iconWidth='20px'
|
||||||
|
iconHeight='20px'
|
||||||
|
iconClassName={[_s.marginRight5PX, _s.fillColorPrimary].join(' ')}
|
||||||
|
onClick={this.handleBackClick}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div className={[_s.default, _s.height100PC, _s.justifyContentCenter, _s.marginRight10PX].join(' ')}>
|
<div className={[_s.default, _s.height100PC, _s.justifyContentCenter, _s.marginRight10PX].join(' ')}>
|
||||||
@ -80,13 +66,17 @@ class ColumnHeader extends PureComponent {
|
|||||||
<div className={[_s.default, _s.backgroundTransparent, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.marginLeftAuto].join(' ')}>
|
<div className={[_s.default, _s.backgroundTransparent, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.marginLeftAuto].join(' ')}>
|
||||||
{
|
{
|
||||||
actions.map((action, i) => (
|
actions.map((action, i) => (
|
||||||
<button
|
<Button
|
||||||
|
radiusSmall
|
||||||
|
backgroundColor='tertiary'
|
||||||
onClick={() => action.onClick()}
|
onClick={() => action.onClick()}
|
||||||
key={`column-header-action-btn-${i}`}
|
key={`column-header-action-btn-${i}`}
|
||||||
className={[_s.default, _s.marginLeft5PX, _s.cursorPointer, _s.backgroundSubtle2, _s.paddingHorizontal10PX, _s.paddingVertical10PX, _s.radiusSmall].join(' ')}
|
className={[_s.marginLeft5PX, _s.paddingHorizontal10PX].join(' ')}
|
||||||
>
|
iconClassName={_s.fillColorSecondary}
|
||||||
<Icon className={_s.fillColorSecondary} id={action.icon} width='20px' height='20px' />
|
icon={action.icon}
|
||||||
</button>
|
iconWidth='20px'
|
||||||
|
iconHeight='20px'
|
||||||
|
/>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,6 +45,8 @@ export default class Icon extends PureComponent {
|
|||||||
return <I.GlobeIcon {...options} />
|
return <I.GlobeIcon {...options} />
|
||||||
case 'group':
|
case 'group':
|
||||||
return <I.GroupIcon {...options} />
|
return <I.GroupIcon {...options} />
|
||||||
|
case 'happy':
|
||||||
|
return <I.HappyIcon {...options} />
|
||||||
case 'home':
|
case 'home':
|
||||||
return <I.HomeIcon {...options} />
|
return <I.HomeIcon {...options} />
|
||||||
case 'like':
|
case 'like':
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { Fragment } from 'react'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import Icon from './icon'
|
import Icon from './icon'
|
||||||
import Text from './text'
|
import Text from './text'
|
||||||
@ -16,6 +17,7 @@ export default class Input extends PureComponent {
|
|||||||
onBlur: PropTypes.func,
|
onBlur: PropTypes.func,
|
||||||
onClear: PropTypes.func,
|
onClear: PropTypes.func,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
|
small: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -29,7 +31,8 @@ export default class Input extends PureComponent {
|
|||||||
onFocus,
|
onFocus,
|
||||||
onBlur,
|
onBlur,
|
||||||
onClear,
|
onClear,
|
||||||
title
|
title,
|
||||||
|
small
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const inputClasses = cx({
|
const inputClasses = cx({
|
||||||
@ -48,7 +51,7 @@ export default class Input extends PureComponent {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<Fragment>
|
||||||
{
|
{
|
||||||
!!title &&
|
!!title &&
|
||||||
<div className={[_s.default, _s.marginBottom10PX, _s.paddingLeft15PX].join(' ')}>
|
<div className={[_s.default, _s.marginBottom10PX, _s.paddingLeft15PX].join(' ')}>
|
||||||
@ -81,7 +84,7 @@ export default class Input extends PureComponent {
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,14 +3,18 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
|
|||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import { decode } from 'blurhash'
|
import { decode } from 'blurhash'
|
||||||
import { autoPlayGif, displayMedia } from '../initial_state'
|
import { autoPlayGif, displayMedia } from '../initial_state'
|
||||||
|
import classNames from 'classnames/bind'
|
||||||
import Icon from './icon'
|
import Icon from './icon'
|
||||||
import Image from './image'
|
import Image from './image'
|
||||||
import Text from './text'
|
import Text from './text'
|
||||||
|
|
||||||
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
export default class MediaItem extends ImmutablePureComponent {
|
export default class MediaItem extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
attachment: ImmutablePropTypes.map.isRequired,
|
attachment: ImmutablePropTypes.map.isRequired,
|
||||||
|
small: PropTypes.bool
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -55,7 +59,7 @@ export default class MediaItem extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { attachment } = this.props
|
const { attachment, small } = this.props
|
||||||
const { visible, loaded } = this.state
|
const { visible, loaded } = this.state
|
||||||
|
|
||||||
const status = attachment.get('status')
|
const status = attachment.get('status')
|
||||||
@ -71,13 +75,33 @@ export default class MediaItem extends ImmutablePureComponent {
|
|||||||
badge = 'GIF'
|
badge = 'GIF'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const containerClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
positionAbsolute: 1,
|
||||||
|
top0: 1,
|
||||||
|
height100PC: 1,
|
||||||
|
width100PC: 1,
|
||||||
|
paddingVertical5PX: !small,
|
||||||
|
paddingHorizontal5PX: !small,
|
||||||
|
})
|
||||||
|
|
||||||
|
const linkClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
width100PC: 1,
|
||||||
|
height100PC: 1,
|
||||||
|
overflowHidden: 1,
|
||||||
|
border1PX: 1,
|
||||||
|
borderColorSecondary: !small,
|
||||||
|
borderColorWhite: small,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.default, _s.width25PC, _s.paddingTop25PC].join(' ')}>
|
<div className={[_s.default, _s.width25PC, _s.paddingTop25PC].join(' ')}>
|
||||||
<div className={[_s.default, _s.positionAbsolute, _s.top0, _s.height100PC, _s.width100PC, _s.paddingVertical5PX, _s.paddingHorizontal5PX].join(' ')}>
|
<div className={containerClasses}>
|
||||||
<NavLink
|
<NavLink
|
||||||
to={status.get('url')} /* : todo : */
|
to={status.get('url')} /* : todo : */
|
||||||
title={title}
|
title={title}
|
||||||
className={[_s.default, _s.width100PC, _s.height100PC, _s.border1PX, _s.borderColorSecondary, _s.overflowHidden].join(' ')}
|
className={linkClasses}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
(!loaded || !visible) &&
|
(!loaded || !visible) &&
|
||||||
|
@ -48,8 +48,11 @@ class ComposeModal extends ImmutablePureComponent {
|
|||||||
const { intl } = this.props;
|
const { intl } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalLayout title={intl.formatMessage(messages.title)} onClose={this.onClickClose}>
|
<ModalLayout
|
||||||
<TimelineComposeBlock />
|
noPadding
|
||||||
|
title={intl.formatMessage(messages.title)} onClose={this.onClickClose}
|
||||||
|
>
|
||||||
|
<TimelineComposeBlock modal />
|
||||||
</ModalLayout>
|
</ModalLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ class ModalBase extends PureComponent {
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<div
|
<div
|
||||||
role='presentation'
|
role='presentation'
|
||||||
className={[_s.default, _s.backgroundColorPrimaryOpaque, _s.positionFixed, _s.z3, _s.top0, _s.right0, _s.bottom0, _s.left0].join(' ')}
|
className={[_s.default, _s.backgroundColorOpaque, _s.positionFixed, _s.z3, _s.top0, _s.right0, _s.bottom0, _s.left0].join(' ')}
|
||||||
onClick={this.handleOnClose}
|
onClick={this.handleOnClose}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
@ -17,7 +17,12 @@ class ModalLayout extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { title, children, intl, onClose } = this.props
|
const {
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
intl,
|
||||||
|
onClose,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.width645PX].join(' ')}>
|
<div className={[_s.width645PX].join(' ')}>
|
||||||
@ -27,12 +32,13 @@ class ModalLayout extends PureComponent {
|
|||||||
{title}
|
{title}
|
||||||
</Heading>
|
</Heading>
|
||||||
<Button
|
<Button
|
||||||
className=''
|
backgroundColor='none'
|
||||||
title={intl.formatMessage(messages.close)}
|
title={intl.formatMessage(messages.close)}
|
||||||
|
className={_s.marginLeftAuto}
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
icon='times'
|
icon='close'
|
||||||
iconWidth='20px'
|
iconWidth='10px'
|
||||||
iconWidth='20px'
|
iconWidth='10px'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX].join(' ')}>
|
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX].join(' ')}>
|
||||||
|
@ -1,52 +1,82 @@
|
|||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import { fetchSuggestions, dismissSuggestion } from '../../actions/suggestions'
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import AccountContainer from '../../containers/account_container'
|
import { expandAccountMediaTimeline } from '../../actions/timelines'
|
||||||
|
import { getAccountGallery } from '../../selectors'
|
||||||
import PanelLayout from './panel_layout'
|
import PanelLayout from './panel_layout'
|
||||||
|
import MediaItem from '../media_item'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'media_gallery_panel.title', defaultMessage: 'Media' },
|
title: { id: 'media_gallery_panel.title', defaultMessage: 'Media' },
|
||||||
show_all: { id: 'media_gallery_panel.all', defaultMessage: 'Show all' },
|
show_all: { id: 'media_gallery_panel.all', defaultMessage: 'Show all' },
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = (state, { account }) => {
|
||||||
suggestions: state.getIn(['suggestions', 'items']),
|
const accountId = !!account ? account.get('id') : -1
|
||||||
})
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
return {
|
||||||
fetchSuggestions: () => dispatch(fetchSuggestions()),
|
accountId,
|
||||||
dismissSuggestion: account => dispatch(dismissSuggestion(account.get('id'))),
|
attachments: getAccountGallery(state, accountId),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@connect(mapStateToProps, mapDispatchToProps)
|
@connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
class MediaGalleryPanel extends ImmutablePureComponent {
|
class MediaGalleryPanel extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
dispatch: PropTypes.func.isRequired,
|
||||||
|
accountId: PropTypes.string,
|
||||||
account: ImmutablePropTypes.map.isRequired,
|
account: ImmutablePropTypes.map.isRequired,
|
||||||
|
attachments: ImmutablePropTypes.list.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
// this.props.fetchSuggestions()
|
const { accountId } = this.props
|
||||||
|
|
||||||
|
if (accountId) {
|
||||||
|
this.props.dispatch(expandAccountMediaTimeline(accountId, {limit: 8}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (nextProps.accountId && nextProps.accountId !== this.props.accountId) {
|
||||||
|
this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, {limit: 8}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { intl, account } = this.props
|
const {
|
||||||
|
intl,
|
||||||
|
account,
|
||||||
|
attachments
|
||||||
|
} = this.props
|
||||||
|
|
||||||
console.log("account:", account)
|
console.log("account, attachments:", account, attachments)
|
||||||
|
|
||||||
|
if (!account || !attachments) return null
|
||||||
|
if (attachments.size === 0) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelLayout
|
<PanelLayout
|
||||||
|
noPadding
|
||||||
title={intl.formatMessage(messages.title)}
|
title={intl.formatMessage(messages.title)}
|
||||||
headerButtonTitle={intl.formatMessage(messages.show_all)}
|
headerButtonTitle={intl.formatMessage(messages.show_all)}
|
||||||
headerButtonTo='/explore'
|
headerButtonTo={`/${account.get('acct')}/media`}
|
||||||
>
|
>
|
||||||
|
<div className={[_s.default, _s.flexRow, _s.flexWrap, _s.paddingHorizontal10PX, _s.paddingVertical10PX].join(' ')}>
|
||||||
|
{
|
||||||
|
attachments.slice(0, 16).map((attachment) => (
|
||||||
|
<MediaItem
|
||||||
|
small
|
||||||
|
key={attachment.get('id')}
|
||||||
|
attachment={attachment}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</PanelLayout>
|
</PanelLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ const mapStateToProps = (state, { account }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
fetchSuggestions: () => dispatch(fetchSuggestions()),
|
fetchSuggestions: () => dispatch(fetchSuggestions()),
|
||||||
|
@ -1,29 +1,34 @@
|
|||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import { Fragment } from 'react'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import classNames from 'classnames';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||||
import escapeTextContentForBrowser from 'escape-html';
|
import classNames from 'classnames/bind'
|
||||||
import spring from 'react-motion/lib/spring';
|
import escapeTextContentForBrowser from 'escape-html'
|
||||||
import Motion from '../../features/ui/util/optional_motion';
|
import spring from 'react-motion/lib/spring'
|
||||||
import { vote, fetchPoll } from '../../actions/polls';
|
import Motion from '../../features/ui/util/optional_motion'
|
||||||
import emojify from '../emoji/emoji';
|
import { vote } from '../../actions/polls'
|
||||||
import RelativeTimestamp from '../relative_timestamp';
|
import emojify from '../emoji/emoji'
|
||||||
import Button from '../button';
|
import RelativeTimestamp from '../relative_timestamp'
|
||||||
|
import Button from '../button'
|
||||||
|
import DotTextSeperator from '../dot_text_seperator'
|
||||||
|
import Text from '../text'
|
||||||
|
|
||||||
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
const mapStateToProps = (state, { pollId }) => ({
|
const mapStateToProps = (state, { pollId }) => ({
|
||||||
poll: state.getIn(['polls', pollId]),
|
poll: state.getIn(['polls', pollId]),
|
||||||
});
|
})
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
closed: { id: 'poll.closed', defaultMessage: 'Closed' },
|
closed: { id: 'poll.closed', defaultMessage: 'Closed' },
|
||||||
vote: { id: 'poll.vote', defaultMessage: 'Vote' },
|
vote: { id: 'poll.vote', defaultMessage: 'Vote' },
|
||||||
refresh: { id: 'poll.refresh', defaultMessage: 'Refresh' },
|
refresh: { id: 'poll.refresh', defaultMessage: 'Refresh' },
|
||||||
});
|
})
|
||||||
|
|
||||||
const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => {
|
const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => {
|
||||||
obj[`:${emoji.get('shortcode')}:`] = emoji.toJS();
|
obj[`:${emoji.get('shortcode')}:`] = emoji.toJS()
|
||||||
return obj;
|
return obj
|
||||||
}, {});
|
}, {})
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@connect(mapStateToProps)
|
@connect(mapStateToProps)
|
||||||
@ -35,71 +40,91 @@ class Poll extends ImmutablePureComponent {
|
|||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
dispatch: PropTypes.func,
|
dispatch: PropTypes.func,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
};
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
selected: {},
|
selected: {},
|
||||||
};
|
}
|
||||||
|
|
||||||
handleOptionChange = e => {
|
handleOptionChange = e => {
|
||||||
const { target: { value } } = e;
|
const { target: { value } } = e
|
||||||
|
|
||||||
if (this.props.poll.get('multiple')) {
|
if (this.props.poll.get('multiple')) {
|
||||||
const tmp = { ...this.state.selected };
|
const tmp = { ...this.state.selected }
|
||||||
if (tmp[value]) {
|
if (tmp[value]) {
|
||||||
delete tmp[value];
|
delete tmp[value]
|
||||||
} else {
|
} else {
|
||||||
tmp[value] = true;
|
tmp[value] = true
|
||||||
}
|
}
|
||||||
this.setState({ selected: tmp });
|
this.setState({ selected: tmp })
|
||||||
} else {
|
} else {
|
||||||
const tmp = {};
|
const tmp = {}
|
||||||
tmp[value] = true;
|
tmp[value] = true
|
||||||
this.setState({ selected: tmp });
|
this.setState({ selected: tmp })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
handleVote = () => {
|
handleVote = () => {
|
||||||
if (this.props.disabled) return;
|
if (this.props.disabled) return
|
||||||
|
|
||||||
this.props.dispatch(vote(this.props.poll.get('id'), Object.keys(this.state.selected)));
|
this.props.dispatch(vote(this.props.poll.get('id'), Object.keys(this.state.selected)))
|
||||||
};
|
|
||||||
|
|
||||||
handleRefresh = () => {
|
|
||||||
if (this.props.disabled) return;
|
|
||||||
|
|
||||||
this.props.dispatch(fetchPoll(this.props.poll.get('id')));
|
|
||||||
};
|
|
||||||
|
|
||||||
renderOption (option, optionIndex) {
|
|
||||||
const { poll, disabled } = this.props;
|
|
||||||
const percent = poll.get('votes_count') === 0 ? 0 : (option.get('votes_count') / poll.get('votes_count')) * 100;
|
|
||||||
const leading = poll.get('options').filterNot(other => other.get('title') === option.get('title')).every(other => option.get('votes_count') > other.get('votes_count'));
|
|
||||||
const active = !!this.state.selected[`${optionIndex}`];
|
|
||||||
const showResults = poll.get('voted') || poll.get('expired');
|
|
||||||
const multiple = poll.get('multiple');
|
|
||||||
|
|
||||||
let titleEmojified = option.get('title_emojified');
|
|
||||||
if (!titleEmojified) {
|
|
||||||
const emojiMap = makeEmojiMap(poll);
|
|
||||||
titleEmojified = emojify(escapeTextContentForBrowser(option.get('title')), emojiMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const chartClasses = classNames('poll__chart', {
|
renderOption(option, optionIndex) {
|
||||||
'poll__chart--leading': leading,
|
const { poll, disabled } = this.props
|
||||||
});
|
const { selected } = this.state
|
||||||
|
const percent = poll.get('votes_count') === 0 ? 0 : (option.get('votes_count') / poll.get('votes_count')) * 100
|
||||||
|
const leading = poll.get('options').filterNot(other => other.get('title') === option.get('title')).every(other => option.get('votes_count') > other.get('votes_count'))
|
||||||
|
const active = !!selected[`${optionIndex}`]
|
||||||
|
const showResults = poll.get('voted') || poll.get('expired')
|
||||||
|
const multiple = poll.get('multiple')
|
||||||
|
|
||||||
const textClasses = classNames('poll__text', {
|
let titleEmojified = option.get('title_emojified')
|
||||||
selectable: !showResults,
|
if (!titleEmojified) {
|
||||||
});
|
const emojiMap = makeEmojiMap(poll)
|
||||||
|
titleEmojified = emojify(escapeTextContentForBrowser(option.get('title')), emojiMap)
|
||||||
|
}
|
||||||
|
|
||||||
const inputClasses = classNames('poll__input', {
|
const chartClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
positionAbsolute: 1,
|
||||||
|
top0: 1,
|
||||||
|
left0: 1,
|
||||||
|
radiusSmall: 1,
|
||||||
|
height100PC: 1,
|
||||||
|
backgroundSubtle2: !leading,
|
||||||
|
backgroundColorBrandLight: leading,
|
||||||
|
})
|
||||||
|
|
||||||
|
const inputClasses = cx('poll__input', {
|
||||||
'poll__input--checkbox': multiple,
|
'poll__input--checkbox': multiple,
|
||||||
'poll__input--active': active,
|
'poll__input--active': active,
|
||||||
});
|
})
|
||||||
|
|
||||||
|
const listItemClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
flexRow: 1,
|
||||||
|
paddingVertical10PX: showResults,
|
||||||
|
marginBottom10PX: 1,
|
||||||
|
border1PX: !showResults,
|
||||||
|
borderColorSecondary: !showResults,
|
||||||
|
circle: !showResults,
|
||||||
|
cursorPointer: !showResults,
|
||||||
|
backgroundSubtle_onHover: !showResults,
|
||||||
|
backgroundSubtle: !showResults && active,
|
||||||
|
})
|
||||||
|
|
||||||
|
const textContainerClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
width100PC: 1,
|
||||||
|
paddingHorizontal15PX: 1,
|
||||||
|
paddingVertical10PX: !showResults,
|
||||||
|
cursorPointer: !showResults,
|
||||||
|
alignItemsCenter: !showResults,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className='poll-item' key={option.get('title')}>
|
<li className={listItemClasses} key={option.get('title')}>
|
||||||
{
|
{
|
||||||
showResults && (
|
showResults && (
|
||||||
<Motion defaultStyle={{ width: 0 }} style={{ width: spring(percent, { stiffness: 180, damping: 12 }) }}>
|
<Motion defaultStyle={{ width: 0 }} style={{ width: spring(percent, { stiffness: 180, damping: 12 }) }}>
|
||||||
@ -110,7 +135,15 @@ class Poll extends ImmutablePureComponent {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
<label className={textClasses}>
|
<label className={textContainerClasses}>
|
||||||
|
<Text
|
||||||
|
size='medium'
|
||||||
|
color='primary'
|
||||||
|
weight={leading ? 'bold' : 'normal'}
|
||||||
|
className={[_s.displayFlex, _s.flexRow, _s.width100PC, _s.alignItemsCenter].join(' ')}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
!showResults &&
|
||||||
<input
|
<input
|
||||||
name='vote-options'
|
name='vote-options'
|
||||||
type={multiple ? 'checkbox' : 'radio'}
|
type={multiple ? 'checkbox' : 'radio'}
|
||||||
@ -118,50 +151,63 @@ class Poll extends ImmutablePureComponent {
|
|||||||
checked={active}
|
checked={active}
|
||||||
onChange={this.handleOptionChange}
|
onChange={this.handleOptionChange}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
className={[_s.default, _s.marginRight10PX].join(' ')}
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
{!showResults && <span className={inputClasses} />}
|
{
|
||||||
{showResults && <span className='poll-item__number'>{Math.round(percent)}%</span>}
|
!showResults && <span className={inputClasses} />
|
||||||
|
}
|
||||||
|
|
||||||
<span className='poll-item__text' dangerouslySetInnerHTML={{ __html: titleEmojified }} />
|
<span dangerouslySetInnerHTML={{ __html: titleEmojified }} />
|
||||||
|
|
||||||
|
{
|
||||||
|
showResults &&
|
||||||
|
<span className={_s.marginLeftAuto}>
|
||||||
|
{Math.round(percent)}%
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</Text>
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { poll, intl } = this.props;
|
const { poll, intl } = this.props
|
||||||
|
|
||||||
if (!poll) return null;
|
if (!poll) return null
|
||||||
|
|
||||||
const timeRemaining = poll.get('expired') ?
|
const timeRemaining = poll.get('expired') ?
|
||||||
intl.formatMessage(messages.closed)
|
intl.formatMessage(messages.closed)
|
||||||
: <RelativeTimestamp timestamp={poll.get('expires_at')} futureDate />;
|
: <RelativeTimestamp timestamp={poll.get('expires_at')} futureDate />
|
||||||
const showResults = poll.get('voted') || poll.get('expired');
|
const showResults = poll.get('voted') || poll.get('expired')
|
||||||
const disabled = this.props.disabled || Object.entries(this.state.selected).every(item => !item);
|
const disabled = this.props.disabled || Object.entries(this.state.selected).every(item => !item)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='poll'>
|
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX].join(' ')}>
|
||||||
<ul className='poll__list'>
|
<ul className={[_s.default, _s.listStyleNone].join(' ')}>
|
||||||
{poll.get('options').map((option, i) => this.renderOption(option, i))}
|
{
|
||||||
|
poll.get('options').map((option, i) => this.renderOption(option, i))
|
||||||
|
}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div className='poll__footer'>
|
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||||
{
|
{
|
||||||
!showResults &&
|
!showResults &&
|
||||||
<Button className='poll__button' disabled={disabled} onClick={this.handleVote} secondary>
|
<Button
|
||||||
|
narrow
|
||||||
|
className={_s.marginRight10PX}
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={this.handleVote}
|
||||||
|
>
|
||||||
|
<Text color='inherit' size='small' className={_s.paddingHorizontal10PX}>
|
||||||
{intl.formatMessage(messages.vote)}
|
{intl.formatMessage(messages.vote)}
|
||||||
|
</Text>
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
{
|
|
||||||
showResults && !this.props.disabled &&
|
<Text color='secondary'>
|
||||||
<span>
|
|
||||||
<button className='poll__link' onClick={this.handleRefresh}>
|
|
||||||
{intl.formatMessage(messages.refresh)}
|
|
||||||
</button>
|
|
||||||
·
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='poll.total_votes'
|
id='poll.total_votes'
|
||||||
defaultMessage='{count, plural, one {# vote} other {# votes}}'
|
defaultMessage='{count, plural, one {# vote} other {# votes}}'
|
||||||
@ -171,11 +217,17 @@ class Poll extends ImmutablePureComponent {
|
|||||||
/>
|
/>
|
||||||
{
|
{
|
||||||
poll.get('expires_at') &&
|
poll.get('expires_at') &&
|
||||||
<span> · {timeRemaining}</span>
|
<Fragment>
|
||||||
|
<DotTextSeperator />
|
||||||
|
<Text color='secondary' className={_s.marginLeft5PX}>
|
||||||
|
{timeRemaining}
|
||||||
|
</Text>
|
||||||
|
</Fragment>
|
||||||
}
|
}
|
||||||
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
41
app/javascript/gabsocial/components/select.js
Normal file
41
app/javascript/gabsocial/components/select.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
|
||||||
|
export default class Select extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
options: PropTypes.oneOf([
|
||||||
|
ImmutablePropTypes.map,
|
||||||
|
PropTypes.object,
|
||||||
|
]),
|
||||||
|
value: PropTypes.string,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
value,
|
||||||
|
options,
|
||||||
|
onChange
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={_s.default}>
|
||||||
|
<select
|
||||||
|
className={[_s.default, _s.outlineNone, _s.text, _s.border1PX, _s.borderColorSecondary, _s.paddingHorizontal15PX, _s.select].join(' ')}
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
options.map(option => (
|
||||||
|
<option key={`option-${option.value}`} value={option.value}>
|
||||||
|
{option.title}
|
||||||
|
</option>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -165,8 +165,8 @@ class Status extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleToggleMediaVisibility = () => {
|
handleToggleMediaVisibility = () => {
|
||||||
this.setState({ showMedia: !this.state.showMedia });
|
this.setState({ showMedia: !this.state.showMedia })
|
||||||
};
|
}
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
if (this.props.onClick) {
|
if (this.props.onClick) {
|
||||||
@ -178,8 +178,8 @@ class Status extends ImmutablePureComponent {
|
|||||||
|
|
||||||
this.context.router.history.push(
|
this.context.router.history.push(
|
||||||
`/${this._properStatus().getIn(['account', 'acct'])}/posts/${this._properStatus().get('id')}`
|
`/${this._properStatus().getIn(['account', 'acct'])}/posts/${this._properStatus().get('id')}`
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
handleExpandClick = e => {
|
handleExpandClick = e => {
|
||||||
if (e.button === 0) {
|
if (e.button === 0) {
|
||||||
@ -271,10 +271,18 @@ class Status extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let media = null;
|
const {
|
||||||
let prepend, rebloggedByText, reblogContent;
|
intl,
|
||||||
|
hidden,
|
||||||
|
featured,
|
||||||
|
unread,
|
||||||
|
showThread,
|
||||||
|
group,
|
||||||
|
promoted
|
||||||
|
} = this.props
|
||||||
|
|
||||||
const { intl, hidden, featured, unread, showThread, group, promoted } = this.props;
|
let media = null
|
||||||
|
let prepend, rebloggedByText, reblogContent
|
||||||
|
|
||||||
// console.log("replies:", this.props.replies)
|
// console.log("replies:", this.props.replies)
|
||||||
|
|
||||||
@ -321,7 +329,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
prepend = (
|
prepend = (
|
||||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter, _s.borderBottom1PX, _s.borderColorSecondary, _s.paddingVertical5PX, _s.paddingHorizontal15PX].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter, _s.borderBottom1PX, _s.borderColorSecondary, _s.paddingVertical5PX, _s.paddingHorizontal15PX].join(' ')}>
|
||||||
<Icon
|
<Icon
|
||||||
id='star'
|
id='pin'
|
||||||
width='10px'
|
width='10px'
|
||||||
height='10px'
|
height='10px'
|
||||||
className={_s.fillColorSecondary}
|
className={_s.fillColorSecondary}
|
||||||
@ -460,12 +468,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
|
|
||||||
{prepend}
|
{prepend}
|
||||||
|
|
||||||
<div
|
<div data-id={status.get('id')}>
|
||||||
className={classNames('status', `status-${status.get('visibility')}`, {
|
|
||||||
muted: this.props.muted,
|
|
||||||
})}
|
|
||||||
data-id={status.get('id')}
|
|
||||||
>
|
|
||||||
|
|
||||||
<StatusHeader status={status} />
|
<StatusHeader status={status} />
|
||||||
|
|
||||||
@ -493,6 +496,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
) */ }
|
) */ }
|
||||||
|
|
||||||
<StatusActionBar status={status} account={account} {...other} />
|
<StatusActionBar status={status} account={account} {...other} />
|
||||||
|
{ /* : todo : comment bar, comments */ }
|
||||||
</div>
|
</div>
|
||||||
</Block>
|
</Block>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,7 +5,7 @@ import classNames from 'classnames/bind'
|
|||||||
import { openModal } from '../actions/modal'
|
import { openModal } from '../actions/modal'
|
||||||
import { me, isStaff } from '../initial_state'
|
import { me, isStaff } from '../initial_state'
|
||||||
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
||||||
import Icon from './icon'
|
import Text from './text'
|
||||||
import StatusActionBarItem from './status_action_bar_item'
|
import StatusActionBarItem from './status_action_bar_item'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
@ -117,6 +117,10 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleShareClick = () => {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { status, intl: { formatMessage } } = this.props
|
const { status, intl: { formatMessage } } = this.props
|
||||||
|
|
||||||
@ -135,34 +139,6 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
<IconButton className='status-action-bar-button' title={formatMessage(messages.share)} icon='share-alt' onClick={this.handleShareClick} />
|
<IconButton className='status-action-bar-button' title={formatMessage(messages.share)} icon='share-alt' onClick={this.handleShareClick} />
|
||||||
)
|
)
|
||||||
|
|
||||||
const items = [
|
|
||||||
{
|
|
||||||
title: formatMessage(messages.like),
|
|
||||||
icon: 'like',
|
|
||||||
active: !!status.get('favorited'),
|
|
||||||
onClick: this.handleFavoriteClick,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: formatMessage(messages.comment),
|
|
||||||
icon: 'comment',
|
|
||||||
active: false,
|
|
||||||
onClick: this.handleReplyClick,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: repostTitle,
|
|
||||||
icon: (status.get('visibility') === 'private') ? 'lock' : 'repost',
|
|
||||||
disabled: !publicStatus,
|
|
||||||
active: !!status.get('reblogged'),
|
|
||||||
onClick: this.handleRepostClick,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: formatMessage(messages.share),
|
|
||||||
icon: 'share',
|
|
||||||
active: false,
|
|
||||||
onClick: this.handleFavoriteClick,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const hasInteractions = favoriteCount > 0 || replyCount > 0 || repostCount > 0
|
const hasInteractions = favoriteCount > 0 || replyCount > 0 || repostCount > 0
|
||||||
const shouldCondense = (!!status.get('card') || status.get('media_attachments').size > 0) && !hasInteractions
|
const shouldCondense = (!!status.get('card') || status.get('media_attachments').size > 0) && !hasInteractions
|
||||||
|
|
||||||
@ -186,9 +162,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
const interactionBtnClasses = cx({
|
const interactionBtnClasses = cx({
|
||||||
default: 1,
|
default: 1,
|
||||||
text: 1,
|
text: 1,
|
||||||
colorSecondary: 1,
|
|
||||||
cursorPointer: 1,
|
cursorPointer: 1,
|
||||||
fontSize15PX: 1,
|
|
||||||
fontWeightNormal: 1,
|
fontWeightNormal: 1,
|
||||||
marginRight10PX: 1,
|
marginRight10PX: 1,
|
||||||
paddingVertical5PX: 1,
|
paddingVertical5PX: 1,
|
||||||
@ -199,33 +173,60 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||||||
{
|
{
|
||||||
hasInteractions &&
|
hasInteractions &&
|
||||||
<div className={[_s.default, _s.flexRow, _s.paddingHorizontal5PX].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.paddingHorizontal5PX].join(' ')}>
|
||||||
{favoriteCount > 0 &&
|
{
|
||||||
|
favoriteCount > 0 &&
|
||||||
<button className={interactionBtnClasses}>
|
<button className={interactionBtnClasses}>
|
||||||
|
<Text color='secondary'>
|
||||||
{favoriteCount}
|
{favoriteCount}
|
||||||
Likes
|
Likes
|
||||||
|
</Text>
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
{replyCount > 0 &&
|
{
|
||||||
|
replyCount > 0 &&
|
||||||
<button className={interactionBtnClasses}>
|
<button className={interactionBtnClasses}>
|
||||||
|
<Text color='secondary'>
|
||||||
{replyCount}
|
{replyCount}
|
||||||
Comments
|
Comments
|
||||||
|
</Text>
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
{repostCount > 0 &&
|
{
|
||||||
|
repostCount > 0 &&
|
||||||
<button className={interactionBtnClasses}>
|
<button className={interactionBtnClasses}>
|
||||||
|
<Text color='secondary'>
|
||||||
{repostCount}
|
{repostCount}
|
||||||
Reposts
|
Reposts
|
||||||
|
</Text>
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div className={innerContainerClasses}>
|
<div className={innerContainerClasses}>
|
||||||
<div className={[_s.default, _s.flexRow, _s.paddingVertical2PX, _s.width100PC].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.paddingVertical2PX, _s.width100PC].join(' ')}>
|
||||||
{
|
<StatusActionBarItem
|
||||||
items.map((item, i) => (
|
title={formatMessage(messages.like)}
|
||||||
<StatusActionBarItem key={`status-action-bar-item-${i}`} {...item} />
|
icon='like'
|
||||||
))
|
active={!!status.get('favorited')}
|
||||||
}
|
onClick={this.handleFavoriteClick}
|
||||||
|
/>
|
||||||
|
<StatusActionBarItem
|
||||||
|
title={formatMessage(messages.comment)}
|
||||||
|
icon='comment'
|
||||||
|
onClick={this.handleReplyClick}
|
||||||
|
/>
|
||||||
|
<StatusActionBarItem
|
||||||
|
title={repostTitle}
|
||||||
|
icon={(status.get('visibility') === 'private') ? 'lock' : 'repost'}
|
||||||
|
disabled={!publicStatus}
|
||||||
|
active={!!status.get('reblogged')}
|
||||||
|
onClick={this.handleRepostClick}
|
||||||
|
/>
|
||||||
|
<StatusActionBarItem
|
||||||
|
title={formatMessage(messages.share)}
|
||||||
|
icon='share'
|
||||||
|
onClick={this.handleShareClick}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={[_s.default, _s.borderTop1PX, _s.borderColorSecondary, _s.paddingTop10PX, _s.marginBottom10PX].join(' ')}>
|
<div className={[_s.default, _s.borderTop1PX, _s.borderColorSecondary, _s.paddingTop10PX, _s.marginBottom10PX].join(' ')}>
|
||||||
|
@ -29,7 +29,7 @@ export default class StatusActionBarItem extends PureComponent {
|
|||||||
paddingHorizontal10PX: 1,
|
paddingHorizontal10PX: 1,
|
||||||
width100PC: 1,
|
width100PC: 1,
|
||||||
radiusSmall: 1,
|
radiusSmall: 1,
|
||||||
outlineFocusBrand: 1,
|
outlineNone: 1,
|
||||||
backgroundTransparent: 1,
|
backgroundTransparent: 1,
|
||||||
backgroundSubtle_onHover: 1,
|
backgroundSubtle_onHover: 1,
|
||||||
colorSecondary: 1,
|
colorSecondary: 1,
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { injectIntl, defineMessages } from 'react-intl'
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import classNames from 'classnames/bind'
|
||||||
import { me } from '../initial_state'
|
import { me } from '../initial_state'
|
||||||
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
||||||
import Block from './block'
|
import Block from './block'
|
||||||
import Heading from './heading'
|
import Heading from './heading'
|
||||||
|
|
||||||
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
createPost: { id: 'column_header.create_post', defaultMessage: 'Create Post' },
|
createPost: { id: 'column_header.create_post', defaultMessage: 'Create Post' },
|
||||||
})
|
})
|
||||||
@ -25,6 +28,7 @@ class TimelineComposeBlock extends ImmutablePureComponent {
|
|||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
account: ImmutablePropTypes.map.isRequired,
|
account: ImmutablePropTypes.map.isRequired,
|
||||||
size: PropTypes.number,
|
size: PropTypes.number,
|
||||||
|
modal: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@ -32,7 +36,23 @@ class TimelineComposeBlock extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { account, size, intl, ...rest } = this.props
|
const {
|
||||||
|
account,
|
||||||
|
size,
|
||||||
|
intl,
|
||||||
|
modal,
|
||||||
|
...rest
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
if (modal) {
|
||||||
|
return (
|
||||||
|
<section className={_s.default}>
|
||||||
|
<div className={[_s.default, _s.flexRow].join(' ')}>
|
||||||
|
<ComposeFormContainer {...rest} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={[_s.default, _s.marginBottom15PX].join(' ')}>
|
<section className={[_s.default, _s.marginBottom15PX].join(' ')}>
|
||||||
@ -42,7 +62,7 @@ class TimelineComposeBlock extends ImmutablePureComponent {
|
|||||||
{intl.formatMessage(messages.createPost)}
|
{intl.formatMessage(messages.createPost)}
|
||||||
</Heading>
|
</Heading>
|
||||||
</div>
|
</div>
|
||||||
<div className={[_s.default, _s.flexRow, _s.paddingVertical15PX, _s.paddingHorizontal15PX].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.paddingHorizontal15PX, _s.paddingVertical15PX].join(' ')}>
|
||||||
<ComposeFormContainer {...rest} />
|
<ComposeFormContainer {...rest} />
|
||||||
</div>
|
</div>
|
||||||
</Block>
|
</Block>
|
||||||
|
@ -109,9 +109,12 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onFavorite (status) {
|
onFavorite (status) {
|
||||||
|
console.log("onFavorite...", status)
|
||||||
if (status.get('favourited')) {
|
if (status.get('favourited')) {
|
||||||
|
console.log("unfav...")
|
||||||
dispatch(unfavorite(status));
|
dispatch(unfavorite(status));
|
||||||
} else {
|
} else {
|
||||||
|
console.log("fav...")
|
||||||
dispatch(favorite(status));
|
dispatch(favorite(status));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -10,6 +10,7 @@ export default class ComposeExtraButton extends PureComponent {
|
|||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
icon: PropTypes.string,
|
icon: PropTypes.string,
|
||||||
small: PropTypes.bool,
|
small: PropTypes.bool,
|
||||||
|
active: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -25,7 +26,15 @@ export default class ComposeExtraButton extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { title, disabled, onClick, icon, children, small } = this.props
|
const {
|
||||||
|
title,
|
||||||
|
disabled,
|
||||||
|
onClick,
|
||||||
|
icon,
|
||||||
|
children,
|
||||||
|
small,
|
||||||
|
active
|
||||||
|
} = this.props
|
||||||
const { hovering } = this.state
|
const { hovering } = this.state
|
||||||
|
|
||||||
const containerClasses = cx({
|
const containerClasses = cx({
|
||||||
@ -39,8 +48,10 @@ export default class ComposeExtraButton extends PureComponent {
|
|||||||
circle: 1,
|
circle: 1,
|
||||||
flexRow: 1,
|
flexRow: 1,
|
||||||
cursorPointer: 1,
|
cursorPointer: 1,
|
||||||
backgroundSubtle: !hovering,
|
outlineNone: 1,
|
||||||
backgroundSubtle2: hovering,
|
backgroundSubtle: !hovering && !active,
|
||||||
|
backgroundSubtle2: hovering && !active,
|
||||||
|
backgroundColorBrandLight: active,
|
||||||
paddingVertical10PX: !small,
|
paddingVertical10PX: !small,
|
||||||
paddingHorizontal10PX: !small,
|
paddingHorizontal10PX: !small,
|
||||||
paddingVertical5PX: small,
|
paddingVertical5PX: small,
|
||||||
@ -54,10 +65,16 @@ export default class ComposeExtraButton extends PureComponent {
|
|||||||
lineHeight15: 1,
|
lineHeight15: 1,
|
||||||
fontSize12PX: 1,
|
fontSize12PX: 1,
|
||||||
fontWeightMedium: 1,
|
fontWeightMedium: 1,
|
||||||
colorSecondary: 1,
|
colorSecondary: !active,
|
||||||
|
colorWhite: active,
|
||||||
displayNone: !hovering,
|
displayNone: !hovering,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const iconClasses = cx({
|
||||||
|
fillColorSecondary: !active,
|
||||||
|
fillColorWhite: active,
|
||||||
|
})
|
||||||
|
|
||||||
const iconSize = !!small ? '12px' : '18px'
|
const iconSize = !!small ? '12px' : '18px'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -70,9 +87,9 @@ export default class ComposeExtraButton extends PureComponent {
|
|||||||
onMouseEnter={() => this.handleOnMouseEnter()}
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
onMouseLeave={() => this.handleOnMouseLeave()}
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
>
|
>
|
||||||
<Icon id={icon} width={iconSize} height={iconSize} className={_s.fillColorSecondary} />
|
<Icon id={icon} width={iconSize} height={iconSize} className={iconClasses} />
|
||||||
{
|
{
|
||||||
!small &&
|
(!small && !!title) &&
|
||||||
<span className={titleClasses}>
|
<span className={titleClasses}>
|
||||||
{title}
|
{title}
|
||||||
</span>
|
</span>
|
||||||
|
@ -11,9 +11,9 @@ import PollButton from '../../components/poll_button';
|
|||||||
import UploadButton from '../../components/upload_button';
|
import UploadButton from '../../components/upload_button';
|
||||||
import SpoilerButton from '../../components/spoiler_button';
|
import SpoilerButton from '../../components/spoiler_button';
|
||||||
import PrivacyDropdown from '../../components/privacy_dropdown';
|
import PrivacyDropdown from '../../components/privacy_dropdown';
|
||||||
|
import EmojiPickerButton from '../../components/emoji_picker_button'
|
||||||
import EmojiPickerDropdown from '../../containers/emoji_picker_dropdown_container';
|
import EmojiPickerDropdown from '../../containers/emoji_picker_dropdown_container';
|
||||||
import PollFormContainer from '../../containers/poll_form_container';
|
import PollFormContainer from '../../containers/poll_form_container';
|
||||||
import WarningContainer from '../../containers/warning_container';
|
|
||||||
import SchedulePostDropdown from '../../components/schedule_post_dropdown';
|
import SchedulePostDropdown from '../../components/schedule_post_dropdown';
|
||||||
import QuotedStatusPreviewContainer from '../../containers/quoted_status_preview_container';
|
import QuotedStatusPreviewContainer from '../../containers/quoted_status_preview_container';
|
||||||
import Icon from '../../../../components/icon';
|
import Icon from '../../../../components/icon';
|
||||||
@ -228,7 +228,8 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
isModalOpen,
|
isModalOpen,
|
||||||
quoteOfId,
|
quoteOfId,
|
||||||
edit,
|
edit,
|
||||||
scheduledAt
|
scheduledAt,
|
||||||
|
spoiler
|
||||||
} = this.props
|
} = this.props
|
||||||
const condensed = shouldCondense && !this.props.text && !this.state.composeFocused;
|
const condensed = shouldCondense && !this.props.text && !this.state.composeFocused;
|
||||||
const disabled = this.props.isSubmitting;
|
const disabled = this.props.isSubmitting;
|
||||||
@ -258,6 +259,15 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
marginTop5PX: shouldCondense,
|
marginTop5PX: shouldCondense,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const contentWarningClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
paddingTop5PX: 1,
|
||||||
|
paddingBottom10PX: 1,
|
||||||
|
borderBottom1PX: 1,
|
||||||
|
borderColorSecondary: 1,
|
||||||
|
displayNone: !spoiler
|
||||||
|
})
|
||||||
|
|
||||||
const avatarSize = shouldCondense ? 28 : 46
|
const avatarSize = shouldCondense ? 28 : 46
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -265,17 +275,16 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
<div className={avatarContainerClasses}>
|
<div className={avatarContainerClasses}>
|
||||||
<Avatar account={account} size={avatarSize} />
|
<Avatar account={account} size={avatarSize} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={containerClasses}
|
className={containerClasses}
|
||||||
ref={this.setForm}
|
ref={this.setForm}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
>
|
>
|
||||||
{ /* <WarningContainer /> */}
|
|
||||||
|
|
||||||
{ /* !shouldCondense && <ReplyIndicatorContainer /> */}
|
{ /* !shouldCondense && <ReplyIndicatorContainer /> */}
|
||||||
|
|
||||||
{ /*
|
<div className={contentWarningClasses}>
|
||||||
<div className={`spoiler-input ${this.props.spoiler ? 'spoiler-input--visible' : ''}`}>
|
|
||||||
<AutosuggestTextbox
|
<AutosuggestTextbox
|
||||||
placeholder={intl.formatMessage(messages.spoiler_placeholder)}
|
placeholder={intl.formatMessage(messages.spoiler_placeholder)}
|
||||||
value={this.props.spoilerText}
|
value={this.props.spoilerText}
|
||||||
@ -292,7 +301,6 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
className='spoiler-input__input'
|
className='spoiler-input__input'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
*/ }
|
|
||||||
|
|
||||||
{ /*
|
{ /*
|
||||||
<div className='emoji-picker-wrapper'>
|
<div className='emoji-picker-wrapper'>
|
||||||
@ -341,6 +349,7 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
<SpoilerButton small={shouldCondense} />
|
<SpoilerButton small={shouldCondense} />
|
||||||
<SchedulePostDropdown small={shouldCondense} position={isModalOpen ? 'top' : undefined} />
|
<SchedulePostDropdown small={shouldCondense} position={isModalOpen ? 'top' : undefined} />
|
||||||
|
<EmojiPickerButton />
|
||||||
</div>
|
</div>
|
||||||
<CharacterCounter max={maxPostCharacterCount} text={text} small={shouldCondense} />
|
<CharacterCounter max={maxPostCharacterCount} text={text} small={shouldCondense} />
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
import { addPoll, removePoll } from '../../../actions/compose'
|
||||||
|
import ComposeExtraButton from './compose_extra_button'
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
// unavailable: state.getIn(['compose', 'is_uploading']) || (state.getIn(['compose', 'media_attachments']).size > 0),
|
||||||
|
// active: state.getIn(['compose', 'poll']) !== null,
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
|
||||||
|
onClick() {
|
||||||
|
dispatch((_, getState) => {
|
||||||
|
if (getState().getIn(['compose', 'poll'])) {
|
||||||
|
dispatch(removePoll())
|
||||||
|
} else {
|
||||||
|
dispatch(addPoll())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
class EmojiPickerButton extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
unavailable: PropTypes.bool,
|
||||||
|
active: PropTypes.bool,
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
small: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick = () => {
|
||||||
|
this.props.onClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { active, unavailable, disabled, small } = this.props
|
||||||
|
|
||||||
|
if (unavailable) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ComposeExtraButton
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={this.handleClick}
|
||||||
|
icon='happy'
|
||||||
|
small={small}
|
||||||
|
active={active}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,31 +1,31 @@
|
|||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import { addPoll, removePoll } from '../../../actions/compose';
|
import { addPoll, removePoll } from '../../../actions/compose'
|
||||||
import ComposeExtraButton from './compose_extra_button'
|
import ComposeExtraButton from './compose_extra_button'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
add_poll: { id: 'poll_button.add_poll', defaultMessage: 'Add poll' },
|
add_poll: { id: 'poll_button.add_poll', defaultMessage: 'Add poll' },
|
||||||
title: { id: 'poll_button.title', defaultMessage: 'Poll' },
|
title: { id: 'poll_button.title', defaultMessage: 'Poll' },
|
||||||
remove_poll: { id: 'poll_button.remove_poll', defaultMessage: 'Remove poll' },
|
remove_poll: { id: 'poll_button.remove_poll', defaultMessage: 'Remove poll' },
|
||||||
});
|
})
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
unavailable: state.getIn(['compose', 'is_uploading']) || (state.getIn(['compose', 'media_attachments']).size > 0),
|
unavailable: state.getIn(['compose', 'is_uploading']) || (state.getIn(['compose', 'media_attachments']).size > 0),
|
||||||
active: state.getIn(['compose', 'poll']) !== null,
|
active: state.getIn(['compose', 'poll']) !== null,
|
||||||
});
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
|
||||||
onClick() {
|
onClick() {
|
||||||
dispatch((_, getState) => {
|
dispatch((_, getState) => {
|
||||||
if (getState().getIn(['compose', 'poll'])) {
|
if (getState().getIn(['compose', 'poll'])) {
|
||||||
dispatch(removePoll());
|
dispatch(removePoll())
|
||||||
} else {
|
} else {
|
||||||
dispatch(addPoll());
|
dispatch(addPoll())
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
});
|
})
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@connect(mapStateToProps, mapDispatchToProps)
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
@ -39,16 +39,16 @@ class PollButton extends PureComponent {
|
|||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
small: PropTypes.bool,
|
small: PropTypes.bool,
|
||||||
};
|
}
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
this.props.onClick();
|
this.props.onClick()
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { intl, active, unavailable, disabled, small } = this.props;
|
const { intl, active, unavailable, disabled, small } = this.props
|
||||||
|
|
||||||
if (unavailable) return null;
|
if (unavailable) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ComposeExtraButton
|
<ComposeExtraButton
|
||||||
@ -57,6 +57,7 @@ class PollButton extends PureComponent {
|
|||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
icon='poll'
|
icon='poll'
|
||||||
small={small}
|
small={small}
|
||||||
|
active={active}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,247 @@
|
|||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import classNames from 'classnames/bind'
|
||||||
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import Button from '../../../components/button'
|
||||||
|
import Text from '../../../components/text'
|
||||||
|
import Select from '../../../components/select'
|
||||||
|
import AutosuggestTextbox from '../../../components/autosuggest_textbox'
|
||||||
|
|
||||||
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
option_placeholder: { id: 'compose_form.poll.option_placeholder', defaultMessage: 'Choice {number}' },
|
||||||
|
add_option: { id: 'compose_form.poll.add_option', defaultMessage: 'Add a choice' },
|
||||||
|
remove_option: { id: 'compose_form.poll.remove_option', defaultMessage: 'Remove this choice' },
|
||||||
|
poll_duration: { id: 'compose_form.poll.duration', defaultMessage: 'Poll duration' },
|
||||||
|
minutes: { id: 'intervals.full.minutes', defaultMessage: '{number, plural, one {# minute} other {# minutes}}' },
|
||||||
|
hours: { id: 'intervals.full.hours', defaultMessage: '{number, plural, one {# hour} other {# hours}}' },
|
||||||
|
days: { id: 'intervals.full.days', defaultMessage: '{number, plural, one {# day} other {# days}}' },
|
||||||
|
})
|
||||||
|
|
||||||
|
@injectIntl
|
||||||
|
class PollFormOption extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
index: PropTypes.number.isRequired,
|
||||||
|
isPollMultiple: PropTypes.bool,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
onRemove: PropTypes.func.isRequired,
|
||||||
|
onToggleMultiple: PropTypes.func.isRequired,
|
||||||
|
suggestions: ImmutablePropTypes.list,
|
||||||
|
onClearSuggestions: PropTypes.func.isRequired,
|
||||||
|
onFetchSuggestions: PropTypes.func.isRequired,
|
||||||
|
onSuggestionSelected: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleOptionTitleChange = e => {
|
||||||
|
this.props.onChange(this.props.index, e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
handleOptionRemove = () => {
|
||||||
|
this.props.onRemove(this.props.index);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
handleToggleMultiple = e => {
|
||||||
|
this.props.onToggleMultiple();
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
};
|
||||||
|
|
||||||
|
onSuggestionsClearRequested = () => {
|
||||||
|
this.props.onClearSuggestions();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSuggestionsFetchRequested = (token) => {
|
||||||
|
this.props.onFetchSuggestions(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSuggestionSelected = (tokenStart, token, value) => {
|
||||||
|
this.props.onSuggestionSelected(tokenStart, token, value, ['poll', 'options', this.props.index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { isPollMultiple, title, index, intl } = this.props;
|
||||||
|
|
||||||
|
const toggleClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
paddingHorizontal10PX: 1,
|
||||||
|
paddingVertical10PX: 1,
|
||||||
|
borderColorSecondary: 1,
|
||||||
|
border1PX: 1,
|
||||||
|
outlineNone: 1,
|
||||||
|
marginRight10PX: 1,
|
||||||
|
circle: !isPollMultiple,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li className={[_s.default, _s.flexRow, _s.marginBottom10PX].join(' ')}>
|
||||||
|
<label className={[_s.default, _s.flexRow, _s.flexGrow1, _s.alignItemsCenter].join(' ')}>
|
||||||
|
<span
|
||||||
|
className={toggleClasses}
|
||||||
|
onClick={this.handleToggleMultiple}
|
||||||
|
role='button'
|
||||||
|
tabIndex='0'
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AutosuggestTextbox
|
||||||
|
placeholder={intl.formatMessage(messages.option_placeholder, { number: index + 1 })}
|
||||||
|
maxLength={25}
|
||||||
|
value={title}
|
||||||
|
onChange={this.handleOptionTitleChange}
|
||||||
|
suggestions={this.props.suggestions}
|
||||||
|
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
||||||
|
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
||||||
|
onSuggestionSelected={this.onSuggestionSelected}
|
||||||
|
searchTokens={[':']}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
narrow
|
||||||
|
circle
|
||||||
|
backgroundColor='none'
|
||||||
|
className={[_s.marginLeft5PX, _s.justifyContentCenter].join(' ')}
|
||||||
|
icon='close'
|
||||||
|
iconWidth='8px'
|
||||||
|
iconHeight='8px'
|
||||||
|
iconClassName={_s.fillColorSecondary}
|
||||||
|
disabled={index <= 1}
|
||||||
|
title={intl.formatMessage(messages.remove_option)}
|
||||||
|
onClick={this.handleOptionRemove}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
@injectIntl
|
||||||
|
class PollForm extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
options: ImmutablePropTypes.list,
|
||||||
|
expiresIn: PropTypes.number,
|
||||||
|
isMultiple: PropTypes.bool,
|
||||||
|
onChangeOption: PropTypes.func.isRequired,
|
||||||
|
onAddOption: PropTypes.func.isRequired,
|
||||||
|
onRemoveOption: PropTypes.func.isRequired,
|
||||||
|
onChangeSettings: PropTypes.func.isRequired,
|
||||||
|
suggestions: ImmutablePropTypes.list,
|
||||||
|
onClearSuggestions: PropTypes.func.isRequired,
|
||||||
|
onFetchSuggestions: PropTypes.func.isRequired,
|
||||||
|
onSuggestionSelected: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleAddOption = () => {
|
||||||
|
this.props.onAddOption('');
|
||||||
|
};
|
||||||
|
|
||||||
|
handleSelectDuration = e => {
|
||||||
|
this.props.onChangeSettings(e.target.value, this.props.isMultiple);
|
||||||
|
};
|
||||||
|
|
||||||
|
handleToggleMultiple = () => {
|
||||||
|
this.props.onChangeSettings(this.props.expiresIn, !this.props.isMultiple);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
options,
|
||||||
|
expiresIn,
|
||||||
|
isMultiple,
|
||||||
|
onChangeOption,
|
||||||
|
onRemoveOption,
|
||||||
|
intl,
|
||||||
|
...otherProps
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
if (!options) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[_s.default, _s.paddingHorizontal10PX, _s.paddingVertical10PX, _s.borderColorSecondary, _s.border1PX, _s.radiusSmall].join(' ')}>
|
||||||
|
<ul className={[_s.default, _s.listStyleNone].join(' ')}>
|
||||||
|
{
|
||||||
|
options.map((title, i) => (
|
||||||
|
<PollFormOption
|
||||||
|
title={title}
|
||||||
|
key={`poll-form-option-${i}`}
|
||||||
|
index={i}
|
||||||
|
onChange={onChangeOption}
|
||||||
|
onRemove={onRemoveOption}
|
||||||
|
isPollMultiple={isMultiple}
|
||||||
|
onToggleMultiple={this.handleToggleMultiple}
|
||||||
|
{...otherProps}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.flexRow].join(' ')}>
|
||||||
|
{
|
||||||
|
options.size < 4 && (
|
||||||
|
<Button
|
||||||
|
outline
|
||||||
|
backgroundColor='none'
|
||||||
|
color='brand'
|
||||||
|
className={[_s.alignItemsCenter, _s.marginRight10PX].join(' ')}
|
||||||
|
onClick={this.handleAddOption}
|
||||||
|
icon='add'
|
||||||
|
iconWidth='14px'
|
||||||
|
iconHeight='14px'
|
||||||
|
iconClassName={[_s.fillColorBrand, _s.marginRight5PX].join(' ')}
|
||||||
|
>
|
||||||
|
<Text color='brand'>
|
||||||
|
{intl.formatMessage(messages.add_option)}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.flexGrow1].join(' ')}>
|
||||||
|
<Select
|
||||||
|
value={expiresIn}
|
||||||
|
onChange={this.handleSelectDuration}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
value: 300,
|
||||||
|
title: intl.formatMessage(messages.minutes, { number: 5 }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1800,
|
||||||
|
title: intl.formatMessage(messages.minutes, { number: 30 }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 3600,
|
||||||
|
title: intl.formatMessage(messages.hours, { number: 1 }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 21600,
|
||||||
|
title: intl.formatMessage(messages.hours, { number: 6 }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 86400,
|
||||||
|
title: intl.formatMessage(messages.days, { number: 1 }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 259200,
|
||||||
|
title: intl.formatMessage(messages.days, { number: 3 }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 604800,
|
||||||
|
title: intl.formatMessage(messages.days, { number: 7 }),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
export { default } from './poll_form'
|
|
@ -1,161 +0,0 @@
|
|||||||
import classNames from 'classnames';
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
|
||||||
import IconButton from '../../../../components/icon_button';
|
|
||||||
import Icon from '../../../../components/icon';
|
|
||||||
import AutosuggestTextbox from '../../../../components/autosuggest_textbox';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
option_placeholder: { id: 'compose_form.poll.option_placeholder', defaultMessage: 'Choice {number}' },
|
|
||||||
add_option: { id: 'compose_form.poll.add_option', defaultMessage: 'Add a choice' },
|
|
||||||
remove_option: { id: 'compose_form.poll.remove_option', defaultMessage: 'Remove this choice' },
|
|
||||||
poll_duration: { id: 'compose_form.poll.duration', defaultMessage: 'Poll duration' },
|
|
||||||
minutes: { id: 'intervals.full.minutes', defaultMessage: '{number, plural, one {# minute} other {# minutes}}' },
|
|
||||||
hours: { id: 'intervals.full.hours', defaultMessage: '{number, plural, one {# hour} other {# hours}}' },
|
|
||||||
days: { id: 'intervals.full.days', defaultMessage: '{number, plural, one {# day} other {# days}}' },
|
|
||||||
});
|
|
||||||
|
|
||||||
@injectIntl
|
|
||||||
class Option extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
title: PropTypes.string.isRequired,
|
|
||||||
index: PropTypes.number.isRequired,
|
|
||||||
isPollMultiple: PropTypes.bool,
|
|
||||||
onChange: PropTypes.func.isRequired,
|
|
||||||
onRemove: PropTypes.func.isRequired,
|
|
||||||
onToggleMultiple: PropTypes.func.isRequired,
|
|
||||||
suggestions: ImmutablePropTypes.list,
|
|
||||||
onClearSuggestions: PropTypes.func.isRequired,
|
|
||||||
onFetchSuggestions: PropTypes.func.isRequired,
|
|
||||||
onSuggestionSelected: PropTypes.func.isRequired,
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
handleOptionTitleChange = e => {
|
|
||||||
this.props.onChange(this.props.index, e.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
handleOptionRemove = () => {
|
|
||||||
this.props.onRemove(this.props.index);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
handleToggleMultiple = e => {
|
|
||||||
this.props.onToggleMultiple();
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
};
|
|
||||||
|
|
||||||
onSuggestionsClearRequested = () => {
|
|
||||||
this.props.onClearSuggestions();
|
|
||||||
}
|
|
||||||
|
|
||||||
onSuggestionsFetchRequested = (token) => {
|
|
||||||
this.props.onFetchSuggestions(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
onSuggestionSelected = (tokenStart, token, value) => {
|
|
||||||
this.props.onSuggestionSelected(tokenStart, token, value, ['poll', 'options', this.props.index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { isPollMultiple, title, index, intl } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<li>
|
|
||||||
<label className='poll__text editable'>
|
|
||||||
<span
|
|
||||||
className={classNames('poll__input', { checkbox: isPollMultiple })}
|
|
||||||
onClick={this.handleToggleMultiple}
|
|
||||||
role='button'
|
|
||||||
tabIndex='0'
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AutosuggestTextbox
|
|
||||||
placeholder={intl.formatMessage(messages.option_placeholder, { number: index + 1 })}
|
|
||||||
maxLength={25}
|
|
||||||
value={title}
|
|
||||||
onChange={this.handleOptionTitleChange}
|
|
||||||
suggestions={this.props.suggestions}
|
|
||||||
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
|
||||||
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
|
||||||
onSuggestionSelected={this.onSuggestionSelected}
|
|
||||||
searchTokens={[':']}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div className='poll__cancel'>
|
|
||||||
<IconButton disabled={index <= 1} title={intl.formatMessage(messages.remove_option)} icon='times' onClick={this.handleOptionRemove} />
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default
|
|
||||||
@injectIntl
|
|
||||||
class PollForm extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
options: ImmutablePropTypes.list,
|
|
||||||
expiresIn: PropTypes.number,
|
|
||||||
isMultiple: PropTypes.bool,
|
|
||||||
onChangeOption: PropTypes.func.isRequired,
|
|
||||||
onAddOption: PropTypes.func.isRequired,
|
|
||||||
onRemoveOption: PropTypes.func.isRequired,
|
|
||||||
onChangeSettings: PropTypes.func.isRequired,
|
|
||||||
suggestions: ImmutablePropTypes.list,
|
|
||||||
onClearSuggestions: PropTypes.func.isRequired,
|
|
||||||
onFetchSuggestions: PropTypes.func.isRequired,
|
|
||||||
onSuggestionSelected: PropTypes.func.isRequired,
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
handleAddOption = () => {
|
|
||||||
this.props.onAddOption('');
|
|
||||||
};
|
|
||||||
|
|
||||||
handleSelectDuration = e => {
|
|
||||||
this.props.onChangeSettings(e.target.value, this.props.isMultiple);
|
|
||||||
};
|
|
||||||
|
|
||||||
handleToggleMultiple = () => {
|
|
||||||
this.props.onChangeSettings(this.props.expiresIn, !this.props.isMultiple);
|
|
||||||
};
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { options, expiresIn, isMultiple, onChangeOption, onRemoveOption, intl, ...other } = this.props;
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='compose-form__poll-wrapper'>
|
|
||||||
<ul>
|
|
||||||
{options.map((title, i) => <Option title={title} key={i} index={i} onChange={onChangeOption} onRemove={onRemoveOption} isPollMultiple={isMultiple} onToggleMultiple={this.handleToggleMultiple} {...other} />)}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div className='poll__footer'>
|
|
||||||
{options.size < 4 && (
|
|
||||||
<button className='button button--secondary' onClick={this.handleAddOption}><Icon id='plus' /> <FormattedMessage {...messages.add_option} /></button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<select value={expiresIn} onChange={this.handleSelectDuration}>
|
|
||||||
<option value={300}>{intl.formatMessage(messages.minutes, { number: 5 })}</option>
|
|
||||||
<option value={1800}>{intl.formatMessage(messages.minutes, { number: 30 })}</option>
|
|
||||||
<option value={3600}>{intl.formatMessage(messages.hours, { number: 1 })}</option>
|
|
||||||
<option value={21600}>{intl.formatMessage(messages.hours, { number: 6 })}</option>
|
|
||||||
<option value={86400}>{intl.formatMessage(messages.days, { number: 1 })}</option>
|
|
||||||
<option value={259200}>{intl.formatMessage(messages.days, { number: 3 })}</option>
|
|
||||||
<option value={604800}>{intl.formatMessage(messages.days, { number: 7 })}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
.poll-list-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&__text {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
width: calc(100% - (23px + 6px));
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
}
|
|
@ -45,6 +45,7 @@ class SpoilerButton extends PureComponent {
|
|||||||
icon='warning'
|
icon='warning'
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
small={small}
|
small={small}
|
||||||
|
active={active}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
|||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import spring from 'react-motion/lib/spring'
|
|
||||||
import Motion from '../../../ui/util/optional_motion'
|
|
||||||
import Button from '../../../../components/button'
|
import Button from '../../../../components/button'
|
||||||
|
import Image from '../../../../components/image'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
description: { id: 'upload_form.description', defaultMessage: 'Describe for the visually impaired' },
|
description: { id: 'upload_form.description', defaultMessage: 'Describe for the visually impaired' },
|
||||||
@ -72,7 +71,10 @@ class Upload extends ImmutablePureComponent {
|
|||||||
handleInputBlur = () => {
|
handleInputBlur = () => {
|
||||||
const { dirtyDescription } = this.state
|
const { dirtyDescription } = this.state
|
||||||
|
|
||||||
this.setState({ focused: false, dirtyDescription: null })
|
this.setState({
|
||||||
|
focused: false,
|
||||||
|
dirtyDescription: null,
|
||||||
|
})
|
||||||
|
|
||||||
if (dirtyDescription !== null) {
|
if (dirtyDescription !== null) {
|
||||||
this.props.onDescriptionChange(this.props.media.get('id'), dirtyDescription)
|
this.props.onDescriptionChange(this.props.media.get('id'), dirtyDescription)
|
||||||
@ -90,9 +92,7 @@ class Upload extends ImmutablePureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='compose-form-upload' tabIndex='0' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} onClick={this.handleClick} role='button'>
|
<div className='compose-form-upload' tabIndex='0' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} onClick={this.handleClick} role='button'>
|
||||||
<Motion defaultStyle={{ scale: 0.8 }} style={{ scale: spring(1, { stiffness: 180, damping: 12 }) }}>
|
<div className='compose-form__upload-thumbnail' style={{ backgroundImage: `url(${media.get('preview_url')})`, backgroundPosition: `${x}% ${y}%` }}>
|
||||||
{({ scale }) => (
|
|
||||||
<div className='compose-form__upload-thumbnail' style={{ transform: `scale(${scale})`, backgroundImage: `url(${media.get('preview_url')})`, backgroundPosition: `${x}% ${y}%` }}>
|
|
||||||
<div className={classNames('compose-form__upload__actions', { active })}>
|
<div className={classNames('compose-form__upload__actions', { active })}>
|
||||||
<Button
|
<Button
|
||||||
title={intl.formatMessage(messages.delete)}
|
title={intl.formatMessage(messages.delete)}
|
||||||
@ -119,8 +119,6 @@ class Upload extends ImmutablePureComponent {
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
</Motion>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export { default } from './warning'
|
|
@ -1,24 +0,0 @@
|
|||||||
import Motion from '../../../ui/util/optional_motion';
|
|
||||||
import spring from 'react-motion/lib/spring';
|
|
||||||
|
|
||||||
export default class Warning extends PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
message: PropTypes.node.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { message } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Motion defaultStyle={{ opacity: 0, scaleX: 0.85, scaleY: 0.75 }} style={{ opacity: spring(1, { damping: 35, stiffness: 400 }), scaleX: spring(1, { damping: 35, stiffness: 400 }), scaleY: spring(1, { damping: 35, stiffness: 400 }) }}>
|
|
||||||
{({ opacity, scaleX, scaleY }) => (
|
|
||||||
<div className='compose-form-warning' style={{ opacity: opacity, transform: `scale(${scaleX}, ${scaleY})` }}>
|
|
||||||
{message}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Motion>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
.compose-form-warning {
|
|
||||||
color: $inverted-text-color;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
background: $ui-primary-color;
|
|
||||||
box-shadow: 0 2px 6px rgba($base-shadow-color, 0.3);
|
|
||||||
padding: 8px 10px;
|
|
||||||
border-radius: 4px;
|
|
||||||
|
|
||||||
@include text-sizing(13px, 400);
|
|
||||||
|
|
||||||
strong {
|
|
||||||
color: $inverted-text-color;
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
@each $lang in $cjk-langs {
|
|
||||||
&:lang(#{$lang}) {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: $lighter-text-color;
|
|
||||||
font-weight: 500;
|
|
||||||
text-decoration: underline;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:active,
|
|
||||||
&:focus {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
import Warning from '../components/warning';
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
import { me } from '../../../initial_state';
|
|
||||||
|
|
||||||
const APPROX_HASHTAG_RE = /(?:^|[^\/\)\w])#(\w*[a-zA-Z·]\w*)/i;
|
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
|
||||||
needsLockWarning: state.getIn(['compose', 'privacy']) === 'private' && !state.getIn(['accounts', me, 'locked']),
|
|
||||||
hashtagWarning: state.getIn(['compose', 'privacy']) !== 'public' && APPROX_HASHTAG_RE.test(state.getIn(['compose', 'text'])),
|
|
||||||
directMessageWarning: state.getIn(['compose', 'privacy']) === 'direct',
|
|
||||||
});
|
|
||||||
|
|
||||||
const WarningWrapper = ({ needsLockWarning, hashtagWarning, directMessageWarning }) => {
|
|
||||||
if (needsLockWarning) {
|
|
||||||
return <Warning message={<FormattedMessage id='compose_form.lock_disclaimer' defaultMessage='Your account is not {locked}. Anyone can follow you to view your follower-only posts.' values={{ locked: <a href='/settings/profile'><FormattedMessage id='compose_form.lock_disclaimer.lock' defaultMessage='locked' /></a> }} />} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashtagWarning) {
|
|
||||||
return <Warning message={<FormattedMessage id='compose_form.hashtag_warning' defaultMessage="This gab won't be listed under any hashtag as it is unlisted. Only public gabs can be searched by hashtag." />} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (directMessageWarning) {
|
|
||||||
const message = (
|
|
||||||
<span>
|
|
||||||
<FormattedMessage id='compose_form.direct_message_warning' defaultMessage='This gab will only be sent to all the mentioned users.' /> <a href='/about/tos' target='_blank'><FormattedMessage id='compose_form.direct_message_warning_learn_more' defaultMessage='Learn more' /></a>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
|
|
||||||
return <Warning message={message} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
WarningWrapper.propTypes = {
|
|
||||||
needsLockWarning: PropTypes.bool,
|
|
||||||
hashtagWarning: PropTypes.bool,
|
|
||||||
directMessageWarning: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps)(WarningWrapper);
|
|
@ -372,6 +372,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderChildren(list) {
|
renderChildren(list) {
|
||||||
|
// : todo : comments
|
||||||
return list.map(id => (
|
return list.map(id => (
|
||||||
<StatusContainer
|
<StatusContainer
|
||||||
key={id}
|
key={id}
|
||||||
@ -464,7 +465,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
{ancestors}
|
{ancestors}
|
||||||
|
|
||||||
<HotKeys handlers={handlers}>
|
<HotKeys handlers={handlers}>
|
||||||
<div className={classNames('focusable', 'detailed-status__wrapper')} tabIndex='0' aria-label={textForScreenReader(intl, status, false)}>
|
<div className={_s.outlineNone} tabIndex='0' aria-label={textForScreenReader(intl, status, false)}>
|
||||||
{ /* <DetailedStatus
|
{ /* <DetailedStatus
|
||||||
status={status}
|
status={status}
|
||||||
onOpenVideo={this.handleOpenVideo}
|
onOpenVideo={this.handleOpenVideo}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import { fromJS, is } from 'immutable'
|
import { is } from 'immutable'
|
||||||
import { throttle } from 'lodash'
|
import { throttle } from 'lodash'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import { decode } from 'blurhash'
|
import { decode } from 'blurhash'
|
||||||
@ -7,7 +7,6 @@ import { isFullscreen, requestFullscreen, exitFullscreen } from '../../utils/ful
|
|||||||
import { isPanoramic, isPortrait, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio'
|
import { isPanoramic, isPortrait, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio'
|
||||||
import { displayMedia } from '../../initial_state'
|
import { displayMedia } from '../../initial_state'
|
||||||
import Button from '../../components/button'
|
import Button from '../../components/button'
|
||||||
import Icon from '../../components/icon'
|
|
||||||
import Text from '../../components/text'
|
import Text from '../../components/text'
|
||||||
|
|
||||||
const cx = classNames.bind(_s)
|
const cx = classNames.bind(_s)
|
||||||
@ -20,72 +19,74 @@ const messages = defineMessages({
|
|||||||
hide: { id: 'video.hide', defaultMessage: 'Hide video' },
|
hide: { id: 'video.hide', defaultMessage: 'Hide video' },
|
||||||
fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' },
|
fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' },
|
||||||
exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
|
exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
|
||||||
});
|
sensitive: { id: 'status.sensitive_warning', defaultMessage: 'Sensitive content' },
|
||||||
|
hidden: { id: 'status.media_hidden', defaultMessage: 'Media hidden' },
|
||||||
|
})
|
||||||
|
|
||||||
const formatTime = secondsNum => {
|
const formatTime = secondsNum => {
|
||||||
let hours = Math.floor(secondsNum / 3600);
|
let hours = Math.floor(secondsNum / 3600)
|
||||||
let minutes = Math.floor((secondsNum - (hours * 3600)) / 60);
|
let minutes = Math.floor((secondsNum - (hours * 3600)) / 60)
|
||||||
let seconds = secondsNum - (hours * 3600) - (minutes * 60);
|
let seconds = secondsNum - (hours * 3600) - (minutes * 60)
|
||||||
|
|
||||||
if (hours < 10) hours = '0' + hours;
|
if (hours < 10) hours = '0' + hours
|
||||||
if (minutes < 10) minutes = '0' + minutes;
|
if (minutes < 10) minutes = '0' + minutes
|
||||||
if (seconds < 10) seconds = '0' + seconds;
|
if (seconds < 10) seconds = '0' + seconds
|
||||||
|
|
||||||
return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}`;
|
return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}`
|
||||||
};
|
}
|
||||||
|
|
||||||
export const findElementPosition = el => {
|
export const findElementPosition = el => {
|
||||||
let box;
|
let box
|
||||||
|
|
||||||
if (el.getBoundingClientRect && el.parentNode) {
|
if (el.getBoundingClientRect && el.parentNode) {
|
||||||
box = el.getBoundingClientRect();
|
box = el.getBoundingClientRect()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!box) {
|
if (!box) {
|
||||||
return {
|
return {
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const docEl = document.documentElement;
|
const docEl = document.documentElement
|
||||||
const body = document.body;
|
const body = document.body
|
||||||
|
|
||||||
const clientLeft = docEl.clientLeft || body.clientLeft || 0;
|
const clientLeft = docEl.clientLeft || body.clientLeft || 0
|
||||||
const scrollLeft = window.pageXOffset || body.scrollLeft;
|
const scrollLeft = window.pageXOffset || body.scrollLeft
|
||||||
const left = (box.left + scrollLeft) - clientLeft;
|
const left = (box.left + scrollLeft) - clientLeft
|
||||||
|
|
||||||
const clientTop = docEl.clientTop || body.clientTop || 0;
|
const clientTop = docEl.clientTop || body.clientTop || 0
|
||||||
const scrollTop = window.pageYOffset || body.scrollTop;
|
const scrollTop = window.pageYOffset || body.scrollTop
|
||||||
const top = (box.top + scrollTop) - clientTop;
|
const top = (box.top + scrollTop) - clientTop
|
||||||
|
|
||||||
return {
|
return {
|
||||||
left: Math.round(left),
|
left: Math.round(left),
|
||||||
top: Math.round(top),
|
top: Math.round(top),
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export const getPointerPosition = (el, event) => {
|
|
||||||
const position = {};
|
|
||||||
const box = findElementPosition(el);
|
|
||||||
const boxW = el.offsetWidth;
|
|
||||||
const boxH = el.offsetHeight;
|
|
||||||
const boxY = box.top;
|
|
||||||
const boxX = box.left;
|
|
||||||
|
|
||||||
let pageY = event.pageY;
|
|
||||||
let pageX = event.pageX;
|
|
||||||
|
|
||||||
if (event.changedTouches) {
|
|
||||||
pageX = event.changedTouches[0].pageX;
|
|
||||||
pageY = event.changedTouches[0].pageY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
position.y = Math.max(0, Math.min(1, (pageY - boxY) / boxH));
|
export const getPointerPosition = (el, event) => {
|
||||||
position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW));
|
const position = {}
|
||||||
|
const box = findElementPosition(el)
|
||||||
|
const boxW = el.offsetWidth
|
||||||
|
const boxH = el.offsetHeight
|
||||||
|
const boxY = box.top
|
||||||
|
const boxX = box.left
|
||||||
|
|
||||||
return position;
|
let pageY = event.pageY
|
||||||
};
|
let pageX = event.pageX
|
||||||
|
|
||||||
|
if (event.changedTouches) {
|
||||||
|
pageX = event.changedTouches[0].pageX
|
||||||
|
pageY = event.changedTouches[0].pageY
|
||||||
|
}
|
||||||
|
|
||||||
|
position.y = Math.max(0, Math.min(1, (pageY - boxY) / boxH))
|
||||||
|
position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW))
|
||||||
|
|
||||||
|
return position
|
||||||
|
}
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@injectIntl
|
@injectIntl
|
||||||
@ -99,8 +100,6 @@ class Video extends PureComponent {
|
|||||||
height: PropTypes.number,
|
height: PropTypes.number,
|
||||||
sensitive: PropTypes.bool,
|
sensitive: PropTypes.bool,
|
||||||
startTime: PropTypes.number,
|
startTime: PropTypes.number,
|
||||||
onOpenVideo: PropTypes.func,
|
|
||||||
onCloseVideo: PropTypes.func,
|
|
||||||
detailed: PropTypes.bool,
|
detailed: PropTypes.bool,
|
||||||
inline: PropTypes.bool,
|
inline: PropTypes.bool,
|
||||||
cacheWidth: PropTypes.func,
|
cacheWidth: PropTypes.func,
|
||||||
@ -109,7 +108,7 @@ class Video extends PureComponent {
|
|||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
blurhash: PropTypes.string,
|
blurhash: PropTypes.string,
|
||||||
aspectRatio: PropTypes.number,
|
aspectRatio: PropTypes.number,
|
||||||
};
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
currentTime: 0,
|
currentTime: 0,
|
||||||
@ -121,237 +120,267 @@ class Video extends PureComponent {
|
|||||||
fullscreen: false,
|
fullscreen: false,
|
||||||
hovered: false,
|
hovered: false,
|
||||||
muted: false,
|
muted: false,
|
||||||
|
hoveringVolumeButton: false,
|
||||||
|
hoveringVolumeControl: false,
|
||||||
revealed: this.props.visible !== undefined ? this.props.visible : (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all'),
|
revealed: this.props.visible !== undefined ? this.props.visible : (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all'),
|
||||||
};
|
}
|
||||||
|
|
||||||
|
volHeight = 100
|
||||||
|
volOffset = 13
|
||||||
|
|
||||||
// hard coded in components.scss
|
|
||||||
// any way to get ::before values programatically?
|
|
||||||
volWidth = 50;
|
|
||||||
volOffset = 70;
|
|
||||||
volHandleOffset = v => {
|
volHandleOffset = v => {
|
||||||
const offset = v * this.volWidth + this.volOffset;
|
const offset = v * this.volHeight + this.volOffset
|
||||||
return (offset > 110) ? 110 : offset;
|
return (offset > 110) ? 110 : offset
|
||||||
}
|
}
|
||||||
|
|
||||||
setPlayerRef = c => {
|
setPlayerRef = c => {
|
||||||
this.player = c;
|
this.player = c
|
||||||
|
|
||||||
if (c) {
|
if (c) {
|
||||||
if (this.props.cacheWidth) this.props.cacheWidth(this.player.offsetWidth);
|
if (this.props.cacheWidth) this.props.cacheWidth(this.player.offsetWidth)
|
||||||
this.setState({
|
this.setState({
|
||||||
containerWidth: c.offsetWidth,
|
containerWidth: c.offsetWidth,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setVideoRef = c => {
|
setVideoRef = c => {
|
||||||
this.video = c;
|
this.video = c
|
||||||
|
|
||||||
if (this.video) {
|
if (this.video) {
|
||||||
this.setState({ volume: this.video.volume, muted: this.video.muted });
|
const { volume, muted } = this.video
|
||||||
|
this.setState({
|
||||||
|
volume,
|
||||||
|
muted,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setSeekRef = c => {
|
setSeekRef = c => {
|
||||||
this.seek = c;
|
this.seek = c
|
||||||
}
|
}
|
||||||
|
|
||||||
setVolumeRef = c => {
|
setVolumeRef = c => {
|
||||||
this.volume = c;
|
this.volume = c
|
||||||
}
|
}
|
||||||
|
|
||||||
setCanvasRef = c => {
|
setCanvasRef = c => {
|
||||||
this.canvas = c;
|
this.canvas = c
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClickRoot = e => e.stopPropagation();
|
handleClickRoot = e => e.stopPropagation()
|
||||||
|
|
||||||
handlePlay = () => {
|
handlePlay = () => {
|
||||||
this.setState({ paused: false });
|
this.setState({ paused: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePause = () => {
|
handlePause = () => {
|
||||||
this.setState({ paused: true });
|
this.setState({ paused: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTimeUpdate = () => {
|
handleTimeUpdate = () => {
|
||||||
|
const { currentTime, duration } = this.video
|
||||||
this.setState({
|
this.setState({
|
||||||
currentTime: Math.floor(this.video.currentTime),
|
currentTime: Math.floor(currentTime),
|
||||||
duration: Math.floor(this.video.duration),
|
duration: Math.floor(duration),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleVolumeMouseDown = e => {
|
handleVolumeMouseDown = e => {
|
||||||
document.addEventListener('mousemove', this.handleMouseVolSlide, true);
|
document.addEventListener('mousemove', this.handleMouseVolSlide, true)
|
||||||
document.addEventListener('mouseup', this.handleVolumeMouseUp, true);
|
document.addEventListener('mouseup', this.handleVolumeMouseUp, true)
|
||||||
document.addEventListener('touchmove', this.handleMouseVolSlide, true);
|
document.addEventListener('touchmove', this.handleMouseVolSlide, true)
|
||||||
document.addEventListener('touchend', this.handleVolumeMouseUp, true);
|
document.addEventListener('touchend', this.handleVolumeMouseUp, true)
|
||||||
|
|
||||||
this.handleMouseVolSlide(e);
|
this.handleMouseVolSlide(e)
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
e.stopPropagation();
|
e.stopPropagation()
|
||||||
}
|
}
|
||||||
|
|
||||||
handleVolumeMouseUp = () => {
|
handleVolumeMouseUp = () => {
|
||||||
document.removeEventListener('mousemove', this.handleMouseVolSlide, true);
|
document.removeEventListener('mousemove', this.handleMouseVolSlide, true)
|
||||||
document.removeEventListener('mouseup', this.handleVolumeMouseUp, true);
|
document.removeEventListener('mouseup', this.handleVolumeMouseUp, true)
|
||||||
document.removeEventListener('touchmove', this.handleMouseVolSlide, true);
|
document.removeEventListener('touchmove', this.handleMouseVolSlide, true)
|
||||||
document.removeEventListener('touchend', this.handleVolumeMouseUp, true);
|
document.removeEventListener('touchend', this.handleVolumeMouseUp, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseVolSlide = throttle(e => {
|
handleMouseVolSlide = throttle(e => {
|
||||||
const rect = this.volume.getBoundingClientRect();
|
const rect = this.volume.getBoundingClientRect()
|
||||||
const x = (e.clientX - rect.left) / this.volWidth; //x position within the element.
|
const y = 1 - ((e.clientY - rect.top) / this.volHeight)
|
||||||
|
|
||||||
if (!isNaN(x)) {
|
if (!isNaN(y)) {
|
||||||
var slideamt = x;
|
var slideamt = y
|
||||||
if (x > 1) {
|
if (y > 1) {
|
||||||
slideamt = 1;
|
slideamt = 1
|
||||||
} else if (x < 0) {
|
} else if (y < 0) {
|
||||||
slideamt = 0;
|
slideamt = 0
|
||||||
}
|
}
|
||||||
this.video.volume = slideamt;
|
this.video.volume = slideamt
|
||||||
this.setState({ volume: slideamt });
|
this.setState({ volume: slideamt })
|
||||||
}
|
}
|
||||||
}, 60);
|
}, 60)
|
||||||
|
|
||||||
handleMouseDown = e => {
|
handleMouseDown = e => {
|
||||||
document.addEventListener('mousemove', this.handleMouseMove, true);
|
document.addEventListener('mousemove', this.handleMouseMove, true)
|
||||||
document.addEventListener('mouseup', this.handleMouseUp, true);
|
document.addEventListener('mouseup', this.handleMouseUp, true)
|
||||||
document.addEventListener('touchmove', this.handleMouseMove, true);
|
document.addEventListener('touchmove', this.handleMouseMove, true)
|
||||||
document.addEventListener('touchend', this.handleMouseUp, true);
|
document.addEventListener('touchend', this.handleMouseUp, true)
|
||||||
|
|
||||||
this.setState({ dragging: true });
|
this.setState({ dragging: true })
|
||||||
this.video.pause();
|
this.video.pause()
|
||||||
this.handleMouseMove(e);
|
this.handleMouseMove(e)
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
e.stopPropagation();
|
e.stopPropagation()
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseUp = () => {
|
handleMouseUp = () => {
|
||||||
document.removeEventListener('mousemove', this.handleMouseMove, true);
|
document.removeEventListener('mousemove', this.handleMouseMove, true)
|
||||||
document.removeEventListener('mouseup', this.handleMouseUp, true);
|
document.removeEventListener('mouseup', this.handleMouseUp, true)
|
||||||
document.removeEventListener('touchmove', this.handleMouseMove, true);
|
document.removeEventListener('touchmove', this.handleMouseMove, true)
|
||||||
document.removeEventListener('touchend', this.handleMouseUp, true);
|
document.removeEventListener('touchend', this.handleMouseUp, true)
|
||||||
|
|
||||||
this.setState({ dragging: false });
|
this.setState({ dragging: false })
|
||||||
this.video.play();
|
this.video.play()
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseMove = throttle(e => {
|
handleMouseMove = throttle(e => {
|
||||||
const { x } = getPointerPosition(this.seek, e);
|
const { x } = getPointerPosition(this.seek, e)
|
||||||
const currentTime = Math.floor(this.video.duration * x);
|
const currentTime = Math.floor(this.video.duration * x)
|
||||||
|
|
||||||
if (!isNaN(currentTime)) {
|
if (!isNaN(currentTime)) {
|
||||||
this.video.currentTime = currentTime;
|
this.video.currentTime = currentTime
|
||||||
this.setState({ currentTime });
|
this.setState({ currentTime })
|
||||||
}
|
}
|
||||||
}, 60);
|
}, 60)
|
||||||
|
|
||||||
togglePlay = () => {
|
togglePlay = () => {
|
||||||
if (this.state.paused) {
|
if (this.state.paused) {
|
||||||
this.video.play();
|
this.video.play()
|
||||||
} else {
|
} else {
|
||||||
this.video.pause();
|
this.video.pause()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleFullscreen = () => {
|
toggleFullscreen = () => {
|
||||||
if (isFullscreen()) {
|
if (isFullscreen()) {
|
||||||
exitFullscreen();
|
exitFullscreen()
|
||||||
} else {
|
} else {
|
||||||
requestFullscreen(this.player);
|
requestFullscreen(this.player)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
document.addEventListener('fullscreenchange', this.handleFullscreenChange, true);
|
document.addEventListener('fullscreenchange', this.handleFullscreenChange, true)
|
||||||
document.addEventListener('webkitfullscreenchange', this.handleFullscreenChange, true);
|
document.addEventListener('webkitfullscreenchange', this.handleFullscreenChange, true)
|
||||||
document.addEventListener('mozfullscreenchange', this.handleFullscreenChange, true);
|
document.addEventListener('mozfullscreenchange', this.handleFullscreenChange, true)
|
||||||
document.addEventListener('MSFullscreenChange', this.handleFullscreenChange, true);
|
document.addEventListener('MSFullscreenChange', this.handleFullscreenChange, true)
|
||||||
|
|
||||||
if (this.props.blurhash) {
|
if (this.props.blurhash) {
|
||||||
this._decode();
|
this._decode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
document.removeEventListener('fullscreenchange', this.handleFullscreenChange, true);
|
document.removeEventListener('fullscreenchange', this.handleFullscreenChange, true)
|
||||||
document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange, true);
|
document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange, true)
|
||||||
document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange, true);
|
document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange, true)
|
||||||
document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange, true);
|
document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (!is(nextProps.visible, this.props.visible) && nextProps.visible !== undefined) {
|
if (!is(nextProps.visible, this.props.visible) && nextProps.visible !== undefined) {
|
||||||
this.setState({ revealed: nextProps.visible });
|
this.setState({ revealed: nextProps.visible })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState) {
|
componentDidUpdate(prevProps, prevState) {
|
||||||
if (prevState.revealed && !this.state.revealed && this.video) {
|
if (prevState.revealed && !this.state.revealed && this.video) {
|
||||||
this.video.pause();
|
this.video.pause()
|
||||||
}
|
}
|
||||||
if (prevProps.blurhash !== this.props.blurhash && this.props.blurhash) {
|
if (prevProps.blurhash !== this.props.blurhash && this.props.blurhash) {
|
||||||
this._decode();
|
this._decode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_decode() {
|
_decode() {
|
||||||
const hash = this.props.blurhash;
|
const hash = this.props.blurhash
|
||||||
const pixels = decode(hash, 32, 32);
|
const pixels = decode(hash, 32, 32)
|
||||||
|
|
||||||
if (pixels && this.canvas) {
|
if (pixels && this.canvas) {
|
||||||
const ctx = this.canvas.getContext('2d');
|
const ctx = this.canvas.getContext('2d')
|
||||||
const imageData = new ImageData(pixels, 32, 32);
|
const imageData = new ImageData(pixels, 32, 32)
|
||||||
|
|
||||||
ctx.putImageData(imageData, 0, 0);
|
ctx.putImageData(imageData, 0, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFullscreenChange = () => {
|
handleFullscreenChange = () => {
|
||||||
this.setState({ fullscreen: isFullscreen() });
|
this.setState({ fullscreen: isFullscreen() })
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseEnter = () => {
|
handleMouseEnter = () => {
|
||||||
this.setState({ hovered: true });
|
this.setState({ hovered: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseLeave = () => {
|
handleMouseLeave = () => {
|
||||||
this.setState({ hovered: false });
|
this.setState({ hovered: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleMouseEnterAudio = () => {
|
||||||
|
this.setState({ hoveringVolumeButton: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMouseLeaveAudio = throttle(e => {
|
||||||
|
this.setState({ hoveringVolumeButton: false })
|
||||||
|
}, 2000)
|
||||||
|
|
||||||
|
handleMouseEnterVolumeControl = () => {
|
||||||
|
this.setState({ hoveringVolumeControl: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMouseLeaveVolumeControl = throttle(e => {
|
||||||
|
this.setState({ hoveringVolumeControl: false })
|
||||||
|
}, 2000)
|
||||||
|
|
||||||
toggleMute = () => {
|
toggleMute = () => {
|
||||||
this.video.muted = !this.video.muted;
|
this.video.muted = !this.video.muted
|
||||||
this.setState({ muted: this.video.muted });
|
this.setState({ muted: this.video.muted })
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleReveal = () => {
|
toggleReveal = () => {
|
||||||
if (this.props.onToggleVisibility) {
|
if (this.props.onToggleVisibility) {
|
||||||
this.props.onToggleVisibility();
|
this.props.onToggleVisibility()
|
||||||
} else {
|
} else {
|
||||||
this.setState({ revealed: !this.state.revealed });
|
this.setState({ revealed: !this.state.revealed })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLoadedData = () => {
|
handleLoadedData = () => {
|
||||||
if (this.props.startTime) {
|
if (this.props.startTime) {
|
||||||
this.video.currentTime = this.props.startTime;
|
this.video.currentTime = this.props.startTime
|
||||||
this.video.play();
|
this.video.play()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleProgress = () => {
|
handleProgress = () => {
|
||||||
if (!this.video.buffered) return;
|
const { buffered, duration } = this.video
|
||||||
if (this.video.buffered.length > 0) {
|
|
||||||
this.setState({ buffer: this.video.buffered.end(0) / this.video.duration * 100 });
|
if (!buffered) return
|
||||||
|
if (buffered.length > 0) {
|
||||||
|
this.setState({
|
||||||
|
buffer: buffered.end(0) / duration * 100,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleVolumeChange = () => {
|
handleVolumeChange = () => {
|
||||||
this.setState({ volume: this.video.volume, muted: this.video.muted });
|
const { volume, muted } = this.video
|
||||||
|
this.setState({
|
||||||
|
volume,
|
||||||
|
muted,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -360,8 +389,6 @@ class Video extends PureComponent {
|
|||||||
src,
|
src,
|
||||||
inline,
|
inline,
|
||||||
startTime,
|
startTime,
|
||||||
onOpenVideo,
|
|
||||||
onCloseVideo,
|
|
||||||
intl,
|
intl,
|
||||||
alt,
|
alt,
|
||||||
detailed,
|
detailed,
|
||||||
@ -380,54 +407,44 @@ class Video extends PureComponent {
|
|||||||
fullscreen,
|
fullscreen,
|
||||||
hovered,
|
hovered,
|
||||||
muted,
|
muted,
|
||||||
revealed
|
revealed,
|
||||||
|
hoveringVolumeButton,
|
||||||
|
hoveringVolumeControl
|
||||||
} = this.state
|
} = this.state
|
||||||
|
|
||||||
const progress = (currentTime / duration) * 100;
|
const progress = (currentTime / duration) * 100
|
||||||
|
|
||||||
const volumeWidth = (muted) ? 0 : volume * this.volWidth;
|
const volumeHeight = (muted) ? 0 : volume * this.volHeight
|
||||||
const volumeHandleLoc = (muted) ? this.volHandleOffset(0) : this.volHandleOffset(volume);
|
const volumeHandleLoc = (muted) ? this.volHandleOffset(0) : this.volHandleOffset(volume)
|
||||||
const playerStyle = {};
|
const playerStyle = {}
|
||||||
|
|
||||||
let { width, height } = this.props;
|
let { width, height } = this.props
|
||||||
|
|
||||||
console.log("buffer, progress:", buffer, progress)
|
|
||||||
|
|
||||||
if (inline && containerWidth) {
|
if (inline && containerWidth) {
|
||||||
width = containerWidth;
|
width = containerWidth
|
||||||
const minSize = containerWidth / (16 / 9);
|
const minSize = containerWidth / (16 / 9)
|
||||||
|
|
||||||
if (isPanoramic(aspectRatio)) {
|
if (isPanoramic(aspectRatio)) {
|
||||||
height = Math.max(Math.floor(containerWidth / maximumAspectRatio), minSize);
|
height = Math.max(Math.floor(containerWidth / maximumAspectRatio), minSize)
|
||||||
} else if (isPortrait(aspectRatio)) {
|
} else if (isPortrait(aspectRatio)) {
|
||||||
height = Math.max(Math.floor(containerWidth / minimumAspectRatio), minSize);
|
height = Math.max(Math.floor(containerWidth / minimumAspectRatio), minSize)
|
||||||
} else {
|
} else {
|
||||||
height = Math.floor(containerWidth / aspectRatio);
|
height = Math.floor(containerWidth / aspectRatio)
|
||||||
}
|
}
|
||||||
|
|
||||||
playerStyle.height = height;
|
playerStyle.height = height
|
||||||
}
|
}
|
||||||
|
|
||||||
let preload;
|
let preload
|
||||||
|
|
||||||
if (startTime || fullscreen || dragging) {
|
if (startTime || fullscreen || dragging) {
|
||||||
preload = 'auto';
|
preload = 'auto'
|
||||||
} else if (detailed) {
|
} else if (detailed) {
|
||||||
preload = 'metadata';
|
preload = 'metadata'
|
||||||
} else {
|
} else {
|
||||||
preload = 'none';
|
preload = 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
let warning;
|
|
||||||
|
|
||||||
if (sensitive) {
|
|
||||||
warning = <FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' />;
|
|
||||||
} else {
|
|
||||||
warning = <FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' />;
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.log("width, height:", width, height)
|
|
||||||
|
|
||||||
// className={classNames('video-player', {
|
// className={classNames('video-player', {
|
||||||
// inactive: !revealed,
|
// inactive: !revealed,
|
||||||
// detailed,
|
// detailed,
|
||||||
@ -444,6 +461,7 @@ class Video extends PureComponent {
|
|||||||
backgroundColorBrand: 1,
|
backgroundColorBrand: 1,
|
||||||
marginLeftNeg5PX: 1,
|
marginLeftNeg5PX: 1,
|
||||||
z3: 1,
|
z3: 1,
|
||||||
|
boxShadow1: 1,
|
||||||
opacity0: !dragging,
|
opacity0: !dragging,
|
||||||
opacity1: dragging || hovered,
|
opacity1: dragging || hovered,
|
||||||
})
|
})
|
||||||
@ -456,6 +474,16 @@ class Video extends PureComponent {
|
|||||||
height4PX: 1,
|
height4PX: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const volumeControlClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
positionAbsolute: 1,
|
||||||
|
backgroundColorOpaque: 1,
|
||||||
|
videoPlayerVolume: 1,
|
||||||
|
height122PX: 1,
|
||||||
|
circle: 1,
|
||||||
|
displayNone: !hoveringVolumeButton && !hoveringVolumeControl || !hovered,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
role='menuitem'
|
role='menuitem'
|
||||||
@ -478,7 +506,6 @@ class Video extends PureComponent {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
revealed &&
|
revealed &&
|
||||||
<video
|
<video
|
||||||
@ -508,16 +535,38 @@ class Video extends PureComponent {
|
|||||||
|
|
||||||
{ /* <div className={classNames('spoiler-button', { 'spoiler-button--hidden': revealed })}>
|
{ /* <div className={classNames('spoiler-button', { 'spoiler-button--hidden': revealed })}>
|
||||||
<button type='button' className='spoiler-button__overlay' onClick={this.toggleReveal}>
|
<button type='button' className='spoiler-button__overlay' onClick={this.toggleReveal}>
|
||||||
<span className='spoiler-button__overlay__label'>{warning}</span>
|
<span className='spoiler-button__overlay__label'>
|
||||||
|
{intl.formatMessage(sensitive ? messages.sensitive : messages.hidden)}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div> */ }
|
</div> */ }
|
||||||
|
|
||||||
<div className='video-player__volume' onMouseDown={this.handleVolumeMouseDown} ref={this.setVolumeRef}>
|
<div
|
||||||
<div className='video-player__volume__current' style={{ height: `${volumeWidth}px` }} />
|
className={volumeControlClasses}
|
||||||
|
onMouseDown={this.handleVolumeMouseDown}
|
||||||
|
onMouseEnter={this.handleMouseEnterVolumeControl}
|
||||||
|
onMouseLeave={this.handleMouseLeaveVolumeControl}
|
||||||
|
ref={this.setVolumeRef}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={[_s.default, _s.radiusSmall, _s.marginVertical10PX, _s.positionAbsolute, _s.width4PX, _s.marginLeft10PX, _s.backgroundColorPrimaryOpaque].join(' ')}
|
||||||
|
style={{
|
||||||
|
height: '102px',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={[_s.default, _s.radiusSmall, _s.marginVertical10PX, _s.bottom0, _s.positionAbsolute, _s.width4PX, _s.marginLeft10PX, _s.backgroundColorPrimary].join(' ')}
|
||||||
|
style={{
|
||||||
|
height: `${volumeHeight}px`
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<span
|
<span
|
||||||
className={classNames('video-player__volume__handle')}
|
className={[_s.default, _s.cursorPointer, _s.positionAbsolute, _s.circle, _s.paddingHorizontal5PX, _s.boxShadow1, _s.marginBottomNeg5PX, _s.paddingVertical5PX, _s.backgroundColorPrimary, _s.z3].join(' ')}
|
||||||
tabIndex='0'
|
tabIndex='0'
|
||||||
style={{ left: `${volumeHandleLoc}px` }}
|
style={{
|
||||||
|
marginLeft: '7px',
|
||||||
|
bottom: `${volumeHandleLoc}px`,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -562,7 +611,6 @@ class Video extends PureComponent {
|
|||||||
{formatTime(duration)}
|
{formatTime(duration)}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
narrow
|
narrow
|
||||||
backgroundColor='none'
|
backgroundColor='none'
|
||||||
@ -574,6 +622,8 @@ class Video extends PureComponent {
|
|||||||
iconHeight='24px'
|
iconHeight='24px'
|
||||||
iconClassName={_s.fillColorWhite}
|
iconClassName={_s.fillColorWhite}
|
||||||
className={[_s.paddingHorizontal10PX, _s.marginLeft10PX].join(' ')}
|
className={[_s.paddingHorizontal10PX, _s.marginLeft10PX].join(' ')}
|
||||||
|
onMouseEnter={this.handleMouseEnterAudio}
|
||||||
|
onMouseLeave={this.handleMouseLeaveAudio}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@ -592,7 +642,7 @@ class Video extends PureComponent {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,30 +26,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.inline {
|
|
||||||
video {
|
|
||||||
object-fit: contain;
|
|
||||||
position: relative;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__controls {
|
|
||||||
z-index: 2;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background: linear-gradient(0deg, rgba($base-shadow-color, 0.85) 0, rgba($base-shadow-color, 0.45) 60%, transparent);
|
|
||||||
padding: 0 15px;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity .1s ease;
|
|
||||||
|
|
||||||
@include abs-position(auto, 0, 0, 0);
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.inactive {
|
&.inactive {
|
||||||
|
|
||||||
video,
|
video,
|
||||||
@ -92,145 +68,4 @@
|
|||||||
@include text-sizing(11px, 500);
|
@include text-sizing(11px, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__buttons-bar {
|
|
||||||
padding-bottom: 10px;
|
|
||||||
|
|
||||||
@include flex(space-between);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__buttons {
|
|
||||||
font-size: 16px;
|
|
||||||
|
|
||||||
@include text-overflow(nowrap);
|
|
||||||
|
|
||||||
&.left {
|
|
||||||
button {
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.right {
|
|
||||||
button {
|
|
||||||
padding-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
background: transparent;
|
|
||||||
padding: 2px 10px;
|
|
||||||
font-size: 16px;
|
|
||||||
border: 0;
|
|
||||||
color: rgba($white, 0.75);
|
|
||||||
|
|
||||||
&:active,
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
color: $white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__time-sep,
|
|
||||||
&__time-total,
|
|
||||||
&__time-current {
|
|
||||||
@include text-sizing(14px, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__time-current {
|
|
||||||
color: $white;
|
|
||||||
margin-left: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__time-sep {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__time-sep,
|
|
||||||
&__time-total {
|
|
||||||
color: $white;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__volume {
|
|
||||||
display: inline;
|
|
||||||
height: 24px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
background: rgba($white, 0.35);
|
|
||||||
border-radius: 4px;
|
|
||||||
|
|
||||||
@include pseudo;
|
|
||||||
@include size(50px, 4px);
|
|
||||||
@include abs-position(auto, auto, 20px, 70px, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__current {
|
|
||||||
display: block;
|
|
||||||
height: 4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: lighten($ui-highlight-color, 8%);
|
|
||||||
|
|
||||||
@include abs-position(auto, auto, 20px, 70px);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__handle {
|
|
||||||
z-index: 3;
|
|
||||||
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(auto, auto, 16px, 70px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__link {
|
|
||||||
padding: 2px 10px;
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: $white;
|
|
||||||
|
|
||||||
@include text-sizing(14px, 500);
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:active,
|
|
||||||
&:focus {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__seek {
|
|
||||||
cursor: pointer;
|
|
||||||
height: 24px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
background: rgba($white, 0.35);
|
|
||||||
border-radius: 4px;
|
|
||||||
top: 10px;
|
|
||||||
|
|
||||||
@include pseudo;
|
|
||||||
@include size(100%, 40x);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.video-player__seek__handle {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.detailed,
|
|
||||||
&.fullscreen {
|
|
||||||
.video-player__buttons {
|
|
||||||
button {
|
|
||||||
@include vertical-padding(10px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -10,6 +10,7 @@ body {
|
|||||||
overscroll-behavior-y: none;
|
overscroll-behavior-y: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.statusContent,
|
||||||
.statusContent * {
|
.statusContent * {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -18,6 +19,7 @@ body {
|
|||||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dangerousContent,
|
||||||
.dangerousContent * {
|
.dangerousContent * {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -145,10 +147,6 @@ body {
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.outlineFocusBrand:focus {
|
|
||||||
outline: 2px solid #21cf7a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.resizeNone {
|
.resizeNone {
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
@ -286,7 +284,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.backgroundColorPrimaryOpaque {
|
.backgroundColorPrimaryOpaque {
|
||||||
background-color: rgba(255, 255, 255, 0.8);
|
background-color: rgba(255, 255, 255, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
.backgroundColorBrandLightOpaque {
|
.backgroundColorBrandLightOpaque {
|
||||||
@ -509,6 +507,10 @@ body {
|
|||||||
width: 25%;
|
width: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.width4PX {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.maxWidth100PC {
|
.maxWidth100PC {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
@ -714,6 +716,10 @@ body {
|
|||||||
margin-left: -5px;
|
margin-left: -5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.marginBottomNeg5PX {
|
||||||
|
margin-bottom: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
.marginRight2PX {
|
.marginRight2PX {
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
@ -787,6 +793,14 @@ body {
|
|||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.paddingTop5PX {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paddingBottom10PX {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.paddingBottom5PX {
|
.paddingBottom5PX {
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
@ -851,6 +865,22 @@ body {
|
|||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.opacity0 {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opacity1 {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.boxShadow1 {
|
||||||
|
box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, .25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.listStyleNone {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
.videoPlayerControlsBackground {
|
.videoPlayerControlsBackground {
|
||||||
background: linear-gradient(0deg, rgba(0, 0, 0, .85), rgba(0, 0, 0, .45) 60%, transparent);
|
background: linear-gradient(0deg, rgba(0, 0, 0, .85), rgba(0, 0, 0, .45) 60%, transparent);
|
||||||
}
|
}
|
||||||
@ -859,17 +889,35 @@ body {
|
|||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
/* background: rgba(255, 255, 255, 0.35); */
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.opacity0 {
|
.videoPlayerVolume {
|
||||||
opacity: 0;
|
width: 24px;
|
||||||
|
right: 65px;
|
||||||
|
bottom: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.opacity1 {
|
.select {
|
||||||
opacity: 1;
|
height: 42px;
|
||||||
|
line-height: 42px;
|
||||||
|
font-size: 18px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.emojione {
|
||||||
|
margin: -3px 0 0;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .videoPlayerVolume:before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
} */
|
@ -143,7 +143,6 @@
|
|||||||
"react-redux-loading-bar": "^4.0.8",
|
"react-redux-loading-bar": "^4.0.8",
|
||||||
"react-router-dom": "^4.1.1",
|
"react-router-dom": "^4.1.1",
|
||||||
"react-router-scroll-4": "^1.0.0-beta.1",
|
"react-router-scroll-4": "^1.0.0-beta.1",
|
||||||
"react-select": "^2.4.4",
|
|
||||||
"react-stickynode": "^2.1.1",
|
"react-stickynode": "^2.1.1",
|
||||||
"react-swipeable-views": "^0.13.0",
|
"react-swipeable-views": "^0.13.0",
|
||||||
"react-textarea-autosize": "^7.1.0",
|
"react-textarea-autosize": "^7.1.0",
|
||||||
|
146
yarn.lock
146
yarn.lock
@ -1540,18 +1540,6 @@
|
|||||||
exec-sh "^0.3.2"
|
exec-sh "^0.3.2"
|
||||||
minimist "^1.2.0"
|
minimist "^1.2.0"
|
||||||
|
|
||||||
"@emotion/babel-utils@^0.6.4":
|
|
||||||
version "0.6.10"
|
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/babel-utils/-/babel-utils-0.6.10.tgz#83dbf3dfa933fae9fc566e54fbb45f14674c6ccc"
|
|
||||||
integrity sha512-/fnkM/LTEp3jKe++T0KyTszVGWNKPNOUJfjNKLO17BzQ6QPxgbg3whayom1Qr2oLFH3V92tDymU+dT5q676uow==
|
|
||||||
dependencies:
|
|
||||||
"@emotion/hash" "^0.6.6"
|
|
||||||
"@emotion/memoize" "^0.6.6"
|
|
||||||
"@emotion/serialize" "^0.9.1"
|
|
||||||
convert-source-map "^1.5.1"
|
|
||||||
find-root "^1.1.0"
|
|
||||||
source-map "^0.7.2"
|
|
||||||
|
|
||||||
"@emotion/cache@^10.0.27":
|
"@emotion/cache@^10.0.27":
|
||||||
version "10.0.27"
|
version "10.0.27"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.27.tgz#7895db204e2c1a991ae33d51262a3a44f6737303"
|
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.27.tgz#7895db204e2c1a991ae33d51262a3a44f6737303"
|
||||||
@ -1588,11 +1576,6 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.4.tgz#f14932887422c9056b15a8d222a9074a7dfa2831"
|
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.4.tgz#f14932887422c9056b15a8d222a9074a7dfa2831"
|
||||||
integrity sha512-fxfMSBMX3tlIbKUdtGKxqB1fyrH6gVrX39Gsv3y8lRYKUqlgDt3UMqQyGnR1bQMa2B8aGnhLZokZgg8vT0Le+A==
|
integrity sha512-fxfMSBMX3tlIbKUdtGKxqB1fyrH6gVrX39Gsv3y8lRYKUqlgDt3UMqQyGnR1bQMa2B8aGnhLZokZgg8vT0Le+A==
|
||||||
|
|
||||||
"@emotion/hash@^0.6.2", "@emotion/hash@^0.6.6":
|
|
||||||
version "0.6.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.6.6.tgz#62266c5f0eac6941fece302abad69f2ee7e25e44"
|
|
||||||
integrity sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ==
|
|
||||||
|
|
||||||
"@emotion/is-prop-valid@0.8.6":
|
"@emotion/is-prop-valid@0.8.6":
|
||||||
version "0.8.6"
|
version "0.8.6"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.6.tgz#4757646f0a58e9dec614c47c838e7147d88c263c"
|
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.6.tgz#4757646f0a58e9dec614c47c838e7147d88c263c"
|
||||||
@ -1605,11 +1588,6 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
|
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
|
||||||
integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
|
integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
|
||||||
|
|
||||||
"@emotion/memoize@^0.6.1", "@emotion/memoize@^0.6.6":
|
|
||||||
version "0.6.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.6.6.tgz#004b98298d04c7ca3b4f50ca2035d4f60d2eed1b"
|
|
||||||
integrity sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ==
|
|
||||||
|
|
||||||
"@emotion/serialize@^0.11.15":
|
"@emotion/serialize@^0.11.15":
|
||||||
version "0.11.15"
|
version "0.11.15"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.15.tgz#9a0f5873fb458d87d4f23e034413c12ed60a705a"
|
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.15.tgz#9a0f5873fb458d87d4f23e034413c12ed60a705a"
|
||||||
@ -1621,16 +1599,6 @@
|
|||||||
"@emotion/utils" "0.11.3"
|
"@emotion/utils" "0.11.3"
|
||||||
csstype "^2.5.7"
|
csstype "^2.5.7"
|
||||||
|
|
||||||
"@emotion/serialize@^0.9.1":
|
|
||||||
version "0.9.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.9.1.tgz#a494982a6920730dba6303eb018220a2b629c145"
|
|
||||||
integrity sha512-zTuAFtyPvCctHBEL8KZ5lJuwBanGSutFEncqLn/m9T1a6a93smBStK+bZzcNPgj4QS8Rkw9VTwJGhRIUVO8zsQ==
|
|
||||||
dependencies:
|
|
||||||
"@emotion/hash" "^0.6.6"
|
|
||||||
"@emotion/memoize" "^0.6.6"
|
|
||||||
"@emotion/unitless" "^0.6.7"
|
|
||||||
"@emotion/utils" "^0.8.2"
|
|
||||||
|
|
||||||
"@emotion/sheet@0.9.4":
|
"@emotion/sheet@0.9.4":
|
||||||
version "0.9.4"
|
version "0.9.4"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5"
|
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5"
|
||||||
@ -1659,31 +1627,16 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04"
|
resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04"
|
||||||
integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==
|
integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==
|
||||||
|
|
||||||
"@emotion/stylis@^0.7.0":
|
|
||||||
version "0.7.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.7.1.tgz#50f63225e712d99e2b2b39c19c70fff023793ca5"
|
|
||||||
integrity sha512-/SLmSIkN13M//53TtNxgxo57mcJk/UJIDFRKwOiLIBEyBHEcipgR6hNMQ/59Sl4VjCJ0Z/3zeAZyvnSLPG/1HQ==
|
|
||||||
|
|
||||||
"@emotion/unitless@0.7.5":
|
"@emotion/unitless@0.7.5":
|
||||||
version "0.7.5"
|
version "0.7.5"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
|
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
|
||||||
integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
|
integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
|
||||||
|
|
||||||
"@emotion/unitless@^0.6.2", "@emotion/unitless@^0.6.7":
|
|
||||||
version "0.6.7"
|
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.6.7.tgz#53e9f1892f725b194d5e6a1684a7b394df592397"
|
|
||||||
integrity sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg==
|
|
||||||
|
|
||||||
"@emotion/utils@0.11.3":
|
"@emotion/utils@0.11.3":
|
||||||
version "0.11.3"
|
version "0.11.3"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924"
|
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924"
|
||||||
integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==
|
integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==
|
||||||
|
|
||||||
"@emotion/utils@^0.8.2":
|
|
||||||
version "0.8.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.8.2.tgz#576ff7fb1230185b619a75d258cbc98f0867a8dc"
|
|
||||||
integrity sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw==
|
|
||||||
|
|
||||||
"@emotion/weak-memoize@0.2.5":
|
"@emotion/weak-memoize@0.2.5":
|
||||||
version "0.2.5"
|
version "0.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
|
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
|
||||||
@ -3232,24 +3185,6 @@ babel-plugin-emotion@^10.0.20, babel-plugin-emotion@^10.0.27:
|
|||||||
find-root "^1.1.0"
|
find-root "^1.1.0"
|
||||||
source-map "^0.5.7"
|
source-map "^0.5.7"
|
||||||
|
|
||||||
babel-plugin-emotion@^9.2.11:
|
|
||||||
version "9.2.11"
|
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-9.2.11.tgz#319c005a9ee1d15bb447f59fe504c35fd5807728"
|
|
||||||
integrity sha512-dgCImifnOPPSeXod2znAmgc64NhaaOjGEHROR/M+lmStb3841yK1sgaDYAYMnlvWNz8GnpwIPN0VmNpbWYZ+VQ==
|
|
||||||
dependencies:
|
|
||||||
"@babel/helper-module-imports" "^7.0.0"
|
|
||||||
"@emotion/babel-utils" "^0.6.4"
|
|
||||||
"@emotion/hash" "^0.6.2"
|
|
||||||
"@emotion/memoize" "^0.6.1"
|
|
||||||
"@emotion/stylis" "^0.7.0"
|
|
||||||
babel-plugin-macros "^2.0.0"
|
|
||||||
babel-plugin-syntax-jsx "^6.18.0"
|
|
||||||
convert-source-map "^1.5.0"
|
|
||||||
find-root "^1.1.0"
|
|
||||||
mkdirp "^0.5.1"
|
|
||||||
source-map "^0.5.7"
|
|
||||||
touch "^2.0.1"
|
|
||||||
|
|
||||||
babel-plugin-istanbul@^5.1.0:
|
babel-plugin-istanbul@^5.1.0:
|
||||||
version "5.2.0"
|
version "5.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz#df4ade83d897a92df069c4d9a25cf2671293c854"
|
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz#df4ade83d897a92df069c4d9a25cf2671293c854"
|
||||||
@ -4475,7 +4410,7 @@ content-type@~1.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||||
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
|
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
|
||||||
|
|
||||||
convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1:
|
convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
|
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
|
||||||
integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
|
integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
|
||||||
@ -4601,19 +4536,6 @@ create-ecdh@^4.0.0:
|
|||||||
bn.js "^4.1.0"
|
bn.js "^4.1.0"
|
||||||
elliptic "^6.0.0"
|
elliptic "^6.0.0"
|
||||||
|
|
||||||
create-emotion@^9.2.12:
|
|
||||||
version "9.2.12"
|
|
||||||
resolved "https://registry.yarnpkg.com/create-emotion/-/create-emotion-9.2.12.tgz#0fc8e7f92c4f8bb924b0fef6781f66b1d07cb26f"
|
|
||||||
integrity sha512-P57uOF9NL2y98Xrbl2OuiDQUZ30GVmASsv5fbsjF4Hlraip2kyAvMm+2PoYUvFFw03Fhgtxk3RqZSm2/qHL9hA==
|
|
||||||
dependencies:
|
|
||||||
"@emotion/hash" "^0.6.2"
|
|
||||||
"@emotion/memoize" "^0.6.1"
|
|
||||||
"@emotion/stylis" "^0.7.0"
|
|
||||||
"@emotion/unitless" "^0.6.2"
|
|
||||||
csstype "^2.5.2"
|
|
||||||
stylis "^3.5.0"
|
|
||||||
stylis-rule-sheet "^0.0.10"
|
|
||||||
|
|
||||||
create-hash@^1.1.0, create-hash@^1.1.2:
|
create-hash@^1.1.0, create-hash@^1.1.2:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
|
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
|
||||||
@ -4936,7 +4858,7 @@ cssstyle@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
cssom "0.3.x"
|
cssom "0.3.x"
|
||||||
|
|
||||||
csstype@^2.2.0, csstype@^2.5.2:
|
csstype@^2.2.0:
|
||||||
version "2.6.7"
|
version "2.6.7"
|
||||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5"
|
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5"
|
||||||
integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ==
|
integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ==
|
||||||
@ -5497,14 +5419,6 @@ emotion-theming@^10.0.19:
|
|||||||
"@emotion/weak-memoize" "0.2.5"
|
"@emotion/weak-memoize" "0.2.5"
|
||||||
hoist-non-react-statics "^3.3.0"
|
hoist-non-react-statics "^3.3.0"
|
||||||
|
|
||||||
emotion@^9.1.2:
|
|
||||||
version "9.2.12"
|
|
||||||
resolved "https://registry.yarnpkg.com/emotion/-/emotion-9.2.12.tgz#53925aaa005614e65c6e43db8243c843574d1ea9"
|
|
||||||
integrity sha512-hcx7jppaI8VoXxIWEhxpDW7I+B4kq9RNzQLmsrF6LY8BGKqe2N+gFAQr0EfuFucFlPs2A9HM4+xNj4NeqEWIOQ==
|
|
||||||
dependencies:
|
|
||||||
babel-plugin-emotion "^9.2.11"
|
|
||||||
create-emotion "^9.2.12"
|
|
||||||
|
|
||||||
encodeurl@~1.0.2:
|
encodeurl@~1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||||
@ -8975,11 +8889,6 @@ mem@^4.0.0:
|
|||||||
mimic-fn "^2.0.0"
|
mimic-fn "^2.0.0"
|
||||||
p-is-promise "^2.0.0"
|
p-is-promise "^2.0.0"
|
||||||
|
|
||||||
memoize-one@^5.0.0:
|
|
||||||
version "5.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0"
|
|
||||||
integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==
|
|
||||||
|
|
||||||
memoizerific@^1.11.3:
|
memoizerific@^1.11.3:
|
||||||
version "1.11.3"
|
version "1.11.3"
|
||||||
resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a"
|
resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a"
|
||||||
@ -9572,13 +9481,6 @@ nopt@^4.0.1:
|
|||||||
abbrev "1"
|
abbrev "1"
|
||||||
osenv "^0.1.4"
|
osenv "^0.1.4"
|
||||||
|
|
||||||
nopt@~1.0.10:
|
|
||||||
version "1.0.10"
|
|
||||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
|
|
||||||
integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=
|
|
||||||
dependencies:
|
|
||||||
abbrev "1"
|
|
||||||
|
|
||||||
normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
|
normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
|
||||||
version "2.5.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
|
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
|
||||||
@ -11393,13 +11295,6 @@ react-infinite-scroller@^1.0.12:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prop-types "^15.5.8"
|
prop-types "^15.5.8"
|
||||||
|
|
||||||
react-input-autosize@^2.2.1:
|
|
||||||
version "2.2.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.2.tgz#fcaa7020568ec206bc04be36f4eb68e647c4d8c2"
|
|
||||||
integrity sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw==
|
|
||||||
dependencies:
|
|
||||||
prop-types "^15.5.8"
|
|
||||||
|
|
||||||
react-intl-translations-manager@^5.0.3:
|
react-intl-translations-manager@^5.0.3:
|
||||||
version "5.0.3"
|
version "5.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/react-intl-translations-manager/-/react-intl-translations-manager-5.0.3.tgz#aee010ecf35975673e033ca5d7d3f4147894324d"
|
resolved "https://registry.yarnpkg.com/react-intl-translations-manager/-/react-intl-translations-manager-5.0.3.tgz#aee010ecf35975673e033ca5d7d3f4147894324d"
|
||||||
@ -11559,19 +11454,6 @@ react-router@^4.3.1:
|
|||||||
prop-types "^15.6.1"
|
prop-types "^15.6.1"
|
||||||
warning "^4.0.1"
|
warning "^4.0.1"
|
||||||
|
|
||||||
react-select@^2.4.4:
|
|
||||||
version "2.4.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-select/-/react-select-2.4.4.tgz#ba72468ef1060c7d46fbb862b0748f96491f1f73"
|
|
||||||
integrity sha512-C4QPLgy9h42J/KkdrpVxNmkY6p4lb49fsrbDk/hRcZpX7JvZPNb6mGj+c5SzyEtBv1DmQ9oPH4NmhAFvCrg8Jw==
|
|
||||||
dependencies:
|
|
||||||
classnames "^2.2.5"
|
|
||||||
emotion "^9.1.2"
|
|
||||||
memoize-one "^5.0.0"
|
|
||||||
prop-types "^15.6.0"
|
|
||||||
raf "^3.4.0"
|
|
||||||
react-input-autosize "^2.2.1"
|
|
||||||
react-transition-group "^2.2.1"
|
|
||||||
|
|
||||||
react-sizeme@^2.6.7:
|
react-sizeme@^2.6.7:
|
||||||
version "2.6.12"
|
version "2.6.12"
|
||||||
resolved "https://registry.yarnpkg.com/react-sizeme/-/react-sizeme-2.6.12.tgz#ed207be5476f4a85bf364e92042520499455453e"
|
resolved "https://registry.yarnpkg.com/react-sizeme/-/react-sizeme-2.6.12.tgz#ed207be5476f4a85bf364e92042520499455453e"
|
||||||
@ -11660,7 +11542,7 @@ react-toggle@^4.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
classnames "^2.2.5"
|
classnames "^2.2.5"
|
||||||
|
|
||||||
react-transition-group@^2.2.0, react-transition-group@^2.2.1:
|
react-transition-group@^2.2.0:
|
||||||
version "2.9.0"
|
version "2.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"
|
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"
|
||||||
integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==
|
integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==
|
||||||
@ -12742,11 +12624,6 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
|
|||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||||
|
|
||||||
source-map@^0.7.2:
|
|
||||||
version "0.7.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
|
||||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
|
||||||
|
|
||||||
space-separated-tokens@^1.0.0:
|
space-separated-tokens@^1.0.0:
|
||||||
version "1.1.5"
|
version "1.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899"
|
resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899"
|
||||||
@ -13141,16 +13018,6 @@ stylehacks@^4.0.0:
|
|||||||
postcss "^7.0.0"
|
postcss "^7.0.0"
|
||||||
postcss-selector-parser "^3.0.0"
|
postcss-selector-parser "^3.0.0"
|
||||||
|
|
||||||
stylis-rule-sheet@^0.0.10:
|
|
||||||
version "0.0.10"
|
|
||||||
resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430"
|
|
||||||
integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==
|
|
||||||
|
|
||||||
stylis@^3.5.0:
|
|
||||||
version "3.5.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe"
|
|
||||||
integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==
|
|
||||||
|
|
||||||
subscribe-ui-event@^2.0.0:
|
subscribe-ui-event@^2.0.0:
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/subscribe-ui-event/-/subscribe-ui-event-2.0.5.tgz#f276d8eae3f82b640e69d7b9d55f7334f9ec67ec"
|
resolved "https://registry.yarnpkg.com/subscribe-ui-event/-/subscribe-ui-event-2.0.5.tgz#f276d8eae3f82b640e69d7b9d55f7334f9ec67ec"
|
||||||
@ -13514,13 +13381,6 @@ toidentifier@1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||||
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
||||||
|
|
||||||
touch@^2.0.1:
|
|
||||||
version "2.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/touch/-/touch-2.0.2.tgz#ca0b2a3ae3211246a61b16ba9e6cbf1596287164"
|
|
||||||
integrity sha512-qjNtvsFXTRq7IuMLweVgFxmEuQ6gLbRs2jQxL80TtZ31dEKWYIxRXquij6w6VimyDek5hD3PytljHmEtAs2u0A==
|
|
||||||
dependencies:
|
|
||||||
nopt "~1.0.10"
|
|
||||||
|
|
||||||
tough-cookie@^2.3.3, tough-cookie@^2.3.4:
|
tough-cookie@^2.3.3, tough-cookie@^2.3.4:
|
||||||
version "2.5.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user