tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
28
pulls
pipelines
cleaned up naming
cozylittle.house
1 month ago
4b18fdf3
75b0ea62
+214
-225
7 changed files
expand all
collapse all
unified
split
app
lish
[did]
[publication]
[rkey]
Blocks
PublishBskyPostBlock.tsx
BlueskyQuotesPage.tsx
BskyPostContent.tsx
Interactions
Quotes.tsx
PostLinks.tsx
PostPages.tsx
ThreadPage.tsx
+1
-1
app/lish/[did]/[publication]/[rkey]/Blocks/PublishBskyPostBlock.tsx
···
113
113
{post.replyCount != null && post.replyCount > 0 && (
114
114
<>
115
115
<ThreadLink
116
116
-
threadUri={post.uri}
116
116
+
postUri={post.uri}
117
117
parent={parent}
118
118
className="flex items-center gap-1 hover:text-accent-contrast"
119
119
onClick={(e) => e.stopPropagation()}
+8
-12
app/lish/[did]/[publication]/[rkey]/BlueskyQuotesPage.tsx
···
87
87
const parent = { type: "quotes" as const, uri: quotesUri };
88
88
89
89
return (
90
90
-
<div
91
91
-
className="flex gap-2 relative py-2 px-2 hover:bg-bg-page rounded cursor-pointer"
92
92
-
onClick={() => openPage(parent, { type: "thread", uri: post.uri })}
93
93
-
>
94
94
-
<BskyPostContent
95
95
-
post={post}
96
96
-
parent={parent}
97
97
-
showEmbed={true}
98
98
-
showBlueskyLink={true}
99
99
-
onEmbedClick={(e) => e.stopPropagation()}
100
100
-
/>
101
101
-
</div>
90
90
+
<BskyPostContent
91
91
+
post={post}
92
92
+
parent={parent}
93
93
+
showEmbed={true}
94
94
+
showBlueskyLink={true}
95
95
+
onEmbedClick={(e) => e.stopPropagation()}
96
96
+
className="relative py-2 px-2 hover:bg-bg-page rounded cursor-pointer"
97
97
+
/>
102
98
);
103
99
}
+139
-106
app/lish/[did]/[publication]/[rkey]/BskyPostContent.tsx
···
8
8
import { Separator } from "components/Layout";
9
9
import { useLocalizedDate } from "src/hooks/useLocalizedDate";
10
10
import { useHasPageLoaded } from "components/InitialPageLoadProvider";
11
11
-
import { OpenPage } from "./PostPages";
11
11
+
import { OpenPage, openPage } from "./PostPages";
12
12
import { ThreadLink, QuotesLink } from "./PostLinks";
13
13
import { BlueskyLinkTiny } from "components/Icons/BlueskyLinkTiny";
14
14
import { Avatar } from "components/Avatar";
···
25
25
showEmbed?: boolean;
26
26
showBlueskyLink?: boolean;
27
27
onEmbedClick?: (e: React.MouseEvent) => void;
28
28
-
quoteCountOnClick?: (e: React.MouseEvent) => void;
29
29
-
replyCountOnClick?: (e: React.MouseEvent) => void;
28
28
+
quoteEnabled?: boolean;
29
29
+
replyEnabled?: boolean;
30
30
+
replyOnClick?: (e: React.MouseEvent) => void;
31
31
+
replyLine?: {
32
32
+
onToggle: (e: React.MouseEvent) => void;
33
33
+
};
30
34
}) {
31
35
const {
32
36
post,
···
35
39
showEmbed = true,
36
40
showBlueskyLink = true,
37
41
onEmbedClick,
38
38
-
quoteCountOnClick,
39
39
-
replyCountOnClick,
42
42
+
quoteEnabled,
43
43
+
replyEnabled,
44
44
+
replyOnClick,
45
45
+
replyLine,
40
46
} = props;
41
47
42
48
const record = post.record as AppBskyFeedPost.Record;
···
44
50
const url = `https://bsky.app/profile/${post.author.handle}/post/${postId}`;
45
51
46
52
return (
47
47
-
<>
48
48
-
<Avatar
49
49
-
src={post.author.avatar}
50
50
-
displayName={post.author.displayName}
51
51
-
size={props.avatarSize ? props.avatarSize : "medium"}
52
52
-
/>
53
53
+
<div className="bskyPost relative flex flex-col">
54
54
+
{replyLine && (
55
55
+
<div className="replyLine absolute top-0 bottom-0 shrink-0 w-6 bg-test">
56
56
+
<button
57
57
+
onClick={(e) => {
58
58
+
e.preventDefault();
59
59
+
e.stopPropagation();
60
60
+
replyLine.onToggle(e);
61
61
+
console.log("clicked");
62
62
+
}}
63
63
+
className="w-full h-full flex justify-center"
64
64
+
aria-label="Toggle replies"
65
65
+
>
66
66
+
<div className="w-0.5 h-full bg-border-light" />
67
67
+
</button>
68
68
+
</div>
69
69
+
)}
70
70
+
<button
71
71
+
className={`flex gap-2 text-left ${props.className}`}
72
72
+
onClick={() => {
73
73
+
openPage(parent, { type: "thread", uri: post.uri });
74
74
+
console.log("do this");
75
75
+
}}
76
76
+
>
77
77
+
<Avatar
78
78
+
src={post.author.avatar}
79
79
+
displayName={post.author.displayName}
80
80
+
size={props.avatarSize ? props.avatarSize : "medium"}
81
81
+
/>
53
82
54
54
-
<div className={`flex flex-col grow min-w-0 ${props.className}`}>
55
55
-
<div
56
56
-
className={`flex justify-between items-center gap-2 leading-tight `}
57
57
-
>
58
58
-
<div className="flex gap-2 items-center">
59
59
-
<div className="font-bold text-secondary">
60
60
-
{post.author.displayName}
83
83
+
<div className={`bskyPostTextContent flex flex-col grow min-w-0 mt-1 `}>
84
84
+
<div
85
85
+
className={`flex justify-between items-center gap-2 leading-tight `}
86
86
+
>
87
87
+
<div className="flex gap-2 items-center">
88
88
+
<div className="font-bold text-secondary">
89
89
+
{post.author.displayName}
90
90
+
</div>
91
91
+
<ProfilePopover
92
92
+
trigger={
93
93
+
<div className="text-sm text-tertiary hover:underline">
94
94
+
@{post.author.handle}
95
95
+
</div>
96
96
+
}
97
97
+
didOrHandle={post.author.handle}
98
98
+
/>
61
99
</div>
62
62
-
<ProfilePopover
63
63
-
trigger={
64
64
-
<div className="text-sm text-tertiary hover:underline">
65
65
-
@{post.author.handle}
66
66
-
</div>
67
67
-
}
68
68
-
didOrHandle={post.author.handle}
69
69
-
/>
100
100
+
<div className="text-sm text-tertiary">
101
101
+
{timeAgo(record.createdAt, { compact: true })}
102
102
+
</div>
70
103
</div>
71
71
-
<div className="text-sm text-tertiary">
72
72
-
{timeAgo(record.createdAt, { compact: true })}
104
104
+
105
105
+
<div
106
106
+
className={`flex flex-col gap-2 ${avatarSize === "large" ? "mt-0.5" : "mt-1"}`}
107
107
+
>
108
108
+
<div className="text-sm text-secondary">
109
109
+
<BlueskyRichText record={record} />
110
110
+
</div>
111
111
+
{showEmbed && post.embed && (
112
112
+
<div onClick={onEmbedClick}>
113
113
+
<BlueskyEmbed
114
114
+
embed={post.embed}
115
115
+
postUrl={url}
116
116
+
className="text-sm"
117
117
+
/>
118
118
+
</div>
119
119
+
)}
73
120
</div>
74
74
-
</div>
75
121
76
76
-
<div
77
77
-
className={`flex flex-col gap-2 ${avatarSize === "large" ? "mt-0.5" : "mt-1"}`}
78
78
-
>
79
79
-
<div className="text-sm text-secondary">
80
80
-
<BlueskyRichText record={record} />
81
81
-
</div>
82
82
-
{showEmbed && post.embed && (
83
83
-
<div onClick={onEmbedClick}>
84
84
-
<BlueskyEmbed
85
85
-
embed={post.embed}
86
86
-
postUrl={url}
87
87
-
className="text-sm"
88
88
-
/>
122
122
+
<div className={`flex gap-2 items-center justify-between mt-2`}>
123
123
+
<PostCounts
124
124
+
post={post}
125
125
+
parent={parent}
126
126
+
replyEnabled={replyEnabled}
127
127
+
replyOnClick={replyOnClick}
128
128
+
quoteEnabled={quoteEnabled}
129
129
+
showBlueskyLink={showBlueskyLink}
130
130
+
url={url}
131
131
+
/>
132
132
+
<div className="flex gap-3 items-center">
133
133
+
{showBlueskyLink && (
134
134
+
<>
135
135
+
<a className="text-tertiary" target="_blank" href={url}>
136
136
+
<BlueskyLinkTiny />
137
137
+
</a>
138
138
+
</>
139
139
+
)}
89
140
</div>
90
90
-
)}
91
91
-
</div>
92
92
-
93
93
-
<div className={`flex gap-2 items-center justify-between mt-2`}>
94
94
-
<PostCounts
95
95
-
post={post}
96
96
-
parent={parent}
97
97
-
replyCountOnClick={replyCountOnClick}
98
98
-
quoteCountOnClick={quoteCountOnClick}
99
99
-
showBlueskyLink={showBlueskyLink}
100
100
-
url={url}
101
101
-
/>
102
102
-
<div className="flex gap-3 items-center">
103
103
-
{showBlueskyLink && (
104
104
-
<>
105
105
-
<a className="text-tertiary" target="_blank" href={url}>
106
106
-
<BlueskyLinkTiny />
107
107
-
</a>
108
108
-
</>
109
109
-
)}
110
141
</div>
111
142
</div>
112
112
-
</div>
113
113
-
</>
143
143
+
</button>
144
144
+
</div>
114
145
);
115
146
}
116
147
117
148
function PostCounts(props: {
118
149
post: PostView;
119
150
parent?: OpenPage;
120
120
-
quoteCountOnClick?: (e: React.MouseEvent) => void;
121
121
-
replyCountOnClick?: (e: React.MouseEvent) => void;
151
151
+
quoteEnabled?: boolean;
152
152
+
replyEnabled?: boolean;
153
153
+
replyOnClick?: (e: React.MouseEvent) => void;
122
154
showBlueskyLink: boolean;
123
155
url: string;
124
156
}) {
157
157
+
const replyContent = props.post.replyCount != null &&
158
158
+
props.post.replyCount > 0 && (
159
159
+
<div className="postRepliesCount flex items-center gap-1 text-tertiary text-xs">
160
160
+
<CommentTiny />
161
161
+
{props.post.replyCount}
162
162
+
</div>
163
163
+
);
164
164
+
165
165
+
const quoteContent = props.post.quoteCount != null &&
166
166
+
props.post.quoteCount > 0 && (
167
167
+
<div className="postQuoteCount flex items-center gap-1 text-tertiary text-xs">
168
168
+
<QuoteTiny />
169
169
+
{props.post.quoteCount}
170
170
+
</div>
171
171
+
);
172
172
+
125
173
return (
126
174
<div className="postCounts flex gap-2 items-center">
127
127
-
{props.post.replyCount != null && props.post.replyCount > 0 && (
128
128
-
<>
129
129
-
{props.replyCountOnClick ? (
130
130
-
<ThreadLink
131
131
-
threadUri={props.post.uri}
132
132
-
parent={parent}
133
133
-
className="relative postRepliesLink flex items-center gap-1 text-tertiary text-xs hover:text-accent-contrast"
134
134
-
onClick={props.replyCountOnClick}
135
135
-
>
136
136
-
<CommentTiny />
137
137
-
{props.post.replyCount}
138
138
-
</ThreadLink>
139
139
-
) : (
140
140
-
<div className="postRepliesCount flex items-center gap-1 text-tertiary text-xs">
141
141
-
<CommentTiny />
142
142
-
{props.post.replyCount}
143
143
-
</div>
144
144
-
)}
145
145
-
</>
146
146
-
)}
147
147
-
{props.post.quoteCount != null && props.post.quoteCount > 0 && (
148
148
-
<>
149
149
-
{props.quoteCountOnClick ? (
150
150
-
<QuotesLink
151
151
-
postUri={props.post.uri}
152
152
-
parent={parent}
153
153
-
className="relative flex items-center gap-1 text-tertiary text-xs hover:text-accent-contrast"
154
154
-
onClick={props.quoteCountOnClick}
155
155
-
>
156
156
-
<QuoteTiny />
157
157
-
{props.post.quoteCount}
158
158
-
</QuotesLink>
159
159
-
) : (
160
160
-
<div className="postQuoteCount flex items-center gap-1 text-tertiary text-xs">
161
161
-
<QuoteTiny />
162
162
-
{props.post.quoteCount}
163
163
-
</div>
164
164
-
)}
165
165
-
</>
166
166
-
)}
175
175
+
{replyContent &&
176
176
+
(props.replyEnabled ? (
177
177
+
<ThreadLink
178
178
+
postUri={props.post.uri}
179
179
+
parent={props.parent}
180
180
+
className="relative postRepliesLink hover:text-accent-contrast"
181
181
+
onClick={props.replyOnClick}
182
182
+
>
183
183
+
{replyContent}
184
184
+
</ThreadLink>
185
185
+
) : (
186
186
+
replyContent
187
187
+
))}
188
188
+
{quoteContent &&
189
189
+
(props.quoteEnabled ? (
190
190
+
<QuotesLink
191
191
+
postUri={props.post.uri}
192
192
+
parent={props.parent}
193
193
+
className="relative hover:text-accent-contrast"
194
194
+
>
195
195
+
{quoteContent}
196
196
+
</QuotesLink>
197
197
+
) : (
198
198
+
quoteContent
199
199
+
))}
167
200
</div>
168
201
);
169
202
}
+9
-20
app/lish/[did]/[publication]/[rkey]/Interactions/Quotes.tsx
···
136
136
137
137
const parent = { type: "thread" as const, uri: q.uri };
138
138
return (
139
139
-
<button
140
140
-
className="flex gap-2 text-left"
141
141
-
onClick={() => {
142
142
-
openPage(undefined, { type: "thread", uri: q.uri });
143
143
-
}}
144
144
-
>
145
145
-
<BskyPostContent
146
146
-
key={`mention-${index}`}
147
147
-
post={post}
148
148
-
parent={parent}
149
149
-
showBlueskyLink={true}
150
150
-
showEmbed={true}
151
151
-
avatarSize="large"
152
152
-
quoteCountOnClick={(e) => {
153
153
-
e.stopPropagation();
154
154
-
e.preventDefault();
155
155
-
openPage(undefined, { type: "quotes", uri: q.uri });
156
156
-
}}
157
157
-
/>
158
158
-
</button>
139
139
+
<BskyPostContent
140
140
+
key={`mention-${index}`}
141
141
+
post={post}
142
142
+
parent={parent}
143
143
+
showBlueskyLink={true}
144
144
+
showEmbed={true}
145
145
+
avatarSize="large"
146
146
+
quoteEnabled={true}
147
147
+
/>
159
148
);
160
149
})}
161
150
</div>
+6
-4
app/lish/[did]/[publication]/[rkey]/PostLinks.tsx
···
55
55
56
56
// Link component for opening thread pages with prefetching
57
57
export function ThreadLink(props: {
58
58
-
threadUri: string;
58
58
+
postUri: string;
59
59
parent?: OpenPage;
60
60
children: React.ReactNode;
61
61
className?: string;
62
62
onClick?: (e: React.MouseEvent) => void;
63
63
}) {
64
64
-
const { threadUri, parent, children, className, onClick } = props;
64
64
+
const { postUri, parent, children, className, onClick } = props;
65
65
66
66
const handleClick = (e: React.MouseEvent) => {
67
67
+
e.stopPropagation();
67
68
onClick?.(e);
68
69
if (e.defaultPrevented) return;
69
69
-
openPage(parent, { type: "thread", uri: threadUri });
70
70
+
openPage(parent, { type: "thread", uri: postUri });
70
71
};
71
72
72
73
const handlePrefetch = () => {
73
73
-
prefetchThread(threadUri);
74
74
+
prefetchThread(postUri);
74
75
};
75
76
76
77
return (
···
96
97
const { postUri, parent, children, className, onClick } = props;
97
98
98
99
const handleClick = (e: React.MouseEvent) => {
100
100
+
e.stopPropagation();
99
101
onClick?.(e);
100
102
if (e.defaultPrevented) return;
101
103
openPage(parent, { type: "quotes", uri: postUri });
+1
-1
app/lish/[did]/[publication]/[rkey]/PostPages.tsx
···
297
297
<Fragment key={pageKey}>
298
298
<SandwichSpacer />
299
299
<ThreadPageComponent
300
300
-
threadUri={openPage.uri}
300
300
+
parentUri={openPage.uri}
301
301
pageId={pageKey}
302
302
hasPageBackground={hasPageBackground}
303
303
pageOptions={
+50
-81
app/lish/[did]/[publication]/[rkey]/ThreadPage.tsx
···
25
25
type ThreadType = ThreadViewPost | NotFoundPost | BlockedPost;
26
26
27
27
export function ThreadPage(props: {
28
28
-
threadUri: string;
28
28
+
parentUri: string;
29
29
pageId: string;
30
30
pageOptions?: React.ReactNode;
31
31
hasPageBackground: boolean;
32
32
}) {
33
33
-
const { threadUri, pageId, pageOptions } = props;
34
34
-
const drawer = useDrawerOpen(threadUri);
33
33
+
const { parentUri: parentUri, pageId, pageOptions } = props;
34
34
+
const drawer = useDrawerOpen(parentUri);
35
35
36
36
const {
37
37
data: thread,
38
38
isLoading,
39
39
error,
40
40
-
} = useSWR(threadUri ? getThreadKey(threadUri) : null, () =>
41
41
-
fetchThread(threadUri),
40
40
+
} = useSWR(parentUri ? getThreadKey(parentUri) : null, () =>
41
41
+
fetchThread(parentUri),
42
42
);
43
43
44
44
return (
···
60
60
Failed to load thread
61
61
</div>
62
62
) : thread ? (
63
63
-
<ThreadContent thread={thread} threadUri={threadUri} />
63
63
+
<ThreadContent thread={thread} parentUri={parentUri} />
64
64
) : null}
65
65
</div>
66
66
</PageWrapper>
67
67
);
68
68
}
69
69
70
70
-
function ThreadContent(props: { thread: ThreadType; threadUri: string }) {
71
71
-
const { thread, threadUri } = props;
70
70
+
function ThreadContent(props: { thread: ThreadType; parentUri: string }) {
71
71
+
const { thread, parentUri: parentUri } = props;
72
72
const mainPostRef = useRef<HTMLDivElement>(null);
73
73
74
74
// Scroll the main post into view when the thread loads
···
114
114
post={parent}
115
115
isMainPost={false}
116
116
showReplyLine={index < parents.length - 1 || true}
117
117
-
threadUri={threadUri}
117
117
+
parentUri={parentUri}
118
118
/>
119
119
</div>
120
120
))}
···
125
125
post={thread}
126
126
isMainPost={true}
127
127
showReplyLine={false}
128
128
-
threadUri={threadUri}
128
128
+
parentUri={parentUri}
129
129
/>
130
130
</div>
131
131
···
134
134
<div className="threadReplies flex flex-col mt-2 pt-2 border-t border-border-light">
135
135
<Replies
136
136
replies={thread.replies as any[]}
137
137
-
threadUri={threadUri}
137
137
+
parentUri={parentUri}
138
138
depth={0}
139
139
parentAuthorDid={thread.post.author.did}
140
140
/>
···
148
148
post: ThreadViewPost;
149
149
isMainPost: boolean;
150
150
showReplyLine: boolean;
151
151
-
threadUri: string;
151
151
+
parentUri: string;
152
152
}) {
153
153
-
const { post, isMainPost, showReplyLine, threadUri } = props;
153
153
+
const { post, isMainPost, showReplyLine, parentUri } = props;
154
154
const postView = post.post;
155
155
-
const parent = { type: "thread" as const, uri: threadUri };
155
155
+
const parent = { type: "thread" as const, uri: parentUri };
156
156
157
157
return (
158
158
<div className="threadPost flex gap-2 relative">
···
165
165
parent={parent}
166
166
showBlueskyLink={true}
167
167
showEmbed={true}
168
168
-
quoteCountOnClick={(e) => {
169
169
-
e.stopPropagation();
170
170
-
e.preventDefault();
171
171
-
openPage(parent, { type: "quotes", uri: postView.uri });
172
172
-
}}
173
173
-
replyCountOnClick={(e) => {
174
174
-
e.stopPropagation();
175
175
-
e.preventDefault();
176
176
-
}}
168
168
+
quoteEnabled
169
169
+
replyEnabled
177
170
/>
178
171
</div>
179
172
);
···
181
174
182
175
function Replies(props: {
183
176
replies: (ThreadViewPost | NotFoundPost | BlockedPost)[];
184
184
-
threadUri: string;
185
177
depth: number;
186
178
parentAuthorDid?: string;
187
187
-
parentUri?: string;
179
179
+
parentUri: string;
188
180
}) {
189
189
-
const { replies, threadUri, depth, parentAuthorDid, parentUri } = props;
181
181
+
const { replies, depth, parentAuthorDid, parentUri } = props;
190
182
const collapsedThreads = useThreadState((s) => s.collapsedThreads);
191
183
const toggleCollapsed = useThreadState((s) => s.toggleCollapsed);
192
184
···
241
233
<ReplyPost
242
234
post={reply}
243
235
isLast={index === replies.length - 1 && !hasReplies}
244
244
-
threadUri={threadUri}
245
245
-
toggleCollapsed={(e) => {
246
246
-
e.stopPropagation();
247
247
-
e.preventDefault();
248
248
-
if (parentUri) toggleCollapsed(parentUri);
249
249
-
console.log("collapse?");
250
250
-
}}
236
236
+
parentUri={parentUri}
237
237
+
toggleCollapsed={(uri) => toggleCollapsed(uri)}
251
238
isCollapsed={isCollapsed}
252
239
depth={props.depth}
253
240
/>
···
255
242
})}
256
243
{parentUri && depth > 0 && replies.length > 3 && (
257
244
<ThreadLink
258
258
-
threadUri={parentUri}
259
259
-
parent={{ type: "thread", uri: threadUri }}
245
245
+
postUri={parentUri}
246
246
+
parent={{ type: "thread", uri: parentUri }}
260
247
className="flex justify-start text-sm text-accent-contrast h-fit hover:underline"
261
248
>
262
249
<div className="mx-[19px] w-0.5 h-[24px] bg-border-light" />
···
271
258
const ReplyPost = (props: {
272
259
post: ThreadViewPost;
273
260
isLast: boolean;
274
274
-
threadUri: string;
275
275
-
toggleCollapsed: (e: React.MouseEvent) => void;
261
261
+
parentUri: string;
262
262
+
toggleCollapsed: (uri: string) => void;
276
263
isCollapsed: boolean;
277
264
depth: number;
278
265
}) => {
279
279
-
const { post, threadUri } = props;
266
266
+
const { post, parentUri } = props;
280
267
const postView = post.post;
281
281
-
const parent = { type: "thread" as const, uri: threadUri };
282
268
283
269
const hasReplies = props.post.replies && props.post.replies.length > 0;
284
270
285
285
-
// was in the middle of trying to get the right set of comments to close when this line is clicked
286
286
-
// then i really need to style the parent and grandparent threads, hide some of the content unless its the main post
287
287
-
// the thread line on them is also weird
288
271
return (
289
272
<div className="threadReply relative flex flex-col">
290
290
-
{props.depth > 0 && (
291
291
-
<button
292
292
-
onClick={(e) => {
293
293
-
props.toggleCollapsed(e);
294
294
-
}}
295
295
-
className="replyThreadLine absolute top-0 bottom-0 left-1 z-0 cursor-pointer shrink-0 "
296
296
-
aria-label={"Toggle replies"}
297
297
-
>
298
298
-
<div className="mx-[15px] w-0.5 h-full bg-border-light" />
299
299
-
</button>
300
300
-
)}
301
301
-
302
302
-
<button
303
303
-
className="replyThreadPost flex gap-2 text-left relative py-2 px-2 rounded cursor-pointer"
304
304
-
onClick={() => {
305
305
-
openPage(parent, { type: "thread", uri: postView.uri });
273
273
+
<BskyPostContent
274
274
+
post={postView}
275
275
+
parent={{ type: "thread", uri: parentUri }}
276
276
+
showEmbed={false}
277
277
+
showBlueskyLink={false}
278
278
+
replyLine={
279
279
+
props.depth > 0
280
280
+
? {
281
281
+
onToggle: () => {
282
282
+
props.toggleCollapsed(props.parentUri);
283
283
+
console.log("click click");
284
284
+
},
285
285
+
}
286
286
+
: undefined
287
287
+
}
288
288
+
quoteEnabled
289
289
+
replyEnabled
290
290
+
replyOnClick={(e) => {
291
291
+
e.preventDefault();
292
292
+
props.toggleCollapsed(post.post.uri);
306
293
}}
307
307
-
>
308
308
-
<BskyPostContent
309
309
-
post={postView}
310
310
-
parent={parent}
311
311
-
showEmbed={false}
312
312
-
showBlueskyLink={false}
313
313
-
quoteCountOnClick={(e) => {
314
314
-
e.preventDefault();
315
315
-
e.stopPropagation();
316
316
-
openPage(parent, { type: "quotes", uri: postView.uri });
317
317
-
}}
318
318
-
replyCountOnClick={(e) => {
319
319
-
e.preventDefault();
320
320
-
e.stopPropagation();
321
321
-
props.toggleCollapsed();
322
322
-
}}
323
323
-
onEmbedClick={(e) => e.stopPropagation()}
324
324
-
className="text-sm z-10"
325
325
-
/>
326
326
-
</button>
294
294
+
onEmbedClick={(e) => e.stopPropagation()}
295
295
+
className="text-sm z-10"
296
296
+
/>
327
297
{hasReplies && props.depth < 3 && (
328
298
<div className="ml-[28px] flex">
329
299
{!props.isCollapsed && (
···
331
301
<Replies
332
302
parentUri={postView.uri}
333
303
replies={props.post.replies as any[]}
334
334
-
threadUri={threadUri}
335
304
depth={props.depth + 1}
336
305
parentAuthorDid={props.post.post.author.did}
337
306
/>
···
342
311
343
312
{hasReplies && props.depth >= 3 && (
344
313
<ThreadLink
345
345
-
threadUri={props.post.post.uri}
346
346
-
parent={{ type: "thread", uri: threadUri }}
314
314
+
postUri={props.post.post.uri}
315
315
+
parent={{ type: "thread", uri: parentUri }}
347
316
className="text-left ml-10 text-sm text-accent-contrast hover:underline"
348
317
>
349
318
View more replies