diff options
Diffstat (limited to 'src/view')
-rw-r--r-- | src/view/com/algos/AlgoItem.tsx | 67 | ||||
-rw-r--r-- | src/view/index.ts | 2 | ||||
-rw-r--r-- | src/view/screens/CustomFeed.tsx | 2 | ||||
-rw-r--r-- | src/view/screens/SavedFeeds.tsx | 107 |
4 files changed, 120 insertions, 58 deletions
diff --git a/src/view/com/algos/AlgoItem.tsx b/src/view/com/algos/AlgoItem.tsx index 4377e3583..f7d320530 100644 --- a/src/view/com/algos/AlgoItem.tsx +++ b/src/view/com/algos/AlgoItem.tsx @@ -19,7 +19,17 @@ import {useStores} from 'state/index' import {HeartIconSolid} from 'lib/icons' const AlgoItem = observer( - ({item, style}: {item: AlgoItemModel; style?: StyleProp<ViewStyle>}) => { + ({ + item, + style, + showBottom = true, + onLongPress, + }: { + item: AlgoItemModel + style?: StyleProp<ViewStyle> + showBottom?: boolean + onLongPress?: () => void + }) => { const store = useStores() const pal = usePalette('default') const navigation = useNavigation<NavigationProp>() @@ -34,10 +44,11 @@ const AlgoItem = observer( rkey: item.data.uri, }) }} + onLongPress={onLongPress} key={item.data.uri}> <View style={[styles.headerContainer]}> <View style={[s.mr10]}> - <UserAvatar size={36} avatar={item.data.avatar} s /> + <UserAvatar size={36} avatar={item.data.avatar} /> </View> <View style={[styles.headerTextContainer]}> <Text style={[pal.text, s.bold]}> @@ -49,37 +60,39 @@ const AlgoItem = observer( </View> </View> - <View style={styles.bottomContainer}> - <View style={styles.likedByContainer}> - {/* <View style={styles.likedByAvatars}> + {showBottom ? ( + <View style={styles.bottomContainer}> + <View style={styles.likedByContainer}> + {/* <View style={styles.likedByAvatars}> <UserAvatar size={24} avatar={item.data.avatar} /> <UserAvatar size={24} avatar={item.data.avatar} /> <UserAvatar size={24} avatar={item.data.avatar} /> </View> */} - <HeartIconSolid size={16} style={[s.mr2, {color: colors.red3}]} /> - <Text style={[pal.text, pal.textLight]}> - {item.data.likeCount && item.data.likeCount > 1 - ? `Liked by ${item.data.likeCount} others` - : 'Be the first to like this'} - </Text> - </View> - <View> - <Button - type="inverted" - onPress={() => { - if (item.data.viewer?.saved) { - item.unsave() - store.me.savedFeeds.removeFeed(item.data.uri) - } else { - item.save() - store.me.savedFeeds.addFeed(item) - } - }} - label={item.data.viewer?.saved ? 'Unsave' : 'Save'} - /> + <HeartIconSolid size={16} style={[s.mr2, {color: colors.red3}]} /> + <Text style={[pal.text, pal.textLight]}> + {item.data.likeCount && item.data.likeCount > 1 + ? `Liked by ${item.data.likeCount} others` + : 'Be the first to like this'} + </Text> + </View> + <View> + <Button + type="inverted" + onPress={() => { + if (item.data.viewer?.saved) { + item.unsave() + store.me.savedFeeds.removeFeed(item.data.uri) + } else { + item.save() + store.me.savedFeeds.addFeed(item) + } + }} + label={item.data.viewer?.saved ? 'Unsave' : 'Save'} + /> + </View> </View> - </View> + ) : null} </TouchableOpacity> ) }, diff --git a/src/view/index.ts b/src/view/index.ts index dd8a585d6..253735e81 100644 --- a/src/view/index.ts +++ b/src/view/index.ts @@ -75,6 +75,7 @@ import {faX} from '@fortawesome/free-solid-svg-icons/faX' import {faXmark} from '@fortawesome/free-solid-svg-icons/faXmark' import {faPlay} from '@fortawesome/free-solid-svg-icons/faPlay' import {faPause} from '@fortawesome/free-solid-svg-icons/faPause' +import {faThumbtack} from '@fortawesome/free-solid-svg-icons/faThumbtack' export function setup() { library.add( @@ -149,6 +150,7 @@ export function setup() { faUserXmark, faTicket, faTrashCan, + faThumbtack, faX, faXmark, faPlay, diff --git a/src/view/screens/CustomFeed.tsx b/src/view/screens/CustomFeed.tsx index 05c8d38f1..97dd1cf81 100644 --- a/src/view/screens/CustomFeed.tsx +++ b/src/view/screens/CustomFeed.tsx @@ -19,7 +19,7 @@ import {Text} from 'view/com/util/text/Text' type Props = NativeStackScreenProps<CommonNavigatorParams, 'CustomFeed'> export const CustomFeed = withAuthRequired( - observer(({route, navigation}: Props) => { + observer(({route}: Props) => { const rootStore = useStores() const {rkey, name} = route.params const currentFeed = useCustomFeed(rkey) diff --git a/src/view/screens/SavedFeeds.tsx b/src/view/screens/SavedFeeds.tsx index 7b04a6474..65ffdb233 100644 --- a/src/view/screens/SavedFeeds.tsx +++ b/src/view/screens/SavedFeeds.tsx @@ -3,8 +3,9 @@ import { RefreshControl, StyleSheet, View, - FlatList, ActivityIndicator, + FlatList, + TouchableOpacity, } from 'react-native' import {useFocusEffect} from '@react-navigation/native' import {NativeStackScreenProps} from '@react-navigation/native-stack' @@ -13,28 +14,28 @@ import {usePalette} from 'lib/hooks/usePalette' import {CommonNavigatorParams} from 'lib/routes/types' import {observer} from 'mobx-react-lite' import {useStores} from 'state/index' -import {SavedFeedsModel} from 'state/models/feeds/algo/saved' import AlgoItem from 'view/com/algos/AlgoItem' import {withAuthRequired} from 'view/com/auth/withAuthRequired' import {ViewHeader} from 'view/com/util/ViewHeader' import {CenteredView} from 'view/com/util/Views' import {Text} from 'view/com/util/text/Text' import {isDesktopWeb} from 'platform/detection' -import {s} from 'lib/styles' +import {colors, s} from 'lib/styles' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' +import {AlgoItemModel} from 'state/models/feeds/algo/algo-item' +import {SavedFeedsModel} from 'state/models/feeds/algo/saved' type Props = NativeStackScreenProps<CommonNavigatorParams, 'SavedFeeds'> export const SavedFeeds = withAuthRequired( observer(({}: Props) => { + // hooks for global items const pal = usePalette('default') const rootStore = useStores() const {screen} = useAnalytics() - const savedFeeds = useMemo( - () => new SavedFeedsModel(rootStore), - [rootStore], - ) - + // hooks for local + const savedFeeds = useMemo(() => rootStore.me.savedFeeds, [rootStore]) useFocusEffect( useCallback(() => { screen('SavedFeeds') @@ -42,14 +43,38 @@ export const SavedFeeds = withAuthRequired( savedFeeds.refresh() }, [screen, rootStore, savedFeeds]), ) + const _ListEmptyComponent = () => { + return ( + <View + style={[ + pal.border, + !isDesktopWeb && s.flex1, + pal.viewLight, + styles.empty, + ]}> + <Text type="lg" style={[pal.text]}> + You don't have any saved feeds. To save a feed, click the save + button when a custom feed or algorithm shows up. + </Text> + </View> + ) + } + const _ListFooterComponent = () => { + return ( + <View style={styles.footer}> + {savedFeeds.isLoading && <ActivityIndicator />} + </View> + ) + } return ( <CenteredView style={[s.flex1]}> - <ViewHeader title="Custom Algorithms" showOnDesktop /> + <ViewHeader title="Saved Feeds" showOnDesktop /> <FlatList style={[!isDesktopWeb && s.flex1]} data={savedFeeds.feeds} keyExtractor={item => item.data.uri} + refreshing={savedFeeds.isRefreshing} refreshControl={ <RefreshControl refreshing={savedFeeds.isRefreshing} @@ -58,28 +83,12 @@ export const SavedFeeds = withAuthRequired( titleColor={pal.colors.text} /> } - onEndReached={() => savedFeeds.loadMore()} - renderItem={({item}) => <AlgoItem key={item.data.uri} item={item} />} - initialNumToRender={15} - ListFooterComponent={() => ( - <View style={styles.footer}> - {savedFeeds.isLoading && <ActivityIndicator />} - </View> - )} - ListEmptyComponent={() => ( - <View - style={[ - pal.border, - !isDesktopWeb && s.flex1, - pal.viewLight, - styles.empty, - ]}> - <Text type="lg" style={[pal.text]}> - You don't have any saved feeds. To save a feed, click the save - button when a custom feed or algorithm shows up. - </Text> - </View> + renderItem={({item}) => ( + <SavedFeedItem item={item} savedFeeds={savedFeeds} /> )} + initialNumToRender={10} + ListFooterComponent={_ListFooterComponent} + ListEmptyComponent={_ListEmptyComponent} extraData={savedFeeds.isLoading} // @ts-ignore our .web version only -prf desktopFixedHeight @@ -89,6 +98,36 @@ export const SavedFeeds = withAuthRequired( }), ) +const SavedFeedItem = observer( + ({item, savedFeeds}: {item: AlgoItemModel; savedFeeds: SavedFeedsModel}) => { + const isPinned = savedFeeds.isPinned(item) + + return ( + <View style={styles.itemContainer}> + <AlgoItem + key={item.data.uri} + item={item} + showBottom={false} + style={styles.item} + /> + <TouchableOpacity + accessibilityRole="button" + onPress={() => { + savedFeeds.togglePinnedFeed(item) + console.log('pinned', savedFeeds.pinned) + console.log('isPinned', savedFeeds.isPinned(item)) + }}> + <FontAwesomeIcon + icon="thumb-tack" + size={20} + color={isPinned ? colors.blue3 : colors.gray3} + /> + </TouchableOpacity> + </View> + ) + }, +) + const styles = StyleSheet.create({ footer: { paddingVertical: 20, @@ -100,4 +139,12 @@ const styles = StyleSheet.create({ marginHorizontal: 24, marginTop: 10, }, + itemContainer: { + flexDirection: 'row', + alignItems: 'center', + marginRight: 18, + }, + item: { + borderTopWidth: 0, + }, }) |