Make tooltip rendering more efficient (#807)

* Don't use very slow dayjs formatter on timestamp tooltips

* Kill dead code in feed-bets.tsx

* Clean up tooltip markup
This commit is contained in:
Marshall Polaris 2022-08-27 13:46:35 -07:00 committed by GitHub
parent eeed9eef10
commit 4b513a894d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 16 additions and 105 deletions

View File

@ -233,7 +233,7 @@ export function ContractDetails(props: {
<ClockIcon className="h-5 w-5" /> <ClockIcon className="h-5 w-5" />
<DateTimeTooltip <DateTimeTooltip
text="Market resolved:" text="Market resolved:"
time={dayjs(contract.resolutionTime)} time={contract.resolutionTime}
> >
{resolvedDate} {resolvedDate}
</DateTimeTooltip> </DateTimeTooltip>
@ -322,7 +322,7 @@ function EditableCloseDate(props: {
) : ( ) : (
<DateTimeTooltip <DateTimeTooltip
text={closeTime > Date.now() ? 'Trading ends:' : 'Trading ended:'} text={closeTime > Date.now() ? 'Trading ends:' : 'Trading ended:'}
time={dayJsCloseTime} time={closeTime}
> >
{isSameYear {isSameYear
? dayJsCloseTime.format('MMM D') ? dayJsCloseTime.format('MMM D')

View File

@ -1,15 +1,12 @@
import dayjs, { Dayjs } from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'
import advanced from 'dayjs/plugin/advancedFormat'
import { Tooltip } from './tooltip' import { Tooltip } from './tooltip'
dayjs.extend(utc) const FORMATTER = new Intl.DateTimeFormat('default', {
dayjs.extend(timezone) dateStyle: 'medium',
dayjs.extend(advanced) timeStyle: 'long',
})
export function DateTimeTooltip(props: { export function DateTimeTooltip(props: {
time: Dayjs time: number
text?: string text?: string
className?: string className?: string
children?: React.ReactNode children?: React.ReactNode
@ -17,7 +14,7 @@ export function DateTimeTooltip(props: {
}) { }) {
const { className, time, text, noTap } = props const { className, time, text, noTap } = props
const formattedTime = time.format('MMM DD, YYYY hh:mm a z') const formattedTime = FORMATTER.format(time)
const toolTip = text ? `${text} ${formattedTime}` : formattedTime const toolTip = text ? `${text} ${formattedTime}` : formattedTime
return ( return (

View File

@ -7,7 +7,6 @@ import { fromNow } from 'web/lib/util/time'
import { ToastClipboard } from 'web/components/toast-clipboard' import { ToastClipboard } from 'web/components/toast-clipboard'
import { LinkIcon } from '@heroicons/react/outline' import { LinkIcon } from '@heroicons/react/outline'
import clsx from 'clsx' import clsx from 'clsx'
import dayjs from 'dayjs'
export function CopyLinkDateTimeComponent(props: { export function CopyLinkDateTimeComponent(props: {
prefix: string prefix: string
@ -18,7 +17,6 @@ export function CopyLinkDateTimeComponent(props: {
}) { }) {
const { prefix, slug, elementId, createdTime, className } = props const { prefix, slug, elementId, createdTime, className } = props
const [showToast, setShowToast] = useState(false) const [showToast, setShowToast] = useState(false)
const time = dayjs(createdTime)
function copyLinkToComment( function copyLinkToComment(
event: React.MouseEvent<HTMLAnchorElement, MouseEvent> event: React.MouseEvent<HTMLAnchorElement, MouseEvent>
@ -32,7 +30,7 @@ export function CopyLinkDateTimeComponent(props: {
} }
return ( return (
<div className={clsx('inline', className)}> <div className={clsx('inline', className)}>
<DateTimeTooltip time={time} noTap> <DateTimeTooltip time={createdTime} noTap>
<Link href={`/${prefix}/${slug}#${elementId}`} passHref={true}> <Link href={`/${prefix}/${slug}#${elementId}`} passHref={true}>
<a <a
onClick={(event) => copyLinkToComment(event)} onClick={(event) => copyLinkToComment(event)}

View File

@ -6,13 +6,10 @@ import { useUser, useUserById } from 'web/hooks/use-user'
import { Row } from 'web/components/layout/row' import { Row } from 'web/components/layout/row'
import { Avatar, EmptyAvatar } from 'web/components/avatar' import { Avatar, EmptyAvatar } from 'web/components/avatar'
import clsx from 'clsx' import clsx from 'clsx'
import { UsersIcon } from '@heroicons/react/solid'
import { formatMoney, formatPercent } from 'common/util/format' import { formatMoney, formatPercent } from 'common/util/format'
import { OutcomeLabel } from 'web/components/outcome-label' import { OutcomeLabel } from 'web/components/outcome-label'
import { RelativeTimestamp } from 'web/components/relative-timestamp' import { RelativeTimestamp } from 'web/components/relative-timestamp'
import React, { Fragment, useEffect } from 'react' import React, { useEffect } from 'react'
import { uniqBy, partition, sumBy, groupBy } from 'lodash'
import { JoinSpans } from 'web/components/join-spans'
import { UserLink } from '../user-page' import { UserLink } from '../user-page'
import { formatNumericProbability } from 'common/pseudo-numeric' import { formatNumericProbability } from 'common/pseudo-numeric'
import { SiteLink } from 'web/components/site-link' import { SiteLink } from 'web/components/site-link'
@ -154,79 +151,3 @@ export function BetStatusText(props: {
</div> </div>
) )
} }
function BetGroupSpan(props: {
contract: Contract
bets: Bet[]
outcome?: string
}) {
const { contract, bets, outcome } = props
const numberTraders = uniqBy(bets, (b) => b.userId).length
const [buys, sells] = partition(bets, (bet) => bet.amount >= 0)
const buyTotal = sumBy(buys, (b) => b.amount)
const sellTotal = sumBy(sells, (b) => -b.amount)
return (
<span>
{numberTraders} {numberTraders > 1 ? 'traders' : 'trader'}{' '}
<JoinSpans>
{buyTotal > 0 && <>bought {formatMoney(buyTotal)} </>}
{sellTotal > 0 && <>sold {formatMoney(sellTotal)} </>}
</JoinSpans>
{outcome && (
<>
{' '}
of{' '}
<OutcomeLabel
outcome={outcome}
contract={contract}
truncate="short"
/>
</>
)}{' '}
</span>
)
}
export function FeedBetGroup(props: {
contract: Contract
bets: Bet[]
hideOutcome: boolean
}) {
const { contract, bets, hideOutcome } = props
const betGroups = groupBy(bets, (bet) => bet.outcome)
const outcomes = Object.keys(betGroups)
// Use the time of the last bet for the entire group
const createdTime = bets[bets.length - 1].createdTime
return (
<>
<div>
<div className="relative px-1">
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-gray-200">
<UsersIcon className="h-5 w-5 text-gray-500" aria-hidden="true" />
</div>
</div>
</div>
<div className={clsx('min-w-0 flex-1', outcomes.length === 1 && 'mt-1')}>
<div className="text-sm text-gray-500">
{outcomes.map((outcome, index) => (
<Fragment key={outcome}>
<BetGroupSpan
contract={contract}
outcome={hideOutcome ? undefined : outcome}
bets={betGroups[outcome]}
/>
{index !== outcomes.length - 1 && <br />}
</Fragment>
))}
<RelativeTimestamp time={createdTime} />
</div>
</div>
</>
)
}

View File

@ -8,7 +8,7 @@ export function RelativeTimestamp(props: { time: number }) {
return ( return (
<DateTimeTooltip <DateTimeTooltip
className="ml-1 whitespace-nowrap text-gray-400" className="ml-1 whitespace-nowrap text-gray-400"
time={dayJsTime} time={time}
> >
{dayJsTime.fromNow()} {dayJsTime.fromNow()}
</DateTimeTooltip> </DateTimeTooltip>

View File

@ -11,7 +11,6 @@ import {
useRole, useRole,
} from '@floating-ui/react-dom-interactions' } from '@floating-ui/react-dom-interactions'
import { Transition } from '@headlessui/react' import { Transition } from '@headlessui/react'
import clsx from 'clsx'
import { ReactNode, useRef, useState } from 'react' import { ReactNode, useRef, useState } from 'react'
// See https://floating-ui.com/docs/react-dom // See https://floating-ui.com/docs/react-dom
@ -58,14 +57,10 @@ export function Tooltip(props: {
}[placement.split('-')[0]] as string }[placement.split('-')[0]] as string
return text ? ( return text ? (
<div className="contents"> <>
<div <span className={className} ref={reference} {...getReferenceProps()}>
className={clsx('inline-block', className)}
ref={reference}
{...getReferenceProps()}
>
{children} {children}
</div> </span>
{/* conditionally render tooltip and fade in/out */} {/* conditionally render tooltip and fade in/out */}
<Transition <Transition
show={open} show={open}
@ -95,7 +90,7 @@ export function Tooltip(props: {
}} }}
/> />
</Transition> </Transition>
</div> </>
) : ( ) : (
<>{children}</> <>{children}</>
) )

View File

@ -188,7 +188,7 @@ function Section(props: {
</span> </span>
)} )}
{endTime && ( {endTime && (
<DateTimeTooltip time={endTime} text="Ends"> <DateTimeTooltip time={endTime.valueOf()} text="Ends">
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<ClockIcon className="h-4" /> <ClockIcon className="h-4" />
{endTime.format('MMM D')} {endTime.format('MMM D')}