v3: added content slugs, fixed real-time updates in client, added @mentions across the app, added new file selector and drop zone

This commit is contained in:
khannurien
2026-03-22 16:06:26 +00:00
parent 39a0cc397e
commit 34e908d1bc
42 changed files with 2170 additions and 628 deletions

View File

@@ -10,9 +10,10 @@ import {
db,
isCommentRow,
} from "../model/db.ts";
import { notifyMentions } from "./notification-service.ts";
const SELECT_COLS =
`c.id, c.dump_id, c.user_id, c.parent_id, c.body, c.created_at, c.deleted,
`c.id, c.dump_id, c.user_id, c.parent_id, c.body, c.created_at, c.updated_at, c.deleted,
u.username as author_username, u.avatar_mime as author_avatar_mime`;
function fetchComment(commentId: string): Comment {
@@ -59,7 +60,63 @@ export function createComment(
body.trim(),
createdAt.toISOString(),
);
return fetchComment(id);
const comment = fetchComment(id);
const dumpRow = db.prepare(`SELECT title FROM dumps WHERE id = ?;`).get(
dumpId,
) as { title: string } | undefined;
notifyMentions(userId, body, "comment", id, dumpRow?.title ?? "", dumpId);
return comment;
}
export function updateComment(
commentId: string,
body: string,
requestingUserId: string,
isAdmin: boolean,
): { comment: Comment; dumpId: string; isPrivate: boolean } {
const row = db.prepare(
`SELECT c.dump_id, d.is_private FROM comments c JOIN dumps d ON c.dump_id = d.id WHERE c.id = ?;`,
).get(commentId) as { dump_id: string; is_private: number } | undefined;
if (!row) {
throw new APIException(APIErrorCode.NOT_FOUND, 404, "Comment not found");
}
const existing = fetchComment(commentId);
if (existing.deleted) {
throw new APIException(
APIErrorCode.VALIDATION_ERROR,
400,
"Cannot edit a deleted comment",
);
}
if (existing.userId !== requestingUserId && !isAdmin) {
throw new APIException(
APIErrorCode.UNAUTHORIZED,
401,
"Not authorized to edit this comment",
);
}
const now = new Date().toISOString();
db.prepare(`UPDATE comments SET body = ?, updated_at = ? WHERE id = ?;`).run(
body.trim(),
now,
commentId,
);
const dumpRow = db.prepare(`SELECT title FROM dumps WHERE id = ?;`).get(
row.dump_id,
) as { title: string } | undefined;
notifyMentions(
requestingUserId,
body,
"comment",
commentId,
dumpRow?.title ?? "",
row.dump_id,
);
return {
comment: fetchComment(commentId),
dumpId: row.dump_id,
isPrivate: Boolean(row.is_private),
};
}
export function deleteComment(