feat(mentions): @ autocomplete, blue @nick, avatar notification toast

- Chat input @ autocomplete: typing @ shows online users (room users +
  online friends + room aliases) with avatars; arrows/Tab/Enter to pick.
- Any valid @nick token is highlighted blue in chat bubbles (like @all),
  giving visual feedback that it is a recognised mention.
- Side notification toast on a received mention: sender avatar (from the
  new senderFigure wire field) + message + dismiss; dismiss marks it read
  so the toolbar unread badge updates. Auto-hides after 8s.
- IMentionEntry/parsers carry senderFigure end to end.
This commit is contained in:
medievalshell
2026-06-04 01:18:26 +02:00
parent f8e943d262
commit 0df810c556
14 changed files with 452 additions and 17 deletions
+7 -12
View File
@@ -1,17 +1,15 @@
import { MentionReceivedEvent, MentionsListEvent, RequestMentionsComposer } from '@nitrots/nitro-renderer';
import { useCallback, useEffect } from 'react';
import { GetConfigurationValue, IMentionEntry, LocalizeText, NotificationBubbleType, PlaySound, SendMessageComposer } from '../../api';
import { GetConfigurationValue, IMentionEntry, PlaySound, SendMessageComposer } from '../../api';
import { useMessageEvent } from '../events';
import { useNotificationActions } from '../notification';
import { addMention, setMentions } from './mentionsStore';
import { pushMentionToast } from './mentionToastsStore';
// Dedicated mention chime served from nitro-assets/sounds/<sample>.mp3.
const MENTION_SOUND_SAMPLE = 'mentions_notification';
export const useMentionMessages = (): void =>
{
const { showSingleBubble } = useNotificationActions();
const onMentionsList = useCallback((event: MentionsListEvent) =>
{
const list = event.getParser().mentions;
@@ -20,6 +18,7 @@ export const useMentionMessages = (): void =>
mentionId: m.mentionId,
senderId: m.senderId,
senderUsername: m.senderUsername,
senderFigure: m.senderFigure,
roomId: m.roomId,
roomName: m.roomName,
message: m.message,
@@ -39,6 +38,7 @@ export const useMentionMessages = (): void =>
mentionId: m.mentionId,
senderId: m.senderId,
senderUsername: m.senderUsername,
senderFigure: m.senderFigure,
roomId: m.roomId,
roomName: m.roomName,
message: m.message,
@@ -51,14 +51,9 @@ export const useMentionMessages = (): void =>
if(GetConfigurationValue<boolean>('mentions_ui.sound', true)) PlaySound(MENTION_SOUND_SAMPLE);
showSingleBubble(
LocalizeText('mentions.notification', [ 'sender', 'room' ], [ entry.senderUsername, entry.roomName ]),
NotificationBubbleType.INFO,
null,
'mentions/toggle',
entry.senderUsername
);
}, [ showSingleBubble ]);
// Notifica laterale custom (avatar + messaggio + dismiss) invece del bubble generico.
pushMentionToast(entry);
}, []);
useMessageEvent<MentionsListEvent>(MentionsListEvent, onMentionsList);
useMessageEvent<MentionReceivedEvent>(MentionReceivedEvent, onMentionReceived);