Merge branch 'main' into glitch-soc/merge-upstream
Conflicts: - `config/i18n-tasks.yml`: Upstream added new ignored strings, glitch-soc has extra ignored strings because of the theming system. Added upstream's changes.
This commit is contained in:
@@ -46,6 +46,7 @@ const messages = defineMessages({
|
||||
follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
|
||||
favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' },
|
||||
lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' },
|
||||
followed_tags: { id: 'navigation_bar.followed_tags', defaultMessage: 'Followed hashtags' },
|
||||
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
|
||||
domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Blocked domains' },
|
||||
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
||||
@@ -193,7 +194,7 @@ class Header extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
if (account.getIn(['relationship', 'requested']) || account.getIn(['relationship', 'following'])) {
|
||||
bellBtn = <IconButton icon='bell-o' size={24} active={account.getIn(['relationship', 'notifying'])} title={intl.formatMessage(account.getIn(['relationship', 'notifying']) ? messages.disableNotifications : messages.enableNotifications, { name: account.get('username') })} onClick={this.props.onNotifyToggle} />;
|
||||
bellBtn = <IconButton icon={account.getIn(['relationship', 'notifying']) ? 'bell' : 'bell-o'} size={24} active={account.getIn(['relationship', 'notifying'])} title={intl.formatMessage(account.getIn(['relationship', 'notifying']) ? messages.disableNotifications : messages.enableNotifications, { name: account.get('username') })} onClick={this.props.onNotifyToggle} />;
|
||||
}
|
||||
|
||||
if (me !== account.get('id')) {
|
||||
@@ -242,6 +243,7 @@ class Header extends ImmutablePureComponent {
|
||||
menu.push({ text: intl.formatMessage(messages.follow_requests), to: '/follow_requests' });
|
||||
menu.push({ text: intl.formatMessage(messages.favourites), to: '/favourites' });
|
||||
menu.push({ text: intl.formatMessage(messages.lists), to: '/lists' });
|
||||
menu.push({ text: intl.formatMessage(messages.followed_tags), to: '/followed_tags' });
|
||||
menu.push(null);
|
||||
menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' });
|
||||
menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' });
|
||||
|
@@ -11,6 +11,7 @@ const messages = defineMessages({
|
||||
follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
|
||||
favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' },
|
||||
lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' },
|
||||
followed_tags: { id: 'navigation_bar.followed_tags', defaultMessage: 'Followed hashtags' },
|
||||
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
|
||||
domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' },
|
||||
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
||||
@@ -45,6 +46,7 @@ class ActionBar extends React.PureComponent {
|
||||
menu.push({ text: intl.formatMessage(messages.favourites), to: '/favourites' });
|
||||
menu.push({ text: intl.formatMessage(messages.bookmarks), to: '/bookmarks' });
|
||||
menu.push({ text: intl.formatMessage(messages.lists), to: '/lists' });
|
||||
menu.push({ text: intl.formatMessage(messages.followed_tags), to: '/followed_tags' });
|
||||
menu.push(null);
|
||||
menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' });
|
||||
menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' });
|
||||
|
@@ -43,10 +43,10 @@ export default class Upload extends ImmutablePureComponent {
|
||||
<div className='compose-form__upload-thumbnail' style={{ transform: `scale(${scale})`, backgroundImage: `url(${media.get('preview_url')})`, backgroundPosition: `${x}% ${y}%` }}>
|
||||
<div className='compose-form__upload__actions'>
|
||||
<button type='button' className='icon-button' onClick={this.handleUndoClick}><Icon id='times' /> <FormattedMessage id='upload_form.undo' defaultMessage='Delete' /></button>
|
||||
{!!media.get('unattached') && (<button type='button' className='icon-button' onClick={this.handleFocalPointClick}><Icon id='pencil' /> <FormattedMessage id='upload_form.edit' defaultMessage='Edit' /></button>)}
|
||||
<button type='button' className='icon-button' onClick={this.handleFocalPointClick}><Icon id='pencil' /> <FormattedMessage id='upload_form.edit' defaultMessage='Edit' /></button>
|
||||
</div>
|
||||
|
||||
{(media.get('description') || '').length === 0 && !!media.get('unattached') && (
|
||||
{(media.get('description') || '').length === 0 && (
|
||||
<div className='compose-form__upload__warning'>
|
||||
<button type='button' className='icon-button' onClick={this.handleFocalPointClick}><Icon id='info-circle' /> <FormattedMessage id='upload_form.description_missing' defaultMessage='No description added' /></button>
|
||||
</div>
|
||||
|
89
app/javascript/mastodon/features/followed_tags/index.js
Normal file
89
app/javascript/mastodon/features/followed_tags/index.js
Normal file
@@ -0,0 +1,89 @@
|
||||
import { debounce } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
import ColumnHeader from 'mastodon/components/column_header';
|
||||
import ScrollableList from 'mastodon/components/scrollable_list';
|
||||
import Column from 'mastodon/features/ui/components/column';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import Hashtag from 'mastodon/components/hashtag';
|
||||
import { expandFollowedHashtags, fetchFollowedHashtags } from 'mastodon/actions/tags';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'followed_tags', defaultMessage: 'Followed hashtags' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
hashtags: state.getIn(['followed_tags', 'items']),
|
||||
isLoading: state.getIn(['followed_tags', 'isLoading'], true),
|
||||
hasMore: !!state.getIn(['followed_tags', 'next']),
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class FollowedTags extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
hashtags: ImmutablePropTypes.list,
|
||||
isLoading: PropTypes.bool,
|
||||
hasMore: PropTypes.bool,
|
||||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.props.dispatch(fetchFollowedHashtags());
|
||||
};
|
||||
|
||||
handleLoadMore = debounce(() => {
|
||||
this.props.dispatch(expandFollowedHashtags());
|
||||
}, 300, { leading: true });
|
||||
|
||||
render () {
|
||||
const { intl, hashtags, isLoading, hasMore, multiColumn } = this.props;
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.followed_tags' defaultMessage='You have not followed any hashtags yet. When you do, they will show up here.' />;
|
||||
|
||||
return (
|
||||
<Column bindToDocument={!multiColumn}>
|
||||
<ColumnHeader
|
||||
icon='hashtag'
|
||||
title={intl.formatMessage(messages.heading)}
|
||||
showBackButton
|
||||
multiColumn={multiColumn}
|
||||
/>
|
||||
|
||||
<ScrollableList
|
||||
scrollKey='followed_tags'
|
||||
emptyMessage={emptyMessage}
|
||||
hasMore={hasMore}
|
||||
isLoading={isLoading}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
bindToDocument={!multiColumn}
|
||||
>
|
||||
{hashtags.map((hashtag) => (
|
||||
<Hashtag
|
||||
key={hashtag.get('name')}
|
||||
name={hashtag.get('name')}
|
||||
to={`/tags/${hashtag.get('name')}`}
|
||||
withGraph={false}
|
||||
// Taken from ImmutableHashtag. Should maybe refactor ImmutableHashtag to accept more options?
|
||||
people={hashtag.getIn(['history', 0, 'accounts']) * 1 + hashtag.getIn(['history', 1, 'accounts']) * 1}
|
||||
history={hashtag.get('history').reverse().map((day) => day.get('uses')).toArray()}
|
||||
/>
|
||||
))}
|
||||
</ScrollableList>
|
||||
|
||||
<Helmet>
|
||||
<meta name='robots' content='noindex' />
|
||||
</Helmet>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@@ -320,7 +320,7 @@ class FocalPointModal extends ImmutablePureComponent {
|
||||
<React.Fragment>
|
||||
<label className='setting-text-label' htmlFor='upload-modal__thumbnail'><FormattedMessage id='upload_form.thumbnail' defaultMessage='Change thumbnail' /></label>
|
||||
|
||||
<Button disabled={isUploadingThumbnail} text={intl.formatMessage(messages.chooseImage)} onClick={this.handleFileInputClick} />
|
||||
<Button disabled={isUploadingThumbnail || !media.get('unattached')} text={intl.formatMessage(messages.chooseImage)} onClick={this.handleFileInputClick} />
|
||||
|
||||
<label>
|
||||
<span style={{ display: 'none' }}>{intl.formatMessage(messages.chooseImage)}</span>
|
||||
|
@@ -30,7 +30,7 @@ const SignInBanner = () => {
|
||||
|
||||
return (
|
||||
<div className='sign-in-banner'>
|
||||
<p><FormattedMessage id='sign_in_banner.text' defaultMessage='Sign in to follow profiles or hashtags, favourite, share and reply to posts, or interact from your account on a different server.' /></p>
|
||||
<p><FormattedMessage id='sign_in_banner.text' defaultMessage='Sign in to follow profiles or hashtags, favourite, share and reply to posts. You can also interact from your account on a different server.' /></p>
|
||||
<a href='/auth/sign_in' className='button button--block'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' /></a>
|
||||
{signupButton}
|
||||
</div>
|
||||
|
@@ -42,6 +42,7 @@ import {
|
||||
FollowRequests,
|
||||
FavouritedStatuses,
|
||||
BookmarkedStatuses,
|
||||
FollowedTags,
|
||||
ListTimeline,
|
||||
Blocks,
|
||||
DomainBlocks,
|
||||
@@ -54,7 +55,7 @@ import {
|
||||
About,
|
||||
PrivacyPolicy,
|
||||
} from './util/async-components';
|
||||
import initialState, { me, owner, singleUserMode, showTrends } from '../../initial_state';
|
||||
import initialState, { me, owner, singleUserMode, showTrends, trendsAsLanding } from '../../initial_state';
|
||||
import { closeOnboarding, INTRODUCTION_VERSION } from 'mastodon/actions/onboarding';
|
||||
import Header from './components/header';
|
||||
|
||||
@@ -163,7 +164,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
||||
}
|
||||
} else if (singleUserMode && owner && initialState?.accounts[owner]) {
|
||||
redirect = <Redirect from='/' to={`/@${initialState.accounts[owner].username}`} exact />;
|
||||
} else if (showTrends) {
|
||||
} else if (showTrends && trendsAsLanding) {
|
||||
redirect = <Redirect from='/' to='/explore' exact />;
|
||||
} else {
|
||||
redirect = <Redirect from='/' to='/about' exact />;
|
||||
@@ -216,6 +217,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
||||
<WrappedRoute path='/follow_requests' component={FollowRequests} content={children} />
|
||||
<WrappedRoute path='/blocks' component={Blocks} content={children} />
|
||||
<WrappedRoute path='/domain_blocks' component={DomainBlocks} content={children} />
|
||||
<WrappedRoute path='/followed_tags' component={FollowedTags} content={children} />
|
||||
<WrappedRoute path='/mutes' component={Mutes} content={children} />
|
||||
<WrappedRoute path='/lists' component={Lists} content={children} />
|
||||
|
||||
|
@@ -90,6 +90,10 @@ export function FavouritedStatuses () {
|
||||
return import(/* webpackChunkName: "features/favourited_statuses" */'../../favourited_statuses');
|
||||
}
|
||||
|
||||
export function FollowedTags () {
|
||||
return import(/* webpackChunkName: "features/followed_tags" */'../../followed_tags');
|
||||
}
|
||||
|
||||
export function BookmarkedStatuses () {
|
||||
return import(/* webpackChunkName: "features/bookmarked_statuses" */'../../bookmarked_statuses');
|
||||
}
|
||||
|
Reference in New Issue
Block a user