[NEW] Pull to refresh RoomsList (#1701)

This commit is contained in:
Djorkaeff Alexandre 2020-02-11 17:13:44 -03:00 committed by GitHub
parent ebe36cdc00
commit 42a53b4c9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 63 additions and 17 deletions

View File

@ -22,6 +22,7 @@ export const SHARE = createRequestTypes('SHARE', [
export const USER = createRequestTypes('USER', ['SET']); export const USER = createRequestTypes('USER', ['SET']);
export const ROOMS = createRequestTypes('ROOMS', [ export const ROOMS = createRequestTypes('ROOMS', [
...defaultTypes, ...defaultTypes,
'REFRESH',
'SET_SEARCH', 'SET_SEARCH',
'CLOSE_SERVER_DROPDOWN', 'CLOSE_SERVER_DROPDOWN',
'TOGGLE_SERVER_DROPDOWN', 'TOGGLE_SERVER_DROPDOWN',

View File

@ -1,9 +1,10 @@
import * as types from './actionsTypes'; import * as types from './actionsTypes';
export function roomsRequest() { export function roomsRequest(params = { allData: false }) {
return { 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) { export function setSearch(searchText) {
return { return {
type: types.ROOMS.SET_SEARCH, type: types.ROOMS.SET_SEARCH,

View File

@ -2,6 +2,7 @@ import * as types from '../actions/actionsTypes';
const initialState = { const initialState = {
isFetching: false, isFetching: false,
refreshing: false,
failure: false, failure: false,
errorMessage: {}, errorMessage: {},
searchText: '', searchText: '',
@ -23,15 +24,23 @@ export default function login(state = initialState, action) {
case types.ROOMS.SUCCESS: case types.ROOMS.SUCCESS:
return { return {
...state, ...state,
isFetching: false isFetching: false,
refreshing: false
}; };
case types.ROOMS.FAILURE: case types.ROOMS.FAILURE:
return { return {
...state, ...state,
isFetching: false, isFetching: false,
refreshing: false,
failure: true, failure: true,
errorMessage: action.err errorMessage: action.err
}; };
case types.ROOMS.REFRESH:
return {
...state,
isFetching: true,
refreshing: true
};
case types.ROOMS.SET_SEARCH: case types.ROOMS.SET_SEARCH:
return { return {
...state, ...state,

View File

@ -6,7 +6,7 @@ import { Q } from '@nozbe/watermelondb';
import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
import * as types from '../actions/actionsTypes'; 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 database from '../lib/database';
import log from '../utils/log'; import log from '../utils/log';
import mergeSubscriptionsRooms from '../lib/methods/helpers/mergeSubscriptionsRooms'; 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 { try {
const serversDB = database.servers; const serversDB = database.servers;
yield RocketChat.subscribeRooms(); RocketChat.subscribeRooms();
const newRoomsUpdatedAt = new Date(); const newRoomsUpdatedAt = new Date();
let roomsUpdatedAt;
const server = yield select(state => state.server.server); const server = yield select(state => state.server.server);
if (params.allData) {
yield put(roomsRefresh());
} else {
const serversCollection = serversDB.collections.get('servers'); const serversCollection = serversDB.collections.get('servers');
const serverRecord = yield serversCollection.find(server); const serverRecord = yield serversCollection.find(server);
const { roomsUpdatedAt } = serverRecord; ({ roomsUpdatedAt } = serverRecord);
}
const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt); const [subscriptionsResult, roomsResult] = yield RocketChat.getRooms(roomsUpdatedAt);
const { subscriptions } = mergeSubscriptionsRooms(subscriptionsResult, roomsResult); const { subscriptions } = mergeSubscriptionsRooms(subscriptionsResult, roomsResult);

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { FlatList, InteractionManager } from 'react-native'; import { FlatList, InteractionManager, RefreshControl } from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import orderBy from 'lodash/orderBy'; import orderBy from 'lodash/orderBy';
import { Q } from '@nozbe/watermelondb'; import { Q } from '@nozbe/watermelondb';
@ -15,6 +15,7 @@ import { isIOS } from '../../utils/deviceInfo';
import { animateNextTransition } from '../../utils/layoutAnimation'; import { animateNextTransition } from '../../utils/layoutAnimation';
import ActivityIndicator from '../../containers/ActivityIndicator'; import ActivityIndicator from '../../containers/ActivityIndicator';
import debounce from '../../utils/debounce'; import debounce from '../../utils/debounce';
import { themes } from '../../constants/colors';
class List extends React.Component { class List extends React.Component {
static propTypes = { static propTypes = {
@ -237,8 +238,13 @@ class List extends React.Component {
maxToRenderPerBatch={5} maxToRenderPerBatch={5}
windowSize={10} windowSize={10}
ListFooterComponent={this.renderFooter} ListFooterComponent={this.renderFooter}
onRefresh={this.onRefresh} refreshControl={(
<RefreshControl
refreshing={refreshing} refreshing={refreshing}
onRefresh={this.onRefresh}
tintColor={themes[theme].auxiliaryText}
/>
)}
{...scrollPersistTaps} {...scrollPersistTaps}
/> />
</> </>

View File

@ -6,7 +6,8 @@ import {
BackHandler, BackHandler,
Text, Text,
Keyboard, Keyboard,
Dimensions Dimensions,
RefreshControl
} from 'react-native'; } from 'react-native';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { isEqual, orderBy } from 'lodash'; import { isEqual, orderBy } from 'lodash';
@ -87,7 +88,8 @@ const shouldUpdateProps = [
'StoreLastMessage', 'StoreLastMessage',
'appState', 'appState',
'theme', 'theme',
'split' 'split',
'refreshing'
]; ];
const getItemLayout = (data, index) => ({ const getItemLayout = (data, index) => ({
length: ROW_HEIGHT, length: ROW_HEIGHT,
@ -163,6 +165,7 @@ class RoomsListView extends React.Component {
groupByType: PropTypes.bool, groupByType: PropTypes.bool,
showFavorites: PropTypes.bool, showFavorites: PropTypes.bool,
showUnread: PropTypes.bool, showUnread: PropTypes.bool,
refreshing: PropTypes.bool,
StoreLastMessage: PropTypes.bool, StoreLastMessage: PropTypes.bool,
appState: PropTypes.string, appState: PropTypes.string,
theme: 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); getScrollRef = ref => (this.scroll = ref);
renderListHeader = () => { renderListHeader = () => {
@ -757,8 +765,10 @@ class RoomsListView extends React.Component {
} }
renderScroll = () => { renderScroll = () => {
const { loading, chats, search } = this.state; const {
const { theme } = this.props; loading, chats, search
} = this.state;
const { theme, refreshing } = this.props;
if (loading) { if (loading) {
return <ActivityIndicator theme={theme} />; return <ActivityIndicator theme={theme} />;
@ -778,6 +788,13 @@ class RoomsListView extends React.Component {
removeClippedSubviews={isIOS} removeClippedSubviews={isIOS}
keyboardShouldPersistTaps='always' keyboardShouldPersistTaps='always'
initialNumToRender={INITIAL_NUM_TO_RENDER} initialNumToRender={INITIAL_NUM_TO_RENDER}
refreshControl={(
<RefreshControl
refreshing={refreshing}
onRefresh={this.onRefresh}
tintColor={themes[theme].auxiliaryText}
/>
)}
windowSize={9} windowSize={9}
/> />
); );
@ -825,6 +842,7 @@ const mapStateToProps = state => ({
loadingServer: state.server.loading, loadingServer: state.server.loading,
showServerDropdown: state.rooms.showServerDropdown, showServerDropdown: state.rooms.showServerDropdown,
showSortDropdown: state.rooms.showSortDropdown, showSortDropdown: state.rooms.showSortDropdown,
refreshing: state.rooms.refreshing,
sortBy: state.sortPreferences.sortBy, sortBy: state.sortPreferences.sortBy,
groupByType: state.sortPreferences.groupByType, groupByType: state.sortPreferences.groupByType,
showFavorites: state.sortPreferences.showFavorites, showFavorites: state.sortPreferences.showFavorites,
@ -839,7 +857,7 @@ const mapDispatchToProps = dispatch => ({
openSearchHeader: () => dispatch(openSearchHeaderAction()), openSearchHeader: () => dispatch(openSearchHeaderAction()),
closeSearchHeader: () => dispatch(closeSearchHeaderAction()), closeSearchHeader: () => dispatch(closeSearchHeaderAction()),
appStart: () => dispatch(appStartAction()), appStart: () => dispatch(appStartAction()),
roomsRequest: () => dispatch(roomsRequestAction()), roomsRequest: params => dispatch(roomsRequestAction(params)),
selectServerRequest: server => dispatch(selectServerRequestAction(server)), selectServerRequest: server => dispatch(selectServerRequestAction(server)),
closeServerDropdown: () => dispatch(closeServerDropdownAction()) closeServerDropdown: () => dispatch(closeServerDropdownAction())
}); });