From 129fc42e95605617e4dd6509a0458a2b66527ad0 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Wed, 17 May 2023 23:32:19 -0500 Subject: [PATCH] Improve pinned feed management --- src/state/models/ui/saved-feeds.ts | 2 +- src/view/com/pager/Pager.tsx | 125 ++++++++++++++--------------- src/view/screens/Home.tsx | 23 +++++- 3 files changed, 79 insertions(+), 71 deletions(-) diff --git a/src/state/models/ui/saved-feeds.ts b/src/state/models/ui/saved-feeds.ts index 50bb1b8715..d68664c2d8 100644 --- a/src/state/models/ui/saved-feeds.ts +++ b/src/state/models/ui/saved-feeds.ts @@ -81,7 +81,7 @@ export class SavedFeedsModel { togglePinnedFeed(feed: CustomFeedModel) { if (!this.isPinned(feed)) { - this.pinned.push(feed) + this.pinned = [...this.pinned, feed] } else { this.removePinnedFeed(feed.data.uri) } diff --git a/src/view/com/pager/Pager.tsx b/src/view/com/pager/Pager.tsx index 34747db6dd..e2c8bf6d2c 100644 --- a/src/view/com/pager/Pager.tsx +++ b/src/view/com/pager/Pager.tsx @@ -1,16 +1,17 @@ -import React from 'react' +import React, {forwardRef} from 'react' import {Animated, View} from 'react-native' import PagerView, {PagerViewOnPageSelectedEvent} from 'react-native-pager-view' -import {useAnimatedValue} from 'lib/hooks/useAnimatedValue' import {s} from 'lib/styles' export type PageSelectedEvent = PagerViewOnPageSelectedEvent const AnimatedPagerView = Animated.createAnimatedComponent(PagerView) +export interface PagerRef { + setPage: (index: number) => void +} + export interface RenderTabBarFnProps { selectedPage: number - position: Animated.Value - offset: Animated.Value onSelect?: (index: number) => void } export type RenderTabBarFn = (props: RenderTabBarFnProps) => JSX.Element @@ -22,68 +23,60 @@ interface Props { onPageSelected?: (index: number) => void testID?: string } -export const Pager = ({ - children, - tabBarPosition = 'top', - initialPage = 0, - renderTabBar, - onPageSelected, - testID, -}: React.PropsWithChildren) => { - const [selectedPage, setSelectedPage] = React.useState(0) - const position = useAnimatedValue(0) - const offset = useAnimatedValue(0) - const pagerView = React.useRef() +export const Pager = forwardRef>( + ( + { + children, + tabBarPosition = 'top', + initialPage = 0, + renderTabBar, + onPageSelected, + testID, + }: React.PropsWithChildren, + ref, + ) => { + const [selectedPage, setSelectedPage] = React.useState(0) + const pagerView = React.useRef() - const onPageSelectedInner = React.useCallback( - (e: PageSelectedEvent) => { - setSelectedPage(e.nativeEvent.position) - onPageSelected?.(e.nativeEvent.position) - }, - [setSelectedPage, onPageSelected], - ) + React.useImperativeHandle(ref, () => ({ + setPage: (index: number) => pagerView.current?.setPage(index), + })) - const onTabBarSelect = React.useCallback( - (index: number) => { - pagerView.current?.setPage(index) - }, - [pagerView], - ) + const onPageSelectedInner = React.useCallback( + (e: PageSelectedEvent) => { + setSelectedPage(e.nativeEvent.position) + onPageSelected?.(e.nativeEvent.position) + }, + [setSelectedPage, onPageSelected], + ) - return ( - - {tabBarPosition === 'top' && - renderTabBar({ - selectedPage, - position, - offset, - onSelect: onTabBarSelect, - })} - - {children} - - {tabBarPosition === 'bottom' && - renderTabBar({ - selectedPage, - position, - offset, - onSelect: onTabBarSelect, - })} - - ) -} + const onTabBarSelect = React.useCallback( + (index: number) => { + pagerView.current?.setPage(index) + }, + [pagerView], + ) + + return ( + + {tabBarPosition === 'top' && + renderTabBar({ + selectedPage, + onSelect: onTabBarSelect, + })} + + {children} + + {tabBarPosition === 'bottom' && + renderTabBar({ + selectedPage, + onSelect: onTabBarSelect, + })} + + ) + }, +) diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index 9be4a47942..644182126a 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -1,6 +1,7 @@ import React from 'react' import {FlatList, View} from 'react-native' import {useFocusEffect, useIsFocused} from '@react-navigation/native' +import {AppBskyFeedGetFeed as GetCustomFeed} from '@atproto/api' import {observer} from 'mobx-react-lite' import useAppState from 'react-native-appstate-hook' import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types' @@ -12,7 +13,7 @@ import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState' import {WhatsHotEmptyState} from 'view/com/posts/WhatsHotEmptyState' import {LoadLatestBtn} from '../com/util/load-latest/LoadLatestBtn' import {FeedsTabBar} from '../com/pager/FeedsTabBar' -import {Pager, RenderTabBarFnProps} from 'view/com/pager/Pager' +import {Pager, PagerRef, RenderTabBarFnProps} from 'view/com/pager/Pager' import {FAB} from '../com/util/fab/FAB' import {SavedFeeds} from 'view/com/feeds/SavedFeeds' import {useStores} from 'state/index' @@ -29,7 +30,9 @@ type Props = NativeStackScreenProps export const HomeScreen = withAuthRequired( observer((_opts: Props) => { const store = useStores() + const pagerRef = React.useRef(null) const [selectedPage, setSelectedPage] = React.useState(0) + const [customFeeds, setCustomFeeds] = React.useState([]) const [initialLanguages] = React.useState( store.preferences.contentLanguages, ) @@ -40,6 +43,17 @@ export const HomeScreen = withAuthRequired( return feed }, [store]) + React.useEffect(() => { + const feeds = [] + for (const feed of store.me.savedFeeds.pinned) { + const model = new PostsFeedModel(store, 'custom', {feed: feed.uri}) + model.setup() + feeds.push(model) + } + pagerRef.current?.setPage(0) + setCustomFeeds(feeds) + }, [store, store.me.savedFeeds.pinned, setCustomFeeds]) + React.useEffect(() => { // refresh whats hot when lang preferences change if (initialLanguages !== store.preferences.contentLanguages) { @@ -94,6 +108,7 @@ export const HomeScreen = withAuthRequired( const initialPage = store.me.followsCount === 0 ? 1 : 0 return ( - {store.me.savedFeeds.pinned.map((f, index) => { + {customFeeds.map((f, index) => { return ( )