about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/state/queries/post-feed.ts29
-rw-r--r--src/state/queries/threadgate.ts22
-rw-r--r--src/view/com/posts/FeedItem.tsx76
-rw-r--r--src/view/screens/Search/Explore.tsx17
4 files changed, 88 insertions, 56 deletions
diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts
index 315c9cfad..c1484a59e 100644
--- a/src/state/queries/post-feed.ts
+++ b/src/state/queries/post-feed.ts
@@ -78,7 +78,10 @@ export interface FeedPostSliceItem {
   uri: string
   post: AppBskyFeedDefs.PostView
   record: AppBskyFeedPost.Record
-  reason?: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource
+  reason?:
+    | AppBskyFeedDefs.ReasonRepost
+    | ReasonFeedSource
+    | {[k: string]: unknown; $type: string}
   feedContext: string | undefined
   moderation: ModerationDecision
   parentAuthor?: AppBskyActorDefs.ProfileViewBasic
@@ -323,7 +326,7 @@ export function usePostFeedQuery(
                     )
                   }
 
-                  return {
+                  const feedPostSlice: FeedPostSlice = {
                     _reactKey: slice._reactKey,
                     _isFeedPostSlice: true,
                     rootUri: slice.rootItem.post.uri,
@@ -341,15 +344,23 @@ export function usePostFeedQuery(
                           AppBskyFeedPost.validateRecord(item.post.record)
                             .success
                         ) {
-                          const parentAuthor =
-                            item.reply?.parent?.author ??
-                            slice.items[i + 1]?.reply?.grandparentAuthor
+                          const parent = item.reply?.parent
+                          let parentAuthor:
+                            | AppBskyActorDefs.ProfileViewBasic
+                            | undefined
+                          if (AppBskyFeedDefs.isPostView(parent)) {
+                            parentAuthor = parent.author
+                          }
+                          if (!parentAuthor) {
+                            parentAuthor =
+                              slice.items[i + 1]?.reply?.grandparentAuthor
+                          }
                           const replyRef = item.reply
                           const isParentBlocked = AppBskyFeedDefs.isBlockedPost(
                             replyRef?.parent,
                           )
 
-                          return {
+                          const feedPostSliceItem: FeedPostSliceItem = {
                             _reactKey: `${slice._reactKey}-${i}-${item.post.uri}`,
                             uri: item.post.uri,
                             post: item.post,
@@ -363,13 +374,15 @@ export function usePostFeedQuery(
                             parentAuthor,
                             isParentBlocked,
                           }
+                          return feedPostSliceItem
                         }
                         return undefined
                       })
-                      .filter(Boolean) as FeedPostSliceItem[],
+                      .filter(<T>(n?: T): n is T => Boolean(n)),
                   }
+                  return feedPostSlice
                 })
-                .filter(Boolean) as FeedPostSlice[],
+                .filter(<T>(n?: T): n is T => Boolean(n)),
             })),
           ],
         }
diff --git a/src/state/queries/threadgate.ts b/src/state/queries/threadgate.ts
index 67c6f8c08..c05d1f564 100644
--- a/src/state/queries/threadgate.ts
+++ b/src/state/queries/threadgate.ts
@@ -4,7 +4,7 @@ export type ThreadgateSetting =
   | {type: 'nobody'}
   | {type: 'mention'}
   | {type: 'following'}
-  | {type: 'list'; list: string}
+  | {type: 'list'; list: unknown}
 
 export function threadgateViewToSettings(
   threadgate: AppBskyFeedDefs.ThreadgateView | undefined,
@@ -21,18 +21,18 @@ export function threadgateViewToSettings(
   if (!record.allow?.length) {
     return [{type: 'nobody'}]
   }
-  return record.allow
+  const settings: ThreadgateSetting[] = record.allow
     .map(allow => {
+      let setting: ThreadgateSetting | undefined
       if (allow.$type === 'app.bsky.feed.threadgate#mentionRule') {
-        return {type: 'mention'}
+        setting = {type: 'mention'}
+      } else if (allow.$type === 'app.bsky.feed.threadgate#followingRule') {
+        setting = {type: 'following'}
+      } else if (allow.$type === 'app.bsky.feed.threadgate#listRule') {
+        setting = {type: 'list', list: allow.list}
       }
-      if (allow.$type === 'app.bsky.feed.threadgate#followingRule') {
-        return {type: 'following'}
-      }
-      if (allow.$type === 'app.bsky.feed.threadgate#listRule') {
-        return {type: 'list', list: allow.list}
-      }
-      return undefined
+      return setting
     })
-    .filter(Boolean) as ThreadgateSetting[]
+    .filter(<T>(n?: T): n is T => Boolean(n))
+  return settings
 }
diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx
index a59eeea52..dbc5796db 100644
--- a/src/view/com/posts/FeedItem.tsx
+++ b/src/view/com/posts/FeedItem.tsx
@@ -48,7 +48,11 @@ import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repos
 
 interface FeedItemProps {
   record: AppBskyFeedPost.Record
-  reason: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource | undefined
+  reason:
+    | AppBskyFeedDefs.ReasonRepost
+    | ReasonFeedSource
+    | {[k: string]: unknown; $type: string}
+    | undefined
   moderation: ModerationDecision
   parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
   showReplyTo: boolean
@@ -337,9 +341,11 @@ let FeedItemInner = ({
             postHref={href}
             onOpenAuthor={onOpenAuthor}
           />
-          {!isThreadChild && showReplyTo && parentAuthor && (
-            <ReplyToLabel blocked={isParentBlocked} profile={parentAuthor} />
-          )}
+          {!isThreadChild &&
+            showReplyTo &&
+            (parentAuthor || isParentBlocked) && (
+              <ReplyToLabel blocked={isParentBlocked} profile={parentAuthor} />
+            )}
           <LabelsOnMyPost post={post} />
           <PostContent
             moderation={moderation}
@@ -431,12 +437,46 @@ function ReplyToLabel({
   profile,
   blocked,
 }: {
-  profile: AppBskyActorDefs.ProfileViewBasic
+  profile: AppBskyActorDefs.ProfileViewBasic | undefined
   blocked?: boolean
 }) {
   const pal = usePalette('default')
   const {currentAccount} = useSession()
-  const isMe = profile.did === currentAccount?.did
+
+  let label
+  if (blocked) {
+    label = <Trans context="description">Reply to a blocked post</Trans>
+  } else if (profile != null) {
+    const isMe = profile.did === currentAccount?.did
+    if (isMe) {
+      label = <Trans context="description">Reply to you</Trans>
+    } else {
+      label = (
+        <Trans context="description">
+          Reply to{' '}
+          <ProfileHoverCard inline did={profile.did}>
+            <TextLinkOnWebOnly
+              type="md"
+              style={pal.textLight}
+              lineHeight={1.2}
+              numberOfLines={1}
+              href={makeProfileLink(profile)}
+              text={
+                profile.displayName
+                  ? sanitizeDisplayName(profile.displayName)
+                  : sanitizeHandle(profile.handle)
+              }
+            />
+          </ProfileHoverCard>
+        </Trans>
+      )
+    }
+  }
+
+  if (!label) {
+    // Should not happen.
+    return null
+  }
 
   return (
     <View style={[s.flexRow, s.mb2, s.alignCenter]}>
@@ -450,29 +490,7 @@ function ReplyToLabel({
         style={[pal.textLight, s.mr2]}
         lineHeight={1.2}
         numberOfLines={1}>
-        {isMe ? (
-          <Trans context="description">Reply to you</Trans>
-        ) : blocked ? (
-          <Trans context="description">Reply to a blocked post</Trans>
-        ) : (
-          <Trans context="description">
-            Reply to{' '}
-            <ProfileHoverCard inline did={profile.did}>
-              <TextLinkOnWebOnly
-                type="md"
-                style={pal.textLight}
-                lineHeight={1.2}
-                numberOfLines={1}
-                href={makeProfileLink(profile)}
-                text={
-                  profile.displayName
-                    ? sanitizeDisplayName(profile.displayName)
-                    : sanitizeHandle(profile.handle)
-                }
-              />
-            </ProfileHoverCard>
-          </Trans>
-        )}
+        {label}
       </Text>
     </View>
   )
diff --git a/src/view/screens/Search/Explore.tsx b/src/view/screens/Search/Explore.tsx
index 05fd85eff..e9b744527 100644
--- a/src/view/screens/Search/Explore.tsx
+++ b/src/view/screens/Search/Explore.tsx
@@ -75,17 +75,17 @@ function SuggestedItemsHeader({
   )
 }
 
-type LoadMoreItems =
+type LoadMoreItem =
   | {
       type: 'profile'
       key: string
-      avatar: string
+      avatar: string | undefined
       moderation: ModerationDecision
     }
   | {
       type: 'feed'
       key: string
-      avatar: string
+      avatar: string | undefined
       moderation: undefined
     }
 
@@ -98,27 +98,28 @@ function LoadMore({
 }) {
   const t = useTheme()
   const {_} = useLingui()
-  const items = React.useMemo(() => {
+  const items: LoadMoreItem[] = React.useMemo(() => {
     return item.items
       .map(_item => {
+        let loadMoreItem: LoadMoreItem | undefined
         if (_item.type === 'profile') {
-          return {
+          loadMoreItem = {
             type: 'profile',
             key: _item.profile.did,
             avatar: _item.profile.avatar,
             moderation: moderateProfile(_item.profile, moderationOpts!),
           }
         } else if (_item.type === 'feed') {
-          return {
+          loadMoreItem = {
             type: 'feed',
             key: _item.feed.uri,
             avatar: _item.feed.avatar,
             moderation: undefined,
           }
         }
-        return undefined
+        return loadMoreItem
       })
-      .filter(Boolean) as LoadMoreItems[]
+      .filter(<T,>(n?: T): n is T => Boolean(n))
   }, [item.items, moderationOpts])
 
   if (items.length === 0) return null