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