Update chat settings (#10449)
This commit is contained in:
@@ -572,4 +572,29 @@ export function BaseRadio({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function RadioWithLabel({
|
||||||
|
label,
|
||||||
|
selected,
|
||||||
|
}: {
|
||||||
|
label: string
|
||||||
|
selected: boolean
|
||||||
|
}) {
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}>
|
||||||
|
<Radio />
|
||||||
|
<LabelText
|
||||||
|
style={[
|
||||||
|
a.font_medium,
|
||||||
|
a.flex_1,
|
||||||
|
a.leading_tight,
|
||||||
|
selected ? t.atoms.text : t.atoms.text_contrast_high,
|
||||||
|
]}>
|
||||||
|
{label}
|
||||||
|
</LabelText>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export const Platform = IS_NATIVE ? Switch : Checkbox
|
export const Platform = IS_NATIVE ? Switch : Checkbox
|
||||||
|
|||||||
@@ -1,23 +1,27 @@
|
|||||||
import {useCallback} from 'react'
|
import {useCallback, useState} from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {Trans} from '@lingui/react/macro'
|
|
||||||
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
|
|
||||||
|
import {DM_SERVICE_HEADERS} from '#/lib/constants'
|
||||||
|
import {saveBytesToDisk} from '#/lib/media/manip'
|
||||||
import {type CommonNavigatorParams} from '#/lib/routes/types'
|
import {type CommonNavigatorParams} from '#/lib/routes/types'
|
||||||
|
import {logger} from '#/logger'
|
||||||
import {useUpdateActorDeclaration} from '#/state/queries/messages/actor-declaration'
|
import {useUpdateActorDeclaration} from '#/state/queries/messages/actor-declaration'
|
||||||
import {useProfileQuery} from '#/state/queries/profile'
|
import {useProfileQuery} from '#/state/queries/profile'
|
||||||
import {useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {Admonition} from '#/components/Admonition'
|
|
||||||
import {AgeRestrictedScreen} from '#/components/ageAssurance/AgeRestrictedScreen'
|
import {AgeRestrictedScreen} from '#/components/ageAssurance/AgeRestrictedScreen'
|
||||||
import {useAgeAssuranceCopy} from '#/components/ageAssurance/useAgeAssuranceCopy'
|
import {useAgeAssuranceCopy} from '#/components/ageAssurance/useAgeAssuranceCopy'
|
||||||
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
import {Divider} from '#/components/Divider'
|
import {Divider} from '#/components/Divider'
|
||||||
import * as Toggle from '#/components/forms/Toggle'
|
import * as Toggle from '#/components/forms/Toggle'
|
||||||
|
import {Download_Stroke2_Corner0_Rounded as DownloadIcon} from '#/components/icons/Download'
|
||||||
import * as Layout from '#/components/Layout'
|
import * as Layout from '#/components/Layout'
|
||||||
|
import {Loader} from '#/components/Loader'
|
||||||
import * as Toast from '#/components/Toast'
|
import * as Toast from '#/components/Toast'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
import {IS_NATIVE} from '#/env'
|
import {IS_NATIVE} from '#/env'
|
||||||
import {useBackgroundNotificationPreferences} from '../../../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
|
import {useBackgroundNotificationPreferences} from '../../../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
|
||||||
|
|
||||||
@@ -26,12 +30,12 @@ type AllowIncoming = 'all' | 'none' | 'following'
|
|||||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'MessagesSettings'>
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'MessagesSettings'>
|
||||||
|
|
||||||
export function MessagesSettingsScreen(props: Props) {
|
export function MessagesSettingsScreen(props: Props) {
|
||||||
const {_} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const aaCopy = useAgeAssuranceCopy()
|
const aaCopy = useAgeAssuranceCopy()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AgeRestrictedScreen
|
<AgeRestrictedScreen
|
||||||
screenTitle={_(msg`Chat settings`)}
|
screenTitle={l`Chat settings`}
|
||||||
infoText={aaCopy.chatsInfoText}>
|
infoText={aaCopy.chatsInfoText}>
|
||||||
<MessagesSettingsScreenInner {...props} />
|
<MessagesSettingsScreenInner {...props} />
|
||||||
</AgeRestrictedScreen>
|
</AgeRestrictedScreen>
|
||||||
@@ -39,16 +43,84 @@ export function MessagesSettingsScreen(props: Props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function MessagesSettingsScreenInner({}: Props) {
|
export function MessagesSettingsScreenInner({}: Props) {
|
||||||
const {_} = useLingui()
|
const t = useTheme()
|
||||||
|
const {t: l} = useLingui()
|
||||||
|
const ax = useAnalytics()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
|
const agent = useAgent()
|
||||||
const {data: profile} = useProfileQuery({
|
const {data: profile} = useProfileQuery({
|
||||||
did: currentAccount!.did,
|
did: currentAccount!.did,
|
||||||
})
|
})
|
||||||
const {preferences, setPref} = useBackgroundNotificationPreferences()
|
const {preferences, setPref} = useBackgroundNotificationPreferences()
|
||||||
|
|
||||||
|
const isGroupChatEnabled = ax.features.enabled(ax.features.GroupChatsEnable)
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
|
const allowMessagesFromOptions: {name: AllowIncoming; label: string}[] = [
|
||||||
|
{
|
||||||
|
name: 'all',
|
||||||
|
label: l({context: 'allow messages from', message: `Everyone`}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'following',
|
||||||
|
label: l({context: 'allow messages from', message: `Users I follow`}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'none',
|
||||||
|
label: l({context: 'allow messages from', message: `No one`}),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const allowGroupInvitesFromOptions: {name: AllowIncoming; label: string}[] = [
|
||||||
|
{
|
||||||
|
name: 'all',
|
||||||
|
label: l({context: 'allow group chat invites from', message: `Everyone`}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'following',
|
||||||
|
label: l({
|
||||||
|
context: 'allow group chat invites from',
|
||||||
|
message: `Users I follow`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'none',
|
||||||
|
label: l({context: 'allow group chat invites from', message: `No one`}),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const onDownloadChatData = async () => {
|
||||||
|
if (!agent.session) return
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
|
const res = await agent.sessionManager.fetchHandler(
|
||||||
|
'/xrpc/chat.bsky.actor.exportAccountData',
|
||||||
|
{headers: DM_SERVICE_HEADERS},
|
||||||
|
)
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(`HTTP ${res.status}`)
|
||||||
|
}
|
||||||
|
const data = new Uint8Array(await res.arrayBuffer())
|
||||||
|
const saveRes = await saveBytesToDisk(
|
||||||
|
'chat.jsonl',
|
||||||
|
data,
|
||||||
|
res.headers.get('content-type') || 'application/jsonl',
|
||||||
|
)
|
||||||
|
if (saveRes) {
|
||||||
|
Toast.show(l`File saved successfully!`)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
logger.error('Error occurred while downloading chat data', {message: e})
|
||||||
|
Toast.show(l`Error occurred while saving file`, {type: 'error'})
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const {mutate: updateDeclaration} = useUpdateActorDeclaration({
|
const {mutate: updateDeclaration} = useUpdateActorDeclaration({
|
||||||
onError: () => {
|
onError: () => {
|
||||||
Toast.show(_(msg`Failed to update settings`), {
|
Toast.show(l`Failed to update settings`, {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -58,16 +130,23 @@ export function MessagesSettingsScreenInner({}: Props) {
|
|||||||
(keys: string[]) => {
|
(keys: string[]) => {
|
||||||
const key = keys[0]
|
const key = keys[0]
|
||||||
if (!key) return
|
if (!key) return
|
||||||
updateDeclaration(key as AllowIncoming)
|
updateDeclaration({allowIncoming: key as AllowIncoming})
|
||||||
|
},
|
||||||
|
[updateDeclaration],
|
||||||
|
)
|
||||||
|
|
||||||
|
const onSelectGroupInvitesFrom = useCallback(
|
||||||
|
(keys: string[]) => {
|
||||||
|
const key = keys[0]
|
||||||
|
if (!key) return
|
||||||
|
updateDeclaration({allowGroupInvites: key as AllowIncoming})
|
||||||
},
|
},
|
||||||
[updateDeclaration],
|
[updateDeclaration],
|
||||||
)
|
)
|
||||||
|
|
||||||
const onSelectSoundSetting = useCallback(
|
const onSelectSoundSetting = useCallback(
|
||||||
(keys: string[]) => {
|
(selected: boolean) => {
|
||||||
const key = keys[0]
|
setPref('playSoundChat', selected)
|
||||||
if (!key) return
|
|
||||||
setPref('playSoundChat', key === 'enabled')
|
|
||||||
},
|
},
|
||||||
[setPref],
|
[setPref],
|
||||||
)
|
)
|
||||||
@@ -84,90 +163,146 @@ export function MessagesSettingsScreenInner({}: Props) {
|
|||||||
<Layout.Header.Slot />
|
<Layout.Header.Slot />
|
||||||
</Layout.Header.Outer>
|
</Layout.Header.Outer>
|
||||||
<Layout.Content>
|
<Layout.Content>
|
||||||
<View style={[a.p_lg, a.gap_md]}>
|
<View style={[a.py_xl, a.gap_md]}>
|
||||||
<Text style={[a.text_lg, a.font_semi_bold]}>
|
<View style={[a.px_xl]}>
|
||||||
<Trans>Allow new messages from</Trans>
|
<Text style={[a.pb_xs, a.text_md, a.font_semi_bold, t.atoms.text]}>
|
||||||
</Text>
|
<Trans>Allow direct messages from</Trans>
|
||||||
<Toggle.Group
|
</Text>
|
||||||
label={_(msg`Allow new messages from`)}
|
<Text
|
||||||
type="radio"
|
style={[
|
||||||
values={[
|
a.pb_md,
|
||||||
(profile?.associated?.chat?.allowIncoming as AllowIncoming) ??
|
a.text_sm,
|
||||||
'following',
|
a.leading_snug,
|
||||||
]}
|
t.atoms.text_contrast_high,
|
||||||
onChange={onSelectMessagesFrom}>
|
]}>
|
||||||
<View>
|
<Trans>
|
||||||
<Toggle.Item
|
You can continue ongoing conversations regardless of which
|
||||||
name="all"
|
setting you choose.
|
||||||
label={_(msg`Everyone`)}
|
</Trans>
|
||||||
style={[a.justify_between, a.py_sm]}>
|
</Text>
|
||||||
<Toggle.LabelText>
|
<Toggle.Group
|
||||||
<Trans>Everyone</Trans>
|
label={l`Allow direct messages from`}
|
||||||
</Toggle.LabelText>
|
type="radio"
|
||||||
<Toggle.Radio />
|
values={[
|
||||||
</Toggle.Item>
|
(profile?.associated?.chat?.allowIncoming as AllowIncoming) ??
|
||||||
<Toggle.Item
|
'following',
|
||||||
name="following"
|
]}
|
||||||
label={_(msg`Users I follow`)}
|
onChange={onSelectMessagesFrom}>
|
||||||
style={[a.justify_between, a.py_sm]}>
|
<View>
|
||||||
<Toggle.LabelText>
|
{allowMessagesFromOptions.map(option => (
|
||||||
<Trans>Users I follow</Trans>
|
<Toggle.Item
|
||||||
</Toggle.LabelText>
|
key={option.name}
|
||||||
<Toggle.Radio />
|
highlightRow
|
||||||
</Toggle.Item>
|
name={option.name}
|
||||||
<Toggle.Item
|
label={option.label}>
|
||||||
name="none"
|
{({selected}) => (
|
||||||
label={_(
|
<Toggle.RadioWithLabel
|
||||||
msg({context: 'allow messages from', message: `No one`}),
|
label={option.label}
|
||||||
)}
|
selected={selected}
|
||||||
style={[a.justify_between, a.py_sm]}>
|
/>
|
||||||
<Toggle.LabelText>
|
)}
|
||||||
<Trans context="allow messages from">No one</Trans>
|
</Toggle.Item>
|
||||||
</Toggle.LabelText>
|
))}
|
||||||
<Toggle.Radio />
|
</View>
|
||||||
</Toggle.Item>
|
</Toggle.Group>
|
||||||
</View>
|
</View>
|
||||||
</Toggle.Group>
|
<Divider style={{marginVertical: 10}} />
|
||||||
<Admonition type="tip">
|
{isGroupChatEnabled ? (
|
||||||
<Trans>
|
<>
|
||||||
You can continue ongoing conversations regardless of which setting
|
<View style={[a.px_xl]}>
|
||||||
you choose.
|
<Text
|
||||||
</Trans>
|
style={[a.pb_xs, a.text_md, a.font_semi_bold, t.atoms.text]}>
|
||||||
</Admonition>
|
<Trans>Allow group chat invites from</Trans>
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.pb_md,
|
||||||
|
a.text_sm,
|
||||||
|
a.leading_snug,
|
||||||
|
t.atoms.text_contrast_high,
|
||||||
|
]}>
|
||||||
|
<Trans>
|
||||||
|
You can continue ongoing conversations regardless of which
|
||||||
|
setting you choose.
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
<Toggle.Group
|
||||||
|
label={l`Allow group chat invites from`}
|
||||||
|
type="radio"
|
||||||
|
values={[
|
||||||
|
(profile?.associated?.chat
|
||||||
|
?.allowGroupInvites as AllowIncoming) ?? 'following',
|
||||||
|
]}
|
||||||
|
onChange={onSelectGroupInvitesFrom}>
|
||||||
|
<View>
|
||||||
|
{allowGroupInvitesFromOptions.map(option => (
|
||||||
|
<Toggle.Item
|
||||||
|
key={option.name}
|
||||||
|
highlightRow
|
||||||
|
name={option.name}
|
||||||
|
label={option.label}>
|
||||||
|
{({selected}) => (
|
||||||
|
<Toggle.RadioWithLabel
|
||||||
|
label={option.label}
|
||||||
|
selected={selected}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Toggle.Item>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
</Toggle.Group>
|
||||||
|
</View>
|
||||||
|
<Divider style={{marginVertical: 10}} />
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
{IS_NATIVE && (
|
{IS_NATIVE && (
|
||||||
<>
|
<>
|
||||||
<Divider style={a.my_md} />
|
<View style={[a.px_xl]}>
|
||||||
<Text style={[a.text_lg, a.font_semi_bold]}>
|
<Toggle.Item
|
||||||
<Trans>Notification Sounds</Trans>
|
label={l`Notification sounds`}
|
||||||
</Text>
|
name="playSoundChat"
|
||||||
<Toggle.Group
|
value={preferences.playSoundChat}
|
||||||
label={_(msg`Notification sounds`)}
|
style={[a.flex_row, a.align_center, a.justify_between]}
|
||||||
type="radio"
|
onChange={onSelectSoundSetting}>
|
||||||
values={[preferences.playSoundChat ? 'enabled' : 'disabled']}
|
<Text style={[a.text_md, a.font_semi_bold, t.atoms.text]}>
|
||||||
onChange={onSelectSoundSetting}>
|
<Trans>Notification sounds</Trans>
|
||||||
<View>
|
</Text>
|
||||||
<Toggle.Item
|
<Toggle.Switch />
|
||||||
name="enabled"
|
</Toggle.Item>
|
||||||
label={_(msg`Enabled`)}
|
</View>
|
||||||
style={[a.justify_between, a.py_sm]}>
|
<Divider style={{marginVertical: 10}} />
|
||||||
<Toggle.LabelText>
|
|
||||||
<Trans>Enabled</Trans>
|
|
||||||
</Toggle.LabelText>
|
|
||||||
<Toggle.Radio />
|
|
||||||
</Toggle.Item>
|
|
||||||
<Toggle.Item
|
|
||||||
name="disabled"
|
|
||||||
label={_(msg`Disabled`)}
|
|
||||||
style={[a.justify_between, a.py_sm]}>
|
|
||||||
<Toggle.LabelText>
|
|
||||||
<Trans>Disabled</Trans>
|
|
||||||
</Toggle.LabelText>
|
|
||||||
<Toggle.Radio />
|
|
||||||
</Toggle.Item>
|
|
||||||
</View>
|
|
||||||
</Toggle.Group>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
<View style={[a.px_xl]}>
|
||||||
|
<Text style={[a.pb_xs, a.text_md, a.font_semi_bold, t.atoms.text]}>
|
||||||
|
<Trans>Download chat data</Trans>
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.pb_md,
|
||||||
|
a.text_sm,
|
||||||
|
a.leading_snug,
|
||||||
|
t.atoms.text_contrast_high,
|
||||||
|
]}>
|
||||||
|
<Trans>
|
||||||
|
This file only includes chat messages that you have sent and
|
||||||
|
does not include chat messages that you have received.
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
<Button
|
||||||
|
disabled={loading}
|
||||||
|
color="primary"
|
||||||
|
size="small"
|
||||||
|
label={l`Download .jsonl file`}
|
||||||
|
style={[a.self_start]}
|
||||||
|
onPress={() => void onDownloadChatData()}>
|
||||||
|
<ButtonIcon icon={loading ? Loader : DownloadIcon} />
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Download .jsonl file</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
<Divider style={{marginVertical: 10}} />
|
||||||
</View>
|
</View>
|
||||||
</Layout.Content>
|
</Layout.Content>
|
||||||
</Layout.Screen>
|
</Layout.Screen>
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ export function InviteLinkDialog({
|
|||||||
name={option.name}
|
name={option.name}
|
||||||
style={[a.flex_1]}>
|
style={[a.flex_1]}>
|
||||||
{({selected}) => (
|
{({selected}) => (
|
||||||
<TargetOption
|
<Toggle.RadioWithLabel
|
||||||
label={isOwner ? option.owner : option.member}
|
label={isOwner ? option.owner : option.member}
|
||||||
selected={selected}
|
selected={selected}
|
||||||
/>
|
/>
|
||||||
@@ -454,22 +454,3 @@ export function InviteLinkDialog({
|
|||||||
</Dialog.Outer>
|
</Dialog.Outer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function TargetOption({label, selected}: {label: string; selected: boolean}) {
|
|
||||||
const t = useTheme()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={[a.flex_1, a.flex_row, a.align_center, a.gap_sm]}>
|
|
||||||
<Toggle.Radio />
|
|
||||||
<Toggle.LabelText
|
|
||||||
style={[
|
|
||||||
a.font_normal,
|
|
||||||
a.flex_1,
|
|
||||||
a.leading_tight,
|
|
||||||
selected ? t.atoms.text : t.atoms.text_contrast_high,
|
|
||||||
]}>
|
|
||||||
{label}
|
|
||||||
</Toggle.LabelText>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -21,8 +21,21 @@ export function useUpdateActorDeclaration({
|
|||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async (allowIncoming: 'all' | 'none' | 'following') => {
|
mutationFn: async (update: {
|
||||||
|
allowIncoming?: 'all' | 'none' | 'following'
|
||||||
|
allowGroupInvites?: 'all' | 'none' | 'following'
|
||||||
|
}) => {
|
||||||
if (!currentAccount) throw new Error('Not signed in')
|
if (!currentAccount) throw new Error('Not signed in')
|
||||||
|
const current =
|
||||||
|
queryClient.getQueryData<AppBskyActorDefs.ProfileViewDetailed>(
|
||||||
|
PROFILE_RKEY(currentAccount.did),
|
||||||
|
)
|
||||||
|
const allowIncoming =
|
||||||
|
update.allowIncoming ??
|
||||||
|
current?.associated?.chat?.allowIncoming ??
|
||||||
|
'following'
|
||||||
|
const 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',
|
||||||
@@ -30,11 +43,12 @@ export function useUpdateActorDeclaration({
|
|||||||
record: {
|
record: {
|
||||||
$type: 'chat.bsky.actor.declaration',
|
$type: 'chat.bsky.actor.declaration',
|
||||||
allowIncoming,
|
allowIncoming,
|
||||||
|
...(allowGroupInvites && {allowGroupInvites}),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
onMutate: allowIncoming => {
|
onMutate: update => {
|
||||||
if (!currentAccount) return
|
if (!currentAccount) return
|
||||||
queryClient.setQueryData(
|
queryClient.setQueryData(
|
||||||
PROFILE_RKEY(currentAccount?.did),
|
PROFILE_RKEY(currentAccount?.did),
|
||||||
@@ -45,7 +59,9 @@ export function useUpdateActorDeclaration({
|
|||||||
associated: {
|
associated: {
|
||||||
...old.associated,
|
...old.associated,
|
||||||
chat: {
|
chat: {
|
||||||
allowIncoming,
|
allowIncoming: 'following',
|
||||||
|
...old.associated?.chat,
|
||||||
|
...update,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} satisfies AppBskyActorDefs.ProfileViewDetailed
|
} satisfies AppBskyActorDefs.ProfileViewDetailed
|
||||||
|
|||||||
Reference in New Issue
Block a user