diff options
Diffstat (limited to 'app/javascript/themes/glitch/features/status/components')
3 files changed, 0 insertions, 382 deletions
diff --git a/app/javascript/themes/glitch/features/status/components/action_bar.js b/app/javascript/themes/glitch/features/status/components/action_bar.js deleted file mode 100644 index 6cda988d1..000000000 --- a/app/javascript/themes/glitch/features/status/components/action_bar.js +++ /dev/null @@ -1,129 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import IconButton from 'themes/glitch/components/icon_button'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import DropdownMenuContainer from 'themes/glitch/containers/dropdown_menu_container'; -import { defineMessages, injectIntl } from 'react-intl'; -import { me } from 'themes/glitch/util/initial_state'; - -const messages = defineMessages({ - delete: { id: 'status.delete', defaultMessage: 'Delete' }, - mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, - reply: { id: 'status.reply', defaultMessage: 'Reply' }, - reblog: { id: 'status.reblog', defaultMessage: 'Boost' }, - cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' }, - favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }, - report: { id: 'status.report', defaultMessage: 'Report @{name}' }, - share: { id: 'status.share', defaultMessage: 'Share' }, - pin: { id: 'status.pin', defaultMessage: 'Pin on profile' }, - unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' }, - embed: { id: 'status.embed', defaultMessage: 'Embed' }, -}); - -@injectIntl -export default class ActionBar extends React.PureComponent { - - static contextTypes = { - router: PropTypes.object, - }; - - static propTypes = { - status: ImmutablePropTypes.map.isRequired, - onReply: PropTypes.func.isRequired, - onReblog: PropTypes.func.isRequired, - onFavourite: PropTypes.func.isRequired, - onDelete: PropTypes.func.isRequired, - onMention: PropTypes.func.isRequired, - onReport: PropTypes.func, - onPin: PropTypes.func, - onEmbed: PropTypes.func, - intl: PropTypes.object.isRequired, - }; - - handleReplyClick = () => { - this.props.onReply(this.props.status); - } - - handleReblogClick = (e) => { - this.props.onReblog(this.props.status, e); - } - - handleFavouriteClick = () => { - this.props.onFavourite(this.props.status); - } - - handleDeleteClick = () => { - this.props.onDelete(this.props.status); - } - - handleMentionClick = () => { - this.props.onMention(this.props.status.get('account'), this.context.router.history); - } - - handleReport = () => { - this.props.onReport(this.props.status); - } - - handlePinClick = () => { - this.props.onPin(this.props.status); - } - - handleShare = () => { - navigator.share({ - text: this.props.status.get('search_index'), - url: this.props.status.get('url'), - }); - } - - handleEmbed = () => { - this.props.onEmbed(this.props.status); - } - - render () { - const { status, intl } = this.props; - - const publicStatus = ['public', 'unlisted'].includes(status.get('visibility')); - - let menu = []; - - if (publicStatus) { - menu.push({ text: intl.formatMessage(messages.embed), action: this.handleEmbed }); - } - - if (me === status.getIn(['account', 'id'])) { - if (publicStatus) { - menu.push({ text: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick }); - } - - menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); - } else { - menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); - menu.push(null); - menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); - } - - const shareButton = ('share' in navigator) && status.get('visibility') === 'public' && ( - <div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.share)} icon='share-alt' onClick={this.handleShare} /></div> - ); - - let reblogIcon = 'retweet'; - //if (status.get('visibility') === 'direct') reblogIcon = 'envelope'; - // else if (status.get('visibility') === 'private') reblogIcon = 'lock'; - - let reblog_disabled = (status.get('visibility') === 'direct' || status.get('visibility') === 'private'); - - return ( - <div className='detailed-status__action-bar'> - <div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get('in_reply_to_id', null) === null ? 'reply' : 'reply-all'} onClick={this.handleReplyClick} /></div> - <div className='detailed-status__button'><IconButton disabled={reblog_disabled} active={status.get('reblogged')} title={reblog_disabled ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)} icon={reblogIcon} onClick={this.handleReblogClick} /></div> - <div className='detailed-status__button'><IconButton animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} activeStyle={{ color: '#ca8f04' }} /></div> - {shareButton} - - <div className='detailed-status__action-bar-dropdown'> - <DropdownMenuContainer size={18} icon='ellipsis-h' items={menu} direction='left' ariaLabel='More' /> - </div> - </div> - ); - } - -} diff --git a/app/javascript/themes/glitch/features/status/components/card.js b/app/javascript/themes/glitch/features/status/components/card.js deleted file mode 100644 index bb83374b9..000000000 --- a/app/javascript/themes/glitch/features/status/components/card.js +++ /dev/null @@ -1,125 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import punycode from 'punycode'; -import classnames from 'classnames'; - -const IDNA_PREFIX = 'xn--'; - -const decodeIDNA = domain => { - return domain - .split('.') - .map(part => part.indexOf(IDNA_PREFIX) === 0 ? punycode.decode(part.slice(IDNA_PREFIX.length)) : part) - .join('.'); -}; - -const getHostname = url => { - const parser = document.createElement('a'); - parser.href = url; - return parser.hostname; -}; - -export default class Card extends React.PureComponent { - - static propTypes = { - card: ImmutablePropTypes.map, - maxDescription: PropTypes.number, - }; - - static defaultProps = { - maxDescription: 50, - }; - - state = { - width: 0, - }; - - renderLink () { - const { card, maxDescription } = this.props; - - let image = ''; - let provider = card.get('provider_name'); - - if (card.get('image')) { - image = ( - <div className='status-card__image'> - <img src={card.get('image')} alt={card.get('title')} className='status-card__image-image' width={card.get('width')} height={card.get('height')} /> - </div> - ); - } - - if (provider.length < 1) { - provider = decodeIDNA(getHostname(card.get('url'))); - } - - const className = classnames('status-card', { - 'horizontal': card.get('width') > card.get('height'), - }); - - return ( - <a href={card.get('url')} className={className} target='_blank' rel='noopener'> - {image} - - <div className='status-card__content'> - <strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong> - <p className='status-card__description'>{(card.get('description') || '').substring(0, maxDescription)}</p> - <span className='status-card__host'>{provider}</span> - </div> - </a> - ); - } - - renderPhoto () { - const { card } = this.props; - - return ( - <a href={card.get('url')} className='status-card-photo' target='_blank' rel='noopener'> - <img src={card.get('url')} alt={card.get('title')} width={card.get('width')} height={card.get('height')} /> - </a> - ); - } - - setRef = c => { - if (c) { - this.setState({ width: c.offsetWidth }); - } - } - - renderVideo () { - const { card } = this.props; - const content = { __html: card.get('html') }; - const { width } = this.state; - const ratio = card.get('width') / card.get('height'); - const height = card.get('width') > card.get('height') ? (width / ratio) : (width * ratio); - - return ( - <div - ref={this.setRef} - className='status-card-video' - dangerouslySetInnerHTML={content} - style={{ height }} - /> - ); - } - - render () { - const { card } = this.props; - - if (card === null) { - return null; - } - - switch(card.get('type')) { - case 'link': - return this.renderLink(); - case 'photo': - return this.renderPhoto(); - case 'video': - return this.renderVideo(); - case 'rich': - default: - return null; - } - } - -} diff --git a/app/javascript/themes/glitch/features/status/components/detailed_status.js b/app/javascript/themes/glitch/features/status/components/detailed_status.js deleted file mode 100644 index 7606bfbf3..000000000 --- a/app/javascript/themes/glitch/features/status/components/detailed_status.js +++ /dev/null @@ -1,128 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import Avatar from 'themes/glitch/components/avatar'; -import DisplayName from 'themes/glitch/components/display_name'; -import StatusContent from 'themes/glitch/components/status_content'; -import StatusGallery from 'themes/glitch/components/media_gallery'; -import AttachmentList from 'themes/glitch/components/attachment_list'; -import { Link } from 'react-router-dom'; -import { FormattedDate, FormattedNumber } from 'react-intl'; -import CardContainer from '../containers/card_container'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import Video from 'themes/glitch/features/video'; -import VisibilityIcon from 'themes/glitch/components/status_visibility_icon'; - -export default class DetailedStatus extends ImmutablePureComponent { - - static contextTypes = { - router: PropTypes.object, - }; - - static propTypes = { - status: ImmutablePropTypes.map.isRequired, - settings: ImmutablePropTypes.map.isRequired, - onOpenMedia: PropTypes.func.isRequired, - onOpenVideo: PropTypes.func.isRequired, - }; - - handleAccountClick = (e) => { - if (e.button === 0) { - e.preventDefault(); - this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`); - } - - e.stopPropagation(); - } - - // handleOpenVideo = startTime => { - // this.props.onOpenVideo(this.props.status.getIn(['media_attachments', 0]), startTime); - // } - - render () { - const status = this.props.status.get('reblog') ? this.props.status.get('reblog') : this.props.status; - const { settings } = this.props; - - let media = ''; - let mediaIcon = null; - let applicationLink = ''; - let reblogLink = ''; - let reblogIcon = 'retweet'; - - if (status.get('media_attachments').size > 0) { - if (status.get('media_attachments').some(item => item.get('type') === 'unknown')) { - media = <AttachmentList media={status.get('media_attachments')} />; - } else if (status.getIn(['media_attachments', 0, 'type']) === 'video') { - media = ( - <Video - sensitive={status.get('sensitive')} - media={status.getIn(['media_attachments', 0])} - letterbox={settings.getIn(['media', 'letterbox'])} - fullwidth={settings.getIn(['media', 'fullwidth'])} - onOpenVideo={this.props.onOpenVideo} - autoplay - /> - ); - mediaIcon = 'video-camera'; - } else { - media = ( - <StatusGallery - sensitive={status.get('sensitive')} - media={status.get('media_attachments')} - letterbox={settings.getIn(['media', 'letterbox'])} - onOpenMedia={this.props.onOpenMedia} - /> - ); - mediaIcon = 'picture-o'; - } - } else media = <CardContainer statusId={status.get('id')} />; - - if (status.get('application')) { - applicationLink = <span> · <a className='detailed-status__application' href={status.getIn(['application', 'website'])} target='_blank' rel='noopener'>{status.getIn(['application', 'name'])}</a></span>; - } - - if (status.get('visibility') === 'direct') { - reblogIcon = 'envelope'; - } else if (status.get('visibility') === 'private') { - reblogIcon = 'lock'; - } - - if (status.get('visibility') === 'private') { - reblogLink = <i className={`fa fa-${reblogIcon}`} />; - } else { - reblogLink = (<Link to={`/statuses/${status.get('id')}/reblogs`} className='detailed-status__link'> - <i className={`fa fa-${reblogIcon}`} /> - <span className='detailed-status__reblogs'> - <FormattedNumber value={status.get('reblogs_count')} /> - </span> - </Link>); - } - - return ( - <div className='detailed-status'> - <a href={status.getIn(['account', 'url'])} onClick={this.handleAccountClick} className='detailed-status__display-name'> - <div className='detailed-status__display-avatar'><Avatar account={status.get('account')} size={48} /></div> - <DisplayName account={status.get('account')} /> - </a> - - <StatusContent - status={status} - media={media} - mediaIcon={mediaIcon} - /> - - <div className='detailed-status__meta'> - <a className='detailed-status__datetime' href={status.get('url')} target='_blank' rel='noopener'> - <FormattedDate value={new Date(status.get('created_at'))} hour12={false} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' /> - </a>{applicationLink} · {reblogLink} · <Link to={`/statuses/${status.get('id')}/favourites`} className='detailed-status__link'> - <i className='fa fa-star' /> - <span className='detailed-status__favorites'> - <FormattedNumber value={status.get('favourites_count')} /> - </span> - </Link> · <VisibilityIcon visibility={status.get('visibility')} /> - </div> - </div> - ); - } - -} |