From 42a53b4c9d1b13d1478b2dc5ba7e6de070dea729 Mon Sep 17 00:00:00 2001 From: Djorkaeff Alexandre Date: Tue, 11 Feb 2020 17:13:44 -0300 Subject: [PATCH] [NEW] Pull to refresh RoomsList (#1701) --- app/actions/actionsTypes.js | 1 + app/actions/rooms.js | 11 +++++++++-- app/reducers/rooms.js | 11 ++++++++++- app/sagas/rooms.js | 17 +++++++++++------ app/views/RoomView/List.js | 12 +++++++++--- app/views/RoomsListView/index.js | 28 +++++++++++++++++++++++----- 6 files changed, 63 insertions(+), 17 deletions(-) diff --git a/app/actions/actionsTypes.js b/app/actions/actionsTypes.js index 15718b171..ad8964391 100644 --- a/app/actions/actionsTypes.js +++ b/app/actions/actionsTypes.js @@ -22,6 +22,7 @@ export const SHARE = createRequestTypes('SHARE', [ export const USER = createRequestTypes('USER', ['SET']); export const ROOMS = createRequestTypes('ROOMS', [ ...defaultTypes, + 'REFRESH', 'SET_SEARCH', 'CLOSE_SERVER_DROPDOWN', 'TOGGLE_SERVER_DROPDOWN', diff --git a/app/actions/rooms.js b/app/actions/rooms.js index 098237187..a37c17cae 100644 --- a/app/actions/rooms.js +++ b/app/actions/rooms.js @@ -1,9 +1,10 @@ import * as types from './actionsTypes'; -export function roomsRequest() { +export function roomsRequest(params = { allData: false }) { return { - type: types.ROOMS.REQUEST + type: types.ROOMS.REQUEST, + params }; } @@ -20,6 +21,12 @@ export function roomsFailure(err) { }; } +export function roomsRefresh() { + return { + type: types.ROOMS.REFRESH + }; +} + export function setSearch(searchText) { return { type: types.ROOMS.SET_SEARCH, diff --git a/app/reducers/rooms.js b/app/reducers/rooms.js index 5903c0891..6b6914fe9 100644 --- a/app/reducers/rooms.js +++ b/app/reducers/rooms.js @@ -2,6 +2,7 @@ import * as types from '../actions/actionsTypes'; const initialState = { isFetching: false, + refreshing: false, failure: false, errorMessage: {}, searchText: '', @@ -23,15 +24,23 @@ export default function login(state = initialState, action) { case types.ROOMS.SUCCESS: return { ...state, - isFetching: false + isFetching: false, + refreshing: false }; case types.ROOMS.FAILURE: return { ...state, isFetching: false, + refreshing: false, failure: true, errorMessage: action.err }; + case types.ROOMS.REFRESH: + return { + ...state, + isFetching: true, + refreshing: true + }; case types.ROOMS.SET_SEARCH: return { ...state, diff --git a/app/sagas/rooms.js b/app/sagas/rooms.js index 641a75e53..02f989d54 100644 --- a/app/sagas/rooms.js +++ b/app/sagas/rooms.js @@ -6,7 +6,7 @@ import { Q } from '@nozbe/watermelondb'; import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import * as types from '../actions/actionsTypes'; -import { roomsSuccess, roomsFailure } from '../actions/rooms'; +import { roomsSuccess, roomsFailure, roomsRefresh } from '../actions/rooms'; import database from '../lib/database'; import log from '../utils/log'; import mergeSubscriptionsRooms from '../lib/methods/helpers/mergeSubscriptionsRooms'; @@ -26,15 +26,20 @@ const updateRooms = function* updateRooms({ server, newRoomsUpdatedAt }) { }); }; -const handleRoomsRequest = function* handleRoomsRequest() { +const handleRoomsRequest = function* handleRoomsRequest({ params }) { try { const serversDB = database.servers; - yield RocketChat.subscribeRooms(); + RocketChat.subscribeRooms(); const newRoomsUpdatedAt = new Date(); + let roomsUpdatedAt; const server = yield select(state => state.server.server); - const serversCollection = serversDB.collections.get('servers'); - const serverRecord = yield serversCollection.find(server); - const { roomsUpdatedAt } = serverRecord; + if (params.allData) { + yield put(roomsRefresh()); + } else { + const serversCollection = serversDB.collections.get('servers'); + const serverRecord = yield serversCollection.find(server); + ({ roomsUpdatedAt } = serverRecord); + } const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt); const { subscriptions } = mergeSubscriptionsRooms(subscriptionsResult, roomsResult); diff --git a/app/views/RoomView/List.js b/app/views/RoomView/List.js index 1d4d8e248..c39e32e63 100644 --- a/app/views/RoomView/List.js +++ b/app/views/RoomView/List.js @@ -1,5 +1,5 @@ import React from 'react'; -import { FlatList, InteractionManager } from 'react-native'; +import { FlatList, InteractionManager, RefreshControl } from 'react-native'; import PropTypes from 'prop-types'; import orderBy from 'lodash/orderBy'; import { Q } from '@nozbe/watermelondb'; @@ -15,6 +15,7 @@ import { isIOS } from '../../utils/deviceInfo'; import { animateNextTransition } from '../../utils/layoutAnimation'; import ActivityIndicator from '../../containers/ActivityIndicator'; import debounce from '../../utils/debounce'; +import { themes } from '../../constants/colors'; class List extends React.Component { static propTypes = { @@ -237,8 +238,13 @@ class List extends React.Component { maxToRenderPerBatch={5} windowSize={10} ListFooterComponent={this.renderFooter} - onRefresh={this.onRefresh} - refreshing={refreshing} + refreshControl={( + + )} {...scrollPersistTaps} /> diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js index fb72085ac..611c72d8f 100644 --- a/app/views/RoomsListView/index.js +++ b/app/views/RoomsListView/index.js @@ -6,7 +6,8 @@ import { BackHandler, Text, Keyboard, - Dimensions + Dimensions, + RefreshControl } from 'react-native'; import { connect } from 'react-redux'; import { isEqual, orderBy } from 'lodash'; @@ -87,7 +88,8 @@ const shouldUpdateProps = [ 'StoreLastMessage', 'appState', 'theme', - 'split' + 'split', + 'refreshing' ]; const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, @@ -163,6 +165,7 @@ class RoomsListView extends React.Component { groupByType: PropTypes.bool, showFavorites: PropTypes.bool, showUnread: PropTypes.bool, + refreshing: PropTypes.bool, StoreLastMessage: PropTypes.bool, appState: PropTypes.string, theme: PropTypes.string, @@ -672,6 +675,11 @@ class RoomsListView extends React.Component { } }; + onRefresh = () => { + const { roomsRequest } = this.props; + roomsRequest({ allData: true }); + } + getScrollRef = ref => (this.scroll = ref); renderListHeader = () => { @@ -757,8 +765,10 @@ class RoomsListView extends React.Component { } renderScroll = () => { - const { loading, chats, search } = this.state; - const { theme } = this.props; + const { + loading, chats, search + } = this.state; + const { theme, refreshing } = this.props; if (loading) { return ; @@ -778,6 +788,13 @@ class RoomsListView extends React.Component { removeClippedSubviews={isIOS} keyboardShouldPersistTaps='always' initialNumToRender={INITIAL_NUM_TO_RENDER} + refreshControl={( + + )} windowSize={9} /> ); @@ -825,6 +842,7 @@ const mapStateToProps = state => ({ loadingServer: state.server.loading, showServerDropdown: state.rooms.showServerDropdown, showSortDropdown: state.rooms.showSortDropdown, + refreshing: state.rooms.refreshing, sortBy: state.sortPreferences.sortBy, groupByType: state.sortPreferences.groupByType, showFavorites: state.sortPreferences.showFavorites, @@ -839,7 +857,7 @@ const mapDispatchToProps = dispatch => ({ openSearchHeader: () => dispatch(openSearchHeaderAction()), closeSearchHeader: () => dispatch(closeSearchHeaderAction()), appStart: () => dispatch(appStartAction()), - roomsRequest: () => dispatch(roomsRequestAction()), + roomsRequest: params => dispatch(roomsRequestAction(params)), selectServerRequest: server => dispatch(selectServerRequestAction(server)), closeServerDropdown: () => dispatch(closeServerDropdownAction()) });