diff --git a/apps/mobile/src/lib/platform.ts b/apps/mobile/src/lib/platform.ts new file mode 100644 index 000000000..b0b492f46 --- /dev/null +++ b/apps/mobile/src/lib/platform.ts @@ -0,0 +1,3 @@ +import { Platform } from "react-native" + +export const isIOS = Platform.OS === "ios" diff --git a/apps/mobile/src/modules/discover/constants.ts b/apps/mobile/src/modules/discover/constants.ts index 96e009248..39dcfb891 100644 --- a/apps/mobile/src/modules/discover/constants.ts +++ b/apps/mobile/src/modules/discover/constants.ts @@ -1,11 +1,11 @@ export enum SearchType { Feed = "feed", List = "list", - User = "user", + // User = "user", } export const SearchTabs = [ { name: "Feed", value: SearchType.Feed }, { name: "List", value: SearchType.List }, - { name: "User", value: SearchType.User }, + // { name: "User", value: SearchType.User }, ] diff --git a/apps/mobile/src/modules/feed-drawer/collection-panel.tsx b/apps/mobile/src/modules/feed-drawer/collection-panel.tsx index 78fdfd115..1b59baf8d 100644 --- a/apps/mobile/src/modules/feed-drawer/collection-panel.tsx +++ b/apps/mobile/src/modules/feed-drawer/collection-panel.tsx @@ -1,12 +1,13 @@ import { cn } from "@follow/utils" import { Image, - SafeAreaView, ScrollView, + StyleSheet, TouchableOpacity, useWindowDimensions, View, } from "react-native" +import { useSafeAreaInsets } from "react-native-safe-area-context" import { FallbackIcon } from "@/src/components/ui/icon/fallback-icon" import type { ViewDefinition } from "@/src/constants/views" @@ -20,23 +21,34 @@ export const CollectionPanel = () => { const winDim = useWindowDimensions() const lists = useAllListSubscription() + const insets = useSafeAreaInsets() return ( - - + {views.map((viewDef) => ( ))} + {lists.map((listId) => ( ))} - + ) } +const styles = StyleSheet.create({ + hairline: { + height: StyleSheet.hairlineWidth, + }, +}) + const ViewButton = ({ viewDef }: { viewDef: ViewDefinition }) => { const selectedCollection = useSelectedCollection() const isActive = selectedCollection.type === "view" && selectedCollection.viewId === viewDef.view @@ -45,7 +57,7 @@ const ViewButton = ({ viewDef }: { viewDef: ViewDefinition }) => { selectCollection({ diff --git a/apps/mobile/src/modules/feed-drawer/drawer.tsx b/apps/mobile/src/modules/feed-drawer/drawer.tsx index 9ae8ae732..7ecb4ef22 100644 --- a/apps/mobile/src/modules/feed-drawer/drawer.tsx +++ b/apps/mobile/src/modules/feed-drawer/drawer.tsx @@ -63,7 +63,7 @@ export const FeedDrawer = ({ children }: PropsWithChildren) => { const DrawerContent = () => { return ( - + diff --git a/apps/mobile/src/modules/feed-drawer/feed-panel.tsx b/apps/mobile/src/modules/feed-drawer/feed-panel.tsx index b2896fff9..e58a9c61e 100644 --- a/apps/mobile/src/modules/feed-drawer/feed-panel.tsx +++ b/apps/mobile/src/modules/feed-drawer/feed-panel.tsx @@ -1,12 +1,12 @@ -import type { FeedViewType } from "@follow/constants" import { cn } from "@follow/utils" +import { BottomTabBarHeightContext } from "@react-navigation/bottom-tabs" +import { HeaderHeightContext } from "@react-navigation/elements" import { router } from "expo-router" import type { FC } from "react" -import { createContext, memo, useContext, useMemo } from "react" +import { createContext, memo, useContext, useState } from "react" import { Animated, Easing, - SafeAreaView, ScrollView, StyleSheet, Text, @@ -23,13 +23,7 @@ import { ItemPressable } from "@/src/components/ui/pressable/item-pressable" import { MingcuteRightLine } from "@/src/icons/mingcute_right_line" import { useFeed, usePrefetchFeed } from "@/src/store/feed/hooks" import { useList } from "@/src/store/list/hooks" -import { - useGroupedSubscription, - usePrefetchSubscription, - useSortedGroupedSubscription, - useSortedUngroupedSubscription, - useSubscription, -} from "@/src/store/subscription/hooks" +import { useSortedUngroupedSubscription, useSubscription } from "@/src/store/subscription/hooks" import { useUnreadCount, useUnreadCounts } from "@/src/store/unread/hooks" import { @@ -37,40 +31,44 @@ import { SubscriptionFeedItemContextMenu, } from "../context-menu/feeds" import { useCurrentView, useFeedListSortMethod, useFeedListSortOrder } from "../subscription/atoms" +import { ViewPageCurrentViewProvider } from "../subscription/ctx" +import { SubscriptionList } from "../subscription/SubscriptionLists" import { useSelectedCollection } from "./atoms" import { ListHeaderComponent, ViewHeaderComponent } from "./header" -const useSortedSubscription = (view: FeedViewType) => { - usePrefetchSubscription(view) - const { grouped, unGrouped } = useGroupedSubscription(view) - - const sortBy = useFeedListSortMethod() - const sortOrder = useFeedListSortOrder() - const sortedGrouped = useSortedGroupedSubscription(grouped, sortBy, sortOrder) - const sortedUnGrouped = useSortedUngroupedSubscription(unGrouped, sortBy, sortOrder) - const data = useMemo( - () => [...sortedGrouped, ...sortedUnGrouped], - [sortedGrouped, sortedUnGrouped], - ) - return data -} - export const FeedPanel = () => { const selectedCollection = useSelectedCollection() + const [headerHeight, setHeaderHeight] = useState(0) + if (selectedCollection.type === "view") { return ( - - - - + + { + setHeaderHeight(e.nativeEvent.layout.height) + }} + /> + + + + + + + + + ) } return ( - + - + ) } @@ -93,23 +91,6 @@ const ListView = ({ listId }: { listId: string }) => { ) } -const FeedListView = ({ view }: { view: FeedViewType }) => { - const data = useSortedSubscription(view) - return ( - - {data.map((item, index) => ( - - ))} - {/* Just a placeholder */} - - - ) -} - const ItemRender = ({ item, }: { diff --git a/apps/mobile/src/modules/feed-drawer/header.tsx b/apps/mobile/src/modules/feed-drawer/header.tsx index 2afabd0e5..67471adc9 100644 --- a/apps/mobile/src/modules/feed-drawer/header.tsx +++ b/apps/mobile/src/modules/feed-drawer/header.tsx @@ -1,16 +1,32 @@ import type { FeedViewType } from "@follow/constants" +import type { LayoutChangeEvent } from "react-native" import { Text, View } from "react-native" +import { useSafeAreaInsets } from "react-native-safe-area-context" +import { BlurEffect } from "@/src/components/common/HeaderBlur" import { useList } from "@/src/store/list/hooks" import { SortActionButton } from "../subscription/header-actions" import { useViewDefinition } from "./atoms" -export const ViewHeaderComponent = ({ view }: { view: FeedViewType }) => { +export const ViewHeaderComponent = ({ + view, + onLayout, +}: { + view: FeedViewType + onLayout?: (event: LayoutChangeEvent) => void +}) => { const viewDef = useViewDefinition(view) + const insets = useSafeAreaInsets() + return ( - - {viewDef.name} + + + {viewDef.name} ) @@ -18,17 +34,21 @@ export const ViewHeaderComponent = ({ view }: { view: FeedViewType }) => { export const ListHeaderComponent = ({ listId }: { listId: string }) => { const list = useList(listId) + const insets = useSafeAreaInsets() if (!list) { console.warn("list not found:", listId) return null } return ( - + {list.title} {list.description && ( - {list.description} + {list.description} )} ) diff --git a/apps/mobile/src/modules/subscription/ItemSeparator.tsx b/apps/mobile/src/modules/subscription/ItemSeparator.tsx index d96b44a8c..b96f3061c 100644 --- a/apps/mobile/src/modules/subscription/ItemSeparator.tsx +++ b/apps/mobile/src/modules/subscription/ItemSeparator.tsx @@ -1,7 +1,7 @@ import { StyleSheet, View } from "react-native" const el = ( - + ) export const ItemSeparator = () => { return el diff --git a/apps/mobile/src/modules/subscription/SubscriptionLists.tsx b/apps/mobile/src/modules/subscription/SubscriptionLists.tsx index 467f82bfa..8d886f019 100644 --- a/apps/mobile/src/modules/subscription/SubscriptionLists.tsx +++ b/apps/mobile/src/modules/subscription/SubscriptionLists.tsx @@ -62,7 +62,7 @@ export const SubscriptionLists = memo(() => { ].map((view) => { return ( - + ) })} @@ -75,7 +75,13 @@ const keyExtractor = (item: string | { category: string; subscriptionIds: string } return item.category } -const SubscriptionList = ({ view }: { view: FeedViewType }) => { +export const SubscriptionList = ({ + view, + additionalOffsetTop, +}: { + view: FeedViewType + additionalOffsetTop?: number +}) => { const headerHeight = useHeaderHeight() const insets = useSafeAreaInsets() const tabHeight = useBottomTabBarHeight() @@ -97,13 +103,13 @@ const SubscriptionList = ({ view }: { view: FeedViewType }) => { return subscriptionSyncService.fetch(view) }) - const offsetTop = headerHeight - insets.top + ViewTabHeight * 2 + 23 + const offsetTop = headerHeight - insets.top + (additionalOffsetTop || 0) return ( { setRefreshing(true) onRefresh().finally(() => { diff --git a/apps/mobile/src/screens/(headless)/search.tsx b/apps/mobile/src/screens/(headless)/search.tsx index fc8a46dbd..a3b11185d 100644 --- a/apps/mobile/src/screens/(headless)/search.tsx +++ b/apps/mobile/src/screens/(headless)/search.tsx @@ -19,7 +19,6 @@ import { import { SearchHeader } from "@/src/modules/discover/search" import { SearchFeed } from "@/src/modules/discover/search-tabs/SearchFeed" import { SearchList } from "@/src/modules/discover/search-tabs/SearchList" -import { SearchUser } from "@/src/modules/discover/search-tabs/SearchUser" const Search = () => { return ( @@ -39,7 +38,7 @@ const Search = () => { const SearchType2RenderContent: Record = { [SearchType.Feed]: SearchFeed, [SearchType.List]: SearchList, - [SearchType.User]: SearchUser, + // [SearchType.User]: SearchUser, } const PlaceholderLazyView = () => { const windowWidth = Dimensions.get("window").width