diff --git a/apps/mobile/src/modules/entry-list/index.tsx b/apps/mobile/src/modules/entry-list/index.tsx index 650284b82..7b559d0f0 100644 --- a/apps/mobile/src/modules/entry-list/index.tsx +++ b/apps/mobile/src/modules/entry-list/index.tsx @@ -1,7 +1,7 @@ import { FeedViewType } from "@follow/constants" import { useIsFocused } from "@react-navigation/native" import { useEffect, useMemo } from "react" -import { Animated, StyleSheet, View } from "react-native" +import { Animated, StyleSheet } from "react-native" import PagerView from "react-native-pager-view" import { views } from "@/src/constants/views" @@ -19,7 +19,7 @@ import { } from "@/src/store/entry/hooks" import { useListEntryIds } from "@/src/store/list/hooks" -import { TimelineSelectorHeader } from "../screen/TimelineSelectorHeader" +import { TimelineSelectorProvider } from "../screen/TimelineSelectorProvider" import { EntryListSelector } from "./EntryListSelector" import { usePagerView } from "./usePagerView" @@ -35,26 +35,30 @@ export function EntryList() { }, [setDrawerSwipeDisabled, isFocused]) const selectedFeed = useSelectedFeed() - if (!selectedFeed) return null - switch (selectedFeed.type) { - case "view": { - return + const Content = useMemo(() => { + if (!selectedFeed) return null + switch (selectedFeed.type) { + case "view": { + return + } + case "feed": { + return + } + case "category": { + return + } + case "list": { + return + } + case "inbox": { + return + } } - case "feed": { - return - } - case "category": { - return - } - case "list": { - return - } - case "inbox": { - return - } - // No default - } + }, [selectedFeed]) + if (!Content) return null + + return {Content} } const AnimatedPagerView = Animated.createAnimatedComponent(PagerView) @@ -73,33 +77,21 @@ function ViewPagerList({ viewId }: { viewId: FeedViewType }) { }, [page, pagerRef, viewId]) return ( - - - - {useMemo( - () => - views.map((view) => ( - - - - )), - [], - )} - - - + + {useMemo(() => views.map((view) => ), [])} + ) } diff --git a/apps/mobile/src/modules/entry-list/templates/EntryGridItem.tsx b/apps/mobile/src/modules/entry-list/templates/EntryGridItem.tsx index 93821103e..567b68e2a 100644 --- a/apps/mobile/src/modules/entry-list/templates/EntryGridItem.tsx +++ b/apps/mobile/src/modules/entry-list/templates/EntryGridItem.tsx @@ -74,6 +74,7 @@ export function EntryGridItem(props: MasonryItem) { } case "video": { const { videoPreviewImageUrl } = props + return ( <> {videoPreviewImageUrl ? ( diff --git a/apps/mobile/src/modules/screen/TimelineSelectorList.tsx b/apps/mobile/src/modules/screen/TimelineSelectorList.tsx index 499b176db..7f61f89ed 100644 --- a/apps/mobile/src/modules/screen/TimelineSelectorList.tsx +++ b/apps/mobile/src/modules/screen/TimelineSelectorList.tsx @@ -27,13 +27,15 @@ export const TimelineSelectorList = forwardRef< const insets = useSafeAreaInsets() const headerHeight = useHeaderHeight() - const scrollY = useContext(NavigationContext)?.scrollY + const { scrollY } = useContext(NavigationContext)! const onScroll = useCallback( (e: NativeSyntheticEvent) => { + props.onScroll?.(e) + scrollY?.setValue(e.nativeEvent.contentOffset.y) }, - [scrollY], + [scrollY, props.onScroll], ) const tabBarHeight = useBottomTabBarHeight() @@ -56,7 +58,6 @@ export const TimelineSelectorList = forwardRef< refreshing={isRefetching} /> } - onScroll={onScroll} scrollIndicatorInsets={{ top: headerHeight - insets.top, bottom: tabBarHeight ? tabBarHeight - insets.bottom : undefined, @@ -66,6 +67,7 @@ export const TimelineSelectorList = forwardRef< paddingBottom: tabBarHeight, }} {...props} + onScroll={onScroll} /> ) }) @@ -85,9 +87,10 @@ export const TimelineSelectorMasonryList = ({ const onScroll = useCallback( (e: NativeSyntheticEvent) => { + props.onScroll?.(e) scrollY?.setValue(e.nativeEvent.contentOffset.y) }, - [scrollY], + [scrollY, props.onScroll], ) const tabBarHeight = useBottomTabBarHeight() @@ -109,7 +112,6 @@ export const TimelineSelectorMasonryList = ({ refreshing={isRefetching} /> } - onScroll={onScroll} scrollIndicatorInsets={{ top: headerHeight - insets.top, bottom: tabBarHeight ? tabBarHeight - insets.bottom : undefined, @@ -119,6 +121,7 @@ export const TimelineSelectorMasonryList = ({ paddingBottom: tabBarHeight, }} {...props} + onScroll={onScroll} /> ) } diff --git a/apps/mobile/src/modules/screen/TimelineSelectorHeader.tsx b/apps/mobile/src/modules/screen/TimelineSelectorProvider.tsx similarity index 97% rename from apps/mobile/src/modules/screen/TimelineSelectorHeader.tsx rename to apps/mobile/src/modules/screen/TimelineSelectorProvider.tsx index 5bcb85823..63755e379 100644 --- a/apps/mobile/src/modules/screen/TimelineSelectorHeader.tsx +++ b/apps/mobile/src/modules/screen/TimelineSelectorProvider.tsx @@ -22,7 +22,7 @@ import { getFeed } from "@/src/store/feed/getter" import { useEntryListContext, useSelectedFeedTitle, useSelectedView } from "./atoms" -export function TimelineSelectorHeader({ children }: { children: React.ReactNode }) { +export function TimelineSelectorProvider({ children }: { children: React.ReactNode }) { const scrollY = useAnimatedValue(0) const viewTitle = useSelectedFeedTitle() const screenType = useEntryListContext().type diff --git a/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx b/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx index 464402552..37547c99a 100644 --- a/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx +++ b/apps/mobile/src/screens/(stack)/(tabs)/_layout.tsx @@ -22,7 +22,6 @@ import { Search3CuteFiIcon } from "@/src/icons/search_3_cute_fi" import { Search3CuteReIcon } from "@/src/icons/search_3_cute_re" import { Settings1CuteFiIcon } from "@/src/icons/settings_1_cute_fi" import { Settings1CuteReIcon } from "@/src/icons/settings_1_cute_re" -import { FeedDrawer } from "@/src/modules/feed-drawer/drawer" import { useColor } from "@/src/theme/colors" const fifthTap = Gesture.Tap() @@ -46,112 +45,110 @@ export default function TabLayout() { }, [animatedTransformY, tabBarVisible]) return ( - - ({ opacity }), [opacity])}> - - { - opacity.value = 1 + ({ opacity }), [opacity])}> + + { + opacity.value = 1 + }, + transitionStart: () => { + opacity.value = 1 + }, + }} + screenOptions={{ + tabBarBackground: TabBarBackground, + tabBarStyle: { + position: "absolute", + borderTopWidth: 0, + transform: [ + { + translateY: animatedTransformY.interpolate({ + inputRange: [0, 1], + outputRange: [100, 0], + }), + }, + ], + }, + animation: "fade", + transitionSpec: { + animation: "timing", + config: { + duration: 50, + easing: Easing.ease, }, - transitionStart: () => { - opacity.value = 1 + }, + }} + > + { + const Icon = !focused ? Home5CuteReIcon : Home5CuteFiIcon + return + }, + tabBarButton(props) { + return }, }} - screenOptions={{ - tabBarBackground: TabBarBackground, - tabBarStyle: { - position: "absolute", - borderTopWidth: 0, - transform: [ - { - translateY: animatedTransformY.interpolate({ - inputRange: [0, 1], - outputRange: [100, 0], - }), - }, - ], + /> + { + const Icon = !focused ? BlackBoard2CuteReIcon : BlackBoard2CuteFiIcon + return }, - animation: "fade", - transitionSpec: { - animation: "timing", - config: { - duration: 50, - easing: Easing.ease, - }, + tabBarLabel: "Subscriptions", + + tabBarButton(props) { + return }, }} - > - { - const Icon = !focused ? Home5CuteReIcon : Home5CuteFiIcon - return - }, - tabBarButton(props) { - return - }, - }} - /> - { - const Icon = !focused ? BlackBoard2CuteReIcon : BlackBoard2CuteFiIcon - return - }, - tabBarLabel: "Subscriptions", + /> + { + const Icon = !focused ? Search3CuteReIcon : Search3CuteFiIcon + return + }, + tabBarButton(props) { + return + }, + }} + /> - tabBarButton(props) { - return - }, - }} - /> - { - const Icon = !focused ? Search3CuteReIcon : Search3CuteFiIcon - return - }, - tabBarButton(props) { - return - }, - }} - /> - - - - - - - ) - }, - tabBarIcon: ({ color, focused }) => { - const Icon = !focused ? Settings1CuteReIcon : Settings1CuteFiIcon - return - }, - }} - /> - - - - + + + + + + ) + }, + tabBarIcon: ({ color, focused }) => { + const Icon = !focused ? Settings1CuteReIcon : Settings1CuteFiIcon + return + }, + }} + /> + + + ) } diff --git a/apps/mobile/src/screens/(stack)/(tabs)/subscriptions.tsx b/apps/mobile/src/screens/(stack)/(tabs)/subscriptions.tsx index be9796277..a467e3c08 100644 --- a/apps/mobile/src/screens/(stack)/(tabs)/subscriptions.tsx +++ b/apps/mobile/src/screens/(stack)/(tabs)/subscriptions.tsx @@ -1,5 +1,5 @@ import { useSelectedFeed } from "@/src/modules/screen/atoms" -import { TimelineSelectorHeader } from "@/src/modules/screen/TimelineSelectorHeader" +import { TimelineSelectorProvider } from "@/src/modules/screen/TimelineSelectorProvider" import { SubscriptionList } from "@/src/modules/subscription/SubscriptionLists" export default function Subscriptions() { @@ -7,8 +7,8 @@ export default function Subscriptions() { const view = selectedFeed?.type === "view" ? selectedFeed.viewId : undefined return ( - + - + ) } diff --git a/apps/mobile/src/screens/(stack)/feeds/[feedId]/index.tsx b/apps/mobile/src/screens/(stack)/feeds/[feedId]/index.tsx index 36ee35b32..e256090d8 100644 --- a/apps/mobile/src/screens/(stack)/feeds/[feedId]/index.tsx +++ b/apps/mobile/src/screens/(stack)/feeds/[feedId]/index.tsx @@ -6,7 +6,7 @@ import { useSafeAreaInsets } from "react-native-safe-area-context" import { EntryListSelector } from "@/src/modules/entry-list/EntryListSelector" import { EntryListContext, useSelectedView } from "@/src/modules/screen/atoms" -import { TimelineSelectorHeader } from "@/src/modules/screen/TimelineSelectorHeader" +import { TimelineSelectorProvider } from "@/src/modules/screen/TimelineSelectorProvider" import { useCollectionEntryList } from "@/src/store/collection/hooks" import { useEntryIdsByCategory, useEntryIdsByFeedId } from "@/src/store/entry/hooks" import { FEED_COLLECTION_LIST } from "@/src/store/entry/utils" @@ -29,9 +29,9 @@ export default function Feed() { return ( ({ type: "feed" }), [])}> - + - + )