about summary refs log tree commit diff
path: root/src/view/screens/Home.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/screens/Home.tsx')
-rw-r--r--src/view/screens/Home.tsx360
1 files changed, 233 insertions, 127 deletions
diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx
index 6c708e2fd..fa200e931 100644
--- a/src/view/screens/Home.tsx
+++ b/src/view/screens/Home.tsx
@@ -1,15 +1,23 @@
 import React from 'react'
-import {FlatList, StyleSheet, View, useWindowDimensions} from 'react-native'
+import {
+  FlatList,
+  StyleSheet,
+  TouchableOpacity,
+  View,
+  useWindowDimensions,
+} from 'react-native'
 import {useFocusEffect, useIsFocused} from '@react-navigation/native'
 import {observer} from 'mobx-react-lite'
 import useAppState from 'react-native-appstate-hook'
 import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types'
+import {FeedModel} from 'state/models/feed-view'
 import {withAuthRequired} from 'view/com/auth/withAuthRequired'
-import {ViewHeader} from '../com/util/ViewHeader'
 import {Feed} from '../com/posts/Feed'
 import {LoadLatestBtn} from '../com/util/LoadLatestBtn'
 import {WelcomeBanner} from '../com/util/WelcomeBanner'
 import {UserAvatar} from 'view/com/util/UserAvatar'
+import {TabBar} from 'view/com/util/TabBar'
+import {Pager, PageSelectedEvent, TabBarProps} from 'view/com/util/Pager'
 import {FAB} from '../com/util/FAB'
 import {useStores} from 'state/index'
 import {usePalette} from 'lib/hooks/usePalette'
@@ -18,157 +26,255 @@ import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
 import {useAnalytics} from 'lib/analytics'
 import {ComposeIcon2} from 'lib/icons'
 
-import {Pager, PageSelectedEvent} from 'view/com/util/Pager'
-import {Text} from 'view/com/util/text/Text'
-
-const HEADER_HEIGHT = 42
+const TAB_BAR_HEIGHT = 82
 
 type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
 export const HomeScreen = withAuthRequired((_opts: Props) => {
   const store = useStores()
+  const pal = usePalette('default')
+  const [selectedPage, setSelectedPage] = React.useState(0)
+
+  useFocusEffect(
+    React.useCallback(() => {
+      store.shell.setIsDrawerSwipeDisabled(selectedPage > 0)
+      return () => {
+        store.shell.setIsDrawerSwipeDisabled(false)
+      }
+    }, [store, selectedPage]),
+  )
+
   const onPageSelected = React.useCallback(
     (e: PageSelectedEvent) => {
+      setSelectedPage(e.nativeEvent.position)
       store.shell.setIsDrawerSwipeDisabled(e.nativeEvent.position > 0)
     },
     [store],
   )
 
+  const onPressAvi = React.useCallback(() => {
+    store.shell.openDrawer()
+  }, [store])
+
+  const renderTabBar = React.useCallback(
+    (props: TabBarProps) => {
+      return (
+        <View style={[pal.view, styles.tabBar]}>
+          <TouchableOpacity style={styles.tabBarAvi} onPress={onPressAvi}>
+            <UserAvatar avatar={store.me.avatar} size={32} />
+          </TouchableOpacity>
+          <TabBar items={['Popular', 'Following']} {...props} />
+        </View>
+      )
+    },
+    [store.me.avatar, pal, onPressAvi],
+  )
+
+  return (
+    <Pager onPageSelected={onPageSelected} renderTabBar={renderTabBar}>
+      <AlgoView key="1" />
+      <View key="2">
+        <FollowingView />
+      </View>
+    </Pager>
+  )
+})
+
+const AlgoView = observer(() => {
+  const store = useStores()
+  const onMainScroll = useOnMainScroll(store)
+  const {screen, track} = useAnalytics()
+  const scrollElRef = React.useRef<FlatList>(null)
+  const {appState} = useAppState({
+    onForeground: () => doPoll(true),
+  })
+  const isFocused = useIsFocused()
+  const winDim = useWindowDimensions()
+  const containerStyle = React.useMemo(
+    () => ({height: winDim.height - TAB_BAR_HEIGHT}),
+    [winDim],
+  )
+  const algoFeed = React.useMemo(() => {
+    const feed = new FeedModel(store, 'goodstuff', {})
+    feed.setup()
+    return feed
+  }, [store])
+
+  const doPoll = React.useCallback(
+    (knownActive = false) => {
+      if ((!knownActive && appState !== 'active') || !isFocused) {
+        return
+      }
+      if (algoFeed.isLoading) {
+        return
+      }
+      store.log.debug('HomeScreen: Polling for new posts')
+      algoFeed.checkForLatest()
+    },
+    [appState, isFocused, store, algoFeed],
+  )
+
+  const scrollToTop = React.useCallback(() => {
+    scrollElRef.current?.scrollToOffset({offset: 0})
+  }, [scrollElRef])
+
   useFocusEffect(
     React.useCallback(() => {
+      const softResetSub = store.onScreenSoftReset(scrollToTop)
+      const feedCleanup = algoFeed.registerListeners()
+      const pollInterval = setInterval(doPoll, 15e3)
+
+      screen('Feed')
+      store.log.debug('HomeScreen: Updating feed')
+      if (algoFeed.hasContent) {
+        algoFeed.update()
+      }
+
       return () => {
-        store.shell.setIsDrawerSwipeDisabled(false)
+        clearInterval(pollInterval)
+        softResetSub.remove()
+        feedCleanup()
       }
-    }, [store]),
+    }, [store, doPoll, scrollToTop, screen, algoFeed]),
   )
 
+  const onPressCompose = React.useCallback(() => {
+    track('HomeScreen:PressCompose')
+    store.shell.openComposer({})
+  }, [store, track])
+
+  const onPressTryAgain = React.useCallback(() => {
+    algoFeed.refresh()
+  }, [algoFeed])
+
+  const onPressLoadLatest = React.useCallback(() => {
+    algoFeed.refresh()
+    scrollToTop()
+  }, [algoFeed, scrollToTop])
+
   return (
-    <Pager onPageSelected={onPageSelected}>
-      <View key="1">
-        <MyPage>First page</MyPage>
-      </View>
-      <View key="2">
-        <MyPage>Second page</MyPage>
-      </View>
-      <View key="3">
-        <MyPage>Third page</MyPage>
-      </View>
-    </Pager>
+    <View style={containerStyle}>
+      {store.shell.isOnboarding && <WelcomeBanner />}
+      <Feed
+        testID="homeFeed"
+        key="default"
+        feed={algoFeed}
+        scrollElRef={scrollElRef}
+        style={s.hContentRegion}
+        showPostFollowBtn
+        onPressTryAgain={onPressTryAgain}
+        onScroll={onMainScroll}
+      />
+      {algoFeed.hasNewLatest && !algoFeed.isRefreshing && (
+        <LoadLatestBtn onPress={onPressLoadLatest} />
+      )}
+      <FAB
+        testID="composeFAB"
+        onPress={onPressCompose}
+        icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
+      />
+    </View>
   )
 })
-function MyPage({children}) {
+
+const FollowingView = observer(() => {
+  const store = useStores()
+  const onMainScroll = useOnMainScroll(store)
+  const {screen, track} = useAnalytics()
+  const scrollElRef = React.useRef<FlatList>(null)
+  const {appState} = useAppState({
+    onForeground: () => doPoll(true),
+  })
+  const isFocused = useIsFocused()
+  const winDim = useWindowDimensions()
+  const containerStyle = React.useMemo(
+    () => ({height: winDim.height - TAB_BAR_HEIGHT}),
+    [winDim],
+  )
+
+  const doPoll = React.useCallback(
+    (knownActive = false) => {
+      if ((!knownActive && appState !== 'active') || !isFocused) {
+        return
+      }
+      if (store.me.mainFeed.isLoading) {
+        return
+      }
+      store.log.debug('HomeScreen: Polling for new posts')
+      store.me.mainFeed.checkForLatest()
+    },
+    [appState, isFocused, store],
+  )
+
+  const scrollToTop = React.useCallback(() => {
+    scrollElRef.current?.scrollToOffset({offset: 0})
+  }, [scrollElRef])
+
+  useFocusEffect(
+    React.useCallback(() => {
+      const softResetSub = store.onScreenSoftReset(scrollToTop)
+      const feedCleanup = store.me.mainFeed.registerListeners()
+      const pollInterval = setInterval(doPoll, 15e3)
+
+      screen('Feed')
+      store.log.debug('HomeScreen: Updating feed')
+      if (store.me.mainFeed.hasContent) {
+        store.me.mainFeed.update()
+      }
+
+      return () => {
+        clearInterval(pollInterval)
+        softResetSub.remove()
+        feedCleanup()
+      }
+    }, [store, doPoll, scrollToTop, screen]),
+  )
+
+  const onPressCompose = React.useCallback(() => {
+    track('HomeScreen:PressCompose')
+    store.shell.openComposer({})
+  }, [store, track])
+
+  const onPressTryAgain = React.useCallback(() => {
+    store.me.mainFeed.refresh()
+  }, [store])
+
+  const onPressLoadLatest = React.useCallback(() => {
+    store.me.mainFeed.refresh()
+    scrollToTop()
+  }, [store, scrollToTop])
+
   return (
-    <View
-      style={{
-        flex: 1,
-        justifyContent: 'center',
-        alignItems: 'center',
-        borderWidth: 1,
-        backgroundColor: 'white',
-      }}>
-      <Text>{children}</Text>
+    <View style={containerStyle}>
+      {store.shell.isOnboarding && <WelcomeBanner />}
+      <Feed
+        testID="homeFeed"
+        key="default"
+        feed={store.me.mainFeed}
+        scrollElRef={scrollElRef}
+        style={s.hContentRegion}
+        showPostFollowBtn
+        onPressTryAgain={onPressTryAgain}
+        onScroll={onMainScroll}
+      />
+      {store.me.mainFeed.hasNewLatest && !store.me.mainFeed.isRefreshing && (
+        <LoadLatestBtn onPress={onPressLoadLatest} />
+      )}
+      <FAB
+        testID="composeFAB"
+        onPress={onPressCompose}
+        icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
+      />
     </View>
   )
-}
+})
 
 const styles = StyleSheet.create({
   tabBar: {
     flexDirection: 'row',
+    alignItems: 'center',
+    paddingHorizontal: 18,
+  },
+  tabBarAvi: {
+    marginRight: 16,
   },
 })
-/*
-type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
-export const HomeScreen = withAuthRequired(
-  observer(function Home(_opts: Props) {
-    const store = useStores()
-    const onMainScroll = useOnMainScroll(store)
-    const {screen, track} = useAnalytics()
-    const scrollElRef = React.useRef<FlatList>(null)
-    const {appState} = useAppState({
-      onForeground: () => doPoll(true),
-    })
-    const isFocused = useIsFocused()
-
-    const doPoll = React.useCallback(
-      (knownActive = false) => {
-        if ((!knownActive && appState !== 'active') || !isFocused) {
-          return
-        }
-        if (store.me.mainFeed.isLoading) {
-          return
-        }
-        store.log.debug('HomeScreen: Polling for new posts')
-        store.me.mainFeed.checkForLatest()
-      },
-      [appState, isFocused, store],
-    )
-
-    const scrollToTop = React.useCallback(() => {
-      // NOTE: the feed is offset by the height of the collapsing header,
-      //       so we scroll to the negative of that height -prf
-      scrollElRef.current?.scrollToOffset({offset: -HEADER_HEIGHT})
-    }, [scrollElRef])
-
-    useFocusEffect(
-      React.useCallback(() => {
-        const softResetSub = store.onScreenSoftReset(scrollToTop)
-        const feedCleanup = store.me.mainFeed.registerListeners()
-        const pollInterval = setInterval(doPoll, 15e3)
-
-        screen('Feed')
-        store.log.debug('HomeScreen: Updating feed')
-        if (store.me.mainFeed.hasContent) {
-          store.me.mainFeed.update()
-        }
-
-        return () => {
-          clearInterval(pollInterval)
-          softResetSub.remove()
-          feedCleanup()
-        }
-      }, [store, doPoll, scrollToTop, screen]),
-    )
-
-    const onPressCompose = React.useCallback(() => {
-      track('HomeScreen:PressCompose')
-      store.shell.openComposer({})
-    }, [store, track])
-
-    const onPressTryAgain = React.useCallback(() => {
-      store.me.mainFeed.refresh()
-    }, [store])
-
-    const onPressLoadLatest = React.useCallback(() => {
-      store.me.mainFeed.refresh()
-      scrollToTop()
-    }, [store, scrollToTop])
-
-    return (
-      <View style={s.hContentRegion}>
-        {store.shell.isOnboarding && <WelcomeBanner />}
-        <Feed
-          testID="homeFeed"
-          key="default"
-          feed={store.me.mainFeed}
-          scrollElRef={scrollElRef}
-          style={s.hContentRegion}
-          showPostFollowBtn
-          onPressTryAgain={onPressTryAgain}
-          onScroll={onMainScroll}
-          headerOffset={store.shell.isOnboarding ? 0 : HEADER_HEIGHT}
-        />
-        {!store.shell.isOnboarding && (
-          <ViewHeader title="Bluesky" canGoBack={false} hideOnScroll />
-        )}
-        {store.me.mainFeed.hasNewLatest && !store.me.mainFeed.isRefreshing && (
-          <LoadLatestBtn onPress={onPressLoadLatest} />
-        )}
-        <FAB
-          testID="composeFAB"
-          onPress={onPressCompose}
-          icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />}
-        />
-      </View>
-    )
-  }),
-)
-*/