diff --git a/src/state/models/ui/profile.ts b/src/state/models/ui/profile.ts index 1d4fe28c..eb38509f 100644 --- a/src/state/models/ui/profile.ts +++ b/src/state/models/ui/profile.ts @@ -15,6 +15,10 @@ export interface ProfileUiParams { } export class ProfileUiModel { + static LOADING_ITEM = {_reactKey: '__loading__'} + static END_ITEM = {_reactKey: '__end__'} + static EMPTY_ITEM = {_reactKey: '__empty__'} + // data profile: ProfileViewModel feed: FeedModel @@ -76,6 +80,51 @@ export class ProfileUiModel { return this.selectorItems[this.selectedViewIndex] } + get uiItems() { + let arr: any[] = [] + if (this.isInitialLoading) { + arr = arr.concat([ProfileUiModel.LOADING_ITEM]) + } else if (this.currentView.hasError) { + arr = arr.concat([ + { + _reactKey: '__error__', + error: this.currentView.error, + }, + ]) + } else { + if ( + this.selectedView === Sections.Posts || + this.selectedView === Sections.PostsWithReplies + ) { + if (this.feed.hasContent) { + if (this.selectedView === Sections.Posts) { + arr = this.feed.nonReplyFeed + } else { + arr = this.feed.feed.slice() + } + if (!this.feed.hasMore) { + arr = arr.concat([ProfileUiModel.END_ITEM]) + } + } else if (this.feed.isEmpty) { + arr = arr.concat([ProfileUiModel.EMPTY_ITEM]) + } + } else { + arr = arr.concat([ProfileUiModel.EMPTY_ITEM]) + } + } + return arr + } + + get showLoadingMoreFooter() { + if ( + this.selectedView === Sections.Posts || + this.selectedView === Sections.PostsWithReplies + ) { + return this.feed.hasContent && this.feed.hasMore && this.feed.isLoading + } + return false + } + // public api // = diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx index c686bd26..a27fa6b8 100644 --- a/src/view/screens/Profile.tsx +++ b/src/view/screens/Profile.tsx @@ -8,6 +8,7 @@ import {ViewSelector} from '../com/util/ViewSelector' import {CenteredView} from '../com/util/Views' import {ProfileUiModel, Sections} from 'state/models/ui/profile' import {useStores} from 'state/index' +import {FeedItemModel} from 'state/models/feed-view' import {ProfileHeader} from '../com/profile/ProfileHeader' import {FeedItem} from '../com/posts/FeedItem' import {PostFeedLoadingPlaceholder} from '../com/util/LoadingPlaceholder' @@ -21,10 +22,6 @@ import {useOnMainScroll} from 'lib/hooks/useOnMainScroll' import {useAnalytics} from 'lib/analytics' import {ComposeIcon2} from 'lib/icons' -const LOADING_ITEM = {_reactKey: '__loading__'} -const END_ITEM = {_reactKey: '__end__'} -const EMPTY_ITEM = {_reactKey: '__empty__'} - type Props = NativeStackScreenProps export const ProfileScreen = withAuthRequired( observer(({route}: Props) => { @@ -73,98 +70,66 @@ export const ProfileScreen = withAuthRequired( const onSelectView = (index: number) => { uiState.setSelectedViewIndex(index) } - const onRefresh = () => { + const onRefresh = React.useCallback(() => { uiState .refresh() .catch((err: any) => store.log.error('Failed to refresh user profile', err), ) - } - const onEndReached = () => { + }, [uiState, store]) + const onEndReached = React.useCallback(() => { uiState .loadMore() .catch((err: any) => store.log.error('Failed to load more entries in user profile', err), ) - } - const onPressTryAgain = () => { + }, [uiState, store]) + const onPressTryAgain = React.useCallback(() => { uiState.setup() - } + }, [uiState]) // rendering // = - const renderHeader = () => { + const renderHeader = React.useCallback(() => { if (!uiState) { return } return - } - let renderItem - let Footer - let items: any[] = [] - if (uiState) { - if (uiState.isInitialLoading) { - items = items.concat([LOADING_ITEM]) - renderItem = () => - } else if (uiState.currentView.hasError) { - items = items.concat([ - { - _reactKey: '__error__', - error: uiState.currentView.error, - }, - ]) - renderItem = (item: any) => ( - - - - ) - } else { - if ( - uiState.selectedView === Sections.Posts || - uiState.selectedView === Sections.PostsWithReplies - ) { - if (uiState.feed.hasContent) { - if (uiState.selectedView === Sections.Posts) { - items = uiState.feed.nonReplyFeed - } else { - items = uiState.feed.feed.slice() - } - if (!uiState.feed.hasMore) { - items = items.concat([END_ITEM]) - } else if (uiState.feed.isLoading) { - Footer = LoadingMoreFooter - } - renderItem = (item: any) => { - if (item === END_ITEM) { - return - end of feed - - } - return ( - - ) - } - } else if (uiState.feed.isEmpty) { - items = items.concat([EMPTY_ITEM]) - renderItem = () => ( - { + return uiState.showLoadingMoreFooter ? LoadingMoreFooter : undefined + }, [uiState.showLoadingMoreFooter]) + const renderItem = React.useCallback( + (item: any) => { + if (item === ProfileUiModel.END_ITEM) { + return - end of feed - + } else if (item === ProfileUiModel.LOADING_ITEM) { + return + } else if (item._reactKey === '__error__') { + return ( + + - ) - } - } else { - items = items.concat([EMPTY_ITEM]) - renderItem = () => TODO + + ) + } else if (item === ProfileUiModel.EMPTY_ITEM) { + return ( + + ) + } else if (item instanceof FeedItemModel) { + return } - } - } - if (!renderItem) { - renderItem = () => - } + return + }, + [onPressTryAgain, uiState.profile.did], + ) return ( @@ -180,7 +145,7 @@ export const ProfileScreen = withAuthRequired(