mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
fix(app): show the full user tag beside display names instead of a bare discriminator (#1696)
This commit is contained in:
1 parent
10ae4bfe1e
commit
3fa766c39c
24 files changed
+53
-58
No files matched your search
+2
-1
@@ -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 (
|
||||
|
||||
@@ -236,6 +236,8 @@
|
||||
}
|
||||
|
||||
.accountMenuDiscriminator {
|
||||
margin-left: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-tertiary);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<FocusRing
|
||||
key={account.userId}
|
||||
@@ -344,7 +347,7 @@ const SwitchAccountsMenu = observer(
|
||||
className={styles.accountMenuDiscriminator}
|
||||
data-flx="app.floating.user-area-popout.switch-accounts-menu.account-menu-discriminator"
|
||||
>
|
||||
#{discriminator}
|
||||
{accountTag}
|
||||
</span>
|
||||
</span>
|
||||
{isCurrent && (
|
||||
|
||||
@@ -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}) => (
|
||||
<VoiceParticipantContextMenu
|
||||
user={user}
|
||||
participantName={NicknameUtils.getNickname(user)}
|
||||
participantName={NicknameUtils.getNickname(user, guildId)}
|
||||
onClose={onClose}
|
||||
guildId={guildId}
|
||||
isGroupedItem={true}
|
||||
@@ -244,7 +244,7 @@ export const GroupedVoiceParticipant = observer(function GroupedVoiceParticipant
|
||||
)}
|
||||
data-flx="app.grouped-voice-participant.participant-name"
|
||||
>
|
||||
{NicknameUtils.getNickname(user)}
|
||||
{NicknameUtils.getNickname(user, guildId)}
|
||||
</span>
|
||||
<Tooltip
|
||||
text={
|
||||
|
||||
@@ -127,7 +127,7 @@ const ResolvedDMListItem = observer(function ResolvedDMListItem({
|
||||
const isMuted = UserGuildSettings.isChannelMuted(null, channel.id);
|
||||
const mentionCount = ReadStates.getMentionCount(channel.id);
|
||||
const unreadState = resolveDMListItemUnreadState(channel.id);
|
||||
const directMessageName = recipient ? NicknameUtils.getNickname(recipient) : null;
|
||||
const directMessageName = recipient ? NicknameUtils.getNickname(recipient, null, channel.id) : null;
|
||||
const computedDisplayName = ChannelUtils.getDMDisplayName(channel);
|
||||
const displayName = isGroupDM ? computedDisplayName : (directMessageName ?? computedDisplayName);
|
||||
const hasActiveCall = CallState.hasActiveCall(channel.id);
|
||||
|
||||
@@ -85,6 +85,7 @@ button.clickable:active {
|
||||
}
|
||||
|
||||
.discriminator {
|
||||
margin-left: 0.25rem;
|
||||
color: var(--text-tertiary);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import type {Account} from '@app/features/platform/state/AuthSession';
|
||||
import {remFromPx} from '@app/features/theme/layout/RemFromPx';
|
||||
import {MockAvatar} from '@app/features/ui/components/MockAvatar';
|
||||
import FocusRing from '@app/features/ui/focus_ring/FocusRing';
|
||||
import * as NicknameUtils from '@app/features/user/utils/NicknameUtils';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
import {Trans, useLingui} from '@lingui/react/macro';
|
||||
import {CaretRightIcon, CheckIcon, DotsThreeIcon} from '@phosphor-icons/react';
|
||||
@@ -52,7 +53,10 @@ export const AccountRow = observer(
|
||||
const {i18n} = useLingui();
|
||||
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;
|
||||
const menuButtonRef = useRef<HTMLButtonElement | null>(null);
|
||||
const isContextMenuOpen = useContextMenuHoverState(menuButtonRef, Boolean(onMenuClick));
|
||||
const handleMenuClick = useCallback(
|
||||
@@ -96,7 +100,7 @@ export const AccountRow = observer(
|
||||
>
|
||||
{displayName}
|
||||
<span className={styles.discriminator} data-flx="auth.accounts.account-row.discriminator">
|
||||
#{discriminator}
|
||||
{accountTag}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
@@ -110,7 +114,7 @@ export const AccountRow = observer(
|
||||
>
|
||||
{displayName}
|
||||
<span className={styles.discriminator} data-flx="auth.accounts.account-row.discriminator--2">
|
||||
#{discriminator}
|
||||
{accountTag}
|
||||
</span>
|
||||
</span>
|
||||
) : (
|
||||
@@ -124,10 +128,7 @@ export const AccountRow = observer(
|
||||
</div>
|
||||
{variant !== 'manage' ? (
|
||||
<span className={clsx('user-text', styles.tag)} data-flx="auth.accounts.account-row.user-text--4">
|
||||
{displayName}
|
||||
<span className={styles.discriminator} data-flx="auth.accounts.account-row.discriminator--3">
|
||||
#{discriminator}
|
||||
</span>
|
||||
{accountTag}
|
||||
</span>
|
||||
) : null}
|
||||
{variant === 'manage' && isCurrent ? (
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<User>, channel: Channel) => {
|
||||
const [a, b, c] = typingUsers.map((user) => {
|
||||
const member = GuildMembers.getMember(channel.guildId ?? '', user.id);
|
||||
|
||||
+4
-3
@@ -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;
|
||||
}
|
||||
|
||||
+2
-2
@@ -35,7 +35,7 @@ export const ChannelInfoHeader: React.FC<ChannelInfoHeaderProps> = ({
|
||||
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 (
|
||||
<div className={styles.channelInfoSection} data-flx="channel.channel-details-bottom-sheet.channel-info-section">
|
||||
<Sheet.CloseButton
|
||||
@@ -83,7 +83,7 @@ export const ChannelInfoHeader: React.FC<ChannelInfoHeaderProps> = ({
|
||||
className={styles.channelInfoDiscriminator}
|
||||
data-flx="channel.channel-details-bottom-sheet.channel-info-discriminator"
|
||||
>
|
||||
#{recipient.discriminator}
|
||||
{NicknameUtils.formatUserTagForStreamerMode(recipient)}
|
||||
</span>
|
||||
</div>
|
||||
{recipient.bot && (
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ export const DMMembersList: React.FC<DMMembersListProps> = ({
|
||||
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 (
|
||||
<div className={styles.dmMembersContainer} data-flx="channel.channel-details-bottom-sheet.dm-members-container">
|
||||
{isDM && recipient && (
|
||||
|
||||
@@ -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 '';
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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 = (
|
||||
<span key={id} className={markupStyles.mention} data-flx="messaging.markdown.renderers.mention-renderer.span">
|
||||
<MentionLabel data-flx="messaging.markdown.renderers.mention-renderer.mention-label">
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -55,7 +55,7 @@ export const IARModalPreview: React.FC<IARModalPreviewProps> = ({context, curren
|
||||
{NicknameUtils.getDisplayName(context.user)}
|
||||
</div>
|
||||
<div className={styles.previewSubtitle} data-flx="moderation.iar-modal-preview.preview-subtitle">
|
||||
#{context.user.discriminator?.toString().padStart(4, '0') ?? '0000'}
|
||||
{NicknameUtils.formatUserTagForStreamerMode(context.user)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -133,7 +133,7 @@ const MutualFriendsList: React.FC<{profile: Profile; onClose: () => void}> = obs
|
||||
/>
|
||||
<div className={styles.itemInfo} data-flx="user.mutual-items-sheet.mutual-friends-list.item-info">
|
||||
<span className={styles.itemName} data-flx="user.mutual-items-sheet.mutual-friends-list.item-name">
|
||||
{NicknameUtils.getNickname(friendRecord, profile.guildId ?? undefined)}
|
||||
{NicknameUtils.getNickname(friendRecord, profile.guildId ?? null)}
|
||||
</span>
|
||||
<span className={styles.itemDetail} data-flx="user.mutual-items-sheet.mutual-friends-list.item-detail">
|
||||
{NicknameUtils.formatTagForStreamerMode(friendRecord.tag)}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 (
|
||||
<div key={user.id} className={styles.userCard} data-flx="user.blocked-users-tab.user-card">
|
||||
<div className={styles.userInfo} data-flx="user.blocked-users-tab.user-info">
|
||||
@@ -162,7 +162,7 @@ export const BlockedUsersContent: React.FC = observer(() => {
|
||||
{displayName}
|
||||
</span>
|
||||
<span className={styles.discriminator} data-flx="user.blocked-users-tab.discriminator">
|
||||
#{user.discriminator}
|
||||
{NicknameUtils.formatUserTagForStreamerMode(user)}
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ export const MutualFriendItem: React.FC<MutualFriendItemProps> = ({
|
||||
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)}
|
||||
</span>
|
||||
<span
|
||||
className={userProfileModalStyles.mutualFriendUsername}
|
||||
|
||||
Reference in new issue
Block a user