diff --git a/app/actions/views/channel.js b/app/actions/views/channel.js index f1aa434ab..e6967a154 100644 --- a/app/actions/views/channel.js +++ b/app/actions/views/channel.js @@ -331,3 +331,10 @@ export function setChannelLoading(loading = true) { loading }; } + +export function setChannelRefreshing(refreshing = true) { + return { + type: ViewTypes.SET_CHANNEL_REFRESHING, + refreshing + }; +} diff --git a/app/components/post_list/index.js b/app/components/post_list/index.js index 0f02eaf7d..26d1c333a 100644 --- a/app/components/post_list/index.js +++ b/app/components/post_list/index.js @@ -1,18 +1,32 @@ // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. +import {bindActionCreators} from 'redux'; import {connect} from 'react-redux'; +import {loadPostsIfNecessary, setChannelRefreshing} from 'app/actions/views/channel'; import {getTheme} from 'app/selectors/preferences'; import PostList from './post_list'; function mapStateToProps(state, ownProps) { + const {loading, refreshing} = state.views.channel; + return { ...ownProps, - channelIsLoading: state.views.channel.loading, + channelIsLoading: loading, + refreshing, theme: getTheme(state) }; } -export default connect(mapStateToProps)(PostList); +function mapDispatchToProps(dispatch) { + return { + actions: bindActionCreators({ + loadPostsIfNecessary, + setChannelRefreshing + }, dispatch) + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(PostList); diff --git a/app/components/post_list/post_list.js b/app/components/post_list/post_list.js index 24ea8f1e9..f50348ce8 100644 --- a/app/components/post_list/post_list.js +++ b/app/components/post_list/post_list.js @@ -5,9 +5,10 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; import { ListView, - StyleSheet, + RefreshControl, View } from 'react-native'; +import InvertibleScrollView from 'react-native-invertible-scroll-view'; import {General, Posts} from 'mattermost-redux/constants'; import {addDatesToPostList} from 'mattermost-redux/utils/post_utils'; @@ -22,6 +23,10 @@ const LOAD_MORE_POSTS = 'load-more-posts'; export default class PostList extends Component { static propTypes = { + actions: PropTypes.shape({ + loadPostsIfNecessary: PropTypes.func.isRequired, + setChannelRefreshing: PropTypes.func.isRequired + }).isRequired, channel: PropTypes.object, channelIsLoading: PropTypes.bool.isRequired, posts: PropTypes.array.isRequired, @@ -31,6 +36,7 @@ export default class PostList extends Component { isLoadingMore: PropTypes.bool, showLoadMore: PropTypes.bool, onPostPress: PropTypes.func, + refreshing: PropTypes.bool, renderReplies: PropTypes.bool, indicateNewMessages: PropTypes.bool, currentUserId: PropTypes.string, @@ -53,6 +59,7 @@ export default class PostList extends Component { componentWillReceiveProps(nextProps) { if (nextProps.posts !== this.props.posts) { + this.props.actions.setChannelRefreshing(false); const posts = this.getPostsWithDates(nextProps); this.setState({posts}); } @@ -79,6 +86,15 @@ export default class PostList extends Component { } }; + onRefresh = () => { + const {actions, channel} = this.props; + + if (Object.keys(channel).length) { + actions.setChannelRefreshing(true); + actions.loadPostsIfNecessary(channel); + } + }; + renderChannelIntro = () => { const {channel, channelIsLoading, posts} = this.props; @@ -90,7 +106,7 @@ export default class PostList extends Component { } return ( - + ); @@ -107,7 +123,6 @@ export default class PostList extends Component { return ( ); } @@ -116,7 +131,6 @@ export default class PostList extends Component { ); } @@ -128,7 +142,6 @@ export default class PostList extends Component { return ( ); @@ -137,7 +150,6 @@ export default class PostList extends Component { renderPost = (post) => { return ( { + const {theme, refreshing} = this.props; + + return ( + + ); + }; + + renderScrollComponent = (props) => { + return ( + + ); + }; + render() { + const {dataSource} = this.state; + return ( ); } } - -const style = StyleSheet.create({ - container: { - transform: [{rotate: '180deg'}] - }, - row: { - transform: [{rotate: '180deg'}] - } -}); diff --git a/app/constants/view.js b/app/constants/view.js index 6851ccf95..d499388ee 100644 --- a/app/constants/view.js +++ b/app/constants/view.js @@ -34,6 +34,7 @@ const ViewTypes = keyMirror({ ADD_FILE_TO_FETCH_CACHE: null, SET_CHANNEL_LOADER: null, + SET_CHANNEL_REFRESHING: null, SET_LAST_CHANNEL_FOR_TEAM: null, diff --git a/app/reducers/views/channel.js b/app/reducers/views/channel.js index 51579994b..e2abdf8ba 100644 --- a/app/reducers/views/channel.js +++ b/app/reducers/views/channel.js @@ -172,7 +172,17 @@ function loading(state = false, action) { } } +function refreshing(state = false, action) { + switch (action.type) { + case ViewTypes.SET_CHANNEL_REFRESHING: + return action.refreshing; + default: + return state; + } +} + export default combineReducers({ drafts, - loading + loading, + refreshing }); diff --git a/app/screens/channel/channel_post_list/channel_post_list.js b/app/screens/channel/channel_post_list/channel_post_list.js index e0d607892..2e856ec06 100644 --- a/app/screens/channel/channel_post_list/channel_post_list.js +++ b/app/screens/channel/channel_post_list/channel_post_list.js @@ -29,6 +29,7 @@ class ChannelPostList extends PureComponent { applicationInitializing: PropTypes.bool.isRequired, channel: PropTypes.object.isRequired, channelIsLoading: PropTypes.bool, + channelIsRefreshing: PropTypes.bool, intl: intlShape.isRequired, myMember: PropTypes.object.isRequired, navigator: PropTypes.object, @@ -147,6 +148,7 @@ class ChannelPostList extends PureComponent { applicationInitializing, channel, channelIsLoading, + channelIsRefreshing, navigator, posts, postsRequests, @@ -162,7 +164,7 @@ class ChannelPostList extends PureComponent { theme={theme} /> ); - } else if (!applicationInitializing && !channelIsLoading && posts && (postsRequests.getPosts.status !== RequestStatus.STARTED || !this.state.didInitialPostsLoad)) { + } else if (!applicationInitializing && !channelIsLoading && posts && (postsRequests.getPosts.status !== RequestStatus.STARTED || channelIsRefreshing || !this.state.didInitialPostsLoad)) { component = (