Fr comment ux improvements (#451)
* Extend comment input box, only use airplane * Only 1 commentable bet, shrink input, fix feed lines * Pad sign in to comment button * Small changes
This commit is contained in:
parent
ad6594f0bc
commit
7e37fc776c
|
@ -29,7 +29,6 @@ export type CommentInputItem = BaseActivityItem & {
|
|||
type: 'commentInput'
|
||||
betsByCurrentUser: Bet[]
|
||||
commentsByCurrentUser: Comment[]
|
||||
answerOutcome?: string
|
||||
}
|
||||
|
||||
export type DescriptionItem = BaseActivityItem & {
|
||||
|
@ -74,10 +73,10 @@ export type BetGroupItem = BaseActivityItem & {
|
|||
|
||||
export type AnswerGroupItem = BaseActivityItem & {
|
||||
type: 'answergroup'
|
||||
user: User | undefined | null
|
||||
answer: Answer
|
||||
items: ActivityItem[]
|
||||
betsByCurrentUser?: Bet[]
|
||||
commentsByCurrentUser?: Comment[]
|
||||
comments: Comment[]
|
||||
bets: Bet[]
|
||||
}
|
||||
|
||||
export type CloseItem = BaseActivityItem & {
|
||||
|
@ -232,31 +231,19 @@ function getAnswerGroups(
|
|||
|
||||
const answerGroups = outcomes
|
||||
.map((outcome) => {
|
||||
const answerBets = bets.filter((bet) => bet.outcome === outcome)
|
||||
const answerComments = comments.filter((comment) =>
|
||||
answerBets.some((bet) => bet.id === comment.betId)
|
||||
)
|
||||
const answer = contract.answers?.find(
|
||||
(answer) => answer.id === outcome
|
||||
) as Answer
|
||||
|
||||
let items = groupBets(answerBets, answerComments, contract, user?.id, {
|
||||
hideOutcome: true,
|
||||
abbreviated,
|
||||
smallAvatar: true,
|
||||
reversed,
|
||||
})
|
||||
|
||||
if (abbreviated)
|
||||
items = items.slice(-ABBREVIATED_NUM_COMMENTS_OR_BETS_TO_SHOW)
|
||||
|
||||
// TODO: this doesn't abbreviate these groups for activity feed anymore
|
||||
return {
|
||||
id: outcome,
|
||||
type: 'answergroup' as const,
|
||||
contract,
|
||||
answer,
|
||||
items,
|
||||
user,
|
||||
answer,
|
||||
comments,
|
||||
bets,
|
||||
}
|
||||
})
|
||||
.filter((group) => group.answer)
|
||||
|
@ -276,7 +263,6 @@ function getAnswerAndCommentInputGroups(
|
|||
outcomes = sortBy(outcomes, (outcome) =>
|
||||
getOutcomeProbability(contract, outcome)
|
||||
)
|
||||
const betsByCurrentUser = bets.filter((bet) => bet.userId === user?.id)
|
||||
|
||||
const answerGroups = outcomes
|
||||
.map((outcome) => {
|
||||
|
@ -284,25 +270,14 @@ function getAnswerAndCommentInputGroups(
|
|||
(answer) => answer.id === outcome
|
||||
) as Answer
|
||||
|
||||
const answerBets = bets.filter((bet) => bet.outcome === outcome)
|
||||
const answerComments = comments.filter(
|
||||
(comment) =>
|
||||
comment.answerOutcome === outcome ||
|
||||
answerBets.some((bet) => bet.id === comment.betId)
|
||||
)
|
||||
const items = getCommentThreads(bets, answerComments, contract)
|
||||
|
||||
return {
|
||||
id: outcome,
|
||||
type: 'answergroup' as const,
|
||||
contract,
|
||||
answer,
|
||||
items,
|
||||
user,
|
||||
betsByCurrentUser,
|
||||
commentsByCurrentUser: answerComments.filter(
|
||||
(comment) => comment.userId === user?.id
|
||||
),
|
||||
answer,
|
||||
comments,
|
||||
bets,
|
||||
}
|
||||
})
|
||||
.filter((group) => group.answer) as ActivityItem[]
|
||||
|
@ -425,13 +400,6 @@ export function getAllContractActivityItems(
|
|||
}
|
||||
)
|
||||
)
|
||||
items.push({
|
||||
type: 'commentInput' as const,
|
||||
id: 'commentInput',
|
||||
contract,
|
||||
betsByCurrentUser: [],
|
||||
commentsByCurrentUser: [],
|
||||
})
|
||||
} else {
|
||||
items.push(
|
||||
...groupBetsAndComments(bets, comments, contract, user?.id, {
|
||||
|
@ -450,16 +418,6 @@ export function getAllContractActivityItems(
|
|||
items.push({ type: 'resolve', id: `${contract.resolutionTime}`, contract })
|
||||
}
|
||||
|
||||
if (outcomeType === 'BINARY') {
|
||||
items.push({
|
||||
type: 'commentInput' as const,
|
||||
id: 'commentInput',
|
||||
contract,
|
||||
betsByCurrentUser: [],
|
||||
commentsByCurrentUser: [],
|
||||
})
|
||||
}
|
||||
|
||||
if (reversed) items.reverse()
|
||||
|
||||
return items
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import { Answer } from 'common/answer'
|
||||
import { ActivityItem } from 'web/components/feed/activity-items'
|
||||
import { Bet } from 'common/bet'
|
||||
import { Comment } from 'common/comment'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { getDpmOutcomeProbability } from 'common/calculate-dpm'
|
||||
import { formatPercent } from 'common/util/format'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
|
@ -16,44 +14,80 @@ import { Linkify } from 'web/components/linkify'
|
|||
import clsx from 'clsx'
|
||||
import { tradingAllowed } from 'web/lib/firebase/contracts'
|
||||
import { BuyButton } from 'web/components/yes-no-selector'
|
||||
import { FeedItem } from 'web/components/feed/feed-items'
|
||||
import {
|
||||
CommentInput,
|
||||
CommentRepliesList,
|
||||
getMostRecentCommentableBet,
|
||||
} from 'web/components/feed/feed-comments'
|
||||
import { CopyLinkDateTimeComponent } from 'web/components/feed/copy-link-date-time'
|
||||
import { useRouter } from 'next/router'
|
||||
import { groupBy } from 'lodash'
|
||||
import { User } from 'common/user'
|
||||
|
||||
export function FeedAnswerCommentGroup(props: {
|
||||
contract: any
|
||||
user: User | undefined | null
|
||||
answer: Answer
|
||||
items: ActivityItem[]
|
||||
type: string
|
||||
betsByCurrentUser?: Bet[]
|
||||
commentsByCurrentUser?: Comment[]
|
||||
comments: Comment[]
|
||||
bets: Bet[]
|
||||
}) {
|
||||
const { answer, items, contract, betsByCurrentUser, commentsByCurrentUser } =
|
||||
props
|
||||
const { answer, contract, comments, bets, user } = props
|
||||
const { username, avatarUrl, name, text } = answer
|
||||
const answerElementId = `answer-${answer.id}`
|
||||
const user = useUser()
|
||||
const mostRecentCommentableBet = getMostRecentCommentableBet(
|
||||
betsByCurrentUser ?? [],
|
||||
commentsByCurrentUser ?? [],
|
||||
user,
|
||||
answer.number + ''
|
||||
)
|
||||
const prob = getDpmOutcomeProbability(contract.totalShares, answer.id)
|
||||
const probPercent = formatPercent(prob)
|
||||
|
||||
const [replyToUsername, setReplyToUsername] = useState('')
|
||||
const [open, setOpen] = useState(false)
|
||||
const [showReply, setShowReply] = useState(false)
|
||||
const isFreeResponseContractPage = !!commentsByCurrentUser
|
||||
if (mostRecentCommentableBet && !showReply) setShowReplyAndFocus(true)
|
||||
const [inputRef, setInputRef] = useState<HTMLTextAreaElement | null>(null)
|
||||
const [highlighted, setHighlighted] = useState(false)
|
||||
const router = useRouter()
|
||||
|
||||
// If they've already opened the input box, focus it once again
|
||||
function setShowReplyAndFocus(show: boolean) {
|
||||
setShowReply(show)
|
||||
const answerElementId = `answer-${answer.id}`
|
||||
const betsByUserId = groupBy(bets, (bet) => bet.userId)
|
||||
const commentsByUserId = groupBy(comments, (comment) => comment.userId)
|
||||
const answerComments = comments.filter(
|
||||
(comment) => comment.answerOutcome === answer.number.toString()
|
||||
)
|
||||
const commentReplies = comments.filter(
|
||||
(comment) =>
|
||||
comment.replyToCommentId &&
|
||||
!comment.answerOutcome &&
|
||||
answerComments.map((c) => c.id).includes(comment.replyToCommentId)
|
||||
)
|
||||
const commentsList = answerComments.concat(commentReplies)
|
||||
|
||||
const prob = getDpmOutcomeProbability(contract.totalShares, answer.id)
|
||||
const probPercent = formatPercent(prob)
|
||||
const betsByCurrentUser = (user && betsByUserId[user.id]) ?? []
|
||||
const commentsByCurrentUser = (user && commentsByUserId[user.id]) ?? []
|
||||
const isFreeResponseContractPage = !!commentsByCurrentUser
|
||||
useEffect(() => {
|
||||
const mostRecentCommentableBet = getMostRecentCommentableBet(
|
||||
betsByCurrentUser,
|
||||
commentsByCurrentUser,
|
||||
user,
|
||||
answer.number.toString()
|
||||
)
|
||||
if (mostRecentCommentableBet && !showReply)
|
||||
scrollAndOpenReplyInput(undefined, answer)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [betsByCurrentUser])
|
||||
|
||||
useEffect(() => {
|
||||
// Only show one comment input for a bet at a time
|
||||
const usersMostRecentBet = bets
|
||||
.filter((b) => b.userId === user?.id)
|
||||
.sort((a, b) => b.createdTime - a.createdTime)[0]
|
||||
if (
|
||||
usersMostRecentBet &&
|
||||
usersMostRecentBet.outcome !== answer.number.toString()
|
||||
) {
|
||||
setShowReply(false)
|
||||
}
|
||||
}, [answer.number, bets, user])
|
||||
|
||||
function scrollAndOpenReplyInput(comment?: Comment, answer?: Answer) {
|
||||
setReplyToUsername(comment?.userUsername ?? answer?.username ?? '')
|
||||
setShowReply(true)
|
||||
inputRef?.focus()
|
||||
}
|
||||
|
||||
|
@ -61,8 +95,6 @@ export function FeedAnswerCommentGroup(props: {
|
|||
if (showReply && inputRef) inputRef.focus()
|
||||
}, [inputRef, showReply])
|
||||
|
||||
const [highlighted, setHighlighted] = useState(false)
|
||||
const router = useRouter()
|
||||
useEffect(() => {
|
||||
if (router.asPath.endsWith(`#${answerElementId}`)) {
|
||||
setHighlighted(true)
|
||||
|
@ -70,7 +102,7 @@ export function FeedAnswerCommentGroup(props: {
|
|||
}, [answerElementId, router.asPath])
|
||||
|
||||
return (
|
||||
<Col className={'flex-1 gap-2'}>
|
||||
<Col className={'relative flex-1 gap-2'}>
|
||||
<Modal open={open} setOpen={setOpen}>
|
||||
<AnswerBetPanel
|
||||
answer={answer}
|
||||
|
@ -113,7 +145,7 @@ export function FeedAnswerCommentGroup(props: {
|
|||
className={
|
||||
'text-xs font-bold text-gray-500 hover:underline'
|
||||
}
|
||||
onClick={() => setShowReplyAndFocus(true)}
|
||||
onClick={() => scrollAndOpenReplyInput(undefined, answer)}
|
||||
>
|
||||
Reply
|
||||
</button>
|
||||
|
@ -143,7 +175,7 @@ export function FeedAnswerCommentGroup(props: {
|
|||
<div className={'justify-initial hidden sm:block'}>
|
||||
<button
|
||||
className={'text-xs font-bold text-gray-500 hover:underline'}
|
||||
onClick={() => setShowReplyAndFocus(true)}
|
||||
onClick={() => scrollAndOpenReplyInput(undefined, answer)}
|
||||
>
|
||||
Reply
|
||||
</button>
|
||||
|
@ -151,36 +183,31 @@ export function FeedAnswerCommentGroup(props: {
|
|||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{items.map((item, index) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className={clsx(
|
||||
'relative ml-8',
|
||||
index !== items.length - 1 && 'pb-4'
|
||||
)}
|
||||
>
|
||||
{index !== items.length - 1 ? (
|
||||
<span
|
||||
className="absolute top-5 left-5 -ml-px h-[calc(100%-1rem)] w-0.5 bg-gray-200"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
) : null}
|
||||
<div className="relative flex items-start space-x-3">
|
||||
<FeedItem item={item} />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<CommentRepliesList
|
||||
contract={contract}
|
||||
commentsList={commentsList}
|
||||
betsByUserId={betsByUserId}
|
||||
smallAvatar={true}
|
||||
truncate={false}
|
||||
bets={bets}
|
||||
scrollAndOpenReplyInput={scrollAndOpenReplyInput}
|
||||
treatFirstIndexEqually={true}
|
||||
/>
|
||||
|
||||
{showReply && (
|
||||
<div className={'ml-8 pt-4'}>
|
||||
<div className={'ml-6 pt-4'}>
|
||||
<span
|
||||
className="absolute -ml-[1px] mt-[0.8rem] h-2 w-0.5 rotate-90 bg-gray-200"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<CommentInput
|
||||
contract={contract}
|
||||
betsByCurrentUser={betsByCurrentUser ?? []}
|
||||
commentsByCurrentUser={commentsByCurrentUser ?? []}
|
||||
answerOutcome={answer.number + ''}
|
||||
replyToUsername={answer.username}
|
||||
betsByCurrentUser={betsByCurrentUser}
|
||||
commentsByCurrentUser={commentsByCurrentUser}
|
||||
parentAnswerOutcome={answer.number.toString()}
|
||||
replyToUsername={replyToUsername}
|
||||
setRef={setInputRef}
|
||||
onSubmitComment={() => setShowReply(false)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Comment } from 'common/comment'
|
|||
import { User } from 'common/user'
|
||||
import { Contract } from 'common/contract'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { minBy, maxBy, groupBy, partition, sumBy } from 'lodash'
|
||||
import { minBy, maxBy, groupBy, partition, sumBy, Dictionary } from 'lodash'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
import { useRouter } from 'next/router'
|
||||
|
@ -54,15 +54,77 @@ export function FeedCommentThread(props: {
|
|||
if (showReply && inputRef) inputRef.focus()
|
||||
}, [inputRef, showReply])
|
||||
return (
|
||||
<div className={'flex-col pr-1'}>
|
||||
<div className={'w-full flex-col pr-1'}>
|
||||
<span
|
||||
className="absolute top-5 left-5 -ml-px h-[calc(100%-2rem)] w-0.5 bg-gray-200"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<CommentRepliesList
|
||||
contract={contract}
|
||||
commentsList={commentsList}
|
||||
betsByUserId={betsByUserId}
|
||||
smallAvatar={smallAvatar}
|
||||
truncate={truncate}
|
||||
bets={bets}
|
||||
scrollAndOpenReplyInput={scrollAndOpenReplyInput}
|
||||
/>
|
||||
{showReply && (
|
||||
<div className={'-pb-2 ml-6 flex flex-col pt-5'}>
|
||||
<span
|
||||
className="absolute -ml-[1px] mt-[0.8rem] h-2 w-0.5 rotate-90 bg-gray-200"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<CommentInput
|
||||
contract={contract}
|
||||
betsByCurrentUser={(user && betsByUserId[user.id]) ?? []}
|
||||
commentsByCurrentUser={comments.filter(
|
||||
(c) => c.userId === user?.id
|
||||
)}
|
||||
parentCommentId={parentComment.id}
|
||||
replyToUsername={replyToUsername}
|
||||
parentAnswerOutcome={comments[0].answerOutcome}
|
||||
setRef={setInputRef}
|
||||
onSubmitComment={() => setShowReply(false)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function CommentRepliesList(props: {
|
||||
contract: Contract
|
||||
commentsList: Comment[]
|
||||
betsByUserId: Dictionary<Bet[]>
|
||||
scrollAndOpenReplyInput: (comment: Comment) => void
|
||||
bets: Bet[]
|
||||
treatFirstIndexEqually?: boolean
|
||||
smallAvatar?: boolean
|
||||
truncate?: boolean
|
||||
}) {
|
||||
const {
|
||||
contract,
|
||||
commentsList,
|
||||
betsByUserId,
|
||||
truncate,
|
||||
smallAvatar,
|
||||
bets,
|
||||
scrollAndOpenReplyInput,
|
||||
treatFirstIndexEqually,
|
||||
} = props
|
||||
return (
|
||||
<>
|
||||
{commentsList.map((comment, commentIdx) => (
|
||||
<div
|
||||
key={comment.id}
|
||||
id={comment.id}
|
||||
className={clsx('relative', commentIdx === 0 ? '' : 'mt-3 ml-6')}
|
||||
className={clsx(
|
||||
'relative',
|
||||
!treatFirstIndexEqually && commentIdx === 0 ? '' : 'mt-3 ml-6'
|
||||
)}
|
||||
>
|
||||
{/*draw a gray line from the comment to the left:*/}
|
||||
{commentIdx != 0 && (
|
||||
{(treatFirstIndexEqually || commentIdx != 0) && (
|
||||
<span
|
||||
className="absolute -ml-[1px] mt-[0.8rem] h-2 w-0.5 rotate-90 bg-gray-200"
|
||||
aria-hidden="true"
|
||||
|
@ -87,24 +149,7 @@ export function FeedCommentThread(props: {
|
|||
/>
|
||||
</div>
|
||||
))}
|
||||
{showReply && (
|
||||
<div className={'-pb-2 ml-6 flex flex-col pt-5'}>
|
||||
<span
|
||||
className="absolute -ml-[1px] mt-[0.8rem] h-2 w-0.5 rotate-90 bg-gray-200"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<CommentInput
|
||||
contract={contract}
|
||||
betsByCurrentUser={(user && betsByUserId[user.id]) ?? []}
|
||||
commentsByCurrentUser={comments}
|
||||
parentComment={parentComment}
|
||||
replyToUsername={replyToUsername}
|
||||
answerOutcome={comments[0].answerOutcome}
|
||||
setRef={setInputRef}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -229,7 +274,13 @@ export function getMostRecentCommentableBet(
|
|||
user?: User | null,
|
||||
answerOutcome?: string
|
||||
) {
|
||||
return betsByCurrentUser
|
||||
let sortedBetsByCurrentUser = betsByCurrentUser.sort(
|
||||
(a, b) => b.createdTime - a.createdTime
|
||||
)
|
||||
if (answerOutcome) {
|
||||
sortedBetsByCurrentUser = sortedBetsByCurrentUser.slice(0, 1)
|
||||
}
|
||||
return sortedBetsByCurrentUser
|
||||
.filter((bet) => {
|
||||
if (
|
||||
canCommentOnBet(bet, user) &&
|
||||
|
@ -238,12 +289,10 @@ export function getMostRecentCommentableBet(
|
|||
)
|
||||
) {
|
||||
if (!answerOutcome) return true
|
||||
// If we're in free response, don't allow commenting on ante bet
|
||||
return answerOutcome === bet.outcome
|
||||
}
|
||||
return false
|
||||
})
|
||||
.sort((b1, b2) => b1.createdTime - b2.createdTime)
|
||||
.pop()
|
||||
}
|
||||
|
||||
|
@ -266,20 +315,22 @@ export function CommentInput(props: {
|
|||
contract: Contract
|
||||
betsByCurrentUser: Bet[]
|
||||
commentsByCurrentUser: Comment[]
|
||||
// Tie a comment to an free response answer outcome
|
||||
answerOutcome?: string
|
||||
// Tie a comment to another comment
|
||||
parentComment?: Comment
|
||||
replyToUsername?: string
|
||||
setRef?: (ref: HTMLTextAreaElement) => void
|
||||
// Reply to a free response answer
|
||||
parentAnswerOutcome?: string
|
||||
// Reply to another comment
|
||||
parentCommentId?: string
|
||||
onSubmitComment?: () => void
|
||||
}) {
|
||||
const {
|
||||
contract,
|
||||
betsByCurrentUser,
|
||||
commentsByCurrentUser,
|
||||
answerOutcome,
|
||||
parentComment,
|
||||
parentAnswerOutcome,
|
||||
parentCommentId,
|
||||
replyToUsername,
|
||||
onSubmitComment,
|
||||
setRef,
|
||||
} = props
|
||||
const user = useUser()
|
||||
|
@ -291,7 +342,7 @@ export function CommentInput(props: {
|
|||
betsByCurrentUser,
|
||||
commentsByCurrentUser,
|
||||
user,
|
||||
answerOutcome
|
||||
parentAnswerOutcome
|
||||
)
|
||||
const { id } = mostRecentCommentableBet || { id: undefined }
|
||||
|
||||
|
@ -312,9 +363,10 @@ export function CommentInput(props: {
|
|||
comment,
|
||||
user,
|
||||
betId,
|
||||
answerOutcome,
|
||||
parentComment?.id
|
||||
parentAnswerOutcome,
|
||||
parentCommentId
|
||||
)
|
||||
onSubmitComment?.()
|
||||
setComment('')
|
||||
setFocused(false)
|
||||
setIsSubmitting(false)
|
||||
|
@ -326,7 +378,7 @@ export function CommentInput(props: {
|
|||
betsByCurrentUser
|
||||
)
|
||||
|
||||
const shouldCollapseAfterClickOutside = false
|
||||
const shouldCollapseAfterClickOutside = !comment
|
||||
|
||||
const isNumeric = contract.outcomeType === 'NUMERIC'
|
||||
|
||||
|
@ -373,74 +425,45 @@ export function CommentInput(props: {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<Row className="grid grid-cols-8 gap-1.5 text-gray-700">
|
||||
<Col
|
||||
<Row className="gap-1.5 text-gray-700">
|
||||
<Textarea
|
||||
ref={setRef}
|
||||
value={comment}
|
||||
onChange={(e) => setComment(e.target.value)}
|
||||
className={clsx(
|
||||
'col-span-8 sm:col-span-6',
|
||||
!user && 'col-span-8'
|
||||
'textarea textarea-bordered w-full resize-none'
|
||||
)}
|
||||
>
|
||||
<Textarea
|
||||
ref={setRef}
|
||||
value={comment}
|
||||
onChange={(e) => setComment(e.target.value)}
|
||||
className={clsx('textarea textarea-bordered resize-none')}
|
||||
placeholder={
|
||||
parentComment || answerOutcome
|
||||
? 'Write a reply... '
|
||||
: 'Write a comment...'
|
||||
placeholder={
|
||||
parentCommentId || parentAnswerOutcome
|
||||
? 'Write a reply... '
|
||||
: 'Write a comment...'
|
||||
}
|
||||
autoFocus={true}
|
||||
onFocus={() => setFocused(true)}
|
||||
onBlur={() =>
|
||||
shouldCollapseAfterClickOutside && setFocused(false)
|
||||
}
|
||||
maxLength={MAX_COMMENT_LENGTH}
|
||||
disabled={isSubmitting}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault()
|
||||
submitComment(id)
|
||||
e.currentTarget.blur()
|
||||
}
|
||||
autoFocus={focused}
|
||||
rows={focused ? 3 : 1}
|
||||
onFocus={() => setFocused(true)}
|
||||
onBlur={() =>
|
||||
shouldCollapseAfterClickOutside && setFocused(false)
|
||||
}
|
||||
maxLength={MAX_COMMENT_LENGTH}
|
||||
disabled={isSubmitting}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault()
|
||||
submitComment(id)
|
||||
e.currentTarget.blur()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
{!user && (
|
||||
<Col
|
||||
className={clsx(
|
||||
'col-span-8 sm:col-span-2',
|
||||
focused ? 'justify-end' : 'justify-center'
|
||||
)}
|
||||
>
|
||||
<button
|
||||
className={
|
||||
'btn btn-outline btn-sm text-transform: capitalize'
|
||||
}
|
||||
onClick={() => submitComment(id)}
|
||||
>
|
||||
Sign in to Comment
|
||||
</button>
|
||||
</Col>
|
||||
)}
|
||||
}}
|
||||
/>
|
||||
|
||||
<Col
|
||||
className={clsx(
|
||||
'col-span-1 sm:col-span-2',
|
||||
focused ? 'justify-end' : 'justify-center'
|
||||
)}
|
||||
>
|
||||
<Col className={clsx(focused ? 'justify-end' : 'justify-center')}>
|
||||
{user && !isSubmitting && (
|
||||
<button
|
||||
className={clsx(
|
||||
'btn btn-ghost btn-sm block flex flex-row capitalize',
|
||||
'absolute bottom-4 right-1 col-span-1',
|
||||
parentComment ? ' bottom-6 right-2.5' : '',
|
||||
'sm:relative sm:bottom-0 sm:right-0 sm:col-span-2',
|
||||
focused && comment
|
||||
? 'sm:btn-outline'
|
||||
: 'pointer-events-none text-gray-500'
|
||||
'btn btn-ghost btn-sm absolute right-2 block flex flex-row capitalize',
|
||||
parentCommentId || parentAnswerOutcome
|
||||
? ' bottom-4'
|
||||
: ' bottom-2',
|
||||
(!focused || !comment) &&
|
||||
'pointer-events-none text-gray-500'
|
||||
)}
|
||||
onClick={() => {
|
||||
if (!focused) return
|
||||
|
@ -449,12 +472,9 @@ export function CommentInput(props: {
|
|||
}
|
||||
}}
|
||||
>
|
||||
<span className={'hidden sm:block'}>
|
||||
{parentComment || answerOutcome ? 'Reply' : 'Comment'}
|
||||
</span>
|
||||
{focused && (
|
||||
<PaperAirplaneIcon
|
||||
className={'m-0 min-w-[22px] rotate-90 p-0 sm:hidden'}
|
||||
className={'m-0 min-w-[22px] rotate-90 p-0 '}
|
||||
height={25}
|
||||
/>
|
||||
)}
|
||||
|
@ -465,6 +485,16 @@ export function CommentInput(props: {
|
|||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
{!user && (
|
||||
<button
|
||||
className={'btn btn-outline btn-sm mt-2 normal-case'}
|
||||
onClick={() => submitComment(id)}
|
||||
>
|
||||
Sign in to comment
|
||||
</button>
|
||||
)}
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
</Row>
|
||||
|
|
Loading…
Reference in New Issue
Block a user