diff --git a/app/javascript/mastodon/features/compose/containers/search_results_container.js b/app/javascript/mastodon/features/compose/containers/search_results_container.js
index 7273460e28..2f879f9d96 100644
--- a/app/javascript/mastodon/features/compose/containers/search_results_container.js
+++ b/app/javascript/mastodon/features/compose/containers/search_results_container.js
@@ -4,7 +4,7 @@ import { fetchTrends } from '../../../actions/trends';
const mapStateToProps = state => ({
results: state.getIn(['search', 'results']),
- trends: state.get('trends'),
+ trends: state.getIn(['trends', 'items']),
});
const mapDispatchToProps = dispatch => ({
diff --git a/app/javascript/mastodon/features/getting_started/components/trends.js b/app/javascript/mastodon/features/getting_started/components/trends.js
new file mode 100644
index 0000000000..5d6b7ed8cd
--- /dev/null
+++ b/app/javascript/mastodon/features/getting_started/components/trends.js
@@ -0,0 +1,58 @@
+import classNames from 'classnames';
+import React from 'react';
+import ImmutablePureComponent from 'react-immutable-pure-component';
+import PropTypes from 'prop-types';
+import ImmutablePropTypes from 'react-immutable-proptypes';
+import { FormattedMessage, defineMessages } from 'react-intl';
+import Hashtag from '../../../components/hashtag';
+
+const messages = defineMessages({
+ refresh_trends: { id: 'trends.refresh', defaultMessage: 'Refresh' },
+});
+
+export default class Trends extends ImmutablePureComponent {
+
+ static defaultProps = {
+ loading: false,
+ };
+
+ static propTypes = {
+ trends: ImmutablePropTypes.list,
+ loading: PropTypes.bool.isRequired,
+ };
+
+ componentDidMount () {
+ setTimeout(() => this.props.fetchTrends(), 5000);
+ }
+
+ handleRefreshTrends = () => {
+ this.props.fetchTrends();
+ }
+
+ render () {
+ const { intl, trends, loading } = this.props;
+
+ if (!trends || trends.size < 1) {
+ return null;
+ }
+
+ return (
+
+
+
+
{trends.take(3).map(hashtag => )}
+
+ );
+ }
+
+}
diff --git a/app/javascript/mastodon/features/getting_started/containers/trends_container.js b/app/javascript/mastodon/features/getting_started/containers/trends_container.js
new file mode 100644
index 0000000000..549556b76e
--- /dev/null
+++ b/app/javascript/mastodon/features/getting_started/containers/trends_container.js
@@ -0,0 +1,15 @@
+import { connect } from 'react-redux';
+import { injectIntl } from 'react-intl';
+import { fetchTrends } from '../../../actions/trends';
+import Trends from '../components/trends';
+
+const mapStateToProps = state => ({
+ trends: state.getIn(['trends', 'items']),
+ loading: state.getIn(['trends', 'isLoading']),
+});
+
+const mapDispatchToProps = dispatch => ({
+ fetchTrends: () => dispatch(fetchTrends()),
+});
+
+export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(Trends));
diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js
index da19096533..9575afd7ab 100644
--- a/app/javascript/mastodon/features/getting_started/index.js
+++ b/app/javascript/mastodon/features/getting_started/index.js
@@ -11,9 +11,8 @@ import { me } from '../../initial_state';
import { fetchFollowRequests } from '../../actions/accounts';
import { List as ImmutableList } from 'immutable';
import { Link } from 'react-router-dom';
-import { fetchTrends } from '../../actions/trends';
-import Hashtag from '../../components/hashtag';
import NavigationBar from '../compose/components/navigation_bar';
+import TrendsContainer from './containers/trends_container';
const messages = defineMessages({
home_timeline: { id: 'tabs_bar.home', defaultMessage: 'Home' },
@@ -30,7 +29,6 @@ const messages = defineMessages({
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned toots' },
lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' },
- refresh_trends: { id: 'trends.refresh', defaultMessage: 'Refresh' },
discover: { id: 'navigation_bar.discover', defaultMessage: 'Discover' },
personal: { id: 'navigation_bar.personal', defaultMessage: 'Personal' },
security: { id: 'navigation_bar.security', defaultMessage: 'Security' },
@@ -39,12 +37,10 @@ const messages = defineMessages({
const mapStateToProps = state => ({
myAccount: state.getIn(['accounts', me]),
unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
- trends: state.get('trends'),
});
const mapDispatchToProps = dispatch => ({
fetchFollowRequests: () => dispatch(fetchFollowRequests()),
- fetchTrends: () => dispatch(fetchTrends()),
});
const badgeDisplay = (number, limit) => {
@@ -69,7 +65,6 @@ export default class GettingStarted extends ImmutablePureComponent {
fetchFollowRequests: PropTypes.func.isRequired,
unreadFollowRequests: PropTypes.number,
unreadNotifications: PropTypes.number,
- trends: ImmutablePropTypes.list,
};
componentDidMount () {
@@ -78,16 +73,10 @@ export default class GettingStarted extends ImmutablePureComponent {
if (myAccount.get('locked')) {
fetchFollowRequests();
}
-
- setTimeout(() => this.props.fetchTrends(), 5000);
- }
-
- handleRefreshTrends = () => {
- this.props.fetchTrends();
}
render () {
- const { intl, myAccount, multiColumn, unreadFollowRequests, trends } = this.props;
+ const { intl, myAccount, multiColumn, unreadFollowRequests } = this.props;
const navItems = [];
let i = 1;
@@ -135,21 +124,7 @@ export default class GettingStarted extends ImmutablePureComponent {
{navItems}
- {multiColumn && trends &&
-
-
-
{trends.take(3).map(hashtag => )}
-
}
+ {multiColumn && }
{!multiColumn && }
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index d8a115a768..c710e1270d 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -1036,6 +1036,19 @@
],
"path": "app/javascript/mastodon/features/follow_requests/index.json"
},
+ {
+ "descriptors": [
+ {
+ "defaultMessage": "Refresh",
+ "id": "trends.refresh"
+ },
+ {
+ "defaultMessage": "Trending now",
+ "id": "trends.header"
+ }
+ ],
+ "path": "app/javascript/mastodon/features/getting_started/components/trends.json"
+ },
{
"descriptors": [
{
@@ -1094,10 +1107,6 @@
"defaultMessage": "Lists",
"id": "navigation_bar.lists"
},
- {
- "defaultMessage": "Refresh",
- "id": "trends.refresh"
- },
{
"defaultMessage": "Discover",
"id": "navigation_bar.discover"
@@ -1114,10 +1123,6 @@
"defaultMessage": "Getting started",
"id": "getting_started.heading"
},
- {
- "defaultMessage": "Trending now",
- "id": "trends.header"
- },
{
"defaultMessage": "Hotkeys",
"id": "navigation_bar.keyboard_shortcuts"
diff --git a/app/javascript/mastodon/reducers/trends.js b/app/javascript/mastodon/reducers/trends.js
index 95cf8f2841..5cecc8fcab 100644
--- a/app/javascript/mastodon/reducers/trends.js
+++ b/app/javascript/mastodon/reducers/trends.js
@@ -1,12 +1,22 @@
-import { TRENDS_FETCH_SUCCESS } from '../actions/trends';
-import { fromJS } from 'immutable';
+import { TRENDS_FETCH_REQUEST, TRENDS_FETCH_SUCCESS, TRENDS_FETCH_FAIL } from '../actions/trends';
+import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
-const initialState = null;
+const initialState = ImmutableMap({
+ items: ImmutableList(),
+ isLoading: false,
+});
export default function trendsReducer(state = initialState, action) {
switch(action.type) {
+ case TRENDS_FETCH_REQUEST:
+ return state.set('isLoading', true);
case TRENDS_FETCH_SUCCESS:
- return fromJS(action.trends);
+ return state.withMutations(map => {
+ map.set('items', fromJS(action.trends));
+ map.set('isLoading', false);
+ });
+ case TRENDS_FETCH_FAIL:
+ return state.set('isLoading', false);
default:
return state;
}