Use dropdown for reposts, do not display cards for quote posts

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2022-01-23 22:15:25 +01:00
parent 361831f021
commit 289cdcc776
8 changed files with 120 additions and 18 deletions

View File

@ -207,6 +207,8 @@ export default class Dropdown extends React.PureComponent {
src: PropTypes.string, src: PropTypes.string,
items: PropTypes.array.isRequired, items: PropTypes.array.isRequired,
size: PropTypes.number, size: PropTypes.number,
active: PropTypes.bool,
pressed: PropTypes.bool,
title: PropTypes.string, title: PropTypes.string,
disabled: PropTypes.bool, disabled: PropTypes.bool,
status: ImmutablePropTypes.map, status: ImmutablePropTypes.map,
@ -217,6 +219,7 @@ export default class Dropdown extends React.PureComponent {
dropdownPlacement: PropTypes.string, dropdownPlacement: PropTypes.string,
openDropdownId: PropTypes.number, openDropdownId: PropTypes.number,
openedViaKeyboard: PropTypes.bool, openedViaKeyboard: PropTypes.bool,
text: PropTypes.string,
}; };
static defaultProps = { static defaultProps = {
@ -302,7 +305,7 @@ export default class Dropdown extends React.PureComponent {
} }
render() { render() {
const { icon, src, items, size, title, disabled, dropdownPlacement, openDropdownId, openedViaKeyboard } = this.props; const { icon, src, items, size, title, disabled, dropdownPlacement, openDropdownId, openedViaKeyboard, active, pressed, text } = this.props;
const open = this.state.id === openDropdownId; const open = this.state.id === openDropdownId;
return ( return (
@ -311,9 +314,11 @@ export default class Dropdown extends React.PureComponent {
icon={icon} icon={icon}
src={src} src={src}
title={title} title={title}
active={open} active={open || active}
pressed={pressed}
disabled={disabled} disabled={disabled}
size={size} size={size}
text={text}
ref={this.setTargetRef} ref={this.setTargetRef}
onClick={this.handleClick} onClick={this.handleClick}
onMouseDown={this.handleMouseDown} onMouseDown={this.handleMouseDown}

View File

@ -458,7 +458,7 @@ class Status extends ImmutablePureComponent {
</Bundle> </Bundle>
); );
} }
} else if (status.get('spoiler_text').length === 0 && status.get('card')) { } else if (status.get('spoiler_text').length === 0 && !status.getIn(['pleroma', 'quote']) && status.get('card')) {
media = ( media = (
<Card <Card
onOpenMedia={this.props.onOpenMedia} onOpenMedia={this.props.onOpenMedia}

View File

@ -62,6 +62,7 @@ const messages = defineMessages({
reactionOpenMouth: { id: 'status.reactions.open_mouth', defaultMessage: 'Wow' }, reactionOpenMouth: { id: 'status.reactions.open_mouth', defaultMessage: 'Wow' },
reactionCry: { id: 'status.reactions.cry', defaultMessage: 'Sad' }, reactionCry: { id: 'status.reactions.cry', defaultMessage: 'Sad' },
reactionWeary: { id: 'status.reactions.weary', defaultMessage: 'Weary' }, reactionWeary: { id: 'status.reactions.weary', defaultMessage: 'Weary' },
quotePost: { id: 'status.quote', defaultMessage: 'Quote post' },
}); });
class StatusActionBar extends ImmutablePureComponent { class StatusActionBar extends ImmutablePureComponent {
@ -506,7 +507,7 @@ class StatusActionBar extends ImmutablePureComponent {
} }
render() { render() {
const { status, intl, allowedEmoji, emojiSelectorFocused, handleEmojiSelectorUnfocus, features } = this.props; const { status, intl, allowedEmoji, emojiSelectorFocused, handleEmojiSelectorUnfocus, features, me } = this.props;
const { emojiSelectorVisible } = this.state; const { emojiSelectorVisible } = this.state;
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility')); const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
@ -530,6 +531,47 @@ class StatusActionBar extends ImmutablePureComponent {
'😩': messages.reactionWeary, '😩': messages.reactionWeary,
}[meEmojiReact] || messages.favourite); }[meEmojiReact] || messages.favourite);
let reblogButton;
if (me && features.quotePosts) {
const reblogMenu = [
{
text: intl.formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog),
action: this.handleReblogClick,
icon: require('@tabler/icons/icons/repeat.svg'),
},
{
text: intl.formatMessage(messages.quotePost),
action: this.handleQuoteClick,
icon: require('@tabler/icons/icons/quote.svg'),
},
];
reblogButton = (
<DropdownMenuContainer
items={reblogMenu}
disabled={!publicStatus}
active={status.get('reblogged')}
pressed={status.get('reblogged')}
title={!publicStatus ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)}
src={require('@tabler/icons/icons/repeat.svg')}
direction='right'
/>
);
} else {
reblogButton = (
<IconButton
className='status__action-bar-button'
disabled={!publicStatus}
active={status.get('reblogged')}
pressed={status.get('reblogged')}
title={!publicStatus ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)}
src={reblogIcon}
onClick={this.handleReblogClick}
/>
);
}
const menu = this._makeMenu(publicStatus); const menu = this._makeMenu(publicStatus);
let reblogIcon = require('feather-icons/dist/icons/repeat.svg'); let reblogIcon = require('feather-icons/dist/icons/repeat.svg');
let replyTitle; let replyTitle;
@ -563,13 +605,10 @@ class StatusActionBar extends ImmutablePureComponent {
<IconButton className='status__action-bar-button' title={replyTitle} src={require('feather-icons/dist/icons/message-circle.svg')} onClick={this.handleReplyClick} /> <IconButton className='status__action-bar-button' title={replyTitle} src={require('feather-icons/dist/icons/message-circle.svg')} onClick={this.handleReplyClick} />
{replyCount !== 0 && <Link to={`/@${status.getIn(['account', 'acct'])}/posts/${status.get('id')}`} className='detailed-status__link'>{replyCount}</Link>} {replyCount !== 0 && <Link to={`/@${status.getIn(['account', 'acct'])}/posts/${status.get('id')}`} className='detailed-status__link'>{replyCount}</Link>}
</div> </div>
<div className='status__action-bar__counter'> <div className='status__action-bar__counter status__action-bar__counter--reblog'>
<IconButton className='status__action-bar-button' disabled={!publicStatus} active={status.get('reblogged')} pressed={status.get('reblogged')} title={!publicStatus ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)} src={reblogIcon} onClick={this.handleReblogClick} /> {reblogButton}
{reblogCount !== 0 && <span className='detailed-status__link' type='button' role='presentation' onClick={this.handleOpenReblogsModal}>{reblogCount}</span>} {reblogCount !== 0 && <span className='detailed-status__link' type='button' role='presentation' onClick={this.handleOpenReblogsModal}>{reblogCount}</span>}
</div> </div>
<div className='status__action-bar__counter'>
<IconButton className='status__action-bar-button' disabled={!publicStatus} title={!publicStatus ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)} src={require('@tabler/icons/icons/quote.svg')} onClick={this.handleQuoteClick} />
</div>
<div <div
className='status__action-bar__counter status__action-bar__counter--favourite' className='status__action-bar__counter status__action-bar__counter--favourite'
onMouseEnter={this.handleLikeButtonHover} onMouseEnter={this.handleLikeButtonHover}

View File

@ -53,6 +53,7 @@ const messages = defineMessages({
reactionCry: { id: 'status.reactions.cry', defaultMessage: 'Sad' }, reactionCry: { id: 'status.reactions.cry', defaultMessage: 'Sad' },
reactionWeary: { id: 'status.reactions.weary', defaultMessage: 'Weary' }, reactionWeary: { id: 'status.reactions.weary', defaultMessage: 'Weary' },
emojiPickerExpand: { id: 'status.reactions_expand', defaultMessage: 'Select emoji' }, emojiPickerExpand: { id: 'status.reactions_expand', defaultMessage: 'Select emoji' },
quotePost: { id: 'status.quote', defaultMessage: 'Quote post' },
}); });
const mapStateToProps = state => { const mapStateToProps = state => {
@ -87,6 +88,7 @@ class ActionBar extends React.PureComponent {
status: ImmutablePropTypes.map.isRequired, status: ImmutablePropTypes.map.isRequired,
onReply: PropTypes.func.isRequired, onReply: PropTypes.func.isRequired,
onReblog: PropTypes.func.isRequired, onReblog: PropTypes.func.isRequired,
onQuote: PropTypes.func.isRequired,
onFavourite: PropTypes.func.isRequired, onFavourite: PropTypes.func.isRequired,
onEmojiReact: PropTypes.func.isRequired, onEmojiReact: PropTypes.func.isRequired,
onDelete: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired,
@ -143,6 +145,15 @@ class ActionBar extends React.PureComponent {
} }
} }
handleQuoteClick = () => {
const { me, onQuote, onOpenUnauthorizedModal, status } = this.props;
if (me) {
onQuote(status, this.context.router.history);
} else {
onOpenUnauthorizedModal('REBLOG');
}
}
handleBookmarkClick = () => { handleBookmarkClick = () => {
this.props.onBookmark(this.props.status); this.props.onBookmark(this.props.status);
} }
@ -319,6 +330,47 @@ class ActionBar extends React.PureComponent {
'😩': messages.reactionWeary, '😩': messages.reactionWeary,
}[meEmojiReact] || messages.favourite); }[meEmojiReact] || messages.favourite);
let reblogButton;
if (me && features.quotePosts) {
const reblogMenu = [
{
text: intl.formatMessage(status.get('reblogged') ? messages.cancel_reblog_private : messages.reblog),
action: this.handleReblogClick,
icon: require('@tabler/icons/icons/repeat.svg'),
},
{
text: intl.formatMessage(messages.quotePost),
action: this.handleQuoteClick,
icon: require('@tabler/icons/icons/quote.svg'),
},
];
reblogButton = (
<DropdownMenuContainer
items={reblogMenu}
disabled={!publicStatus}
active={status.get('reblogged')}
pressed={status.get('reblogged')}
title={!publicStatus ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)}
src={require('@tabler/icons/icons/repeat.svg')}
direction='right'
text={intl.formatMessage(messages.reblog)}
/>
);
} else {
reblogButton = (
<IconButton
disabled={reblog_disabled}
active={status.get('reblogged')}
title={reblog_disabled ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)}
src={reblogIcon}
onClick={this.handleReblogClick}
text={intl.formatMessage(messages.reblog)}
/>
);
}
const menu = []; const menu = [];
if (publicStatus) { if (publicStatus) {
@ -497,14 +549,7 @@ class ActionBar extends React.PureComponent {
/> />
</div> </div>
<div className='detailed-status__button'> <div className='detailed-status__button'>
<IconButton {reblogButton}
disabled={reblog_disabled}
active={status.get('reblogged')}
title={reblog_disabled ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)}
src={reblogIcon}
onClick={this.handleReblogClick}
text={intl.formatMessage(messages.reblog)}
/>
</div> </div>
<div <div
className='detailed-status__button detailed-status__button--favourite' className='detailed-status__button detailed-status__button--favourite'

View File

@ -157,7 +157,7 @@ class DetailedStatus extends ImmutablePureComponent {
/> />
); );
} }
} else if (status.get('spoiler_text').length === 0) { } else if (status.get('spoiler_text').length === 0 && !status.getIn(['pleroma', 'quote'])) {
media = <Card onOpenMedia={this.props.onOpenMedia} card={status.get('card', null)} />; media = <Card onOpenMedia={this.props.onOpenMedia} card={status.get('card', null)} />;
} }

View File

@ -29,6 +29,8 @@ class QuotedStatus extends ImmutablePureComponent {
} }
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/posts/${this.props.status.get('id')}`); this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/posts/${this.props.status.get('id')}`);
e.preventDefault();
} }
} }

View File

@ -78,6 +78,7 @@ export const getFeatures = createSelector([
remoteInteractionsAPI: v.software === PLEROMA && gte(v.version, '2.4.50'), remoteInteractionsAPI: v.software === PLEROMA && gte(v.version, '2.4.50'),
explicitAddressing: v.software === PLEROMA && gte(v.version, '1.0.0'), explicitAddressing: v.software === PLEROMA && gte(v.version, '1.0.0'),
accountEndorsements: v.software === PLEROMA && gte(v.version, '2.4.50'), accountEndorsements: v.software === PLEROMA && gte(v.version, '2.4.50'),
quotePosts: v.software === PLEROMA && gte(v.version, '2.4.50'),
}; };
}); });

View File

@ -338,6 +338,16 @@
font-weight: 500; font-weight: 500;
color: var(--brand-color); color: var(--brand-color);
} }
&--reblog {
> div {
display: flex;
> .icon-button {
margin-right: 8px;
}
}
}
} }
} }