Merge pull request #2511 from ClearlyClaire/glitch-soc/cleanup-2

Further reduce code differences with upstream
main
Claire 2023-12-10 18:03:04 +01:00 committed by GitHub
commit 98f50429d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 86 additions and 90 deletions

View File

@ -17,7 +17,6 @@ import { Avatar } from './avatar';
import { Button } from './button'; import { Button } from './button';
import { FollowersCounter } from './counters'; import { FollowersCounter } from './counters';
import { DisplayName } from './display_name'; import { DisplayName } from './display_name';
import { IconButton } from './icon_button';
import Permalink from './permalink'; import Permalink from './permalink';
import { RelativeTimestamp } from './relative_timestamp'; import { RelativeTimestamp } from './relative_timestamp';
@ -45,10 +44,7 @@ class Account extends ImmutablePureComponent {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
hidden: PropTypes.bool, hidden: PropTypes.bool,
minimal: PropTypes.bool, minimal: PropTypes.bool,
actionIcon: PropTypes.string,
actionTitle: PropTypes.string,
defaultAction: PropTypes.string, defaultAction: PropTypes.string,
onActionClick: PropTypes.func,
withBio: PropTypes.bool, withBio: PropTypes.bool,
}; };
@ -76,12 +72,8 @@ class Account extends ImmutablePureComponent {
this.props.onMuteNotifications(this.props.account, false); this.props.onMuteNotifications(this.props.account, false);
}; };
handleAction = () => {
this.props.onActionClick(this.props.account);
};
render () { render () {
const { account, intl, hidden, withBio, onActionClick, actionIcon, actionTitle, defaultAction, size, minimal } = this.props; const { account, intl, hidden, withBio, defaultAction, size, minimal } = this.props;
if (!account) { if (!account) {
return <EmptyAccount size={size} minimal={minimal} />; return <EmptyAccount size={size} minimal={minimal} />;
@ -98,9 +90,7 @@ class Account extends ImmutablePureComponent {
let buttons; let buttons;
if (actionIcon && onActionClick) { if (account.get('id') !== me && account.get('relationship', null) !== null) {
buttons = <IconButton icon={actionIcon} title={actionTitle} onClick={this.handleAction} />;
} else if (!actionIcon && account.get('id') !== me && account.get('relationship', null) !== null) {
const following = account.getIn(['relationship', 'following']); const following = account.getIn(['relationship', 'following']);
const requested = account.getIn(['relationship', 'requested']); const requested = account.getIn(['relationship', 'requested']);
const blocking = account.getIn(['relationship', 'blocking']); const blocking = account.getIn(['relationship', 'blocking']);

View File

@ -12,7 +12,6 @@ export default class Column extends PureComponent {
static propTypes = { static propTypes = {
children: PropTypes.node, children: PropTypes.node,
extraClasses: PropTypes.string, extraClasses: PropTypes.string,
name: PropTypes.string,
label: PropTypes.string, label: PropTypes.string,
bindToDocument: PropTypes.bool, bindToDocument: PropTypes.bool,
}; };
@ -62,10 +61,10 @@ export default class Column extends PureComponent {
} }
render () { render () {
const { children, extraClasses, name, label } = this.props; const { label, children, extraClasses } = this.props;
return ( return (
<div role='region' aria-label={label} data-column={name} className={`column ${extraClasses || ''}`} ref={this.setRef}> <div role='region' aria-label={label} className={`column ${extraClasses || ''}`} ref={this.setRef}>
{children} {children}
</div> </div>
); );

View File

@ -79,6 +79,7 @@ class Status extends ImmutablePureComponent {
previousId: PropTypes.string, previousId: PropTypes.string,
nextInReplyToId: PropTypes.string, nextInReplyToId: PropTypes.string,
rootId: PropTypes.string, rootId: PropTypes.string,
onClick: PropTypes.func,
onReply: PropTypes.func, onReply: PropTypes.func,
onFavourite: PropTypes.func, onFavourite: PropTypes.func,
onReblog: PropTypes.func, onReblog: PropTypes.func,
@ -109,7 +110,6 @@ class Status extends ImmutablePureComponent {
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
cacheMediaWidth: PropTypes.func, cacheMediaWidth: PropTypes.func,
cachedMediaWidth: PropTypes.number, cachedMediaWidth: PropTypes.number,
onClick: PropTypes.func,
scrollKey: PropTypes.string, scrollKey: PropTypes.string,
deployPictureInPicture: PropTypes.func, deployPictureInPicture: PropTypes.func,
settings: ImmutablePropTypes.map.isRequired, settings: ImmutablePropTypes.map.isRequired,

View File

@ -22,6 +22,7 @@ import { store } from 'flavours/glitch/store';
const title = process.env.NODE_ENV === 'production' ? siteTitle : `${siteTitle} (Dev)`; const title = process.env.NODE_ENV === 'production' ? siteTitle : `${siteTitle} (Dev)`;
const hydrateAction = hydrateStore(initialState); const hydrateAction = hydrateStore(initialState);
store.dispatch(hydrateAction); store.dispatch(hydrateAction);
// check for deprecated local settings // check for deprecated local settings
@ -71,8 +72,8 @@ export default class Mastodon extends PureComponent {
} }
} }
shouldUpdateScroll (_, { location }) { shouldUpdateScroll (prevRouterProps, { location }) {
return !(location.state?.mastodonModalKey); return !(location.state?.mastodonModalKey && location.state?.mastodonModalKey !== prevRouterProps?.location?.state?.mastodonModalKey);
} }
render () { render () {

View File

@ -38,7 +38,7 @@ class FeaturedTags extends ImmutablePureComponent {
name={featuredTag.get('name')} name={featuredTag.get('name')}
href={featuredTag.get('url')} href={featuredTag.get('url')}
to={`/@${account.get('acct')}/tagged/${featuredTag.get('name')}`} to={`/@${account.get('acct')}/tagged/${featuredTag.get('name')}`}
uses={featuredTag.get('statuses_count')} uses={featuredTag.get('statuses_count') * 1}
withGraph={false} withGraph={false}
description={((featuredTag.get('statuses_count') * 1) > 0) ? intl.formatMessage(messages.lastStatusAt, { date: intl.formatDate(featuredTag.get('last_status_at'), { month: 'short', day: '2-digit' }) }) : intl.formatMessage(messages.empty)} description={((featuredTag.get('statuses_count') * 1) > 0) ? intl.formatMessage(messages.lastStatusAt, { date: intl.formatDate(featuredTag.get('last_status_at'), { month: 'short', day: '2-digit' }) }) : intl.formatMessage(messages.empty)}
/> />

View File

@ -76,7 +76,7 @@ export default class MediaItem extends ImmutablePureComponent {
if (['audio', 'video'].includes(attachment.get('type'))) { if (['audio', 'video'].includes(attachment.get('type'))) {
content = ( content = (
<img <img
src={attachment.get('preview_url') || attachment.getIn(['account', 'avatar_static'])} src={attachment.get('preview_url') || status.getIn(['account', 'avatar_static'])}
alt={attachment.get('description')} alt={attachment.get('description')}
lang={status.get('language')} lang={status.get('language')}
onLoad={this.handleImageLoad} onLoad={this.handleImageLoad}

View File

@ -184,7 +184,7 @@ class AccountTimeline extends ImmutablePureComponent {
const remoteMessage = remote ? <RemoteHint url={remoteUrl} /> : null; const remoteMessage = remote ? <RemoteHint url={remoteUrl} /> : null;
return ( return (
<Column ref={this.setRef} name='account'> <Column ref={this.setRef}>
<ProfileColumnHeader onClick={this.handleHeaderClick} multiColumn={multiColumn} /> <ProfileColumnHeader onClick={this.handleHeaderClick} multiColumn={multiColumn} />
<StatusList <StatusList

View File

@ -59,7 +59,7 @@ class Blocks extends ImmutablePureComponent {
const emptyMessage = <FormattedMessage id='empty_column.blocks' defaultMessage="You haven't blocked any users yet." />; const emptyMessage = <FormattedMessage id='empty_column.blocks' defaultMessage="You haven't blocked any users yet." />;
return ( return (
<Column name='blocks' bindToDocument={!multiColumn} icon='ban' heading={intl.formatMessage(messages.heading)}> <Column bindToDocument={!multiColumn} icon='ban' heading={intl.formatMessage(messages.heading)}>
<ColumnBackButtonSlim /> <ColumnBackButtonSlim />
<ScrollableList <ScrollableList
scrollKey='blocks' scrollKey='blocks'

View File

@ -77,7 +77,7 @@ class Bookmarks extends ImmutablePureComponent {
const emptyMessage = <FormattedMessage id='empty_column.bookmarked_statuses' defaultMessage="You don't have any bookmarked posts yet. When you bookmark one, it will show up here." />; const emptyMessage = <FormattedMessage id='empty_column.bookmarked_statuses' defaultMessage="You don't have any bookmarked posts yet. When you bookmark one, it will show up here." />;
return ( return (
<Column bindToDocument={!multiColumn} ref={this.setRef} name='bookmarks'> <Column bindToDocument={!multiColumn} ref={this.setRef}>
<ColumnHeader <ColumnHeader
icon='bookmark' icon='bookmark'
title={intl.formatMessage(messages.heading)} title={intl.formatMessage(messages.heading)}

View File

@ -40,14 +40,14 @@ const mapStateToProps = (state, { columnId }) => {
class CommunityTimeline extends PureComponent { class CommunityTimeline extends PureComponent {
static defaultProps = {
onlyMedia: false,
};
static contextTypes = { static contextTypes = {
identity: PropTypes.object, identity: PropTypes.object,
}; };
static defaultProps = {
onlyMedia: false,
};
static propTypes = { static propTypes = {
dispatch: PropTypes.func.isRequired, dispatch: PropTypes.func.isRequired,
columnId: PropTypes.string, columnId: PropTypes.string,
@ -128,7 +128,7 @@ class CommunityTimeline extends PureComponent {
const pinned = !!columnId; const pinned = !!columnId;
return ( return (
<Column ref={this.setRef} name='local' bindToDocument={!multiColumn} label={intl.formatMessage(messages.title)}> <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
<ColumnHeader <ColumnHeader
icon='users' icon='users'
active={hasUnread} active={hasUnread}

View File

@ -17,19 +17,21 @@ export default class NavigationBar extends ImmutablePureComponent {
static propTypes = { static propTypes = {
account: ImmutablePropTypes.map.isRequired, account: ImmutablePropTypes.map.isRequired,
onLogout: PropTypes.func.isRequired, onLogout: PropTypes.func.isRequired,
onClose: PropTypes.func,
}; };
render () { render () {
const username = this.props.account.get('acct');
return ( return (
<div className='navigation-bar'> <div className='navigation-bar'>
<Permalink className='avatar' href={this.props.account.get('url')} to={`/@${this.props.account.get('acct')}`}> <Permalink className='avatar' href={this.props.account.get('url')} to={`/@${username}`}>
<span style={{ display: 'none' }}>{this.props.account.get('acct')}</span> <span style={{ display: 'none' }}>{username}</span>
<Avatar account={this.props.account} size={48} /> <Avatar account={this.props.account} size={46} />
</Permalink> </Permalink>
<div className='navigation-bar__profile'> <div className='navigation-bar__profile'>
<Permalink className='acct' href={this.props.account.get('url')} to={`/@${this.props.account.get('acct')}`}> <Permalink className='acct' href={this.props.account.get('url')} to={`/@${this.props.account.get('acct')}`}>
<strong>@{this.props.account.get('acct')}</strong> <strong className='navigation-bar__profile-account'>@{username}</strong>
</Permalink> </Permalink>
{ profileLink !== undefined && ( { profileLink !== undefined && (

View File

@ -92,25 +92,6 @@ class Search extends PureComponent {
} }
}; };
handleBlur = () => {
this.setState({ expanded: false, selectedOption: -1 });
};
handleFocus = () => {
const { onShow, singleColumn } = this.props;
this.setState({ expanded: true, selectedOption: -1 });
onShow();
if (this.searchForm && !singleColumn) {
const { left, right } = this.searchForm.getBoundingClientRect();
if (left < 0 || right > (window.innerWidth || document.documentElement.clientWidth)) {
this.searchForm.scrollIntoView();
}
}
};
handleKeyDown = (e) => { handleKeyDown = (e) => {
const { selectedOption } = this.state; const { selectedOption } = this.state;
const options = searchEnabled ? this._getOptions().concat(this.defaultOptions) : this._getOptions(); const options = searchEnabled ? this._getOptions().concat(this.defaultOptions) : this._getOptions();
@ -161,8 +142,23 @@ class Search extends PureComponent {
} }
}; };
findTarget = () => { handleFocus = () => {
return this.searchForm; const { onShow, singleColumn } = this.props;
this.setState({ expanded: true, selectedOption: -1 });
onShow();
if (this.searchForm && !singleColumn) {
const { left, right } = this.searchForm.getBoundingClientRect();
if (left < 0 || right > (window.innerWidth || document.documentElement.clientWidth)) {
this.searchForm.scrollIntoView();
}
}
};
handleBlur = () => {
this.setState({ expanded: false, selectedOption: -1 });
}; };
handleHashtagClick = () => { handleHashtagClick = () => {

View File

@ -69,6 +69,7 @@ class SearchResults extends ImmutablePureComponent {
); );
} }
return ( return (
<div className='drawer--results'> <div className='drawer--results'>
<header className='search-results__header'> <header className='search-results__header'>

View File

@ -77,7 +77,7 @@ class Favourites extends ImmutablePureComponent {
const emptyMessage = <FormattedMessage id='empty_column.favourited_statuses' defaultMessage="You don't have any favorite posts yet. When you favorite one, it will show up here." />; const emptyMessage = <FormattedMessage id='empty_column.favourited_statuses' defaultMessage="You don't have any favorite posts yet. When you favorite one, it will show up here." />;
return ( return (
<Column bindToDocument={!multiColumn} ref={this.setRef} name='favourites' label={intl.formatMessage(messages.heading)}> <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.heading)}>
<ColumnHeader <ColumnHeader
icon='star' icon='star'
title={intl.formatMessage(messages.heading)} title={intl.formatMessage(messages.heading)}

View File

@ -85,9 +85,10 @@ class Favourites extends ImmutablePureComponent {
showBackButton showBackButton
multiColumn={multiColumn} multiColumn={multiColumn}
extraButton={( extraButton={(
<button className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button> <button type='button' className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
)} )}
/> />
<ScrollableList <ScrollableList
scrollKey='favourites' scrollKey='favourites'
onLoadMore={this.handleLoadMore} onLoadMore={this.handleLoadMore}

View File

@ -67,7 +67,7 @@ class FollowRequests extends ImmutablePureComponent {
); );
return ( return (
<Column bindToDocument={!multiColumn} name='follow-requests' icon='user-plus' heading={intl.formatMessage(messages.heading)}> <Column bindToDocument={!multiColumn} icon='user-plus' heading={intl.formatMessage(messages.heading)}>
<ColumnBackButtonSlim /> <ColumnBackButtonSlim />
<ScrollableList <ScrollableList
scrollKey='follow_requests' scrollKey='follow_requests'

View File

@ -394,7 +394,7 @@ class Announcements extends ImmutablePureComponent {
_markAnnouncementAsRead () { _markAnnouncementAsRead () {
const { dismissAnnouncement, announcements } = this.props; const { dismissAnnouncement, announcements } = this.props;
const { index } = this.state; const { index } = this.state;
const announcement = announcements.get(index); const announcement = announcements.get(announcements.size - 1 - index);
if (!announcement.get('read')) dismissAnnouncement(announcement.get('id')); if (!announcement.get('read')) dismissAnnouncement(announcement.get('id'));
} }
@ -435,7 +435,7 @@ class Announcements extends ImmutablePureComponent {
selected={index === idx} selected={index === idx}
disabled={disableSwiping} disabled={disableSwiping}
/> />
))} )).reverse()}
</ReactSwipeableViews> </ReactSwipeableViews>
{announcements.size > 1 && ( {announcements.size > 1 && (

View File

@ -173,7 +173,7 @@ class GettingStarted extends ImmutablePureComponent {
} }
return ( return (
<Column bindToDocument={!multiColumn} name='getting-started' icon='asterisk' heading={intl.formatMessage(messages.heading)} label={intl.formatMessage(messages.menu)} hideHeadingOnMobile> <Column bindToDocument={!multiColumn} icon='asterisk' heading={intl.formatMessage(messages.heading)} label={intl.formatMessage(messages.menu)} hideHeadingOnMobile>
<div className='scrollable optionally-scrollable'> <div className='scrollable optionally-scrollable'>
<div className='getting-started__wrapper'> <div className='getting-started__wrapper'>
{!multiColumn && signedIn && <NavigationBar account={myAccount} />} {!multiColumn && signedIn && <NavigationBar account={myAccount} />}

View File

@ -196,7 +196,7 @@ class HomeTimeline extends PureComponent {
} }
return ( return (
<Column bindToDocument={!multiColumn} ref={this.setRef} name='home' label={intl.formatMessage(messages.title)}> <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
<ColumnHeader <ColumnHeader
icon='home' icon='home'
active={hasUnread} active={hasUnread}

View File

@ -61,7 +61,7 @@ class Mutes extends ImmutablePureComponent {
const emptyMessage = <FormattedMessage id='empty_column.mutes' defaultMessage="You haven't muted any users yet." />; const emptyMessage = <FormattedMessage id='empty_column.mutes' defaultMessage="You haven't muted any users yet." />;
return ( return (
<Column bindToDocument={!multiColumn} name='mutes' icon='volume-off' heading={intl.formatMessage(messages.heading)}> <Column bindToDocument={!multiColumn} icon='volume-off' heading={intl.formatMessage(messages.heading)}>
<ColumnBackButtonSlim /> <ColumnBackButtonSlim />
<ScrollableList <ScrollableList
scrollKey='mutes' scrollKey='mutes'

View File

@ -333,7 +333,6 @@ class Notifications extends PureComponent {
<Column <Column
bindToDocument={!multiColumn} bindToDocument={!multiColumn}
ref={this.setColumnRef} ref={this.setColumnRef}
name='notifications'
extraClasses={this.props.notifCleaningActive ? 'notif-cleaning' : null} extraClasses={this.props.notifCleaningActive ? 'notif-cleaning' : null}
label={intl.formatMessage(messages.title)} label={intl.formatMessage(messages.title)}
> >

View File

@ -122,8 +122,8 @@ class Footer extends ImmutablePureComponent {
} }
}; };
_performReblog = (privacy) => { _performReblog = (status, privacy) => {
const { dispatch, status } = this.props; const { dispatch } = this.props;
dispatch(reblog(status, privacy)); dispatch(reblog(status, privacy));
}; };
@ -135,7 +135,7 @@ class Footer extends ImmutablePureComponent {
if (status.get('reblogged')) { if (status.get('reblogged')) {
dispatch(unreblog(status)); dispatch(unreblog(status));
} else if ((e && e.shiftKey) || !boostModal) { } else if ((e && e.shiftKey) || !boostModal) {
this._performReblog(); this._performReblog(status);
} else { } else {
dispatch(initBoostModal({ status, onReblog: this._performReblog })); dispatch(initBoostModal({ status, onReblog: this._performReblog }));
} }

View File

@ -133,7 +133,7 @@ class PublicTimeline extends PureComponent {
const pinned = !!columnId; const pinned = !!columnId;
return ( return (
<Column bindToDocument={!multiColumn} ref={this.setRef} name='federated' label={intl.formatMessage(messages.title)}> <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
<ColumnHeader <ColumnHeader
icon='globe' icon='globe'
active={hasUnread} active={hasUnread}

View File

@ -12,7 +12,7 @@ import VisibilityIcon from 'flavours/glitch/components/status_visibility_icon';
import Option from './option'; import Option from './option';
export default class StatusCheckBox extends PureComponent { class StatusCheckBox extends PureComponent {
static propTypes = { static propTypes = {
id: PropTypes.string.isRequired, id: PropTypes.string.isRequired,
@ -40,7 +40,9 @@ export default class StatusCheckBox extends PureComponent {
<Avatar account={status.get('account')} size={46} /> <Avatar account={status.get('account')} size={46} />
</div> </div>
<div><DisplayName account={status.get('account')} /> · <VisibilityIcon visibility={status.get('visibility')} /><RelativeTimestamp timestamp={status.get('created_at')} /></div> <div>
<DisplayName account={status.get('account')} /> · <VisibilityIcon visibility={status.get('visibility')} /><RelativeTimestamp timestamp={status.get('created_at')} />
</div>
</div> </div>
<StatusContent status={status} media={<MediaAttachments status={status} revealed={false} />} /> <StatusContent status={status} media={<MediaAttachments status={status} revealed={false} />} />
@ -61,3 +63,5 @@ export default class StatusCheckBox extends PureComponent {
} }
} }
export default StatusCheckBox;

View File

@ -58,13 +58,13 @@ class ActionBar extends PureComponent {
onReblog: PropTypes.func.isRequired, onReblog: PropTypes.func.isRequired,
onFavourite: PropTypes.func.isRequired, onFavourite: PropTypes.func.isRequired,
onBookmark: PropTypes.func.isRequired, onBookmark: PropTypes.func.isRequired,
onMute: PropTypes.func,
onMuteConversation: PropTypes.func,
onBlock: PropTypes.func,
onDelete: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired,
onEdit: PropTypes.func.isRequired, onEdit: PropTypes.func.isRequired,
onDirect: PropTypes.func.isRequired, onDirect: PropTypes.func.isRequired,
onMention: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired,
onMute: PropTypes.func,
onBlock: PropTypes.func,
onMuteConversation: PropTypes.func,
onReport: PropTypes.func, onReport: PropTypes.func,
onPin: PropTypes.func, onPin: PropTypes.func,
onEmbed: PropTypes.func, onEmbed: PropTypes.func,
@ -112,14 +112,14 @@ class ActionBar extends PureComponent {
this.props.onMute(this.props.status.get('account')); this.props.onMute(this.props.status.get('account'));
}; };
handleConversationMuteClick = () => {
this.props.onMuteConversation(this.props.status);
};
handleBlockClick = () => { handleBlockClick = () => {
this.props.onBlock(this.props.status); this.props.onBlock(this.props.status);
}; };
handleConversationMuteClick = () => {
this.props.onMuteConversation(this.props.status);
};
handleReport = () => { handleReport = () => {
this.props.onReport(this.props.status); this.props.onReport(this.props.status);
}; };

View File

@ -3,7 +3,7 @@ import { PureComponent } from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import classnames from 'classnames'; import classNames from 'classnames';
import Immutable from 'immutable'; import Immutable from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
@ -148,7 +148,7 @@ export default class Card extends PureComponent {
const provider = card.get('provider_name').length === 0 ? decodeIDNA(getHostname(card.get('url'))) : card.get('provider_name'); const provider = card.get('provider_name').length === 0 ? decodeIDNA(getHostname(card.get('url'))) : card.get('provider_name');
const horizontal = (!compact && card.get('width') > card.get('height')) || card.get('type') !== 'link' || embedded; const horizontal = (!compact && card.get('width') > card.get('height')) || card.get('type') !== 'link' || embedded;
const interactive = card.get('type') !== 'link'; const interactive = card.get('type') !== 'link';
const className = classnames('status-card', { horizontal, compact, interactive }); const className = classNames('status-card', { horizontal, compact, interactive });
const title = interactive ? <a className='status-card__title' href={card.get('url')} title={card.get('title')} rel='noopener noreferrer' target='_blank'><strong>{card.get('title')}</strong></a> : <strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong>; const title = interactive ? <a className='status-card__title' href={card.get('url')} title={card.get('title')} rel='noopener noreferrer' target='_blank'><strong>{card.get('title')}</strong></a> : <strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong>;
const language = card.get('language') || ''; const language = card.get('language') || '';
@ -171,15 +171,17 @@ export default class Card extends PureComponent {
let embed = ''; let embed = '';
let canvas = ( let canvas = (
<Blurhash <Blurhash
className={classnames('status-card__image-preview', { className={classNames('status-card__image-preview', {
'status-card__image-preview--hidden': revealed && this.state.previewLoaded, 'status-card__image-preview--hidden': revealed && this.state.previewLoaded,
})} })}
hash={card.get('blurhash')} hash={card.get('blurhash')}
dummy={!useBlurhash} dummy={!useBlurhash}
/> />
); );
const thumbnailDescription = card.get('image_description'); const thumbnailDescription = card.get('image_description');
const thumbnail = <img src={card.get('image')} alt={thumbnailDescription} title={thumbnailDescription} lang={language} style={thumbnailStyle} onLoad={this.handleImageLoad} className='status-card__image-image' />; const thumbnail = <img src={card.get('image')} alt={thumbnailDescription} title={thumbnailDescription} lang={language} style={thumbnailStyle} onLoad={this.handleImageLoad} className='status-card__image-image' />;
let spoilerButton = ( let spoilerButton = (
<button type='button' onClick={this.handleReveal} className='spoiler-button__overlay'> <button type='button' onClick={this.handleReveal} className='spoiler-button__overlay'>
<span className='spoiler-button__overlay__label'> <span className='spoiler-button__overlay__label'>
@ -188,8 +190,9 @@ export default class Card extends PureComponent {
</span> </span>
</button> </button>
); );
spoilerButton = ( spoilerButton = (
<div className={classnames('spoiler-button', { 'spoiler-button--minified': revealed })}> <div className={classNames('spoiler-button', { 'spoiler-button--minified': revealed })}>
{spoilerButton} {spoilerButton}
</div> </div>
); );
@ -209,15 +212,14 @@ export default class Card extends PureComponent {
{canvas} {canvas}
{thumbnail} {thumbnail}
{revealed && ( {revealed ? (
<div className='status-card__actions'> <div className='status-card__actions'>
<div> <div>
<button onClick={this.handleEmbedClick}><Icon id={iconVariant} /></button> <button type='button' onClick={this.handleEmbedClick}><Icon id={iconVariant} /></button>
{horizontal && <a href={card.get('url')} target='_blank' rel='noopener noreferrer'><Icon id='external-link' /></a>} {horizontal && <a href={card.get('url')} target='_blank' rel='noopener noreferrer'><Icon id='external-link' /></a>}
</div> </div>
</div> </div>
)} ) : spoilerButton}
{!revealed && spoilerButton}
</div> </div>
); );
} }

View File

@ -75,7 +75,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl'); this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl');
} }
componentWillUpdate(nextProps) { UNSAFE_componentWillUpdate(nextProps) {
if (this.props.singleColumn !== nextProps.singleColumn && nextProps.singleColumn) { if (this.props.singleColumn !== nextProps.singleColumn && nextProps.singleColumn) {
this.node.removeEventListener('wheel', this.handleWheel); this.node.removeEventListener('wheel', this.handleWheel);
} }

View File

@ -96,6 +96,7 @@ class MediaModal extends ImmutablePureComponent {
componentDidMount () { componentDidMount () {
window.addEventListener('keydown', this.handleKeyDown, false); window.addEventListener('keydown', this.handleKeyDown, false);
this._sendBackgroundColor(); this._sendBackgroundColor();
} }