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 isBlurred = hiddenByThreadgate || blurred || muted
82 return {
83 type: 'threadPost',
84 key: uri,
85 uri,
86 depth,
87 value: {
88 ...value,
89 /*
90 * Do not spread anything here, load bearing for post shadow strict
91 * equality reference checks.
92 */
93 post: value.post as Omit<AppBskyFeedDefs.PostView, 'record'> & {
94 record: AppBskyFeedPost.Record
95 },
96 },
97 isBlurred,
98 moderation,
99 // @ts-ignore populated by the traversal
100 ui: {},
101 }
102}
103
104export function readMore({
105 depth,
106 repliesUnhydrated,
107 skippedIndentIndices,
108 postData,
109}: TraversalMetadata): Extract<ThreadItem, {type: 'readMore'}> {
110 const urip = new AtUri(postData.uri)
111 const href = makeProfileLink(
112 {
113 did: urip.host,
114 handle: postData.authorHandle,
115 },
116 'post',
117 urip.rkey,
118 )
119 return {
120 type: 'readMore' as const,
121 key: `readMore:${postData.uri}`,
122 href,
123 moreReplies: repliesUnhydrated,
124 depth,
125 skippedIndentIndices,
126 }
127}
128
129export function readMoreUp({
130 postData,
131}: TraversalMetadata): Extract<ThreadItem, {type: 'readMoreUp'}> {
132 const urip = new AtUri(postData.uri)
133 const href = makeProfileLink(
134 {
135 did: urip.host,
136 handle: postData.authorHandle,
137 },
138 'post',
139 urip.rkey,
140 )
141 return {
142 type: 'readMoreUp' as const,
143 key: `readMoreUp:${postData.uri}`,
144 href,
145 }
146}
147
148export function skeleton({
149 key,
150 item,
151}: Omit<Extract<ThreadItem, {type: 'skeleton'}>, 'type'>): Extract<
152 ThreadItem,
153 {type: 'skeleton'}
154> {
155 return {
156 type: 'skeleton',
157 key,
158 item,
159 }
160}
161
162export function postViewToThreadPlaceholder(
163 post: AppBskyFeedDefs.PostView,
164): $Typed<
165 Omit<AppBskyUnspeccedGetPostThreadV2.ThreadItem, 'value'> & {
166 value: $Typed<AppBskyUnspeccedDefs.ThreadItemPost>
167 }
168> {
169 return {
170 $type: 'app.bsky.unspecced.getPostThreadV2#threadItem',
171 uri: post.uri,
172 depth: 0, // reset to 0 for highlighted post
173 value: {
174 $type: 'app.bsky.unspecced.defs#threadItemPost',
175 post,
176 opThread: false,
177 moreParents: false,
178 moreReplies: 0,
179 hiddenByThreadgate: false,
180 mutedByViewer: false,
181 },
182 }
183}