From 915959a0214daa214f14c338c25f8884f46375d8 Mon Sep 17 00:00:00 2001 From: hampus-fluxer Date: Tue, 6 Jan 2026 06:28:27 +0100 Subject: [PATCH] fix(app): invite member & presence counts (#59) --- .../src/components/channel/InviteEmbed.tsx | 11 ++-- .../components/modals/InviteAcceptModal.tsx | 16 +++++- .../src/utils/invite/GroupDmInviteCounts.ts | 50 +++++++++++++++++++ .../utils/invite/GuildInviteActionState.ts | 15 +----- 4 files changed, 74 insertions(+), 18 deletions(-) create mode 100644 fluxer_app/src/utils/invite/GroupDmInviteCounts.ts diff --git a/fluxer_app/src/components/channel/InviteEmbed.tsx b/fluxer_app/src/components/channel/InviteEmbed.tsx index 09e9a892..448793ec 100644 --- a/fluxer_app/src/components/channel/InviteEmbed.tsx +++ b/fluxer_app/src/components/channel/InviteEmbed.tsx @@ -42,7 +42,6 @@ import {Tooltip} from '~/components/uikit/Tooltip/Tooltip'; import {ComponentDispatch} from '~/lib/ComponentDispatch'; import {Routes} from '~/Routes'; import {UserRecord} from '~/records/UserRecord'; -import ChannelStore from '~/stores/ChannelStore'; import GuildMemberStore from '~/stores/GuildMemberStore'; import GuildStore from '~/stores/GuildStore'; import InviteStore from '~/stores/InviteStore'; @@ -51,6 +50,7 @@ import UserStore from '~/stores/UserStore'; import {isGroupDmInvite, isGuildInvite, isPackInvite as isPackInviteGuard} from '~/types/InviteTypes'; import * as AvatarUtils from '~/utils/AvatarUtils'; +import {getGroupDmInviteCounts} from '~/utils/invite/GroupDmInviteCounts'; import { GuildInvitePrimaryAction, getGuildInviteActionState, @@ -58,7 +58,6 @@ import { isGuildInviteActionDisabled, } from '~/utils/invite/GuildInviteActionState'; import * as RouterUtils from '~/utils/RouterUtils'; - import {getGroupDMTitle, getGuildEmbedSplashAspectRatio, getImageAspectRatioFromBase64} from './InviteEmbed/utils'; import styles from './InviteEmbed.module.css'; @@ -146,8 +145,12 @@ export const InviteEmbed = observer(function InviteEmbed({code}: InviteEmbedProp const groupDMPath = Routes.dmChannel(invite.channel.id); const handleAcceptInvite = () => InviteActionCreators.acceptAndTransitionToChannel(invite.code, i18n); const handleNavigateToGroup = () => RouterUtils.transitionTo(groupDMPath); - const isAlreadyInGroupDM = !!ChannelStore.getChannel(invite.channel.id); - const memberCount = invite.member_count ?? 0; + const groupDMCounts = getGroupDmInviteCounts({ + channelId: invite.channel.id, + inviteMemberCount: invite.member_count, + }); + const isAlreadyInGroupDM = groupDMCounts.hasLocalChannel; + const memberCount = groupDMCounts.memberCount; return ( { if (!invite) return null; + if (isGroupDM && groupDMCounts) { + return { + ...invite, + member_count: groupDMCounts.memberCount, + }; + } return { ...invite, presence_count: presenceCount, member_count: memberCount, }; - }, [invite, presenceCount, memberCount]); + }, [invite, isGroupDM, presenceCount, memberCount, groupDMCounts?.memberCount]); const splashUrl = React.useMemo(() => { if (!invite || !isGuildInvite(invite)) { diff --git a/fluxer_app/src/utils/invite/GroupDmInviteCounts.ts b/fluxer_app/src/utils/invite/GroupDmInviteCounts.ts new file mode 100644 index 00000000..6dd4e460 --- /dev/null +++ b/fluxer_app/src/utils/invite/GroupDmInviteCounts.ts @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2026 Fluxer Contributors + * + * This file is part of Fluxer. + * + * Fluxer is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Fluxer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Fluxer. If not, see . + */ + +import AuthenticationStore from '~/stores/AuthenticationStore'; +import ChannelStore from '~/stores/ChannelStore'; + +export interface GroupDmInviteCounts { + memberCount: number; + hasLocalChannel: boolean; +} + +export const getGroupDmInviteCounts = (params: { + channelId: string; + inviteMemberCount?: number | null; +}): GroupDmInviteCounts => { + const channel = ChannelStore.getChannel(params.channelId); + if (!channel) { + return { + memberCount: params.inviteMemberCount ?? 0, + hasLocalChannel: false, + }; + } + + const memberIds = new Set(channel.recipientIds); + const currentUserId = AuthenticationStore.currentUserId; + if (currentUserId) { + memberIds.add(currentUserId); + } + + return { + memberCount: memberIds.size, + hasLocalChannel: true, + }; +}; diff --git a/fluxer_app/src/utils/invite/GuildInviteActionState.ts b/fluxer_app/src/utils/invite/GuildInviteActionState.ts index 0d1a4797..ce3afb16 100644 --- a/fluxer_app/src/utils/invite/GuildInviteActionState.ts +++ b/fluxer_app/src/utils/invite/GuildInviteActionState.ts @@ -22,7 +22,6 @@ import type {Guild, GuildRecord} from '~/records/GuildRecord'; import type {Invite} from '~/records/MessageRecord'; import AuthenticationStore from '~/stores/AuthenticationStore'; import GuildMemberStore from '~/stores/GuildMemberStore'; -import PresenceStore from '~/stores/PresenceStore'; import {isGuildInvite} from '~/types/InviteTypes'; const normalizeFeatures = (features?: Iterable | null): Array => { @@ -55,18 +54,8 @@ export const getGuildInviteActionState = (params: { const guildId = guildRecord?.id ?? null; const currentUserId = AuthenticationStore.currentUserId; const isMember = Boolean(guildId && currentUserId && GuildMemberStore.getMember(guildId, currentUserId)); - const presenceCount = - guildId && isMember - ? PresenceStore.getPresenceCount(guildId) - : params.invite && isGuildInvite(params.invite) - ? params.invite.presence_count - : 0; - const memberCount = - guildId && isMember - ? GuildMemberStore.getMemberCount(guildId) - : params.invite && isGuildInvite(params.invite) - ? params.invite.member_count - : 0; + const presenceCount = params.invite && isGuildInvite(params.invite) ? (params.invite.presence_count ?? 0) : 0; + const memberCount = params.invite && isGuildInvite(params.invite) ? (params.invite.member_count ?? 0) : 0; const features = normalizeFeatures(guildRecord?.features ?? inviteGuild?.features); return {