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="M2 12a2 2 0 1 1 4 0 2 2 0 0 1-4 0Zm16 0a2 2 0 1 1 4 0 2 2 0 0 1-4 0Zm-6-2a2 2 0 1 0 0 4 2 2 0 0 0 0-4Z" clip-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 245 B |
@@ -122,6 +122,9 @@ export const atoms = {
|
|||||||
flex_shrink: {
|
flex_shrink: {
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
},
|
},
|
||||||
|
justify_start: {
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
},
|
||||||
justify_center: {
|
justify_center: {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
@@ -140,6 +143,24 @@ export const atoms = {
|
|||||||
align_end: {
|
align_end: {
|
||||||
alignItems: 'flex-end',
|
alignItems: 'flex-end',
|
||||||
},
|
},
|
||||||
|
self_auto: {
|
||||||
|
alignSelf: 'auto',
|
||||||
|
},
|
||||||
|
self_start: {
|
||||||
|
alignSelf: 'flex-start',
|
||||||
|
},
|
||||||
|
self_end: {
|
||||||
|
alignSelf: 'flex-end',
|
||||||
|
},
|
||||||
|
self_center: {
|
||||||
|
alignSelf: 'center',
|
||||||
|
},
|
||||||
|
self_stretch: {
|
||||||
|
alignSelf: 'stretch',
|
||||||
|
},
|
||||||
|
self_baseline: {
|
||||||
|
alignSelf: 'baseline',
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Text
|
* Text
|
||||||
|
|||||||
@@ -361,7 +361,6 @@ export function Button({
|
|||||||
disabled: disabled || false,
|
disabled: disabled || false,
|
||||||
}}
|
}}
|
||||||
style={[
|
style={[
|
||||||
flatten(style),
|
|
||||||
a.flex_row,
|
a.flex_row,
|
||||||
a.align_center,
|
a.align_center,
|
||||||
a.justify_center,
|
a.justify_center,
|
||||||
@@ -370,6 +369,7 @@ export function Button({
|
|||||||
...baseStyles,
|
...baseStyles,
|
||||||
...(state.hovered || state.pressed ? hoverStyles : []),
|
...(state.hovered || state.pressed ? hoverStyles : []),
|
||||||
...(state.focused ? focusStyles : []),
|
...(state.focused ? focusStyles : []),
|
||||||
|
flatten(style),
|
||||||
]}
|
]}
|
||||||
onPressIn={onPressIn}
|
onPressIn={onPressIn}
|
||||||
onPressOut={onPressOut}
|
onPressOut={onPressOut}
|
||||||
|
|||||||
+18
-2
@@ -13,7 +13,7 @@ import {sanitizeUrl} from '@braintree/sanitize-url'
|
|||||||
|
|
||||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||||
import {isWeb} from '#/platform/detection'
|
import {isWeb} from '#/platform/detection'
|
||||||
import {useTheme, web, flatten, TextStyleProp} from '#/alf'
|
import {useTheme, web, flatten, TextStyleProp, atoms as a} from '#/alf'
|
||||||
import {Button, ButtonProps} from '#/components/Button'
|
import {Button, ButtonProps} from '#/components/Button'
|
||||||
import {AllNavigatorParams, NavigationProp} from '#/lib/routes/types'
|
import {AllNavigatorParams, NavigationProp} from '#/lib/routes/types'
|
||||||
import {
|
import {
|
||||||
@@ -35,6 +35,8 @@ type BaseLinkProps = Pick<
|
|||||||
Parameters<typeof useLinkProps<AllNavigatorParams>>[0],
|
Parameters<typeof useLinkProps<AllNavigatorParams>>[0],
|
||||||
'to'
|
'to'
|
||||||
> & {
|
> & {
|
||||||
|
testID?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The React Navigation `StackAction` to perform when the link is pressed.
|
* The React Navigation `StackAction` to perform when the link is pressed.
|
||||||
*/
|
*/
|
||||||
@@ -46,6 +48,13 @@ type BaseLinkProps = Pick<
|
|||||||
* Note: atm this only works for `InlineLink`s with a string child.
|
* Note: atm this only works for `InlineLink`s with a string child.
|
||||||
*/
|
*/
|
||||||
warnOnMismatchingTextChild?: boolean
|
warnOnMismatchingTextChild?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for when the link is pressed.
|
||||||
|
*
|
||||||
|
* DO NOT use this for navigation, that's what the `to` prop is for.
|
||||||
|
*/
|
||||||
|
onPress?: (e: GestureResponderEvent) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useLink({
|
export function useLink({
|
||||||
@@ -53,6 +62,7 @@ export function useLink({
|
|||||||
displayText,
|
displayText,
|
||||||
action = 'push',
|
action = 'push',
|
||||||
warnOnMismatchingTextChild,
|
warnOnMismatchingTextChild,
|
||||||
|
onPress: outerOnPress,
|
||||||
}: BaseLinkProps & {
|
}: BaseLinkProps & {
|
||||||
displayText: string
|
displayText: string
|
||||||
}) {
|
}) {
|
||||||
@@ -66,6 +76,8 @@ export function useLink({
|
|||||||
|
|
||||||
const onPress = React.useCallback(
|
const onPress = React.useCallback(
|
||||||
(e: GestureResponderEvent) => {
|
(e: GestureResponderEvent) => {
|
||||||
|
outerOnPress?.(e)
|
||||||
|
|
||||||
const requiresWarning = Boolean(
|
const requiresWarning = Boolean(
|
||||||
warnOnMismatchingTextChild &&
|
warnOnMismatchingTextChild &&
|
||||||
displayText &&
|
displayText &&
|
||||||
@@ -143,7 +155,7 @@ export function useLink({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type LinkProps = Omit<BaseLinkProps, 'warnOnMismatchingTextChild'> &
|
export type LinkProps = Omit<BaseLinkProps, 'warnOnMismatchingTextChild'> &
|
||||||
Omit<ButtonProps, 'style' | 'onPress' | 'disabled' | 'label'> & {
|
Omit<ButtonProps, 'onPress' | 'disabled' | 'label'> & {
|
||||||
/**
|
/**
|
||||||
* Label for a11y. Defaults to the href.
|
* Label for a11y. Defaults to the href.
|
||||||
*/
|
*/
|
||||||
@@ -169,6 +181,10 @@ export function Link({children, to, action = 'push', ...rest}: LinkProps) {
|
|||||||
<Button
|
<Button
|
||||||
label={href}
|
label={href}
|
||||||
{...rest}
|
{...rest}
|
||||||
|
style={[
|
||||||
|
a.justify_start,
|
||||||
|
flatten(rest.style),
|
||||||
|
]}
|
||||||
role="link"
|
role="link"
|
||||||
accessibilityRole="link"
|
accessibilityRole="link"
|
||||||
href={href}
|
href={href}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import {createSinglePathSVG} from './TEMPLATE'
|
||||||
|
|
||||||
|
export const DotGrid1x3Horizontal_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||||
|
path: 'M2 12a2 2 0 1 1 4 0 2 2 0 0 1-4 0Zm16 0a2 2 0 1 1 4 0 2 2 0 0 1-4 0Zm-6-2a2 2 0 1 0 0 4 2 2 0 0 0 0-4Z',
|
||||||
|
})
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {Pressable, StyleSheet, View} from 'react-native'
|
import {Pressable, StyleSheet, View} from 'react-native'
|
||||||
|
import LinearGradient from 'react-native-linear-gradient'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
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 {usePalette} from 'lib/hooks/usePalette'
|
||||||
@@ -25,16 +26,21 @@ 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 } from '#/alf'
|
import {useTheme, atoms as a, tokens} from '#/alf'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} 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 {ChevronLeft_Stroke2_Corner0_Rounded as ChevronLeft} from '#/components/icons/Chevron'
|
||||||
|
import {Divider} from '#/components/Divider'
|
||||||
|
|
||||||
export function Header({
|
export function Header({
|
||||||
info,
|
info,
|
||||||
}: {
|
}: {
|
||||||
info: AppBskyModerationDefs.ModServiceViewDetailed
|
info: AppBskyModerationDefs.ModServiceViewDetailed
|
||||||
}) {
|
}) {
|
||||||
|
const t = useTheme()
|
||||||
const setDrawerOpen = useSetDrawerOpen()
|
const setDrawerOpen = useSetDrawerOpen()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
@@ -55,86 +61,87 @@ export function Header({
|
|||||||
}, [setDrawerOpen])
|
}, [setDrawerOpen])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CenteredView style={pal.view}>
|
<View style={[a.pb_xl]}>
|
||||||
{isMobile && (
|
{isMobile && (
|
||||||
<View
|
<View style={[a.mb_xl]}>
|
||||||
style={[
|
<View
|
||||||
{
|
style={[a.flex_row, a.justify_between, a.align_center, a.pb_md]}>
|
||||||
flexDirection: 'row',
|
<Button
|
||||||
alignItems: 'center',
|
testID="headerDrawerBtn"
|
||||||
borderBottomWidth: 1,
|
size="small"
|
||||||
paddingTop: isNative ? 0 : 8,
|
color="secondary"
|
||||||
paddingBottom: 8,
|
variant="ghost"
|
||||||
paddingHorizontal: isMobile ? 12 : 14,
|
shape="round"
|
||||||
},
|
onPress={canGoBack ? onPressBack : onPressMenu}
|
||||||
pal.border,
|
label={canGoBack ? 'Back' : 'Menu'}>
|
||||||
]}>
|
{canGoBack ? (
|
||||||
<Pressable
|
<ChevronLeft width={18} style={[t.atoms.text]} />
|
||||||
testID="headerDrawerBtn"
|
) : (
|
||||||
onPress={canGoBack ? onPressBack : onPressMenu}
|
<FontAwesomeIcon
|
||||||
hitSlop={BACK_HITSLOP}
|
size={18}
|
||||||
style={canGoBack ? styles.backBtn : styles.backBtnWide}
|
icon="bars"
|
||||||
accessibilityRole="button"
|
style={[styles.backIcon, pal.textLight]}
|
||||||
accessibilityLabel={canGoBack ? 'Back' : 'Menu'}
|
/>
|
||||||
accessibilityHint="">
|
)}
|
||||||
{canGoBack ? (
|
</Button>
|
||||||
<FontAwesomeIcon
|
|
||||||
size={18}
|
<CommonControls info={info} />
|
||||||
icon="angle-left"
|
</View>
|
||||||
style={[styles.backIcon, pal.text]}
|
|
||||||
/>
|
<Divider />
|
||||||
) : (
|
|
||||||
<FontAwesomeIcon
|
|
||||||
size={18}
|
|
||||||
icon="bars"
|
|
||||||
style={[styles.backIcon, pal.textLight]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Pressable>
|
|
||||||
<View style={{flex: 1}} />
|
|
||||||
<CommonControls info={info} />
|
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
<View
|
|
||||||
style={{
|
<View style={[a.flex_row, a.gap_lg, a.align_start]}>
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'flex-start',
|
|
||||||
gap: 10,
|
|
||||||
paddingTop: 14,
|
|
||||||
paddingBottom: 14,
|
|
||||||
paddingHorizontal: isMobile ? 12 : 14,
|
|
||||||
}}>
|
|
||||||
<View style={{alignSelf: 'center'}}>
|
|
||||||
<HandIcon style={pal.text} size={32} strokeWidth={5.5} />
|
|
||||||
</View>
|
|
||||||
<View style={{flex: 1}}>
|
|
||||||
<TextLink
|
|
||||||
testID="headerTitle"
|
|
||||||
type="title-xl"
|
|
||||||
href={makeProfileLink(info.creator, 'modservice')}
|
|
||||||
style={[pal.text, {fontWeight: 'bold'}]}
|
|
||||||
text={
|
|
||||||
info.creator.displayName
|
|
||||||
? sanitizeDisplayName(info.creator.displayName)
|
|
||||||
: sanitizeHandle(info.creator.handle, '@')
|
|
||||||
}
|
|
||||||
onPress={emitSoftReset}
|
|
||||||
numberOfLines={4}
|
|
||||||
/>
|
|
||||||
<OldText type="xl" style={[pal.textLight]} numberOfLines={1}>
|
|
||||||
<Trans>Moderation service</Trans>
|
|
||||||
</OldText>
|
|
||||||
</View>
|
|
||||||
<View
|
<View
|
||||||
style={{
|
style={[
|
||||||
flexDirection: 'row',
|
a.p_md,
|
||||||
alignItems: 'center',
|
t.atoms.bg_contrast_50,
|
||||||
}}>
|
a.rounded_md,
|
||||||
<OldButton type="primary" label={_(msg`Subscribe`)} />
|
a.overflow_hidden,
|
||||||
|
]}>
|
||||||
|
<LinearGradient
|
||||||
|
colors={tokens.gradients.sky.values.map(c => c[1])}
|
||||||
|
locations={tokens.gradients.bonfire.values.map(c => c[0])}
|
||||||
|
start={{x: 0, y: 0}}
|
||||||
|
end={{x: 1, y: 1}}
|
||||||
|
style={[a.absolute, a.inset_0]}
|
||||||
|
/>
|
||||||
|
<RaisingHand width={32} fill={t.atoms.text.color} style={[a.z_10]} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={[a.flex_1, a.gap_xs]}>
|
||||||
|
<InlineLink
|
||||||
|
testID="headerTitle"
|
||||||
|
to={makeProfileLink(info.creator, 'modservice')}
|
||||||
|
onPress={emitSoftReset}
|
||||||
|
style={[a.text_4xl, a.font_bold, t.atoms.text]}>
|
||||||
|
{/* A really long and complex title for a moderation service */}
|
||||||
|
{info.creator.displayName
|
||||||
|
? sanitizeDisplayName(info.creator.displayName)
|
||||||
|
: sanitizeHandle(info.creator.handle, '@')}
|
||||||
|
</InlineLink>
|
||||||
|
|
||||||
|
<Text style={[a.text_md, t.atoms.text_contrast_700]}>
|
||||||
|
<Trans>Moderation service</Trans>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
{!isMobile && <CommonControls info={info} />}
|
{!isMobile && <CommonControls info={info} />}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</CenteredView>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +150,7 @@ function CommonControls({
|
|||||||
}: {
|
}: {
|
||||||
info: AppBskyModerationDefs.ModServiceViewDetailed
|
info: AppBskyModerationDefs.ModServiceViewDetailed
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const t = useTheme()
|
||||||
const {hasSession} = useSession()
|
const {hasSession} = useSession()
|
||||||
const {openModal} = useModalControls()
|
const {openModal} = useModalControls()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
@@ -199,8 +206,8 @@ function CommonControls({
|
|||||||
items={dropdownItems}
|
items={dropdownItems}
|
||||||
accessibilityLabel={_(msg`More options`)}
|
accessibilityLabel={_(msg`More options`)}
|
||||||
accessibilityHint="">
|
accessibilityHint="">
|
||||||
<View style={[pal.viewLight, styles.btn, {marginLeft: 6}]}>
|
<View style={[a.rounded_full, a.p_sm, t.atoms.bg_contrast_50]}>
|
||||||
<FontAwesomeIcon icon="ellipsis" size={20} color={pal.colors.text} />
|
<Ellipsis width={20} fill={t.atoms.text_contrast_700.color} />
|
||||||
</View>
|
</View>
|
||||||
</NativeDropdown>
|
</NativeDropdown>
|
||||||
</>
|
</>
|
||||||
@@ -229,4 +236,3 @@ const styles = StyleSheet.create({
|
|||||||
borderRadius: 50,
|
borderRadius: 50,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user