Add: #92 アカウントのおすすめタグを真ん中のカラムからも確認できるように (#678)

* Add: #92 アカウントのおすすめタグを真ん中のカラムからも確認できるように

* ハッシュタグを隠さないよう修正
This commit is contained in:
KMY(雪あすか) 2024-03-27 18:32:32 +09:00 committed by GitHub
parent 227090147e
commit 808244f0cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 45 additions and 8 deletions

View file

@ -196,9 +196,15 @@ export function getHashtagBarForStatus(status: StatusLike) {
}; };
} }
export function getFeaturedHashtagBar(acct: string, tags: string[]) {
return <HashtagBar acct={acct} hashtags={tags} defaultExpanded />;
}
const HashtagBar: React.FC<{ const HashtagBar: React.FC<{
hashtags: string[]; hashtags: string[];
}> = ({ hashtags }) => { acct?: string;
defaultExpanded?: boolean;
}> = ({ hashtags, acct, defaultExpanded }) => {
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
const handleClick = useCallback(() => { const handleClick = useCallback(() => {
setExpanded(true); setExpanded(true);
@ -208,19 +214,23 @@ const HashtagBar: React.FC<{
return null; return null;
} }
const revealedHashtags = expanded const revealedHashtags =
? hashtags expanded || defaultExpanded
: hashtags.slice(0, VISIBLE_HASHTAGS); ? hashtags
: hashtags.slice(0, VISIBLE_HASHTAGS);
return ( return (
<div className='hashtag-bar'> <div className='hashtag-bar'>
{revealedHashtags.map((hashtag) => ( {revealedHashtags.map((hashtag) => (
<Link key={hashtag} to={`/tags/${hashtag}`}> <Link
key={hashtag}
to={acct ? `/@${acct}/tagged/${hashtag}` : `/tags/${hashtag}`}
>
#<span>{hashtag}</span> #<span>{hashtag}</span>
</Link> </Link>
))} ))}
{!expanded && hashtags.length > VISIBLE_HASHTAGS && ( {!expanded && !defaultExpanded && hashtags.length > VISIBLE_HASHTAGS && (
<button className='link-button' onClick={handleClick}> <button className='link-button' onClick={handleClick}>
<FormattedMessage <FormattedMessage
id='hashtags.and_other' id='hashtags.and_other'

View file

@ -20,6 +20,7 @@ import { Badge, AutomatedBadge, GroupBadge } from 'mastodon/components/badge';
import { Button } from 'mastodon/components/button'; import { Button } from 'mastodon/components/button';
import { CopyIconButton } from 'mastodon/components/copy_icon_button'; import { CopyIconButton } from 'mastodon/components/copy_icon_button';
import { FollowersCounter, FollowingCounter, StatusesCounter } from 'mastodon/components/counters'; import { FollowersCounter, FollowingCounter, StatusesCounter } from 'mastodon/components/counters';
import { getFeaturedHashtagBar } from 'mastodon/components/hashtag_bar';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
import { IconButton } from 'mastodon/components/icon_button'; import { IconButton } from 'mastodon/components/icon_button';
import { LoadingIndicator } from 'mastodon/components/loading_indicator'; import { LoadingIndicator } from 'mastodon/components/loading_indicator';
@ -115,6 +116,7 @@ class Header extends ImmutablePureComponent {
static propTypes = { static propTypes = {
account: ImmutablePropTypes.record, account: ImmutablePropTypes.record,
featuredTags: PropTypes.array,
identity_props: ImmutablePropTypes.list, identity_props: ImmutablePropTypes.list,
onFollow: PropTypes.func.isRequired, onFollow: PropTypes.func.isRequired,
onBlock: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired,
@ -215,6 +217,16 @@ class Header extends ImmutablePureComponent {
} }
}; };
handleFeaturedHashtagClick = e => {
const { history, account } = this.props;
const value = e.currentTarget.textContent.replace(/^#/, '');
if (history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault();
history.push(`/@${account.get('acct')}/tagged/${value}`);
}
};
handleMentionClick = e => { handleMentionClick = e => {
const { history, onOpenURL } = this.props; const { history, onOpenURL } = this.props;
@ -244,7 +256,11 @@ class Header extends ImmutablePureComponent {
link = links[i]; link = links[i];
if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) { if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) {
link.addEventListener('click', this.handleHashtagClick, false); if (link.href && link.href.includes('/tagged/')) {
link.addEventListener('click', this.handleFeaturedHashtagClick, false);
} else {
link.addEventListener('click', this.handleHashtagClick, false);
}
} else if (link.classList.contains('mention')) { } else if (link.classList.contains('mention')) {
link.addEventListener('click', this.handleMentionClick, false); link.addEventListener('click', this.handleMentionClick, false);
} }
@ -409,6 +425,8 @@ class Header extends ImmutablePureComponent {
const username = account.get('acct').split('@')[0]; const username = account.get('acct').split('@')[0];
const domain = isLocal ? localDomain : account.get('acct').split('@')[1]; const domain = isLocal ? localDomain : account.get('acct').split('@')[1];
const isIndexable = !account.get('noindex'); const isIndexable = !account.get('noindex');
const featuredTagsArr = this.props.featuredTags?.map((tag) => tag.get('name')).toArray() || [];
const featuredTags = getFeaturedHashtagBar(account.get('acct'), featuredTagsArr);
const badges = []; const badges = [];
@ -472,6 +490,12 @@ class Header extends ImmutablePureComponent {
{account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content translate' dangerouslySetInnerHTML={content} />} {account.get('note').length > 0 && account.get('note') !== '<p></p>' && <div className='account__header__content translate' dangerouslySetInnerHTML={content} />}
{featuredTagsArr.length > 0 && (
<div className='account__header__featured-tags'>
{featuredTags}
</div>
)}
<div className='account__header__fields'> <div className='account__header__fields'>
<dl> <dl>
<dt><FormattedMessage id='account.joined_short' defaultMessage='Joined' /></dt> <dt><FormattedMessage id='account.joined_short' defaultMessage='Joined' /></dt>

View file

@ -18,6 +18,7 @@ class Header extends ImmutablePureComponent {
static propTypes = { static propTypes = {
account: ImmutablePropTypes.record, account: ImmutablePropTypes.record,
featuredTags: PropTypes.array,
onFollow: PropTypes.func.isRequired, onFollow: PropTypes.func.isRequired,
onBlock: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired,
onMention: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired,
@ -123,7 +124,7 @@ class Header extends ImmutablePureComponent {
}; };
render () { render () {
const { account, hidden, hideTabs } = this.props; const { account, featuredTags, hidden, hideTabs } = this.props;
if (account === null) { if (account === null) {
return null; return null;
@ -136,6 +137,7 @@ class Header extends ImmutablePureComponent {
<InnerHeader <InnerHeader
account={account} account={account}
featuredTags={featuredTags}
onFollow={this.handleFollow} onFollow={this.handleFollow}
onBlock={this.handleBlock} onBlock={this.handleBlock}
onMention={this.handleMention} onMention={this.handleMention}

View file

@ -37,6 +37,7 @@ const makeMapStateToProps = () => {
account: getAccount(state, accountId), account: getAccount(state, accountId),
domain: state.getIn(['meta', 'domain']), domain: state.getIn(['meta', 'domain']),
hidden: getAccountHidden(state, accountId), hidden: getAccountHidden(state, accountId),
featuredTags: state.getIn(['user_lists', 'featured_tags', accountId, 'items']),
}); });
return mapStateToProps; return mapStateToProps;