+80
-19
src/modules/comments.tsx
+80
-19
src/modules/comments.tsx
···
158
158
<div class="flex-1 flex flex-col py-4 gap-6 overflow-y-scroll grain-scroll-area">
159
159
{topLevel.map((comment) => (
160
160
<div key={comment.cid} class="flex flex-col gap-4">
161
-
<CommentBlock comment={comment} />
161
+
<CommentBlock userProfile={userProfile} comment={comment} />
162
162
163
163
{repliesByParent.get(comment.uri)?.map((reply) => (
164
164
<div key={reply.cid} class="ml-6">
165
-
<CommentBlock comment={reply} />
165
+
<CommentBlock userProfile={userProfile} comment={reply} />
166
166
</div>
167
167
))}
168
168
</div>
···
183
183
);
184
184
}
185
185
186
-
function CommentBlock({ comment }: Readonly<{ comment: CommentView }>) {
186
+
function CommentBlock(
187
+
{ userProfile, comment }: Readonly<
188
+
{ userProfile: ProfileView; comment: CommentView }
189
+
>,
190
+
) {
187
191
const gallery = isGalleryView(comment.subject) ? comment.subject : undefined;
188
192
const rkey = gallery ? new AtUri(gallery.uri).rkey : undefined;
189
193
return (
···
209
213
/>
210
214
)}
211
215
212
-
{!comment.replyTo
213
-
? (
214
-
<button
215
-
type="button"
216
-
class="w-fit p-0 mt-2 cursor-pointer text-zinc-600 dark:text-zinc-500 font-semibold text-sm"
217
-
hx-get={`/ui/comments/${gallery?.creator.did}/gallery/${rkey}/reply?comment=${
218
-
encodeURIComponent(comment.uri)
219
-
}`}
220
-
hx-trigger="click"
221
-
hx-target="#dialog-target"
222
-
hx-swap="innerHTML"
223
-
>
224
-
Reply
225
-
</button>
226
-
)
227
-
: null}
216
+
<div class="flex gap-2">
217
+
{!comment.replyTo
218
+
? (
219
+
<button
220
+
type="button"
221
+
class="w-fit p-0 mt-2 cursor-pointer text-zinc-600 dark:text-zinc-500 font-semibold text-sm"
222
+
hx-get={`/ui/comments/${gallery?.creator.did}/gallery/${rkey}/reply?comment=${
223
+
encodeURIComponent(comment.uri)
224
+
}`}
225
+
hx-trigger="click"
226
+
hx-target="#dialog-target"
227
+
hx-swap="innerHTML"
228
+
>
229
+
Reply
230
+
</button>
231
+
)
232
+
: null}
233
+
{userProfile.did === comment.author.did
234
+
? (
235
+
<button
236
+
type="button"
237
+
class="w-fit p-0 mt-2 cursor-pointer text-zinc-600 dark:text-zinc-500 font-semibold text-sm"
238
+
hx-delete={`/actions/comments/${gallery?.creator.did}/gallery/${rkey}?comment=${
239
+
encodeURIComponent(comment.uri)
240
+
}`}
241
+
hx-confirm="Are you sure you want to delete this comment?"
242
+
hx-target="#dialog-target"
243
+
hx-swap="innerHTML"
244
+
>
245
+
Delete
246
+
</button>
247
+
)
248
+
: null}
249
+
</div>
228
250
</div>
229
251
</div>
230
252
);
···
324
346
);
325
347
} catch (error) {
326
348
console.error("Error creating comment:", error);
349
+
}
350
+
351
+
const comments = getGalleryComments(gallery.uri, ctx);
352
+
353
+
return ctx.html(
354
+
<GalleryCommentsDialog
355
+
userProfile={profile}
356
+
comments={comments}
357
+
gallery={gallery}
358
+
/>,
359
+
);
360
+
},
361
+
),
362
+
363
+
route(
364
+
"/actions/comments/:creatorDid/gallery/:rkey",
365
+
["DELETE"],
366
+
async (req, params, ctx) => {
367
+
const { did } = ctx.requireAuth();
368
+
const profile = getActorProfile(did, ctx);
369
+
if (!profile) return ctx.next();
370
+
371
+
const url = new URL(req.url);
372
+
const commentUri = url.searchParams.get("comment");
373
+
374
+
if (!commentUri) {
375
+
return new Response("Comment URI is required", { status: 400 });
376
+
}
377
+
378
+
const creatorDid = params.creatorDid;
379
+
const rkey = params.rkey;
380
+
381
+
const gallery = getGallery(creatorDid, rkey, ctx);
382
+
if (!gallery) return ctx.next();
383
+
384
+
try {
385
+
await ctx.deleteRecord(commentUri);
386
+
} catch (error) {
387
+
console.error("Error deleting comment:", error);
327
388
}
328
389
329
390
const comments = getGalleryComments(gallery.uri, ctx);