import { FC, Fragment, ReactNode, useMemo } from 'react'; import { GetNickIconUrl } from '../assets/images/user_custom/nick_icons'; import { PREFIX_EFFECT_KEYFRAMES, getPrefixEffectStyle, getPrefixFontStyle, parseFontSegments, parsePrefixColors } from '../api'; const renderInlineFontMarkup = (text: string): ReactNode => { if(!text) return text; if(text.indexOf(' { if(segment.color) return { segment.text }; return { segment.text }; }); }; interface UserIdentityViewProps { username: string; nickIcon?: string; prefixText?: string; prefixColor?: string; prefixIcon?: string; prefixEffect?: string; prefixFont?: string; displayOrder?: string; showColon?: boolean; className?: string; iconClassName?: string; nameClassName?: string; prefixClassName?: string; } const sanitizeDisplayOrder = (displayOrder?: string) => { const fallback = [ 'icon', 'prefix', 'name' ]; if(!displayOrder?.length) return fallback; const parts = displayOrder.toLowerCase().split('-'); if(parts.length !== 3) return fallback; const unique = new Set(parts); if(unique.size !== 3) return fallback; if(parts.some(part => !fallback.includes(part))) return fallback; return parts; }; export const UserIdentityView: FC = ({ username = '', nickIcon = '', prefixText = '', prefixColor = '', prefixIcon = '', prefixEffect = '', prefixFont = '', displayOrder = 'icon-prefix-name', showColon = false, className = '', iconClassName = 'inline-block w-auto h-auto align-[-1px]', nameClassName = 'username font-bold', prefixClassName = '' }) => { const nickIconUrl = GetNickIconUrl(nickIcon); const prefixColors = useMemo(() => parsePrefixColors(prefixText, prefixColor), [ prefixText, prefixColor ]); const hasMultiColor = (prefixColors.length > 1) && (new Set(prefixColors).size > 1); const prefixStyle = getPrefixEffectStyle(prefixEffect, prefixColors[0] || '#FFFFFF'); const prefixFontStyle = getPrefixFontStyle(prefixFont); const displayParts = sanitizeDisplayOrder(displayOrder); const parts = displayParts.map(part => { switch(part) { case 'icon': if(!nickIconUrl) return null; return ; case 'prefix': if(!prefixText?.length) return null; return ( { prefixIcon && { prefixIcon } } {'{'} { hasMultiColor ? [ ...prefixText ].map((char, index) => ( { char } )) : prefixText } {'}'} ); case 'name': return { renderInlineFontMarkup(username) }{ showColon ? ':' : '' }{ showColon ? ' ' : '' }; default: return null; } }).filter(Boolean); return ( { !!prefixEffect && } { parts } ); };