Add loading indicator for trending tags (#7693)
This commit is contained in:
		
							parent
							
								
									bfa12239e8
								
							
						
					
					
						commit
						69b45350fe
					
				| @ -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 => ({ | ||||
|  | ||||
| @ -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 ( | ||||
|       <div className='getting-started__trends'> | ||||
|         <div className='column-header__wrapper'> | ||||
|           <h1 className='column-header'> | ||||
|             <button> | ||||
|               <i className='fa fa-fire fa-fw' /> | ||||
|               <FormattedMessage id='trends.header' defaultMessage='Trending now' /> | ||||
|             </button> | ||||
|             <div className='column-header__buttons'> | ||||
|               <button onClick={this.handleRefreshTrends} className='column-header__button' title={intl.formatMessage(messages.refresh_trends)} aria-label={intl.formatMessage(messages.refresh_trends)} disabled={loading}><i className={classNames('fa', 'fa-refresh', { 'fa-spin': loading })} /></button> | ||||
|             </div> | ||||
|           </h1> | ||||
|         </div> | ||||
| 
 | ||||
|         <div className='getting-started__scrollable'>{trends.take(3).map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)}</div> | ||||
|       </div> | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| @ -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)); | ||||
| @ -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} | ||||
|         </div> | ||||
| 
 | ||||
|         {multiColumn && trends && <div className='getting-started__trends'> | ||||
|           <div className='column-header__wrapper'> | ||||
|             <h1 className='column-header'> | ||||
|               <button> | ||||
|                 <i className='fa fa-fire fa-fw' /> | ||||
|                 <FormattedMessage id='trends.header' defaultMessage='Trending now' /> | ||||
|               </button> | ||||
|               <div className='column-header__buttons'> | ||||
|                 <button onClick={this.handleRefreshTrends} className='column-header__button' title={intl.formatMessage(messages.refresh_trends)} aria-label={intl.formatMessage(messages.refresh_trends)}><i className='fa fa-refresh' /></button> | ||||
|               </div> | ||||
|             </h1> | ||||
|           </div> | ||||
| 
 | ||||
|           <div className='getting-started__scrollable'>{trends.take(3).map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)}</div> | ||||
|         </div>} | ||||
|         {multiColumn && <TrendsContainer />} | ||||
| 
 | ||||
|         {!multiColumn && <div className='flex-spacer' />} | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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; | ||||
|   } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user