2022-06-22 16:35:50 +00:00
|
|
|
import { Row } from 'web/components/layout/row'
|
|
|
|
import { Col } from 'web/components/layout/col'
|
2022-08-03 21:38:35 +00:00
|
|
|
import { PrivateUser, User } from 'common/user'
|
2022-06-24 17:16:37 +00:00
|
|
|
import React, { useEffect, memo, useState, useMemo } from 'react'
|
2022-06-22 16:35:50 +00:00
|
|
|
import { Avatar } from 'web/components/avatar'
|
|
|
|
import { Group } from 'common/group'
|
2022-08-19 08:06:40 +00:00
|
|
|
import { Comment, GroupComment } from 'common/comment'
|
|
|
|
import { createCommentOnGroup } from 'web/lib/firebase/comments'
|
2022-08-06 20:39:52 +00:00
|
|
|
import { CommentInputTextArea } from 'web/components/feed/feed-comments'
|
2022-06-22 16:35:50 +00:00
|
|
|
import { track } from 'web/lib/service/analytics'
|
|
|
|
import { firebaseLogin } from 'web/lib/firebase/users'
|
|
|
|
import { useRouter } from 'next/router'
|
|
|
|
import clsx from 'clsx'
|
|
|
|
import { UserLink } from 'web/components/user-page'
|
|
|
|
import { CopyLinkDateTimeComponent } from 'web/components/feed/copy-link-date-time'
|
2022-07-07 23:23:13 +00:00
|
|
|
import { CommentTipMap, CommentTips } from 'web/hooks/use-tip-txns'
|
|
|
|
import { Tipper } from 'web/components/tipper'
|
|
|
|
import { sum } from 'lodash'
|
|
|
|
import { formatMoney } from 'common/util/format'
|
2022-07-11 23:40:25 +00:00
|
|
|
import { useWindowSize } from 'web/hooks/use-window-size'
|
2022-08-06 20:39:52 +00:00
|
|
|
import { Content, useTextEditor } from 'web/components/editor'
|
2022-08-28 20:20:21 +00:00
|
|
|
import { useUnseenNotifications } from 'web/hooks/use-notifications'
|
2022-08-05 12:58:39 +00:00
|
|
|
import { ChevronDownIcon, UsersIcon } from '@heroicons/react/outline'
|
2022-08-03 21:38:35 +00:00
|
|
|
import { setNotificationsAsSeen } from 'web/pages/notifications'
|
2022-08-11 05:00:40 +00:00
|
|
|
import { usePrivateUser } from 'web/hooks/use-user'
|
2022-06-22 16:35:50 +00:00
|
|
|
|
2022-06-24 17:16:37 +00:00
|
|
|
export function GroupChat(props: {
|
2022-08-19 08:06:40 +00:00
|
|
|
messages: GroupComment[]
|
2022-06-22 16:35:50 +00:00
|
|
|
user: User | null | undefined
|
|
|
|
group: Group
|
2022-07-07 23:23:13 +00:00
|
|
|
tips: CommentTipMap
|
2022-06-22 16:35:50 +00:00
|
|
|
}) {
|
2022-07-07 23:23:13 +00:00
|
|
|
const { messages, user, group, tips } = props
|
2022-08-11 05:00:40 +00:00
|
|
|
|
2022-08-12 20:41:00 +00:00
|
|
|
const privateUser = usePrivateUser()
|
2022-08-11 05:00:40 +00:00
|
|
|
|
2022-08-06 20:39:52 +00:00
|
|
|
const { editor, upload } = useTextEditor({
|
|
|
|
simple: true,
|
|
|
|
placeholder: 'Send a message',
|
|
|
|
})
|
2022-06-22 16:35:50 +00:00
|
|
|
const [isSubmitting, setIsSubmitting] = useState(false)
|
|
|
|
const [scrollToBottomRef, setScrollToBottomRef] =
|
|
|
|
useState<HTMLDivElement | null>(null)
|
|
|
|
const [scrollToMessageId, setScrollToMessageId] = useState('')
|
|
|
|
const [scrollToMessageRef, setScrollToMessageRef] =
|
|
|
|
useState<HTMLDivElement | null>(null)
|
2022-08-06 20:39:52 +00:00
|
|
|
const [replyToUser, setReplyToUser] = useState<any>()
|
|
|
|
|
2022-06-22 16:35:50 +00:00
|
|
|
const router = useRouter()
|
2022-07-06 23:24:53 +00:00
|
|
|
const isMember = user && group.memberIds.includes(user?.id)
|
2022-06-22 16:35:50 +00:00
|
|
|
|
2022-08-03 22:16:46 +00:00
|
|
|
const { width, height } = useWindowSize()
|
|
|
|
const [containerRef, setContainerRef] = useState<HTMLDivElement | null>(null)
|
|
|
|
// Subtract bottom bar when it's showing (less than lg screen)
|
2022-08-03 22:42:51 +00:00
|
|
|
const bottomBarHeight = (width ?? 0) < 1024 ? 58 : 0
|
|
|
|
const remainingHeight =
|
|
|
|
(height ?? 0) - (containerRef?.offsetTop ?? 0) - bottomBarHeight
|
2022-08-03 22:16:46 +00:00
|
|
|
|
2022-08-06 20:39:52 +00:00
|
|
|
// array of groups, where each group is an array of messages that are displayed as one
|
|
|
|
const groupedMessages = useMemo(() => {
|
2022-06-24 17:16:37 +00:00
|
|
|
// Group messages with createdTime within 2 minutes of each other.
|
2022-08-19 08:06:40 +00:00
|
|
|
const tempGrouped: GroupComment[][] = []
|
2022-06-24 17:16:37 +00:00
|
|
|
for (let i = 0; i < messages.length; i++) {
|
|
|
|
const message = messages[i]
|
2022-08-06 20:39:52 +00:00
|
|
|
if (i === 0) tempGrouped.push([message])
|
2022-06-24 17:16:37 +00:00
|
|
|
else {
|
|
|
|
const prevMessage = messages[i - 1]
|
|
|
|
const diff = message.createdTime - prevMessage.createdTime
|
|
|
|
const creatorsMatch = message.userId === prevMessage.userId
|
|
|
|
if (diff < 2 * 60 * 1000 && creatorsMatch) {
|
2022-08-06 20:39:52 +00:00
|
|
|
tempGrouped.at(-1)?.push(message)
|
2022-06-24 17:16:37 +00:00
|
|
|
} else {
|
2022-08-06 20:39:52 +00:00
|
|
|
tempGrouped.push([message])
|
2022-06-24 17:16:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-06 20:39:52 +00:00
|
|
|
return tempGrouped
|
2022-06-24 17:16:37 +00:00
|
|
|
}, [messages])
|
|
|
|
|
2022-06-22 16:35:50 +00:00
|
|
|
useEffect(() => {
|
|
|
|
scrollToMessageRef?.scrollIntoView()
|
|
|
|
}, [scrollToMessageRef])
|
|
|
|
|
|
|
|
useEffect(() => {
|
2022-08-03 21:38:35 +00:00
|
|
|
if (scrollToBottomRef)
|
|
|
|
scrollToBottomRef.scrollTo({ top: scrollToBottomRef.scrollHeight || 0 })
|
|
|
|
// Must also listen to groupedMessages as they update the height of the messaging window
|
|
|
|
}, [scrollToBottomRef, groupedMessages])
|
2022-06-22 16:35:50 +00:00
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
const elementInUrl = router.asPath.split('#')[1]
|
|
|
|
if (messages.map((m) => m.id).includes(elementInUrl)) {
|
|
|
|
setScrollToMessageId(elementInUrl)
|
|
|
|
}
|
|
|
|
}, [messages, router.asPath])
|
|
|
|
|
2022-08-03 21:38:35 +00:00
|
|
|
useEffect(() => {
|
2022-08-03 22:16:46 +00:00
|
|
|
// is mobile?
|
2022-08-06 20:39:52 +00:00
|
|
|
if (width && width > 720) focusInput()
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, [width])
|
2022-08-03 21:38:35 +00:00
|
|
|
|
2022-06-22 16:35:50 +00:00
|
|
|
function onReplyClick(comment: Comment) {
|
2022-08-06 20:39:52 +00:00
|
|
|
setReplyToUser({ id: comment.userId, username: comment.userUsername })
|
2022-06-22 16:35:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async function submitMessage() {
|
|
|
|
if (!user) {
|
|
|
|
track('sign in to comment')
|
|
|
|
return await firebaseLogin()
|
|
|
|
}
|
2022-08-06 20:39:52 +00:00
|
|
|
if (!editor || editor.isEmpty || isSubmitting) return
|
2022-06-22 16:35:50 +00:00
|
|
|
setIsSubmitting(true)
|
2022-08-06 20:39:52 +00:00
|
|
|
await createCommentOnGroup(group.id, editor.getJSON(), user)
|
|
|
|
editor.commands.clearContent()
|
2022-06-22 16:35:50 +00:00
|
|
|
setIsSubmitting(false)
|
2022-08-06 20:39:52 +00:00
|
|
|
setReplyToUser(undefined)
|
|
|
|
focusInput()
|
|
|
|
}
|
|
|
|
function focusInput() {
|
|
|
|
editor?.commands.focus()
|
2022-06-22 16:35:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
2022-07-11 23:40:25 +00:00
|
|
|
<Col ref={setContainerRef} style={{ height: remainingHeight }}>
|
2022-06-22 16:35:50 +00:00
|
|
|
<Col
|
|
|
|
className={
|
2022-07-11 23:40:25 +00:00
|
|
|
'w-full flex-1 space-y-2 overflow-x-hidden overflow-y-scroll pt-2'
|
2022-06-22 16:35:50 +00:00
|
|
|
}
|
2022-06-23 17:36:09 +00:00
|
|
|
ref={setScrollToBottomRef}
|
2022-06-22 16:35:50 +00:00
|
|
|
>
|
2022-08-06 20:39:52 +00:00
|
|
|
{groupedMessages.map((messages) => (
|
2022-06-22 16:35:50 +00:00
|
|
|
<GroupMessage
|
|
|
|
user={user}
|
2022-08-06 20:39:52 +00:00
|
|
|
key={`group ${messages[0].id}`}
|
|
|
|
comments={messages}
|
2022-06-22 16:35:50 +00:00
|
|
|
group={group}
|
|
|
|
onReplyClick={onReplyClick}
|
2022-08-06 20:39:52 +00:00
|
|
|
highlight={messages[0].id === scrollToMessageId}
|
2022-06-22 16:35:50 +00:00
|
|
|
setRef={
|
2022-08-06 20:39:52 +00:00
|
|
|
scrollToMessageId === messages[0].id
|
2022-06-22 16:35:50 +00:00
|
|
|
? setScrollToMessageRef
|
|
|
|
: undefined
|
|
|
|
}
|
2022-08-06 20:39:52 +00:00
|
|
|
tips={tips[messages[0].id] ?? {}}
|
2022-06-22 16:35:50 +00:00
|
|
|
/>
|
|
|
|
))}
|
|
|
|
{messages.length === 0 && (
|
|
|
|
<div className="p-2 text-gray-500">
|
2022-07-06 23:24:53 +00:00
|
|
|
No messages yet. Why not{isMember ? ` ` : ' join and '}
|
2022-07-01 13:47:19 +00:00
|
|
|
<button
|
|
|
|
className={'cursor-pointer font-bold text-gray-700'}
|
2022-08-06 20:39:52 +00:00
|
|
|
onClick={focusInput}
|
2022-07-01 13:47:19 +00:00
|
|
|
>
|
|
|
|
add one?
|
|
|
|
</button>
|
2022-06-22 16:35:50 +00:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</Col>
|
|
|
|
{user && group.memberIds.includes(user.id) && (
|
2022-07-11 23:40:25 +00:00
|
|
|
<div className="flex w-full justify-start gap-2 p-2">
|
2022-06-22 16:35:50 +00:00
|
|
|
<div className="mt-1">
|
|
|
|
<Avatar
|
|
|
|
username={user?.username}
|
|
|
|
avatarUrl={user?.avatarUrl}
|
|
|
|
size={'sm'}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<div className={'flex-1'}>
|
|
|
|
<CommentInputTextArea
|
2022-08-06 20:39:52 +00:00
|
|
|
editor={editor}
|
|
|
|
upload={upload}
|
2022-06-22 16:35:50 +00:00
|
|
|
user={user}
|
2022-08-06 20:39:52 +00:00
|
|
|
replyToUser={replyToUser}
|
2022-06-22 16:35:50 +00:00
|
|
|
submitComment={submitMessage}
|
|
|
|
isSubmitting={isSubmitting}
|
2022-08-06 20:39:52 +00:00
|
|
|
submitOnEnter
|
2022-06-22 16:35:50 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)}
|
2022-08-11 05:00:40 +00:00
|
|
|
|
|
|
|
{privateUser && (
|
|
|
|
<GroupChatNotificationsIcon
|
|
|
|
group={group}
|
|
|
|
privateUser={privateUser}
|
|
|
|
shouldSetAsSeen={true}
|
|
|
|
hidden={true}
|
|
|
|
/>
|
|
|
|
)}
|
2022-06-22 16:35:50 +00:00
|
|
|
</Col>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-08-03 21:38:35 +00:00
|
|
|
export function GroupChatInBubble(props: {
|
2022-08-19 08:06:40 +00:00
|
|
|
messages: GroupComment[]
|
2022-08-03 21:38:35 +00:00
|
|
|
user: User | null | undefined
|
|
|
|
privateUser: PrivateUser | null | undefined
|
|
|
|
group: Group
|
|
|
|
tips: CommentTipMap
|
|
|
|
}) {
|
|
|
|
const { messages, user, group, tips, privateUser } = props
|
|
|
|
const [shouldShowChat, setShouldShowChat] = useState(false)
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
const groupsWithChatEmphasis = [
|
|
|
|
'welcome',
|
|
|
|
'bugs',
|
|
|
|
'manifold-features-25bad7c7792e',
|
|
|
|
'updates',
|
|
|
|
]
|
|
|
|
if (
|
|
|
|
router.asPath.includes('/chat') ||
|
|
|
|
groupsWithChatEmphasis.includes(
|
|
|
|
router.asPath.split('/group/')[1].split('/')[0]
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
setShouldShowChat(true)
|
|
|
|
}
|
|
|
|
// Leave chat open between groups if user is using chat?
|
|
|
|
else {
|
|
|
|
setShouldShowChat(false)
|
|
|
|
}
|
|
|
|
}, [router.asPath])
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Col
|
|
|
|
className={clsx(
|
2022-08-04 00:42:40 +00:00
|
|
|
'fixed right-0 bottom-[0px] h-1 w-full sm:bottom-[20px] sm:right-20 sm:w-2/3 md:w-1/2 lg:right-24 lg:w-1/3 xl:right-32 xl:w-1/4',
|
|
|
|
shouldShowChat ? 'p-2m z-10 h-screen bg-white' : ''
|
2022-08-03 21:38:35 +00:00
|
|
|
)}
|
|
|
|
>
|
|
|
|
{shouldShowChat && (
|
|
|
|
<GroupChat messages={messages} user={user} group={group} tips={tips} />
|
|
|
|
)}
|
|
|
|
<button
|
|
|
|
type="button"
|
|
|
|
className={clsx(
|
|
|
|
'fixed right-1 inline-flex items-center rounded-full border md:right-2 lg:right-5 xl:right-10' +
|
|
|
|
' border-transparent p-3 text-white shadow-sm lg:p-4' +
|
|
|
|
' focus:outline-none focus:ring-2 focus:ring-offset-2 ' +
|
|
|
|
' bottom-[70px] ',
|
|
|
|
shouldShowChat
|
|
|
|
? 'bottom-auto top-2 bg-gray-600 hover:bg-gray-400 focus:ring-gray-500 sm:bottom-[70px] sm:top-auto '
|
|
|
|
: ' bg-indigo-600 hover:bg-indigo-700 focus:ring-indigo-500'
|
|
|
|
)}
|
|
|
|
onClick={() => {
|
|
|
|
// router.push('/chat')
|
|
|
|
setShouldShowChat(!shouldShowChat)
|
|
|
|
track('mobile group chat button')
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{!shouldShowChat ? (
|
2022-08-05 12:58:29 +00:00
|
|
|
<UsersIcon className="h-10 w-10" aria-hidden="true" />
|
2022-08-03 21:38:35 +00:00
|
|
|
) : (
|
|
|
|
<ChevronDownIcon className={'h-10 w-10'} aria-hidden={'true'} />
|
|
|
|
)}
|
|
|
|
{privateUser && (
|
|
|
|
<GroupChatNotificationsIcon
|
|
|
|
group={group}
|
|
|
|
privateUser={privateUser}
|
|
|
|
shouldSetAsSeen={shouldShowChat}
|
2022-08-11 05:00:40 +00:00
|
|
|
hidden={false}
|
2022-08-03 21:38:35 +00:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</button>
|
|
|
|
</Col>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
function GroupChatNotificationsIcon(props: {
|
|
|
|
group: Group
|
|
|
|
privateUser: PrivateUser
|
|
|
|
shouldSetAsSeen: boolean
|
2022-08-11 05:00:40 +00:00
|
|
|
hidden: boolean
|
2022-08-03 21:38:35 +00:00
|
|
|
}) {
|
2022-08-11 05:00:40 +00:00
|
|
|
const { privateUser, group, shouldSetAsSeen, hidden } = props
|
2022-08-28 20:20:21 +00:00
|
|
|
const notificationsForThisGroup = useUnseenNotifications(
|
|
|
|
privateUser
|
|
|
|
// Disabled tracking by customHref for now.
|
|
|
|
// {
|
|
|
|
// customHref: `/group/${group.slug}`,
|
|
|
|
// }
|
2022-08-03 21:38:35 +00:00
|
|
|
)
|
2022-08-28 20:20:21 +00:00
|
|
|
|
2022-08-03 21:38:35 +00:00
|
|
|
useEffect(() => {
|
2022-08-28 20:20:21 +00:00
|
|
|
if (!notificationsForThisGroup) return
|
|
|
|
|
|
|
|
notificationsForThisGroup.forEach((notification) => {
|
2022-08-03 21:38:35 +00:00
|
|
|
if (
|
|
|
|
(shouldSetAsSeen && notification.isSeenOnHref?.includes('chat')) ||
|
|
|
|
// old style chat notif that simply ended with the group slug
|
|
|
|
notification.isSeenOnHref?.endsWith(group.slug)
|
|
|
|
) {
|
|
|
|
setNotificationsAsSeen([notification])
|
|
|
|
}
|
|
|
|
})
|
2022-08-28 20:20:21 +00:00
|
|
|
}, [group.slug, notificationsForThisGroup, shouldSetAsSeen])
|
2022-08-03 21:38:35 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className={
|
2022-08-11 05:00:40 +00:00
|
|
|
!hidden &&
|
2022-08-28 20:20:21 +00:00
|
|
|
notificationsForThisGroup &&
|
|
|
|
notificationsForThisGroup.length > 0 &&
|
2022-08-11 05:00:40 +00:00
|
|
|
!shouldSetAsSeen
|
2022-08-03 21:38:35 +00:00
|
|
|
? 'absolute right-4 top-4 h-3 w-3 rounded-full border-2 border-white bg-red-500'
|
|
|
|
: 'hidden'
|
|
|
|
}
|
|
|
|
></div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-06-22 16:35:50 +00:00
|
|
|
const GroupMessage = memo(function GroupMessage_(props: {
|
|
|
|
user: User | null | undefined
|
2022-08-19 08:06:40 +00:00
|
|
|
comments: GroupComment[]
|
2022-06-22 16:35:50 +00:00
|
|
|
group: Group
|
|
|
|
onReplyClick?: (comment: Comment) => void
|
|
|
|
setRef?: (ref: HTMLDivElement) => void
|
|
|
|
highlight?: boolean
|
2022-07-07 23:23:13 +00:00
|
|
|
tips: CommentTips
|
2022-06-22 16:35:50 +00:00
|
|
|
}) {
|
2022-08-06 20:39:52 +00:00
|
|
|
const { comments, onReplyClick, group, setRef, highlight, user, tips } = props
|
|
|
|
const first = comments[0]
|
|
|
|
const { id, userUsername, userName, userAvatarUrl, createdTime } = first
|
|
|
|
|
|
|
|
const isCreatorsComment = user && first.userId === user.id
|
2022-06-22 16:35:50 +00:00
|
|
|
return (
|
2022-06-23 17:36:09 +00:00
|
|
|
<Col
|
2022-06-22 16:35:50 +00:00
|
|
|
ref={setRef}
|
|
|
|
className={clsx(
|
2022-06-24 17:16:37 +00:00
|
|
|
isCreatorsComment ? 'mr-2 self-end' : '',
|
|
|
|
'w-fit max-w-sm gap-1 space-x-3 rounded-md bg-white p-1 text-sm text-gray-500 transition-colors duration-1000 sm:max-w-md sm:p-3 sm:leading-[1.3rem]',
|
2022-06-22 16:35:50 +00:00
|
|
|
highlight ? `-m-1 bg-indigo-500/[0.2] p-2` : ''
|
|
|
|
)}
|
|
|
|
>
|
2022-06-23 17:36:09 +00:00
|
|
|
<Row className={'items-center'}>
|
|
|
|
{!isCreatorsComment && (
|
|
|
|
<Col>
|
|
|
|
<Avatar
|
2022-06-24 17:16:37 +00:00
|
|
|
className={'mx-2 ml-2.5'}
|
|
|
|
size={'xs'}
|
2022-06-23 17:36:09 +00:00
|
|
|
username={userUsername}
|
|
|
|
avatarUrl={userAvatarUrl}
|
|
|
|
/>
|
|
|
|
</Col>
|
|
|
|
)}
|
|
|
|
{!isCreatorsComment ? (
|
|
|
|
<UserLink username={userUsername} name={userName} />
|
|
|
|
) : (
|
2022-06-24 17:16:37 +00:00
|
|
|
<span className={'ml-2.5'}>{'You'}</span>
|
2022-06-23 17:36:09 +00:00
|
|
|
)}
|
|
|
|
<CopyLinkDateTimeComponent
|
|
|
|
prefix={'group'}
|
|
|
|
slug={group.slug}
|
|
|
|
createdTime={createdTime}
|
2022-08-06 20:39:52 +00:00
|
|
|
elementId={id}
|
2022-06-22 16:35:50 +00:00
|
|
|
/>
|
2022-06-23 17:36:09 +00:00
|
|
|
</Row>
|
2022-08-17 17:45:30 +00:00
|
|
|
<div className="mt-2 text-base text-black">
|
2022-08-06 20:39:52 +00:00
|
|
|
{comments.map((comment) => (
|
2022-08-10 17:33:21 +00:00
|
|
|
<Content
|
|
|
|
key={comment.id}
|
|
|
|
content={comment.content || comment.text}
|
|
|
|
smallImage
|
|
|
|
/>
|
2022-08-06 20:39:52 +00:00
|
|
|
))}
|
|
|
|
</div>
|
2022-07-07 23:23:13 +00:00
|
|
|
<Row>
|
|
|
|
{!isCreatorsComment && onReplyClick && (
|
|
|
|
<button
|
|
|
|
className={
|
|
|
|
'self-start py-1 text-xs font-bold text-gray-500 hover:underline'
|
|
|
|
}
|
2022-08-06 20:39:52 +00:00
|
|
|
onClick={() => onReplyClick(first)}
|
2022-07-07 23:23:13 +00:00
|
|
|
>
|
|
|
|
Reply
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
{isCreatorsComment && sum(Object.values(tips)) > 0 && (
|
|
|
|
<span className={'text-primary'}>
|
|
|
|
{formatMoney(sum(Object.values(tips)))}
|
|
|
|
</span>
|
|
|
|
)}
|
2022-08-06 20:39:52 +00:00
|
|
|
{!isCreatorsComment && <Tipper comment={first} tips={tips} />}
|
2022-07-07 23:23:13 +00:00
|
|
|
</Row>
|
2022-06-23 17:36:09 +00:00
|
|
|
</Col>
|
2022-06-22 16:35:50 +00:00
|
|
|
)
|
|
|
|
})
|