289 lines
9.8 KiB
TypeScript
289 lines
9.8 KiB
TypeScript
import {useCallback} from 'react'
|
|
import {View} from 'react-native'
|
|
import {Trans, useLingui} from '@lingui/react/macro'
|
|
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
|
|
|
|
import {type CommonNavigatorParams} from '#/lib/routes/types'
|
|
import {useUpdateActorDeclaration} from '#/state/queries/messages/actor-declaration'
|
|
import {useProfileQuery} from '#/state/queries/profile'
|
|
import {useSession} from '#/state/session'
|
|
import {ExportCarDialog} from '#/screens/Settings/components/ExportCarDialog'
|
|
import {atoms as a, useTheme} from '#/alf'
|
|
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'
|
|
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron'
|
|
import * as Layout from '#/components/Layout'
|
|
import * as Toast from '#/components/Toast'
|
|
import {Text} from '#/components/Typography'
|
|
import {useAgeAssurance} from '#/ageAssurance'
|
|
import {useAnalytics} from '#/analytics'
|
|
import {IS_NATIVE} from '#/env'
|
|
import {useBackgroundNotificationPreferences} from '../../../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
|
|
|
|
type AllowIncoming = 'all' | 'none' | 'following'
|
|
|
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'MessagesSettings'>
|
|
|
|
export function MessagesSettingsScreen(props: Props) {
|
|
const {t: l} = useLingui()
|
|
const aaCopy = useAgeAssuranceCopy()
|
|
|
|
return (
|
|
<AgeRestrictedScreen
|
|
screenTitle={l`Chat settings`}
|
|
infoText={aaCopy.chatsInfoText}>
|
|
<MessagesSettingsScreenInner {...props} />
|
|
</AgeRestrictedScreen>
|
|
)
|
|
}
|
|
|
|
export function MessagesSettingsScreenInner({}: Props) {
|
|
const t = useTheme()
|
|
const {t: l} = useLingui()
|
|
const ax = useAnalytics()
|
|
const aa = useAgeAssurance()
|
|
const {currentAccount} = useSession()
|
|
const {data: profile} = useProfileQuery({
|
|
did: currentAccount!.did,
|
|
})
|
|
const {preferences, setPref} = useBackgroundNotificationPreferences()
|
|
|
|
const exportCarControl = Dialog.useDialogControl()
|
|
|
|
const isGroupChatEnabled = !ax.features.enabled(ax.features.GroupChatsDisable)
|
|
const groupInvitesLocked = aa.flags.groupChatDisabled
|
|
|
|
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 {mutate: updateDeclaration} = useUpdateActorDeclaration({
|
|
onError: () => {
|
|
Toast.show(l`Failed to update settings`, {
|
|
type: 'error',
|
|
})
|
|
},
|
|
})
|
|
|
|
const onSelectMessagesFrom = useCallback(
|
|
(keys: string[]) => {
|
|
const key = keys[0]
|
|
if (!key) return
|
|
updateDeclaration({allowIncoming: key as AllowIncoming})
|
|
},
|
|
[updateDeclaration],
|
|
)
|
|
|
|
const onSelectGroupInvitesFrom = useCallback(
|
|
(keys: string[]) => {
|
|
const key = keys[0]
|
|
if (!key) return
|
|
updateDeclaration({allowGroupInvites: key as AllowIncoming})
|
|
},
|
|
[updateDeclaration],
|
|
)
|
|
|
|
const onSelectSoundSetting = useCallback(
|
|
(selected: boolean) => {
|
|
setPref('playSoundChat', selected)
|
|
},
|
|
[setPref],
|
|
)
|
|
|
|
return (
|
|
<Layout.Screen testID="messagesSettingsScreen">
|
|
<Layout.Header.Outer>
|
|
<Layout.Header.BackButton />
|
|
<Layout.Header.Content>
|
|
<Layout.Header.TitleText>
|
|
<Trans>Chat Settings</Trans>
|
|
</Layout.Header.TitleText>
|
|
</Layout.Header.Content>
|
|
<Layout.Header.Slot />
|
|
</Layout.Header.Outer>
|
|
<Layout.Content>
|
|
<View style={[a.py_xl, a.gap_md]}>
|
|
<View style={[a.px_xl]}>
|
|
<Text style={[a.pb_xs, a.text_md, a.font_semi_bold, t.atoms.text]}>
|
|
<Trans>Allow direct messages 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 direct messages from`}
|
|
type="radio"
|
|
values={[
|
|
(profile?.associated?.chat?.allowIncoming as AllowIncoming) ??
|
|
'following',
|
|
]}
|
|
onChange={onSelectMessagesFrom}>
|
|
<View>
|
|
{allowMessagesFromOptions.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}} />
|
|
{isGroupChatEnabled ? (
|
|
<>
|
|
<View style={[a.px_xl]}>
|
|
<Text
|
|
style={[a.pb_xs, a.text_md, a.font_semi_bold, t.atoms.text]}>
|
|
<Trans>Allow group chat invites from</Trans>
|
|
</Text>
|
|
<Text
|
|
style={[
|
|
a.pb_md,
|
|
a.text_sm,
|
|
a.leading_snug,
|
|
t.atoms.text_contrast_high,
|
|
]}>
|
|
{groupInvitesLocked ? (
|
|
<Trans>
|
|
Group chats are only available to users 18 and over.
|
|
</Trans>
|
|
) : (
|
|
<Trans>
|
|
You can continue ongoing conversations regardless of which
|
|
setting you choose.
|
|
</Trans>
|
|
)}
|
|
</Text>
|
|
<Toggle.Group
|
|
disabled={groupInvitesLocked}
|
|
label={l`Allow group chat invites from`}
|
|
type="radio"
|
|
values={[
|
|
groupInvitesLocked
|
|
? 'none'
|
|
: resolveAllowGroupInvites(profile?.associated?.chat),
|
|
]}
|
|
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 && (
|
|
<>
|
|
<View style={[a.px_xl]}>
|
|
<Toggle.Item
|
|
label={l`Notification sounds`}
|
|
name="playSoundChat"
|
|
value={preferences.playSoundChat}
|
|
style={[a.flex_row, a.align_center, a.justify_between]}
|
|
onChange={onSelectSoundSetting}>
|
|
<BellIcon style={[a.mr_2xs, t.atoms.text]} size="lg" />
|
|
<Text
|
|
style={[
|
|
a.flex_1,
|
|
a.text_md,
|
|
a.font_semi_bold,
|
|
t.atoms.text,
|
|
]}>
|
|
<Trans>Notification sounds</Trans>
|
|
</Text>
|
|
<Toggle.Switch />
|
|
</Toggle.Item>
|
|
</View>
|
|
<Divider style={{marginVertical: 10}} />
|
|
</>
|
|
)}
|
|
<View style={[a.px_xl]}>
|
|
<Toggle.Item
|
|
label={l`Export my chat data`}
|
|
name="playSoundChat"
|
|
value={preferences.playSoundChat}
|
|
style={[a.flex_row, a.align_center, a.justify_between]}
|
|
onChange={() => {
|
|
exportCarControl.open()
|
|
}}>
|
|
<CarIcon style={[a.mr_2xs, t.atoms.text]} size="lg" />
|
|
<Text
|
|
style={[a.flex_1, a.text_md, a.font_semi_bold, t.atoms.text]}>
|
|
<Trans>Export my chat data</Trans>
|
|
</Text>
|
|
<ChevronRightIcon style={[a.ml_2xs, t.atoms.text]} size="lg" />
|
|
</Toggle.Item>
|
|
</View>
|
|
<Divider style={{marginVertical: 10}} />
|
|
</View>
|
|
</Layout.Content>
|
|
<ExportCarDialog control={exportCarControl} />
|
|
</Layout.Screen>
|
|
)
|
|
}
|