From 78997c1e45afcbb8b10dc7198306af4eb342d253 Mon Sep 17 00:00:00 2001
From: Boa
Date: Fri, 29 Apr 2022 15:11:04 -0600
Subject: [PATCH] Show comments position (#110)
* Add betting activity back to feed
* Show position in bin. markets, no comments on bets
* Degroup bets on Bets tab
* Show users position or recent bet with comments
* Add tooltip on answer to FR comments
* Style improvements
* Only use bets by current user for comment input
---
web/components/feed/activity-items.ts | 91 ++++---
web/components/feed/feed-items.tsx | 328 +++++++++++++++++-------
web/components/outcome-label.tsx | 34 ++-
web/pages/[username]/[contractSlug].tsx | 2 +-
4 files changed, 308 insertions(+), 147 deletions(-)
diff --git a/web/components/feed/activity-items.ts b/web/components/feed/activity-items.ts
index a12c4e0a..7879b637 100644
--- a/web/components/feed/activity-items.ts
+++ b/web/components/feed/activity-items.ts
@@ -31,6 +31,8 @@ type BaseActivityItem = {
export type CommentInputItem = BaseActivityItem & {
type: 'commentInput'
+ betsByCurrentUser: Bet[]
+ comments: Comment[]
}
export type DescriptionItem = BaseActivityItem & {
@@ -48,12 +50,13 @@ export type BetItem = BaseActivityItem & {
bet: Bet
hideOutcome: boolean
smallAvatar: boolean
+ hideComment?: boolean
}
export type CommentItem = BaseActivityItem & {
type: 'comment'
comment: Comment
- bet: Bet | undefined
+ betsBySameUser: Bet[]
hideOutcome: boolean
truncate: boolean
smallAvatar: boolean
@@ -129,7 +132,7 @@ function groupBets(
type: 'comment' as const,
id: bet.id,
comment,
- bet,
+ betsBySameUser: [bet],
contract,
hideOutcome,
truncate: abbreviated,
@@ -280,7 +283,7 @@ function groupBetsAndComments(
id: comment.id,
contract: contract,
comment,
- bet: undefined,
+ betsBySameUser: [],
truncate: abbreviated,
hideOutcome: true,
smallAvatar,
@@ -308,6 +311,27 @@ function groupBetsAndComments(
return abbrItems
}
+function getCommentsWithPositions(
+ bets: Bet[],
+ comments: Comment[],
+ contract: Contract
+) {
+ const betsByUserId = _.groupBy(bets, (bet) => bet.userId)
+
+ const items = comments.map((comment) => ({
+ type: 'comment' as const,
+ id: comment.id,
+ contract: contract,
+ comment,
+ betsBySameUser: bets.length === 0 ? [] : betsByUserId[comment.userId] ?? [],
+ truncate: true,
+ hideOutcome: false,
+ smallAvatar: false,
+ }))
+
+ return items
+}
+
export function getAllContractActivityItems(
contract: Contract,
bets: Bet[],
@@ -361,6 +385,8 @@ export function getAllContractActivityItems(
type: 'commentInput',
id: 'commentInput',
contract,
+ betsByCurrentUser: [],
+ comments: [],
})
} else {
items.push(
@@ -385,6 +411,8 @@ export function getAllContractActivityItems(
type: 'commentInput',
id: 'commentInput',
contract,
+ betsByCurrentUser: [],
+ comments: [],
})
}
@@ -432,24 +460,13 @@ export function getRecentContractActivityItems(
)
)
} else {
- const onlyUsersBetsOrBetsWithComments = bets.filter((bet) =>
- comments.some(
- (comment) => comment.betId === bet.id || bet.userId === user?.id
- )
- )
items.push(
- ...groupBetsAndComments(
- onlyUsersBetsOrBetsWithComments,
- comments,
- contract,
- user?.id,
- {
- hideOutcome: false,
- abbreviated: true,
- smallAvatar: false,
- reversed: true,
- }
- )
+ ...groupBetsAndComments(bets, comments, contract, user?.id, {
+ hideOutcome: false,
+ abbreviated: true,
+ smallAvatar: false,
+ reversed: true,
+ })
)
}
@@ -471,37 +488,29 @@ export function getSpecificContractActivityItems(
switch (mode) {
case 'bets':
items.push(
- ...groupBets(bets, comments, contract, user?.id, {
+ ...bets.map((bet) => ({
+ type: 'bet' as const,
+ id: bet.id,
+ bet,
+ contract,
hideOutcome: false,
- abbreviated: false,
smallAvatar: false,
- reversed: false,
- })
+ hideComment: true,
+ }))
)
break
case 'comments':
- const onlyBetsWithComments = bets.filter((bet) =>
- comments.some((comment) => comment.betId === bet.id)
- )
- items.push(
- ...groupBetsAndComments(
- onlyBetsWithComments,
- comments,
- contract,
- user?.id,
- {
- hideOutcome: false,
- abbreviated: false,
- smallAvatar: false,
- reversed: false,
- }
- )
- )
+ items.push(...getCommentsWithPositions(bets, comments, contract))
+
items.push({
type: 'commentInput',
id: 'commentInput',
contract,
+ betsByCurrentUser: user
+ ? bets.filter((bet) => bet.userId === user.id)
+ : [],
+ comments: comments,
})
break
}
diff --git a/web/components/feed/feed-items.tsx b/web/components/feed/feed-items.tsx
index 7518c998..584907d9 100644
--- a/web/components/feed/feed-items.tsx
+++ b/web/components/feed/feed-items.tsx
@@ -39,7 +39,13 @@ import BetRow from '../bet-row'
import { Avatar } from '../avatar'
import { Answer } from '../../../common/answer'
import { ActivityItem } from './activity-items'
-import { FreeResponse, FullContract } from '../../../common/contract'
+import {
+ Binary,
+ CPMM,
+ DPM,
+ FreeResponse,
+ FullContract,
+} from '../../../common/contract'
import { BuyButton } from '../yes-no-selector'
import { getDpmOutcomeProbability } from '../../../common/calculate-dpm'
import { AnswerBetPanel } from '../answers/answer-bet-panel'
@@ -50,6 +56,7 @@ import { trackClick } from '../../lib/firebase/tracking'
import { firebaseLogin } from '../../lib/firebase/users'
import { DAY_MS } from '../../../common/util/time'
import NewContractBadge from '../new-contract-badge'
+import { calculateCpmmSale } from '../../../common/calculate-cpmm'
export function FeedItems(props: {
contract: Contract
@@ -123,21 +130,38 @@ function FeedItem(props: { item: ActivityItem }) {
export function FeedComment(props: {
contract: Contract
comment: Comment
- bet: Bet | undefined
+ betsBySameUser: Bet[]
hideOutcome: boolean
truncate: boolean
smallAvatar: boolean
}) {
- const { contract, comment, bet, hideOutcome, truncate, smallAvatar } = props
- let money: string | undefined
- let outcome: string | undefined
- let bought: string | undefined
- if (bet) {
- outcome = bet.outcome
- bought = bet.amount >= 0 ? 'bought' : 'sold'
- money = formatMoney(Math.abs(bet.amount))
- }
+ const {
+ contract,
+ comment,
+ betsBySameUser,
+ hideOutcome,
+ truncate,
+ smallAvatar,
+ } = props
const { text, userUsername, userName, userAvatarUrl, createdTime } = comment
+ let outcome: string | undefined,
+ bought: string | undefined,
+ money: string | undefined
+
+ const matchedBet = betsBySameUser.find((bet) => bet.id === comment.betId)
+ if (matchedBet) {
+ outcome = matchedBet.outcome
+ bought = matchedBet.amount >= 0 ? 'bought' : 'sold'
+ money = formatMoney(Math.abs(matchedBet.amount))
+ }
+
+ // Only calculated if they don't have a matching bet
+ const { userPosition, userPositionMoney, yesFloorShares, noFloorShares } =
+ getBettorsPosition(
+ contract,
+ comment.createdTime,
+ matchedBet ? [] : betsBySameUser
+ )
return (
<>
@@ -155,18 +179,33 @@ export function FeedComment(props: {
username={userUsername}
name={userName}
/>{' '}
- {bought} {money}
- {!hideOutcome && (
+ {!matchedBet && userPosition > 0 && (
<>
- {' '}
- of{' '}
-
+ {'with ' + userPositionMoney + ' '}
+ <>
+ {' of '}
+ noFloorShares ? 'YES' : 'NO'}
+ contract={contract}
+ truncate="short"
+ />
+ >
>
)}
+ <>
+ {bought} {money}
+ {outcome && !hideOutcome && (
+ <>
+ {' '}
+ of{' '}
+
+ >
+ )}
+ >
@@ -180,20 +219,12 @@ export function FeedComment(props: {
)
}
-function RelativeTimestamp(props: { time: number }) {
- const { time } = props
- return (
-
-
- {fromNow(time)}
-
-
- )
-}
-
-export function CommentInput(props: { contract: Contract }) {
- // see if we can comment input on any bet:
- const { contract } = props
+export function CommentInput(props: {
+ contract: Contract
+ betsByCurrentUser: Bet[]
+ comments: Comment[]
+}) {
+ const { contract, betsByCurrentUser, comments } = props
const user = useUser()
const [comment, setComment] = useState('')
@@ -206,14 +237,50 @@ export function CommentInput(props: { contract: Contract }) {
setComment('')
}
+ // Should this be oldest bet or most recent bet?
+ const mostRecentCommentableBet = betsByCurrentUser
+ .filter(
+ (bet) =>
+ canCommentOnBet(bet.userId, bet.createdTime, user) &&
+ !comments.some((comment) => comment.betId == bet.id)
+ )
+ .sort((b1, b2) => b1.createdTime - b2.createdTime)
+ .pop()
+
+ if (mostRecentCommentableBet) {
+ return (
+
+ )
+ }
+ const { userPosition, userPositionMoney, yesFloorShares, noFloorShares } =
+ getBettorsPosition(contract, Date.now(), betsByCurrentUser)
+
return (
<>
-
+
+ {user && userPosition > 0 && (
+ <>
+ {'You with ' + userPositionMoney + ' '}
+ <>
+ {' of '}
+
noFloorShares ? 'YES' : 'NO'}
+ contract={contract}
+ truncate="short"
+ />
+ >
+ >
+ )}