Skip to content

Commit

Permalink
feat: view selector in entry list
Browse files Browse the repository at this point in the history
  • Loading branch information
DIYgod committed Jan 23, 2025
1 parent 4696ac6 commit d565cb8
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 74 deletions.
28 changes: 9 additions & 19 deletions apps/mobile/src/modules/entry-list/entry-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,17 @@ import {
NavigationContext,
} from "@/src/components/common/SafeNavigationScrollView"
import { ItemPressable } from "@/src/components/ui/pressable/item-pressable"
import {
useSelectedFeed,
useSetDrawerSwipeDisabled,
useViewDefinition,
} from "@/src/modules/feed-drawer/atoms"
import { useSelectedFeed, useSetDrawerSwipeDisabled } from "@/src/modules/feed-drawer/atoms"
import {
useEntry,
useEntryIdsByCategory,
useEntryIdsByFeedId,
useEntryIdsByInboxId,
useEntryIdsByView,
} from "@/src/store/entry/hooks"
import { FEED_COLLECTION_LIST } from "@/src/store/entry/utils"
import { useFeed } from "@/src/store/feed/hooks"
import { useInbox } from "@/src/store/inbox/hooks"
import { useList } from "@/src/store/list/hooks"

import { ViewSelector } from "../feed-drawer/view-selector"
import { LeftAction, RightAction } from "./action"
import { EntryListContentGrid } from "./entry-list-gird"

Expand Down Expand Up @@ -70,37 +64,33 @@ export function EntryList() {

function ViewEntryList({ viewId }: { viewId: FeedViewType }) {
const entryIds = useEntryIdsByView(viewId)
const viewDef = useViewDefinition(viewId)

return <EntryListScreen title={viewDef.name} entryIds={entryIds} />
return <EntryListScreen entryIds={entryIds} />
}

function FeedEntryList({ feedId }: { feedId: string }) {
const feed = useFeed(feedId)
const entryIds = useEntryIdsByFeedId(feedId)
const title = feedId === FEED_COLLECTION_LIST ? "Collections" : (feed?.title ?? "")
return <EntryListScreen title={title} entryIds={entryIds} />
return <EntryListScreen entryIds={entryIds} />
}

function CategoryEntryList({ categoryName }: { categoryName: string }) {
const entryIds = useEntryIdsByCategory(categoryName)
return <EntryListScreen title={categoryName} entryIds={entryIds} />
return <EntryListScreen entryIds={entryIds} />
}

function ListEntryList({ listId }: { listId: string }) {
const list = useList(listId)
if (!list) return null

return <EntryListScreen title={list.title} entryIds={list.entryIds ?? []} />
return <EntryListScreen entryIds={list.entryIds ?? []} />
}

function InboxEntryList({ inboxId }: { inboxId: string }) {
const inbox = useInbox(inboxId)
const entryIds = useEntryIdsByInboxId(inboxId)
return <EntryListScreen title={inbox?.title ?? "Inbox"} entryIds={entryIds} />
return <EntryListScreen entryIds={entryIds} />
}

function EntryListScreen({ title, entryIds }: { title: string; entryIds: string[] }) {
function EntryListScreen({ entryIds }: { entryIds: string[] }) {
const scrollY = useAnimatedValue(0)
const selectedFeed = useSelectedFeed()
const view = selectedFeed.type === "view" ? selectedFeed.viewId : null
Expand All @@ -109,7 +99,7 @@ function EntryListScreen({ title, entryIds }: { title: string; entryIds: string[
<NavigationContext.Provider value={useMemo(() => ({ scrollY }), [scrollY])}>
<NavigationBlurEffectHeader
headerShown
title={title}
headerTitle={ViewSelector}
headerLeft={useCallback(
() => (
<LeftAction />
Expand Down
32 changes: 31 additions & 1 deletion apps/mobile/src/modules/feed-drawer/atoms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { useCallback, useMemo } from "react"
import { views } from "@/src/constants/views"
import { usePrefetchEntries } from "@/src/store/entry/hooks"
import type { FetchEntriesProps } from "@/src/store/entry/types"
import { FEED_COLLECTION_LIST } from "@/src/store/entry/utils"
import { useFeed } from "@/src/store/feed/hooks"
import { useInbox } from "@/src/store/inbox/hooks"
import { useList } from "@/src/store/list/hooks"
import { getSubscriptionByCategory } from "@/src/store/subscription/getter"

// drawer open state
Expand Down Expand Up @@ -123,11 +127,37 @@ export function useSelectedFeed() {
return selectedFeed
}

export const useSelectedFeedTitle = () => {
const selectedFeed = useSelectedFeed()
const viewDef = useViewDefinition(selectedFeed.type === "view" ? selectedFeed.viewId : undefined)
const feed = useFeed(selectedFeed.type === "feed" ? selectedFeed.feedId : "")
const list = useList(selectedFeed.type === "list" ? selectedFeed.listId : "")
const inbox = useInbox(selectedFeed.type === "inbox" ? selectedFeed.inboxId : "")

switch (selectedFeed.type) {
case "view": {
return viewDef?.name
}
case "feed": {
return selectedFeed.feedId === FEED_COLLECTION_LIST ? "Collections" : (feed?.title ?? "")
}
case "category": {
return selectedFeed.categoryName
}
case "list": {
return list?.title
}
case "inbox": {
return inbox?.title ?? "Inbox"
}
}
}

export const selectFeed = (state: SelectedFeed) => {
jotaiStore.set(selectedFeedAtom, state)
}

export const useViewDefinition = (view: FeedViewType) => {
export const useViewDefinition = (view?: FeedViewType) => {
const viewDef = useMemo(() => views.find((v) => v.view === view), [view])
if (!viewDef) {
throw new Error(`View ${view} not found`)
Expand Down
67 changes: 19 additions & 48 deletions apps/mobile/src/modules/feed-drawer/view-selector.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,21 @@
import { cn } from "@follow/utils"
import { Image } from "expo-image"
import { Stack } from "expo-router"
import { ScrollView, TouchableOpacity, View } from "react-native"
import { ScrollView, TouchableOpacity } from "react-native"
import { Grayscale } from "react-native-color-matrix-image-filters"

import { BlurEffect } from "@/src/components/common/BlurEffect"
import { FallbackIcon } from "@/src/components/ui/icon/fallback-icon"
import type { ViewDefinition } from "@/src/constants/views"
import { views } from "@/src/constants/views"
import { useList } from "@/src/store/list/hooks"
import { useAllListSubscription } from "@/src/store/subscription/hooks"
import { useColor } from "@/src/theme/colors"

import { LeftAction, RightAction } from "../entry-list/action"
import { selectFeed, useSelectedFeed } from "../feed-drawer/atoms"

export function ViewSelector() {
return (
<Stack.Screen
options={{
headerShown: true,
headerTitle: ViewItems,
headerLeft: LeftAction,
headerRight: RightAction,
headerTransparent: true,
headerBackground: BlurEffect,
}}
/>
)
}

function ViewItems() {
const lists = useAllListSubscription()

return (
<ScrollView horizontal className="mx-7">
<ScrollView horizontal contentContainerClassName="flex-row gap-3 items-center">
{views.map((view) => (
<ViewItem key={view.name} view={view} />
))}
Expand All @@ -53,19 +34,13 @@ function ViewItem({ view }: { view: ViewDefinition }) {

return (
<TouchableOpacity
className="relative flex aspect-square items-center justify-center"
className="relative flex size-8 items-center justify-center overflow-hidden rounded-full"
onPress={() => selectFeed({ type: "view", viewId: view.view })}
style={{
backgroundColor: isActive ? view.activeColor : bgColor,
}}
>
<View className="flex size-8 items-center justify-center overflow-hidden rounded-full">
<View
className="flex size-full items-center justify-center"
style={{
backgroundColor: isActive ? view.activeColor : bgColor,
}}
>
<view.icon color={"#fff"} height={15} width={15} />
</View>
</View>
<view.icon color={"#fff"} height={15} width={15} />
</TouchableOpacity>
)
}
Expand All @@ -79,24 +54,20 @@ function ListItem({ listId }: { listId: string }) {

return (
<TouchableOpacity
className="relative flex aspect-square items-center justify-center"
className="relative flex size-8 items-center justify-center overflow-hidden rounded-full"
onPress={() => selectFeed({ type: "list", listId })}
>
<View className="flex size-8 items-center justify-center overflow-hidden rounded-full">
<View className={cn("flex size-full items-center justify-center")}>
{list.image ? (
isActive ? (
<Image source={list.image} contentFit="cover" style={{ width: 32, height: 32 }} />
) : (
<Grayscale>
<Image source={list.image} contentFit="cover" style={{ width: 32, height: 32 }} />
</Grayscale>
)
) : (
<FallbackIcon title={list.title} size="100%" gray={!isActive} />
)}
</View>
</View>
{list.image ? (
isActive ? (
<Image source={list.image} contentFit="cover" style={{ width: 32, height: 32 }} />
) : (
<Grayscale>
<Image source={list.image} contentFit="cover" style={{ width: 32, height: 32 }} />
</Grayscale>
)
) : (
<FallbackIcon title={list.title} size="100%" gray={!isActive} />
)}
</TouchableOpacity>
)
}
7 changes: 1 addition & 6 deletions apps/mobile/src/screens/(stack)/(tabs)/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { EntryList } from "@/src/modules/entry-list/entry-list"

export default function Index() {
return (
<>
{/* <ViewSelector /> */}
<EntryList />
</>
)
return <EntryList />
}

0 comments on commit d565cb8

Please sign in to comment.