mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import {
2 type $Typed,
3 type AppBskyFeedDefs,
4 type AppBskyFeedPost,
5 type AppBskyUnspeccedDefs,
6 type AppBskyUnspeccedGetPostThreadV2,
7 AtUri,
8 moderatePost,
9 type ModerationOpts,
10} from '@atproto/api'
11
12import {makeProfileLink} from '#/lib/routes/links'
13import {
14 type ApiThreadItem,
15 type ThreadItem,
16 type TraversalMetadata,
17} from '#/state/queries/usePostThread/types'
18
19export function threadPostNoUnauthenticated({
20 uri,
21 depth,
22 value,
23}: ApiThreadItem): Extract<ThreadItem, {type: 'threadPostNoUnauthenticated'}> {
24 return {
25 type: 'threadPostNoUnauthenticated',
26 key: uri,
27 uri,
28 depth,
29 value: value as AppBskyUnspeccedDefs.ThreadItemNoUnauthenticated,
30 // @ts-ignore populated by the traversal
31 ui: {},
32 }
33}
34
35export function threadPostNotFound({
36 uri,
37 depth,
38 value,
39}: ApiThreadItem): Extract<ThreadItem, {type: 'threadPostNotFound'}> {
40 return {
41 type: 'threadPostNotFound',
42 key: uri,
43 uri,
44 depth,
45 value: value as AppBskyUnspeccedDefs.ThreadItemNotFound,
46 }
47}
48
49export function threadPostBlocked({
50 uri,
51 depth,
52 value,
53}: ApiThreadItem): Extract<ThreadItem, {type: 'threadPostBlocked'}> {
54 return {
55 type: 'threadPostBlocked',
56 key: uri,
57 uri,
58 depth,
59 value: value as AppBskyUnspeccedDefs.ThreadItemBlocked,
60 }
61}
62
63export function threadPost({
64 uri,
65 depth,
66 value,
67 moderationOpts,
68 threadgateHiddenReplies,
69}: {
70 uri: string
71 depth: number
72 value: $Typed<AppBskyUnspeccedDefs.ThreadItemPost>
73 moderationOpts: ModerationOpts
74 threadgateHiddenReplies: Set<string>
75}): Extract<ThreadItem, {type: 'threadPost'}> {
76 const moderation = moderatePost(value.post, moderationOpts)
77 const modui = moderation.ui('contentList')
78 const blurred = modui.blur || modui.filter
79 const muted = (modui.blurs[0] || modui.filters[0])?.type === 'muted'
80 const hiddenByThreadgate = threadgateHiddenReplies.has(uri)
81 const isOwnPost = value.post.author.did === moderationOpts.userDid
82 const isBlurred = (hiddenByThreadgate || blurred || muted) && !isOwnPost
83 return {
84 type: 'threadPost',
85 key: uri,
86 uri,
87 depth,
88 value: {
89 ...value,
90 /*
91 * Do not spread anything here, load bearing for post shadow strict
92 * equality reference checks.
93 */
94 post: value.post as Omit<AppBskyFeedDefs.PostView, 'record'> & {
95 record: AppBskyFeedPost.Record
96 },
97 },
98 isBlurred,
99 moderation,
100 // @ts-ignore populated by the traversal
101 ui: {},
102 }
103}
104
105export function readMore({
106 depth,
107 repliesUnhydrated,
108 skippedIndentIndices,
109 postData,
110}: TraversalMetadata): Extract<ThreadItem, {type: 'readMore'}> {
111 const urip = new AtUri(postData.uri)
112 const href = makeProfileLink(
113 {
114 did: urip.host,
115 handle: postData.authorHandle,
116 },
117 'post',
118 urip.rkey,
119 )
120 return {
121 type: 'readMore' as const,
122 key: `readMore:${postData.uri}`,
123 href,
124 moreReplies: repliesUnhydrated,
125 depth,
126 skippedIndentIndices,
127 }
128}
129
130export function readMoreUp({
131 postData,
132}: TraversalMetadata): Extract<ThreadItem, {type: 'readMoreUp'}> {
133 const urip = new AtUri(postData.uri)
134 const href = makeProfileLink(
135 {
136 did: urip.host,
137 handle: postData.authorHandle,
138 },
139 'post',
140 urip.rkey,
141 )
142 return {
143 type: 'readMoreUp' as const,
144 key: `readMoreUp:${postData.uri}`,
145 href,
146 }
147}
148
149export function skeleton({
150 key,
151 item,
152}: Omit<Extract<ThreadItem, {type: 'skeleton'}>, 'type'>): Extract<
153 ThreadItem,
154 {type: 'skeleton'}
155> {
156 return {
157 type: 'skeleton',
158 key,
159 item,
160 }
161}
162
163export function postViewToThreadPlaceholder(
164 post: AppBskyFeedDefs.PostView,
165): $Typed<
166 Omit<AppBskyUnspeccedGetPostThreadV2.ThreadItem, 'value'> & {
167 value: $Typed<AppBskyUnspeccedDefs.ThreadItemPost>
168 }
169> {
170 return {
171 $type: 'app.bsky.unspecced.getPostThreadV2#threadItem',
172 uri: post.uri,
173 depth: 0, // reset to 0 for highlighted post
174 value: {
175 $type: 'app.bsky.unspecced.defs#threadItemPost',
176 post,
177 opThread: false,
178 moreParents: false,
179 moreReplies: 0,
180 hiddenByThreadgate: false,
181 mutedByViewer: false,
182 },
183 }
184}