2025-01-29 21:23:29 +01:00
|
|
|
import { Spinner } from 'components/Spinner'
|
|
|
|
import { useNDKContext } from 'hooks'
|
2024-09-23 20:57:29 +05:00
|
|
|
import { useComments } from 'hooks/useComments'
|
2025-01-29 21:23:29 +01:00
|
|
|
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react'
|
|
|
|
import { useLoaderData } from 'react-router-dom'
|
2024-09-23 20:57:29 +05:00
|
|
|
import {
|
2024-11-05 13:57:39 +01:00
|
|
|
Addressable,
|
2025-01-29 21:23:29 +01:00
|
|
|
AuthorFilterEnum,
|
2025-01-28 15:35:30 +01:00
|
|
|
BlogPageLoaderResult,
|
2024-09-23 20:57:29 +05:00
|
|
|
CommentEvent,
|
2025-01-28 15:35:30 +01:00
|
|
|
ModPageLoaderResult,
|
2025-01-29 21:23:29 +01:00
|
|
|
SortByEnum
|
|
|
|
} from 'types'
|
|
|
|
import { handleCommentSubmit } from 'utils'
|
|
|
|
import { Filter, FilterOptions } from './Filter'
|
|
|
|
import { CommentForm } from './CommentForm'
|
|
|
|
import { Comment } from './Comment'
|
2024-09-10 11:41:54 +05:00
|
|
|
|
|
|
|
type Props = {
|
2024-11-05 13:57:39 +01:00
|
|
|
addressable: Addressable
|
2024-09-10 11:41:54 +05:00
|
|
|
setCommentCount: Dispatch<SetStateAction<number>>
|
|
|
|
}
|
|
|
|
|
2024-11-05 13:57:39 +01:00
|
|
|
export const Comments = ({ addressable, setCommentCount }: Props) => {
|
2025-01-28 15:35:30 +01:00
|
|
|
const { ndk } = useNDKContext()
|
2024-11-05 13:57:39 +01:00
|
|
|
const { commentEvents, setCommentEvents } = useComments(
|
|
|
|
addressable.author,
|
|
|
|
addressable.aTag
|
|
|
|
)
|
2025-01-28 15:35:30 +01:00
|
|
|
const { event } = useLoaderData() as
|
|
|
|
| ModPageLoaderResult
|
|
|
|
| BlogPageLoaderResult
|
2024-09-10 11:41:54 +05:00
|
|
|
const [filterOptions, setFilterOptions] = useState<FilterOptions>({
|
|
|
|
sort: SortByEnum.Latest,
|
|
|
|
author: AuthorFilterEnum.All_Comments
|
|
|
|
})
|
|
|
|
|
2024-11-14 14:38:52 +01:00
|
|
|
const [isLoading, setIsLoading] = useState(true)
|
|
|
|
useEffect(() => {
|
2024-11-14 16:50:37 +01:00
|
|
|
// Initial loading to indicate comments fetching (stop after 5 seconds)
|
|
|
|
const t = window.setTimeout(() => setIsLoading(false), 5000)
|
2024-11-14 14:38:52 +01:00
|
|
|
return () => {
|
|
|
|
window.clearTimeout(t)
|
|
|
|
}
|
|
|
|
}, [])
|
|
|
|
|
2024-09-11 16:47:55 +05:00
|
|
|
useEffect(() => {
|
|
|
|
setCommentCount(commentEvents.length)
|
|
|
|
}, [commentEvents, setCommentCount])
|
|
|
|
|
2025-01-29 21:23:29 +01:00
|
|
|
const handleSubmit = handleCommentSubmit(event, setCommentEvents, ndk)
|
2024-09-10 11:41:54 +05:00
|
|
|
|
2024-11-14 16:50:37 +01:00
|
|
|
const handleDiscoveredClick = () => {
|
|
|
|
setVisible(commentEvents)
|
|
|
|
}
|
|
|
|
const [visible, setVisible] = useState<CommentEvent[]>([])
|
|
|
|
useEffect(() => {
|
|
|
|
if (isLoading) {
|
|
|
|
setVisible(commentEvents)
|
|
|
|
}
|
|
|
|
}, [commentEvents, isLoading])
|
|
|
|
|
2024-09-10 11:41:54 +05:00
|
|
|
const comments = useMemo(() => {
|
2024-11-14 16:50:37 +01:00
|
|
|
let filteredComments = visible
|
2024-09-10 11:41:54 +05:00
|
|
|
if (filterOptions.author === AuthorFilterEnum.Creator_Comments) {
|
|
|
|
filteredComments = filteredComments.filter(
|
2025-01-28 15:35:30 +01:00
|
|
|
(comment) => comment.event.pubkey === addressable.author
|
2024-09-10 11:41:54 +05:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (filterOptions.sort === SortByEnum.Latest) {
|
2025-01-28 15:35:30 +01:00
|
|
|
filteredComments.sort((a, b) =>
|
|
|
|
a.event.created_at && b.event.created_at
|
|
|
|
? b.event.created_at - a.event.created_at
|
|
|
|
: 0
|
|
|
|
)
|
2024-09-10 11:41:54 +05:00
|
|
|
} else if (filterOptions.sort === SortByEnum.Oldest) {
|
2025-01-28 15:35:30 +01:00
|
|
|
filteredComments.sort((a, b) =>
|
|
|
|
a.event.created_at && b.event.created_at
|
|
|
|
? a.event.created_at - b.event.created_at
|
|
|
|
: 0
|
|
|
|
)
|
2024-09-10 11:41:54 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
return filteredComments
|
2024-11-14 16:50:37 +01:00
|
|
|
}, [visible, filterOptions.author, filterOptions.sort, addressable.author])
|
2024-09-10 11:41:54 +05:00
|
|
|
|
2024-11-14 16:50:37 +01:00
|
|
|
const discoveredCount = commentEvents.length - visible.length
|
2024-09-10 11:41:54 +05:00
|
|
|
return (
|
|
|
|
<div className='IBMSMSMBSSCommentsWrapper'>
|
|
|
|
<h4 className='IBMSMSMBSSTitle'>Comments</h4>
|
|
|
|
<div className='IBMSMSMBSSComments'>
|
2024-11-13 15:12:45 +01:00
|
|
|
{/* Hide comment form if aTag is missing */}
|
2024-11-13 15:08:43 +01:00
|
|
|
{!!addressable.aTag && <CommentForm handleSubmit={handleSubmit} />}
|
2024-11-14 16:50:37 +01:00
|
|
|
<div>
|
|
|
|
{isLoading ? (
|
|
|
|
<Spinner />
|
|
|
|
) : (
|
|
|
|
<button
|
|
|
|
type='button'
|
|
|
|
className='btnMain'
|
|
|
|
onClick={discoveredCount ? handleDiscoveredClick : undefined}
|
|
|
|
>
|
|
|
|
<span>Load {discoveredCount} discovered comments</span>
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
</div>
|
2024-09-10 11:41:54 +05:00
|
|
|
<Filter
|
|
|
|
filterOptions={filterOptions}
|
|
|
|
setFilterOptions={setFilterOptions}
|
|
|
|
/>
|
|
|
|
<div className='IBMSMSMBSSCommentsList'>
|
2025-01-28 15:35:30 +01:00
|
|
|
{comments.map((comment) => (
|
|
|
|
<Comment key={comment.event.id} comment={comment} />
|
2024-09-10 11:41:54 +05:00
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|