From a2019aceec001e276272832b97ea5e2ec864c8a5 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Tue, 17 Dec 2024 21:45:39 -0600 Subject: Trending (Beta) (#7144) * Add WIP UIs for trending topics and suggested starterpacks * Disable SPs for now * Improve explore treatment a bit, add some polish to cards * Add tiny option in RightNav * Add persisted option to hide trending from sidebar * Add to settings, abstract state, not updating in tab * Fix up hide/show toggle state, WITH broadcast hacK * Clean up persisted code, add new setting * Add new interstitial to Discover * Exploration * First hack at mute words * Wire up interstitial and Explore page * Align components * Some skeleton UI * Handle service config, enablement, load states, update lex contract * Centralize mute word handling * Stale time to 30m * Cache enabled value for reloads, use real data for service config * Remove broadcast hack * Remove titleChild * Gate settings too * Update package, rm langs * Add feature gate * Only english during beta period * Hook up real data * Tweak config * Straight passthrough links * Hook up prod agent * Fix no-show logic * Up config query to 5 min * Remove old file * Remove comment * Remove stray flex_1 * Make trending setting global * Quick placeholder state * Limit # in sidebar, tweak spacing * Tweak gaps * Handle hide/show of sidebar * Simplify messages * Remove interstitial * Revert "Remove interstitial" This reverts commit 1358ad47fdf7e633749340c410933b508af46c10. * Only show interstitial on mobile * Fix gap * Add explore page recommendations * [topics] add topic screen (#7149) * add topic screen * decode * fix search query * decode * add server route * Fix potential bad destructure (undefined) --------- Co-authored-by: Paul Frazee Co-authored-by: Dan Abramov Co-authored-by: Hailey --- src/screens/Topic.tsx | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 src/screens/Topic.tsx (limited to 'src/screens/Topic.tsx') diff --git a/src/screens/Topic.tsx b/src/screens/Topic.tsx new file mode 100644 index 000000000..6cd69f05f --- /dev/null +++ b/src/screens/Topic.tsx @@ -0,0 +1,204 @@ +import React from 'react' +import {ListRenderItemInfo, View} from 'react-native' +import {PostView} from '@atproto/api/dist/client/types/app/bsky/feed/defs' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {useFocusEffect} from '@react-navigation/native' +import {NativeStackScreenProps} from '@react-navigation/native-stack' + +import {HITSLOP_10} from '#/lib/constants' +import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender' +import {CommonNavigatorParams} from '#/lib/routes/types' +import {shareUrl} from '#/lib/sharing' +import {cleanError} from '#/lib/strings/errors' +import {enforceLen} from '#/lib/strings/helpers' +import {useSearchPostsQuery} from '#/state/queries/search-posts' +import {useSetMinimalShellMode} from '#/state/shell' +import {Pager} from '#/view/com/pager/Pager' +import {TabBar} from '#/view/com/pager/TabBar' +import {Post} from '#/view/com/post/Post' +import {List} from '#/view/com/util/List' +import {atoms as a, web} from '#/alf' +import {Button, ButtonIcon} from '#/components/Button' +import {ArrowOutOfBox_Stroke2_Corner0_Rounded as Share} from '#/components/icons/ArrowOutOfBox' +import * as Layout from '#/components/Layout' +import {ListFooter, ListMaybePlaceholder} from '#/components/Lists' + +const renderItem = ({item}: ListRenderItemInfo) => { + return +} + +const keyExtractor = (item: PostView, index: number) => { + return `${item.uri}-${index}` +} + +export default function TopicScreen({ + route, +}: NativeStackScreenProps) { + const {topic} = route.params + const {_} = useLingui() + + const headerTitle = React.useMemo(() => { + return enforceLen(decodeURIComponent(topic), 24, true, 'middle') + }, [topic]) + + const onShare = React.useCallback(() => { + const url = new URL('https://bsky.app') + url.pathname = `/topic/${topic}` + shareUrl(url.toString()) + }, [topic]) + + const [activeTab, setActiveTab] = React.useState(0) + const setMinimalShellMode = useSetMinimalShellMode() + + useFocusEffect( + React.useCallback(() => { + setMinimalShellMode(false) + }, [setMinimalShellMode]), + ) + + const onPageSelected = React.useCallback( + (index: number) => { + setMinimalShellMode(false) + setActiveTab(index) + }, + [setMinimalShellMode], + ) + + const sections = React.useMemo(() => { + return [ + { + title: _(msg`Top`), + component: ( + + ), + }, + { + title: _(msg`Latest`), + component: ( + + ), + }, + ] + }, [_, topic, activeTab]) + + return ( + + + + + {headerTitle} + + + + + + ( + + section.title)} {...props} /> + + )} + initialPage={0}> + {sections.map((section, i) => ( + {section.component} + ))} + + + ) +} + +function TopicScreenTab({ + topic, + sort, + active, +}: { + topic: string + sort: 'top' | 'latest' + active: boolean +}) { + const {_} = useLingui() + const initialNumToRender = useInitialNumToRender() + const [isPTR, setIsPTR] = React.useState(false) + + const { + data, + isFetched, + isFetchingNextPage, + isLoading, + isError, + error, + refetch, + fetchNextPage, + hasNextPage, + } = useSearchPostsQuery({ + query: decodeURIComponent(topic), + sort, + enabled: active, + }) + + const posts = React.useMemo(() => { + return data?.pages.flatMap(page => page.posts) || [] + }, [data]) + + const onRefresh = React.useCallback(async () => { + setIsPTR(true) + await refetch() + setIsPTR(false) + }, [refetch]) + + const onEndReached = React.useCallback(() => { + if (isFetchingNextPage || !hasNextPage || error) return + fetchNextPage() + }, [isFetchingNextPage, hasNextPage, error, fetchNextPage]) + + return ( + <> + {posts.length < 1 ? ( + + ) : ( + + } + initialNumToRender={initialNumToRender} + windowSize={11} + /> + )} + + ) +} -- cgit 1.4.1