Complete header
This commit is contained in:
@@ -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 |
@@ -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',
|
||||||
|
})
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user