Progress
This commit is contained in:
@@ -165,7 +165,7 @@ class Account extends ImmutablePureComponent {
|
||||
<NavLink
|
||||
title={account.get('acct')}
|
||||
to={`/${account.get('acct')}`}
|
||||
className={[_s.default, _s.alignItemsStart, _s.noUnderline, _s.px10, _s.flexGrow1].join(' ')}
|
||||
className={[_s.default, _s.alignItemsStart, _s.noUnderline, _s.px10, _s.overflowHidden, _s.flexNormal].join(' ')}
|
||||
>
|
||||
<DisplayName account={account} isMultiline={compact} />
|
||||
{!compact && actionButton}
|
||||
|
||||
@@ -164,13 +164,13 @@ export default class Button extends PureComponent {
|
||||
|
||||
underline_onHover: underlineOnHover,
|
||||
|
||||
backgroundColorSubtle2Dark_onHover: backgroundColor === COLORS.tertiary || backgroundColor === COLORS.secondary,
|
||||
backgroundColorBlackOpaque_onHover: backgroundColor === COLORS.black,
|
||||
backgroundColorBrandDark_onHover: backgroundColor === COLORS.brand,
|
||||
backgroundColorDangerDark_onHover: backgroundColor === COLORS.danger,
|
||||
backgroundColorSubtle2Dark_onHover: backgroundColor === COLORS.tertiary || backgroundColor === COLORS.secondary && !isDisabled,
|
||||
backgroundColorBlackOpaque_onHover: backgroundColor === COLORS.black && !isDisabled,
|
||||
backgroundColorBrandDark_onHover: backgroundColor === COLORS.brand && !isDisabled,
|
||||
backgroundColorDangerDark_onHover: backgroundColor === COLORS.danger && !isDisabled,
|
||||
|
||||
backgroundColorBrand_onHover: color === COLORS.brand && isOutline,
|
||||
colorWhite_onHover: !!children && color === COLORS.brand && isOutline,
|
||||
backgroundColorBrand_onHover: color === COLORS.brand && isOutline && !isDisabled,
|
||||
colorWhite_onHover: !!children && color === COLORS.brand && isOutline && !isDisabled,
|
||||
|
||||
fillColorSecondary: !!icon && color === COLORS.secondary,
|
||||
fillColorWhite: !!icon && color === COLORS.white,
|
||||
|
||||
@@ -27,7 +27,7 @@ class ColumnIndicator extends PureComponent {
|
||||
render() {
|
||||
const { type, message, intl } = this.props
|
||||
|
||||
const title = type !== 'error' ? intl.formatMessage(messages[type]) : message
|
||||
const title = type !== 'error' && !message ? intl.formatMessage(messages[type]) : message
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.width100PC, _s.justifyContentCenter, _s.alignItemsCenter, _s.py15].join(' ')}>
|
||||
|
||||
@@ -60,7 +60,7 @@ class Comment extends ImmutablePureComponent {
|
||||
<Avatar account={status.get('account')} size={32} />
|
||||
</NavLink>
|
||||
|
||||
<div className={[_s.default, _s.flexNormal].join(' ')}>
|
||||
<div className={_s.default}>
|
||||
<div className={[_s.default, _s.px10, _s.pt5, _s.pb10, _s.radiusSmall, _s.backgroundColorSubtle].join(' ')}>
|
||||
<CommentHeader status={status} />
|
||||
<StatusContent
|
||||
|
||||
@@ -161,7 +161,7 @@ class DisplayName extends ImmutablePureComponent {
|
||||
/>
|
||||
{
|
||||
!noRelationship && account.get('locked') &&
|
||||
<Icon id='lock-filled' size={iconSize} className={_s.ml5} />
|
||||
<Icon id='lock-filled' size={iconSize} className={[_s.fillColorPrimary, _s.ml5].join(' ')} />
|
||||
}
|
||||
</bdi>
|
||||
{
|
||||
|
||||
@@ -31,8 +31,6 @@ class FloatingActionButton extends PureComponent {
|
||||
return (
|
||||
<Button
|
||||
onClick={onOpenCompose}
|
||||
color='white'
|
||||
backgroundColor='brand'
|
||||
className={[_s.posFixed, _s.z4, _s.py15, _s.mb15, _s.mr15, _s.bottom0, _s.right0].join(' ')}
|
||||
title={message}
|
||||
aria-label={message}
|
||||
|
||||
37
app/javascript/gabsocial/components/form.js
Normal file
37
app/javascript/gabsocial/components/form.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import Text from './text'
|
||||
|
||||
export default class Form extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
children: PropTypes.any,
|
||||
errorMessage: PropTypes.string,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
children,
|
||||
errorMessage,
|
||||
onSubmit,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit} className={_s.default}>
|
||||
{
|
||||
!!errorMessage &&
|
||||
<Text color='danger' className={_s.my10}>
|
||||
{errorMessage}
|
||||
</Text>
|
||||
}
|
||||
<div className={_s.default}>
|
||||
{children}
|
||||
</div>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { Fragment } from 'react'
|
||||
import { NavLink } from 'react-router-dom'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import classNames from 'classnames/bind'
|
||||
import { PLACEHOLDER_MISSING_HEADER_SRC } from '../constants'
|
||||
import { shortNumberFormat } from '../utils/numbers'
|
||||
import Button from './button'
|
||||
import DotTextSeperator from './dot_text_seperator'
|
||||
@@ -34,10 +35,16 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
group: ImmutablePropTypes.map,
|
||||
relationships: ImmutablePropTypes.map,
|
||||
isHidden: PropTypes.bool,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, group, relationships } = this.props
|
||||
const {
|
||||
intl,
|
||||
group,
|
||||
relationships,
|
||||
isHidden,
|
||||
} = this.props
|
||||
|
||||
if (!relationships) return null
|
||||
|
||||
@@ -53,7 +60,20 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
||||
|
||||
const isMember = relationships.get('member')
|
||||
const isAdmin = relationships.get('admin')
|
||||
const coverSrc = group.get('cover')
|
||||
const coverSrc = group.get('cover_image_url') || ''
|
||||
const coverMissing = coverSrc.indexOf(PLACEHOLDER_MISSING_HEADER_SRC) > -1 || !coverSrc
|
||||
|
||||
|
||||
if (isHidden) {
|
||||
return (
|
||||
<Fragment>
|
||||
{group.get('title')}
|
||||
{subtitle}
|
||||
{isMember && intl.formatMessage(messages.member)}
|
||||
{isAdmin && intl.formatMessage(messages.admin)}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
const navLinkClasses = cx({
|
||||
default: 1,
|
||||
@@ -77,7 +97,7 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
||||
className={navLinkClasses}
|
||||
>
|
||||
{
|
||||
!!coverSrc &&
|
||||
!!coverSrc && !coverMissing &&
|
||||
<Image
|
||||
src={coverSrc}
|
||||
alt={group.get('title')}
|
||||
@@ -86,7 +106,7 @@ class GroupCollectionItem extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
{
|
||||
!coverSrc && (isMember || isAdmin) &&
|
||||
(!coverSrc || coverMissing) && (isMember || isAdmin) &&
|
||||
<div className={[_s.default, _s.height40PX, _s.backgroundColorSubtle, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')} />
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class GroupHeader extends ImmutablePureComponent {
|
||||
},
|
||||
]
|
||||
|
||||
const coverSrc = !!group ? group.get('cover') : undefined
|
||||
const coverSrc = !!group ? group.get('cover_image_url') : undefined
|
||||
const title = !!group ? group.get('title') : undefined
|
||||
|
||||
return (
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Fragment } from 'react'
|
||||
import { NavLink } from 'react-router-dom'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import classNames from 'classnames/bind'
|
||||
import { PLACEHOLDER_MISSING_HEADER_SRC } from '../constants'
|
||||
import { shortNumberFormat } from '../utils/numbers'
|
||||
import Image from './image'
|
||||
import Text from './text'
|
||||
@@ -31,6 +32,7 @@ class GroupListItem extends ImmutablePureComponent {
|
||||
relationships: ImmutablePropTypes.map,
|
||||
slim: PropTypes.bool,
|
||||
isLast: PropTypes.bool,
|
||||
isHidden: PropTypes.bool,
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
@@ -39,9 +41,16 @@ class GroupListItem extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, group, relationships, slim, isLast } = this.props
|
||||
const {
|
||||
intl,
|
||||
group,
|
||||
relationships,
|
||||
slim,
|
||||
isLast,
|
||||
isHidden,
|
||||
} = this.props
|
||||
|
||||
if (!relationships) return null
|
||||
if (!relationships || !group) return null
|
||||
|
||||
const unreadCount = relationships.get('unread_count')
|
||||
|
||||
@@ -53,6 +62,15 @@ class GroupListItem extends ImmutablePureComponent {
|
||||
</Fragment>
|
||||
) : intl.formatMessage(messages.no_recent_activity)
|
||||
|
||||
if (isHidden) {
|
||||
return (
|
||||
<Fragment>
|
||||
{group.get('title')}
|
||||
{subtitle}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
const containerClasses = cx({
|
||||
default: 1,
|
||||
noUnderline: 1,
|
||||
@@ -80,10 +98,12 @@ class GroupListItem extends ImmutablePureComponent {
|
||||
default: 1,
|
||||
px10: 1,
|
||||
mt5: 1,
|
||||
flexShrink1: slim,
|
||||
mb10: !slim,
|
||||
})
|
||||
|
||||
const coverSrc = group.get('cover')
|
||||
const coverSrc = group.get('cover_image_url') || ''
|
||||
const coverMissing = coverSrc.indexOf(PLACEHOLDER_MISSING_HEADER_SRC) > -1 || !coverSrc
|
||||
|
||||
return (
|
||||
<NavLink
|
||||
@@ -92,7 +112,7 @@ class GroupListItem extends ImmutablePureComponent {
|
||||
>
|
||||
|
||||
{
|
||||
(!!coverSrc || slim) &&
|
||||
(!!coverSrc || slim) && !coverMissing &&
|
||||
<Image
|
||||
src={coverSrc}
|
||||
alt={group.get('title')}
|
||||
|
||||
@@ -11,6 +11,7 @@ import ChatIcon from '../assets/chat_icon'
|
||||
import CircleIcon from '../assets/circle_icon'
|
||||
import CloseIcon from '../assets/close_icon'
|
||||
import CodeIcon from '../assets/code_icon'
|
||||
import CogIcon from '../assets/cog_icon'
|
||||
import CommentIcon from '../assets/comment_icon'
|
||||
import CopyIcon from '../assets/copy_icon'
|
||||
import DissenterIcon from '../assets/dissenter_icon'
|
||||
@@ -80,6 +81,7 @@ const ICONS = {
|
||||
'chat': ChatIcon,
|
||||
'close': CloseIcon,
|
||||
'code': CodeIcon,
|
||||
'cog': CogIcon,
|
||||
'comment': CommentIcon,
|
||||
'copy': CopyIcon,
|
||||
'dissenter': DissenterIcon,
|
||||
|
||||
@@ -7,6 +7,7 @@ import Text from './text'
|
||||
const cx = classNames.bind(_s)
|
||||
|
||||
export default class Input extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
placeholder: PropTypes.string,
|
||||
prependIcon: PropTypes.string,
|
||||
@@ -25,6 +26,10 @@ export default class Input extends PureComponent {
|
||||
hideLabel: PropTypes.bool,
|
||||
}
|
||||
|
||||
handleOnChange = (e) => {
|
||||
this.props.onChange(e.target.value)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
placeholder,
|
||||
@@ -55,6 +60,7 @@ export default class Input extends PureComponent {
|
||||
py5: small,
|
||||
backgroundTransparent: !readOnly,
|
||||
backgroundColorSubtle2: readOnly,
|
||||
colorPrimary: !readOnly,
|
||||
colorSecondary: readOnly,
|
||||
fontSize15PX: !small,
|
||||
fontSize13PX: small,
|
||||
@@ -101,7 +107,7 @@ export default class Input extends PureComponent {
|
||||
placeholder={placeholder}
|
||||
ref={inputRef}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onChange={this.handleOnChange}
|
||||
onKeyUp={onKeyUp}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Fragment } from 'react'
|
||||
import classNames from 'classnames/bind'
|
||||
import Button from './button'
|
||||
import Icon from './icon'
|
||||
@@ -9,6 +10,7 @@ export default class ListItem extends PureComponent {
|
||||
static propTypes = {
|
||||
icon: PropTypes.string,
|
||||
isLast: PropTypes.bool,
|
||||
isHidden: PropTypes.bool,
|
||||
to: PropTypes.string,
|
||||
href: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
@@ -29,8 +31,17 @@ export default class ListItem extends PureComponent {
|
||||
size,
|
||||
icon,
|
||||
hideArrow,
|
||||
isHidden,
|
||||
} = this.props
|
||||
|
||||
if (isHidden) {
|
||||
return (
|
||||
<Fragment>
|
||||
{title}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
const small = size === 'small'
|
||||
const large = size === 'large'
|
||||
|
||||
@@ -77,7 +88,7 @@ export default class ListItem extends PureComponent {
|
||||
/>
|
||||
}
|
||||
|
||||
<Text color='primary' size={textSize}>
|
||||
<Text color='primary' size={textSize} className={[_s.overflowHidden, _s.flexNormal, _s.pr5, _s.textOverflowEllipsis].join(' ')}>
|
||||
{title}
|
||||
</Text>
|
||||
|
||||
@@ -86,7 +97,7 @@ export default class ListItem extends PureComponent {
|
||||
<Icon
|
||||
id='angle-right'
|
||||
size='10px'
|
||||
className={[_s.mlAuto, _s.fillColorSecondary].join(' ')}
|
||||
className={[_s.mlAuto, _s.fillColorSecondary, _s.flexShrink1].join(' ')}
|
||||
/>
|
||||
}
|
||||
</Button>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import Button from './button'
|
||||
import Icon from './icon'
|
||||
import Text from './text'
|
||||
|
||||
const messages = defineMessages({
|
||||
@@ -15,8 +14,6 @@ class LoadMore extends PureComponent {
|
||||
onClick: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
visible: PropTypes.bool,
|
||||
maxId: PropTypes.string,
|
||||
gap: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
@@ -24,13 +21,16 @@ class LoadMore extends PureComponent {
|
||||
visible: true,
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
const { gap, maxId } = this.props
|
||||
this.props.onClick(gap ? maxId : undefined)
|
||||
handleClick = (e) => {
|
||||
this.props.onClick()
|
||||
}
|
||||
|
||||
render() {
|
||||
const { disabled, visible, gap, intl } = this.props
|
||||
const {
|
||||
disabled,
|
||||
visible,
|
||||
intl,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.py10, _s.px10].join(' ')}>
|
||||
@@ -40,22 +40,15 @@ class LoadMore extends PureComponent {
|
||||
backgroundColor='tertiary'
|
||||
color='primary'
|
||||
disabled={disabled || !visible}
|
||||
style={{ visibility: visible ? 'visible' : 'hidden' }}
|
||||
style={{
|
||||
visibility: visible ? 'visible' : 'hidden',
|
||||
}}
|
||||
onClick={this.handleClick}
|
||||
aria-label={intl.formatMessage(messages.load_more)}
|
||||
>
|
||||
{
|
||||
!gap &&
|
||||
<Text color='inherit' align='center'>
|
||||
{intl.formatMessage(messages.load_more)}
|
||||
</Text>
|
||||
}
|
||||
{
|
||||
gap &&
|
||||
<Text align='center'>
|
||||
<Icon id='ellipsis' size='14px' />
|
||||
</Text>
|
||||
}
|
||||
<Text color='inherit' align='center'>
|
||||
{intl.formatMessage(messages.load_more)}
|
||||
</Text>
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -13,13 +13,14 @@ const cx = classNames.bind(_s)
|
||||
export default class MediaItem extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
attachment: ImmutablePropTypes.map.isRequired,
|
||||
small: PropTypes.bool
|
||||
isSmall: PropTypes.bool,
|
||||
}
|
||||
|
||||
state = {
|
||||
visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all',
|
||||
loaded: false,
|
||||
visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all',
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -59,7 +60,11 @@ export default class MediaItem extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { attachment, small } = this.props
|
||||
const {
|
||||
account,
|
||||
attachment,
|
||||
isSmall,
|
||||
} = this.props
|
||||
const { visible, loaded } = this.state
|
||||
|
||||
const status = attachment.get('status')
|
||||
@@ -81,8 +86,8 @@ export default class MediaItem extends ImmutablePureComponent {
|
||||
top0: 1,
|
||||
height100PC: 1,
|
||||
width100PC: 1,
|
||||
py5: !small,
|
||||
px5: !small,
|
||||
py2: !isSmall,
|
||||
px2: !isSmall,
|
||||
})
|
||||
|
||||
const linkClasses = cx({
|
||||
@@ -91,15 +96,16 @@ export default class MediaItem extends ImmutablePureComponent {
|
||||
height100PC: 1,
|
||||
overflowHidden: 1,
|
||||
border1PX: 1,
|
||||
borderColorPrimary: !small,
|
||||
borderColorPrimary: small,
|
||||
borderColorPrimary: 1,
|
||||
})
|
||||
|
||||
const statusUrl = `/${account.getIn(['acct'])}/posts/${status.get('id')}`;
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.width25PC, _s.pt25PC].join(' ')}>
|
||||
<div className={containerClasses}>
|
||||
<NavLink
|
||||
to={status.get('url')} /* : todo : */
|
||||
to={statusUrl}
|
||||
title={title}
|
||||
className={linkClasses}
|
||||
>
|
||||
|
||||
@@ -51,7 +51,7 @@ class CommunityTimelineSettingsModal extends ImmutablePureComponent {
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
width='320'
|
||||
width={320}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
>
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { muteAccount } from '../../actions/accounts'
|
||||
|
||||
const messages = defineMessages({
|
||||
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
||||
title: { id: 'display_options', defaultMessage: 'Display Options' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class DisplayOptionsModal extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
isSubmitting: PropTypes.bool.isRequired,
|
||||
account: PropTypes.object.isRequired,
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.button.focus()
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onClose()
|
||||
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||
}
|
||||
|
||||
handleCancel = () => {
|
||||
this.props.onClose()
|
||||
}
|
||||
|
||||
// document.documentElement.style.setProperty("--color-surface", "black");
|
||||
|
||||
render() {
|
||||
const { account, intl } = this.props
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
width={320}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
>
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,10 +28,11 @@ class EditProfileModal extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account, intl } = this.props
|
||||
const { account, intl, onClose } = this.props
|
||||
|
||||
const headerSrc = !!account ? account.get('header') : ''
|
||||
|
||||
@@ -40,6 +41,7 @@ class EditProfileModal extends ImmutablePureComponent {
|
||||
title={intl.formatMessage(messages.edit_profile)}
|
||||
noPadding
|
||||
width={460}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className={[_s.default, _s.py5, _s.px5, _s.width100PC, _s.overflowHidden].join(' ')}>
|
||||
<Image
|
||||
|
||||
@@ -4,7 +4,7 @@ import ModalLayout from './modal_layout'
|
||||
import GroupCreate from '../../features/group_create'
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'create_group', defaultMessage: 'Create Group' },
|
||||
title: { id: 'create_group', defaultMessage: 'Create group' },
|
||||
})
|
||||
|
||||
export default
|
||||
@@ -22,7 +22,7 @@ class GroupCreateModal extends ImmutablePureComponent {
|
||||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width='440'
|
||||
width={440}
|
||||
onClose={onClose}
|
||||
>
|
||||
<GroupCreate onCloseModal={onClose} />
|
||||
|
||||
@@ -54,7 +54,7 @@ class HashtagTimelineSettingsModal extends ImmutablePureComponent {
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
width='320'
|
||||
width={320}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
onClose={onClose}
|
||||
>
|
||||
|
||||
@@ -55,7 +55,7 @@ class HomeTimelineSettingsModal extends ImmutablePureComponent {
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
width='320'
|
||||
width={320}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
onClose={onClose}
|
||||
>
|
||||
|
||||
@@ -22,10 +22,10 @@ class ListCreateModal extends ImmutablePureComponent {
|
||||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width='500'
|
||||
width={500}
|
||||
onClose={onClose}
|
||||
>
|
||||
<ListCreate />
|
||||
<ListCreate isModal />
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { makeGetAccount } from '../../selectors'
|
||||
import { blockAccount } from '../../actions/accounts'
|
||||
import { deleteList } from '../../actions/lists'
|
||||
import ConfirmationModal from './confirmation_modal'
|
||||
|
||||
const messages = defineMessages({
|
||||
@@ -10,14 +9,14 @@ const messages = defineMessages({
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onConfirm(account) {
|
||||
// dispatch(blockAccount(account.get('id')))
|
||||
onConfirm(listId) {
|
||||
dispatch(deleteList(listId))
|
||||
},
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(null, mapDispatchToProps)
|
||||
@injectIntl
|
||||
@connect(null, mapDispatchToProps)
|
||||
class ListDeleteModal extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
@@ -27,17 +26,17 @@ class ListDeleteModal extends PureComponent {
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onConfirm(this.props.account)
|
||||
this.props.onConfirm(this.props.list.get('id'))
|
||||
}
|
||||
|
||||
render() {
|
||||
const { list, intl, onClose } = this.props
|
||||
|
||||
const title = intl.formatMessage(messages.title, {
|
||||
list: !!list ? account.get('title') : '',
|
||||
list: !!list ? list.get('title') : '',
|
||||
})
|
||||
const message = intl.formatMessage(messages.listMessage, {
|
||||
list: !!list ? account.get('title') : '',
|
||||
list: !!list ? list.get('title') : '',
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,68 +1,33 @@
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { muteAccount } from '../../actions/accounts'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ModalLayout from './modal_layout'
|
||||
import ListEdit from '../../features/list_edit'
|
||||
|
||||
const messages = defineMessages({
|
||||
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
||||
confirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
|
||||
account: state.getIn(['mutes', 'new', 'account']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onConfirm(account, notifications) {
|
||||
dispatch(muteAccount(account.get('id'), notifications))
|
||||
},
|
||||
title: { id: 'lists.edit', defaultMessage: 'Edit list' },
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class UnfollowModal extends PureComponent {
|
||||
class ListEditorModal extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
isSubmitting: PropTypes.bool.isRequired,
|
||||
account: PropTypes.object.isRequired,
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.button.focus()
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onClose()
|
||||
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||
}
|
||||
|
||||
handleCancel = () => {
|
||||
this.props.onClose()
|
||||
onClose: PropTypes.func.isRequired,
|
||||
listId: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account, intl } = this.props
|
||||
|
||||
// , {
|
||||
// message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
||||
// confirm: intl.formatMessage(messages.unfollowConfirm),
|
||||
// onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
||||
// }));
|
||||
const { intl, onClose, listId } = this.props
|
||||
|
||||
return (
|
||||
<ConfirmationModal
|
||||
title={`Mute @${account.get('acct')}`}
|
||||
message={<FormattedMessage id='confirmations.mute.message' defaultMessage='Are you sure you want to mute @{name}?' values={{ name: account.get('acct') }} />}
|
||||
confirm={<FormattedMessage id='mute' defaultMessage='Mute' />}
|
||||
onConfirm={() => {
|
||||
// dispatch(blockDomain(domain))
|
||||
// dispatch(blockDomain(domain))
|
||||
}}
|
||||
/>
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width={500}
|
||||
onClose={onClose}
|
||||
>
|
||||
<ListEdit listId={listId} />
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ class ListTimelineSettingsModal extends ImmutablePureComponent {
|
||||
|
||||
return (
|
||||
<ModalLayout
|
||||
width='320'
|
||||
width={320}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
onClose={onClose}
|
||||
>
|
||||
|
||||
@@ -17,7 +17,6 @@ class ModalLayout extends PureComponent {
|
||||
title: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
handleCloseModal: PropTypes.func.isRequired,
|
||||
width: PropTypes.number,
|
||||
hideClose: PropTypes.bool,
|
||||
noPadding: PropTypes.bool,
|
||||
|
||||
@@ -2,73 +2,101 @@ import { closeModal } from '../../actions/modal'
|
||||
import { cancelReplyCompose } from '../../actions/compose'
|
||||
import Bundle from '../../features/ui/util/bundle'
|
||||
import {
|
||||
MuteModal,
|
||||
ReportModal,
|
||||
MODAL_ACTIONS,
|
||||
MODAL_BLOCK_ACCOUNT,
|
||||
MODAL_BLOCK_DOMAIN,
|
||||
MODAL_BOOST,
|
||||
MODAL_COMMUNITY_TIMELINE_SETTINGS,
|
||||
MODAL_COMPOSE,
|
||||
MODAL_CONFIRM,
|
||||
MODAL_DISPLAY_OPTIONS,
|
||||
MODAL_EDIT_PROFILE,
|
||||
MODAL_EMBED,
|
||||
MODAL_GIF_PICKER,
|
||||
MODAL_GROUP_CREATE,
|
||||
MODAL_GROUP_DELETE,
|
||||
MODAL_GROUP_EDITOR,
|
||||
MODAL_HASHTAG_TIMELINE_SETTINGS,
|
||||
MODAL_HOME_TIMELINE_SETTINGS,
|
||||
MODAL_HOTKEYS,
|
||||
MODAL_LIST_CREATE,
|
||||
MODAL_LIST_DELETE,
|
||||
MODAL_LIST_EDITOR,
|
||||
MODAL_LIST_TIMELINE_SETTINGS,
|
||||
MODAL_MEDIA,
|
||||
MODAL_MUTE,
|
||||
MODAL_PRO_UPGRADE,
|
||||
MODAL_REPORT,
|
||||
MODAL_STATUS_REVISIONS,
|
||||
MODAL_UNAUTHORIZED,
|
||||
MODAL_UNFOLLOW,
|
||||
MODAL_VIDEO,
|
||||
} from '../../constants'
|
||||
import {
|
||||
ActionsModal,
|
||||
BlockAccountModal,
|
||||
BlockDomainModal,
|
||||
BoostModal,
|
||||
CommunityTimelineSettingsModal,
|
||||
ComposeModal,
|
||||
ConfirmationModal,
|
||||
DisplayOptionsModal,
|
||||
EditProfileModal,
|
||||
EmbedModal,
|
||||
// ListEditor,
|
||||
// ListAdder,
|
||||
GifPickerModal,
|
||||
GroupCreateModal,
|
||||
GroupDeleteModal,
|
||||
GroupEditorModal,
|
||||
HashtagTimelineSettingsModal,
|
||||
HomeTimelineSettingsModal,
|
||||
HotkeysModal,
|
||||
ListCreateModal,
|
||||
ListDeleteModal,
|
||||
ListEditorModal,
|
||||
ListTimelineSettingsModal,
|
||||
MediaModal,
|
||||
MuteModal,
|
||||
ProUpgradeModal,
|
||||
ReportModal,
|
||||
StatusRevisionsModal,
|
||||
UnauthorizedModal,
|
||||
UnfollowModal,
|
||||
VideoModal,
|
||||
} from '../../features/ui/util/async_components'
|
||||
|
||||
import ModalBase from './modal_base'
|
||||
import BundleModalError from '../bundle_modal_error'
|
||||
|
||||
import ActionsModal from './actions_modal'
|
||||
import BlockAccountModal from './block_account_modal'
|
||||
import BlockDomainModal from './block_domain_modal'
|
||||
import BoostModal from './boost_modal'
|
||||
import CommunityTimelineSettingsModal from './community_timeline_settings_modal'
|
||||
import ComposeModal from './compose_modal'
|
||||
import ConfirmationModal from './confirmation_modal'
|
||||
import EditProfileModal from './edit_profile_modal'
|
||||
import GifPickerModal from './gif_picker_modal'
|
||||
import GroupCreateModal from './group_create_modal'
|
||||
import GroupDeleteModal from './group_delete_modal'
|
||||
import GroupEditorModal from './group_editor_modal'
|
||||
import HashtagTimelineSettingsModal from './hashtag_timeline_settings_modal'
|
||||
import HomeTimelineSettingsModal from './home_timeline_settings_modal'
|
||||
import HotkeysModal from './hotkeys_modal'
|
||||
import ListCreateModal from './list_create_modal'
|
||||
import ListDeleteModal from './list_delete_modal'
|
||||
import ListEditorModal from './list_editor_modal'
|
||||
import ListTimelineSettingsModal from './list_timeline_settings_modal'
|
||||
import MediaModal from './media_modal'
|
||||
import ModalLoading from './modal_loading'
|
||||
import ProUpgradeModal from './pro_upgrade_modal'
|
||||
import VideoModal from './video_modal'
|
||||
import UnauthorizedModal from './unauthorized_modal'
|
||||
import UnfollowModal from './unfollow_modal'
|
||||
|
||||
const MODAL_COMPONENTS = {
|
||||
ACTIONS: () => Promise.resolve({ default: ActionsModal }),
|
||||
BLOCK_ACCOUNT: () => Promise.resolve({ default: BlockAccountModal }),
|
||||
BLOCK_DOMAIN: () => Promise.resolve({ default: BlockDomainModal }),
|
||||
BOOST: () => Promise.resolve({ default: BoostModal }),
|
||||
COMMUNITY_TIMELINE_SETTINGS: () => Promise.resolve({ default: CommunityTimelineSettingsModal }),
|
||||
COMPOSE: () => Promise.resolve({ default: ComposeModal }),
|
||||
CONFIRM: () => Promise.resolve({ default: ConfirmationModal }),
|
||||
EDIT_PROFILE: () => Promise.resolve({ default: EditProfileModal }),
|
||||
EMBED: () => Promise.resolve({ default: EmbedModal }),
|
||||
GIF_PICKER: () => Promise.resolve({ default: GifPickerModal }),
|
||||
GROUP_CREATE: () => Promise.resolve({ default: GroupCreateModal }),
|
||||
GROUP_DELETE: () => Promise.resolve({ default: GroupDeleteModal }),
|
||||
GROUP_EDITOR: () => Promise.resolve({ default: GroupEditorModal }),
|
||||
HASHTAG_TIMELINE_SETTINGS: () => Promise.resolve({ default: HashtagTimelineSettingsModal }),
|
||||
HOME_TIMELINE_SETTINGS: () => Promise.resolve({ default: HomeTimelineSettingsModal }),
|
||||
HOTKEYS: () => Promise.resolve({ default: HotkeysModal }),
|
||||
LIST_CREATE: () => Promise.resolve({ default: ListCreateModal }),
|
||||
LIST_DELETE: () => Promise.resolve({ default: ListDeleteModal }),
|
||||
LIST_EDITOR: () => Promise.resolve({ default: ListEditorModal }),
|
||||
LIST_TIMELINE_SETTINGS: () => Promise.resolve({ default: ListTimelineSettingsModal }),
|
||||
MEDIA: () => Promise.resolve({ default: MediaModal }),
|
||||
MUTE: MuteModal,
|
||||
PRO_UPGRADE: () => Promise.resolve({ default: ProUpgradeModal }),
|
||||
REPORT: ReportModal,
|
||||
STATUS_REVISIONS: StatusRevisionsModal,
|
||||
UNAUTHORIZED: () => Promise.resolve({ default: UnauthorizedModal }),
|
||||
UNFOLLOW: () => Promise.resolve({ default: UnfollowModal }),
|
||||
VIDEO: () => Promise.resolve({ default: VideoModal }),
|
||||
}
|
||||
const MODAL_COMPONENTS = {}
|
||||
MODAL_COMPONENTS[MODAL_ACTIONS] = ActionsModal
|
||||
MODAL_COMPONENTS[MODAL_BLOCK_ACCOUNT] = BlockAccountModal
|
||||
MODAL_COMPONENTS[MODAL_BLOCK_DOMAIN] = BlockDomainModal
|
||||
MODAL_COMPONENTS[MODAL_BOOST] = BoostModal
|
||||
MODAL_COMPONENTS[MODAL_COMMUNITY_TIMELINE_SETTINGS] = CommunityTimelineSettingsModal
|
||||
MODAL_COMPONENTS[MODAL_COMPOSE] = ComposeModal
|
||||
MODAL_COMPONENTS[MODAL_CONFIRM] = ConfirmationModal
|
||||
MODAL_COMPONENTS[MODAL_DISPLAY_OPTIONS] = DisplayOptionsModal
|
||||
MODAL_COMPONENTS[MODAL_EDIT_PROFILE] = EditProfileModal
|
||||
MODAL_COMPONENTS[MODAL_EMBED] = EmbedModal
|
||||
MODAL_COMPONENTS[MODAL_GIF_PICKER] = GifPickerModal
|
||||
MODAL_COMPONENTS[MODAL_GROUP_CREATE] = GroupCreateModal
|
||||
MODAL_COMPONENTS[MODAL_GROUP_DELETE] = GroupDeleteModal
|
||||
MODAL_COMPONENTS[MODAL_GROUP_EDITOR] = GroupEditorModal
|
||||
MODAL_COMPONENTS[MODAL_HASHTAG_TIMELINE_SETTINGS] = HashtagTimelineSettingsModal
|
||||
MODAL_COMPONENTS[MODAL_HOME_TIMELINE_SETTINGS] = HomeTimelineSettingsModal
|
||||
MODAL_COMPONENTS[MODAL_HOTKEYS] = HotkeysModal
|
||||
MODAL_COMPONENTS[MODAL_LIST_CREATE] = ListCreateModal
|
||||
MODAL_COMPONENTS[MODAL_LIST_DELETE] = ListDeleteModal
|
||||
MODAL_COMPONENTS[MODAL_LIST_EDITOR] = ListEditorModal
|
||||
MODAL_COMPONENTS[MODAL_LIST_TIMELINE_SETTINGS] = ListTimelineSettingsModal
|
||||
MODAL_COMPONENTS[MODAL_MEDIA] = MediaModal
|
||||
MODAL_COMPONENTS[MODAL_MUTE] = MuteModal
|
||||
MODAL_COMPONENTS[MODAL_PRO_UPGRADE] = ProUpgradeModal
|
||||
MODAL_COMPONENTS[MODAL_REPORT] = ReportModal
|
||||
MODAL_COMPONENTS[MODAL_STATUS_REVISIONS] = StatusRevisionsModal
|
||||
MODAL_COMPONENTS[MODAL_UNAUTHORIZED] = UnauthorizedModal
|
||||
MODAL_COMPONENTS[MODAL_UNFOLLOW] = UnfollowModal
|
||||
MODAL_COMPONENTS[MODAL_VIDEO] = VideoModal
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
type: state.getIn(['modal', 'modalType']),
|
||||
|
||||
@@ -25,7 +25,7 @@ class ProUpgradeModal extends ImmutablePureComponent {
|
||||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width='460'
|
||||
width={460}
|
||||
onClose={onClose}
|
||||
>
|
||||
<Text>
|
||||
|
||||
@@ -5,7 +5,6 @@ import classNames from 'classnames/bind'
|
||||
import { loadStatusRevisions } from '../../actions/status_revisions'
|
||||
import ModalLayout from './modal_layout'
|
||||
import RelativeTimestamp from '../relative_timestamp'
|
||||
import ScrollableList from '../scrollable_list'
|
||||
import Text from '../text'
|
||||
|
||||
const cx = classNames.bind(_s)
|
||||
@@ -56,42 +55,40 @@ class StatusRevisionsModal extends ImmutablePureComponent {
|
||||
return (
|
||||
<ModalLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
width='480'
|
||||
width={480}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className={[_s.default]}>
|
||||
<ScrollableList>
|
||||
{
|
||||
revisions.map((revision, i) => {
|
||||
const isFirst = i === 0
|
||||
const isLast = i === revisions.size - 1
|
||||
{
|
||||
revisions.map((revision, i) => {
|
||||
const isFirst = i === 0
|
||||
const isLast = i === revisions.size - 1
|
||||
|
||||
const containerClasses = cx({
|
||||
default: 1,
|
||||
pt5: 1,
|
||||
pb10: 1,
|
||||
mt5: !isFirst,
|
||||
borderColorSecondary: !isLast,
|
||||
borderBottom1PX: !isLast,
|
||||
})
|
||||
|
||||
return (
|
||||
<div key={`status-revision-${i}`} className={containerClasses}>
|
||||
<div className={[_s.default, _s.pb5].join(' ')}>
|
||||
<Text size='medium'>
|
||||
{revision.get('text')}
|
||||
</Text>
|
||||
</div>
|
||||
<div className={[_s.default]}>
|
||||
<Text size='small' color='secondary'>
|
||||
Edited on <RelativeTimestamp timestamp={revision.get('created_at')} />
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
const containerClasses = cx({
|
||||
default: 1,
|
||||
pt5: 1,
|
||||
pb10: 1,
|
||||
mt5: !isFirst,
|
||||
borderColorSecondary: !isLast,
|
||||
borderBottom1PX: !isLast,
|
||||
})
|
||||
}
|
||||
</ScrollableList>
|
||||
|
||||
return (
|
||||
<div key={`status-revision-${i}`} className={containerClasses}>
|
||||
<div className={[_s.default, _s.pb5].join(' ')}>
|
||||
<Text size='medium'>
|
||||
{revision.get('text')}
|
||||
</Text>
|
||||
</div>
|
||||
<div className={[_s.default]}>
|
||||
<Text size='small' color='secondary'>
|
||||
Edited on <RelativeTimestamp timestamp={revision.get('created_at')} />
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</ModalLayout>
|
||||
)
|
||||
|
||||
@@ -43,10 +43,18 @@ class Notification extends ImmutablePureComponent {
|
||||
createdAt: PropTypes.string,
|
||||
statusId: PropTypes.string,
|
||||
type: PropTypes.string.isRequired,
|
||||
isHidden: PropTypes.bool,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, accounts, createdAt, type, statusId } = this.props
|
||||
const {
|
||||
intl,
|
||||
accounts,
|
||||
createdAt,
|
||||
type,
|
||||
statusId,
|
||||
isHidden,
|
||||
} = this.props
|
||||
|
||||
const count = !!accounts ? accounts.size : 0
|
||||
|
||||
@@ -83,6 +91,10 @@ class Notification extends ImmutablePureComponent {
|
||||
return null
|
||||
}
|
||||
|
||||
if (isHidden) {
|
||||
// : todo :
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.px10, _s.cursorPointer, _s.backgroundColorSubtle_onHover].join(' ')}>
|
||||
<div className={[_s.default, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Fragment } from 'react'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { shortNumberFormat } from '../../utils/numbers'
|
||||
@@ -9,6 +9,7 @@ import Divider from '../divider'
|
||||
import Heading from '../heading'
|
||||
import Icon from '../icon'
|
||||
import Text from '../text'
|
||||
import RelativeTimestamp from '../relative_timestamp'
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'about', defaultMessage: 'About' },
|
||||
@@ -27,15 +28,19 @@ class GroupInfoPanel extends ImmutablePureComponent {
|
||||
render() {
|
||||
const { intl, group } = this.props
|
||||
|
||||
console.log("group:", group)
|
||||
|
||||
return (
|
||||
<PanelLayout title={intl.formatMessage(messages.title)}>
|
||||
{
|
||||
!!group &&
|
||||
<Fragment>
|
||||
|
||||
<Heading size='h2'>
|
||||
{group.get('title')}
|
||||
</Heading>
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||
<Text weight='medium'>
|
||||
{group.get('title')}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Divider isSmall />
|
||||
|
||||
@@ -63,6 +68,23 @@ class GroupInfoPanel extends ImmutablePureComponent {
|
||||
|
||||
<Divider isSmall />
|
||||
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||
<Icon id='calendar' size='12px' className={_s.fillColorSecondary} />
|
||||
<Text
|
||||
size='small'
|
||||
color='secondary'
|
||||
className={_s.ml5}
|
||||
>
|
||||
{
|
||||
<FormattedMessage id='lists.panel_created' defaultMessage='Created: {date}' values={{
|
||||
date: <RelativeTimestamp timestamp={group.get('created_at')} />,
|
||||
}} />
|
||||
}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Divider isSmall />
|
||||
|
||||
<Text>
|
||||
{group.get('description')}
|
||||
</Text>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { fetchGroups } from '../../actions/groups'
|
||||
import PanelLayout from './panel_layout'
|
||||
import GroupListItem from '../group_list_item'
|
||||
import Button from '../button'
|
||||
import ScrollableList from '../scrollable_list'
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'groups.sidebar-panel.title', defaultMessage: 'Groups you\'re in' },
|
||||
@@ -15,13 +16,41 @@ const mapStateToProps = (state) => ({
|
||||
groupIds: state.getIn(['group_lists', 'member']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onFetchGroups: (type) => {
|
||||
dispatch(fetchGroups(type))
|
||||
}
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class GroupSidebarPanel extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
groupIds: ImmutablePropTypes.list,
|
||||
slim: PropTypes.bool,
|
||||
isLazy: PropTypes.bool,
|
||||
isSlim: PropTypes.bool,
|
||||
onFetchGroups: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
state = {
|
||||
fetched: false,
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
if (!nextProps.isHidden && nextProps.isIntersecting && !prevState.fetched) {
|
||||
return {
|
||||
fetched: true
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (!prevState.fetched && this.state.fetched && this.props.isLazy) {
|
||||
this.props.onFetchGroups('member')
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -42,16 +71,20 @@ class GroupSidebarPanel extends ImmutablePureComponent {
|
||||
noPadding={slim}
|
||||
>
|
||||
<div className={_s.default}>
|
||||
{
|
||||
groupIds.slice(0, maxCount).map((groupId, i) => (
|
||||
<GroupListItem
|
||||
key={`group-panel-item-${groupId}`}
|
||||
id={groupId}
|
||||
slim={slim}
|
||||
isLast={groupIds.length - 1 === i}
|
||||
/>
|
||||
))
|
||||
}
|
||||
<ScrollableList
|
||||
scrollKey='groups-panel'
|
||||
>
|
||||
{
|
||||
groupIds.slice(0, maxCount).map((groupId, i) => (
|
||||
<GroupListItem
|
||||
key={`group-panel-item-${groupId}`}
|
||||
id={groupId}
|
||||
slim={slim}
|
||||
isLast={groupIds.length - 1 === i}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
</PanelLayout>
|
||||
)
|
||||
|
||||
@@ -1,57 +1,48 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { fetchSuggestions, dismissSuggestion } from '../../actions/suggestions'
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import PanelLayout from './panel_layout'
|
||||
import Avatar from '../avatar'
|
||||
import Divider from '../divider'
|
||||
import Icon from '../icon'
|
||||
import Heading from '../heading'
|
||||
import RelativeTimestamp from '../relative_timestamp'
|
||||
import Text from '../text'
|
||||
|
||||
const messages = defineMessages({
|
||||
dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
|
||||
memberCount: { id: 'lists.panel_members', defaultMessage: 'Members: {count}' },
|
||||
createdAt: { id: 'lists.panel_created', defaultMessage: 'Created: {date}' },
|
||||
title: { id: 'lists_information', defaultMessage: 'List Information' },
|
||||
edit: { id: 'edit', defaultMessage: 'Edit' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
// accountIds: state.getIn(['listEditor', 'accounts', 'items']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class ListDetailsPanel extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onEdit: PropTypes.func.isRequired,
|
||||
list: ImmutablePropTypes.map,
|
||||
}
|
||||
|
||||
handleShowAllLists() {
|
||||
|
||||
handleOnEdit = () => {
|
||||
this.props.onEdit()
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props
|
||||
const { intl, list } = this.props
|
||||
|
||||
const title = !!list ? list.get('title') : ''
|
||||
const createdAt = !!list ? list.get('created_at') : ''
|
||||
|
||||
return (
|
||||
<PanelLayout
|
||||
title={intl.formatMessage(messages.title)}
|
||||
headerButtonTitle={intl.formatMessage(messages.edit)}
|
||||
headerButtonAction={this.handleShowAllLists}
|
||||
headerButtonAction={this.handleOnEdit}
|
||||
>
|
||||
<div className={_s.default}>
|
||||
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter,].join(' ')}>
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||
<Text weight='medium'>
|
||||
Some List Title
|
||||
{title}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
@@ -65,42 +56,13 @@ class ListDetailsPanel extends ImmutablePureComponent {
|
||||
className={_s.ml5}
|
||||
>
|
||||
{
|
||||
intl.formatMessage(messages.createdAt, {
|
||||
date: '12-25-2019'
|
||||
})
|
||||
<FormattedMessage id='lists.panel_created' defaultMessage='Created: {date}' values={{
|
||||
date: <RelativeTimestamp timestamp={createdAt} />,
|
||||
}} />
|
||||
}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Divider isSmall />
|
||||
|
||||
<div className={[_s.default].join(' ')}>
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
|
||||
<Icon id='group' size='12px' className={_s.fillColorSecondary} />
|
||||
<Text
|
||||
size='small'
|
||||
color='secondary'
|
||||
className={_s.ml5}
|
||||
>
|
||||
{
|
||||
intl.formatMessage(messages.memberCount, {
|
||||
count: 10
|
||||
})
|
||||
}
|
||||
</Text>
|
||||
</div>
|
||||
<div className={[_s.default, _s.flexRow, _s.flexWrap, _s.pt10].join(' ')}>
|
||||
|
||||
{
|
||||
[1, 2, 3, 4, 5, 6, 7, 8, 9].map(item => (
|
||||
<div className={[_s.default, _s.mr5].join(' ')}>
|
||||
<Avatar size={26} />
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</PanelLayout>
|
||||
)
|
||||
|
||||
@@ -32,8 +32,28 @@ class ListsPanel extends ImmutablePureComponent {
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.props.onFetchLists()
|
||||
state = {
|
||||
fetched: false,
|
||||
}
|
||||
|
||||
updateOnProps = [
|
||||
'lists',
|
||||
]
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
if (!nextProps.isHidden && nextProps.isIntersecting && !prevState.fetched) {
|
||||
return {
|
||||
fetched: true,
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (!prevState.fetched && this.state.fetched) {
|
||||
this.props.onFetchLists()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -66,11 +66,12 @@ class MediaGalleryPanel extends ImmutablePureComponent {
|
||||
>
|
||||
<div className={[_s.default, _s.flexRow, _s.flexWrap, _s.px10, _s.py10].join(' ')}>
|
||||
{
|
||||
attachments.slice(0, 16).map((attachment) => (
|
||||
attachments.slice(0, 16).map((attachment, i) => (
|
||||
<MediaItem
|
||||
small
|
||||
isSmall
|
||||
key={attachment.get('id')}
|
||||
attachment={attachment}
|
||||
account={account}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import SettingSwitch from '../setting_switch'
|
||||
const messages = defineMessages({
|
||||
title: { id: 'notification_filters', defaultMessage: 'Notification Filters' },
|
||||
onlyVerified: { id: 'notification_only_verified', defaultMessage: 'Only Verified Users' },
|
||||
onlyFollowing: { id: 'notification_only_following', defaultMessage: 'Only People I Follow' },
|
||||
// onlyFollowing: { id: 'notification_only_following', defaultMessage: 'Only People I Follow' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
@@ -55,13 +55,14 @@ class NotificationFilterPanel extends ImmutablePureComponent {
|
||||
label={intl.formatMessage(messages.onlyVerified)}
|
||||
/>
|
||||
|
||||
<SettingSwitch
|
||||
{ /* : todo :
|
||||
<SettingSwitch
|
||||
prefix='notification'
|
||||
settings={settings}
|
||||
settingPath={'onlyFollowing'}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(messages.onlyFollowing)}
|
||||
/>
|
||||
/> */ }
|
||||
</PanelLayout>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { fetchGabTrends } from '../../actions/gab_trends'
|
||||
import PanelLayout from './panel_layout'
|
||||
import ColumnIndicator from '../column_indicator'
|
||||
import ScrollableList from '../scrollable_list'
|
||||
import TrendingItem from '../trends_item'
|
||||
|
||||
const messages = defineMessages({
|
||||
@@ -29,7 +30,7 @@ class TrendsPanel extends ImmutablePureComponent {
|
||||
onFetchGabTrends: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
this.props.onFetchGabTrends()
|
||||
}
|
||||
|
||||
@@ -47,19 +48,26 @@ class TrendsPanel extends ImmutablePureComponent {
|
||||
<ColumnIndicator type='loading' />
|
||||
}
|
||||
{
|
||||
gabtrends && gabtrends.slice(0, 8).map((trend, i) => (
|
||||
<TrendingItem
|
||||
key={`gab-trend-${i}`}
|
||||
index={i + 1}
|
||||
isLast={i === 7}
|
||||
url={trend.get('url')}
|
||||
title={trend.get('title')}
|
||||
description={trend.get('description')}
|
||||
imageUrl={trend.get('image')}
|
||||
publishDate={trend.get('date_published')}
|
||||
author={trend.getIn(['author', 'name'], '')}
|
||||
/>
|
||||
))
|
||||
!gabtrends.isEmpty() &&
|
||||
<ScrollableList
|
||||
scrollKey='trending-items'
|
||||
>
|
||||
{
|
||||
gabtrends.slice(0, 8).map((trend, i) => (
|
||||
<TrendingItem
|
||||
key={`gab-trend-${i}`}
|
||||
index={i + 1}
|
||||
isLast={i === 7}
|
||||
url={trend.get('url')}
|
||||
title={trend.get('title')}
|
||||
description={trend.get('description')}
|
||||
imageUrl={trend.get('image')}
|
||||
publishDate={trend.get('date_published')}
|
||||
author={trend.getIn(['author', 'name'], '')}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</ScrollableList>
|
||||
}
|
||||
</div>
|
||||
</PanelLayout>
|
||||
|
||||
@@ -36,19 +36,34 @@ class WhoToFollowPanel extends ImmutablePureComponent {
|
||||
'suggestions',
|
||||
]
|
||||
|
||||
componentDidMount () {
|
||||
this.props.fetchSuggestions()
|
||||
state = {
|
||||
fetched: false,
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
if (!nextProps.isHidden && nextProps.isIntersecting && !prevState.fetched) {
|
||||
return {
|
||||
fetched: true
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
if (!prevState.fetched && this.state.fetched) {
|
||||
this.props.fetchSuggestions()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, suggestions, dismissSuggestion } = this.props
|
||||
|
||||
if (suggestions.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
if (suggestions.isEmpty()) return null
|
||||
|
||||
return (
|
||||
<PanelLayout
|
||||
noPadding
|
||||
title={intl.formatMessage(messages.title)}
|
||||
footerButtonTitle={intl.formatMessage(messages.show_more)}
|
||||
footerButtonTo='/explore'
|
||||
@@ -57,6 +72,7 @@ class WhoToFollowPanel extends ImmutablePureComponent {
|
||||
{
|
||||
suggestions.map(accountId => (
|
||||
<Account
|
||||
compact
|
||||
showDismiss
|
||||
key={accountId}
|
||||
id={accountId}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import PopoverLayout from './popover_layout'
|
||||
import Text from '../text'
|
||||
|
||||
export default class UserInfoPopover extends PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<PopoverLayout>
|
||||
<Text>testing</Text>
|
||||
</PopoverLayout>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { Manager, Reference, Popper } from 'react-popper'
|
||||
import classnames from 'classnames/bind'
|
||||
import spring from 'react-motion/lib/spring'
|
||||
import Motion from '../../features/ui/util/optional_motion'
|
||||
import { openPopover, closePopover } from '../../actions/popover'
|
||||
import { openModal, closeModal } from '../../actions/modal'
|
||||
import { isUserTouching } from '../../utils/is_mobile'
|
||||
@@ -117,7 +115,6 @@ class PopoverBase extends ImmutablePureComponent {
|
||||
targetRef,
|
||||
innerRef,
|
||||
} = this.props
|
||||
const open = this.state.id === openPopoverType
|
||||
|
||||
const containerClasses = cx({
|
||||
default: 1,
|
||||
@@ -125,8 +122,6 @@ class PopoverBase extends ImmutablePureComponent {
|
||||
displayNone: !visible,
|
||||
})
|
||||
|
||||
console.log('targetRef:', targetRef)
|
||||
|
||||
return (
|
||||
<Manager>
|
||||
<Popper
|
||||
|
||||
@@ -1,37 +1,51 @@
|
||||
import detectPassiveEvents from 'detect-passive-events'
|
||||
import { closePopover } from '../../actions/popover'
|
||||
import {
|
||||
POPOVER_CONTENT_WARNING,
|
||||
POPOVER_DATE_PICKER,
|
||||
POPOVER_EMOJI_PICKER,
|
||||
POPOVER_GROUP_INFO,
|
||||
POPOVER_PROFILE_OPTIONS,
|
||||
POPOVER_REPOST_OPTIONS,
|
||||
POPOVER_SEARCH,
|
||||
POPOVER_SIDEBAR_MORE,
|
||||
POPOVER_STATUS_OPTIONS,
|
||||
POPOVER_STATUS_SHARE,
|
||||
POPOVER_STATUS_VISIBILITY,
|
||||
POPOVER_USER_INFO,
|
||||
} from '../../constants'
|
||||
import {
|
||||
ContentWarningPopover,
|
||||
DatePickerPopover,
|
||||
EmojiPickerPopover,
|
||||
GroupInfoPopover,
|
||||
ProfileOptionsPopover,
|
||||
RepostOptionsPopover,
|
||||
SearchPopover,
|
||||
SidebarMorePopover,
|
||||
StatusOptionsPopover,
|
||||
StatusSharePopover,
|
||||
StatusVisibilityPopover,
|
||||
UserInfoPopover,
|
||||
} from '../../features/ui/util/async_components'
|
||||
import Bundle from '../../features/ui/util/bundle'
|
||||
import BundleModalError from '../bundle_modal_error'
|
||||
import PopoverBase from './popover_base'
|
||||
import ContentWarningPopover from './content_warning_popover'
|
||||
import DatePickerPopover from './date_picker_popover'
|
||||
import EmojiPickerPopover from './emoji_picker_popover'
|
||||
import GroupInfoPopover from './group_info_popover'
|
||||
import ProfileOptionsPopover from './profile_options_popover'
|
||||
import RepostOptionsPopover from './repost_options_popover'
|
||||
import SearchPopover from './search_popover'
|
||||
import SidebarMorePopover from './sidebar_more_popover'
|
||||
import StatusOptionsPopover from './status_options_popover'
|
||||
import StatusSharePopover from './status_share_popover'
|
||||
import StatusVisibilityPopover from './status_visibility_popover'
|
||||
import UserInfoPopover from './user_info_popover'
|
||||
|
||||
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false
|
||||
|
||||
const POPOVER_COMPONENTS = {
|
||||
CONTENT_WARNING: () => Promise.resolve({ default: ContentWarningPopover }),
|
||||
DATE_PICKER: () => Promise.resolve({ default: DatePickerPopover }),
|
||||
EMOJI_PICKER: () => Promise.resolve({ default: EmojiPickerPopover }),
|
||||
GROUP_INFO: () => GroupInfoPopover,
|
||||
PROFILE_OPTIONS: () => Promise.resolve({ default: ProfileOptionsPopover }),
|
||||
REPOST_OPTIONS: () => Promise.resolve({ default: RepostOptionsPopover }),
|
||||
SEARCH: () => Promise.resolve({ default: SearchPopover }),
|
||||
SIDEBAR_MORE: () => Promise.resolve({ default: SidebarMorePopover }),
|
||||
STATUS_OPTIONS: () => Promise.resolve({ default: StatusOptionsPopover }),
|
||||
STATUS_SHARE: () => Promise.resolve({ default: StatusSharePopover }),
|
||||
STATUS_VISIBILITY: () => Promise.resolve({ default: StatusVisibilityPopover }),
|
||||
USER_INFO: () => Promise.resolve({ default: UserInfoPopover }),
|
||||
}
|
||||
const POPOVER_COMPONENTS = {}
|
||||
POPOVER_COMPONENTS[POPOVER_CONTENT_WARNING] = ContentWarningPopover
|
||||
POPOVER_COMPONENTS[POPOVER_DATE_PICKER] = DatePickerPopover
|
||||
POPOVER_COMPONENTS[POPOVER_EMOJI_PICKER] = EmojiPickerPopover
|
||||
POPOVER_COMPONENTS[POPOVER_GROUP_INFO] = GroupInfoPopover
|
||||
POPOVER_COMPONENTS[POPOVER_PROFILE_OPTIONS] = ProfileOptionsPopover
|
||||
POPOVER_COMPONENTS[POPOVER_REPOST_OPTIONS] = RepostOptionsPopover
|
||||
POPOVER_COMPONENTS[POPOVER_SEARCH] = SearchPopover
|
||||
POPOVER_COMPONENTS[POPOVER_SIDEBAR_MORE] = SidebarMorePopover
|
||||
POPOVER_COMPONENTS[POPOVER_STATUS_OPTIONS] = StatusOptionsPopover
|
||||
POPOVER_COMPONENTS[POPOVER_STATUS_SHARE] = StatusSharePopover
|
||||
POPOVER_COMPONENTS[POPOVER_STATUS_VISIBILITY] = StatusVisibilityPopover
|
||||
POPOVER_COMPONENTS[POPOVER_USER_INFO] = UserInfoPopover
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
type: state.getIn(['popover', 'popoverType']),
|
||||
@@ -84,14 +98,10 @@ class PopoverRoot extends PureComponent {
|
||||
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions)
|
||||
}
|
||||
|
||||
setRef = c => {
|
||||
setRef = (c) => {
|
||||
this.node = c
|
||||
}
|
||||
|
||||
setFocusRef = c => {
|
||||
this.focusedItem = c
|
||||
}
|
||||
|
||||
handleKeyDown = e => {
|
||||
const items = Array.from(this.node.getElementsByTagName('a'))
|
||||
const index = items.indexOf(document.activeElement)
|
||||
@@ -150,8 +160,6 @@ class PopoverRoot extends PureComponent {
|
||||
const { type, props } = this.props
|
||||
const visible = !!type
|
||||
|
||||
console.log("POPOVER_COMPONENTS[type]:", type, POPOVER_COMPONENTS[type]);
|
||||
|
||||
return (
|
||||
<PopoverBase
|
||||
visible={visible}
|
||||
@@ -162,12 +170,12 @@ class PopoverRoot extends PureComponent {
|
||||
visible &&
|
||||
<Bundle
|
||||
fetchComponent={POPOVER_COMPONENTS[type]}
|
||||
loading={this.renderLoading(type)}
|
||||
loading={this.renderLoading()}
|
||||
error={this.renderError}
|
||||
renderDelay={200}
|
||||
>
|
||||
{
|
||||
(SpecificComponent) => <SpecificComponent {...props} />
|
||||
(Component) => <Component {...props} />
|
||||
}
|
||||
</Bundle>
|
||||
}
|
||||
|
||||
@@ -1,8 +1,39 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { MODAL_DISPLAY_OPTIONS } from '../../constants'
|
||||
import { openModal } from '../../actions/modal'
|
||||
import PopoverLayout from './popover_layout'
|
||||
import List from '../list'
|
||||
|
||||
export default class SidebarMorePopover extends PureComponent {
|
||||
const messages = defineMessages({
|
||||
display: { id: 'display_options', defaultMessage: 'Display Options' },
|
||||
help: { id: 'getting_started.help', defaultMessage: 'Help' },
|
||||
settings: { id: 'settings', defaultMessage: 'Settings' },
|
||||
logout: { 'id': 'confirmations.logout.confirm', 'defaultMessage': 'Log out' },
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onOpenDisplayModal: () => {
|
||||
dispatch(openModal(MODAL_DISPLAY_OPTIONS))
|
||||
},
|
||||
})
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@connect(null, mapDispatchToProps)
|
||||
class SidebarMorePopover extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onOpenDisplayModal: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
handleOnOpenDisplayModal = () => {
|
||||
this.props.onOpenDisplayModal()
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props
|
||||
|
||||
return (
|
||||
<PopoverLayout className={_s.width240PX}>
|
||||
<List
|
||||
@@ -10,15 +41,19 @@ export default class SidebarMorePopover extends PureComponent {
|
||||
scrollKey='profile_options'
|
||||
items={[
|
||||
{
|
||||
title: 'Help',
|
||||
title: intl.formatMessage(messages.help),
|
||||
href: 'https://help.gab.com',
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
title: intl.formatMessage(messages.display),
|
||||
onClick: this.handleOnOpenDisplayModal,
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage(messages.settings),
|
||||
href: '/settings',
|
||||
},
|
||||
{
|
||||
title: 'Log Out',
|
||||
title: intl.formatMessage(messages.logout),
|
||||
href: '/auth/log_out',
|
||||
},
|
||||
]}
|
||||
|
||||
@@ -47,7 +47,7 @@ class StatusVisibilityDropdown extends PureComponent {
|
||||
this.props.onChange(value)
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
componentDidMount () {
|
||||
const { intl } = this.props
|
||||
|
||||
this.options = [
|
||||
|
||||
@@ -6,7 +6,9 @@ import {
|
||||
CX,
|
||||
POPOVER_PROFILE_OPTIONS,
|
||||
PLACEHOLDER_MISSING_HEADER_SRC,
|
||||
MODAL_EDIT_PROFILE,
|
||||
} from '../constants'
|
||||
import { openModal } from '../actions/modal'
|
||||
import { openPopover } from '../actions/popover'
|
||||
import { me } from '../initial_state'
|
||||
import AccountActionButton from './account_action_button'
|
||||
@@ -27,6 +29,7 @@ const messages = defineMessages({
|
||||
comments: { id: 'comments', defaultMessage: 'Comments' },
|
||||
media: { id: 'media', defaultMessage: 'Media' },
|
||||
accountFollowsYou: { id: 'account.follows_you', defaultMessage: 'Follows you' },
|
||||
editProfile: { id: "account.edit_profile", defaultMessage: "Edit profile" },
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
@@ -35,6 +38,10 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
dispatch(openPopover(POPOVER_PROFILE_OPTIONS, props))
|
||||
},
|
||||
|
||||
onEditProfile() {
|
||||
dispatch(openModal(MODAL_EDIT_PROFILE))
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default
|
||||
@@ -45,6 +52,7 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onEditProfile: PropTypes.func.isRequired,
|
||||
openProfileOptionsPopover: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
@@ -52,6 +60,10 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||
stickied: false,
|
||||
}
|
||||
|
||||
handleOnEditProfile = () => {
|
||||
this.props.onEditProfile()
|
||||
}
|
||||
|
||||
handleOpenMore = () => {
|
||||
const { openProfileOptionsPopover, account } = this.props
|
||||
|
||||
@@ -164,15 +176,10 @@ class ProfileHeader extends ImmutablePureComponent {
|
||||
backgroundColor='none'
|
||||
color='brand'
|
||||
className={[_s.justifyContentCenter, _s.alignItemsCenter].join(' ')}
|
||||
href=''
|
||||
onClick={this.handleOnEditProfile}
|
||||
>
|
||||
<Text
|
||||
color='inherit'
|
||||
weight='bold'
|
||||
size='medium'
|
||||
className={[_s.px15].join(' ')}
|
||||
>
|
||||
Edit Profile
|
||||
<Text color='inherit' weight='bold' size='medium' className={_s.px15}>
|
||||
{intl.formatMessage(messages.editProfile)}
|
||||
</Text>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -196,7 +196,7 @@ export default class ScrollableList extends PureComponent {
|
||||
return firstChild && firstChild.key;
|
||||
}
|
||||
|
||||
handleLoadMore = e => {
|
||||
handleLoadMore = (e) => {
|
||||
e.preventDefault();
|
||||
this.props.onLoadMore();
|
||||
}
|
||||
@@ -213,9 +213,7 @@ export default class ScrollableList extends PureComponent {
|
||||
} = this.props
|
||||
const childrenCount = React.Children.count(children);
|
||||
|
||||
const trackScroll = true; //placeholder
|
||||
|
||||
const loadMore = (hasMore && onLoadMore) ? <LoadMore visible={!isLoading} onClick={this.handleLoadMore} /> : null;
|
||||
const loadMore = (hasMore && onLoadMore) ? <LoadMore visible={!isLoading} onClick={this.handleLoadMore} /> : null
|
||||
|
||||
if (showLoading) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
@@ -232,7 +230,7 @@ export default class ScrollableList extends PureComponent {
|
||||
index={index}
|
||||
listLength={childrenCount}
|
||||
intersectionObserverWrapper={this.intersectionObserverWrapper}
|
||||
saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null}
|
||||
saveHeightKey={`${this.context.router.route.location.key}:${scrollKey}`}
|
||||
>
|
||||
{
|
||||
React.cloneElement(child, {
|
||||
|
||||
@@ -57,8 +57,8 @@ class Search extends PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
handleChange = (e) => {
|
||||
this.props.onChange(e.target.value)
|
||||
handleChange = (value) => {
|
||||
this.props.onChange(value)
|
||||
}
|
||||
|
||||
handleFocus = () => {
|
||||
|
||||
@@ -43,8 +43,13 @@ const mapStateToProps = (state, { timelineId }) => {
|
||||
const getStatusIds = makeGetStatusIds();
|
||||
const promotion = promotions.length > 0 && sample(promotions.filter(p => p.timeline_id === timelineId));
|
||||
|
||||
const statusIds = getStatusIds(state, {
|
||||
type: timelineId.substring(0,5) === 'group' ? 'group' : timelineId,
|
||||
id: timelineId
|
||||
})
|
||||
|
||||
return {
|
||||
statusIds: getStatusIds(state, { type: timelineId.substring(0,5) === 'group' ? 'group' : timelineId, id: timelineId }),
|
||||
statusIds,
|
||||
isLoading: state.getIn(['timelines', timelineId, 'isLoading'], true),
|
||||
isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false),
|
||||
hasMore: state.getIn(['timelines', timelineId, 'hasMore']),
|
||||
|
||||
@@ -28,7 +28,7 @@ export default class TabBar extends PureComponent {
|
||||
onClick={tab.onClick}
|
||||
icon={tab.icon}
|
||||
to={tab.to}
|
||||
active={tab.active}
|
||||
isActive={tab.active}
|
||||
isLarge={isLarge}
|
||||
/>
|
||||
))
|
||||
|
||||
@@ -13,22 +13,23 @@ export default class Textarea extends PureComponent {
|
||||
onKeyUp: PropTypes.func,
|
||||
onFocus: PropTypes.func,
|
||||
onBlur: PropTypes.func,
|
||||
onClear: PropTypes.func,
|
||||
title: PropTypes.string,
|
||||
}
|
||||
|
||||
handleOnChange = (e) => {
|
||||
this.props.onChange(e.target.value)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
placeholder,
|
||||
prependIcon,
|
||||
value,
|
||||
hasClear,
|
||||
onChange,
|
||||
onKeyUp,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onClear,
|
||||
title
|
||||
title,
|
||||
} = this.props
|
||||
|
||||
const inputClasses = cx({
|
||||
@@ -64,7 +65,7 @@ export default class Textarea extends PureComponent {
|
||||
type='text'
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onChange={this.handleOnChange}
|
||||
onKeyUp={onKeyUp}
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Fragment } from 'react'
|
||||
import classNames from 'classnames/bind'
|
||||
import { urlRegex } from '../features/compose/util/url_regex'
|
||||
import Button from './button'
|
||||
@@ -19,6 +20,7 @@ export default class TrendingItem extends PureComponent {
|
||||
author: PropTypes.string,
|
||||
publishDate: PropTypes.string,
|
||||
isLast: PropTypes.bool,
|
||||
isHidden: PropTypes.bool,
|
||||
wide: PropTypes.bool,
|
||||
}
|
||||
|
||||
@@ -51,9 +53,24 @@ export default class TrendingItem extends PureComponent {
|
||||
publishDate,
|
||||
isLast,
|
||||
wide,
|
||||
isHidden,
|
||||
} = this.props
|
||||
const { hovering } = this.state
|
||||
|
||||
const correctedAuthor = author.replace('www.', '')
|
||||
const correctedDescription = description.length >= 120 ? `${description.substring(0, 120).trim()}...` : description
|
||||
const descriptionHasLink = correctedDescription.match(urlRegex)
|
||||
|
||||
if (isHidden) {
|
||||
return (
|
||||
<Fragment>
|
||||
{title}
|
||||
{!descriptionHasLink && correctedDescription}
|
||||
{correctedAuthor}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
const containerClasses = cx({
|
||||
default: 1,
|
||||
noUnderline: 1,
|
||||
@@ -70,10 +87,6 @@ export default class TrendingItem extends PureComponent {
|
||||
underline: hovering,
|
||||
})
|
||||
|
||||
const correctedAuthor = author.replace('www.', '')
|
||||
const correctedDescription = description.length >= 120 ? `${description.substring(0, 120).trim()}...` : description
|
||||
const descriptionHasLink = correctedDescription.match(urlRegex)
|
||||
|
||||
const image = (
|
||||
<Image
|
||||
nullable
|
||||
|
||||
Reference in New Issue
Block a user