Complete header

This commit is contained in:
Eric Bailey
2024-02-07 18:52:44 -06:00
parent 9a57155339
commit 97bfa40ce3
5 changed files with 112 additions and 127 deletions
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M3 5a1 1 0 0 0 0 2h18a1 1 0 1 0 0-2H3Zm-1 7a1 1 0 0 1 1-1h18a1 1 0 1 1 0 2H3a1 1 0 0 1-1-1Zm0 6a1 1 0 0 1 1-1h18a1 1 0 1 1 0 2H3a1 1 0 0 1-1-1Z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 286 B

+5
View File
@@ -0,0 +1,5 @@
import {createSinglePathSVG} from './TEMPLATE'
export const Bars3_Stroke2_Corner0_Rounded = createSinglePathSVG({
path: 'M3 5a1 1 0 0 0 0 2h18a1 1 0 1 0 0-2H3Zm-1 7a1 1 0 0 1 1-1h18a1 1 0 1 1 0 2H3a1 1 0 0 1-1-1Zm0 6a1 1 0 0 1 1-1h18a1 1 0 1 1 0 2H3a1 1 0 0 1-1-1Z',
})
+68 -94
View File
@@ -1,38 +1,29 @@
import React from 'react' import React from 'react'
import {Pressable, StyleSheet, View} from 'react-native' import {View} from 'react-native'
import LinearGradient from 'react-native-linear-gradient' import LinearGradient from 'react-native-linear-gradient'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {useNavigation} from '@react-navigation/native' import {useNavigation} from '@react-navigation/native'
import {usePalette} from 'lib/hooks/usePalette' import {AppBskyModerationDefs} from '@atproto/api'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {Text as OldText} from '#/view/com/util/text/Text'
import {TextLink} from '#/view/com/util/Link'
import {CenteredView} from '#/view/com/util/Views'
import {sanitizeHandle} from 'lib/strings/handles'
import {makeProfileLink} from 'lib/routes/links'
import {NavigationProp} from 'lib/routes/types'
import {BACK_HITSLOP} from 'lib/constants'
import {isNative} from 'platform/detection'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {Trans, msg} from '@lingui/macro' import {Trans, msg} from '@lingui/macro'
import {sanitizeHandle} from '#/lib/strings/handles'
import {makeProfileLink} from '#/lib/routes/links'
import {NavigationProp} from '#/lib/routes/types'
import {useSetDrawerOpen} from '#/state/shell' import {useSetDrawerOpen} from '#/state/shell'
import {emitSoftReset} from '#/state/events' import {emitSoftReset} from '#/state/events'
import {AppBskyModerationDefs} from '@atproto/api' import {shareUrl} from '#/lib/sharing'
import {HandIcon} from '#/lib/icons'
import {shareUrl} from 'lib/sharing'
import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {Button as OldButton} from '#/view/com/util/forms/Button' import {NativeDropdown, DropdownItem} from '#/view/com/util/forms/NativeDropdown'
import {NativeDropdown, DropdownItem} from 'view/com/util/forms/NativeDropdown'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {useModalControls} from '#/state/modals' import {useModalControls} from '#/state/modals'
import {useTheme, atoms as a, tokens} from '#/alf' import {useTheme, atoms as a, tokens, web, native, useBreakpoints} from '#/alf'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {Button, ButtonText} from '#/components/Button' import {Button, ButtonText, ButtonIcon} from '#/components/Button'
import {RaisingHande4Finger_Stroke2_Corner0_Rounded as RaisingHand} from '#/components/icons/RaisingHand' import {RaisingHande4Finger_Stroke2_Corner0_Rounded as RaisingHand} from '#/components/icons/RaisingHand'
import {InlineLink} from '#/components/Link'
import {DotGrid1x3Horizontal_Stroke2_Corner0_Rounded as Ellipsis} from '#/components/icons/DotGrid' import {DotGrid1x3Horizontal_Stroke2_Corner0_Rounded as Ellipsis} from '#/components/icons/DotGrid'
import {ChevronLeft_Stroke2_Corner0_Rounded as ChevronLeft} from '#/components/icons/Chevron' import {ChevronLeft_Stroke2_Corner0_Rounded as ChevronLeft} from '#/components/icons/Chevron'
import {Bars3_Stroke2_Corner0_Rounded as Bars} from '#/components/icons/Bars'
import {Divider} from '#/components/Divider' import {Divider} from '#/components/Divider'
export function Header({ export function Header({
@@ -41,11 +32,10 @@ export function Header({
info: AppBskyModerationDefs.ModServiceViewDetailed info: AppBskyModerationDefs.ModServiceViewDetailed
}) { }) {
const t = useTheme() const t = useTheme()
const {gtMobile} = useBreakpoints()
const setDrawerOpen = useSetDrawerOpen() const setDrawerOpen = useSetDrawerOpen()
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
const {_} = useLingui() const {_} = useLingui()
const {isMobile} = useWebMediaQueries()
const pal = usePalette('default')
const canGoBack = navigation.canGoBack() const canGoBack = navigation.canGoBack()
const onPressBack = React.useCallback(() => { const onPressBack = React.useCallback(() => {
@@ -61,8 +51,8 @@ export function Header({
}, [setDrawerOpen]) }, [setDrawerOpen])
return ( return (
<View style={[a.pb_xl]}> <View style={[a.pb_xl, web(a.pt_md), gtMobile && web(a.pt_4xl)]}>
{isMobile && ( {!gtMobile && (
<View style={[a.mb_xl]}> <View style={[a.mb_xl]}>
<View <View
style={[a.flex_row, a.justify_between, a.align_center, a.pb_md]}> style={[a.flex_row, a.justify_between, a.align_center, a.pb_md]}>
@@ -70,22 +60,26 @@ export function Header({
testID="headerDrawerBtn" testID="headerDrawerBtn"
size="small" size="small"
color="secondary" color="secondary"
variant="ghost" variant="solid"
shape="round" shape="square"
onPress={canGoBack ? onPressBack : onPressMenu} onPress={canGoBack ? onPressBack : onPressMenu}
label={canGoBack ? 'Back' : 'Menu'}> label={canGoBack ? _(msg`Go back`) : _(msg`Open main menu`)}>
{canGoBack ? ( <ButtonIcon icon={canGoBack ? ChevronLeft : Bars} />
<ChevronLeft width={18} style={[t.atoms.text]} />
) : (
<FontAwesomeIcon
size={18}
icon="bars"
style={[styles.backIcon, pal.textLight]}
/>
)}
</Button> </Button>
<CommonControls info={info} /> <View style={[a.flex_row, a.align_center, a.gap_md]}>
<Button
size="small"
variant="solid"
color="primary"
label={_(msg`Subscribe to moderation service`)}>
<ButtonText>
<Trans>Subscribe</Trans>
</ButtonText>
</Button>
<CommonControls info={info} />
</View>
</View> </View>
<Divider /> <Divider />
@@ -107,39 +101,44 @@ export function Header({
end={{x: 1, y: 1}} end={{x: 1, y: 1}}
style={[a.absolute, a.inset_0]} style={[a.absolute, a.inset_0]}
/> />
<RaisingHand width={32} fill={t.atoms.text.color} style={[a.z_10]} /> <RaisingHand width={32} fill={t.palette.white} style={[a.z_10]} />
</View> </View>
<View style={[a.flex_1, a.gap_xs]}> <View style={[a.flex_1, a.gap_xs, native(a.pt_2xs)]}>
<InlineLink <Button
label={_(msg`Refresh page`)}
testID="headerTitle" testID="headerTitle"
to={makeProfileLink(info.creator, 'modservice')} // TODO do we need this?
onPress={emitSoftReset} onPress={emitSoftReset}
style={[a.text_4xl, a.font_bold, t.atoms.text]}> style={[a.justify_start]}>
{/* A really long and complex title for a moderation service */} <Text style={[a.text_4xl, a.font_bold, t.atoms.text]}>
{info.creator.displayName {/* A really long and complex title for a moderation service */}
? sanitizeDisplayName(info.creator.displayName) {info.creator.displayName
: sanitizeHandle(info.creator.handle, '@')} ? sanitizeDisplayName(info.creator.displayName)
</InlineLink> : sanitizeHandle(info.creator.handle, '@')}
</Text>
</Button>
<Text style={[a.text_md, t.atoms.text_contrast_700]}> <Text style={[a.text_md, t.atoms.text_contrast_700]}>
<Trans>Moderation service</Trans> <Trans>Moderation service</Trans>
</Text> </Text>
</View> </View>
<View style={[a.flex_row, a.align_center, a.gap_md]}> {gtMobile && (
<Button <View style={[a.flex_row, a.align_center, a.gap_md]}>
size="small" <Button
variant="solid" size="small"
color="primary" variant="solid"
label={_(msg`Subscribe to moderation service`)}> color="primary"
<ButtonText> label={_(msg`Subscribe to moderation service`)}>
<Trans>Subscribe</Trans> <ButtonText>
</ButtonText> <Trans>Subscribe</Trans>
</Button> </ButtonText>
</Button>
{!isMobile && <CommonControls info={info} />} <CommonControls info={info} />
</View> </View>
)}
</View> </View>
</View> </View>
) )
@@ -151,9 +150,9 @@ function CommonControls({
info: AppBskyModerationDefs.ModServiceViewDetailed info: AppBskyModerationDefs.ModServiceViewDetailed
}) { }) {
const t = useTheme() const t = useTheme()
const {_} = useLingui()
const {hasSession} = useSession() const {hasSession} = useSession()
const {openModal} = useModalControls() const {openModal} = useModalControls()
const {_} = useLingui()
const onPressShare = React.useCallback(() => { const onPressShare = React.useCallback(() => {
const url = makeProfileLink(info.creator, 'modservice') const url = makeProfileLink(info.creator, 'modservice')
@@ -200,39 +199,14 @@ function CommonControls({
}, [hasSession, onPressReport, onPressShare, _]) }, [hasSession, onPressReport, onPressShare, _])
return ( return (
<> <NativeDropdown
<NativeDropdown testID="headerDropdownBtn"
testID="headerDropdownBtn" items={dropdownItems}
items={dropdownItems} accessibilityLabel={_(msg`More options`)}
accessibilityLabel={_(msg`More options`)} accessibilityHint="">
accessibilityHint=""> <View style={[a.rounded_full, a.p_sm, t.atoms.bg_contrast_50]}>
<View style={[a.rounded_full, a.p_sm, t.atoms.bg_contrast_50]}> <Ellipsis width={20} fill={t.atoms.text_contrast_700.color} />
<Ellipsis width={20} fill={t.atoms.text_contrast_700.color} /> </View>
</View> </NativeDropdown>
</NativeDropdown>
</>
) )
} }
const styles = StyleSheet.create({
backBtn: {
width: 20,
height: 30,
},
backBtnWide: {
width: 20,
height: 30,
paddingHorizontal: 6,
},
backIcon: {
marginTop: 6,
},
btn: {
flexDirection: 'row',
alignItems: 'center',
gap: 6,
paddingVertical: 7,
paddingHorizontal: 14,
borderRadius: 50,
},
})
@@ -65,7 +65,6 @@ export function ProfileModserviceScreen(
<CenteredView> <CenteredView>
<View <View
style={[ style={[
a.pt_2xl,
a.px_xl, a.px_xl,
a.border_l, a.border_l,
a.border_r, a.border_r,
+38 -32
View File
@@ -12,6 +12,9 @@ import {usePalette} from 'lib/hooks/usePalette'
import {s, colors} from 'lib/styles' import {s, colors} from 'lib/styles'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {atoms as a} from '#/alf'
import {Link} from '#/components/Link'
const richtext = new RichTextAPI({ const richtext = new RichTextAPI({
text: "Bluesky's official moderation service", text: "Bluesky's official moderation service",
}) })
@@ -21,41 +24,44 @@ export function ProfileHeaderModCard() {
const {isMobile} = useWebMediaQueries() const {isMobile} = useWebMediaQueries()
return ( return (
<View <Link to='/profile/alice.test/modservice' style={[a.flex_row]}>
style={[ <View
pal.view, style={[
pal.borderDark, a.w_full,
s.mt5, pal.view,
{ pal.borderDark,
borderWidth: 1, s.mt5,
borderRadius: 8, {
paddingVertical: 10, borderWidth: 1,
paddingHorizontal: 12, borderRadius: 8,
}, paddingVertical: 10,
]}> paddingHorizontal: 12,
<View style={[s.flexRow, s.alignCenter, {gap: 8}]}> },
{!isMobile && <HandIcon style={pal.text} size={24} strokeWidth={5.5} />} ]}>
<View style={{flex: 1}}> <View style={[s.flexRow, s.alignCenter, {gap: 8}]}>
<Text type="lg-bold" style={pal.text}> {!isMobile && <HandIcon style={pal.text} size={24} strokeWidth={5.5} />}
<Trans>Moderation service</Trans> <View style={{flex: 1}}>
</Text> <Text type="lg-bold" style={pal.text}>
<RichText richText={richtext} /> <Trans>Moderation service</Trans>
</View>
{isMobile ? (
<HandIcon style={pal.text} size={24} strokeWidth={5.5} />
) : (
<View
style={[
pal.viewLight,
{paddingHorizontal: 12, paddingVertical: 6, borderRadius: 24},
]}>
<Text type="button" style={pal.text}>
<Trans>View</Trans>
</Text> </Text>
<RichText richText={richtext} />
</View> </View>
)} {isMobile ? (
<HandIcon style={pal.text} size={24} strokeWidth={5.5} />
) : (
<View
style={[
pal.viewLight,
{paddingHorizontal: 12, paddingVertical: 6, borderRadius: 24},
]}>
<Text type="button" style={pal.text}>
<Trans>View</Trans>
</Text>
</View>
)}
</View>
</View> </View>
</View> </Link>
) )
} }