extract resolveAllowGroupInvites helper, fix optimistic cache
Address review feedback: dedupe the allowGroupInvites fallback chain into a single helper next to canBeAddedToGroup, used by the settings display, the save path, and onMutate. The optimistic cache now stores the same resolved value the server receives, so cache and persisted record stay aligned before the next profile refetch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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,15 +200,7 @@ export function MessagesSettingsScreenInner({}: Props) {
|
||||
<Toggle.Group
|
||||
label={l`Allow group chat invites from`}
|
||||
type="radio"
|
||||
values={[
|
||||
(profile?.associated?.chat
|
||||
?.allowGroupInvites as AllowIncoming) ??
|
||||
// when unset, group invites follow the general DM
|
||||
// preference (see canBeAddedToGroup)
|
||||
(profile?.associated?.chat
|
||||
?.allowIncoming as AllowIncoming) ??
|
||||
'following',
|
||||
]}
|
||||
values={[resolveAllowGroupInvites(profile?.associated?.chat)]}
|
||||
onChange={onSelectGroupInvitesFrom}>
|
||||
<View>
|
||||
{allowGroupInvitesFromOptions.map(option => (
|
||||
|
||||
@@ -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,12 +35,12 @@ export function useUpdateActorDeclaration({
|
||||
update.allowIncoming ??
|
||||
current?.associated?.chat?.allowIncoming ??
|
||||
'following'
|
||||
const allowGroupInvites =
|
||||
update.allowGroupInvites ??
|
||||
current?.associated?.chat?.allowGroupInvites ??
|
||||
// when unset, group invites follow the general DM preference
|
||||
// (see canBeAddedToGroup), so mirror that when persisting
|
||||
allowIncoming
|
||||
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',
|
||||
@@ -58,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
|
||||
|
||||
Reference in New Issue
Block a user