Add 'loading more' spinner to feeds

zio/stable
Paul Frazee 2022-12-12 11:22:54 -06:00
parent 2b27be31e6
commit 8501cf1c7d
3 changed files with 38 additions and 8 deletions

View File

@ -1,6 +1,12 @@
import React, {MutableRefObject} from 'react' import React, {MutableRefObject} from 'react'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import {View, FlatList, StyleProp, ViewStyle} from 'react-native' import {
ActivityIndicator,
View,
FlatList,
StyleProp,
ViewStyle,
} from 'react-native'
import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
import {EmptyState} from '../util/EmptyState' import {EmptyState} from '../util/EmptyState'
import {ErrorMessage} from '../util/ErrorMessage' import {ErrorMessage} from '../util/ErrorMessage'
@ -57,6 +63,14 @@ export const Feed = observer(function Feed({
data = [COMPOSE_PROMPT_ITEM].concat(feed.feed) data = [COMPOSE_PROMPT_ITEM].concat(feed.feed)
} }
} }
const FeedFooter = () =>
feed.isLoading ? (
<View style={{paddingTop: 20}}>
<ActivityIndicator />
</View>
) : (
<View />
)
return ( return (
<View style={style}> <View style={style}>
{!data && <ComposePrompt onPressCompose={onPressCompose} />} {!data && <ComposePrompt onPressCompose={onPressCompose} />}
@ -75,6 +89,7 @@ export const Feed = observer(function Feed({
data={data} data={data}
keyExtractor={item => item._reactKey} keyExtractor={item => item._reactKey}
renderItem={renderItem} renderItem={renderItem}
ListFooterComponent={FeedFooter}
refreshing={feed.isRefreshing} refreshing={feed.isRefreshing}
contentContainerStyle={{paddingBottom: 100}} contentContainerStyle={{paddingBottom: 100}}
onRefresh={onRefresh} onRefresh={onRefresh}

View File

@ -1,9 +1,8 @@
import React, {useEffect, useState, useMemo} from 'react' import React, {useEffect, useState} from 'react'
import {FlatList, StyleSheet, View} from 'react-native' import {FlatList, View} from 'react-native'
import {Selector} from './Selector' import {Selector} from './Selector'
import {HorzSwipe} from './gestures/HorzSwipe' import {HorzSwipe} from './gestures/HorzSwipe'
import {useAnimatedValue} from '../../lib/useAnimatedValue' import {useAnimatedValue} from '../../lib/useAnimatedValue'
import {useStores} from '../../../state'
const HEADER_ITEM = {_reactKey: '__header__'} const HEADER_ITEM = {_reactKey: '__header__'}
const SELECTOR_ITEM = {_reactKey: '__selector__'} const SELECTOR_ITEM = {_reactKey: '__selector__'}
@ -16,6 +15,7 @@ export function ViewSelector({
swipeEnabled, swipeEnabled,
renderHeader, renderHeader,
renderItem, renderItem,
ListFooterComponent,
onSelectView, onSelectView,
onRefresh, onRefresh,
onEndReached, onEndReached,
@ -26,11 +26,15 @@ export function ViewSelector({
swipeEnabled?: boolean swipeEnabled?: boolean
renderHeader?: () => JSX.Element renderHeader?: () => JSX.Element
renderItem: (item: any) => JSX.Element renderItem: (item: any) => JSX.Element
ListFooterComponent?:
| React.ComponentType<any>
| React.ReactElement
| null
| undefined
onSelectView?: (viewIndex: number) => void onSelectView?: (viewIndex: number) => void
onRefresh?: () => void onRefresh?: () => void
onEndReached?: (info: {distanceFromEnd: number}) => void onEndReached?: (info: {distanceFromEnd: number}) => void
}) { }) {
const store = useStores()
const [selectedIndex, setSelectedIndex] = useState<number>(0) const [selectedIndex, setSelectedIndex] = useState<number>(0)
const panX = useAnimatedValue(0) const panX = useAnimatedValue(0)
@ -83,6 +87,7 @@ export function ViewSelector({
data={data} data={data}
keyExtractor={item => item._reactKey} keyExtractor={item => item._reactKey}
renderItem={renderItemInternal} renderItem={renderItemInternal}
ListFooterComponent={ListFooterComponent}
stickyHeaderIndices={STICKY_HEADER_INDICES} stickyHeaderIndices={STICKY_HEADER_INDICES}
refreshing={refreshing} refreshing={refreshing}
onRefresh={onRefresh} onRefresh={onRefresh}
@ -91,5 +96,3 @@ export function ViewSelector({
</HorzSwipe> </HorzSwipe>
) )
} }
const styles = StyleSheet.create({})

View File

@ -1,5 +1,5 @@
import React, {useEffect, useState, useMemo} from 'react' import React, {useEffect, useState, useMemo} from 'react'
import {StyleSheet, Text, View} from 'react-native' import {ActivityIndicator, StyleSheet, Text, View} from 'react-native'
import {observer} from 'mobx-react-lite' import {observer} from 'mobx-react-lite'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {ViewSelector} from '../com/util/ViewSelector' import {ViewSelector} from '../com/util/ViewSelector'
@ -97,6 +97,7 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => {
return <ProfileHeader view={uiState.profile} onRefreshAll={onRefresh} /> return <ProfileHeader view={uiState.profile} onRefreshAll={onRefresh} />
} }
let renderItem let renderItem
let Footer
let items: any[] = [] let items: any[] = []
if (uiState) { if (uiState) {
if (uiState.isInitialLoading) { if (uiState.isInitialLoading) {
@ -132,6 +133,8 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => {
} }
if (!uiState.feed.hasMore) { if (!uiState.feed.hasMore) {
items = items.concat([END_ITEM]) items = items.concat([END_ITEM])
} else {
Footer = LoadingMoreFooter
} }
renderItem = (item: any) => { renderItem = (item: any) => {
if (item === END_ITEM) { if (item === END_ITEM) {
@ -246,6 +249,7 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => {
items={items} items={items}
renderHeader={renderHeader} renderHeader={renderHeader}
renderItem={renderItem} renderItem={renderItem}
ListFooterComponent={Footer}
refreshing={uiState.isRefreshing || false} refreshing={uiState.isRefreshing || false}
onSelectView={onSelectView} onSelectView={onSelectView}
onRefresh={onRefresh} onRefresh={onRefresh}
@ -258,6 +262,14 @@ export const Profile = observer(({navIdx, visible, params}: ScreenParams) => {
) )
}) })
function LoadingMoreFooter() {
return (
<View style={{paddingVertical: 20}}>
<ActivityIndicator />
</View>
)
}
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flexDirection: 'column', flexDirection: 'column',