Fix sloppy filter(Boolean) types (#4830)
* Fix sloppy filter(Boolean) in threadgate * Fix sloppy filter(Boolean) in Explore * Fix sloppy filter(Boolean) in post-feed * Harden FeedPostSliceItem.reason type def * Harden parentAuthor types * Fix lying component types, handle blockszio/stable
parent
fac1af43b0
commit
4291711f1d
|
@ -78,7 +78,10 @@ export interface FeedPostSliceItem {
|
||||||
uri: string
|
uri: string
|
||||||
post: AppBskyFeedDefs.PostView
|
post: AppBskyFeedDefs.PostView
|
||||||
record: AppBskyFeedPost.Record
|
record: AppBskyFeedPost.Record
|
||||||
reason?: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource
|
reason?:
|
||||||
|
| AppBskyFeedDefs.ReasonRepost
|
||||||
|
| ReasonFeedSource
|
||||||
|
| {[k: string]: unknown; $type: string}
|
||||||
feedContext: string | undefined
|
feedContext: string | undefined
|
||||||
moderation: ModerationDecision
|
moderation: ModerationDecision
|
||||||
parentAuthor?: AppBskyActorDefs.ProfileViewBasic
|
parentAuthor?: AppBskyActorDefs.ProfileViewBasic
|
||||||
|
@ -323,7 +326,7 @@ export function usePostFeedQuery(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
const feedPostSlice: FeedPostSlice = {
|
||||||
_reactKey: slice._reactKey,
|
_reactKey: slice._reactKey,
|
||||||
_isFeedPostSlice: true,
|
_isFeedPostSlice: true,
|
||||||
rootUri: slice.rootItem.post.uri,
|
rootUri: slice.rootItem.post.uri,
|
||||||
|
@ -341,15 +344,23 @@ export function usePostFeedQuery(
|
||||||
AppBskyFeedPost.validateRecord(item.post.record)
|
AppBskyFeedPost.validateRecord(item.post.record)
|
||||||
.success
|
.success
|
||||||
) {
|
) {
|
||||||
const parentAuthor =
|
const parent = item.reply?.parent
|
||||||
item.reply?.parent?.author ??
|
let parentAuthor:
|
||||||
slice.items[i + 1]?.reply?.grandparentAuthor
|
| AppBskyActorDefs.ProfileViewBasic
|
||||||
|
| undefined
|
||||||
|
if (AppBskyFeedDefs.isPostView(parent)) {
|
||||||
|
parentAuthor = parent.author
|
||||||
|
}
|
||||||
|
if (!parentAuthor) {
|
||||||
|
parentAuthor =
|
||||||
|
slice.items[i + 1]?.reply?.grandparentAuthor
|
||||||
|
}
|
||||||
const replyRef = item.reply
|
const replyRef = item.reply
|
||||||
const isParentBlocked = AppBskyFeedDefs.isBlockedPost(
|
const isParentBlocked = AppBskyFeedDefs.isBlockedPost(
|
||||||
replyRef?.parent,
|
replyRef?.parent,
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
const feedPostSliceItem: FeedPostSliceItem = {
|
||||||
_reactKey: `${slice._reactKey}-${i}-${item.post.uri}`,
|
_reactKey: `${slice._reactKey}-${i}-${item.post.uri}`,
|
||||||
uri: item.post.uri,
|
uri: item.post.uri,
|
||||||
post: item.post,
|
post: item.post,
|
||||||
|
@ -363,13 +374,15 @@ export function usePostFeedQuery(
|
||||||
parentAuthor,
|
parentAuthor,
|
||||||
isParentBlocked,
|
isParentBlocked,
|
||||||
}
|
}
|
||||||
|
return feedPostSliceItem
|
||||||
}
|
}
|
||||||
return undefined
|
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)),
|
||||||
})),
|
})),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ export type ThreadgateSetting =
|
||||||
| {type: 'nobody'}
|
| {type: 'nobody'}
|
||||||
| {type: 'mention'}
|
| {type: 'mention'}
|
||||||
| {type: 'following'}
|
| {type: 'following'}
|
||||||
| {type: 'list'; list: string}
|
| {type: 'list'; list: unknown}
|
||||||
|
|
||||||
export function threadgateViewToSettings(
|
export function threadgateViewToSettings(
|
||||||
threadgate: AppBskyFeedDefs.ThreadgateView | undefined,
|
threadgate: AppBskyFeedDefs.ThreadgateView | undefined,
|
||||||
|
@ -21,18 +21,18 @@ export function threadgateViewToSettings(
|
||||||
if (!record.allow?.length) {
|
if (!record.allow?.length) {
|
||||||
return [{type: 'nobody'}]
|
return [{type: 'nobody'}]
|
||||||
}
|
}
|
||||||
return record.allow
|
const settings: ThreadgateSetting[] = record.allow
|
||||||
.map(allow => {
|
.map(allow => {
|
||||||
|
let setting: ThreadgateSetting | undefined
|
||||||
if (allow.$type === 'app.bsky.feed.threadgate#mentionRule') {
|
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 setting
|
||||||
return {type: 'following'}
|
|
||||||
}
|
|
||||||
if (allow.$type === 'app.bsky.feed.threadgate#listRule') {
|
|
||||||
return {type: 'list', list: allow.list}
|
|
||||||
}
|
|
||||||
return undefined
|
|
||||||
})
|
})
|
||||||
.filter(Boolean) as ThreadgateSetting[]
|
.filter(<T>(n?: T): n is T => Boolean(n))
|
||||||
|
return settings
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,11 @@ import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repos
|
||||||
|
|
||||||
interface FeedItemProps {
|
interface FeedItemProps {
|
||||||
record: AppBskyFeedPost.Record
|
record: AppBskyFeedPost.Record
|
||||||
reason: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource | undefined
|
reason:
|
||||||
|
| AppBskyFeedDefs.ReasonRepost
|
||||||
|
| ReasonFeedSource
|
||||||
|
| {[k: string]: unknown; $type: string}
|
||||||
|
| undefined
|
||||||
moderation: ModerationDecision
|
moderation: ModerationDecision
|
||||||
parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
|
parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
|
||||||
showReplyTo: boolean
|
showReplyTo: boolean
|
||||||
|
@ -337,9 +341,11 @@ let FeedItemInner = ({
|
||||||
postHref={href}
|
postHref={href}
|
||||||
onOpenAuthor={onOpenAuthor}
|
onOpenAuthor={onOpenAuthor}
|
||||||
/>
|
/>
|
||||||
{!isThreadChild && showReplyTo && parentAuthor && (
|
{!isThreadChild &&
|
||||||
<ReplyToLabel blocked={isParentBlocked} profile={parentAuthor} />
|
showReplyTo &&
|
||||||
)}
|
(parentAuthor || isParentBlocked) && (
|
||||||
|
<ReplyToLabel blocked={isParentBlocked} profile={parentAuthor} />
|
||||||
|
)}
|
||||||
<LabelsOnMyPost post={post} />
|
<LabelsOnMyPost post={post} />
|
||||||
<PostContent
|
<PostContent
|
||||||
moderation={moderation}
|
moderation={moderation}
|
||||||
|
@ -431,12 +437,46 @@ function ReplyToLabel({
|
||||||
profile,
|
profile,
|
||||||
blocked,
|
blocked,
|
||||||
}: {
|
}: {
|
||||||
profile: AppBskyActorDefs.ProfileViewBasic
|
profile: AppBskyActorDefs.ProfileViewBasic | undefined
|
||||||
blocked?: boolean
|
blocked?: boolean
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {currentAccount} = useSession()
|
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 (
|
return (
|
||||||
<View style={[s.flexRow, s.mb2, s.alignCenter]}>
|
<View style={[s.flexRow, s.mb2, s.alignCenter]}>
|
||||||
|
@ -450,29 +490,7 @@ function ReplyToLabel({
|
||||||
style={[pal.textLight, s.mr2]}
|
style={[pal.textLight, s.mr2]}
|
||||||
lineHeight={1.2}
|
lineHeight={1.2}
|
||||||
numberOfLines={1}>
|
numberOfLines={1}>
|
||||||
{isMe ? (
|
{label}
|
||||||
<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>
|
|
||||||
)}
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|
|
@ -75,17 +75,17 @@ function SuggestedItemsHeader({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
type LoadMoreItems =
|
type LoadMoreItem =
|
||||||
| {
|
| {
|
||||||
type: 'profile'
|
type: 'profile'
|
||||||
key: string
|
key: string
|
||||||
avatar: string
|
avatar: string | undefined
|
||||||
moderation: ModerationDecision
|
moderation: ModerationDecision
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'feed'
|
type: 'feed'
|
||||||
key: string
|
key: string
|
||||||
avatar: string
|
avatar: string | undefined
|
||||||
moderation: undefined
|
moderation: undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,27 +98,28 @@ function LoadMore({
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const items = React.useMemo(() => {
|
const items: LoadMoreItem[] = React.useMemo(() => {
|
||||||
return item.items
|
return item.items
|
||||||
.map(_item => {
|
.map(_item => {
|
||||||
|
let loadMoreItem: LoadMoreItem | undefined
|
||||||
if (_item.type === 'profile') {
|
if (_item.type === 'profile') {
|
||||||
return {
|
loadMoreItem = {
|
||||||
type: 'profile',
|
type: 'profile',
|
||||||
key: _item.profile.did,
|
key: _item.profile.did,
|
||||||
avatar: _item.profile.avatar,
|
avatar: _item.profile.avatar,
|
||||||
moderation: moderateProfile(_item.profile, moderationOpts!),
|
moderation: moderateProfile(_item.profile, moderationOpts!),
|
||||||
}
|
}
|
||||||
} else if (_item.type === 'feed') {
|
} else if (_item.type === 'feed') {
|
||||||
return {
|
loadMoreItem = {
|
||||||
type: 'feed',
|
type: 'feed',
|
||||||
key: _item.feed.uri,
|
key: _item.feed.uri,
|
||||||
avatar: _item.feed.avatar,
|
avatar: _item.feed.avatar,
|
||||||
moderation: undefined,
|
moderation: undefined,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined
|
return loadMoreItem
|
||||||
})
|
})
|
||||||
.filter(Boolean) as LoadMoreItems[]
|
.filter(<T,>(n?: T): n is T => Boolean(n))
|
||||||
}, [item.items, moderationOpts])
|
}, [item.items, moderationOpts])
|
||||||
|
|
||||||
if (items.length === 0) return null
|
if (items.length === 0) return null
|
||||||
|
|
Loading…
Reference in New Issue