mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 07:26:19 +00:00
feat(mentions): overhaul, refactor, notification bubble & window update
Chat tagging: - Any @user is a visible tag in chat bubbles (the .mention-tag CSS never existed, so highlighting was invisible); self/alias mentions get a gold emphasis. Fixes cross-room tags not being highlighted. Mentions window: - Redesigned: unread count in the header, restyled filter chips + a refresh button, CSS-driven list/date-groups, adaptive height (compact when few, capped + scroll when many), polished empty state. - Rows: framed avatar (friends-list head crop so the face is never clipped), per-row unread dot, type marker, icon action buttons (goto / remove). - Re-requests from the server each time it opens. Autocomplete: - Never suggests the viewer themselves; suggests room users + online friends + aliases. Notifications: - Mention toast removed; mentions flow through the client's standard notification stream via a dedicated mention bubble (avatar + actions) in the default position. EVERY received mention surfaces (independent of the generic info-feed toggle, gated only by mentions_ui.enabled). Refactor (behaviour-preserving): - Centralised @-token classification in api/mentions/mentionTokens. - Moved mentionsFormat -> api/mentions, useMentionActions -> hooks/mentions. - Extracted ChatInputView @-autocomplete into a tested useChatMentions hook + pure helper; removed the dead duplicate useMentionAutocomplete.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
// Shared @-mention token classification, used by both the chat-bubble
|
||||
// highlighter and the mentions panel so the two can't diverge.
|
||||
|
||||
export const MENTION_ROOM_ALIASES: ReadonlyArray<string> = [
|
||||
'all', 'everyone', 'tutti',
|
||||
'friends', 'amici',
|
||||
'room', 'stanza'
|
||||
];
|
||||
|
||||
const NON_NICK_CHARS = /[^A-Za-z0-9_]/g;
|
||||
|
||||
const normalizeToken = (token: string): string =>
|
||||
{
|
||||
if(!token || (token.length < 2) || (token.charAt(0) !== '@')) return '';
|
||||
|
||||
return token.substring(1).replace(NON_NICK_CHARS, '').toLowerCase();
|
||||
};
|
||||
|
||||
const normalizeNick = (value: string): string => (value || '').replace(NON_NICK_CHARS, '').toLowerCase();
|
||||
|
||||
// '' = not a mention; 'tag' = any @user (subtle chip); 'self' = the token
|
||||
// targets the viewer (own nick) or is a broadcast alias (strong highlight).
|
||||
export type MentionKind = '' | 'tag' | 'self';
|
||||
|
||||
export const classifyMentionToken = (
|
||||
token: string,
|
||||
ownUsername: string,
|
||||
aliases: ReadonlyArray<string> = MENTION_ROOM_ALIASES
|
||||
): MentionKind =>
|
||||
{
|
||||
const nick = normalizeToken(token);
|
||||
|
||||
if(!nick) return '';
|
||||
|
||||
const ownLower = normalizeNick(ownUsername);
|
||||
|
||||
if((ownLower && (nick === ownLower)) || aliases.some(alias => alias.toLowerCase() === nick)) return 'self';
|
||||
|
||||
return 'tag';
|
||||
};
|
||||
|
||||
/**
|
||||
* Back-compat boolean — true only when the token targets the viewer or a
|
||||
* broadcast alias (i.e. "I was mentioned"), not for generic @user tags.
|
||||
*/
|
||||
export const tokenIsMention = (
|
||||
token: string,
|
||||
ownUsername: string,
|
||||
aliases: ReadonlyArray<string> = MENTION_ROOM_ALIASES
|
||||
): boolean => (classifyMentionToken(token, ownUsername, aliases) === 'self');
|
||||
Reference in New Issue
Block a user