This commit is contained in:
parent
c2a931f49c
commit
f84a379376
3 changed files with 297 additions and 289 deletions
292
src/view/shell/mobile/BottomBar.tsx
Normal file
292
src/view/shell/mobile/BottomBar.tsx
Normal file
|
@ -0,0 +1,292 @@
|
||||||
|
import React from 'react'
|
||||||
|
import {
|
||||||
|
Animated,
|
||||||
|
GestureResponderEvent,
|
||||||
|
StyleSheet,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
} from 'react-native'
|
||||||
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
|
import {observer} from 'mobx-react-lite'
|
||||||
|
import {Text} from 'view/com/util/text/Text'
|
||||||
|
import {useStores} from 'state/index'
|
||||||
|
import {useAnalytics} from 'lib/analytics'
|
||||||
|
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
|
||||||
|
import {TabPurpose, TabPurposeMainPath} from 'state/models/navigation'
|
||||||
|
import {clamp} from 'lib/numbers'
|
||||||
|
import {
|
||||||
|
HomeIcon,
|
||||||
|
HomeIconSolid,
|
||||||
|
MagnifyingGlassIcon2,
|
||||||
|
MagnifyingGlassIcon2Solid,
|
||||||
|
ComposeIcon2,
|
||||||
|
BellIcon,
|
||||||
|
BellIconSolid,
|
||||||
|
UserIcon,
|
||||||
|
} from 'lib/icons'
|
||||||
|
import {colors} from 'lib/styles'
|
||||||
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
|
||||||
|
export const BottomBar = observer(() => {
|
||||||
|
const store = useStores()
|
||||||
|
const pal = usePalette('default')
|
||||||
|
const minimalShellInterp = useAnimatedValue(0)
|
||||||
|
const safeAreaInsets = useSafeAreaInsets()
|
||||||
|
const {track} = useAnalytics()
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (store.shell.minimalShellMode) {
|
||||||
|
Animated.timing(minimalShellInterp, {
|
||||||
|
toValue: 1,
|
||||||
|
duration: 100,
|
||||||
|
useNativeDriver: true,
|
||||||
|
isInteraction: false,
|
||||||
|
}).start()
|
||||||
|
} else {
|
||||||
|
Animated.timing(minimalShellInterp, {
|
||||||
|
toValue: 0,
|
||||||
|
duration: 100,
|
||||||
|
useNativeDriver: true,
|
||||||
|
isInteraction: false,
|
||||||
|
}).start()
|
||||||
|
}
|
||||||
|
}, [minimalShellInterp, store.shell.minimalShellMode])
|
||||||
|
const footerMinimalShellTransform = {
|
||||||
|
transform: [{translateY: Animated.multiply(minimalShellInterp, 100)}],
|
||||||
|
}
|
||||||
|
|
||||||
|
const onPressHome = React.useCallback(() => {
|
||||||
|
track('MobileShell:HomeButtonPressed')
|
||||||
|
if (store.nav.tab.fixedTabPurpose === TabPurpose.Default) {
|
||||||
|
if (!store.nav.tab.canGoBack) {
|
||||||
|
store.emitScreenSoftReset()
|
||||||
|
} else {
|
||||||
|
store.nav.tab.fixedTabReset()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
store.nav.switchTo(TabPurpose.Default, false)
|
||||||
|
if (store.nav.tab.index === 0) {
|
||||||
|
store.nav.tab.fixedTabReset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [store, track])
|
||||||
|
const onPressSearch = React.useCallback(() => {
|
||||||
|
track('MobileShell:SearchButtonPressed')
|
||||||
|
if (store.nav.tab.fixedTabPurpose === TabPurpose.Search) {
|
||||||
|
if (!store.nav.tab.canGoBack) {
|
||||||
|
store.emitScreenSoftReset()
|
||||||
|
} else {
|
||||||
|
store.nav.tab.fixedTabReset()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
store.nav.switchTo(TabPurpose.Search, false)
|
||||||
|
if (store.nav.tab.index === 0) {
|
||||||
|
store.nav.tab.fixedTabReset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [store, track])
|
||||||
|
const onPressCompose = React.useCallback(() => {
|
||||||
|
track('MobileShell:ComposeButtonPressed')
|
||||||
|
store.shell.openComposer({})
|
||||||
|
}, [store, track])
|
||||||
|
const onPressNotifications = React.useCallback(() => {
|
||||||
|
track('MobileShell:NotificationsButtonPressed')
|
||||||
|
if (store.nav.tab.fixedTabPurpose === TabPurpose.Notifs) {
|
||||||
|
if (!store.nav.tab.canGoBack) {
|
||||||
|
store.emitScreenSoftReset()
|
||||||
|
} else {
|
||||||
|
store.nav.tab.fixedTabReset()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
store.nav.switchTo(TabPurpose.Notifs, false)
|
||||||
|
if (store.nav.tab.index === 0) {
|
||||||
|
store.nav.tab.fixedTabReset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [store, track])
|
||||||
|
const onPressProfile = React.useCallback(() => {
|
||||||
|
track('MobileShell:ProfileButtonPressed')
|
||||||
|
store.nav.navigate(`/profile/${store.me.handle}`)
|
||||||
|
}, [store, track])
|
||||||
|
|
||||||
|
const isAtHome =
|
||||||
|
store.nav.tab.current.url === TabPurposeMainPath[TabPurpose.Default]
|
||||||
|
const isAtSearch =
|
||||||
|
store.nav.tab.current.url === TabPurposeMainPath[TabPurpose.Search]
|
||||||
|
const isAtNotifications =
|
||||||
|
store.nav.tab.current.url === TabPurposeMainPath[TabPurpose.Notifs]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Animated.View
|
||||||
|
style={[
|
||||||
|
styles.bottomBar,
|
||||||
|
pal.view,
|
||||||
|
pal.border,
|
||||||
|
{paddingBottom: clamp(safeAreaInsets.bottom, 15, 30)},
|
||||||
|
footerMinimalShellTransform,
|
||||||
|
]}>
|
||||||
|
<Btn
|
||||||
|
icon={
|
||||||
|
isAtHome ? (
|
||||||
|
<HomeIconSolid
|
||||||
|
strokeWidth={4}
|
||||||
|
size={24}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<HomeIcon
|
||||||
|
strokeWidth={4}
|
||||||
|
size={24}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onPress={onPressHome}
|
||||||
|
/>
|
||||||
|
<Btn
|
||||||
|
icon={
|
||||||
|
isAtSearch ? (
|
||||||
|
<MagnifyingGlassIcon2Solid
|
||||||
|
size={25}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
||||||
|
strokeWidth={1.8}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<MagnifyingGlassIcon2
|
||||||
|
size={25}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
||||||
|
strokeWidth={1.8}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onPress={onPressSearch}
|
||||||
|
/>
|
||||||
|
<Btn
|
||||||
|
icon={
|
||||||
|
<View style={styles.ctrlIconSizingWrapper}>
|
||||||
|
<ComposeIcon2
|
||||||
|
strokeWidth={1.5}
|
||||||
|
size={29}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.composeIcon]}
|
||||||
|
backgroundColor={pal.colors.background}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
onPress={onPressCompose}
|
||||||
|
/>
|
||||||
|
<Btn
|
||||||
|
icon={
|
||||||
|
isAtNotifications ? (
|
||||||
|
<BellIconSolid
|
||||||
|
size={24}
|
||||||
|
strokeWidth={1.9}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<BellIcon
|
||||||
|
size={24}
|
||||||
|
strokeWidth={1.9}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onPress={onPressNotifications}
|
||||||
|
notificationCount={store.me.notifications.unreadCount}
|
||||||
|
/>
|
||||||
|
<Btn
|
||||||
|
icon={
|
||||||
|
<View style={styles.ctrlIconSizingWrapper}>
|
||||||
|
<UserIcon
|
||||||
|
size={28}
|
||||||
|
strokeWidth={1.5}
|
||||||
|
style={[styles.ctrlIcon, pal.text, styles.profileIcon]}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
onPress={onPressProfile}
|
||||||
|
/>
|
||||||
|
</Animated.View>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
function Btn({
|
||||||
|
icon,
|
||||||
|
notificationCount,
|
||||||
|
onPress,
|
||||||
|
onLongPress,
|
||||||
|
}: {
|
||||||
|
icon: JSX.Element
|
||||||
|
notificationCount?: number
|
||||||
|
onPress?: (event: GestureResponderEvent) => void
|
||||||
|
onLongPress?: (event: GestureResponderEvent) => void
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
style={styles.ctrl}
|
||||||
|
onPress={onLongPress ? onPress : undefined}
|
||||||
|
onPressIn={onLongPress ? undefined : onPress}
|
||||||
|
onLongPress={onLongPress}>
|
||||||
|
{notificationCount ? (
|
||||||
|
<View style={styles.notificationCount}>
|
||||||
|
<Text style={styles.notificationCountLabel}>{notificationCount}</Text>
|
||||||
|
</View>
|
||||||
|
) : undefined}
|
||||||
|
{icon}
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
bottomBar: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
flexDirection: 'row',
|
||||||
|
borderTopWidth: 1,
|
||||||
|
paddingLeft: 5,
|
||||||
|
paddingRight: 10,
|
||||||
|
},
|
||||||
|
ctrl: {
|
||||||
|
flex: 1,
|
||||||
|
paddingTop: 13,
|
||||||
|
paddingBottom: 4,
|
||||||
|
},
|
||||||
|
notificationCount: {
|
||||||
|
position: 'absolute',
|
||||||
|
left: '56%',
|
||||||
|
top: 10,
|
||||||
|
backgroundColor: colors.blue3,
|
||||||
|
paddingHorizontal: 4,
|
||||||
|
paddingBottom: 1,
|
||||||
|
borderRadius: 8,
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
|
notificationCountLabel: {
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: colors.white,
|
||||||
|
},
|
||||||
|
ctrlIcon: {
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
},
|
||||||
|
ctrlIconSizingWrapper: {
|
||||||
|
height: 27,
|
||||||
|
},
|
||||||
|
homeIcon: {
|
||||||
|
top: 0,
|
||||||
|
},
|
||||||
|
searchIcon: {
|
||||||
|
top: -2,
|
||||||
|
},
|
||||||
|
bellIcon: {
|
||||||
|
top: -2.5,
|
||||||
|
},
|
||||||
|
composeIcon: {
|
||||||
|
top: -4.5,
|
||||||
|
},
|
||||||
|
profileIcon: {
|
||||||
|
top: -4,
|
||||||
|
},
|
||||||
|
})
|
|
@ -119,7 +119,6 @@ export const Menu = observer(({onClose}: {onClose: () => void}) => {
|
||||||
style={[
|
style={[
|
||||||
styles.view,
|
styles.view,
|
||||||
theme.colorScheme === 'light' ? pal.view : styles.viewDarkMode,
|
theme.colorScheme === 'light' ? pal.view : styles.viewDarkMode,
|
||||||
store.shell.minimalShellMode && styles.viewMinimalShell,
|
|
||||||
]}>
|
]}>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
testID="profileCardButton"
|
testID="profileCardButton"
|
||||||
|
@ -272,15 +271,12 @@ const styles = StyleSheet.create({
|
||||||
view: {
|
view: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
paddingTop: 10,
|
paddingTop: 10,
|
||||||
paddingBottom: 90,
|
paddingBottom: 50,
|
||||||
paddingLeft: 30,
|
paddingLeft: 30,
|
||||||
},
|
},
|
||||||
viewDarkMode: {
|
viewDarkMode: {
|
||||||
backgroundColor: colors.gray8,
|
backgroundColor: colors.gray8,
|
||||||
},
|
},
|
||||||
viewMinimalShell: {
|
|
||||||
paddingBottom: 50,
|
|
||||||
},
|
|
||||||
|
|
||||||
profileCardDisplayName: {
|
profileCardDisplayName: {
|
||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import React, {useState, useEffect} from 'react'
|
import React, {useState} from 'react'
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {
|
import {
|
||||||
Animated,
|
Animated,
|
||||||
GestureResponderEvent,
|
|
||||||
StatusBar,
|
StatusBar,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
TouchableOpacity,
|
|
||||||
TouchableWithoutFeedback,
|
TouchableWithoutFeedback,
|
||||||
useWindowDimensions,
|
useWindowDimensions,
|
||||||
View,
|
View,
|
||||||
|
@ -14,14 +12,11 @@ import {ScreenContainer, Screen} from 'react-native-screens'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import {IconProp} from '@fortawesome/fontawesome-svg-core'
|
import {IconProp} from '@fortawesome/fontawesome-svg-core'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {
|
import {NavigationModel} from 'state/models/navigation'
|
||||||
NavigationModel,
|
|
||||||
TabPurpose,
|
|
||||||
TabPurposeMainPath,
|
|
||||||
} from 'state/models/navigation'
|
|
||||||
import {match, MatchResult} from '../../routes'
|
import {match, MatchResult} from '../../routes'
|
||||||
import {Login} from '../../screens/Login'
|
import {Login} from '../../screens/Login'
|
||||||
import {Menu} from './Menu'
|
import {Menu} from './Menu'
|
||||||
|
import {BottomBar} from './BottomBar'
|
||||||
import {HorzSwipe} from '../../com/util/gestures/HorzSwipe'
|
import {HorzSwipe} from '../../com/util/gestures/HorzSwipe'
|
||||||
import {ModalsContainer} from '../../com/modals/Modal'
|
import {ModalsContainer} from '../../com/modals/Modal'
|
||||||
import {Lightbox} from '../../com/lightbox/Lightbox'
|
import {Lightbox} from '../../com/lightbox/Lightbox'
|
||||||
|
@ -29,48 +24,9 @@ import {Text} from '../../com/util/text/Text'
|
||||||
import {ErrorBoundary} from '../../com/util/ErrorBoundary'
|
import {ErrorBoundary} from '../../com/util/ErrorBoundary'
|
||||||
import {Composer} from './Composer'
|
import {Composer} from './Composer'
|
||||||
import {s, colors} from 'lib/styles'
|
import {s, colors} from 'lib/styles'
|
||||||
import {clamp} from 'lib/numbers'
|
|
||||||
import {
|
|
||||||
HomeIcon,
|
|
||||||
HomeIconSolid,
|
|
||||||
MagnifyingGlassIcon2,
|
|
||||||
MagnifyingGlassIcon2Solid,
|
|
||||||
ComposeIcon2,
|
|
||||||
BellIcon,
|
|
||||||
BellIconSolid,
|
|
||||||
UserIcon,
|
|
||||||
} from 'lib/icons'
|
|
||||||
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
|
import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
|
||||||
import {useTheme} from 'lib/ThemeContext'
|
import {useTheme} from 'lib/ThemeContext'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
|
||||||
|
|
||||||
const Btn = ({
|
|
||||||
icon,
|
|
||||||
notificationCount,
|
|
||||||
onPress,
|
|
||||||
onLongPress,
|
|
||||||
}: {
|
|
||||||
icon: JSX.Element
|
|
||||||
notificationCount?: number
|
|
||||||
onPress?: (event: GestureResponderEvent) => void
|
|
||||||
onLongPress?: (event: GestureResponderEvent) => void
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<TouchableOpacity
|
|
||||||
style={styles.ctrl}
|
|
||||||
onPress={onLongPress ? onPress : undefined}
|
|
||||||
onPressIn={onLongPress ? undefined : onPress}
|
|
||||||
onLongPress={onLongPress}>
|
|
||||||
{notificationCount ? (
|
|
||||||
<View style={styles.notificationCount}>
|
|
||||||
<Text style={styles.notificationCountLabel}>{notificationCount}</Text>
|
|
||||||
</View>
|
|
||||||
) : undefined}
|
|
||||||
{icon}
|
|
||||||
</TouchableOpacity>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MobileShell: React.FC = observer(() => {
|
export const MobileShell: React.FC = observer(() => {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
@ -79,87 +35,8 @@ export const MobileShell: React.FC = observer(() => {
|
||||||
const winDim = useWindowDimensions()
|
const winDim = useWindowDimensions()
|
||||||
const [menuSwipingDirection, setMenuSwipingDirection] = useState(0)
|
const [menuSwipingDirection, setMenuSwipingDirection] = useState(0)
|
||||||
const swipeGestureInterp = useAnimatedValue(0)
|
const swipeGestureInterp = useAnimatedValue(0)
|
||||||
const minimalShellInterp = useAnimatedValue(0)
|
|
||||||
const safeAreaInsets = useSafeAreaInsets()
|
const safeAreaInsets = useSafeAreaInsets()
|
||||||
const screenRenderDesc = constructScreenRenderDesc(store.nav)
|
const screenRenderDesc = constructScreenRenderDesc(store.nav)
|
||||||
const {track} = useAnalytics()
|
|
||||||
|
|
||||||
const onPressHome = () => {
|
|
||||||
track('MobileShell:HomeButtonPressed')
|
|
||||||
if (store.nav.tab.fixedTabPurpose === TabPurpose.Default) {
|
|
||||||
if (!store.nav.tab.canGoBack) {
|
|
||||||
store.emitScreenSoftReset()
|
|
||||||
} else {
|
|
||||||
store.nav.tab.fixedTabReset()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
store.nav.switchTo(TabPurpose.Default, false)
|
|
||||||
if (store.nav.tab.index === 0) {
|
|
||||||
store.nav.tab.fixedTabReset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const onPressSearch = () => {
|
|
||||||
track('MobileShell:SearchButtonPressed')
|
|
||||||
if (store.nav.tab.fixedTabPurpose === TabPurpose.Search) {
|
|
||||||
if (!store.nav.tab.canGoBack) {
|
|
||||||
store.emitScreenSoftReset()
|
|
||||||
} else {
|
|
||||||
store.nav.tab.fixedTabReset()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
store.nav.switchTo(TabPurpose.Search, false)
|
|
||||||
if (store.nav.tab.index === 0) {
|
|
||||||
store.nav.tab.fixedTabReset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const onPressCompose = () => {
|
|
||||||
track('MobileShell:ComposeButtonPressed')
|
|
||||||
store.shell.openComposer({})
|
|
||||||
}
|
|
||||||
const onPressNotifications = () => {
|
|
||||||
track('MobileShell:NotificationsButtonPressed')
|
|
||||||
if (store.nav.tab.fixedTabPurpose === TabPurpose.Notifs) {
|
|
||||||
if (!store.nav.tab.canGoBack) {
|
|
||||||
store.emitScreenSoftReset()
|
|
||||||
} else {
|
|
||||||
store.nav.tab.fixedTabReset()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
store.nav.switchTo(TabPurpose.Notifs, false)
|
|
||||||
if (store.nav.tab.index === 0) {
|
|
||||||
store.nav.tab.fixedTabReset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const onPressProfile = () => {
|
|
||||||
track('MobileShell:ProfileButtonPressed')
|
|
||||||
store.nav.navigate(`/profile/${store.me.handle}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// minimal shell animation
|
|
||||||
// =
|
|
||||||
useEffect(() => {
|
|
||||||
if (store.shell.minimalShellMode) {
|
|
||||||
Animated.timing(minimalShellInterp, {
|
|
||||||
toValue: 1,
|
|
||||||
duration: 100,
|
|
||||||
useNativeDriver: true,
|
|
||||||
isInteraction: false,
|
|
||||||
}).start()
|
|
||||||
} else {
|
|
||||||
Animated.timing(minimalShellInterp, {
|
|
||||||
toValue: 0,
|
|
||||||
duration: 100,
|
|
||||||
useNativeDriver: true,
|
|
||||||
isInteraction: false,
|
|
||||||
}).start()
|
|
||||||
}
|
|
||||||
}, [minimalShellInterp, store.shell.minimalShellMode])
|
|
||||||
const footerMinimalShellTransform = {
|
|
||||||
transform: [{translateY: Animated.multiply(minimalShellInterp, 100)}],
|
|
||||||
}
|
|
||||||
|
|
||||||
// navigation swipes
|
// navigation swipes
|
||||||
// =
|
// =
|
||||||
|
@ -231,13 +108,6 @@ export const MobileShell: React.FC = observer(() => {
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
// TODO
|
|
||||||
// const tabMenuTransform = {
|
|
||||||
// transform: [{translateY: Animated.multiply(tabMenuInterp, -320)}],
|
|
||||||
// }
|
|
||||||
// const newTabTransform = {
|
|
||||||
// transform: [{scale: newTabInterp}],
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (store.hackUpgradeNeeded) {
|
if (store.hackUpgradeNeeded) {
|
||||||
return (
|
return (
|
||||||
|
@ -286,13 +156,6 @@ export const MobileShell: React.FC = observer(() => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const isAtHome =
|
|
||||||
store.nav.tab.current.url === TabPurposeMainPath[TabPurpose.Default]
|
|
||||||
const isAtSearch =
|
|
||||||
store.nav.tab.current.url === TabPurposeMainPath[TabPurpose.Search]
|
|
||||||
const isAtNotifications =
|
|
||||||
store.nav.tab.current.url === TabPurposeMainPath[TabPurpose.Notifs]
|
|
||||||
|
|
||||||
const screenBg = {
|
const screenBg = {
|
||||||
backgroundColor: theme.colorScheme === 'dark' ? colors.gray7 : colors.gray1,
|
backgroundColor: theme.colorScheme === 'dark' ? colors.gray7 : colors.gray1,
|
||||||
}
|
}
|
||||||
|
@ -360,6 +223,7 @@ export const MobileShell: React.FC = observer(() => {
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
</ScreenContainer>
|
</ScreenContainer>
|
||||||
|
<BottomBar />
|
||||||
{isMenuActive || menuSwipingDirection !== 0 ? (
|
{isMenuActive || menuSwipingDirection !== 0 ? (
|
||||||
<TouchableWithoutFeedback
|
<TouchableWithoutFeedback
|
||||||
onPress={() => store.shell.setMainMenuOpen(false)}>
|
onPress={() => store.shell.setMainMenuOpen(false)}>
|
||||||
|
@ -373,95 +237,6 @@ export const MobileShell: React.FC = observer(() => {
|
||||||
)}
|
)}
|
||||||
</HorzSwipe>
|
</HorzSwipe>
|
||||||
</View>
|
</View>
|
||||||
<Animated.View
|
|
||||||
style={[
|
|
||||||
styles.bottomBar,
|
|
||||||
pal.view,
|
|
||||||
pal.border,
|
|
||||||
{paddingBottom: clamp(safeAreaInsets.bottom, 15, 30)},
|
|
||||||
footerMinimalShellTransform,
|
|
||||||
]}>
|
|
||||||
<Btn
|
|
||||||
icon={
|
|
||||||
isAtHome ? (
|
|
||||||
<HomeIconSolid
|
|
||||||
strokeWidth={4}
|
|
||||||
size={24}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<HomeIcon
|
|
||||||
strokeWidth={4}
|
|
||||||
size={24}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onPress={onPressHome}
|
|
||||||
/>
|
|
||||||
<Btn
|
|
||||||
icon={
|
|
||||||
isAtSearch ? (
|
|
||||||
<MagnifyingGlassIcon2Solid
|
|
||||||
size={25}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
|
||||||
strokeWidth={1.8}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<MagnifyingGlassIcon2
|
|
||||||
size={25}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
|
||||||
strokeWidth={1.8}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onPress={onPressSearch}
|
|
||||||
/>
|
|
||||||
<Btn
|
|
||||||
icon={
|
|
||||||
<View style={styles.ctrlIconSizingWrapper}>
|
|
||||||
<ComposeIcon2
|
|
||||||
strokeWidth={1.5}
|
|
||||||
size={29}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.composeIcon]}
|
|
||||||
backgroundColor={pal.colors.background}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
}
|
|
||||||
onPress={onPressCompose}
|
|
||||||
/>
|
|
||||||
<Btn
|
|
||||||
icon={
|
|
||||||
isAtNotifications ? (
|
|
||||||
<BellIconSolid
|
|
||||||
size={24}
|
|
||||||
strokeWidth={1.9}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<BellIcon
|
|
||||||
size={24}
|
|
||||||
strokeWidth={1.9}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onPress={onPressNotifications}
|
|
||||||
notificationCount={store.me.notifications.unreadCount}
|
|
||||||
/>
|
|
||||||
<Btn
|
|
||||||
icon={
|
|
||||||
<View style={styles.ctrlIconSizingWrapper}>
|
|
||||||
<UserIcon
|
|
||||||
size={28}
|
|
||||||
strokeWidth={1.5}
|
|
||||||
style={[styles.ctrlIcon, pal.text, styles.profileIcon]}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
}
|
|
||||||
onPress={onPressProfile}
|
|
||||||
/>
|
|
||||||
</Animated.View>
|
|
||||||
<ModalsContainer />
|
<ModalsContainer />
|
||||||
<Lightbox />
|
<Lightbox />
|
||||||
<Composer
|
<Composer
|
||||||
|
@ -563,59 +338,4 @@ const styles = StyleSheet.create({
|
||||||
topBarProtectorDark: {
|
topBarProtectorDark: {
|
||||||
backgroundColor: colors.black,
|
backgroundColor: colors.black,
|
||||||
},
|
},
|
||||||
bottomBar: {
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
flexDirection: 'row',
|
|
||||||
borderTopWidth: 1,
|
|
||||||
paddingLeft: 5,
|
|
||||||
paddingRight: 10,
|
|
||||||
},
|
|
||||||
ctrl: {
|
|
||||||
flex: 1,
|
|
||||||
paddingTop: 13,
|
|
||||||
paddingBottom: 4,
|
|
||||||
},
|
|
||||||
notificationCount: {
|
|
||||||
position: 'absolute',
|
|
||||||
left: '56%',
|
|
||||||
top: 10,
|
|
||||||
backgroundColor: colors.blue3,
|
|
||||||
paddingHorizontal: 4,
|
|
||||||
paddingBottom: 1,
|
|
||||||
borderRadius: 8,
|
|
||||||
zIndex: 1,
|
|
||||||
},
|
|
||||||
notificationCountLabel: {
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
color: colors.white,
|
|
||||||
},
|
|
||||||
ctrlIcon: {
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
},
|
|
||||||
ctrlIconSizingWrapper: {
|
|
||||||
height: 27,
|
|
||||||
},
|
|
||||||
inactive: {
|
|
||||||
color: colors.gray3,
|
|
||||||
},
|
|
||||||
homeIcon: {
|
|
||||||
top: 0,
|
|
||||||
},
|
|
||||||
searchIcon: {
|
|
||||||
top: -2,
|
|
||||||
},
|
|
||||||
bellIcon: {
|
|
||||||
top: -2.5,
|
|
||||||
},
|
|
||||||
composeIcon: {
|
|
||||||
top: -4.5,
|
|
||||||
},
|
|
||||||
profileIcon: {
|
|
||||||
top: -4,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue