feat: @mentions in comments
Parse @username in comment content, notify mentioned users (dedup against recipe-author/parent-author who are already notified via comment/reply), and render @username as a link to their profile. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useCallback, useMemo } from "react";
|
||||
import { useState, useEffect, useCallback, useMemo, Fragment } from "react";
|
||||
import Link from "next/link";
|
||||
import { MessageCircle, Reply, Trash2 } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslations } from "next-intl";
|
||||
@@ -24,6 +25,25 @@ type Comment = {
|
||||
};
|
||||
|
||||
const MAX_VISUAL_INDENT = 4;
|
||||
const MENTION_REGEX = /@([a-z0-9_-]{3,30})/gi;
|
||||
|
||||
function renderContentWithMentions(content: string) {
|
||||
const parts = content.split(MENTION_REGEX);
|
||||
// split() with a capturing group interleaves [text, username, text, username, ...text]
|
||||
return parts.map((part, i) =>
|
||||
i % 2 === 1 ? (
|
||||
<Link
|
||||
key={i}
|
||||
href={`/u/${part.toLowerCase()}`}
|
||||
className="text-primary font-medium hover:underline"
|
||||
>
|
||||
@{part}
|
||||
</Link>
|
||||
) : (
|
||||
<Fragment key={i}>{part}</Fragment>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function timeAgo(dateStr: string) {
|
||||
const diff = Date.now() - new Date(dateStr).getTime();
|
||||
@@ -126,7 +146,7 @@ function CommentItem({
|
||||
<span className="font-medium text-sm">{comment.userName}</span>
|
||||
<span className="text-xs text-muted-foreground">{timeAgo(comment.createdAt)}</span>
|
||||
</div>
|
||||
<p className="text-sm leading-relaxed whitespace-pre-wrap">{comment.content}</p>
|
||||
<p className="text-sm leading-relaxed whitespace-pre-wrap">{renderContentWithMentions(comment.content)}</p>
|
||||
<CommentReactions recipeId={recipeId} commentId={comment.id} initialCounts={{}} initialUserReactions={[]} />
|
||||
<div className="flex items-center gap-2">
|
||||
{currentUserId && (
|
||||
|
||||
Reference in New Issue
Block a user