fix(app): render mutual guilds correctly regardless of cache (#46)

This commit is contained in:
hampus-fluxer 2026-01-06 03:53:48 +01:00 committed by GitHub
parent 6f21a7e37b
commit 30869f8c3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 12 deletions

View File

@ -94,6 +94,7 @@ import type {ContextMenuTargetElement} from '~/stores/ContextMenuStore';
import ContextMenuStore, {isContextMenuNodeTarget} from '~/stores/ContextMenuStore';
import DeveloperOptionsStore from '~/stores/DeveloperOptionsStore';
import GuildMemberStore from '~/stores/GuildMemberStore';
import GuildStore from '~/stores/GuildStore';
import MemberPresenceSubscriptionStore from '~/stores/MemberPresenceSubscriptionStore';
import ModalStore from '~/stores/ModalStore';
import PermissionStore from '~/stores/PermissionStore';
@ -332,7 +333,22 @@ const ProfileModalContent: React.FC<ProfileModalContentProps> = observer(
ModalActionCreators.push(modal(() => <CustomStatusModal />));
}, []);
const mutualGuilds = React.useMemo(() => GuildMemberStore.getMutualGuilds(user.id), [user.id]);
const profileMutualGuilds = profile?.mutualGuilds ?? [];
type MutualGuildDisplay = {
guild: GuildRecord;
nick: string | null;
};
const mutualGuildDisplayItems = React.useMemo(() => {
return profileMutualGuilds
.map((mutualGuild) => {
const guild = GuildStore.getGuild(mutualGuild.id);
if (!guild) {
return null;
}
return {guild, nick: mutualGuild.nick};
})
.filter((item): item is MutualGuildDisplay => item !== null);
}, [profileMutualGuilds]);
const mutualGroups = ChannelStore.dmChannels.filter(
(channel) => channel.isGroupDM() && channel.recipientIds.includes(user.id),
);
@ -355,14 +371,14 @@ const ProfileModalContent: React.FC<ProfileModalContentProps> = observer(
const count = mutualGroups.length;
return t`Mutual Groups (${count})`;
}
default: {
const count = mutualGuilds.length;
return t`Mutual Communities (${count})`;
}
default: {
const count = profileMutualGuilds.length;
return t`Mutual Communities (${count})`;
}
},
[t, mutualFriendsCount, mutualGroups.length, mutualGuilds.length],
);
}
},
[t, mutualFriendsCount, mutualGroups.length, profileMutualGuilds.length],
);
const openMutualMenu = React.useCallback(
(event: React.MouseEvent<HTMLButtonElement>) => {
@ -571,16 +587,17 @@ const ProfileModalContent: React.FC<ProfileModalContentProps> = observer(
const renderMutualGuildsList = React.useCallback(() => {
return (
<div className={userProfileModalStyles.mutualFriendsList}>
{mutualGuilds.map((guild) => (
{mutualGuildDisplayItems.map(({guild, nick}) => (
<MutualGuildItem
key={guild.id}
guild={guild}
nick={nick}
onClick={() => handleGuildClick(guild)}
onContextMenu={(e) => handleGuildContextMenu(e, guild)}
isContextMenuOpen={isContextMenuOpenFor}
/>
))}
{mutualGuilds.length === 0 && (
{profileMutualGuilds.length === 0 && (
<div className={userProfileModalStyles.emptyState}>
<UsersThreeIcon className={userProfileModalStyles.emptyStateIcon} />
<Trans>No mutual communities found.</Trans>
@ -588,7 +605,13 @@ const ProfileModalContent: React.FC<ProfileModalContentProps> = observer(
)}
</div>
);
}, [handleGuildClick, handleGuildContextMenu, isContextMenuOpenFor, mutualGuilds]);
}, [
handleGuildClick,
handleGuildContextMenu,
isContextMenuOpenFor,
mutualGuildDisplayItems,
profileMutualGuilds.length,
]);
const renderMutualTabContent = React.useCallback(() => {
switch (mutualView) {
@ -751,11 +774,13 @@ const MutualFriendItem = ({
const MutualGuildItem = ({
guild,
nick,
onClick,
onContextMenu,
isContextMenuOpen,
}: {
guild: GuildRecord;
nick: string | null;
onClick: () => void;
onContextMenu: (e: React.MouseEvent) => void;
isContextMenuOpen: (target: EventTarget | null) => boolean;
@ -782,6 +807,7 @@ const MutualGuildItem = ({
/>
<div className={userProfileModalStyles.mutualFriendInfo}>
<span className={userProfileModalStyles.mutualFriendName}>{guild.name}</span>
{nick && <span className={userProfileModalStyles.mutualFriendUsername}>{nick}</span>}
</div>
</div>
);

View File

@ -24,6 +24,11 @@ import GuildMemberStore from '~/stores/GuildMemberStore';
import GuildStore from '~/stores/GuildStore';
import UserStore from '~/stores/UserStore';
export type ProfileMutualGuild = Readonly<{
id: string;
nick: string | null;
}>;
export type Profile = Readonly<{
user: UserPartial;
user_profile: UserProfile;
@ -34,6 +39,7 @@ export type Profile = Readonly<{
premium_since?: string;
premium_lifetime_sequence?: number;
mutual_friends?: Array<UserPartial>;
mutual_guilds?: Array<ProfileMutualGuild>;
}>;
export class ProfileRecord {
@ -46,6 +52,7 @@ export class ProfileRecord {
readonly premiumSince: Date | null;
readonly premiumLifetimeSequence: number | null;
readonly mutualFriends: ReadonlyArray<UserPartial> | null;
readonly mutualGuilds: ReadonlyArray<ProfileMutualGuild> | null;
constructor(profile: Profile, guildId?: string) {
this.userId = profile.user.id;
@ -57,6 +64,7 @@ export class ProfileRecord {
this.premiumSince = profile.premium_since ? new Date(profile.premium_since) : null;
this.premiumLifetimeSequence = profile.premium_lifetime_sequence ?? null;
this.mutualFriends = profile.mutual_friends ? Object.freeze([...profile.mutual_friends]) : null;
this.mutualGuilds = profile.mutual_guilds ? Object.freeze([...profile.mutual_guilds]) : null;
}
withUpdates(updates: Partial<Profile>): ProfileRecord {
@ -76,6 +84,7 @@ export class ProfileRecord {
? updates.premium_lifetime_sequence
: (this.premiumLifetimeSequence ?? undefined),
mutual_friends: updates.mutual_friends ?? (this.mutualFriends ? [...this.mutualFriends] : undefined),
mutual_guilds: updates.mutual_guilds ?? (this.mutualGuilds ? [...this.mutualGuilds] : undefined),
},
this.guildId ?? undefined,
);
@ -129,7 +138,8 @@ export class ProfileRecord {
this.premiumType === other.premiumType &&
this.premiumSince === other.premiumSince &&
this.premiumLifetimeSequence === other.premiumLifetimeSequence &&
JSON.stringify(this.mutualFriends) === JSON.stringify(other.mutualFriends)
JSON.stringify(this.mutualFriends) === JSON.stringify(other.mutualFriends) &&
JSON.stringify(this.mutualGuilds) === JSON.stringify(other.mutualGuilds)
);
}
@ -143,6 +153,7 @@ export class ProfileRecord {
premium_since: this.premiumSince?.toISOString() ?? undefined,
premium_lifetime_sequence: this.premiumLifetimeSequence ?? undefined,
mutual_friends: this.mutualFriends ? [...this.mutualFriends] : undefined,
mutual_guilds: this.mutualGuilds ? [...this.mutualGuilds] : undefined,
};
}
}