diff --git a/supabase-replicator/supabase/seed.sql b/supabase-replicator/supabase/seed.sql index 67d4c154fe..150ecab7ff 100644 --- a/supabase-replicator/supabase/seed.sql +++ b/supabase-replicator/supabase/seed.sql @@ -493,6 +493,14 @@ as $$ where user_seen_markets.user_id = uid and user_seen_markets.contract_id = crf.contract_id ) + -- That has not been viewed as a card recently. + and not exists ( + select 1 from user_events + where user_events.user_id = uid + and user_events.data->>'name' = 'view market card' + and user_events.data->>'contractId' = crf.contract_id + and user_events.ts > now() - interval '1 day' + ) order by dot(urf, crf) desc $$; @@ -501,12 +509,15 @@ returns JSONB[] immutable parallel safe language sql as $$ - select array_agg(data) as data_array - from get_recommended_contract_ids(uid, count) - left join contracts - on contracts.id = contract_id - -- Not resolved. - where not (data->>'isResolved')::boolean - -- Not closed: closeTime is greater than now. - and (data->>'closeTime')::bigint > extract(epoch from now()) * 1000 + select array_agg(data) from ( + select data + from get_recommended_contract_ids(uid) + left join contracts + on contracts.id = contract_id + -- Not resolved. + where not (data->>'isResolved')::boolean + -- Not closed: closeTime is greater than now. + and (data->>'closeTime')::bigint > extract(epoch from now()) * 1000 + limit count + ) as rec_contracts $$; diff --git a/web/hooks/use-feed.ts b/web/hooks/use-feed.ts index 8f8c20e6db..f8f5d3d8e4 100644 --- a/web/hooks/use-feed.ts +++ b/web/hooks/use-feed.ts @@ -1,29 +1,40 @@ +import { uniqBy } from 'lodash' import { Contract } from 'common/contract' import { User } from 'common/user' -import { useEffect } from 'react' +import { useCallback, useEffect } from 'react' import { usePersistentState, inMemoryStore } from './use-persistent-state' import { db } from 'web/lib/supabase/db' +import { buildArray } from 'common/util/array' -export const useFeed = (user: User | null | undefined, count: number) => { +const PAGE_SIZE = 10 + +export const useFeed = (user: User | null | undefined, key: string) => { const [savedContracts, setSavedContracts] = usePersistentState< Contract[] | undefined >(undefined, { - key: `recommended-contracts-${user?.id}-${count}`, + key: `recommended-contracts-${user?.id}-${key}`, store: inMemoryStore(), }) const userId = user?.id - useEffect(() => { + const loadMore = useCallback(() => { if (userId) { - db.rpc('get_recommended_contracts' as any, { uid: userId, count }).then( - (res) => { - const contracts = res.data as Contract[] - setSavedContracts(contracts) - } - ) + db.rpc('get_recommended_contracts' as any, { + uid: userId, + count: PAGE_SIZE, + }).then((res) => { + const newContracts = res.data as Contract[] | undefined + setSavedContracts((contracts) => + uniqBy(buildArray(contracts, newContracts), (c) => c.id) + ) + }) } - }, [setSavedContracts, userId, count]) + }, [userId, setSavedContracts]) + + useEffect(() => { + loadMore() + }, [loadMore]) - return savedContracts + return { contracts: savedContracts, loadMore } } diff --git a/web/pages/home/index.tsx b/web/pages/home/index.tsx index 754520a32b..8bff60a01f 100644 --- a/web/pages/home/index.tsx +++ b/web/pages/home/index.tsx @@ -380,18 +380,14 @@ const YourFeedSection = (props: { user: User }) => { onVisibilityUpdated={(visible) => visible && setHasViewedBottom(true)} /> - {hasViewedBottom ? ( - - ) : ( - - )} + {hasViewedBottom ? : } ) } -export const DiscoverFeed = (props: { user: User; count: number }) => { - const { user, count } = props - const contracts = useFeed(user, count) +export const DiscoverFeed = (props: { user: User }) => { + const { user } = props + const { contracts, loadMore } = useFeed(user, 'home') if (!contracts) return return ( @@ -399,6 +395,7 @@ export const DiscoverFeed = (props: { user: User; count: number }) => { contracts={contracts} showImageOnTopContract trackCardViews={true} + loadMore={loadMore} /> ) } diff --git a/web/pages/swipe/index.tsx b/web/pages/swipe/index.tsx index a5cb3b09cd..d1a9ccb2b4 100644 --- a/web/pages/swipe/index.tsx +++ b/web/pages/swipe/index.tsx @@ -37,7 +37,8 @@ export default function Swipe() { }) const user = useUser() - const feed = useFeed(user, 400)?.filter((c) => c.outcomeType === 'BINARY') as + const { contracts, loadMore } = useFeed(user, 'swipe') + const feed = contracts?.filter((c) => c.outcomeType === 'BINARY') as | BinaryContract[] | undefined @@ -45,6 +46,13 @@ export default function Swipe() { key: 'swipe-index', store: inMemoryStore(), }) + + useEffect(() => { + if (feed && index + 2 >= feed.length) { + loadMore() + } + }, [feed, index, loadMore]) + const contract = feed ? feed[index] : undefined const cards = useMemo(() => {