diff --git a/web/pages/activity.tsx b/web/components/activity-feed.tsx similarity index 74% rename from web/pages/activity.tsx rename to web/components/activity-feed.tsx index bab58328..bfd4cc1c 100644 --- a/web/pages/activity.tsx +++ b/web/components/activity-feed.tsx @@ -1,9 +1,12 @@ import _ from 'lodash' -import { ContractFeed, ContractSummaryFeed } from '../components/contract-feed' -import { Page } from '../components/page' +import { + ContractActivityFeed, + ContractFeed, + ContractSummaryFeed, +} from './contract-feed' import { Contract } from '../lib/firebase/contracts' import { Comment } from '../lib/firebase/comments' -import { Col } from '../components/layout/col' +import { Col } from './layout/col' import { Bet } from '../../common/bet' const MAX_ACTIVE_CONTRACTS = 75 @@ -72,30 +75,44 @@ export function findActiveContracts( export function ActivityFeed(props: { contracts: Contract[] - contractBets: Bet[][] - contractComments: Comment[][] + recentBets: Bet[] + recentComments: Comment[] + loadBetAndCommentHistory?: boolean }) { - const { contracts, contractBets, contractComments } = props + const { contracts, recentBets, recentComments, loadBetAndCommentHistory } = + props - return contracts.length > 0 ? ( + const groupedBets = _.groupBy(recentBets, (bet) => bet.contractId) + const groupedComments = _.groupBy( + recentComments, + (comment) => comment.contractId + ) + + return ( - + - {contracts.map((contract, i) => ( + {contracts.map((contract) => (
- + {loadBetAndCommentHistory ? ( + + ) : ( + + )}
))} - ) : ( - <> ) } @@ -116,11 +133,3 @@ export function SummaryActivityFeed(props: { contracts: Contract[] }) { ) } - -export default function ActivityPage() { - return ( - - - - ) -} diff --git a/web/components/contract-feed.tsx b/web/components/contract-feed.tsx index bf5885b5..766ba94b 100644 --- a/web/components/contract-feed.tsx +++ b/web/components/contract-feed.tsx @@ -290,7 +290,10 @@ function TruncatedComment(props: { } return ( -
+
{truncated != comment && ( @@ -301,8 +304,11 @@ function TruncatedComment(props: { ) } -function FeedQuestion(props: { contract: Contract }) { - const { contract } = props +function FeedQuestion(props: { + contract: Contract + showDescription?: boolean +}) { + const { contract, showDescription } = props const { creatorName, creatorUsername, question, resolution, outcomeType } = contract const { truePool } = contractMetrics(contract) @@ -337,22 +343,34 @@ function FeedQuestion(props: { contract: Contract }) { {closeMessage}
- - - {question} - + + + + {question} + + {!showDescription && ( + +
See more...
+
+ )} + {(isBinary || resolution) && ( )} - + {showDescription && ( + + )}
) @@ -681,6 +699,7 @@ type ActivityItem = { | 'close' | 'resolve' | 'expand' + | undefined } type FeedType = @@ -691,64 +710,24 @@ type FeedType = // Grouped for a multi-category outcome | 'multi' -export function ContractFeed(props: { +function FeedItems(props: { contract: Contract - bets: Bet[] - comments: Comment[] + items: ActivityItem[] feedType: FeedType + setExpanded: (expanded: boolean) => void outcome?: string // Which multi-category outcome to filter betRowClassName?: string }) { - const { contract, feedType, outcome, betRowClassName } = props - const { id, outcomeType } = contract + const { contract, items, feedType, outcome, setExpanded, betRowClassName } = + props + const { outcomeType } = contract const isBinary = outcomeType === 'BINARY' - const [expanded, setExpanded] = useState(false) - const user = useUser() - - let bets = useBets(contract.id) ?? props.bets - bets = isBinary - ? bets.filter((bet) => !bet.isAnte) - : bets.filter((bet) => !(bet.isAnte && (bet.outcome as string) === '0')) - - if (feedType === 'multi') { - bets = bets.filter((bet) => bet.outcome === outcome) - } - - const comments = useComments(id) ?? props.comments - - const groupWindow = feedType == 'activity' ? 10 * DAY_IN_MS : DAY_IN_MS - - const allItems = [ - { type: 'start', id: 0 }, - ...groupBets(bets, comments, groupWindow, user?.id), - ] - if (contract.closeTime && contract.closeTime <= Date.now()) { - allItems.push({ type: 'close', id: `${contract.closeTime}` }) - } - if (contract.resolution) { - allItems.push({ type: 'resolve', id: `${contract.resolutionTime}` }) - } - if (feedType === 'multi') { - // Hack to add some more padding above the 'multi' feedType, by adding a null item - allItems.unshift({ type: '', id: -1 }) - } - - // If there are more than 5 items, only show the first, an expand item, and last 3 - let items = allItems - if (!expanded && allItems.length > 5 && feedType == 'activity') { - items = [ - allItems[0], - { type: 'expand', id: 'expand' }, - ...allItems.slice(-3), - ] - } - return (
-
+
{items.map((activityItem, activityItemIdx) => ( -
+
{activityItemIdx !== items.length - 1 ? ( !bet.isAnte) + : bets.filter((bet) => !(bet.isAnte && (bet.outcome as string) === '0')) + + if (feedType === 'multi') { + bets = bets.filter((bet) => bet.outcome === outcome) + } + + const comments = useComments(id) ?? props.comments + + const groupWindow = feedType == 'activity' ? 10 * DAY_IN_MS : DAY_IN_MS + + const allItems: ActivityItem[] = [ + { type: 'start', id: '0' }, + ...groupBets(bets, comments, groupWindow, user?.id), + ] + if (contract.closeTime && contract.closeTime <= Date.now()) { + allItems.push({ type: 'close', id: `${contract.closeTime}` }) + } + if (contract.resolution) { + allItems.push({ type: 'resolve', id: `${contract.resolutionTime}` }) + } + if (feedType === 'multi') { + // Hack to add some more padding above the 'multi' feedType, by adding a null item + allItems.unshift({ type: undefined, id: '-1' }) + } + + // If there are more than 5 items, only show the first, an expand item, and last 3 + let items = allItems + if (!expanded && allItems.length > 5 && feedType == 'activity') { + items = [ + allItems[0], + { type: 'expand', id: 'expand' }, + ...allItems.slice(-3), + ] + } + + return ( + + ) +} + +export function ContractActivityFeed(props: { + contract: Contract + bets: Bet[] + comments: Comment[] + betRowClassName?: string +}) { + const { contract, betRowClassName, bets, comments } = props + + const user = useUser() + + bets.sort((b1, b2) => b1.createdTime - b2.createdTime) + comments.sort((c1, c2) => c1.createdTime - c2.createdTime) + + const allItems: ActivityItem[] = [ + { type: 'start', id: '0' }, + ...groupBets(bets, comments, DAY_IN_MS, user?.id), + ] + if (contract.closeTime && contract.closeTime <= Date.now()) { + allItems.push({ type: 'close', id: `${contract.closeTime}` }) + } + if (contract.resolution) { + allItems.push({ type: 'resolve', id: `${contract.resolutionTime}` }) + } + + // Remove all but last bet group. + const betGroups = allItems.filter((item) => item.type === 'betgroup') + const lastBetGroup = betGroups[betGroups.length - 1] + const filtered = allItems.filter( + (item) => item.type !== 'betgroup' || item.id === lastBetGroup?.id + ) + + // Only show the first item plus the last three items. + const items = + filtered.length > 3 ? [filtered[0], ...filtered.slice(-3)] : filtered + + return ( + {}} + betRowClassName={betRowClassName} + /> + ) +} + export function ContractSummaryFeed(props: { contract: Contract betRowClassName?: string @@ -805,7 +895,7 @@ export function ContractSummaryFeed(props: {
- +
diff --git a/web/hooks/use-find-active-contracts.ts b/web/hooks/use-find-active-contracts.ts index f8aa5627..2a6a3b47 100644 --- a/web/hooks/use-find-active-contracts.ts +++ b/web/hooks/use-find-active-contracts.ts @@ -4,11 +4,11 @@ import { useMemo, useRef } from 'react' import { Fold } from '../../common/fold' import { User } from '../../common/user' import { filterDefined } from '../../common/util/array' -import { Bet, getRecentBets } from '../lib/firebase/bets' +import { Bet } from '../lib/firebase/bets' import { Comment, getRecentComments } from '../lib/firebase/comments' import { Contract, getActiveContracts } from '../lib/firebase/contracts' import { listAllFolds } from '../lib/firebase/folds' -import { findActiveContracts } from '../pages/activity' +import { findActiveContracts } from '../components/activity-feed' import { useInactiveContracts } from './use-contracts' import { useFollowedFolds } from './use-fold' import { useUserBetContracts } from './use-user-bets' @@ -20,12 +20,9 @@ export const getAllContractInfo = async () => { listAllFolds().catch(() => []), ]) - const [recentBets, recentComments] = await Promise.all([ - getRecentBets(), - getRecentComments(), - ]) + const recentComments = await getRecentComments() - return { contracts, recentBets, recentComments, folds } + return { contracts, recentComments, folds } } export const useFilterYourContracts = ( diff --git a/web/pages/fold/[...slugs]/index.tsx b/web/pages/fold/[...slugs]/index.tsx index 1d77444b..757fe325 100644 --- a/web/pages/fold/[...slugs]/index.tsx +++ b/web/pages/fold/[...slugs]/index.tsx @@ -12,7 +12,10 @@ import { getFoldBySlug, getFoldContracts, } from '../../../lib/firebase/folds' -import { ActivityFeed, findActiveContracts } from '../../activity' +import { + ActivityFeed, + findActiveContracts, +} from '../../../components/activity-feed' import { TagsList } from '../../../components/tags-list' import { Row } from '../../../components/layout/row' import { UserLink } from '../../../components/user-page' @@ -36,6 +39,9 @@ import { SEO } from '../../../components/SEO' import { useTaggedContracts } from '../../../hooks/use-contracts' import { Linkify } from '../../../components/linkify' import { filterDefined } from '../../../../common/util/array' +import { useRecentBets } from '../../../hooks/use-bets' +import { useRecentComments } from '../../../hooks/use-comments' +import { LoadingIndicator } from '../../../components/loading-indicator' export async function getStaticProps(props: { params: { slugs: string[] } }) { const { slugs } = props.params @@ -48,7 +54,6 @@ export async function getStaticProps(props: { params: { slugs: string[] } }) { const bets = await Promise.all( contracts.map((contract) => listAllBets(contract.id)) ) - const betsByContract = _.fromPairs(contracts.map((c, i) => [c.id, bets[i]])) let activeContracts = findActiveContracts(contracts, [], _.flatten(bets)) const [resolved, unresolved] = _.partition( @@ -57,10 +62,6 @@ export async function getStaticProps(props: { params: { slugs: string[] } }) { ) activeContracts = [...unresolved, ...resolved] - const activeContractBets = activeContracts.map( - (contract) => betsByContract[contract.id] ?? [] - ) - const creatorScores = scoreCreators(contracts, bets) const traderScores = scoreTraders(contracts, bets) const [topCreators, topTraders] = await Promise.all([ @@ -76,8 +77,6 @@ export async function getStaticProps(props: { params: { slugs: string[] } }) { curator, contracts, activeContracts, - activeContractBets, - activeContractComments: activeContracts.map(() => []), traderScores, topTraders, creatorScores, @@ -117,15 +116,8 @@ export default function FoldPage(props: { creatorScores: { [userId: string]: number } topCreators: User[] }) { - const { - curator, - activeContractBets, - activeContractComments, - traderScores, - topTraders, - creatorScores, - topCreators, - } = props + const { curator, traderScores, topTraders, creatorScores, topCreators } = + props const router = useRouter() const { slugs } = router.query as { slugs: string[] } @@ -151,6 +143,9 @@ export default function FoldPage(props: { props.activeContracts.map((contract) => contractsMap[contract.id]) ) + const recentBets = useRecentBets() + const recentComments = useRecentComments() + if (fold === null || !foldSubpages.includes(page) || slugs[2]) { return } @@ -233,19 +228,24 @@ export default function FoldPage(props: { /> )} {page === 'activity' ? ( - <> - - {activeContracts.length === 0 && ( -
- No activity from matching markets.{' '} - {isCurator && 'Try editing to add more tags!'} -
- )} - + recentBets && recentComments ? ( + <> + + {activeContracts.length === 0 && ( +
+ No activity from matching markets.{' '} + {isCurator && 'Try editing to add more tags!'} +
+ )} + + ) : ( + + ) ) : ( { - const { folds, recentComments } = props + const { folds } = props const user = useUser() const contracts = useActiveContracts() ?? props.contracts @@ -51,13 +50,15 @@ const Home = (props: { contracts ) - const recentBets = useGetRecentBets() - const { activeContracts, activeBets, activeComments } = - useFindActiveContracts({ - contracts: yourContracts, - recentBets: recentBets ?? [], - recentComments, - }) + const initialRecentBets = useGetRecentBets() + const recentBets = useRecentBets() ?? initialRecentBets + const recentComments = useRecentComments() ?? props.recentComments + + const { activeContracts } = useFindActiveContracts({ + contracts: yourContracts, + recentBets: initialRecentBets ?? [], + recentComments: props.recentComments, + }) const exploreContracts = useExploreContracts() @@ -71,7 +72,7 @@ const Home = (props: { return ( - + @@ -116,8 +117,8 @@ const Home = (props: { (recentBets ? ( ) : (