refactor replies and full items

This commit is contained in:
keyan 2021-09-23 15:09:07 -05:00
parent e7787e3e67
commit 02c44dca63
9 changed files with 117 additions and 128 deletions

View File

@ -3,7 +3,6 @@ import * as Yup from 'yup'
import { gql, useMutation } from '@apollo/client'
import styles from './reply.module.css'
import TextareaAutosize from 'react-textarea-autosize'
import Countdown from '../components/countdown'
export const CommentSchema = Yup.object({
text: Yup.string().required('required').trim()
@ -53,19 +52,8 @@ export default function CommentEdit ({ comment, editThreshold, onSuccess, onCanc
minRows={4}
autoFocus
required
groupClassName='mb-0'
hint={<Countdown date={editThreshold} />}
/>
<div className='d-flex align-items-center justify-content-between'>
<SubmitButton variant='secondary' className='mt-1'>save</SubmitButton>
<div
className='font-weight-bold text-muted mr-3'
style={{ fontSize: '80%', cursor: 'pointer' }}
onClick={onCancel}
>
cancel
</div>
</div>
<SubmitButton variant='secondary' className='mt-1'>save</SubmitButton>
</Form>
</div>
)

View File

@ -41,9 +41,8 @@ function Parent ({ item, rootText }) {
export default function Comment ({
item, children, replyOpen, includeParent,
rootText, noComments, noReply
rootText, noComments
}) {
const [reply, setReply] = useState(replyOpen)
const [edit, setEdit] = useState()
const [collapse, setCollapse] = useState(false)
const ref = useRef(null)
@ -92,28 +91,36 @@ export default function Comment ({
<span> </span>
<span>{timeSince(new Date(item.createdAt))}</span>
{includeParent && <Parent item={item} rootText={rootText} />}
{canEdit &&
<>
<span> \ </span>
<div
className={styles.edit}
onClick={() => setEdit(!edit)}
>
{edit ? 'cancel' : 'edit'}
<Countdown
date={editThreshold}
onComplete={() => {
setCanEdit(false)
}}
/>
</div>
</>}
</div>
{!includeParent && (collapse
? <Eye className={styles.collapser} height={10} width={10} onClick={() => setCollapse(false)} />
: <EyeClose className={styles.collapser} height={10} width={10} onClick={() => setCollapse(true)} />)}
</div>
{edit
? (
<div className={styles.replyWrapper}>
<CommentEdit
comment={item}
onSuccess={() => {
setEdit(!edit)
setCanEdit(mine && (Date.now() < editThreshold))
}}
onCancel={() => {
setEdit(!edit)
setCanEdit(mine && (Date.now() < editThreshold))
}}
editThreshold={editThreshold}
/>
</div>
<CommentEdit
comment={item}
onSuccess={() => {
setEdit(!edit)
setCanEdit(mine && (Date.now() < editThreshold))
}}
/>
)
: (
<div className={styles.text}>
@ -123,40 +130,9 @@ export default function Comment ({
</div>
</div>
<div className={`${styles.children}`}>
{!noReply && !edit && (
<div className={`${itemStyles.other} ${styles.reply}`}>
<div
className='d-inline-block'
onClick={() => setReply(!reply)}
>
{reply ? 'cancel' : 'reply'}
</div>
{canEdit && !reply && !edit &&
<>
<span> \ </span>
<div
className='d-inline-block'
onClick={() => setEdit(!edit)}
>
edit
<Countdown
date={editThreshold}
className=' '
onComplete={() => {
setCanEdit(false)
}}
/>
</div>
</>}
</div>
)}
<div className={reply ? styles.replyWrapper : 'd-none'}>
<Reply
parentId={item.id} autoFocus={!replyOpen}
onSuccess={() => setReply(replyOpen || false)}
/>
</div>
<Reply
parentId={item.id} replyOpen={replyOpen}
/>
{children}
<div className={`${styles.comments} ml-sm-1 ml-md-3`}>
{item.comments && !noComments

View File

@ -11,6 +11,11 @@
padding-right: 15px;
}
.edit {
display: inline-block;
cursor: pointer;
}
.collapsed .hunk {
margin-bottom: .5rem;
}
@ -33,20 +38,8 @@
user-select: none;
}
.reply {
font-weight: bold;
cursor: pointer;
padding-bottom: .5rem;
}
.replyWrapper {
padding-right: 15px;
padding-bottom: .5rem;
}
.children {
margin-top: 0;
padding-top: .25rem;
margin-left: 24px;
}

View File

@ -2,7 +2,7 @@ import Countdown from 'react-countdown'
export default function SimpleCountdown ({ className, onComplete, date }) {
return (
<span className={className || 'text-muted font-weight-bold'}>
<span className={className}>
<Countdown
date={date}
renderer={props => <span> {props.formatted.minutes}:{props.formatted.seconds}</span>}

View File

@ -10,7 +10,33 @@ import styles from '../styles/item.module.css'
import { NOFOLLOW_LIMIT } from '../lib/constants'
import { useRouter } from 'next/router'
export default function ItemFull ({ item: qItem, minimal }) {
function BioItem ({ item }) {
if (!item.text) {
return null
}
return (
<>
<ItemText item={item} />
<Reply parentId={item.id} />
</>
)
}
function TopLevelItem ({ item }) {
return (
<Item item={item}>
{item.text && <ItemText item={item} />}
<Reply parentId={item.id} replyOpen />
</Item>
)
}
function ItemText ({ item }) {
return <Text nofollow={item.sats + item.boost < NOFOLLOW_LIMIT}>{item.text}</Text>
}
export default function ItemFull ({ item: qItem, bio }) {
const query = gql`
${ITEM_FIELDS}
${COMMENTS}
@ -49,24 +75,9 @@ export default function ItemFull ({ item: qItem, minimal }) {
<>
{item.parentId
? <Comment item={item} replyOpen includeParent noComments />
: (minimal
? (
<>
{item.text &&
<div className='mb-3'>
<Text nofollow={item.sats + item.boost < NOFOLLOW_LIMIT}>{item.text}</Text>
</div>}
</>)
: (
<>
<Item item={item}>
{item.text &&
<div className='mb-3'>
<Text nofollow={item.sats + item.boost < NOFOLLOW_LIMIT}>{item.text}</Text>
</div>}
<Reply parentId={item.id} />
</Item>
</>)
: (bio
? <BioItem item={item} />
: <TopLevelItem item={item} />
)}
<div className={styles.comments}>
<Comments comments={item.comments} />

View File

@ -6,12 +6,14 @@ import { COMMENTS } from '../fragments/comments'
import { useMe } from './me'
import ActionTooltip from './action-tooltip'
import TextareaAutosize from 'react-textarea-autosize'
import { useState } from 'react'
export const CommentSchema = Yup.object({
text: Yup.string().required('required').trim()
})
export default function Reply ({ parentId, onSuccess, autoFocus }) {
export default function Reply ({ parentId, onSuccess, replyOpen }) {
const [reply, setReply] = useState(replyOpen)
const me = useMe()
const [createComment] = useMutation(
@ -47,35 +49,41 @@ export default function Reply ({ parentId, onSuccess, autoFocus }) {
)
return (
<div className={`${styles.reply} mb-1`}>
<Form
initial={{
text: ''
}}
schema={CommentSchema}
onSubmit={async (values, { resetForm }) => {
const { error } = await createComment({ variables: { ...values, parentId } })
if (error) {
throw new Error({ message: error.toString() })
}
resetForm({ text: '' })
if (onSuccess) {
onSuccess()
}
}}
<div>
<div
className={styles.replyButtons}
onClick={() => setReply(!reply)}
>
<MarkdownInput
name='text'
as={TextareaAutosize}
minRows={4}
autoFocus={autoFocus}
required
hint={me?.freeComments ? <span className='text-success'>{me.freeComments} free comments left</span> : null}
/>
<ActionTooltip>
<SubmitButton variant='secondary' className='mt-1'>reply</SubmitButton>
</ActionTooltip>
</Form>
{reply ? 'cancel' : 'reply'}
</div>
<div className={reply ? `${styles.reply}` : 'd-none'}>
<Form
initial={{
text: ''
}}
schema={CommentSchema}
onSubmit={async (values, { resetForm }) => {
const { error } = await createComment({ variables: { ...values, parentId } })
if (error) {
throw new Error({ message: error.toString() })
}
resetForm({ text: '' })
setReply(replyOpen || false)
}}
>
<MarkdownInput
name='text'
as={TextareaAutosize}
minRows={4}
autoFocus={!replyOpen}
required
hint={me?.freeComments ? <span className='text-success'>{me.freeComments} free comments left</span> : null}
/>
<ActionTooltip>
<SubmitButton variant='secondary' className='mt-1'>reply</SubmitButton>
</ActionTooltip>
</Form>
</div>
</div>
)
}

View File

@ -1,5 +1,16 @@
.reply {
max-width: 600px;
padding-right: 15px;
padding-bottom: .5rem;
}
.replyButtons {
font-size: 70%;
color: grey;
font-weight: bold;
display: inline-block;
cursor: pointer;
padding-bottom: .5rem;
}
.skeleton .input {

View File

@ -85,12 +85,14 @@ export default function User ({ user }) {
const [create, setCreate] = useState(false)
const [session] = useSession()
// need to check if this is the user's page
return (
<Layout noSeo containClassName={styles.contain}>
<Seo user={user} />
<UserHeader user={user} />
{user.bio
? <ItemFull item={user.bio} minimal />
? <ItemFull item={user.bio} bio />
: (
<div className={styles.create}>
{create

View File

@ -1,10 +1,10 @@
.comments {
margin-top: 3rem;
margin-top: 1rem;
}
@media only screen and (max-width: 600px) {
.comments {
margin-top: 3rem;
margin-top: 1rem;
margin-left: -15px;
margin-right: -15px;
}