mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 15:06:20 +00:00
0df810c556
- 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.
64 lines
2.4 KiB
TypeScript
64 lines
2.4 KiB
TypeScript
import { CreateLinkEvent, MarkMentionsReadComposer } from '@nitrots/nitro-renderer';
|
|
import { FC, MouseEvent, useEffect } from 'react';
|
|
import { FaTimes } from 'react-icons/fa';
|
|
import { LocalizeText, SendMessageComposer } from '../../api';
|
|
import { LayoutAvatarImageView } from '../../common';
|
|
import { useExternalSnapshot } from '../../hooks/events/useExternalSnapshot';
|
|
import { markRead } from '../../hooks/mentions/mentionsStore';
|
|
import { dismissMentionToast, getMentionToasts, MentionToast, subscribeMentionToasts } from '../../hooks/mentions/mentionToastsStore';
|
|
|
|
// Quanto resta visibile un toast prima di nascondersi da solo (resta non-letto).
|
|
const AUTO_DISMISS_MS = 8000;
|
|
|
|
const MentionToastItemView: FC<{ toast: MentionToast }> = ({ toast }) =>
|
|
{
|
|
useEffect(() =>
|
|
{
|
|
const timer = window.setTimeout(() => dismissMentionToast(toast.mentionId), AUTO_DISMISS_MS);
|
|
return () => window.clearTimeout(timer);
|
|
}, [ toast.mentionId ]);
|
|
|
|
// Dismiss esplicito: segna letta (badge toolbar si aggiorna) + persiste sul server + chiude.
|
|
const onDismiss = (event: MouseEvent) =>
|
|
{
|
|
event.stopPropagation();
|
|
markRead(toast.mentionId);
|
|
SendMessageComposer(new MarkMentionsReadComposer(1, toast.mentionId));
|
|
dismissMentionToast(toast.mentionId);
|
|
};
|
|
|
|
const onOpen = () =>
|
|
{
|
|
CreateLinkEvent('mentions/toggle');
|
|
dismissMentionToast(toast.mentionId);
|
|
};
|
|
|
|
return (
|
|
<div className="mention-toast" onClick={ onOpen }>
|
|
<div className="mention-toast-avatar">
|
|
<LayoutAvatarImageView headOnly direction={ 2 } figure={ toast.senderFigure } />
|
|
</div>
|
|
<div className="mention-toast-body">
|
|
<div className="mention-toast-title">{ toast.senderUsername }</div>
|
|
<div className="mention-toast-message">{ toast.message }</div>
|
|
</div>
|
|
<button className="mention-toast-dismiss" title={ LocalizeText('generic.cancel') } type="button" onClick={ onDismiss }>
|
|
<FaTimes />
|
|
</button>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const MentionToastsView: FC = () =>
|
|
{
|
|
const toasts = useExternalSnapshot(subscribeMentionToasts, getMentionToasts);
|
|
|
|
if(!toasts || !toasts.length) return null;
|
|
|
|
return (
|
|
<div className="mention-toasts">
|
|
{ toasts.map(toast => <MentionToastItemView key={ toast.mentionId } toast={ toast } />) }
|
|
</div>
|
|
);
|
|
};
|