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
refactor interactions into two components
cozylittle.house
3 months ago
86b53c38
4b6ca129
+105
-51
6 changed files
expand all
collapse all
unified
split
app
[leaflet_id]
publish
PublishPost.tsx
lish
[did]
[publication]
[rkey]
CanvasPage.tsx
Interactions
Interactions.tsx
LinearDocumentPage.tsx
PostFooter.tsx
PostHeader
PostHeader.tsx
+6
-4
app/[leaflet_id]/publish/PublishPost.tsx
···
125
125
submit();
126
126
}}
127
127
>
128
128
-
<div className="container flex flex-col gap-2 sm:p-3 p-4">
128
128
+
<div className="container flex flex-col gap-3 sm:p-3 p-4">
129
129
<PublishingTo
130
130
publication_uri={props.publication_uri}
131
131
record={props.record}
132
132
/>
133
133
-
<hr className="border-border-light my-1" />
133
133
+
<hr className="border-border" />
134
134
<ShareOptions
135
135
setShareOption={setShareOption}
136
136
shareOption={shareOption}
···
139
139
editorStateRef={editorStateRef}
140
140
{...props}
141
141
/>
142
142
-
<hr className="border-border-light " />
143
143
-
<div className="flex flex-col gap-1">
142
142
+
<hr className="border-border " />
143
143
+
<div className="flex flex-col gap-2">
144
144
<h4>Tags</h4>
145
145
<TagSelector
146
146
selectedTags={currentTags}
147
147
setSelectedTags={handleTagsChange}
148
148
/>
149
149
</div>
150
150
+
<hr className="border-border mb-2" />
151
151
+
150
152
<div className="flex justify-between">
151
153
<Link
152
154
className="hover:no-underline! font-bold"
-1
app/lish/[did]/[publication]/[rkey]/CanvasPage.tsx
···
213
213
<Interactions
214
214
quotesCount={props.quotesCount || 0}
215
215
commentsCount={props.commentsCount || 0}
216
216
-
compact
217
216
showComments={props.preferences.showComments}
218
217
pageId={props.pageId}
219
218
/>
+95
-39
app/lish/[did]/[publication]/[rkey]/Interactions/Interactions.tsx
···
102
102
export const Interactions = (props: {
103
103
quotesCount: number;
104
104
commentsCount: number;
105
105
-
compact?: boolean;
105
105
+
className?: string;
106
106
+
showComments?: boolean;
107
107
+
pageId?: string;
108
108
+
}) => {
109
109
+
const data = useContext(PostPageContext);
110
110
+
const document_uri = data?.uri;
111
111
+
if (!document_uri)
112
112
+
throw new Error("document_uri not available in PostPageContext");
113
113
+
114
114
+
let { drawerOpen, drawer, pageId } = useInteractionState(document_uri);
115
115
+
116
116
+
const handleQuotePrefetch = () => {
117
117
+
if (data?.quotesAndMentions) {
118
118
+
prefetchQuotesData(data.quotesAndMentions);
119
119
+
}
120
120
+
};
121
121
+
122
122
+
const tags = (data?.data as any)?.tags as string[] | undefined;
123
123
+
const tagCount = tags?.length || 0;
124
124
+
return (
125
125
+
<div className={`flex gap-2 text-tertiary text-sm ${props.className}`}>
126
126
+
{tagCount > 0 && <TagPopover tags={tags} tagCount={tagCount} />}
127
127
+
128
128
+
{props.quotesCount > 0 && (
129
129
+
<button
130
130
+
className="flex w-fit gap-2 items-center"
131
131
+
onClick={() => {
132
132
+
if (!drawerOpen || drawer !== "quotes")
133
133
+
openInteractionDrawer("quotes", document_uri, props.pageId);
134
134
+
else setInteractionState(document_uri, { drawerOpen: false });
135
135
+
}}
136
136
+
onMouseEnter={handleQuotePrefetch}
137
137
+
onTouchStart={handleQuotePrefetch}
138
138
+
aria-label="Post quotes"
139
139
+
>
140
140
+
<QuoteTiny aria-hidden /> {props.quotesCount}
141
141
+
</button>
142
142
+
)}
143
143
+
{props.showComments === false ? null : (
144
144
+
<button
145
145
+
className="flex gap-2 items-center w-fit"
146
146
+
onClick={() => {
147
147
+
if (!drawerOpen || drawer !== "comments" || pageId !== props.pageId)
148
148
+
openInteractionDrawer("comments", document_uri, props.pageId);
149
149
+
else setInteractionState(document_uri, { drawerOpen: false });
150
150
+
}}
151
151
+
aria-label="Post comments"
152
152
+
>
153
153
+
<CommentTiny aria-hidden /> {props.commentsCount}
154
154
+
</button>
155
155
+
)}
156
156
+
</div>
157
157
+
);
158
158
+
};
159
159
+
160
160
+
export const ExpandedInteractions = (props: {
161
161
+
quotesCount: number;
162
162
+
commentsCount: number;
106
163
className?: string;
107
164
showComments?: boolean;
108
165
pageId?: string;
···
120
177
}
121
178
};
122
179
180
180
+
const tags = (data?.data as any)?.tags as string[] | undefined;
181
181
+
const tagCount = tags?.length || 0;
123
182
return (
124
183
<div
125
125
-
className={`flex gap-2 text-tertiary ${props.compact ? "text-sm" : "px-3 sm:px-4"} ${props.className}`}
184
184
+
className={`gap-2 text-tertiary px-3 sm:px-4 flex flex-col ${props.className}`}
126
185
>
127
127
-
{props.compact && <TagPopover />}
128
128
-
<button
129
129
-
className={`flex gap-1 items-center ${!props.compact && "px-1 py-0.5 border border-border-light rounded-lg trasparent-outline selected-outline"}`}
130
130
-
onClick={() => {
131
131
-
if (!drawerOpen || drawer !== "quotes")
132
132
-
openInteractionDrawer("quotes", document_uri, props.pageId);
133
133
-
else setInteractionState(document_uri, { drawerOpen: false });
134
134
-
}}
135
135
-
onMouseEnter={handleQuotePrefetch}
136
136
-
onTouchStart={handleQuotePrefetch}
137
137
-
aria-label="Post quotes"
138
138
-
>
139
139
-
<QuoteTiny aria-hidden /> {props.quotesCount}{" "}
140
140
-
{!props.compact && (
186
186
+
{tagCount > 0 && (
187
187
+
<>
188
188
+
<hr className="border-border-light mb-1 " />
189
189
+
<TagList tags={tags} />
190
190
+
<hr className="border-border-light mt-1 " />
191
191
+
</>
192
192
+
)}
193
193
+
194
194
+
{props.quotesCount > 0 && (
195
195
+
<button
196
196
+
className="flex w-fit gap-2 items-center px-1 py-0.5 border border-border-light rounded-lg trasparent-outline selected-outline"
197
197
+
onClick={() => {
198
198
+
if (!drawerOpen || drawer !== "quotes")
199
199
+
openInteractionDrawer("quotes", document_uri, props.pageId);
200
200
+
else setInteractionState(document_uri, { drawerOpen: false });
201
201
+
}}
202
202
+
onMouseEnter={handleQuotePrefetch}
203
203
+
onTouchStart={handleQuotePrefetch}
204
204
+
aria-label="Post quotes"
205
205
+
>
206
206
+
<QuoteTiny aria-hidden /> {props.quotesCount}{" "}
141
207
<span
142
208
aria-hidden
143
209
>{`Quote${props.quotesCount === 1 ? "" : "s"}`}</span>
144
144
-
)}
145
145
-
</button>
210
210
+
</button>
211
211
+
)}
146
212
{props.showComments === false ? null : (
147
213
<button
148
148
-
className={`flex gap-1 items-center ${!props.compact && "px-1 py-0.5 border border-border-light rounded-lg trasparent-outline selected-outline"}`}
214
214
+
className="flex gap-2 items-center w-fit px-1 py-0.5 border border-border-light rounded-lg trasparent-outline selected-outline"
149
215
onClick={() => {
150
216
if (!drawerOpen || drawer !== "comments" || pageId !== props.pageId)
151
217
openInteractionDrawer("comments", document_uri, props.pageId);
···
154
220
aria-label="Post comments"
155
221
>
156
222
<CommentTiny aria-hidden />{" "}
157
157
-
{props.compact ? (
158
158
-
props.commentsCount
159
159
-
) : props.commentsCount > 0 ? (
223
223
+
{props.commentsCount > 0 ? (
160
224
<span aria-hidden>
161
225
{`${props.commentsCount} Comment${props.commentsCount === 1 ? "" : "s"}`}
162
226
</span>
···
165
229
)}
166
230
</button>
167
231
)}
168
168
-
{!props.compact && <TagList />}
169
232
</div>
170
233
);
171
234
};
172
235
173
173
-
const TagPopover = () => {
174
174
-
const data = useContext(PostPageContext);
175
175
-
const tags = (data?.data as any)?.tags as string[] | undefined;
176
176
-
const tagCount = tags?.length || 0;
177
177
-
178
178
-
if (tagCount === 0) return null;
179
179
-
236
236
+
const TagPopover = (props: {
237
237
+
tagCount: number;
238
238
+
tags: string[] | undefined;
239
239
+
}) => {
180
240
return (
181
241
<Popover
182
242
className="p-2! max-w-xs"
183
243
trigger={
184
244
<div className="tags flex gap-1 items-center ">
185
185
-
<TagTiny /> {tagCount}
245
245
+
<TagTiny /> {props.tagCount}
186
246
</div>
187
247
}
188
248
>
189
189
-
<TagList className="text-secondary!" />
249
249
+
<TagList tags={props.tags} className="text-secondary!" />
190
250
</Popover>
191
251
);
192
252
};
193
253
194
194
-
const TagList = (props: { className?: string }) => {
195
195
-
const data = useContext(PostPageContext);
196
196
-
const tags = (data?.data as any)?.tags as string[] | undefined;
197
197
-
198
198
-
if (!tags || tags.length === 0) return null;
199
199
-
254
254
+
const TagList = (props: { className?: string; tags: string[] | undefined }) => {
255
255
+
if (!props.tags) return;
200
256
return (
201
257
<div className="flex gap-1 flex-wrap">
202
202
-
{tags.map((tag, index) => (
258
258
+
{props.tags.map((tag, index) => (
203
259
<Tag name={tag} key={index} className={props.className} />
204
260
))}
205
261
</div>
+2
-2
app/lish/[did]/[publication]/[rkey]/LinearDocumentPage.tsx
···
11
11
import { SubscribeWithBluesky } from "app/lish/Subscribe";
12
12
import { EditTiny } from "components/Icons/EditTiny";
13
13
import {
14
14
+
ExpandedInteractions,
14
15
getCommentCount,
15
16
getQuoteCount,
16
17
Interactions,
···
84
85
did={did}
85
86
prerenderedCodeBlocks={prerenderedCodeBlocks}
86
87
/>
87
87
-
<Interactions
88
88
+
<ExpandedInteractions
88
89
pageId={pageId}
89
90
showComments={preferences.showComments}
90
91
commentsCount={getCommentCount(document, pageId) || 0}
···
92
93
/>
93
94
{!isSubpage && (
94
95
<>
95
95
-
<hr className="border-border-light mb-4 mt-4 sm:mx-4 mx-3" />
96
96
<div className="sm:px-4 px-3">
97
97
{identity &&
98
98
identity.atp_did ===
+2
-4
app/lish/[did]/[publication]/[rkey]/PostFooter.tsx
···
5
5
import { useIdentityData } from "components/IdentityProvider";
6
6
import { PubLeafletComment } from "lexicons/api";
7
7
import { PostPageData } from "./getPostPageData";
8
8
-
import { Interactions } from "./Interactions/Interactions";
8
8
+
import { ExpandedInteractions } from "./Interactions/Interactions";
9
9
import { decodeQuotePosition } from "./quotePosition";
10
10
11
11
export const PostFooter = (props: {
···
18
18
return;
19
19
return (
20
20
<div className="flex flex-col px-3 sm:px-4">
21
21
-
<hr className="border-border-light mb-4" />
22
22
-
<Interactions
21
21
+
<ExpandedInteractions
23
22
showComments={props.preferences.showComments}
24
23
quotesCount={
25
24
props.data.document_mentions_in_bsky.filter((q) => {
···
36
35
).length
37
36
}
38
37
/>
39
39
-
<hr className="border-border-light mb-4 mt-4 " />
40
38
{identity &&
41
39
identity.atp_did ===
42
40
props.data.documents_in_publications[0]?.publications?.identity_did ? (
-1
app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx
···
90
90
</div>
91
91
<Interactions
92
92
showComments={props.preferences.showComments}
93
93
-
compact
94
93
quotesCount={getQuoteCount(document) || 0}
95
94
commentsCount={getCommentCount(document) || 0}
96
95
/>