Make settings account buttons a little nicer (#4980)
* Replace account dropdown with Menu * Replace card row and add interaction state * Remove testID copy pasta * Sanitize handle * Remove hover from rowzio/stable
parent
990bf306c5
commit
5ec8761b29
|
@ -1,53 +1,59 @@
|
|||
import React from 'react'
|
||||
import {Pressable} from 'react-native'
|
||||
import {
|
||||
FontAwesomeIcon,
|
||||
FontAwesomeIconStyle,
|
||||
} from '@fortawesome/react-native-fontawesome'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
import {SessionAccount, useSessionApi} from '#/state/session'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {s} from 'lib/styles'
|
||||
import {HITSLOP_10} from 'lib/constants'
|
||||
import {Button, ButtonIcon} from '#/components/Button'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {DotGrid_Stroke2_Corner0_Rounded as Ellipsis} from '#/components/icons/DotGrid'
|
||||
import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
|
||||
import * as Menu from '#/components/Menu'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
import * as Toast from '../../com/util/Toast'
|
||||
import {DropdownItem, NativeDropdown} from './forms/NativeDropdown'
|
||||
|
||||
export function AccountDropdownBtn({account}: {account: SessionAccount}) {
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const {removeAccount} = useSessionApi()
|
||||
const removePromptControl = useDialogControl()
|
||||
const {_} = useLingui()
|
||||
|
||||
const items: DropdownItem[] = [
|
||||
{
|
||||
label: _(msg`Remove account`),
|
||||
onPress: removePromptControl.open,
|
||||
icon: {
|
||||
ios: {
|
||||
name: 'trash',
|
||||
},
|
||||
android: 'ic_delete',
|
||||
web: ['far', 'trash-can'],
|
||||
},
|
||||
},
|
||||
]
|
||||
return (
|
||||
<>
|
||||
<Pressable accessibilityRole="button" style={s.pl10}>
|
||||
<NativeDropdown
|
||||
testID="accountSettingsDropdownBtn"
|
||||
items={items}
|
||||
accessibilityLabel={_(msg`Account options`)}
|
||||
accessibilityHint="">
|
||||
<FontAwesomeIcon
|
||||
icon="ellipsis-h"
|
||||
style={pal.textLight as FontAwesomeIconStyle}
|
||||
/>
|
||||
</NativeDropdown>
|
||||
</Pressable>
|
||||
<Menu.Root>
|
||||
<Menu.Trigger label={_(`Account options`)}>
|
||||
{({props}) => {
|
||||
return (
|
||||
<Button
|
||||
{...props}
|
||||
testID="accountSettingsDropdownBtn"
|
||||
label={_(`Account options`)}
|
||||
hitSlop={HITSLOP_10}
|
||||
size="xsmall"
|
||||
shape="round"
|
||||
color="secondary"
|
||||
variant="ghost">
|
||||
<ButtonIcon icon={Ellipsis} size="sm" />
|
||||
</Button>
|
||||
)
|
||||
}}
|
||||
</Menu.Trigger>
|
||||
|
||||
<Menu.Outer style={{minWidth: 170}}>
|
||||
<Menu.Group>
|
||||
<Menu.Item
|
||||
label={_(msg`Remove account`)}
|
||||
onPress={() => {
|
||||
removePromptControl.open()
|
||||
}}>
|
||||
<Menu.ItemText>
|
||||
<Trans>Remove account</Trans>
|
||||
</Menu.ItemText>
|
||||
<Menu.ItemIcon icon={Trash} />
|
||||
</Menu.Item>
|
||||
</Menu.Group>
|
||||
</Menu.Outer>
|
||||
</Menu.Root>
|
||||
|
||||
<Prompt.Basic
|
||||
control={removePromptControl}
|
||||
title={_(msg`Remove from quick access?`)}
|
||||
|
|
|
@ -18,6 +18,7 @@ import {useLingui} from '@lingui/react'
|
|||
import {useFocusEffect, useNavigation} from '@react-navigation/native'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||
import {isNative} from '#/platform/detection'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {clearStorage} from '#/state/persisted'
|
||||
|
@ -55,8 +56,11 @@ import {UserAvatar} from 'view/com/util/UserAvatar'
|
|||
import {ScrollView} from 'view/com/util/Views'
|
||||
import {DeactivateAccountDialog} from '#/screens/Settings/components/DeactivateAccountDialog'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button, ButtonContext} from '#/components/Button'
|
||||
import {useDialogControl} from '#/components/Dialog'
|
||||
import {BirthDateSettingsDialog} from '#/components/dialogs/BirthDateSettings'
|
||||
import {Link as NewLink} from '#/components/Link'
|
||||
import {Text as NewText} from '#/components/Typography'
|
||||
import {Email2FAToggle} from './Email2FAToggle'
|
||||
import {ExportCarDialog} from './ExportCarDialog'
|
||||
|
||||
|
@ -72,62 +76,69 @@ function SettingsAccountCard({
|
|||
logContext: 'Settings',
|
||||
) => void
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const t = useTheme()
|
||||
const {currentAccount} = useSession()
|
||||
const {data: profile} = useProfileQuery({did: account.did})
|
||||
const isCurrentAccount = account.did === currentAccount?.did
|
||||
|
||||
const contents = (
|
||||
const contents = (ctx: ButtonContext) => (
|
||||
<View
|
||||
style={[
|
||||
pal.view,
|
||||
styles.linkCard,
|
||||
account.did === pendingDid && t.atoms.bg_contrast_25,
|
||||
a.w_full,
|
||||
a.flex_row,
|
||||
a.align_center,
|
||||
a.gap_md,
|
||||
a.py_md,
|
||||
t.atoms.bg,
|
||||
{
|
||||
paddingHorizontal: 18,
|
||||
marginBottom: 1,
|
||||
},
|
||||
account.did === pendingDid && [t.atoms.bg_contrast_25],
|
||||
ctx.pressed && [t.atoms.bg_contrast_25],
|
||||
]}>
|
||||
<View style={styles.avi}>
|
||||
<UserAvatar
|
||||
size={40}
|
||||
avatar={profile?.avatar}
|
||||
type={profile?.associated?.labeler ? 'labeler' : 'user'}
|
||||
/>
|
||||
</View>
|
||||
<View style={[s.flex1]}>
|
||||
<Text type="md-bold" style={[pal.text, a.self_start]} numberOfLines={1}>
|
||||
<UserAvatar
|
||||
size={40}
|
||||
avatar={profile?.avatar}
|
||||
type={profile?.associated?.labeler ? 'labeler' : 'user'}
|
||||
/>
|
||||
<View style={[a.flex_1]}>
|
||||
<NewText
|
||||
style={[a.text_md, a.font_bold, a.leading_tight]}
|
||||
numberOfLines={1}>
|
||||
{profile?.displayName || account.handle}
|
||||
</Text>
|
||||
<Text type="sm" style={pal.textLight} numberOfLines={1}>
|
||||
{account.handle}
|
||||
</Text>
|
||||
</NewText>
|
||||
<NewText
|
||||
style={[t.atoms.text_contrast_medium, a.leading_tight]}
|
||||
numberOfLines={1}>
|
||||
{sanitizeHandle(account.handle, '@')}
|
||||
</NewText>
|
||||
</View>
|
||||
<AccountDropdownBtn account={account} />
|
||||
</View>
|
||||
)
|
||||
|
||||
return isCurrentAccount ? (
|
||||
<Link
|
||||
href={makeProfileLink({
|
||||
<NewLink
|
||||
to={makeProfileLink({
|
||||
did: currentAccount?.did,
|
||||
handle: currentAccount?.handle,
|
||||
})}
|
||||
title={_(msg`Your profile`)}
|
||||
noFeedback>
|
||||
label={_(msg`Your profile`)}
|
||||
style={[a.w_full]}>
|
||||
{contents}
|
||||
</Link>
|
||||
</NewLink>
|
||||
) : (
|
||||
<TouchableOpacity
|
||||
<Button
|
||||
testID={`switchToAccountBtn-${account.handle}`}
|
||||
key={account.did}
|
||||
onPress={
|
||||
pendingDid ? undefined : () => onPressSwitchAccount(account, 'Settings')
|
||||
}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={_(msg`Switch to ${account.handle}`)}
|
||||
accessibilityHint={_(msg`Switches the account you are logged in to`)}
|
||||
activeOpacity={0.8}>
|
||||
label={_(msg`Switch to ${account.handle}`)}
|
||||
style={[a.w_full]}>
|
||||
{contents}
|
||||
</TouchableOpacity>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue