diff options
Diffstat (limited to 'src/view/shell')
-rw-r--r-- | src/view/shell/Composer.web.tsx | 3 | ||||
-rw-r--r-- | src/view/shell/Drawer.tsx | 68 | ||||
-rw-r--r-- | src/view/shell/bottom-bar/BottomBar.tsx (renamed from src/view/shell/BottomBar.tsx) | 86 | ||||
-rw-r--r-- | src/view/shell/bottom-bar/BottomBarStyles.tsx | 61 | ||||
-rw-r--r-- | src/view/shell/bottom-bar/BottomBarWeb.tsx | 101 | ||||
-rw-r--r-- | src/view/shell/index.web.tsx | 43 |
6 files changed, 237 insertions, 125 deletions
diff --git a/src/view/shell/Composer.web.tsx b/src/view/shell/Composer.web.tsx index e3994bb23..ed0450c01 100644 --- a/src/view/shell/Composer.web.tsx +++ b/src/view/shell/Composer.web.tsx @@ -4,6 +4,7 @@ import {StyleSheet, View} from 'react-native' import {ComposePost} from '../com/composer/Composer' import {ComposerOpts} from 'state/models/ui/shell' import {usePalette} from 'lib/hooks/usePalette' +import {isMobileWeb} from 'platform/detection' export const Composer = observer( ({ @@ -60,7 +61,7 @@ const styles = StyleSheet.create({ width: '100%', paddingVertical: 0, paddingHorizontal: 2, - borderRadius: 8, + borderRadius: isMobileWeb ? 0 : 8, marginBottom: '10vh', }, }) diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx index ebadb2126..de36463e1 100644 --- a/src/view/shell/Drawer.tsx +++ b/src/view/shell/Drawer.tsx @@ -8,11 +8,7 @@ import { View, ViewStyle, } from 'react-native' -import { - useNavigation, - useNavigationState, - StackActions, -} from '@react-navigation/native' +import {useNavigation, StackActions} from '@react-navigation/native' import {observer} from 'mobx-react-lite' import { FontAwesomeIcon, @@ -40,6 +36,8 @@ import {useAnalytics} from 'lib/analytics' import {pluralize} from 'lib/strings/helpers' import {getTabState, TabState} from 'lib/routes/helpers' import {NavigationProp} from 'lib/routes/types' +import {useNavigationTabState} from 'lib/hooks/useNavigationTabState' +import {isWeb} from 'platform/detection' export const DrawerContent = observer(() => { const theme = useTheme() @@ -47,16 +45,7 @@ export const DrawerContent = observer(() => { const store = useStores() const navigation = useNavigation<NavigationProp>() const {track} = useAnalytics() - const {isAtHome, isAtSearch, isAtNotifications} = useNavigationState( - state => { - return { - isAtHome: getTabState(state, 'Home') !== TabState.Outside, - isAtSearch: getTabState(state, 'Search') !== TabState.Outside, - isAtNotifications: - getTabState(state, 'Notifications') !== TabState.Outside, - } - }, - ) + const {isAtHome, isAtSearch, isAtNotifications} = useNavigationTabState() // events // = @@ -66,14 +55,19 @@ export const DrawerContent = observer(() => { track('Menu:ItemClicked', {url: tab}) const state = navigation.getState() store.shell.closeDrawer() - const tabState = getTabState(state, tab) - if (tabState === TabState.InsideAtRoot) { - store.emitScreenSoftReset() - } else if (tabState === TabState.Inside) { - navigation.dispatch(StackActions.popToTop()) - } else { + if (isWeb) { // @ts-ignore must be Home, Search, or Notifications - navigation.navigate(`${tab}Tab`) + navigation.navigate(tab) + } else { + const tabState = getTabState(state, tab) + if (tabState === TabState.InsideAtRoot) { + store.emitScreenSoftReset() + } else if (tabState === TabState.Inside) { + navigation.dispatch(StackActions.popToTop()) + } else { + // @ts-ignore must be Home, Search, or Notifications + navigation.navigate(`${tab}Tab`) + } } }, [store, track, navigation], @@ -240,20 +234,22 @@ export const DrawerContent = observer(() => { </View> <View style={s.flex1} /> <View style={styles.footer}> - <TouchableOpacity - onPress={onDarkmodePress} - style={[ - styles.footerBtn, - theme.colorScheme === 'light' - ? pal.btn - : styles.footerBtnDarkMode, - ]}> - <MoonIcon - size={22} - style={pal.text as StyleProp<ViewStyle>} - strokeWidth={2} - /> - </TouchableOpacity> + {!isWeb && ( + <TouchableOpacity + onPress={onDarkmodePress} + style={[ + styles.footerBtn, + theme.colorScheme === 'light' + ? pal.btn + : styles.footerBtnDarkMode, + ]}> + <MoonIcon + size={22} + style={pal.text as StyleProp<ViewStyle>} + strokeWidth={2} + /> + </TouchableOpacity> + )} <TouchableOpacity onPress={onPressFeedback} style={[ diff --git a/src/view/shell/BottomBar.tsx b/src/view/shell/bottom-bar/BottomBar.tsx index b01366b2b..59b21968d 100644 --- a/src/view/shell/BottomBar.tsx +++ b/src/view/shell/bottom-bar/BottomBar.tsx @@ -2,7 +2,6 @@ import React from 'react' import { Animated, GestureResponderEvent, - StyleSheet, TouchableOpacity, View, } from 'react-native' @@ -13,7 +12,6 @@ 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 {clamp} from 'lib/numbers' import { HomeIcon, @@ -24,14 +22,14 @@ import { BellIconSolid, UserIcon, } from 'lib/icons' -import {colors} from 'lib/styles' import {usePalette} from 'lib/hooks/usePalette' import {getTabState, TabState} from 'lib/routes/helpers' +import {styles} from './BottomBarStyles' +import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode' export const BottomBar = observer(({navigation}: BottomTabBarProps) => { const store = useStores() const pal = usePalette('default') - const minimalShellInterp = useAnimatedValue(0) const safeAreaInsets = useSafeAreaInsets() const {track} = useAnalytics() const {isAtHome, isAtSearch, isAtNotifications} = useNavigationState( @@ -52,26 +50,7 @@ export const BottomBar = observer(({navigation}: BottomTabBarProps) => { }, ) - 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 {footerMinimalShellTransform} = useMinimalShellMode() const onPressTab = React.useCallback( (tab: string) => { @@ -217,62 +196,3 @@ function Btn({ </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: '52%', - top: 8, - backgroundColor: colors.blue3, - paddingHorizontal: 4, - paddingBottom: 1, - borderRadius: 6, - zIndex: 1, - }, - notificationCountLight: { - borderColor: colors.white, - }, - notificationCountDark: { - borderColor: colors.gray8, - }, - notificationCountLabel: { - fontSize: 12, - fontWeight: 'bold', - color: colors.white, - fontVariant: ['tabular-nums'], - }, - ctrlIcon: { - marginLeft: 'auto', - marginRight: 'auto', - }, - ctrlIconSizingWrapper: { - height: 27, - }, - homeIcon: { - top: 0, - }, - searchIcon: { - top: -2, - }, - bellIcon: { - top: -2.5, - }, - profileIcon: { - top: -4, - }, -}) diff --git a/src/view/shell/bottom-bar/BottomBarStyles.tsx b/src/view/shell/bottom-bar/BottomBarStyles.tsx new file mode 100644 index 000000000..3d5adbc9e --- /dev/null +++ b/src/view/shell/bottom-bar/BottomBarStyles.tsx @@ -0,0 +1,61 @@ +import {StyleSheet} from 'react-native' +import {colors} from 'lib/styles' + +export 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: '52%', + top: 8, + backgroundColor: colors.blue3, + paddingHorizontal: 4, + paddingBottom: 1, + borderRadius: 6, + zIndex: 1, + }, + notificationCountLight: { + borderColor: colors.white, + }, + notificationCountDark: { + borderColor: colors.gray8, + }, + notificationCountLabel: { + fontSize: 12, + fontWeight: 'bold', + color: colors.white, + fontVariant: ['tabular-nums'], + }, + ctrlIcon: { + marginLeft: 'auto', + marginRight: 'auto', + }, + ctrlIconSizingWrapper: { + height: 27, + }, + homeIcon: { + top: 0, + }, + searchIcon: { + top: -2, + }, + bellIcon: { + top: -2.5, + }, + profileIcon: { + top: -4, + }, +}) diff --git a/src/view/shell/bottom-bar/BottomBarWeb.tsx b/src/view/shell/bottom-bar/BottomBarWeb.tsx new file mode 100644 index 000000000..b7daac5af --- /dev/null +++ b/src/view/shell/bottom-bar/BottomBarWeb.tsx @@ -0,0 +1,101 @@ +import React from 'react' +import {observer} from 'mobx-react-lite' +import {useStores} from 'state/index' +import {usePalette} from 'lib/hooks/usePalette' +import {Animated} from 'react-native' +import {useNavigationState} from '@react-navigation/native' +import {useSafeAreaInsets} from 'react-native-safe-area-context' +import {getCurrentRoute, isTab} from 'lib/routes/helpers' +import {styles} from './BottomBarStyles' +import {clamp} from 'lib/numbers' +import { + BellIcon, + BellIconSolid, + HomeIcon, + HomeIconSolid, + MagnifyingGlassIcon2, + MagnifyingGlassIcon2Solid, + UserIcon, +} from 'lib/icons' +import {Link} from 'view/com/util/Link' +import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode' + +export const BottomBarWeb = observer(() => { + const store = useStores() + const pal = usePalette('default') + const safeAreaInsets = useSafeAreaInsets() + const {footerMinimalShellTransform} = useMinimalShellMode() + + return ( + <Animated.View + style={[ + styles.bottomBar, + pal.view, + pal.border, + {paddingBottom: clamp(safeAreaInsets.bottom, 15, 30)}, + footerMinimalShellTransform, + ]}> + <NavItem routeName="Home" href="/"> + {({isActive}) => { + const Icon = isActive ? HomeIconSolid : HomeIcon + return ( + <Icon + strokeWidth={4} + size={24} + style={[styles.ctrlIcon, pal.text, styles.homeIcon]} + /> + ) + }} + </NavItem> + <NavItem routeName="Search" href="/search"> + {({isActive}) => { + const Icon = isActive + ? MagnifyingGlassIcon2Solid + : MagnifyingGlassIcon2 + return ( + <Icon + size={25} + style={[styles.ctrlIcon, pal.text, styles.searchIcon]} + strokeWidth={1.8} + /> + ) + }} + </NavItem> + <NavItem routeName="Notifications" href="/notifications"> + {({isActive}) => { + const Icon = isActive ? BellIconSolid : BellIcon + return ( + <Icon + size={24} + strokeWidth={1.9} + style={[styles.ctrlIcon, pal.text, styles.bellIcon]} + /> + ) + }} + </NavItem> + <NavItem routeName="Profile" href={`/profile/${store.me.handle}`}> + {() => ( + <UserIcon + size={28} + strokeWidth={1.5} + style={[styles.ctrlIcon, pal.text, styles.profileIcon]} + /> + )} + </NavItem> + </Animated.View> + ) +}) + +const NavItem: React.FC<{ + children: (props: {isActive: boolean}) => React.ReactChild + href: string + routeName: string +}> = ({children, href, routeName}) => { + const currentRoute = useNavigationState(getCurrentRoute) + const isActive = isTab(currentRoute.name, routeName) + return ( + <Link href={href} style={styles.ctrl}> + {children({isActive})} + </Link> + ) +} diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx index 96a120642..86d120127 100644 --- a/src/view/shell/index.web.tsx +++ b/src/view/shell/index.web.tsx @@ -1,6 +1,6 @@ import React from 'react' import {observer} from 'mobx-react-lite' -import {View, StyleSheet} from 'react-native' +import {View, StyleSheet, TouchableOpacity} from 'react-native' import {useStores} from 'state/index' import {DesktopLeftNav} from './desktop/LeftNav' import {DesktopRightNav} from './desktop/RightNav' @@ -11,9 +11,13 @@ import {Composer} from './Composer.web' import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle' import {s, colors} from 'lib/styles' import {RoutesContainer, FlatNavigator} from '../../Navigation' +import {DrawerContent} from './Drawer' +import {useWebMediaQueries} from '../../lib/hooks/useWebMediaQueries' +import {BottomBarWeb} from './bottom-bar/BottomBarWeb' const ShellInner = observer(() => { const store = useStores() + const {isDesktop} = useWebMediaQueries() return ( <> @@ -22,10 +26,14 @@ const ShellInner = observer(() => { <FlatNavigator /> </ErrorBoundary> </View> - <DesktopLeftNav /> - <DesktopRightNav /> - <View style={[styles.viewBorder, styles.viewBorderLeft]} /> - <View style={[styles.viewBorder, styles.viewBorderRight]} /> + {isDesktop && ( + <> + <DesktopLeftNav /> + <DesktopRightNav /> + <View style={[styles.viewBorder, styles.viewBorderLeft]} /> + <View style={[styles.viewBorder, styles.viewBorderRight]} /> + </> + )} <Composer active={store.shell.isComposerActive} onClose={() => store.shell.closeComposer()} @@ -34,8 +42,18 @@ const ShellInner = observer(() => { quote={store.shell.composerOpts?.quote} onPost={store.shell.composerOpts?.onPost} /> + {!isDesktop && <BottomBarWeb />} <ModalsContainer /> <Lightbox /> + {!isDesktop && store.shell.isDrawerOpen && ( + <TouchableOpacity + onPress={() => store.shell.closeDrawer()} + style={styles.drawerMask}> + <View style={styles.drawerContainer}> + <DrawerContent /> + </View> + </TouchableOpacity> + )} </> ) }) @@ -71,4 +89,19 @@ const styles = StyleSheet.create({ viewBorderRight: { left: 'calc(50vw + 300px)', }, + drawerMask: { + position: 'absolute', + width: '100%', + height: '100%', + top: 0, + left: 0, + backgroundColor: 'rgba(0,0,0,0.25)', + }, + drawerContainer: { + display: 'flex', + position: 'absolute', + top: 0, + left: 0, + height: '100%', + }, }) |