mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-15 18:07:21 +02:00
Highlight reaction counts when active user has reacted
Changes: - Reaction counts now show in highlight color (text-highlight) when the active user has reacted with that emoji - Added font-semibold to make user's reactions more prominent - Checks if activeAccount.pubkey is in reaction.pubkeys array - Provides clear visual feedback showing which reactions you've made This makes it easy to see at a glance which reactions are yours in a conversation with many reactions.
This commit is contained in:
@@ -1,11 +1,6 @@
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
import { use$ } from "applesauce-react/hooks";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Search } from "lucide-react";
|
||||
import { EmojiSearchService } from "@/services/emoji-search";
|
||||
@@ -83,28 +78,36 @@ export function EmojiPickerDialog({
|
||||
|
||||
// Initialize emoji service with unicode and custom emojis
|
||||
useEffect(() => {
|
||||
// Load unicode emojis
|
||||
emojiService.addUnicodeEmojis(UNICODE_EMOJIS);
|
||||
const loadEmojis = async () => {
|
||||
// Clear and rebuild index on every change to ensure fresh state
|
||||
emojiService.clearCustom(); // Clear custom emoji but keep unicode
|
||||
|
||||
// Load user's custom emoji list (kind 10030)
|
||||
if (userEmojiList) {
|
||||
emojiService.addUserEmojiList(userEmojiList);
|
||||
}
|
||||
// Load unicode emojis (clearCustom keeps these, but add in case of first load)
|
||||
await emojiService.addUnicodeEmojis(UNICODE_EMOJIS);
|
||||
|
||||
// Load context emojis (from conversation messages)
|
||||
for (const emoji of contextEmojis) {
|
||||
emojiService.addEmoji(emoji.shortcode, emoji.url, "context");
|
||||
}
|
||||
}, [emojiService, contextEmojis, userEmojiList]);
|
||||
// Load user's custom emoji list (kind 10030)
|
||||
if (userEmojiList) {
|
||||
console.log(
|
||||
"[EmojiPickerDialog] Loading user emoji list",
|
||||
userEmojiList,
|
||||
);
|
||||
await emojiService.addUserEmojiList(userEmojiList);
|
||||
}
|
||||
|
||||
// Search emojis when query changes
|
||||
useEffect(() => {
|
||||
const search = async () => {
|
||||
// Load context emojis (from conversation messages)
|
||||
for (const emoji of contextEmojis) {
|
||||
await emojiService.addEmoji(emoji.shortcode, emoji.url, "context");
|
||||
}
|
||||
|
||||
console.log("[EmojiPickerDialog] Emoji service size:", emojiService.size);
|
||||
|
||||
// Trigger initial search
|
||||
const results = await emojiService.search(searchQuery, { limit: 48 });
|
||||
setSearchResults(results);
|
||||
};
|
||||
search();
|
||||
}, [searchQuery, emojiService]);
|
||||
|
||||
loadEmojis();
|
||||
}, [emojiService, contextEmojis, userEmojiList, searchQuery]);
|
||||
|
||||
// Get frequently used emojis from history
|
||||
const frequentlyUsed = useMemo(() => {
|
||||
@@ -143,10 +146,6 @@ export function EmojiPickerDialog({
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>React with emoji</DialogTitle>
|
||||
</DialogHeader>
|
||||
|
||||
{/* Quick reaction bar */}
|
||||
<div className="flex gap-2 pb-3 border-b">
|
||||
{QUICK_REACTIONS.map((emoji) => (
|
||||
@@ -154,7 +153,7 @@ export function EmojiPickerDialog({
|
||||
key={emoji}
|
||||
onClick={() => handleQuickReaction(emoji)}
|
||||
className="text-2xl hover:scale-125 transition-transform active:scale-110"
|
||||
title={`React with ${emoji}`}
|
||||
title={emoji}
|
||||
>
|
||||
{emoji}
|
||||
</button>
|
||||
@@ -178,7 +177,7 @@ export function EmojiPickerDialog({
|
||||
{frequentlyUsed.length > 0 && (
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground mb-2 font-medium">
|
||||
Frequently used
|
||||
Recently used
|
||||
</div>
|
||||
<div className="grid grid-cols-8 gap-2">
|
||||
{frequentlyUsed.map((emoji) => (
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { useMemo, useEffect } from "react";
|
||||
import { use$ } from "applesauce-react/hooks";
|
||||
import { cn } from "@/lib/utils";
|
||||
import eventStore from "@/services/event-store";
|
||||
import pool from "@/services/relay-pool";
|
||||
import accountManager from "@/services/accounts";
|
||||
import { EMOJI_SHORTCODE_REGEX } from "@/lib/emoji-helpers";
|
||||
|
||||
interface MessageReactionsProps {
|
||||
@@ -149,9 +151,13 @@ export function MessageReactions({ messageId, relays }: MessageReactionsProps) {
|
||||
* Single reaction badge with tooltip showing who reacted
|
||||
*/
|
||||
function ReactionBadge({ reaction }: { reaction: ReactionSummary }) {
|
||||
// Get active user to check if they reacted
|
||||
const activeAccount = use$(accountManager.active$);
|
||||
const hasUserReacted = activeAccount?.pubkey
|
||||
? reaction.pubkeys.includes(activeAccount.pubkey)
|
||||
: false;
|
||||
|
||||
// Build tooltip with emoji and truncated pubkeys
|
||||
// Note: Could be enhanced to load profiles, but for simplicity and performance
|
||||
// we show truncated pubkeys. Profiles are already loaded in the chat UI context.
|
||||
const tooltip = useMemo(() => {
|
||||
// Truncate pubkeys to first 8 chars for readability
|
||||
const pubkeyList = reaction.pubkeys
|
||||
@@ -179,7 +185,15 @@ function ReactionBadge({ reaction }: { reaction: ReactionSummary }) {
|
||||
) : (
|
||||
<span className="text-xs">{reaction.emoji}</span>
|
||||
)}
|
||||
<span className="text-muted-foreground">{reaction.count}</span>
|
||||
<span
|
||||
className={cn(
|
||||
hasUserReacted
|
||||
? "text-highlight font-semibold"
|
||||
: "text-muted-foreground",
|
||||
)}
|
||||
>
|
||||
{reaction.count}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user