diff options
author | Takeshi Umeda <noel.yoshiba@gmail.com> | 2022-10-16 15:43:59 +0900 |
---|---|---|
committer | Claire <claire.github-309c@sitedethib.com> | 2022-10-28 19:24:02 +0200 |
commit | 8be350cc82cbe2d7befad8be2768e614be52ade4 (patch) | |
tree | 4df8ea94b54170f2fc2c94740c5408e64fe6328d /app/javascript/flavours/glitch/features | |
parent | a2942fd0b89a0adaf86231d0d580f695738f700c (diff) |
[Glitch] Add featured tags selector for WebUI
Port 4c7b5fb6c1787438ef130d9aecd5d0a4d54d08a9 to glitch-soc Signed-off-by: Claire <claire.github-309c@sitedethib.com>
Diffstat (limited to 'app/javascript/flavours/glitch/features')
4 files changed, 92 insertions, 10 deletions
diff --git a/app/javascript/flavours/glitch/features/account/components/featured_tags.js b/app/javascript/flavours/glitch/features/account/components/featured_tags.js new file mode 100644 index 000000000..a273d8fc6 --- /dev/null +++ b/app/javascript/flavours/glitch/features/account/components/featured_tags.js @@ -0,0 +1,71 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { defineMessages, injectIntl } from 'react-intl'; +import classNames from 'classnames'; +import Permalink from 'flavours/glitch/components/permalink'; +import ShortNumber from 'flavours/glitch/components/short_number'; +import { List as ImmutableList } from 'immutable'; + +const messages = defineMessages({ + hashtag_all: { id: 'account.hashtag_all', defaultMessage: 'All' }, + hashtag_all_description: { id: 'account.hashtag_all_description', defaultMessage: 'All posts (deselect hashtags)' }, + hashtag_select_description: { id: 'account.hashtag_select_description', defaultMessage: 'Select hashtag #{name}' }, + statuses_counter: { id: 'account.statuses_counter', defaultMessage: '{count, plural, one {{counter} Post} other {{counter} Posts}}' }, +}); + +const mapStateToProps = (state, { account }) => ({ + featuredTags: state.getIn(['user_lists', 'featured_tags', account.get('id'), 'items'], ImmutableList()), +}); + +export default @connect(mapStateToProps) +@injectIntl +class FeaturedTags extends ImmutablePureComponent { + + static contextTypes = { + router: PropTypes.object, + }; + + static propTypes = { + account: ImmutablePropTypes.map, + featuredTags: ImmutablePropTypes.list, + tagged: PropTypes.string, + intl: PropTypes.object.isRequired, + }; + + render () { + const { account, featuredTags, tagged, intl } = this.props; + + if (!account || featuredTags.isEmpty()) { + return null; + } + + const suspended = account.get('suspended'); + + return ( + <div className={classNames('account__header', 'advanced', { inactive: !!account.get('moved') })}> + <div className='account__header__extra'> + <div className='account__header__extra__hashtag-links'> + <Permalink key='all' className={classNames('account__hashtag-link', { active: !tagged })} title={intl.formatMessage(messages.hashtag_all_description)} href={account.get('url')} to={`/@${account.get('acct')}`}>{intl.formatMessage(messages.hashtag_all)}</Permalink> + {!suspended && featuredTags.map(featuredTag => { + const name = featuredTag.get('name'); + const url = featuredTag.get('url'); + const to = `/@${account.get('acct')}/tagged/${name}`; + const desc = intl.formatMessage(messages.hashtag_select_description, { name }); + const count = featuredTag.get('statuses_count'); + + return ( + <Permalink key={`#${name}`} className={classNames('account__hashtag-link', { active: this.context.router.history.location.pathname === to })} title={desc} href={url} to={to}> + #{name} <span title={intl.formatMessage(messages.statuses_counter, { count: count, counter: intl.formatNumber(count) })}>({<ShortNumber value={count} />})</span> + </Permalink> + ); + })} + </div> + </div> + </div> + ); + } + +} diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/header.js b/app/javascript/flavours/glitch/features/account_timeline/components/header.js index eb332e296..3a4008310 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/components/header.js +++ b/app/javascript/flavours/glitch/features/account_timeline/components/header.js @@ -28,6 +28,7 @@ export default class Header extends ImmutablePureComponent { hideTabs: PropTypes.bool, domain: PropTypes.string.isRequired, hidden: PropTypes.bool, + tagged: PropTypes.string, }; static contextTypes = { @@ -103,7 +104,7 @@ export default class Header extends ImmutablePureComponent { } render () { - const { account, hidden, hideTabs } = this.props; + const { account, hidden, hideTabs, tagged } = this.props; if (account === null) { return null; diff --git a/app/javascript/flavours/glitch/features/account_timeline/index.js b/app/javascript/flavours/glitch/features/account_timeline/index.js index 6d4ebd341..b735af0ac 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/index.js +++ b/app/javascript/flavours/glitch/features/account_timeline/index.js @@ -18,10 +18,11 @@ import TimelineHint from 'flavours/glitch/components/timeline_hint'; import LimitedAccountHint from './components/limited_account_hint'; import { getAccountHidden } from 'flavours/glitch/selectors'; import { normalizeForLookup } from 'flavours/glitch/reducers/accounts_map'; +import { fetchFeaturedTags } from '../../actions/featured_tags'; const emptyList = ImmutableList(); -const mapStateToProps = (state, { params: { acct, id }, withReplies = false }) => { +const mapStateToProps = (state, { params: { acct, id, tagged }, withReplies = false }) => { const accountId = id || state.getIn(['accounts_map', normalizeForLookup(acct)]); if (!accountId) { @@ -31,7 +32,7 @@ const mapStateToProps = (state, { params: { acct, id }, withReplies = false }) = }; } - const path = withReplies ? `${accountId}:with_replies` : accountId; + const path = withReplies ? `${accountId}:with_replies` : `${accountId}${tagged ? `:${tagged}` : ''}`; return { accountId, @@ -39,7 +40,7 @@ const mapStateToProps = (state, { params: { acct, id }, withReplies = false }) = remoteUrl: state.getIn(['accounts', accountId, 'url']), isAccount: !!state.getIn(['accounts', accountId]), statusIds: state.getIn(['timelines', `account:${path}`, 'items'], ImmutableList()), - featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned`, 'items'], ImmutableList()), + featuredStatusIds: withReplies ? ImmutableList() : state.getIn(['timelines', `account:${accountId}:pinned${tagged ? `:${tagged}` : ''}`, 'items'], ImmutableList()), isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']), hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']), suspended: state.getIn(['accounts', accountId, 'suspended'], false), @@ -62,6 +63,7 @@ class AccountTimeline extends ImmutablePureComponent { params: PropTypes.shape({ acct: PropTypes.string, id: PropTypes.string, + tagged: PropTypes.string, }).isRequired, accountId: PropTypes.string, dispatch: PropTypes.func.isRequired, @@ -79,14 +81,16 @@ class AccountTimeline extends ImmutablePureComponent { }; _load () { - const { accountId, withReplies, dispatch } = this.props; + const { accountId, withReplies, params: { tagged }, dispatch } = this.props; dispatch(fetchAccount(accountId)); if (!withReplies) { - dispatch(expandAccountFeaturedTimeline(accountId)); + dispatch(expandAccountFeaturedTimeline(accountId, { tagged })); } - dispatch(expandAccountTimeline(accountId, { withReplies })); + + dispatch(fetchFeaturedTags(accountId)); + dispatch(expandAccountTimeline(accountId, { withReplies, tagged })); } componentDidMount () { @@ -100,12 +104,17 @@ class AccountTimeline extends ImmutablePureComponent { } componentDidUpdate (prevProps) { - const { params: { acct }, accountId, dispatch } = this.props; + const { params: { acct, tagged }, accountId, withReplies, dispatch } = this.props; if (prevProps.accountId !== accountId && accountId) { this._load(); } else if (prevProps.params.acct !== acct) { dispatch(lookupAccount(acct)); + } else if (prevProps.params.tagged !== tagged) { + if (!withReplies) { + dispatch(expandAccountFeaturedTimeline(accountId, { tagged })); + } + dispatch(expandAccountTimeline(accountId, { withReplies, tagged })); } } @@ -128,7 +137,7 @@ class AccountTimeline extends ImmutablePureComponent { } handleLoadMore = maxId => { - this.props.dispatch(expandAccountTimeline(this.props.accountId, { maxId, withReplies: this.props.withReplies })); + this.props.dispatch(expandAccountTimeline(this.props.accountId, { maxId, withReplies: this.props.withReplies, tagged: this.props.params.tagged })); } setRef = c => { @@ -174,7 +183,7 @@ class AccountTimeline extends ImmutablePureComponent { <ProfileColumnHeader onClick={this.handleHeaderClick} multiColumn={multiColumn} /> <StatusList - prepend={<HeaderContainer accountId={this.props.accountId} hideTabs={forceEmptyState} />} + prepend={<HeaderContainer accountId={this.props.accountId} hideTabs={forceEmptyState} tagged={this.props.params.tagged} />} alwaysPrepend append={remoteMessage} scrollKey='account_timeline' diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js index 164c475cc..3d385eee2 100644 --- a/app/javascript/flavours/glitch/features/ui/index.js +++ b/app/javascript/flavours/glitch/features/ui/index.js @@ -211,6 +211,7 @@ class SwitchingColumnsArea extends React.PureComponent { <WrappedRoute path={['/publish', '/statuses/new']} component={Compose} content={children} /> <WrappedRoute path={['/@:acct', '/accounts/:id']} exact component={AccountTimeline} content={children} /> + <WrappedRoute path='/@:acct/tagged/:tagged?' exact component={AccountTimeline} content={children} /> <WrappedRoute path={['/@:acct/with_replies', '/accounts/:id/with_replies']} component={AccountTimeline} content={children} componentParams={{ withReplies: true }} /> <WrappedRoute path={['/accounts/:id/followers', '/users/:acct/followers', '/@:acct/followers']} component={Followers} content={children} /> <WrappedRoute path={['/accounts/:id/following', '/users/:acct/following', '/@:acct/following']} component={Following} content={children} /> |