about summary refs log tree commit diff
path: root/src/view/com/posts
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/posts')
-rw-r--r--src/view/com/posts/FeedItem.tsx57
-rw-r--r--src/view/com/posts/FeedSlice.tsx2
-rw-r--r--src/view/com/posts/FollowingEmptyState.tsx2
-rw-r--r--src/view/com/posts/MultiFeed.tsx256
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,
-  },
-})