diff --git a/fluxer_app/src/features/app/components/dialogs/shared/UseForwardChannelObservations.ts b/fluxer_app/src/features/app/components/dialogs/shared/UseForwardChannelObservations.ts index 09a41c2a3..03a5024ec 100644 --- a/fluxer_app/src/features/app/components/dialogs/shared/UseForwardChannelObservations.ts +++ b/fluxer_app/src/features/app/components/dialogs/shared/UseForwardChannelObservations.ts @@ -13,6 +13,7 @@ import Relationships from '@app/features/relationship/state/Relationships'; import Slowmode from '@app/features/slowmode/state/Slowmode'; import {useNow} from '@app/features/ui/state/Tick'; import Users from '@app/features/user/state/Users'; +import * as NicknameUtils from '@app/features/user/utils/NicknameUtils'; import {ChannelTypes, Permissions} from '@fluxer/constants/src/ChannelConstants'; import {GuildOperations} from '@fluxer/constants/src/GuildConstants'; import {CHANNEL_RATE_LIMIT_PER_USER_MAX} from '@fluxer/constants/src/LimitConstants'; @@ -63,7 +64,7 @@ function resolveChannelDisplayName(channel: Channel, i18n: I18n): string { if (channel.type === ChannelTypes.DM) { const recipient = channel.recipientIds.length > 0 ? Users.getUser(channel.recipientIds[0]) : null; if (recipient) { - return Relationships.getRelationship(recipient.id)?.nickname || recipient.displayName; + return NicknameUtils.getNickname(recipient, null); } } if ( diff --git a/fluxer_app/src/features/app/components/floating/UserAreaPopout.module.css b/fluxer_app/src/features/app/components/floating/UserAreaPopout.module.css index 13da2446c..f9a611276 100644 --- a/fluxer_app/src/features/app/components/floating/UserAreaPopout.module.css +++ b/fluxer_app/src/features/app/components/floating/UserAreaPopout.module.css @@ -236,6 +236,8 @@ } .accountMenuDiscriminator { + margin-left: 0.25rem; + font-size: 0.75rem; color: var(--text-tertiary); font-weight: 400; } diff --git a/fluxer_app/src/features/app/components/floating/UserAreaPopout.tsx b/fluxer_app/src/features/app/components/floating/UserAreaPopout.tsx index f38aedaf1..56fc0262f 100644 --- a/fluxer_app/src/features/app/components/floating/UserAreaPopout.tsx +++ b/fluxer_app/src/features/app/components/floating/UserAreaPopout.tsx @@ -301,7 +301,10 @@ const SwitchAccountsMenu = observer( const isCurrent = account.userId === currentAccountId; const avatarUrl = getAccountAvatarUrl(account); const displayName = getAccountDisplayName(account, '???'); - const discriminator = account.userData?.discriminator ?? '0000'; + const userData = account.userData; + const accountTag = userData + ? NicknameUtils.formatTagForStreamerMode(`${userData.username}#${userData.discriminator}`) + : displayName; return ( - #{discriminator} + {accountTag} {isCurrent && ( diff --git a/fluxer_app/src/features/app/components/layout/GroupedVoiceParticipant.tsx b/fluxer_app/src/features/app/components/layout/GroupedVoiceParticipant.tsx index 64216e62c..c9c1b8903 100644 --- a/fluxer_app/src/features/app/components/layout/GroupedVoiceParticipant.tsx +++ b/fluxer_app/src/features/app/components/layout/GroupedVoiceParticipant.tsx @@ -37,9 +37,9 @@ const OPEN_PROFILE_FOR_DESCRIPTOR = msg({ comment: 'Short label in the app layout grouped voice participant. Preserve {nickname}; it is inserted by code.', }); -function useOpenProfileAriaLabel(user: User) { +function useOpenProfileAriaLabel(user: User, guildId: string) { const {i18n} = useLingui(); - const nickname = NicknameUtils.getNickname(user); + const nickname = NicknameUtils.getNickname(user, guildId); return useMemo(() => i18n._(OPEN_PROFILE_FOR_DESCRIPTOR, {nickname}), [nickname, i18n.locale]); } @@ -56,7 +56,7 @@ export const GroupedVoiceParticipant = observer(function GroupedVoiceParticipant guildId, anySpeaking: propAnySpeaking, }: GroupedVoiceParticipantProps) { - const openProfileAriaLabel = useOpenProfileAriaLabel(user); + const openProfileAriaLabel = useOpenProfileAriaLabel(user, guildId); const mediaEngineVersion = useMediaEngineVersion(); const [isExpanded, setIsExpanded] = useState(false); const currentUser = Users.getCurrentUser(); @@ -77,7 +77,7 @@ export const GroupedVoiceParticipant = observer(function GroupedVoiceParticipant ContextMenuCommands.openFromEvent(event, ({onClose}) => ( - {NicknameUtils.getNickname(user)} + {NicknameUtils.getNickname(user, guildId)} (null); const isContextMenuOpen = useContextMenuHoverState(menuButtonRef, Boolean(onMenuClick)); const handleMenuClick = useCallback( @@ -96,7 +100,7 @@ export const AccountRow = observer( > {displayName} - #{discriminator} + {accountTag} @@ -110,7 +114,7 @@ export const AccountRow = observer( > {displayName} - #{discriminator} + {accountTag} ) : ( @@ -124,10 +128,7 @@ export const AccountRow = observer( {variant !== 'manage' ? ( - {displayName} - - #{discriminator} - + {accountTag} ) : null} {variant === 'manage' && isCurrent ? ( diff --git a/fluxer_app/src/features/channel/components/AutocompleteMention.tsx b/fluxer_app/src/features/channel/components/AutocompleteMention.tsx index 37b78375a..7eb9d66a8 100644 --- a/fluxer_app/src/features/channel/components/AutocompleteMention.tsx +++ b/fluxer_app/src/features/channel/components/AutocompleteMention.tsx @@ -83,7 +83,7 @@ export const AutocompleteMention = observer(function AutocompleteMention({ const routeParams = useParams() as {guildId?: string}; const guildId = routeParams.guildId; const guild = Guilds.getGuild(guildId == null ? '' : guildId); - const nicknameGuildId = guild == null ? undefined : guild.id; + const nicknameGuildId = guild == null ? null : guild.id; const members = options.filter(isMentionMember); const users = options.filter(isMentionUser); const roles = options.filter(isMentionRole); diff --git a/fluxer_app/src/features/channel/components/TypingUsers.tsx b/fluxer_app/src/features/channel/components/TypingUsers.tsx index 15b584684..11e3aab01 100644 --- a/fluxer_app/src/features/channel/components/TypingUsers.tsx +++ b/fluxer_app/src/features/channel/components/TypingUsers.tsx @@ -43,7 +43,7 @@ const HANDFUL_DESCRIPTOR = A_HANDFUL_OF_KEYBOARD_WARRIORS_ARE_ASSEMBLING_DESCRIP const SYMPHONY_DESCRIPTOR = A_SYMPHONY_OF_CLACKING_KEYS_IS_UNDERWAY_DESCRIPTOR; const FIESTA_DESCRIPTOR = IT_S_A_FULL_BLOWN_TYPING_FIESTA_IN_DESCRIPTOR; const APOCALYPSE_DESCRIPTOR = WHOA_IT_S_A_TYPING_APOCALYPSE_DESCRIPTOR; -const getDisplayName = (user: User, guildId?: string | null) => NicknameUtils.getNickname(user, guildId ?? undefined); +const getDisplayName = (user: User, guildId?: string | null) => NicknameUtils.getNickname(user, guildId ?? null); export const getTypingText = (i18n: I18n, typingUsers: ReadonlyArray, channel: Channel) => { const [a, b, c] = typingUsers.map((user) => { const member = GuildMembers.getMember(channel.guildId ?? '', user.id); diff --git a/fluxer_app/src/features/channel/components/bottomsheets/ChannelDetailsBottomSheet.module.css b/fluxer_app/src/features/channel/components/bottomsheets/ChannelDetailsBottomSheet.module.css index 34c570e6c..645cc8226 100644 --- a/fluxer_app/src/features/channel/components/bottomsheets/ChannelDetailsBottomSheet.module.css +++ b/fluxer_app/src/features/channel/components/bottomsheets/ChannelDetailsBottomSheet.module.css @@ -458,6 +458,7 @@ align-items: center; min-width: 0; overflow: hidden; + gap: 0.35rem; } .channelInfoUsername { @@ -471,9 +472,9 @@ } .channelInfoDiscriminator { - font-weight: 600; - font-size: 1.125rem; - line-height: 1.75rem; + font-weight: 400; + font-size: 0.875rem; + line-height: 1.25rem; color: var(--text-tertiary); flex-shrink: 0; } diff --git a/fluxer_app/src/features/channel/components/bottomsheets/channel_details_bottom_sheet/ChannelInfoHeader.tsx b/fluxer_app/src/features/channel/components/bottomsheets/channel_details_bottom_sheet/ChannelInfoHeader.tsx index 605c35218..0606c11af 100644 --- a/fluxer_app/src/features/channel/components/bottomsheets/channel_details_bottom_sheet/ChannelInfoHeader.tsx +++ b/fluxer_app/src/features/channel/components/bottomsheets/channel_details_bottom_sheet/ChannelInfoHeader.tsx @@ -35,7 +35,7 @@ export const ChannelInfoHeader: React.FC = ({ const isDM = channel.type === ChannelTypes.DM; const isPersonalNotes = channel.type === ChannelTypes.DM_PERSONAL_NOTES; const isGroupDM = channel.type === ChannelTypes.GROUP_DM; - const recipientDisplayName = recipient ? NicknameUtils.getNickname(recipient) : ''; + const recipientDisplayName = recipient ? NicknameUtils.getNickname(recipient, null, channel.id) : ''; return (
= ({ className={styles.channelInfoDiscriminator} data-flx="channel.channel-details-bottom-sheet.channel-info-discriminator" > - #{recipient.discriminator} + {NicknameUtils.formatUserTagForStreamerMode(recipient)}
{recipient.bot && ( diff --git a/fluxer_app/src/features/channel/components/bottomsheets/channel_details_bottom_sheet/DMMembersList.tsx b/fluxer_app/src/features/channel/components/bottomsheets/channel_details_bottom_sheet/DMMembersList.tsx index 5d2cc111e..1829a2ffa 100644 --- a/fluxer_app/src/features/channel/components/bottomsheets/channel_details_bottom_sheet/DMMembersList.tsx +++ b/fluxer_app/src/features/channel/components/bottomsheets/channel_details_bottom_sheet/DMMembersList.tsx @@ -39,7 +39,7 @@ export const DMMembersList: React.FC = ({ const {i18n} = useLingui(); const isDM = channel.type === ChannelTypes.DM; const isGroupDM = channel.type === ChannelTypes.GROUP_DM; - const recipientDisplayName = recipient ? NicknameUtils.getNickname(recipient) : ''; + const recipientDisplayName = recipient ? NicknameUtils.getNickname(recipient, null, channel.id) : ''; return (
{isDM && recipient && ( diff --git a/fluxer_app/src/features/channel/components/channel_header/useChannelHeaderData.ts b/fluxer_app/src/features/channel/components/channel_header/useChannelHeaderData.ts index 8676df707..0cdd18015 100644 --- a/fluxer_app/src/features/channel/components/channel_header/useChannelHeaderData.ts +++ b/fluxer_app/src/features/channel/components/channel_header/useChannelHeaderData.ts @@ -9,6 +9,7 @@ import { } from '@app/features/i18n/utils/CommonMessageDescriptors'; import type {User} from '@app/features/user/models/User'; import Users from '@app/features/user/state/Users'; +import * as NicknameUtils from '@app/features/user/utils/NicknameUtils'; import {ChannelTypes} from '@fluxer/constants/src/ChannelConstants'; import {useLingui} from '@lingui/react/macro'; import {useMemo} from 'react'; @@ -39,12 +40,7 @@ export const useChannelHeaderData = (channel?: Channel): ChannelHeaderData => { } return Users.getUser(channel.recipientIds[0]) ?? null; }, [channel, isDM]); - const directMessageName = useMemo(() => { - if (!isDM || !recipient) { - return ''; - } - return recipient.displayName; - }, [isDM, recipient]); + const directMessageName = isDM && recipient && channel ? NicknameUtils.getNickname(recipient, null, channel.id) : ''; const groupDMName = useMemo(() => { if (!isGroupDM || !channel) { return ''; diff --git a/fluxer_app/src/features/channel/components/direct_message/DMListItem.tsx b/fluxer_app/src/features/channel/components/direct_message/DMListItem.tsx index e5211d81f..d81e11794 100644 --- a/fluxer_app/src/features/channel/components/direct_message/DMListItem.tsx +++ b/fluxer_app/src/features/channel/components/direct_message/DMListItem.tsx @@ -249,7 +249,7 @@ const ResolvedDMListItem = observer(function ResolvedDMListItem({ const isCurrentUser = lastMessage.author.id === currentUser?.id; const authorPrefix = isCurrentUser ? `${i18n._(YOU_DESCRIPTOR)}: ` - : `${NicknameUtils.getNickname(lastMessage.author)}: `; + : `${NicknameUtils.getNickname(lastMessage.author, null, channel.id)}: `; if (lastMessage.type !== MessageTypes.DEFAULT && lastMessage.type !== MessageTypes.REPLY) { const systemText = SystemMessageUtils.stringify(lastMessage, i18n); if (systemText) { diff --git a/fluxer_app/src/features/channel/utils/ChannelUtils.tsx b/fluxer_app/src/features/channel/utils/ChannelUtils.tsx index 24b2a71c9..b1a8ffad0 100644 --- a/fluxer_app/src/features/channel/utils/ChannelUtils.tsx +++ b/fluxer_app/src/features/channel/utils/ChannelUtils.tsx @@ -157,7 +157,7 @@ const getDirectMessageDisplayName = (channel: Channel): string => { return i18n._(UNKNOWN_USER_DESCRIPTOR); } const recipient = Users.getUser(channel.recipientIds[0]); - const nickname = recipient ? NicknameUtils.getNickname(recipient) : null; + const nickname = recipient ? NicknameUtils.getNickname(recipient, null, channel.id) : null; return nickname ?? i18n._(UNKNOWN_USER_DESCRIPTOR); }; const getGroupDMDisplayName = (channel: Channel): string => { diff --git a/fluxer_app/src/features/messaging/components/markdown/renderers/MentionRenderer.tsx b/fluxer_app/src/features/messaging/components/markdown/renderers/MentionRenderer.tsx index f466c208a..def29c080 100644 --- a/fluxer_app/src/features/messaging/components/markdown/renderers/MentionRenderer.tsx +++ b/fluxer_app/src/features/messaging/components/markdown/renderers/MentionRenderer.tsx @@ -119,13 +119,7 @@ export const MentionRenderer = observer(function MentionRenderer({ const user = kind.id ? Users.getUser(kind.id) : null; const channel = channelId ? Channels.getChannel(channelId) : undefined; const resolvedGuildId = channel?.guildId || options.guildId || ''; - let name: string | null = null; - if (user) { - name = user.displayName; - if (resolvedGuildId) { - name = NicknameUtils.getNickname(user, resolvedGuildId) || name; - } - } + const name = user ? NicknameUtils.getNickname(user, resolvedGuildId || null, channelId) : null; const genericMention = ( diff --git a/fluxer_app/src/features/messaging/hooks/use_textarea_autocomplete/builders.ts b/fluxer_app/src/features/messaging/hooks/use_textarea_autocomplete/builders.ts index cec2b9602..dd129158c 100644 --- a/fluxer_app/src/features/messaging/hooks/use_textarea_autocomplete/builders.ts +++ b/fluxer_app/src/features/messaging/hooks/use_textarea_autocomplete/builders.ts @@ -42,7 +42,7 @@ export function getMemberDisplayName(member: GuildMember): string { } export function getUserDisplayName(user: User): string { - return firstDisplayText(user.displayName, user.username, user.id); + return DisplayNameUtils.getUntruncatedNickname(user, null); } export interface ParsedMentionQuery { diff --git a/fluxer_app/src/features/messaging/utils/AutocompleteOptionBuilders.ts b/fluxer_app/src/features/messaging/utils/AutocompleteOptionBuilders.ts index 04ce9d8f5..257eb8ed1 100644 --- a/fluxer_app/src/features/messaging/utils/AutocompleteOptionBuilders.ts +++ b/fluxer_app/src/features/messaging/utils/AutocompleteOptionBuilders.ts @@ -46,7 +46,7 @@ export function getMemberDisplayName(member: GuildMember): string { } export function getUserDisplayName(user: User): string { - return firstDisplayText(user.displayName, user.username, user.id); + return DisplayNameUtils.getUntruncatedNickname(user, null); } export interface ParsedMentionQuery { diff --git a/fluxer_app/src/features/messaging/utils/markdown/Plaintext.ts b/fluxer_app/src/features/messaging/utils/markdown/Plaintext.ts index a524ebb8d..008e4c1d6 100644 --- a/fluxer_app/src/features/messaging/utils/markdown/Plaintext.ts +++ b/fluxer_app/src/features/messaging/utils/markdown/Plaintext.ts @@ -364,14 +364,8 @@ function renderMentionToPlaintext(node: MentionNode, options: PlaintextRenderOpt if (!user) { return `@${kind.id}`; } - let name = user.displayName; - if (options.channelId) { - const channel = Channels.getChannel(options.channelId); - if (channel?.guildId) { - name = NicknameUtils.getNickname(user, channel.guildId) || name; - } - } - return `@${name}`; + const channel = options.channelId ? Channels.getChannel(options.channelId) : null; + return `@${NicknameUtils.getNickname(user, channel?.guildId ?? null, options.channelId)}`; } case MentionKind.Role: { const channel = options.channelId ? Channels.getChannel(options.channelId) : null; diff --git a/fluxer_app/src/features/moderation/components/report_modal/IARModalPreview.tsx b/fluxer_app/src/features/moderation/components/report_modal/IARModalPreview.tsx index 90a3ee11d..33c64dbe9 100644 --- a/fluxer_app/src/features/moderation/components/report_modal/IARModalPreview.tsx +++ b/fluxer_app/src/features/moderation/components/report_modal/IARModalPreview.tsx @@ -55,7 +55,7 @@ export const IARModalPreview: React.FC = ({context, curren {NicknameUtils.getDisplayName(context.user)}
- #{context.user.discriminator?.toString().padStart(4, '0') ?? '0000'} + {NicknameUtils.formatUserTagForStreamerMode(context.user)}
); diff --git a/fluxer_app/src/features/user/components/modals/MutualItemsSheet.tsx b/fluxer_app/src/features/user/components/modals/MutualItemsSheet.tsx index 18e2946d6..19955c86f 100644 --- a/fluxer_app/src/features/user/components/modals/MutualItemsSheet.tsx +++ b/fluxer_app/src/features/user/components/modals/MutualItemsSheet.tsx @@ -133,7 +133,7 @@ const MutualFriendsList: React.FC<{profile: Profile; onClose: () => void}> = obs />
- {NicknameUtils.getNickname(friendRecord, profile.guildId ?? undefined)} + {NicknameUtils.getNickname(friendRecord, profile.guildId ?? null)} {NicknameUtils.formatTagForStreamerMode(friendRecord.tag)} diff --git a/fluxer_app/src/features/user/components/modals/tabs/BlockedUsersTab.module.css b/fluxer_app/src/features/user/components/modals/tabs/BlockedUsersTab.module.css index a9a7bc223..58cdfd29b 100644 --- a/fluxer_app/src/features/user/components/modals/tabs/BlockedUsersTab.module.css +++ b/fluxer_app/src/features/user/components/modals/tabs/BlockedUsersTab.module.css @@ -79,6 +79,7 @@ display: flex; min-width: 0; align-items: center; + gap: var(--spacing-1); } .username { @@ -93,10 +94,11 @@ } .discriminator { - font-weight: 600; + flex-shrink: 0; + font-weight: 400; color: color-mix(in srgb, var(--text-primary) 50%, transparent); - font-size: 0.875rem; - line-height: 1.25rem; + font-size: 0.75rem; + line-height: 1rem; } .actions { diff --git a/fluxer_app/src/features/user/components/modals/tabs/BlockedUsersTab.tsx b/fluxer_app/src/features/user/components/modals/tabs/BlockedUsersTab.tsx index 143fb9588..bad42fe01 100644 --- a/fluxer_app/src/features/user/components/modals/tabs/BlockedUsersTab.tsx +++ b/fluxer_app/src/features/user/components/modals/tabs/BlockedUsersTab.tsx @@ -50,7 +50,7 @@ export const BlockedUsersContent: React.FC = observer(() => { const userA = Users.getUser(a.id); const userB = Users.getUser(b.id); if (!userA || !userB) return 0; - return NicknameUtils.getNickname(userA).localeCompare(NicknameUtils.getNickname(userB)); + return NicknameUtils.getNickname(userA, null).localeCompare(NicknameUtils.getNickname(userB, null)); }); }, [relationships]); const handleUnblockUser = (userId: string, event?: {shiftKey?: boolean}) => { @@ -132,7 +132,7 @@ export const BlockedUsersContent: React.FC = observer(() => { {blockedUsers.map((relationship) => { const user = Users.getUser(relationship.id); if (!user) return null; - const displayName = NicknameUtils.getNickname(user); + const displayName = NicknameUtils.getNickname(user, null); return (
@@ -162,7 +162,7 @@ export const BlockedUsersContent: React.FC = observer(() => { {displayName} - #{user.discriminator} + {NicknameUtils.formatUserTagForStreamerMode(user)}
diff --git a/fluxer_app/src/features/user/components/modals/user_profile_modal/MutualFriendItem.tsx b/fluxer_app/src/features/user/components/modals/user_profile_modal/MutualFriendItem.tsx index 0b4d877e0..cd3dba548 100644 --- a/fluxer_app/src/features/user/components/modals/user_profile_modal/MutualFriendItem.tsx +++ b/fluxer_app/src/features/user/components/modals/user_profile_modal/MutualFriendItem.tsx @@ -55,7 +55,7 @@ export const MutualFriendItem: React.FC = ({ className={userProfileModalStyles.mutualFriendName} data-flx="user.user-profile-modal.mutual-friend-item.span" > - {NicknameUtils.getNickname(user, profile?.guildId ?? undefined)} + {NicknameUtils.getNickname(user, profile?.guildId ?? null)}