Align group invite settings with eligibility logic (#10748)
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) {
|
export function localDateString(date: Date) {
|
||||||
// can't use toISOString because it should be in local time
|
// can't use toISOString because it should be in local time
|
||||||
const mm = date.getMonth()
|
const mm = date.getMonth()
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {AgeRestrictedScreen} from '#/components/ageAssurance/AgeRestrictedScreen
|
|||||||
import {useAgeAssuranceCopy} from '#/components/ageAssurance/useAgeAssuranceCopy'
|
import {useAgeAssuranceCopy} from '#/components/ageAssurance/useAgeAssuranceCopy'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import {Divider} from '#/components/Divider'
|
import {Divider} from '#/components/Divider'
|
||||||
|
import {resolveAllowGroupInvites} from '#/components/dms/util'
|
||||||
import * as Toggle from '#/components/forms/Toggle'
|
import * as Toggle from '#/components/forms/Toggle'
|
||||||
import {Bell_Stroke2_Corner0_Rounded as BellIcon} from '#/components/icons/Bell'
|
import {Bell_Stroke2_Corner0_Rounded as BellIcon} from '#/components/icons/Bell'
|
||||||
import {Car_Stroke2_Corner2_Rounded as CarIcon} from '#/components/icons/Car'
|
import {Car_Stroke2_Corner2_Rounded as CarIcon} from '#/components/icons/Car'
|
||||||
@@ -199,10 +200,7 @@ export function MessagesSettingsScreenInner({}: Props) {
|
|||||||
<Toggle.Group
|
<Toggle.Group
|
||||||
label={l`Allow group chat invites from`}
|
label={l`Allow group chat invites from`}
|
||||||
type="radio"
|
type="radio"
|
||||||
values={[
|
values={[resolveAllowGroupInvites(profile?.associated?.chat)]}
|
||||||
(profile?.associated?.chat
|
|
||||||
?.allowGroupInvites as AllowIncoming) ?? 'following',
|
|
||||||
]}
|
|
||||||
onChange={onSelectGroupInvitesFrom}>
|
onChange={onSelectGroupInvitesFrom}>
|
||||||
<View>
|
<View>
|
||||||
{allowGroupInvitesFromOptions.map(option => (
|
{allowGroupInvitesFromOptions.map(option => (
|
||||||
|
|||||||
@@ -483,7 +483,7 @@ function BaseChatItem({
|
|||||||
to={`/messages/${convo.view.id}`}
|
to={`/messages/${convo.view.id}`}
|
||||||
// In split view, this list stays mounted alongside the open convo,
|
// In split view, this list stays mounted alongside the open convo,
|
||||||
// so push would stack duplicate routes on repeated clicks.
|
// so push would stack duplicate routes on repeated clicks.
|
||||||
action={isWithinSplitView ? 'navigate' : 'push'}
|
action={isWithinLeftPanel ? 'navigate' : 'push'}
|
||||||
label={title}
|
label={title}
|
||||||
accessibilityHint={accessibilityHint}
|
accessibilityHint={accessibilityHint}
|
||||||
accessibilityActions={
|
accessibilityActions={
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {useMutation, useQueryClient} from '@tanstack/react-query'
|
|||||||
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
|
import {resolveAllowGroupInvites} from '#/components/dms/util'
|
||||||
import {RQKEY as PROFILE_RKEY} from '../profile'
|
import {RQKEY as PROFILE_RKEY} from '../profile'
|
||||||
|
|
||||||
export function useUpdateActorDeclaration({
|
export function useUpdateActorDeclaration({
|
||||||
@@ -34,8 +35,12 @@ export function useUpdateActorDeclaration({
|
|||||||
update.allowIncoming ??
|
update.allowIncoming ??
|
||||||
current?.associated?.chat?.allowIncoming ??
|
current?.associated?.chat?.allowIncoming ??
|
||||||
'following'
|
'following'
|
||||||
const allowGroupInvites =
|
const allowGroupInvites = resolveAllowGroupInvites({
|
||||||
update.allowGroupInvites ?? current?.associated?.chat?.allowGroupInvites
|
allowIncoming,
|
||||||
|
allowGroupInvites:
|
||||||
|
update.allowGroupInvites ??
|
||||||
|
current?.associated?.chat?.allowGroupInvites,
|
||||||
|
})
|
||||||
const result = await agent.com.atproto.repo.putRecord({
|
const result = await agent.com.atproto.repo.putRecord({
|
||||||
repo: currentAccount.did,
|
repo: currentAccount.did,
|
||||||
collection: 'chat.bsky.actor.declaration',
|
collection: 'chat.bsky.actor.declaration',
|
||||||
@@ -43,7 +48,7 @@ export function useUpdateActorDeclaration({
|
|||||||
record: {
|
record: {
|
||||||
$type: 'chat.bsky.actor.declaration',
|
$type: 'chat.bsky.actor.declaration',
|
||||||
allowIncoming,
|
allowIncoming,
|
||||||
...(allowGroupInvites && {allowGroupInvites}),
|
allowGroupInvites,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
@@ -54,14 +59,26 @@ export function useUpdateActorDeclaration({
|
|||||||
PROFILE_RKEY(currentAccount?.did),
|
PROFILE_RKEY(currentAccount?.did),
|
||||||
(old?: AppBskyActorDefs.ProfileViewDetailed) => {
|
(old?: AppBskyActorDefs.ProfileViewDetailed) => {
|
||||||
if (!old) return old
|
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 {
|
return {
|
||||||
...old,
|
...old,
|
||||||
associated: {
|
associated: {
|
||||||
...old.associated,
|
...old.associated,
|
||||||
chat: {
|
chat: {
|
||||||
allowIncoming: 'following',
|
|
||||||
...old.associated?.chat,
|
...old.associated?.chat,
|
||||||
...update,
|
allowIncoming,
|
||||||
|
allowGroupInvites,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} satisfies AppBskyActorDefs.ProfileViewDetailed
|
} satisfies AppBskyActorDefs.ProfileViewDetailed
|
||||||
|
|||||||
Reference in New Issue
Block a user