mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at schema-errors 277 lines 7.0 kB view raw
1import React from 'react' 2import {StyleSheet, TouchableOpacity, View} from 'react-native' 3import Animated from 'react-native-reanimated' 4import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' 5import {msg} from '@lingui/macro' 6import {useLingui} from '@lingui/react' 7import {useNavigation} from '@react-navigation/native' 8 9import {useSetDrawerOpen} from '#/state/shell' 10import {useAnalytics} from 'lib/analytics/analytics' 11import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode' 12import {usePalette} from 'lib/hooks/usePalette' 13import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' 14import {NavigationProp} from 'lib/routes/types' 15import {useTheme} from '#/alf' 16import {Text} from './text/Text' 17import {CenteredView} from './Views' 18import hairlineWidth = StyleSheet.hairlineWidth 19 20const BACK_HITSLOP = {left: 20, top: 20, right: 50, bottom: 20} 21 22export function ViewHeader({ 23 title, 24 subtitle, 25 canGoBack, 26 showBackButton = true, 27 hideOnScroll, 28 showOnDesktop, 29 showBorder, 30 renderButton, 31}: { 32 title: string 33 subtitle?: string 34 canGoBack?: boolean 35 showBackButton?: boolean 36 hideOnScroll?: boolean 37 showOnDesktop?: boolean 38 showBorder?: boolean 39 renderButton?: () => JSX.Element 40}) { 41 const pal = usePalette('default') 42 const {_} = useLingui() 43 const setDrawerOpen = useSetDrawerOpen() 44 const navigation = useNavigation<NavigationProp>() 45 const {track} = useAnalytics() 46 const {isDesktop, isTablet} = useWebMediaQueries() 47 const t = useTheme() 48 49 const onPressBack = React.useCallback(() => { 50 if (navigation.canGoBack()) { 51 navigation.goBack() 52 } else { 53 navigation.navigate('Home') 54 } 55 }, [navigation]) 56 57 const onPressMenu = React.useCallback(() => { 58 track('ViewHeader:MenuButtonClicked') 59 setDrawerOpen(true) 60 }, [track, setDrawerOpen]) 61 62 if (isDesktop) { 63 if (showOnDesktop) { 64 return ( 65 <DesktopWebHeader 66 title={title} 67 subtitle={subtitle} 68 renderButton={renderButton} 69 showBorder={showBorder} 70 /> 71 ) 72 } 73 return null 74 } else { 75 if (typeof canGoBack === 'undefined') { 76 canGoBack = navigation.canGoBack() 77 } 78 79 return ( 80 <Container hideOnScroll={hideOnScroll || false} showBorder={showBorder}> 81 <View style={{flex: 1}}> 82 <View style={{flexDirection: 'row', alignItems: 'center'}}> 83 {showBackButton ? ( 84 <TouchableOpacity 85 testID="viewHeaderDrawerBtn" 86 onPress={canGoBack ? onPressBack : onPressMenu} 87 hitSlop={BACK_HITSLOP} 88 style={canGoBack ? styles.backBtn : styles.backBtnWide} 89 accessibilityRole="button" 90 accessibilityLabel={canGoBack ? _(msg`Back`) : _(msg`Menu`)} 91 accessibilityHint={ 92 canGoBack ? '' : _(msg`Access navigation links and settings`) 93 }> 94 {canGoBack ? ( 95 <FontAwesomeIcon 96 size={18} 97 icon="angle-left" 98 style={[styles.backIcon, pal.text]} 99 /> 100 ) : !isTablet ? ( 101 <FontAwesomeIcon 102 size={18} 103 icon="bars" 104 style={[styles.backIcon, pal.textLight]} 105 /> 106 ) : null} 107 </TouchableOpacity> 108 ) : null} 109 <View style={styles.titleContainer} pointerEvents="none"> 110 <Text type="title" style={[pal.text, styles.title]}> 111 {title} 112 </Text> 113 </View> 114 {renderButton ? ( 115 renderButton() 116 ) : showBackButton ? ( 117 <View style={canGoBack ? styles.backBtn : styles.backBtnWide} /> 118 ) : null} 119 </View> 120 {subtitle ? ( 121 <View 122 style={[styles.titleContainer, {marginTop: -3}]} 123 pointerEvents="none"> 124 <Text 125 style={[ 126 pal.text, 127 styles.subtitle, 128 t.atoms.text_contrast_medium, 129 ]}> 130 {subtitle} 131 </Text> 132 </View> 133 ) : undefined} 134 </View> 135 </Container> 136 ) 137 } 138} 139 140function DesktopWebHeader({ 141 title, 142 subtitle, 143 renderButton, 144 showBorder = true, 145}: { 146 title: string 147 subtitle?: string 148 renderButton?: () => JSX.Element 149 showBorder?: boolean 150}) { 151 const pal = usePalette('default') 152 const t = useTheme() 153 return ( 154 <CenteredView 155 style={[ 156 styles.header, 157 styles.desktopHeader, 158 pal.border, 159 { 160 borderBottomWidth: showBorder ? hairlineWidth : 0, 161 }, 162 {display: 'flex', flexDirection: 'column'}, 163 ]}> 164 <View> 165 <View style={styles.titleContainer} pointerEvents="none"> 166 <Text type="title-lg" style={[pal.text, styles.title]}> 167 {title} 168 </Text> 169 </View> 170 {renderButton?.()} 171 </View> 172 {subtitle ? ( 173 <View> 174 <View style={[styles.titleContainer]} pointerEvents="none"> 175 <Text 176 style={[ 177 pal.text, 178 styles.subtitleDesktop, 179 t.atoms.text_contrast_medium, 180 ]}> 181 {subtitle} 182 </Text> 183 </View> 184 </View> 185 ) : null} 186 </CenteredView> 187 ) 188} 189 190function Container({ 191 children, 192 hideOnScroll, 193 showBorder, 194}: { 195 children: React.ReactNode 196 hideOnScroll: boolean 197 showBorder?: boolean 198}) { 199 const pal = usePalette('default') 200 const {headerMinimalShellTransform} = useMinimalShellMode() 201 202 if (!hideOnScroll) { 203 return ( 204 <View 205 style={[ 206 styles.header, 207 pal.view, 208 pal.border, 209 showBorder && styles.border, 210 ]}> 211 {children} 212 </View> 213 ) 214 } 215 return ( 216 <Animated.View 217 style={[ 218 styles.header, 219 styles.headerFloating, 220 pal.view, 221 pal.border, 222 headerMinimalShellTransform, 223 showBorder && styles.border, 224 ]}> 225 {children} 226 </Animated.View> 227 ) 228} 229 230const styles = StyleSheet.create({ 231 header: { 232 flexDirection: 'row', 233 paddingHorizontal: 12, 234 paddingVertical: 6, 235 width: '100%', 236 }, 237 headerFloating: { 238 position: 'absolute', 239 top: 0, 240 width: '100%', 241 }, 242 desktopHeader: { 243 paddingVertical: 12, 244 maxWidth: 600, 245 marginLeft: 'auto', 246 marginRight: 'auto', 247 }, 248 border: { 249 borderBottomWidth: hairlineWidth, 250 }, 251 titleContainer: { 252 marginLeft: 'auto', 253 marginRight: 'auto', 254 alignItems: 'center', 255 }, 256 title: { 257 fontWeight: 'bold', 258 }, 259 subtitle: { 260 fontSize: 13, 261 }, 262 subtitleDesktop: { 263 fontSize: 15, 264 }, 265 backBtn: { 266 width: 30, 267 height: 30, 268 }, 269 backBtnWide: { 270 width: 30, 271 height: 30, 272 paddingHorizontal: 6, 273 }, 274 backIcon: { 275 marginTop: 6, 276 }, 277})