about summary refs log tree commit diff
path: root/src/view/com/home
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/home')
-rw-r--r--src/view/com/home/HomeHeader.tsx71
-rw-r--r--src/view/com/home/HomeHeaderLayout.tsx1
-rw-r--r--src/view/com/home/HomeHeaderLayout.web.tsx50
-rw-r--r--src/view/com/home/HomeHeaderLayoutMobile.tsx119
4 files changed, 241 insertions, 0 deletions
diff --git a/src/view/com/home/HomeHeader.tsx b/src/view/com/home/HomeHeader.tsx
new file mode 100644
index 000000000..5ffa31f39
--- /dev/null
+++ b/src/view/com/home/HomeHeader.tsx
@@ -0,0 +1,71 @@
+import React from 'react'
+import {RenderTabBarFnProps} from 'view/com/pager/Pager'
+import {HomeHeaderLayout} from './HomeHeaderLayout'
+import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {usePinnedFeedsInfos} from '#/state/queries/feed'
+import {useNavigation} from '@react-navigation/native'
+import {NavigationProp} from 'lib/routes/types'
+import {isWeb} from 'platform/detection'
+import {TabBar} from '../pager/TabBar'
+import {usePalette} from '#/lib/hooks/usePalette'
+
+export function HomeHeader(
+  props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
+) {
+  const {isDesktop} = useWebMediaQueries()
+  if (isDesktop) {
+    return null
+  }
+  return <HomeHeaderInner {...props} />
+}
+
+export function HomeHeaderInner(
+  props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
+) {
+  const navigation = useNavigation<NavigationProp>()
+  const {feeds, hasPinnedCustom} = usePinnedFeedsInfos()
+  const pal = usePalette('default')
+
+  const items = React.useMemo(() => {
+    const pinnedNames = feeds.map(f => f.displayName)
+
+    if (!hasPinnedCustom) {
+      return pinnedNames.concat('Feeds ✨')
+    }
+    return pinnedNames
+  }, [hasPinnedCustom, feeds])
+
+  const onPressFeedsLink = React.useCallback(() => {
+    if (isWeb) {
+      navigation.navigate('Feeds')
+    } else {
+      navigation.navigate('FeedsTab')
+      navigation.popToTop()
+    }
+  }, [navigation])
+
+  const onSelect = React.useCallback(
+    (index: number) => {
+      if (!hasPinnedCustom && index === items.length - 1) {
+        onPressFeedsLink()
+      } else if (props.onSelect) {
+        props.onSelect(index)
+      }
+    },
+    [items.length, onPressFeedsLink, props, hasPinnedCustom],
+  )
+
+  return (
+    <HomeHeaderLayout>
+      <TabBar
+        key={items.join(',')}
+        onPressSelected={props.onPressSelected}
+        selectedPage={props.selectedPage}
+        onSelect={onSelect}
+        testID={props.testID}
+        items={items}
+        indicatorColor={pal.colors.link}
+      />
+    </HomeHeaderLayout>
+  )
+}
diff --git a/src/view/com/home/HomeHeaderLayout.tsx b/src/view/com/home/HomeHeaderLayout.tsx
new file mode 100644
index 000000000..70bf064d4
--- /dev/null
+++ b/src/view/com/home/HomeHeaderLayout.tsx
@@ -0,0 +1 @@
+export {HomeHeaderLayoutMobile as HomeHeaderLayout} from './HomeHeaderLayoutMobile'
diff --git a/src/view/com/home/HomeHeaderLayout.web.tsx b/src/view/com/home/HomeHeaderLayout.web.tsx
new file mode 100644
index 000000000..47cb00235
--- /dev/null
+++ b/src/view/com/home/HomeHeaderLayout.web.tsx
@@ -0,0 +1,50 @@
+import React from 'react'
+import {StyleSheet} from 'react-native'
+import Animated from 'react-native-reanimated'
+import {usePalette} from 'lib/hooks/usePalette'
+import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {HomeHeaderLayoutMobile} from './HomeHeaderLayoutMobile'
+import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
+import {useShellLayout} from '#/state/shell/shell-layout'
+
+export function HomeHeaderLayout({children}: {children: React.ReactNode}) {
+  const {isMobile} = useWebMediaQueries()
+  if (isMobile) {
+    return <HomeHeaderLayoutMobile>{children}</HomeHeaderLayoutMobile>
+  } else {
+    return <HomeHeaderLayoutTablet>{children}</HomeHeaderLayoutTablet>
+  }
+}
+
+function HomeHeaderLayoutTablet({children}: {children: React.ReactNode}) {
+  const pal = usePalette('default')
+  const {headerMinimalShellTransform} = useMinimalShellMode()
+  const {headerHeight} = useShellLayout()
+
+  return (
+    // @ts-ignore the type signature for transform wrong here, translateX and translateY need to be in separate objects -prf
+    <Animated.View
+      style={[pal.view, pal.border, styles.tabBar, headerMinimalShellTransform]}
+      onLayout={e => {
+        headerHeight.value = e.nativeEvent.layout.height
+      }}>
+      {children}
+    </Animated.View>
+  )
+}
+
+const styles = StyleSheet.create({
+  tabBar: {
+    // @ts-ignore Web only
+    position: 'sticky',
+    zIndex: 1,
+    // @ts-ignore Web only -prf
+    left: 'calc(50% - 300px)',
+    width: 600,
+    top: 0,
+    flexDirection: 'row',
+    alignItems: 'center',
+    borderLeftWidth: 1,
+    borderRightWidth: 1,
+  },
+})
diff --git a/src/view/com/home/HomeHeaderLayoutMobile.tsx b/src/view/com/home/HomeHeaderLayoutMobile.tsx
new file mode 100644
index 000000000..0478f69a4
--- /dev/null
+++ b/src/view/com/home/HomeHeaderLayoutMobile.tsx
@@ -0,0 +1,119 @@
+import React from 'react'
+import {StyleSheet, TouchableOpacity, View} from 'react-native'
+import {usePalette} from 'lib/hooks/usePalette'
+import {Link} from '../util/Link'
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
+import {HITSLOP_10} from 'lib/constants'
+import Animated from 'react-native-reanimated'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
+import {useSetDrawerOpen} from '#/state/shell/drawer-open'
+import {useShellLayout} from '#/state/shell/shell-layout'
+import {isWeb} from 'platform/detection'
+import {Logo} from '#/view/icons/Logo'
+
+import {IS_DEV} from '#/env'
+import {atoms} from '#/alf'
+import {Link as Link2} from '#/components/Link'
+import {ColorPalette_Stroke2_Corner0_Rounded as ColorPalette} from '#/components/icons/ColorPalette'
+
+export function HomeHeaderLayoutMobile({
+  children,
+}: {
+  children: React.ReactNode
+}) {
+  const pal = usePalette('default')
+  const {_} = useLingui()
+  const setDrawerOpen = useSetDrawerOpen()
+  const {headerHeight} = useShellLayout()
+  const {headerMinimalShellTransform} = useMinimalShellMode()
+
+  const onPressAvi = React.useCallback(() => {
+    setDrawerOpen(true)
+  }, [setDrawerOpen])
+
+  return (
+    <Animated.View
+      style={[pal.view, pal.border, styles.tabBar, headerMinimalShellTransform]}
+      onLayout={e => {
+        headerHeight.value = e.nativeEvent.layout.height
+      }}>
+      <View style={[pal.view, styles.topBar]}>
+        <View style={[pal.view, {width: 100}]}>
+          <TouchableOpacity
+            testID="viewHeaderDrawerBtn"
+            onPress={onPressAvi}
+            accessibilityRole="button"
+            accessibilityLabel={_(msg`Open navigation`)}
+            accessibilityHint={_(
+              msg`Access profile and other navigation links`,
+            )}
+            hitSlop={HITSLOP_10}>
+            <FontAwesomeIcon
+              icon="bars"
+              size={18}
+              color={pal.colors.textLight}
+            />
+          </TouchableOpacity>
+        </View>
+        <View>
+          <Logo width={30} />
+        </View>
+        <View
+          style={[
+            atoms.flex_row,
+            atoms.justify_end,
+            atoms.align_center,
+            atoms.gap_md,
+            pal.view,
+            {width: 100},
+          ]}>
+          {IS_DEV && (
+            <Link2 to="/sys/debug">
+              <ColorPalette size="md" />
+            </Link2>
+          )}
+          <Link
+            testID="viewHeaderHomeFeedPrefsBtn"
+            href="/settings/home-feed"
+            hitSlop={HITSLOP_10}
+            accessibilityRole="button"
+            accessibilityLabel={_(msg`Home Feed Preferences`)}
+            accessibilityHint="">
+            <FontAwesomeIcon
+              icon="sliders"
+              style={pal.textLight as FontAwesomeIconStyle}
+            />
+          </Link>
+        </View>
+      </View>
+      {children}
+    </Animated.View>
+  )
+}
+
+const styles = StyleSheet.create({
+  tabBar: {
+    // @ts-ignore web-only
+    position: isWeb ? 'fixed' : 'absolute',
+    zIndex: 1,
+    left: 0,
+    right: 0,
+    top: 0,
+    flexDirection: 'column',
+    borderBottomWidth: 1,
+  },
+  topBar: {
+    flexDirection: 'row',
+    justifyContent: 'space-between',
+    alignItems: 'center',
+    paddingHorizontal: 18,
+    paddingVertical: 8,
+    width: '100%',
+  },
+  title: {
+    fontSize: 21,
+  },
+})