about summary refs log tree commit diff
path: root/src/view/screens/CustomFeed.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/screens/CustomFeed.tsx')
-rw-r--r--src/view/screens/CustomFeed.tsx391
1 files changed, 133 insertions, 258 deletions
diff --git a/src/view/screens/CustomFeed.tsx b/src/view/screens/CustomFeed.tsx
index af4d01843..eaa21f292 100644
--- a/src/view/screens/CustomFeed.tsx
+++ b/src/view/screens/CustomFeed.tsx
@@ -1,7 +1,7 @@
 import React, {useMemo, useRef} from 'react'
 import {NativeStackScreenProps} from '@react-navigation/native-stack'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {useNavigation} from '@react-navigation/native'
+import {useNavigation, useIsFocused} from '@react-navigation/native'
 import {usePalette} from 'lib/hooks/usePalette'
 import {HeartIcon, HeartIconSolid} from 'lib/icons'
 import {CommonNavigatorParams} from 'lib/routes/types'
@@ -14,11 +14,8 @@ import {PostsFeedModel} from 'state/models/feeds/posts'
 import {useCustomFeed} from 'lib/hooks/useCustomFeed'
 import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {Feed} from 'view/com/posts/Feed'
-import {pluralize} from 'lib/strings/helpers'
-import {sanitizeHandle} from 'lib/strings/handles'
 import {TextLink} from 'view/com/util/Link'
-import {UserAvatar} from 'view/com/util/UserAvatar'
-import {ViewHeader} from 'view/com/util/ViewHeader'
+import {SimpleViewHeader} from 'view/com/util/SimpleViewHeader'
 import {Button} from 'view/com/util/forms/Button'
 import {Text} from 'view/com/util/text/Text'
 import * as Toast from 'view/com/util/Toast'
@@ -34,7 +31,6 @@ import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
 import {EmptyState} from 'view/com/util/EmptyState'
 import {useAnalytics} from 'lib/analytics/analytics'
 import {NativeDropdown, DropdownItem} from 'view/com/util/forms/NativeDropdown'
-import {makeProfileLink} from 'lib/routes/links'
 import {resolveName} from 'lib/api'
 import {CenteredView} from 'view/com/util/Views'
 import {NavigationProp} from 'lib/routes/types'
@@ -125,7 +121,10 @@ export const CustomFeedScreenInner = observer(
   }: Props & {feedOwnerDid: string}) {
     const store = useStores()
     const pal = usePalette('default')
-    const {isTabletOrDesktop} = useWebMediaQueries()
+    const palInverted = usePalette('inverted')
+    const navigation = useNavigation<NavigationProp>()
+    const isScreenFocused = useIsFocused()
+    const {isMobile, isTabletOrDesktop} = useWebMediaQueries()
     const {track} = useAnalytics()
     const {rkey, name: handleOrDid} = route.params
     const uri = useMemo(
@@ -186,6 +185,10 @@ export const CustomFeedScreenInner = observer(
       })
     }, [store, currentFeed])
 
+    const onPressViewAuthor = React.useCallback(() => {
+      navigation.navigate('Profile', {name: handleOrDid})
+    }, [handleOrDid, navigation])
+
     const onPressShare = React.useCallback(() => {
       const url = toShareUrl(`/profile/${handleOrDid}/feed/${rkey}`)
       shareUrl(url)
@@ -210,9 +213,40 @@ export const CustomFeedScreenInner = observer(
       store.shell.openComposer({})
     }, [store])
 
+    const onSoftReset = React.useCallback(() => {
+      if (isScreenFocused) {
+        onScrollToTop()
+        algoFeed.refresh()
+      }
+    }, [isScreenFocused, onScrollToTop, algoFeed])
+
+    // fires when page within screen is activated/deactivated
+    React.useEffect(() => {
+      if (!isScreenFocused) {
+        return
+      }
+
+      const softResetSub = store.onScreenSoftReset(onSoftReset)
+      return () => {
+        softResetSub.remove()
+      }
+    }, [store, onSoftReset, isScreenFocused])
+
     const dropdownItems: DropdownItem[] = React.useMemo(() => {
       let items: DropdownItem[] = [
         {
+          testID: 'feedHeaderDropdownViewAuthorBtn',
+          label: 'View author',
+          onPress: onPressViewAuthor,
+          icon: {
+            ios: {
+              name: 'person',
+            },
+            android: '',
+            web: ['far', 'user'],
+          },
+        },
+        {
           testID: 'feedHeaderDropdownToggleSavedBtn',
           label: currentFeed?.isSaved
             ? 'Remove from my feeds'
@@ -260,232 +294,12 @@ export const CustomFeedScreenInner = observer(
         },
       ]
       return items
-    }, [currentFeed?.isSaved, onToggleSaved, onPressReport, onPressShare])
-
-    const renderHeaderBtns = React.useCallback(() => {
-      return (
-        <View style={styles.headerBtns}>
-          <Button
-            type="default-light"
-            testID="toggleLikeBtn"
-            accessibilityLabel="Like this feed"
-            accessibilityHint=""
-            onPress={onToggleLiked}>
-            {currentFeed?.isLiked ? (
-              <HeartIconSolid size={19} style={styles.liked} />
-            ) : (
-              <HeartIcon strokeWidth={3} size={19} style={pal.textLight} />
-            )}
-          </Button>
-          {currentFeed?.isSaved ? (
-            <Button
-              type="default-light"
-              accessibilityLabel={
-                isPinned ? 'Unpin this feed' : 'Pin this feed'
-              }
-              accessibilityHint=""
-              onPress={onTogglePinned}>
-              <FontAwesomeIcon
-                icon="thumb-tack"
-                size={17}
-                color={isPinned ? colors.blue3 : pal.colors.textLight}
-                style={styles.top1}
-              />
-            </Button>
-          ) : undefined}
-          {!currentFeed?.isSaved ? (
-            <Button
-              type="default-light"
-              onPress={onToggleSaved}
-              accessibilityLabel="Add to my feeds"
-              accessibilityHint=""
-              style={styles.headerAddBtn}>
-              <FontAwesomeIcon icon="plus" color={pal.colors.link} size={19} />
-              <Text type="xl-medium" style={pal.link}>
-                Add to My Feeds
-              </Text>
-            </Button>
-          ) : null}
-          <NativeDropdown testID="feedHeaderDropdownBtn" items={dropdownItems}>
-            <View
-              style={{
-                paddingLeft: currentFeed?.isSaved ? 12 : 6,
-                paddingRight: 12,
-                paddingVertical: 8,
-              }}>
-              <FontAwesomeIcon
-                icon="ellipsis"
-                size={20}
-                color={pal.colors.textLight}
-              />
-            </View>
-          </NativeDropdown>
-        </View>
-      )
     }, [
-      pal,
       currentFeed?.isSaved,
-      currentFeed?.isLiked,
-      isPinned,
-      onToggleSaved,
-      onTogglePinned,
-      onToggleLiked,
-      dropdownItems,
-    ])
-
-    const renderListHeaderComponent = React.useCallback(() => {
-      return (
-        <>
-          <View style={[styles.header, pal.border]}>
-            <View style={s.flex1}>
-              <Text
-                testID="feedName"
-                type="title-xl"
-                style={[pal.text, s.bold]}>
-                {currentFeed?.displayName}
-              </Text>
-              {currentFeed && (
-                <Text type="md" style={[pal.textLight]} numberOfLines={1}>
-                  by{' '}
-                  {currentFeed.data.creator.did === store.me.did ? (
-                    'you'
-                  ) : (
-                    <TextLink
-                      text={sanitizeHandle(
-                        currentFeed.data.creator.handle,
-                        '@',
-                      )}
-                      href={makeProfileLink(currentFeed.data.creator)}
-                      style={[pal.textLight]}
-                    />
-                  )}
-                </Text>
-              )}
-              {isTabletOrDesktop && (
-                <View style={[styles.headerBtns, styles.headerBtnsDesktop]}>
-                  <Button
-                    type={currentFeed?.isSaved ? 'default' : 'inverted'}
-                    onPress={onToggleSaved}
-                    accessibilityLabel={
-                      currentFeed?.isSaved
-                        ? 'Unsave this feed'
-                        : 'Save this feed'
-                    }
-                    accessibilityHint=""
-                    label={
-                      currentFeed?.isSaved
-                        ? 'Remove from My Feeds'
-                        : 'Add to My Feeds'
-                    }
-                  />
-                  <Button
-                    type="default"
-                    accessibilityLabel={
-                      isPinned ? 'Unpin this feed' : 'Pin this feed'
-                    }
-                    accessibilityHint=""
-                    onPress={onTogglePinned}>
-                    <FontAwesomeIcon
-                      icon="thumb-tack"
-                      size={15}
-                      color={isPinned ? colors.blue3 : pal.colors.icon}
-                      style={styles.top2}
-                    />
-                  </Button>
-                  <Button
-                    type="default"
-                    accessibilityLabel="Like this feed"
-                    accessibilityHint=""
-                    onPress={onToggleLiked}>
-                    {currentFeed?.isLiked ? (
-                      <HeartIconSolid size={18} style={styles.liked} />
-                    ) : (
-                      <HeartIcon strokeWidth={3} size={18} style={pal.icon} />
-                    )}
-                  </Button>
-                  <Button
-                    type="default"
-                    accessibilityLabel="Share this feed"
-                    accessibilityHint=""
-                    onPress={onPressShare}>
-                    <FontAwesomeIcon
-                      icon="share"
-                      size={18}
-                      color={pal.colors.icon}
-                    />
-                  </Button>
-                  <Button
-                    type="default"
-                    accessibilityLabel="Report this feed"
-                    accessibilityHint=""
-                    onPress={onPressReport}>
-                    <FontAwesomeIcon
-                      icon="circle-exclamation"
-                      size={18}
-                      color={pal.colors.icon}
-                    />
-                  </Button>
-                </View>
-              )}
-            </View>
-            <View>
-              <UserAvatar
-                type="algo"
-                avatar={currentFeed?.data.avatar}
-                size={64}
-              />
-            </View>
-          </View>
-          <View style={styles.headerDetails}>
-            {currentFeed?.data.description ? (
-              <Text style={[pal.text, s.mb10]} numberOfLines={6}>
-                {currentFeed.data.description}
-              </Text>
-            ) : null}
-            <View style={styles.headerDetailsFooter}>
-              {currentFeed ? (
-                <TextLink
-                  type="md-medium"
-                  style={pal.textLight}
-                  href={`/profile/${handleOrDid}/feed/${rkey}/liked-by`}
-                  text={`Liked by ${currentFeed.data.likeCount} ${pluralize(
-                    currentFeed?.data.likeCount || 0,
-                    'user',
-                  )}`}
-                />
-              ) : null}
-            </View>
-          </View>
-          <View
-            style={[
-              styles.fakeSelector,
-              {
-                paddingHorizontal: isTabletOrDesktop ? 16 : 6,
-              },
-              pal.border,
-            ]}>
-            <View
-              style={[styles.fakeSelectorItem, {borderColor: pal.colors.link}]}>
-              <Text type="md-medium" style={[pal.text]}>
-                Feed
-              </Text>
-            </View>
-          </View>
-        </>
-      )
-    }, [
-      pal,
-      currentFeed,
-      store.me.did,
       onToggleSaved,
-      onToggleLiked,
-      onPressShare,
-      handleOrDid,
       onPressReport,
-      rkey,
-      isPinned,
-      onTogglePinned,
-      isTabletOrDesktop,
+      onPressShare,
+      onPressViewAuthor,
     ])
 
     const renderEmptyState = React.useCallback(() => {
@@ -498,22 +312,100 @@ export const CustomFeedScreenInner = observer(
 
     return (
       <View style={s.hContentRegion}>
-        {!isTabletOrDesktop && (
-          <ViewHeader title="" renderButton={currentFeed && renderHeaderBtns} />
-        )}
+        <SimpleViewHeader
+          showBackButton={isMobile}
+          style={
+            !isMobile && [pal.border, {borderLeftWidth: 1, borderRightWidth: 1}]
+          }>
+          <Text type="title-lg" style={styles.headerText} numberOfLines={1}>
+            {currentFeed ? (
+              <TextLink
+                type="title-lg"
+                href="/"
+                style={[pal.text, {fontWeight: 'bold'}]}
+                text={currentFeed?.displayName || ''}
+                onPress={() => store.emitScreenSoftReset()}
+              />
+            ) : (
+              'Loading...'
+            )}
+          </Text>
+          {currentFeed ? (
+            <>
+              <Button
+                type="default-light"
+                testID="toggleLikeBtn"
+                accessibilityLabel="Like this feed"
+                accessibilityHint=""
+                onPress={onToggleLiked}
+                style={styles.headerBtn}>
+                {currentFeed?.isLiked ? (
+                  <HeartIconSolid size={19} style={styles.liked} />
+                ) : (
+                  <HeartIcon strokeWidth={3} size={19} style={pal.textLight} />
+                )}
+              </Button>
+              {currentFeed?.isSaved ? (
+                <Button
+                  type="default-light"
+                  accessibilityLabel={
+                    isPinned ? 'Unpin this feed' : 'Pin this feed'
+                  }
+                  accessibilityHint=""
+                  onPress={onTogglePinned}
+                  style={styles.headerBtn}>
+                  <FontAwesomeIcon
+                    icon="thumb-tack"
+                    size={17}
+                    color={isPinned ? colors.blue3 : pal.colors.textLight}
+                    style={styles.top1}
+                  />
+                </Button>
+              ) : (
+                <Button
+                  type="inverted"
+                  onPress={onToggleSaved}
+                  accessibilityLabel="Add to my feeds"
+                  accessibilityHint=""
+                  style={styles.headerAddBtn}>
+                  <FontAwesomeIcon
+                    icon="plus"
+                    color={palInverted.colors.text}
+                    size={19}
+                  />
+                  <Text type="button" style={palInverted.text}>
+                    Add{!isMobile && ' to My Feeds'}
+                  </Text>
+                </Button>
+              )}
+            </>
+          ) : null}
+          <NativeDropdown testID="feedHeaderDropdownBtn" items={dropdownItems}>
+            <View
+              style={{
+                paddingLeft: 12,
+                paddingRight: isMobile ? 12 : 0,
+              }}>
+              <FontAwesomeIcon
+                icon="ellipsis"
+                size={20}
+                color={pal.colors.textLight}
+              />
+            </View>
+          </NativeDropdown>
+        </SimpleViewHeader>
         <Feed
           scrollElRef={scrollElRef}
           feed={algoFeed}
           onScroll={onMainScroll}
           scrollEventThrottle={100}
-          ListHeaderComponent={renderListHeaderComponent}
           renderEmptyState={renderEmptyState}
           extraData={[uri, isPinned]}
           style={!isTabletOrDesktop ? {flex: 1} : undefined}
         />
         {isScrolledDown ? (
           <LoadLatestBtn
-            onPress={onScrollToTop}
+            onPress={onSoftReset}
             label="Scroll to top"
             showIndicator={false}
           />
@@ -540,36 +432,19 @@ const styles = StyleSheet.create({
     paddingBottom: 16,
     borderTopWidth: 1,
   },
-  headerBtns: {
-    flexDirection: 'row',
-    alignItems: 'center',
+  headerText: {
+    flex: 1,
+    fontWeight: 'bold',
   },
-  headerBtnsDesktop: {
-    marginTop: 8,
-    gap: 4,
+  headerBtn: {
+    paddingVertical: 0,
   },
   headerAddBtn: {
     flexDirection: 'row',
     alignItems: 'center',
     gap: 4,
-    paddingLeft: 4,
-  },
-  headerDetails: {
-    paddingHorizontal: 16,
-    paddingBottom: 16,
-  },
-  headerDetailsFooter: {
-    flexDirection: 'row',
-    alignItems: 'center',
-    justifyContent: 'space-between',
-  },
-  fakeSelector: {
-    flexDirection: 'row',
-  },
-  fakeSelectorItem: {
-    paddingHorizontal: 12,
-    paddingBottom: 8,
-    borderBottomWidth: 3,
+    paddingVertical: 4,
+    paddingLeft: 10,
   },
   liked: {
     color: colors.red3,