diff options
author | Paul Frazee <pfrazee@gmail.com> | 2023-11-01 16:15:40 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-01 16:15:40 -0700 |
commit | f57a8cf8ba0cd10a54abf35d960d8fb90266fa6b (patch) | |
tree | a9da6032bcbd587d92fd1030e698aea2dbef9f72 /src/view/com/lists/ListsList.tsx | |
parent | f9944b55e26fe6109bc2e7a25b88979111470ed9 (diff) | |
download | voidsky-f57a8cf8ba0cd10a54abf35d960d8fb90266fa6b.tar.zst |
Lists updates: curate lists and blocklists (#1689)
* Add lists screen * Update Lists screen and List create/edit modal to support curate lists * Rework the ProfileList screen and add curatelist support * More ProfileList progress * Update list modals * Rename mutelists to modlists * Layout updates/fixes * More layout fixes * Modal fixes * List list screen updates * Update feed page to give more info * Layout fixes to ListAddUser modal * Layout fixes to FlatList and Feed on desktop * Layout fix to LoadLatestBtn on Web * Handle did resolution before showing the ProfileList screen * Rename the CustomFeed routes to ProfileFeed for consistency * Fix layout issues with the pager and feeds * Factor out some common code * Fix UIs for mobile * Fix user list rendering * Fix: dont bubble custom feed errors in the merge feed * Refactor feed models to reduce usage of the SavedFeeds model * Replace CustomFeedModel with FeedSourceModel which abstracts feed-generators and lists * Add the ability to pin lists * Add pinned lists to mobile * Remove dead code * Rework the ProfileScreenHeader to create more real-estate for action buttons * Improve layout behavior on web mobile breakpoints * Refactor feed & list pages to use new Tabs layout component * Refactor to ProfileSubpageHeader * Implement modlist block and mute * Switch to new api and just modify state on modlist actions * Fix some UI overflows * Fix: dont show edit buttons on lists you dont own * Fix alignment issue on long titles * Improve loading and error states for feeds & lists * Update list dropdown icons for ios * Fetch feed display names in the mergefeed * Improve rendering off offline feeds in the feed-listing page * Update Feeds listing UI to react to changes in saved/pinned state * Refresh list and feed on posts tab press * Fix pinned feed ordering UI * Fixes to list pinning * Remove view=simple qp * Add list to feed tuners * Render richtext * Add list href * Add 'view avatar' * Remove unused import * Fix missing import * Correctly reflect block by list state * Replace the <Tabs> component with the more effective <PagerWithHeader> component * Improve the responsiveness of the PagerWithHeader * Fix visual jank in the feed loading state * Improve performance of the PagerWithHeader * Fix a case that would cause the header to animate too aggressively * Add the ability to scroll to top by tapping the selected tab * Fix unit test runner * Update modlists test * Add curatelist tests * Fix: remove link behavior in ListAddUser modal * Fix some layout jank in the PagerWithHeader on iOS * Simplify ListItems header rendering * Wait for the appview to recognize the list before proceeding with list creation * Fix glitch in the onPageSelecting index of the Pager * Fix until() * Copy fix Co-authored-by: Eric Bailey <git@esb.lol> --------- Co-authored-by: Eric Bailey <git@esb.lol>
Diffstat (limited to 'src/view/com/lists/ListsList.tsx')
-rw-r--r-- | src/view/com/lists/ListsList.tsx | 137 |
1 files changed, 43 insertions, 94 deletions
diff --git a/src/view/com/lists/ListsList.tsx b/src/view/com/lists/ListsList.tsx index 4c8befa1f..efc874ef3 100644 --- a/src/view/com/lists/ListsList.tsx +++ b/src/view/com/lists/ListsList.tsx @@ -1,57 +1,44 @@ -import React, {MutableRefObject} from 'react' +import React from 'react' import { + ActivityIndicator, + FlatList as RNFlatList, RefreshControl, StyleProp, StyleSheet, View, ViewStyle, - FlatList, } from 'react-native' import {observer} from 'mobx-react-lite' -import { - FontAwesomeIcon, - FontAwesomeIconStyle, -} from '@fortawesome/react-native-fontawesome' import {AppBskyGraphDefs as GraphDefs} from '@atproto/api' import {ListCard} from './ListCard' -import {ProfileCardFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' import {ErrorMessage} from '../util/error/ErrorMessage' import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn' -import {Button} from '../util/forms/Button' import {Text} from '../util/text/Text' import {ListsListModel} from 'state/models/lists/lists-list' import {useAnalytics} from 'lib/analytics/analytics' import {usePalette} from 'lib/hooks/usePalette' +import {FlatList} from '../util/Views.web' import {s} from 'lib/styles' -const LOADING_ITEM = {_reactKey: '__loading__'} -const CREATENEW_ITEM = {_reactKey: '__loading__'} -const EMPTY_ITEM = {_reactKey: '__empty__'} +const LOADING = {_reactKey: '__loading__'} +const EMPTY = {_reactKey: '__empty__'} const ERROR_ITEM = {_reactKey: '__error__'} const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'} export const ListsList = observer(function ListsListImpl({ listsList, - showAddBtns, + inline, style, - scrollElRef, onPressTryAgain, - onPressCreateNew, renderItem, - renderEmptyState, testID, - headerOffset = 0, }: { listsList: ListsListModel - showAddBtns?: boolean + inline?: boolean style?: StyleProp<ViewStyle> - scrollElRef?: MutableRefObject<FlatList<any> | null> - onPressCreateNew: () => void onPressTryAgain?: () => void - renderItem?: (list: GraphDefs.ListView) => JSX.Element - renderEmptyState?: () => JSX.Element + renderItem?: (list: GraphDefs.ListView, index: number) => JSX.Element testID?: string - headerOffset?: number }) { const pal = usePalette('default') const {track} = useAnalytics() @@ -59,33 +46,27 @@ export const ListsList = observer(function ListsListImpl({ const data = React.useMemo(() => { let items: any[] = [] - if (listsList.hasLoaded) { - if (listsList.hasError) { - items = items.concat([ERROR_ITEM]) - } - if (listsList.isEmpty) { - items = items.concat([EMPTY_ITEM]) - } else { - if (showAddBtns) { - items = items.concat([CREATENEW_ITEM]) - } - items = items.concat(listsList.lists) - } - if (listsList.loadMoreError) { - items = items.concat([LOAD_MORE_ERROR_ITEM]) - } - } else if (listsList.isLoading) { - items = items.concat([LOADING_ITEM]) + if (listsList.hasError) { + items = items.concat([ERROR_ITEM]) + } + if (!listsList.hasLoaded && listsList.isLoading) { + items = items.concat([LOADING]) + } else if (listsList.isEmpty) { + items = items.concat([EMPTY]) + } else { + items = items.concat(listsList.lists) + } + if (listsList.loadMoreError) { + items = items.concat([LOAD_MORE_ERROR_ITEM]) } return items }, [ listsList.hasError, listsList.hasLoaded, listsList.isLoading, - listsList.isEmpty, listsList.lists, + listsList.isEmpty, listsList.loadMoreError, - showAddBtns, ]) // events @@ -119,14 +100,15 @@ export const ListsList = observer(function ListsListImpl({ // = const renderItemInner = React.useCallback( - ({item}: {item: any}) => { - if (item === EMPTY_ITEM) { - if (renderEmptyState) { - return renderEmptyState() - } - return <View /> - } else if (item === CREATENEW_ITEM) { - return <CreateNewItem onPress={onPressCreateNew} /> + ({item, index}: {item: any; index: number}) => { + if (item === EMPTY) { + return ( + <View + testID="listsEmpty" + style={[{padding: 18, borderTopWidth: 1}, pal.border]}> + <Text style={pal.textLight}>You have no lists.</Text> + </View> + ) } else if (item === ERROR_ITEM) { return ( <ErrorMessage @@ -141,11 +123,15 @@ export const ListsList = observer(function ListsListImpl({ onPress={onPressRetryLoadMore} /> ) - } else if (item === LOADING_ITEM) { - return <ProfileCardFeedLoadingPlaceholder /> + } else if (item === LOADING) { + return ( + <View style={{padding: 20}}> + <ActivityIndicator /> + </View> + ) } return renderItem ? ( - renderItem(item) + renderItem(item, index) ) : ( <ListCard list={item} @@ -154,24 +140,17 @@ export const ListsList = observer(function ListsListImpl({ /> ) }, - [ - listsList, - onPressTryAgain, - onPressRetryLoadMore, - onPressCreateNew, - renderItem, - renderEmptyState, - ], + [listsList, onPressTryAgain, onPressRetryLoadMore, renderItem, pal], ) + const FlatListCom = inline ? RNFlatList : FlatList return ( <View testID={testID} style={style}> {data.length > 0 && ( - <FlatList + <FlatListCom testID={testID ? `${testID}-flatlist` : undefined} - ref={scrollElRef} data={data} - keyExtractor={item => item._reactKey} + keyExtractor={(item: any) => item._reactKey} renderItem={renderItemInner} refreshControl={ <RefreshControl @@ -179,15 +158,12 @@ export const ListsList = observer(function ListsListImpl({ onRefresh={onRefresh} tintColor={pal.colors.text} titleColor={pal.colors.text} - progressViewOffset={headerOffset} /> } contentContainerStyle={[s.contentContainer]} - style={{paddingTop: headerOffset}} onEndReached={onEndReached} onEndReachedThreshold={0.6} removeClippedSubviews={true} - contentOffset={{x: 0, y: headerOffset * -1}} // @ts-ignore our .web version only -prf desktopFixedHeight /> @@ -196,36 +172,9 @@ export const ListsList = observer(function ListsListImpl({ ) }) -function CreateNewItem({onPress}: {onPress: () => void}) { - const pal = usePalette('default') - - return ( - <View style={[styles.createNewContainer]}> - <Button type="default" onPress={onPress} style={styles.createNewButton}> - <FontAwesomeIcon icon="plus" style={pal.text as FontAwesomeIconStyle} /> - <Text type="button" style={pal.text}> - New Mute List - </Text> - </Button> - </View> - ) -} - const styles = StyleSheet.create({ - createNewContainer: { - flexDirection: 'row', - alignItems: 'center', - paddingHorizontal: 18, - paddingTop: 18, - paddingBottom: 16, - }, - createNewButton: { - flexDirection: 'row', - alignItems: 'center', - gap: 8, - }, - feedFooter: {paddingTop: 20}, item: { paddingHorizontal: 18, + paddingVertical: 4, }, }) |