diff --git a/src/components/dms/util.ts b/src/components/dms/util.ts index 89b9c5b01f..7fe5f91dc3 100644 --- a/src/components/dms/util.ts +++ b/src/components/dms/util.ts @@ -47,6 +47,22 @@ export function canBeAddedToGroup(profile: bsky.profile.AnyProfileView) { } } +/** + * Resolves the effective `allowGroupInvites` value for a chat declaration. + * When unset, group invites follow the general DM preference + * (`allowIncoming`), which itself defaults to `following`. This mirrors the + * `undefined` fallthrough in canBeAddedToGroup, and is the single source of + * truth for both displaying and persisting the setting. + */ +export function resolveAllowGroupInvites( + chat: {allowIncoming?: string; allowGroupInvites?: string} | undefined, +): 'all' | 'none' | 'following' { + return (chat?.allowGroupInvites ?? chat?.allowIncoming ?? 'following') as + | 'all' + | 'none' + | 'following' +} + export function localDateString(date: Date) { // can't use toISOString because it should be in local time const mm = date.getMonth() diff --git a/src/screens/Messages/Settings.tsx b/src/screens/Messages/Settings.tsx index f49311b0da..91d9f879d5 100644 --- a/src/screens/Messages/Settings.tsx +++ b/src/screens/Messages/Settings.tsx @@ -13,6 +13,7 @@ import {AgeRestrictedScreen} from '#/components/ageAssurance/AgeRestrictedScreen import {useAgeAssuranceCopy} from '#/components/ageAssurance/useAgeAssuranceCopy' import * as Dialog from '#/components/Dialog' import {Divider} from '#/components/Divider' +import {resolveAllowGroupInvites} from '#/components/dms/util' import * as Toggle from '#/components/forms/Toggle' import {Bell_Stroke2_Corner0_Rounded as BellIcon} from '#/components/icons/Bell' import {Car_Stroke2_Corner2_Rounded as CarIcon} from '#/components/icons/Car' @@ -199,10 +200,7 @@ export function MessagesSettingsScreenInner({}: Props) { {allowGroupInvitesFromOptions.map(option => ( diff --git a/src/screens/Messages/components/ChatListItem.tsx b/src/screens/Messages/components/ChatListItem.tsx index 1f691290bf..b6d237f17d 100644 --- a/src/screens/Messages/components/ChatListItem.tsx +++ b/src/screens/Messages/components/ChatListItem.tsx @@ -483,7 +483,7 @@ function BaseChatItem({ to={`/messages/${convo.view.id}`} // In split view, this list stays mounted alongside the open convo, // so push would stack duplicate routes on repeated clicks. - action={isWithinSplitView ? 'navigate' : 'push'} + action={isWithinLeftPanel ? 'navigate' : 'push'} label={title} accessibilityHint={accessibilityHint} accessibilityActions={ diff --git a/src/state/queries/messages/actor-declaration.ts b/src/state/queries/messages/actor-declaration.ts index 53b493ab6a..f6cd2d51d5 100644 --- a/src/state/queries/messages/actor-declaration.ts +++ b/src/state/queries/messages/actor-declaration.ts @@ -7,6 +7,7 @@ import {useMutation, useQueryClient} from '@tanstack/react-query' import {logger} from '#/logger' import {useAgent, useSession} from '#/state/session' +import {resolveAllowGroupInvites} from '#/components/dms/util' import {RQKEY as PROFILE_RKEY} from '../profile' export function useUpdateActorDeclaration({ @@ -34,8 +35,12 @@ export function useUpdateActorDeclaration({ update.allowIncoming ?? current?.associated?.chat?.allowIncoming ?? 'following' - const allowGroupInvites = - update.allowGroupInvites ?? current?.associated?.chat?.allowGroupInvites + const allowGroupInvites = resolveAllowGroupInvites({ + allowIncoming, + allowGroupInvites: + update.allowGroupInvites ?? + current?.associated?.chat?.allowGroupInvites, + }) const result = await agent.com.atproto.repo.putRecord({ repo: currentAccount.did, collection: 'chat.bsky.actor.declaration', @@ -43,7 +48,7 @@ export function useUpdateActorDeclaration({ record: { $type: 'chat.bsky.actor.declaration', allowIncoming, - ...(allowGroupInvites && {allowGroupInvites}), + allowGroupInvites, }, }) return result @@ -54,14 +59,26 @@ export function useUpdateActorDeclaration({ PROFILE_RKEY(currentAccount?.did), (old?: AppBskyActorDefs.ProfileViewDetailed) => { if (!old) return old + const allowIncoming = + update.allowIncoming ?? + old.associated?.chat?.allowIncoming ?? + 'following' + // resolve the same concrete value the server will receive, so + // optimistic cache and persisted record stay aligned + const allowGroupInvites = resolveAllowGroupInvites({ + allowIncoming, + allowGroupInvites: + update.allowGroupInvites ?? + old.associated?.chat?.allowGroupInvites, + }) return { ...old, associated: { ...old.associated, chat: { - allowIncoming: 'following', ...old.associated?.chat, - ...update, + allowIncoming, + allowGroupInvites, }, }, } satisfies AppBskyActorDefs.ProfileViewDetailed