diff options
Diffstat (limited to 'src/view/com/posts')
-rw-r--r-- | src/view/com/posts/FeedItem.tsx | 57 | ||||
-rw-r--r-- | src/view/com/posts/FeedSlice.tsx | 2 | ||||
-rw-r--r-- | src/view/com/posts/FollowingEmptyState.tsx | 2 | ||||
-rw-r--r-- | src/view/com/posts/MultiFeed.tsx | 256 |
4 files changed, 34 insertions, 283 deletions
diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx index bc7b7a7e6..59ab28d72 100644 --- a/src/view/com/posts/FeedItem.tsx +++ b/src/view/com/posts/FeedItem.tsx @@ -8,6 +8,7 @@ import { FontAwesomeIconStyle, } from '@fortawesome/react-native-fontawesome' import {PostsFeedItemModel} from 'state/models/feeds/post' +import {FeedSourceInfo} from 'lib/api/feed/types' import {Link, DesktopWebTextLink} from '../util/Link' import {Text} from '../util/text/Text' import {UserInfoText} from '../util/UserInfoText' @@ -26,17 +27,19 @@ import {usePalette} from 'lib/hooks/usePalette' import {useAnalytics} from 'lib/analytics/analytics' import {sanitizeDisplayName} from 'lib/strings/display-names' import {sanitizeHandle} from 'lib/strings/handles' -import {getTranslatorLink, isPostInLanguage} from '../../../locale/helpers' +import {getTranslatorLink} from '../../../locale/helpers' import {makeProfileLink} from 'lib/routes/links' import {isEmbedByEmbedder} from 'lib/embeds' export const FeedItem = observer(function FeedItemImpl({ item, + source, isThreadChild, isThreadLastChild, isThreadParent, }: { item: PostsFeedItemModel + source?: FeedSourceInfo isThreadChild?: boolean isThreadLastChild?: boolean isThreadParent?: boolean @@ -62,12 +65,6 @@ export const FeedItem = observer(function FeedItemImpl({ return urip.hostname }, [record?.reply]) const translatorUrl = getTranslatorLink(record?.text || '') - const needsTranslation = useMemo( - () => - store.preferences.contentLanguages.length > 0 && - !isPostInLanguage(item.post, store.preferences.contentLanguages), - [item.post, store.preferences.contentLanguages], - ) const onPressReply = React.useCallback(() => { track('FeedItem:PostReply') @@ -179,7 +176,27 @@ export const FeedItem = observer(function FeedItemImpl({ </View> <View style={{paddingTop: 12}}> - {item.reasonRepost && ( + {source ? ( + <Link + title={sanitizeDisplayName(source.displayName)} + href={source.uri}> + <Text + type="sm-bold" + style={pal.textLight} + lineHeight={1.2} + numberOfLines={1}> + From{' '} + <DesktopWebTextLink + type="sm-bold" + style={pal.textLight} + lineHeight={1.2} + numberOfLines={1} + text={sanitizeDisplayName(source.displayName)} + href={source.uri} + /> + </Text> + </Link> + ) : item.reasonRepost ? ( <Link style={styles.includeReason} href={makeProfileLink(item.reasonRepost.by)} @@ -188,10 +205,10 @@ export const FeedItem = observer(function FeedItemImpl({ )}> <FontAwesomeIcon icon="retweet" - style={[ - styles.includeReasonIcon, - {color: pal.colors.textLight} as FontAwesomeIconStyle, - ]} + style={{ + marginRight: 4, + color: pal.colors.textLight, + }} /> <Text type="sm-bold" @@ -212,7 +229,7 @@ export const FeedItem = observer(function FeedItemImpl({ /> </Text> </Link> - )} + ) : null} </View> </View> @@ -304,15 +321,6 @@ export const FeedItem = observer(function FeedItemImpl({ /> </ContentHider> ) : null} - {needsTranslation && ( - <View style={[pal.borderDark, styles.translateLink]}> - <Link href={translatorUrl} title="Translate"> - <Text type="sm" style={pal.link}> - Translate this post - </Text> - </Link> - </View> - )} </ContentHider> <PostCtrls itemUri={itemUri} @@ -362,12 +370,9 @@ const styles = StyleSheet.create({ includeReason: { flexDirection: 'row', marginTop: 2, - marginBottom: 4, + marginBottom: 2, marginLeft: -20, }, - includeReasonIcon: { - marginRight: 4, - }, layout: { flexDirection: 'row', marginTop: 1, diff --git a/src/view/com/posts/FeedSlice.tsx b/src/view/com/posts/FeedSlice.tsx index 47313ee27..1d26f6cbd 100644 --- a/src/view/com/posts/FeedSlice.tsx +++ b/src/view/com/posts/FeedSlice.tsx @@ -28,6 +28,7 @@ export const FeedSlice = observer(function FeedSliceImpl({ <FeedItem key={slice.items[0]._reactKey} item={slice.items[0]} + source={slice.source} isThreadParent={slice.isThreadParentAt(0)} isThreadChild={slice.isThreadChildAt(0)} /> @@ -55,6 +56,7 @@ export const FeedSlice = observer(function FeedSliceImpl({ <FeedItem key={item._reactKey} item={item} + source={i === 0 ? slice.source : undefined} isThreadParent={slice.isThreadParentAt(i)} isThreadChild={slice.isThreadChildAt(i)} isThreadLastChild={ diff --git a/src/view/com/posts/FollowingEmptyState.tsx b/src/view/com/posts/FollowingEmptyState.tsx index 4491b2526..a73ffb68b 100644 --- a/src/view/com/posts/FollowingEmptyState.tsx +++ b/src/view/com/posts/FollowingEmptyState.tsx @@ -28,7 +28,7 @@ export function FollowingEmptyState() { }, [navigation]) const onPressDiscoverFeeds = React.useCallback(() => { - navigation.navigate('DiscoverFeeds') + navigation.navigate('Feeds') }, [navigation]) return ( diff --git a/src/view/com/posts/MultiFeed.tsx b/src/view/com/posts/MultiFeed.tsx deleted file mode 100644 index 9c8f4f246..000000000 --- a/src/view/com/posts/MultiFeed.tsx +++ /dev/null @@ -1,256 +0,0 @@ -import React, {MutableRefObject} from 'react' -import {observer} from 'mobx-react-lite' -import { - ActivityIndicator, - RefreshControl, - StyleProp, - StyleSheet, - View, - ViewStyle, -} from 'react-native' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {FlatList} from '../util/Views' -import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' -import {ErrorMessage} from '../util/error/ErrorMessage' -import {PostsMultiFeedModel, MultiFeedItem} from 'state/models/feeds/multi-feed' -import {FeedSlice} from './FeedSlice' -import {Text} from '../util/text/Text' -import {Link} from '../util/Link' -import {UserAvatar} from '../util/UserAvatar' -import {OnScrollCb} from 'lib/hooks/useOnMainScroll' -import {s} from 'lib/styles' -import {useAnalytics} from 'lib/analytics/analytics' -import {usePalette} from 'lib/hooks/usePalette' -import {useTheme} from 'lib/ThemeContext' -import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' -import {CogIcon} from 'lib/icons' - -export const MultiFeed = observer(function Feed({ - multifeed, - style, - scrollElRef, - onScroll, - scrollEventThrottle, - testID, - headerOffset = 0, - extraData, -}: { - multifeed: PostsMultiFeedModel - style?: StyleProp<ViewStyle> - scrollElRef?: MutableRefObject<FlatList<any> | null> - onPressTryAgain?: () => void - onScroll?: OnScrollCb - scrollEventThrottle?: number - renderEmptyState?: () => JSX.Element - testID?: string - headerOffset?: number - extraData?: any -}) { - const pal = usePalette('default') - const theme = useTheme() - const {isMobile} = useWebMediaQueries() - const {track} = useAnalytics() - const [isRefreshing, setIsRefreshing] = React.useState(false) - - // events - // = - - const onRefresh = React.useCallback(async () => { - track('MultiFeed:onRefresh') - setIsRefreshing(true) - try { - await multifeed.refresh() - } catch (err) { - multifeed.rootStore.log.error('Failed to refresh posts feed', err) - } - setIsRefreshing(false) - }, [multifeed, track, setIsRefreshing]) - - const onEndReached = React.useCallback(async () => { - track('MultiFeed:onEndReached') - try { - await multifeed.loadMore() - } catch (err) { - multifeed.rootStore.log.error('Failed to load more posts', err) - } - }, [multifeed, track]) - - // rendering - // = - - const renderItem = React.useCallback( - ({item}: {item: MultiFeedItem}) => { - if (item.type === 'header') { - if (!isMobile) { - return ( - <> - <View style={[pal.view, pal.border, styles.headerDesktop]}> - <Text type="2xl-bold" style={pal.text}> - My Feeds - </Text> - <Link href="/settings/saved-feeds"> - <CogIcon strokeWidth={1.5} style={pal.icon} size={28} /> - </Link> - </View> - <DiscoverLink /> - </> - ) - } - return ( - <> - <View style={[styles.header, pal.border]} /> - <DiscoverLink /> - </> - ) - } else if (item.type === 'feed-header') { - return ( - <View style={styles.feedHeader}> - <UserAvatar type="algo" avatar={item.avatar} size={28} /> - <Text type="title-lg" style={[pal.text, styles.feedHeaderTitle]}> - {item.title} - </Text> - </View> - ) - } else if (item.type === 'feed-slice') { - return <FeedSlice slice={item.slice} /> - } else if (item.type === 'feed-loading') { - return <PostFeedLoadingPlaceholder /> - } else if (item.type === 'feed-error') { - return <ErrorMessage message={item.error} /> - } else if (item.type === 'feed-footer') { - return ( - <Link - href={item.uri} - style={[styles.feedFooter, pal.border, pal.view]}> - <Text type="lg" style={pal.link}> - See more from {item.title} - </Text> - <FontAwesomeIcon - icon="angle-right" - size={18} - color={pal.colors.link} - /> - </Link> - ) - } else if (item.type === 'footer') { - return <DiscoverLink /> - } - return null - }, - [pal, isMobile], - ) - - const ListFooter = React.useCallback( - () => - multifeed.isLoading && !isRefreshing ? ( - <View style={styles.loadMore}> - <ActivityIndicator color={pal.colors.text} /> - </View> - ) : ( - <View /> - ), - [multifeed.isLoading, isRefreshing, pal], - ) - - return ( - <View testID={testID} style={style}> - {multifeed.items.length > 0 && ( - <FlatList - testID={testID ? `${testID}-flatlist` : undefined} - ref={scrollElRef} - data={multifeed.items} - keyExtractor={item => item._reactKey} - renderItem={renderItem} - ListFooterComponent={ListFooter} - refreshControl={ - <RefreshControl - refreshing={isRefreshing} - onRefresh={onRefresh} - tintColor={pal.colors.text} - titleColor={pal.colors.text} - progressViewOffset={headerOffset} - /> - } - contentContainerStyle={s.contentContainer} - style={[{paddingTop: headerOffset}, pal.view, styles.container]} - onScroll={onScroll} - scrollEventThrottle={scrollEventThrottle} - indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'} - onEndReached={onEndReached} - onEndReachedThreshold={0.6} - removeClippedSubviews={true} - contentOffset={{x: 0, y: headerOffset * -1}} - extraData={extraData} - // @ts-ignore our .web version only -prf - desktopFixedHeight - /> - )} - </View> - ) -}) - -function DiscoverLink() { - const pal = usePalette('default') - return ( - <Link style={[styles.discoverLink, pal.viewLight]} href="/search/feeds"> - <FontAwesomeIcon icon="search" size={18} color={pal.colors.text} /> - <Text type="xl-medium" style={pal.text}> - Discover new feeds - </Text> - </Link> - ) -} - -const styles = StyleSheet.create({ - container: { - height: '100%', - }, - header: { - borderTopWidth: 1, - marginBottom: 4, - }, - headerDesktop: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - borderBottomWidth: 1, - marginBottom: 4, - paddingHorizontal: 16, - paddingVertical: 8, - }, - feedHeader: { - flexDirection: 'row', - gap: 8, - alignItems: 'center', - paddingHorizontal: 16, - paddingBottom: 8, - marginTop: 12, - }, - feedHeaderTitle: { - fontWeight: 'bold', - }, - feedFooter: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - paddingHorizontal: 16, - paddingVertical: 16, - marginBottom: 12, - borderTopWidth: 1, - borderBottomWidth: 1, - }, - discoverLink: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - borderRadius: 8, - paddingHorizontal: 14, - paddingVertical: 12, - marginHorizontal: 8, - marginVertical: 8, - gap: 8, - }, - loadMore: { - paddingTop: 10, - }, -}) |