Clean up drawer (#5761)
* clean up drawer * add a lil bit of padding * Drawer nits (#5778) * Avi stuff * Rm SafeAreaView, not working on Android * Dividers and spacing * Fix count on android, ended up refactoring the whole MenuItem * Litttttle more space * Improve NavSignupCard * format nit --------- Co-authored-by: Samuel Newman <mozzius@protonmail.com> --------- Co-authored-by: Eric Bailey <git@esb.lol>
This commit is contained in:
+244
-316
@@ -1,26 +1,17 @@
|
|||||||
import React, {ComponentProps} from 'react'
|
import React, {ComponentProps} from 'react'
|
||||||
import {
|
import {Linking, ScrollView, TouchableOpacity, View} from 'react-native'
|
||||||
Linking,
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
SafeAreaView,
|
|
||||||
ScrollView,
|
|
||||||
StyleProp,
|
|
||||||
StyleSheet,
|
|
||||||
TouchableOpacity,
|
|
||||||
View,
|
|
||||||
ViewStyle,
|
|
||||||
} from 'react-native'
|
|
||||||
import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
|
|
||||||
import {msg, Plural, Trans} from '@lingui/macro'
|
import {msg, Plural, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {StackActions, useNavigation} from '@react-navigation/native'
|
import {StackActions, useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {FEEDBACK_FORM_URL, HELP_DESK_URL} from '#/lib/constants'
|
import {FEEDBACK_FORM_URL, HELP_DESK_URL} from '#/lib/constants'
|
||||||
|
import {PressableScale} from '#/lib/custom-animations/PressableScale'
|
||||||
import {useNavigationTabState} from '#/lib/hooks/useNavigationTabState'
|
import {useNavigationTabState} from '#/lib/hooks/useNavigationTabState'
|
||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
|
||||||
import {getTabState, TabState} from '#/lib/routes/helpers'
|
import {getTabState, TabState} from '#/lib/routes/helpers'
|
||||||
import {NavigationProp} from '#/lib/routes/types'
|
import {NavigationProp} from '#/lib/routes/types'
|
||||||
import {colors, s} from '#/lib/styles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
import {useTheme} from '#/lib/ThemeContext'
|
import {colors} from '#/lib/styles'
|
||||||
import {isWeb} from '#/platform/detection'
|
import {isWeb} from '#/platform/detection'
|
||||||
import {emitSoftReset} from '#/state/events'
|
import {emitSoftReset} from '#/state/events'
|
||||||
import {useKawaiiMode} from '#/state/preferences/kawaii'
|
import {useKawaiiMode} from '#/state/preferences/kawaii'
|
||||||
@@ -29,12 +20,12 @@ import {useProfileQuery} from '#/state/queries/profile'
|
|||||||
import {SessionAccount, useSession} from '#/state/session'
|
import {SessionAccount, useSession} from '#/state/session'
|
||||||
import {useSetDrawerOpen} from '#/state/shell'
|
import {useSetDrawerOpen} from '#/state/shell'
|
||||||
import {formatCount} from '#/view/com/util/numeric/format'
|
import {formatCount} from '#/view/com/util/numeric/format'
|
||||||
import {Text} from '#/view/com/util/text/Text'
|
|
||||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||||
import {NavSignupCard} from '#/view/shell/NavSignupCard'
|
import {NavSignupCard} from '#/view/shell/NavSignupCard'
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a} from '#/alf'
|
||||||
import {useTheme as useAlfTheme} from '#/alf'
|
import {useTheme} from '#/alf'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
|
import {Divider} from '#/components/Divider'
|
||||||
import {
|
import {
|
||||||
Bell_Filled_Corner0_Rounded as BellFilled,
|
Bell_Filled_Corner0_Rounded as BellFilled,
|
||||||
Bell_Stroke2_Corner0_Rounded as Bell,
|
Bell_Stroke2_Corner0_Rounded as Bell,
|
||||||
@@ -50,15 +41,19 @@ import {
|
|||||||
} from '#/components/icons/HomeOpen'
|
} from '#/components/icons/HomeOpen'
|
||||||
import {MagnifyingGlass_Filled_Stroke2_Corner0_Rounded as MagnifyingGlassFilled} from '#/components/icons/MagnifyingGlass'
|
import {MagnifyingGlass_Filled_Stroke2_Corner0_Rounded as MagnifyingGlassFilled} from '#/components/icons/MagnifyingGlass'
|
||||||
import {MagnifyingGlass2_Stroke2_Corner0_Rounded as MagnifyingGlass} from '#/components/icons/MagnifyingGlass2'
|
import {MagnifyingGlass2_Stroke2_Corner0_Rounded as MagnifyingGlass} from '#/components/icons/MagnifyingGlass2'
|
||||||
import {Message_Stroke2_Corner0_Rounded as Message} from '#/components/icons/Message'
|
import {
|
||||||
|
Message_Stroke2_Corner0_Rounded as Message,
|
||||||
|
Message_Stroke2_Corner0_Rounded_Filled as MessageFilled,
|
||||||
|
} from '#/components/icons/Message'
|
||||||
import {SettingsGear2_Stroke2_Corner0_Rounded as Settings} from '#/components/icons/SettingsGear2'
|
import {SettingsGear2_Stroke2_Corner0_Rounded as Settings} from '#/components/icons/SettingsGear2'
|
||||||
import {
|
import {
|
||||||
UserCircle_Filled_Corner0_Rounded as UserCircleFilled,
|
UserCircle_Filled_Corner0_Rounded as UserCircleFilled,
|
||||||
UserCircle_Stroke2_Corner0_Rounded as UserCircle,
|
UserCircle_Stroke2_Corner0_Rounded as UserCircle,
|
||||||
} from '#/components/icons/UserCircle'
|
} from '#/components/icons/UserCircle'
|
||||||
import {TextLink} from '../com/util/Link'
|
import {InlineLinkText} from '#/components/Link'
|
||||||
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
const iconWidth = 28
|
const iconWidth = 26
|
||||||
|
|
||||||
let DrawerProfileCard = ({
|
let DrawerProfileCard = ({
|
||||||
account,
|
account,
|
||||||
@@ -68,7 +63,7 @@ let DrawerProfileCard = ({
|
|||||||
onPressProfile: () => void
|
onPressProfile: () => void
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const {_, i18n} = useLingui()
|
const {_, i18n} = useLingui()
|
||||||
const pal = usePalette('default')
|
const t = useTheme()
|
||||||
const {data: profile} = useProfileQuery({did: account.did})
|
const {data: profile} = useProfileQuery({did: account.did})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -76,62 +71,52 @@ let DrawerProfileCard = ({
|
|||||||
testID="profileCardButton"
|
testID="profileCardButton"
|
||||||
accessibilityLabel={_(msg`Profile`)}
|
accessibilityLabel={_(msg`Profile`)}
|
||||||
accessibilityHint={_(msg`Navigates to your profile`)}
|
accessibilityHint={_(msg`Navigates to your profile`)}
|
||||||
onPress={onPressProfile}>
|
onPress={onPressProfile}
|
||||||
|
style={[a.gap_sm]}>
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
size={80}
|
size={52}
|
||||||
avatar={profile?.avatar}
|
avatar={profile?.avatar}
|
||||||
// See https://github.com/bluesky-social/social-app/pull/1801:
|
// See https://github.com/bluesky-social/social-app/pull/1801:
|
||||||
usePlainRNImage={true}
|
usePlainRNImage={true}
|
||||||
type={profile?.associated?.labeler ? 'labeler' : 'user'}
|
type={profile?.associated?.labeler ? 'labeler' : 'user'}
|
||||||
/>
|
/>
|
||||||
<Text
|
<View style={[a.gap_2xs]}>
|
||||||
type="title-lg"
|
<Text
|
||||||
style={[pal.text, s.bold, styles.profileCardDisplayName]}
|
emoji
|
||||||
numberOfLines={1}>
|
style={[a.font_heavy, a.text_xl, a.mt_2xs, a.leading_tight]}
|
||||||
{profile?.displayName || account.handle}
|
numberOfLines={1}>
|
||||||
</Text>
|
{profile?.displayName || account.handle}
|
||||||
<Text
|
|
||||||
type="2xl"
|
|
||||||
style={[pal.textLight, styles.profileCardHandle]}
|
|
||||||
numberOfLines={1}>
|
|
||||||
@{account.handle}
|
|
||||||
</Text>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
styles.profileCardFollowers,
|
|
||||||
a.gap_xs,
|
|
||||||
a.flex_row,
|
|
||||||
a.align_center,
|
|
||||||
a.flex_wrap,
|
|
||||||
]}>
|
|
||||||
<Text type="xl" style={pal.textLight}>
|
|
||||||
<Trans>
|
|
||||||
<Text type="xl-medium" style={pal.text}>
|
|
||||||
{formatCount(i18n, profile?.followersCount ?? 0)}
|
|
||||||
</Text>{' '}
|
|
||||||
<Plural
|
|
||||||
value={profile?.followersCount || 0}
|
|
||||||
one="follower"
|
|
||||||
other="followers"
|
|
||||||
/>
|
|
||||||
</Trans>
|
|
||||||
</Text>
|
</Text>
|
||||||
<Text type="xl" style={pal.textLight}>
|
<Text
|
||||||
·
|
emoji
|
||||||
</Text>
|
style={[t.atoms.text_contrast_medium, a.text_md, a.leading_tight]}
|
||||||
<Text type="xl" style={pal.textLight}>
|
numberOfLines={1}>
|
||||||
<Trans>
|
{sanitizeHandle(account.handle, '@')}
|
||||||
<Text type="xl-medium" style={pal.text}>
|
|
||||||
{formatCount(i18n, profile?.followsCount ?? 0)}
|
|
||||||
</Text>{' '}
|
|
||||||
<Plural
|
|
||||||
value={profile?.followsCount || 0}
|
|
||||||
one="following"
|
|
||||||
other="following"
|
|
||||||
/>
|
|
||||||
</Trans>
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
<Text style={[a.text_md, t.atoms.text_contrast_medium]}>
|
||||||
|
<Trans>
|
||||||
|
<Text style={[a.text_md, a.font_bold]}>
|
||||||
|
{formatCount(i18n, profile?.followersCount ?? 0)}
|
||||||
|
</Text>{' '}
|
||||||
|
<Plural
|
||||||
|
value={profile?.followersCount || 0}
|
||||||
|
one="follower"
|
||||||
|
other="followers"
|
||||||
|
/>
|
||||||
|
</Trans>{' '}
|
||||||
|
·{' '}
|
||||||
|
<Trans>
|
||||||
|
<Text style={[a.text_md, a.font_bold]}>
|
||||||
|
{formatCount(i18n, profile?.followsCount ?? 0)}
|
||||||
|
</Text>{' '}
|
||||||
|
<Plural
|
||||||
|
value={profile?.followsCount || 0}
|
||||||
|
one="following"
|
||||||
|
other="following"
|
||||||
|
/>
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -139,14 +124,19 @@ DrawerProfileCard = React.memo(DrawerProfileCard)
|
|||||||
export {DrawerProfileCard}
|
export {DrawerProfileCard}
|
||||||
|
|
||||||
let DrawerContent = ({}: {}): React.ReactNode => {
|
let DrawerContent = ({}: {}): React.ReactNode => {
|
||||||
const theme = useTheme()
|
const t = useTheme()
|
||||||
const t = useAlfTheme()
|
|
||||||
const pal = usePalette('default')
|
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const insets = useSafeAreaInsets()
|
||||||
const setDrawerOpen = useSetDrawerOpen()
|
const setDrawerOpen = useSetDrawerOpen()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const {isAtHome, isAtSearch, isAtFeeds, isAtNotifications, isAtMyProfile} =
|
const {
|
||||||
useNavigationTabState()
|
isAtHome,
|
||||||
|
isAtSearch,
|
||||||
|
isAtFeeds,
|
||||||
|
isAtNotifications,
|
||||||
|
isAtMyProfile,
|
||||||
|
isAtMessages,
|
||||||
|
} = useNavigationTabState()
|
||||||
const {hasSession, currentAccount} = useSession()
|
const {hasSession, currentAccount} = useSession()
|
||||||
const kawaii = useKawaiiMode()
|
const kawaii = useKawaiiMode()
|
||||||
|
|
||||||
@@ -187,6 +177,11 @@ let DrawerContent = ({}: {}): React.ReactNode => {
|
|||||||
[onPressTab],
|
[onPressTab],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const onPressMessages = React.useCallback(
|
||||||
|
() => onPressTab('Messages'),
|
||||||
|
[onPressTab],
|
||||||
|
)
|
||||||
|
|
||||||
const onPressNotifications = React.useCallback(
|
const onPressNotifications = React.useCallback(
|
||||||
() => onPressTab('Notifications'),
|
() => onPressTab('Notifications'),
|
||||||
[onPressTab],
|
[onPressTab],
|
||||||
@@ -228,89 +223,91 @@ let DrawerContent = ({}: {}): React.ReactNode => {
|
|||||||
// =
|
// =
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View testID="drawer" style={[a.flex_1, t.atoms.bg]}>
|
||||||
testID="drawer"
|
<ScrollView
|
||||||
style={[
|
style={[a.flex_1]}
|
||||||
styles.view,
|
contentContainerStyle={[
|
||||||
theme.colorScheme === 'light' ? pal.view : t.atoms.bg_contrast_25,
|
a.px_xl,
|
||||||
]}>
|
{
|
||||||
<SafeAreaView style={s.flex1}>
|
paddingTop: Math.max(
|
||||||
<ScrollView style={styles.main}>
|
insets.top + a.pt_xl.paddingTop,
|
||||||
{hasSession && currentAccount ? (
|
a.pt_xl.paddingTop,
|
||||||
<View style={{}}>
|
),
|
||||||
<DrawerProfileCard
|
},
|
||||||
account={currentAccount}
|
]}>
|
||||||
onPressProfile={onPressProfile}
|
{hasSession && currentAccount ? (
|
||||||
/>
|
<DrawerProfileCard
|
||||||
</View>
|
account={currentAccount}
|
||||||
) : (
|
onPressProfile={onPressProfile}
|
||||||
<View style={{paddingRight: 20}}>
|
/>
|
||||||
<NavSignupCard />
|
) : (
|
||||||
</View>
|
<View style={[a.pr_xl]}>
|
||||||
)}
|
<NavSignupCard />
|
||||||
|
|
||||||
{hasSession ? (
|
|
||||||
<>
|
|
||||||
<View style={{height: 16}} />
|
|
||||||
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
|
|
||||||
<HomeMenuItem isActive={isAtHome} onPress={onPressHome} />
|
|
||||||
<NotificationsMenuItem
|
|
||||||
isActive={isAtNotifications}
|
|
||||||
onPress={onPressNotifications}
|
|
||||||
/>
|
|
||||||
<FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
|
|
||||||
<ListsMenuItem onPress={onPressLists} />
|
|
||||||
<ProfileMenuItem
|
|
||||||
isActive={isAtMyProfile}
|
|
||||||
onPress={onPressProfile}
|
|
||||||
/>
|
|
||||||
<SettingsMenuItem onPress={onPressSettings} />
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<HomeMenuItem isActive={isAtHome} onPress={onPressHome} />
|
|
||||||
<FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
|
|
||||||
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<View style={styles.smallSpacer} />
|
|
||||||
|
|
||||||
<View style={[{flexWrap: 'wrap', gap: 12}, s.flexCol]}>
|
|
||||||
<TextLink
|
|
||||||
type="md"
|
|
||||||
style={pal.link}
|
|
||||||
href="https://bsky.social/about/support/tos"
|
|
||||||
text={_(msg`Terms of Service`)}
|
|
||||||
/>
|
|
||||||
<TextLink
|
|
||||||
type="md"
|
|
||||||
style={pal.link}
|
|
||||||
href="https://bsky.social/about/support/privacy-policy"
|
|
||||||
text={_(msg`Privacy Policy`)}
|
|
||||||
/>
|
|
||||||
{kawaii && (
|
|
||||||
<Text type="md" style={pal.textLight}>
|
|
||||||
Logo by{' '}
|
|
||||||
<TextLink
|
|
||||||
type="md"
|
|
||||||
href="/profile/sawaratsuki.bsky.social"
|
|
||||||
text="@sawaratsuki.bsky.social"
|
|
||||||
style={pal.link}
|
|
||||||
/>
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
<View style={styles.smallSpacer} />
|
<Divider style={[a.mt_xl, a.mb_sm]} />
|
||||||
<View style={styles.smallSpacer} />
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
<DrawerFooter
|
{hasSession ? (
|
||||||
onPressFeedback={onPressFeedback}
|
<>
|
||||||
onPressHelp={onPressHelp}
|
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
|
||||||
/>
|
<HomeMenuItem isActive={isAtHome} onPress={onPressHome} />
|
||||||
</SafeAreaView>
|
<ChatMenuItem isActive={isAtMessages} onPress={onPressMessages} />
|
||||||
|
<NotificationsMenuItem
|
||||||
|
isActive={isAtNotifications}
|
||||||
|
onPress={onPressNotifications}
|
||||||
|
/>
|
||||||
|
<FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
|
||||||
|
<ListsMenuItem onPress={onPressLists} />
|
||||||
|
<ProfileMenuItem
|
||||||
|
isActive={isAtMyProfile}
|
||||||
|
onPress={onPressProfile}
|
||||||
|
/>
|
||||||
|
<SettingsMenuItem onPress={onPressSettings} />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<HomeMenuItem isActive={isAtHome} onPress={onPressHome} />
|
||||||
|
<FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
|
||||||
|
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Divider style={[a.mb_xl, a.mt_sm]} />
|
||||||
|
|
||||||
|
<View style={[a.flex_col, a.gap_md, a.flex_wrap]}>
|
||||||
|
<InlineLinkText
|
||||||
|
style={[a.text_md]}
|
||||||
|
label={_(msg`Terms of Service`)}
|
||||||
|
to="https://bsky.social/about/support/tos">
|
||||||
|
<Trans>Terms of Service</Trans>
|
||||||
|
</InlineLinkText>
|
||||||
|
<InlineLinkText
|
||||||
|
style={[a.text_md]}
|
||||||
|
to="https://bsky.social/about/support/privacy-policy"
|
||||||
|
label={_(msg`Privacy Policy`)}>
|
||||||
|
<Trans>Privacy Policy</Trans>
|
||||||
|
</InlineLinkText>
|
||||||
|
{kawaii && (
|
||||||
|
<Text style={t.atoms.text_contrast_medium}>
|
||||||
|
<Trans>
|
||||||
|
Logo by{' '}
|
||||||
|
<InlineLinkText
|
||||||
|
style={[a.text_md]}
|
||||||
|
to="/profile/sawaratsuki.bsky.social"
|
||||||
|
label="@sawaratsuki.bsky.social">
|
||||||
|
@sawaratsuki.bsky.social
|
||||||
|
</InlineLinkText>
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<DrawerFooter
|
||||||
|
onPressFeedback={onPressFeedback}
|
||||||
|
onPressHelp={onPressHelp}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -325,8 +322,17 @@ let DrawerFooter = ({
|
|||||||
onPressHelp: () => void
|
onPressHelp: () => void
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const insets = useSafeAreaInsets()
|
||||||
return (
|
return (
|
||||||
<View style={styles.footer}>
|
<View
|
||||||
|
style={[
|
||||||
|
a.flex_row,
|
||||||
|
a.gap_sm,
|
||||||
|
a.flex_wrap,
|
||||||
|
a.pl_xl,
|
||||||
|
a.pt_md,
|
||||||
|
{paddingBottom: Math.max(insets.bottom, a.pb_xl.paddingBottom)},
|
||||||
|
]}>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Send feedback`)}
|
label={_(msg`Send feedback`)}
|
||||||
size="small"
|
size="small"
|
||||||
@@ -356,7 +362,7 @@ let DrawerFooter = ({
|
|||||||
}
|
}
|
||||||
DrawerFooter = React.memo(DrawerFooter)
|
DrawerFooter = React.memo(DrawerFooter)
|
||||||
|
|
||||||
interface MenuItemProps extends ComponentProps<typeof TouchableOpacity> {
|
interface MenuItemProps extends ComponentProps<typeof PressableScale> {
|
||||||
icon: JSX.Element
|
icon: JSX.Element
|
||||||
label: string
|
label: string
|
||||||
count?: string
|
count?: string
|
||||||
@@ -371,20 +377,14 @@ let SearchMenuItem = ({
|
|||||||
onPress: () => void
|
onPress: () => void
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const pal = usePalette('default')
|
const t = useTheme()
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={
|
icon={
|
||||||
isActive ? (
|
isActive ? (
|
||||||
<MagnifyingGlassFilled
|
<MagnifyingGlassFilled style={[t.atoms.text]} width={iconWidth} />
|
||||||
style={pal.text as StyleProp<ViewStyle>}
|
|
||||||
width={iconWidth}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<MagnifyingGlass
|
<MagnifyingGlass style={[t.atoms.text]} width={iconWidth} />
|
||||||
style={pal.text as StyleProp<ViewStyle>}
|
|
||||||
width={iconWidth}
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
label={_(msg`Search`)}
|
label={_(msg`Search`)}
|
||||||
@@ -405,17 +405,14 @@ let HomeMenuItem = ({
|
|||||||
onPress: () => void
|
onPress: () => void
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const pal = usePalette('default')
|
const t = useTheme()
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={
|
icon={
|
||||||
isActive ? (
|
isActive ? (
|
||||||
<HomeFilled
|
<HomeFilled style={[t.atoms.text]} width={iconWidth} />
|
||||||
style={pal.text as StyleProp<ViewStyle>}
|
|
||||||
width={iconWidth}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<Home style={pal.text as StyleProp<ViewStyle>} width={iconWidth} />
|
<Home style={[t.atoms.text]} width={iconWidth} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
label={_(msg`Home`)}
|
label={_(msg`Home`)}
|
||||||
@@ -428,6 +425,34 @@ let HomeMenuItem = ({
|
|||||||
}
|
}
|
||||||
HomeMenuItem = React.memo(HomeMenuItem)
|
HomeMenuItem = React.memo(HomeMenuItem)
|
||||||
|
|
||||||
|
let ChatMenuItem = ({
|
||||||
|
isActive,
|
||||||
|
onPress,
|
||||||
|
}: {
|
||||||
|
isActive: boolean
|
||||||
|
onPress: () => void
|
||||||
|
}): React.ReactNode => {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const t = useTheme()
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
icon={
|
||||||
|
isActive ? (
|
||||||
|
<MessageFilled style={[t.atoms.text]} width={iconWidth} />
|
||||||
|
) : (
|
||||||
|
<Message style={[t.atoms.text]} width={iconWidth} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
label={_(msg`Chats`)}
|
||||||
|
accessibilityLabel={_(msg`Chats`)}
|
||||||
|
accessibilityHint=""
|
||||||
|
bold={isActive}
|
||||||
|
onPress={onPress}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ChatMenuItem = React.memo(ChatMenuItem)
|
||||||
|
|
||||||
let NotificationsMenuItem = ({
|
let NotificationsMenuItem = ({
|
||||||
isActive,
|
isActive,
|
||||||
onPress,
|
onPress,
|
||||||
@@ -436,18 +461,15 @@ let NotificationsMenuItem = ({
|
|||||||
onPress: () => void
|
onPress: () => void
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const pal = usePalette('default')
|
const t = useTheme()
|
||||||
const numUnreadNotifications = useUnreadNotifications()
|
const numUnreadNotifications = useUnreadNotifications()
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={
|
icon={
|
||||||
isActive ? (
|
isActive ? (
|
||||||
<BellFilled
|
<BellFilled style={[t.atoms.text]} width={iconWidth} />
|
||||||
style={pal.text as StyleProp<ViewStyle>}
|
|
||||||
width={iconWidth}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<Bell style={pal.text as StyleProp<ViewStyle>} width={iconWidth} />
|
<Bell style={[t.atoms.text]} width={iconWidth} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
label={_(msg`Notifications`)}
|
label={_(msg`Notifications`)}
|
||||||
@@ -473,17 +495,14 @@ let FeedsMenuItem = ({
|
|||||||
onPress: () => void
|
onPress: () => void
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const pal = usePalette('default')
|
const t = useTheme()
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={
|
icon={
|
||||||
isActive ? (
|
isActive ? (
|
||||||
<HashtagFilled
|
<HashtagFilled width={iconWidth} style={[t.atoms.text]} />
|
||||||
width={iconWidth}
|
|
||||||
style={pal.text as FontAwesomeIconStyle}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<Hashtag width={iconWidth} style={pal.text as FontAwesomeIconStyle} />
|
<Hashtag width={iconWidth} style={[t.atoms.text]} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
label={_(msg`Feeds`)}
|
label={_(msg`Feeds`)}
|
||||||
@@ -498,10 +517,11 @@ FeedsMenuItem = React.memo(FeedsMenuItem)
|
|||||||
|
|
||||||
let ListsMenuItem = ({onPress}: {onPress: () => void}): React.ReactNode => {
|
let ListsMenuItem = ({onPress}: {onPress: () => void}): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const pal = usePalette('default')
|
const t = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={<List style={pal.text} width={iconWidth} />}
|
icon={<List style={[t.atoms.text]} width={iconWidth} />}
|
||||||
label={_(msg`Lists`)}
|
label={_(msg`Lists`)}
|
||||||
accessibilityLabel={_(msg`Lists`)}
|
accessibilityLabel={_(msg`Lists`)}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
@@ -519,20 +539,14 @@ let ProfileMenuItem = ({
|
|||||||
onPress: () => void
|
onPress: () => void
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const pal = usePalette('default')
|
const t = useTheme()
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={
|
icon={
|
||||||
isActive ? (
|
isActive ? (
|
||||||
<UserCircleFilled
|
<UserCircleFilled style={[t.atoms.text]} width={iconWidth} />
|
||||||
style={pal.text as StyleProp<ViewStyle>}
|
|
||||||
width={iconWidth}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<UserCircle
|
<UserCircle style={[t.atoms.text]} width={iconWidth} />
|
||||||
style={pal.text as StyleProp<ViewStyle>}
|
|
||||||
width={iconWidth}
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
label={_(msg`Profile`)}
|
label={_(msg`Profile`)}
|
||||||
@@ -546,12 +560,10 @@ ProfileMenuItem = React.memo(ProfileMenuItem)
|
|||||||
|
|
||||||
let SettingsMenuItem = ({onPress}: {onPress: () => void}): React.ReactNode => {
|
let SettingsMenuItem = ({onPress}: {onPress: () => void}): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const pal = usePalette('default')
|
const t = useTheme()
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={
|
icon={<Settings style={[t.atoms.text]} width={iconWidth} />}
|
||||||
<Settings style={pal.text as StyleProp<ViewStyle>} width={iconWidth} />
|
|
||||||
}
|
|
||||||
label={_(msg`Settings`)}
|
label={_(msg`Settings`)}
|
||||||
accessibilityLabel={_(msg`Settings`)}
|
accessibilityLabel={_(msg`Settings`)}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
@@ -569,142 +581,58 @@ function MenuItem({
|
|||||||
bold,
|
bold,
|
||||||
onPress,
|
onPress,
|
||||||
}: MenuItemProps) {
|
}: MenuItemProps) {
|
||||||
const pal = usePalette('default')
|
const t = useTheme()
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<PressableScale
|
||||||
testID={`menuItemButton-${label}`}
|
testID={`menuItemButton-${label}`}
|
||||||
style={styles.menuItem}
|
style={[a.flex_row, a.align_center, a.gap_sm, {paddingVertical: 10}]}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
accessibilityRole="tab"
|
accessibilityRole="tab"
|
||||||
accessibilityLabel={accessibilityLabel}
|
accessibilityLabel={accessibilityLabel}
|
||||||
accessibilityHint="">
|
accessibilityHint=""
|
||||||
<View style={[styles.menuItemIconWrapper]}>
|
targetScale={0.95}>
|
||||||
|
<View style={[a.relative]}>
|
||||||
{icon}
|
{icon}
|
||||||
{count ? (
|
{count ? (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.menuItemCount,
|
a.absolute,
|
||||||
a.rounded_full,
|
a.inset_0,
|
||||||
count.length > 2
|
a.align_end,
|
||||||
? styles.menuItemCountHundreds
|
{top: -4, right: a.gap_sm.gap * -1},
|
||||||
: count.length > 1
|
|
||||||
? styles.menuItemCountTens
|
|
||||||
: undefined,
|
|
||||||
]}>
|
]}>
|
||||||
<Text
|
<View
|
||||||
style={[styles.menuItemCountLabel, a.font_bold]}
|
style={[
|
||||||
numberOfLines={1}>
|
a.rounded_full,
|
||||||
{count}
|
{
|
||||||
</Text>
|
right: count.length === 1 ? 6 : 0,
|
||||||
|
paddingHorizontal: 4,
|
||||||
|
paddingVertical: 1,
|
||||||
|
backgroundColor: t.palette.primary_500,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.text_xs,
|
||||||
|
a.leading_tight,
|
||||||
|
a.font_bold,
|
||||||
|
{
|
||||||
|
fontVariant: ['tabular-nums'],
|
||||||
|
color: colors.white,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
numberOfLines={1}>
|
||||||
|
{count}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
</View>
|
</View>
|
||||||
<Text
|
<Text
|
||||||
type={bold ? '2xl-bold' : '2xl'}
|
style={[a.flex_1, a.text_2xl, bold && a.font_bold]}
|
||||||
style={[pal.text, s.flex1]}
|
|
||||||
numberOfLines={1}>
|
numberOfLines={1}>
|
||||||
{label}
|
{label}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</PressableScale>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
view: {
|
|
||||||
flex: 1,
|
|
||||||
paddingBottom: 50,
|
|
||||||
maxWidth: 300,
|
|
||||||
},
|
|
||||||
viewDarkMode: {
|
|
||||||
backgroundColor: '#1B1919',
|
|
||||||
},
|
|
||||||
main: {
|
|
||||||
paddingHorizontal: 20,
|
|
||||||
paddingTop: 20,
|
|
||||||
},
|
|
||||||
smallSpacer: {
|
|
||||||
height: 20,
|
|
||||||
},
|
|
||||||
|
|
||||||
profileCardDisplayName: {
|
|
||||||
marginTop: 20,
|
|
||||||
paddingRight: 30,
|
|
||||||
},
|
|
||||||
profileCardHandle: {
|
|
||||||
marginTop: 4,
|
|
||||||
paddingRight: 30,
|
|
||||||
},
|
|
||||||
profileCardFollowers: {
|
|
||||||
marginTop: 16,
|
|
||||||
},
|
|
||||||
|
|
||||||
menuItem: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
paddingVertical: 16,
|
|
||||||
},
|
|
||||||
menuItemIconWrapper: {
|
|
||||||
width: 24,
|
|
||||||
height: 24,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
marginRight: 12,
|
|
||||||
},
|
|
||||||
menuItemCount: {
|
|
||||||
position: 'absolute',
|
|
||||||
width: 'auto',
|
|
||||||
right: -6,
|
|
||||||
top: -4,
|
|
||||||
backgroundColor: colors.blue3,
|
|
||||||
paddingHorizontal: 4,
|
|
||||||
paddingBottom: 1,
|
|
||||||
borderRadius: 6,
|
|
||||||
},
|
|
||||||
menuItemCountTens: {
|
|
||||||
width: 25,
|
|
||||||
},
|
|
||||||
menuItemCountHundreds: {
|
|
||||||
right: -12,
|
|
||||||
width: 34,
|
|
||||||
},
|
|
||||||
menuItemCountLabel: {
|
|
||||||
fontSize: 12,
|
|
||||||
fontVariant: ['tabular-nums'],
|
|
||||||
color: colors.white,
|
|
||||||
},
|
|
||||||
|
|
||||||
inviteCodes: {
|
|
||||||
paddingLeft: 0,
|
|
||||||
paddingVertical: 8,
|
|
||||||
flexDirection: 'row',
|
|
||||||
},
|
|
||||||
inviteCodesIcon: {
|
|
||||||
marginRight: 6,
|
|
||||||
flexShrink: 0,
|
|
||||||
marginTop: 2,
|
|
||||||
},
|
|
||||||
|
|
||||||
footer: {
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
flexDirection: 'row',
|
|
||||||
gap: 8,
|
|
||||||
paddingRight: 20,
|
|
||||||
paddingTop: 20,
|
|
||||||
paddingLeft: 20,
|
|
||||||
},
|
|
||||||
footerBtn: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
padding: 10,
|
|
||||||
borderRadius: 25,
|
|
||||||
},
|
|
||||||
footerBtnFeedback: {
|
|
||||||
paddingHorizontal: 20,
|
|
||||||
},
|
|
||||||
footerBtnFeedbackLight: {
|
|
||||||
backgroundColor: '#DDEFFF',
|
|
||||||
},
|
|
||||||
footerBtnFeedbackDark: {
|
|
||||||
backgroundColor: colors.blue6,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -5,18 +5,15 @@ import {useLingui} from '@lingui/react'
|
|||||||
|
|
||||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||||
import {useCloseAllActiveElements} from '#/state/util'
|
import {useCloseAllActiveElements} from '#/state/util'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
|
||||||
import {s} from 'lib/styles'
|
|
||||||
import {Button} from '#/view/com/util/forms/Button'
|
|
||||||
import {Text} from '#/view/com/util/text/Text'
|
|
||||||
import {Logo} from '#/view/icons/Logo'
|
import {Logo} from '#/view/icons/Logo'
|
||||||
import {atoms as a} from '#/alf'
|
import {atoms as a} from '#/alf'
|
||||||
import {AppLanguageDropdown} from '#/components/AppLanguageDropdown'
|
import {AppLanguageDropdown} from '#/components/AppLanguageDropdown'
|
||||||
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import {Link} from '#/components/Link'
|
import {Link} from '#/components/Link'
|
||||||
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
let NavSignupCard = ({}: {}): React.ReactNode => {
|
let NavSignupCard = ({}: {}): React.ReactNode => {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const pal = usePalette('default')
|
|
||||||
const {requestSwitchToAccount} = useLoggedOutViewControls()
|
const {requestSwitchToAccount} = useLoggedOutViewControls()
|
||||||
const closeAllActiveElements = useCloseAllActiveElements()
|
const closeAllActiveElements = useCloseAllActiveElements()
|
||||||
|
|
||||||
@@ -32,45 +29,38 @@ let NavSignupCard = ({}: {}): React.ReactNode => {
|
|||||||
}, [requestSwitchToAccount, closeAllActiveElements])
|
}, [requestSwitchToAccount, closeAllActiveElements])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View style={[{maxWidth: 200}]}>
|
||||||
style={{
|
|
||||||
alignItems: 'flex-start',
|
|
||||||
paddingTop: 6,
|
|
||||||
marginBottom: 24,
|
|
||||||
}}>
|
|
||||||
<Link to="/" label="Bluesky - Home">
|
<Link to="/" label="Bluesky - Home">
|
||||||
<Logo width={48} />
|
<Logo width={32} />
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<View style={{paddingTop: 18}}>
|
<View style={[a.pt_lg]}>
|
||||||
<Text type="md-bold" style={[pal.text]}>
|
<Text
|
||||||
<Trans>Sign up or sign in to join the conversation</Trans>
|
style={[a.text_3xl, a.font_heavy, {lineHeight: a.text_3xl.fontSize}]}>
|
||||||
|
<Trans>Join the conversation</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View
|
<View style={[a.flex_row, a.flex_wrap, a.gap_sm, a.pt_md]}>
|
||||||
style={{
|
|
||||||
flexDirection: 'row',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
paddingTop: 12,
|
|
||||||
gap: 8,
|
|
||||||
}}>
|
|
||||||
<Button
|
<Button
|
||||||
onPress={showCreateAccount}
|
onPress={showCreateAccount}
|
||||||
accessibilityHint={_(msg`Sign up`)}
|
label={_(msg`Sign up`)}
|
||||||
accessibilityLabel={_(msg`Sign up`)}>
|
size="small"
|
||||||
<Text type="md" style={[{color: 'white'}, s.bold]}>
|
variant="solid"
|
||||||
|
color="primary">
|
||||||
|
<ButtonText>
|
||||||
<Trans>Sign up</Trans>
|
<Trans>Sign up</Trans>
|
||||||
</Text>
|
</ButtonText>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="default"
|
|
||||||
onPress={showSignIn}
|
onPress={showSignIn}
|
||||||
accessibilityHint={_(msg`Sign in`)}
|
label={_(msg`Sign in`)}
|
||||||
accessibilityLabel={_(msg`Sign in`)}>
|
size="small"
|
||||||
<Text type="md" style={[pal.text, s.bold]}>
|
variant="solid"
|
||||||
|
color="secondary">
|
||||||
|
<ButtonText>
|
||||||
<Trans>Sign in</Trans>
|
<Trans>Sign in</Trans>
|
||||||
</Text>
|
</ButtonText>
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ function ShellInner() {
|
|||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<Drawer
|
<Drawer
|
||||||
renderDrawerContent={renderDrawerContent}
|
renderDrawerContent={renderDrawerContent}
|
||||||
|
drawerStyle={{width: Math.min(400, winDim.width * 0.8)}}
|
||||||
open={isDrawerOpen}
|
open={isDrawerOpen}
|
||||||
onOpen={onOpenDrawer}
|
onOpen={onOpenDrawer}
|
||||||
onClose={onCloseDrawer}
|
onClose={onCloseDrawer}
|
||||||
|
|||||||
Reference in New Issue
Block a user