113 lines
4.5 KiB
TypeScript
113 lines
4.5 KiB
TypeScript
import { useFeedById, usePrefetchFeed } from "@follow/store/feed/hooks"
|
|
import { useSubscriptionById } from "@follow/store/subscription/hooks"
|
|
import { useUnreadById } from "@follow/store/unread/hooks"
|
|
import { cn } from "@follow/utils"
|
|
import { memo, use } from "react"
|
|
import { View } from "react-native"
|
|
import Animated, { FadeOutUp } from "react-native-reanimated"
|
|
import { useColor } from "react-native-uikit-colors"
|
|
|
|
import { OouiUserAnonymous } from "@/src/components/icons/OouiUserAnonymous"
|
|
import { GROUPED_ICON_TEXT_GAP, GROUPED_LIST_MARGIN } from "@/src/components/ui/grouped/constants"
|
|
import { FeedIcon } from "@/src/components/ui/icon/feed-icon"
|
|
import { PlatformActivityIndicator } from "@/src/components/ui/loading/PlatformActivityIndicator"
|
|
import { ItemPressableStyle } from "@/src/components/ui/pressable/enum"
|
|
import { ItemPressable } from "@/src/components/ui/pressable/ItemPressable"
|
|
import { Text } from "@/src/components/ui/typography/Text"
|
|
import { WifiOffCuteReIcon } from "@/src/icons/wifi_off_cute_re"
|
|
import { useNavigation } from "@/src/lib/navigation/hooks"
|
|
import { selectFeed } from "@/src/modules/screen/atoms"
|
|
import { FeedScreen } from "@/src/screens/(stack)/feeds/[feedId]/FeedScreen"
|
|
|
|
import { SubscriptionFeedItemContextMenu } from "../../context-menu/feeds"
|
|
import { GroupedContext } from "../ctx"
|
|
import { ItemSeparator, SecondaryItemSeparator } from "../ItemSeparator"
|
|
import type { SubscriptionItemBaseProps } from "./types"
|
|
import { UnreadCount } from "./UnreadCount"
|
|
|
|
export const SubscriptionItem = memo(
|
|
({ id, isFirst, isLast, className }: SubscriptionItemBaseProps) => {
|
|
const red = useColor("red")
|
|
const colorLabel = useColor("label")
|
|
const subscription = useSubscriptionById(id)
|
|
const unreadCount = useUnreadById(id)
|
|
const feed = useFeedById(id)!
|
|
const inGrouped = !!use(GroupedContext)
|
|
const { isLoading } = usePrefetchFeed(id, {
|
|
enabled: !subscription && !feed,
|
|
})
|
|
const navigation = useNavigation()
|
|
const feedTestID = feed?.url
|
|
? `subscription-feed-url-${feed.url
|
|
.replaceAll(/[^a-z0-9]+/gi, "-")
|
|
.replaceAll(/^-+|-+$/g, "")
|
|
.toLowerCase()}`
|
|
: `subscription-feed-${id}`
|
|
if (isLoading) {
|
|
return (
|
|
<View className="mt-24 flex-1 flex-row items-start justify-center">
|
|
<PlatformActivityIndicator />
|
|
</View>
|
|
)
|
|
}
|
|
if (!subscription && !feed) return null
|
|
return (
|
|
<>
|
|
<Animated.View
|
|
exiting={FadeOutUp}
|
|
style={{
|
|
marginHorizontal: GROUPED_LIST_MARGIN,
|
|
}}
|
|
className={cn("overflow-hidden", {
|
|
"rounded-t-[10px]": isFirst,
|
|
"rounded-b-[10px]": isLast,
|
|
})}
|
|
>
|
|
<SubscriptionFeedItemContextMenu id={id}>
|
|
<ItemPressable
|
|
itemStyle={ItemPressableStyle.Grouped}
|
|
className={cn(
|
|
"flex h-12 flex-row items-center",
|
|
inGrouped ? "pl-8 pr-4" : "px-4",
|
|
className,
|
|
)}
|
|
testID={feedTestID}
|
|
onPress={() => {
|
|
selectFeed({
|
|
type: "feed",
|
|
feedId: id,
|
|
})
|
|
navigation.pushControllerView(FeedScreen, {
|
|
feedId: id,
|
|
})
|
|
}}
|
|
>
|
|
<View className="size-5 items-center justify-center overflow-hidden rounded border border-transparent dark:border-tertiary-system-background dark:bg-[#222]">
|
|
<FeedIcon feed={feed} />
|
|
</View>
|
|
<View className="flex-1 flex-row items-center gap-2">
|
|
<Text
|
|
numberOfLines={1}
|
|
className={cn("shrink text-sm font-medium text-text", feed.errorAt && "text-red")}
|
|
style={{
|
|
marginLeft: GROUPED_ICON_TEXT_GAP,
|
|
}}
|
|
>
|
|
{subscription?.title || feed.title}
|
|
</Text>
|
|
{!!feed.errorAt && <WifiOffCuteReIcon color={red} height={18} width={18} />}
|
|
{!!subscription?.isPrivate && (
|
|
<OouiUserAnonymous color={colorLabel} height={18} width={18} />
|
|
)}
|
|
</View>
|
|
<UnreadCount unread={unreadCount} className="ml-auto" />
|
|
</ItemPressable>
|
|
</SubscriptionFeedItemContextMenu>
|
|
</Animated.View>
|
|
{!isLast && (inGrouped ? <SecondaryItemSeparator /> : <ItemSeparator />)}
|
|
</>
|
|
)
|
|
},
|
|
)
|
|
SubscriptionItem.displayName = "SubscriptionItem"
|