Compare commits
3 Commits
c4b0d4fce5
...
53cc4f0c79
Author | SHA1 | Date | |
---|---|---|---|
|
53cc4f0c79 | ||
|
b21c79b992 | ||
|
a10e9aafd1 |
@ -1,89 +1,118 @@
|
|||||||
import React from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import '../styles/cardMod.css'
|
import '../styles/cardMod.css'
|
||||||
import { handleModImageError } from '../utils'
|
import { handleModImageError } from '../utils'
|
||||||
|
import { ModDetails } from 'types'
|
||||||
|
import { getModPageRoute } from 'routes'
|
||||||
|
import { kinds, nip19 } from 'nostr-tools'
|
||||||
|
import { useDidMount, useReactions } from 'hooks'
|
||||||
|
import { RelayController } from 'controllers'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import { useComments } from 'hooks/useComments'
|
||||||
|
|
||||||
type ModCardProps = {
|
export const ModCard = React.memo((props: ModDetails) => {
|
||||||
title: string
|
const [totalZappedAmount, setTotalZappedAmount] = useState(0)
|
||||||
gameName: string
|
const [commentCount, setCommentCount] = useState(0)
|
||||||
summary: string
|
const { commentEvents } = useComments(props)
|
||||||
imageUrl: string
|
const { likesCount, disLikesCount } = useReactions({
|
||||||
route: string
|
pubkey: props.author,
|
||||||
}
|
eTag: props.id,
|
||||||
|
aTag: props.aTag
|
||||||
|
})
|
||||||
|
|
||||||
export const ModCard = React.memo(
|
useDidMount(() => {
|
||||||
({ title, gameName, summary, imageUrl, route }: ModCardProps) => {
|
RelayController.getInstance()
|
||||||
return (
|
.getTotalZapAmount(props.author, props.id, props.aTag)
|
||||||
<Link className='cardModMainWrapperLink' to={route}>
|
.then((res) => {
|
||||||
<div className='cardModMain'>
|
setTotalZappedAmount(res.accumulatedZapAmount)
|
||||||
<div className='cMMPictureWrapper'>
|
})
|
||||||
<img
|
.catch((err) => {
|
||||||
src={imageUrl}
|
toast.error(err.message || err)
|
||||||
onError={handleModImageError}
|
})
|
||||||
className='cMMPicture'
|
})
|
||||||
/>
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCommentCount(commentEvents.length)
|
||||||
|
}, [commentEvents])
|
||||||
|
|
||||||
|
const route = getModPageRoute(
|
||||||
|
nip19.naddrEncode({
|
||||||
|
identifier: props.aTag,
|
||||||
|
pubkey: props.author,
|
||||||
|
kind: kinds.ClassifiedListing
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link className='cardModMainWrapperLink' to={route}>
|
||||||
|
<div className='cardModMain'>
|
||||||
|
<div className='cMMPictureWrapper'>
|
||||||
|
<img
|
||||||
|
src={props.featuredImageUrl}
|
||||||
|
onError={handleModImageError}
|
||||||
|
className='cMMPicture'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='cMMBody'>
|
||||||
|
<h3 className='cMMBodyTitle'>{props.title}</h3>
|
||||||
|
<p className='cMMBodyText'>{props.summary}</p>
|
||||||
|
<div className='cMMBodyGame'>
|
||||||
|
<p>{props.game}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className='cMMBody'>
|
</div>
|
||||||
<h3 className='cMMBodyTitle'>{title}</h3>
|
<div className='cMMFoot'>
|
||||||
<p className='cMMBodyText'>{summary}</p>
|
<div className='cMMFootReactions'>
|
||||||
<div className='cMMBodyGame'>
|
<div className='cMMFootReactionsElement'>
|
||||||
<p>{gameName}</p>
|
<svg
|
||||||
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
|
viewBox='0 0 512 512'
|
||||||
|
width='1em'
|
||||||
|
height='1em'
|
||||||
|
fill='currentColor'
|
||||||
|
>
|
||||||
|
<path d='M0 190.9V185.1C0 115.2 50.52 55.58 119.4 44.1C164.1 36.51 211.4 51.37 244 84.02L256 96L267.1 84.02C300.6 51.37 347 36.51 392.6 44.1C461.5 55.58 512 115.2 512 185.1V190.9C512 232.4 494.8 272.1 464.4 300.4L283.7 469.1C276.2 476.1 266.3 480 256 480C245.7 480 235.8 476.1 228.3 469.1L47.59 300.4C17.23 272.1 .0003 232.4 .0003 190.9L0 190.9z'></path>
|
||||||
|
</svg>
|
||||||
|
<p>{likesCount}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className='cMMFootReactionsElement'>
|
||||||
<div className='cMMFoot'>
|
<svg
|
||||||
<div className='cMMFootReactions'>
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
<div className='cMMFootReactionsElement'>
|
viewBox='0 0 512 512'
|
||||||
<svg
|
width='1em'
|
||||||
xmlns='http://www.w3.org/2000/svg'
|
height='1em'
|
||||||
viewBox='0 0 512 512'
|
fill='currentColor'
|
||||||
width='1em'
|
>
|
||||||
height='1em'
|
<path d='M512 440.1C512 479.9 479.7 512 439.1 512H71.92C32.17 512 0 479.8 0 440c0-35.88 26.19-65.35 60.56-70.85C43.31 356 32 335.4 32 312C32 272.2 64.25 240 104 240h13.99C104.5 228.2 96 211.2 96 192c0-35.38 28.56-64 63.94-64h16C220.1 128 256 92.12 256 48c0-17.38-5.784-33.35-15.16-46.47C245.8 .7754 250.9 0 256 0c53 0 96 43 96 96c0 11.25-2.288 22-5.913 32h5.879C387.3 128 416 156.6 416 192c0 19.25-8.59 36.25-22.09 48H408C447.8 240 480 272.2 480 312c0 23.38-11.38 44.01-28.63 57.14C485.7 374.6 512 404.3 512 440.1z'></path>
|
||||||
fill='currentColor'
|
</svg>
|
||||||
>
|
<p>{disLikesCount}</p>
|
||||||
<path d='M0 190.9V185.1C0 115.2 50.52 55.58 119.4 44.1C164.1 36.51 211.4 51.37 244 84.02L256 96L267.1 84.02C300.6 51.37 347 36.51 392.6 44.1C461.5 55.58 512 115.2 512 185.1V190.9C512 232.4 494.8 272.1 464.4 300.4L283.7 469.1C276.2 476.1 266.3 480 256 480C245.7 480 235.8 476.1 228.3 469.1L47.59 300.4C17.23 272.1 .0003 232.4 .0003 190.9L0 190.9z'></path>
|
</div>
|
||||||
</svg>
|
<div className='cMMFootReactionsElement'>
|
||||||
<p>420</p>
|
<svg
|
||||||
</div>
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
<div className='cMMFootReactionsElement'>
|
viewBox='0 0 512 512'
|
||||||
<svg
|
width='1em'
|
||||||
xmlns='http://www.w3.org/2000/svg'
|
height='1em'
|
||||||
viewBox='0 0 512 512'
|
fill='currentColor'
|
||||||
width='1em'
|
>
|
||||||
height='1em'
|
<path d='M256 32C114.6 32 .0272 125.1 .0272 240c0 49.63 21.35 94.98 56.97 130.7c-12.5 50.37-54.27 95.27-54.77 95.77c-2.25 2.25-2.875 5.734-1.5 8.734C1.979 478.2 4.75 480 8 480c66.25 0 115.1-31.76 140.6-51.39C181.2 440.9 217.6 448 256 448c141.4 0 255.1-93.13 255.1-208S397.4 32 256 32z'></path>
|
||||||
fill='currentColor'
|
</svg>
|
||||||
>
|
<p>{commentCount}</p>
|
||||||
<path d='M512 440.1C512 479.9 479.7 512 439.1 512H71.92C32.17 512 0 479.8 0 440c0-35.88 26.19-65.35 60.56-70.85C43.31 356 32 335.4 32 312C32 272.2 64.25 240 104 240h13.99C104.5 228.2 96 211.2 96 192c0-35.38 28.56-64 63.94-64h16C220.1 128 256 92.12 256 48c0-17.38-5.784-33.35-15.16-46.47C245.8 .7754 250.9 0 256 0c53 0 96 43 96 96c0 11.25-2.288 22-5.913 32h5.879C387.3 128 416 156.6 416 192c0 19.25-8.59 36.25-22.09 48H408C447.8 240 480 272.2 480 312c0 23.38-11.38 44.01-28.63 57.14C485.7 374.6 512 404.3 512 440.1z'></path>
|
</div>
|
||||||
</svg>
|
<div className='cMMFootReactionsElement'>
|
||||||
<p>420</p>
|
<svg
|
||||||
</div>
|
xmlns='http://www.w3.org/2000/svg'
|
||||||
<div className='cMMFootReactionsElement'>
|
viewBox='-64 0 512 512'
|
||||||
<svg
|
width='1em'
|
||||||
xmlns='http://www.w3.org/2000/svg'
|
height='1em'
|
||||||
viewBox='0 0 512 512'
|
fill='currentColor'
|
||||||
width='1em'
|
>
|
||||||
height='1em'
|
<path d='M240.5 224H352C365.3 224 377.3 232.3 381.1 244.7C386.6 257.2 383.1 271.3 373.1 280.1L117.1 504.1C105.8 513.9 89.27 514.7 77.19 505.9C65.1 497.1 60.7 481.1 66.59 467.4L143.5 288H31.1C18.67 288 6.733 279.7 2.044 267.3C-2.645 254.8 .8944 240.7 10.93 231.9L266.9 7.918C278.2-1.92 294.7-2.669 306.8 6.114C318.9 14.9 323.3 30.87 317.4 44.61L240.5 224z'></path>
|
||||||
fill='currentColor'
|
</svg>
|
||||||
>
|
<p>{totalZappedAmount}</p>
|
||||||
<path d='M256 32C114.6 32 .0272 125.1 .0272 240c0 49.63 21.35 94.98 56.97 130.7c-12.5 50.37-54.27 95.27-54.77 95.77c-2.25 2.25-2.875 5.734-1.5 8.734C1.979 478.2 4.75 480 8 480c66.25 0 115.1-31.76 140.6-51.39C181.2 440.9 217.6 448 256 448c141.4 0 255.1-93.13 255.1-208S397.4 32 256 32z'></path>
|
|
||||||
</svg>
|
|
||||||
<p>420</p>
|
|
||||||
</div>
|
|
||||||
<div className='cMMFootReactionsElement'>
|
|
||||||
<svg
|
|
||||||
xmlns='http://www.w3.org/2000/svg'
|
|
||||||
viewBox='-64 0 512 512'
|
|
||||||
width='1em'
|
|
||||||
height='1em'
|
|
||||||
fill='currentColor'
|
|
||||||
>
|
|
||||||
<path d='M240.5 224H352C365.3 224 377.3 232.3 381.1 244.7C386.6 257.2 383.1 271.3 373.1 280.1L117.1 504.1C105.8 513.9 89.27 514.7 77.19 505.9C65.1 497.1 60.7 481.1 66.59 467.4L143.5 288H31.1C18.67 288 6.733 279.7 2.044 267.3C-2.645 254.8 .8944 240.7 10.93 231.9L266.9 7.918C278.2-1.92 294.7-2.669 306.8 6.114C318.9 14.9 323.3 30.87 317.4 44.61L240.5 224z'></path>
|
|
||||||
</svg>
|
|
||||||
<p>420</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</div>
|
||||||
)
|
</Link>
|
||||||
}
|
)
|
||||||
)
|
})
|
||||||
|
46
src/hooks/useComments.ts
Normal file
46
src/hooks/useComments.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import {
|
||||||
|
MetadataController,
|
||||||
|
RelayController,
|
||||||
|
UserRelaysType
|
||||||
|
} from 'controllers'
|
||||||
|
import { Filter, kinds } from 'nostr-tools'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { CommentEvent, ModDetails } from 'types'
|
||||||
|
import { useDidMount } from './useDidMount'
|
||||||
|
|
||||||
|
export const useComments = (mod: ModDetails) => {
|
||||||
|
const [commentEvents, setCommentEvents] = useState<CommentEvent[]>([])
|
||||||
|
|
||||||
|
useDidMount(async () => {
|
||||||
|
const metadataController = await MetadataController.getInstance()
|
||||||
|
|
||||||
|
const authorReadRelays = await metadataController.findUserRelays(
|
||||||
|
mod.author,
|
||||||
|
UserRelaysType.Read
|
||||||
|
)
|
||||||
|
|
||||||
|
const filter: Filter = {
|
||||||
|
kinds: [kinds.ShortTextNote],
|
||||||
|
'#a': [mod.aTag]
|
||||||
|
}
|
||||||
|
|
||||||
|
RelayController.getInstance().subscribeForEvents(
|
||||||
|
filter,
|
||||||
|
authorReadRelays,
|
||||||
|
(event) => {
|
||||||
|
setCommentEvents((prev) => {
|
||||||
|
if (prev.find((e) => e.id === event.id)) {
|
||||||
|
return [...prev]
|
||||||
|
}
|
||||||
|
|
||||||
|
return [event, ...prev]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
commentEvents,
|
||||||
|
setCommentEvents
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ import { PaginationWithPageNumbers } from 'components/Pagination'
|
|||||||
import { MAX_MODS_PER_PAGE, T_TAG_VALUE } from 'constants.ts'
|
import { MAX_MODS_PER_PAGE, T_TAG_VALUE } from 'constants.ts'
|
||||||
import { RelayController } from 'controllers'
|
import { RelayController } from 'controllers'
|
||||||
import { useAppSelector, useMuteLists } from 'hooks'
|
import { useAppSelector, useMuteLists } from 'hooks'
|
||||||
import { Filter, kinds, nip19 } from 'nostr-tools'
|
import { Filter, kinds } from 'nostr-tools'
|
||||||
import { Subscription } from 'nostr-tools/abstract-relay'
|
import { Subscription } from 'nostr-tools/abstract-relay'
|
||||||
import React, {
|
import React, {
|
||||||
Dispatch,
|
Dispatch,
|
||||||
@ -16,7 +16,6 @@ import React, {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { useParams } from 'react-router-dom'
|
import { useParams } from 'react-router-dom'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { getModPageRoute } from 'routes'
|
|
||||||
import { ModDetails } from 'types'
|
import { ModDetails } from 'types'
|
||||||
import { extractModData, isModDataComplete, log, LogType } from 'utils'
|
import { extractModData, isModDataComplete, log, LogType } from 'utils'
|
||||||
|
|
||||||
@ -179,26 +178,9 @@ export const GamePage = () => {
|
|||||||
/>
|
/>
|
||||||
<div className='IBMSecMain IBMSMListWrapper'>
|
<div className='IBMSecMain IBMSMListWrapper'>
|
||||||
<div className='IBMSMList'>
|
<div className='IBMSMList'>
|
||||||
{currentMods.map((mod) => {
|
{currentMods.map((mod) => (
|
||||||
const route = getModPageRoute(
|
<ModCard key={mod.id} {...mod} />
|
||||||
nip19.naddrEncode({
|
))}
|
||||||
identifier: mod.aTag,
|
|
||||||
pubkey: mod.author,
|
|
||||||
kind: kinds.ClassifiedListing
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ModCard
|
|
||||||
key={mod.id}
|
|
||||||
title={mod.title}
|
|
||||||
gameName={mod.game}
|
|
||||||
summary={mod.summary}
|
|
||||||
imageUrl={mod.featuredImageUrl}
|
|
||||||
route={route}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<PaginationWithPageNumbers
|
<PaginationWithPageNumbers
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Filter, kinds, nip19 } from 'nostr-tools'
|
import { Filter, nip19 } from 'nostr-tools'
|
||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { A11y, Navigation, Pagination, Autoplay } from 'swiper/modules'
|
import { A11y, Autoplay, Navigation, Pagination } from 'swiper/modules'
|
||||||
import { Swiper, SwiperSlide } from 'swiper/react'
|
import { Swiper, SwiperSlide } from 'swiper/react'
|
||||||
import { BlogCard } from '../components/BlogCard'
|
import { BlogCard } from '../components/BlogCard'
|
||||||
import { GameCard } from '../components/GameCard'
|
import { GameCard } from '../components/GameCard'
|
||||||
@ -250,17 +250,7 @@ const DisplayMod = ({ naddr }: DisplayModProps) => {
|
|||||||
|
|
||||||
if (!mod) return <Spinner />
|
if (!mod) return <Spinner />
|
||||||
|
|
||||||
const route = getModPageRoute(naddr)
|
return <ModCard {...mod} />
|
||||||
|
|
||||||
return (
|
|
||||||
<ModCard
|
|
||||||
title={mod.title}
|
|
||||||
gameName={mod.game}
|
|
||||||
summary={mod.summary}
|
|
||||||
imageUrl={mod.featuredImageUrl}
|
|
||||||
route={route}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DisplayLatestMods = () => {
|
const DisplayLatestMods = () => {
|
||||||
@ -291,24 +281,7 @@ const DisplayLatestMods = () => {
|
|||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
latestMods.map((mod) => {
|
latestMods.map((mod) => {
|
||||||
const route = getModPageRoute(
|
return <ModCard key={mod.id} {...mod} />
|
||||||
nip19.naddrEncode({
|
|
||||||
identifier: mod.aTag,
|
|
||||||
pubkey: mod.author,
|
|
||||||
kind: kinds.ClassifiedListing
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ModCard
|
|
||||||
key={mod.id}
|
|
||||||
title={mod.title}
|
|
||||||
gameName={mod.game}
|
|
||||||
summary={mod.summary}
|
|
||||||
imageUrl={mod.featuredImageUrl}
|
|
||||||
route={route}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,19 +6,24 @@ import {
|
|||||||
} from 'controllers'
|
} from 'controllers'
|
||||||
import { formatDate } from 'date-fns'
|
import { formatDate } from 'date-fns'
|
||||||
import { useAppSelector, useDidMount, useReactions } from 'hooks'
|
import { useAppSelector, useDidMount, useReactions } from 'hooks'
|
||||||
import {
|
import { useComments } from 'hooks/useComments'
|
||||||
Event,
|
import { Event, kinds, nip19, UnsignedEvent } from 'nostr-tools'
|
||||||
kinds,
|
import React, {
|
||||||
nip19,
|
Dispatch,
|
||||||
Filter as NostrEventFilter,
|
SetStateAction,
|
||||||
UnsignedEvent
|
useEffect,
|
||||||
} from 'nostr-tools'
|
useMemo,
|
||||||
import React, { useEffect, useMemo } from 'react'
|
useState
|
||||||
import { Dispatch, SetStateAction, useState } from 'react'
|
} from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { getProfilePageRoute } from 'routes'
|
import { getProfilePageRoute } from 'routes'
|
||||||
import { ModDetails, UserProfile } from 'types'
|
import {
|
||||||
|
CommentEvent,
|
||||||
|
CommentEventStatus,
|
||||||
|
ModDetails,
|
||||||
|
UserProfile
|
||||||
|
} from 'types/index.ts'
|
||||||
import { abbreviateNumber, hexToNpub, log, LogType, now } from 'utils'
|
import { abbreviateNumber, hexToNpub, log, LogType, now } from 'utils'
|
||||||
|
|
||||||
enum SortByEnum {
|
enum SortByEnum {
|
||||||
@ -36,23 +41,13 @@ type FilterOptions = {
|
|||||||
author: AuthorFilterEnum
|
author: AuthorFilterEnum
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CommentEventStatus {
|
|
||||||
Publishing = 'Publishing comment...',
|
|
||||||
Published = 'Published!',
|
|
||||||
Failed = 'Failed to publish comment.'
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CommentEvent extends Event {
|
|
||||||
status?: CommentEventStatus
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
modDetails: ModDetails
|
modDetails: ModDetails
|
||||||
setCommentCount: Dispatch<SetStateAction<number>>
|
setCommentCount: Dispatch<SetStateAction<number>>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Comments = ({ modDetails, setCommentCount }: Props) => {
|
export const Comments = ({ modDetails, setCommentCount }: Props) => {
|
||||||
const [commentEvents, setCommentEvents] = useState<CommentEvent[]>([])
|
const { commentEvents, setCommentEvents } = useComments(modDetails)
|
||||||
const [filterOptions, setFilterOptions] = useState<FilterOptions>({
|
const [filterOptions, setFilterOptions] = useState<FilterOptions>({
|
||||||
sort: SortByEnum.Latest,
|
sort: SortByEnum.Latest,
|
||||||
author: AuthorFilterEnum.All_Comments
|
author: AuthorFilterEnum.All_Comments
|
||||||
@ -64,34 +59,6 @@ export const Comments = ({ modDetails, setCommentCount }: Props) => {
|
|||||||
|
|
||||||
const userState = useAppSelector((state) => state.user)
|
const userState = useAppSelector((state) => state.user)
|
||||||
|
|
||||||
useDidMount(async () => {
|
|
||||||
const metadataController = await MetadataController.getInstance()
|
|
||||||
|
|
||||||
const authorReadRelays = await metadataController.findUserRelays(
|
|
||||||
modDetails.author,
|
|
||||||
UserRelaysType.Read
|
|
||||||
)
|
|
||||||
|
|
||||||
const filter: NostrEventFilter = {
|
|
||||||
kinds: [kinds.ShortTextNote],
|
|
||||||
'#a': [modDetails.aTag]
|
|
||||||
}
|
|
||||||
|
|
||||||
RelayController.getInstance().subscribeForEvents(
|
|
||||||
filter,
|
|
||||||
authorReadRelays,
|
|
||||||
(event) => {
|
|
||||||
setCommentEvents((prev) => {
|
|
||||||
if (prev.find((e) => e.id === event.id)) {
|
|
||||||
return [...prev]
|
|
||||||
}
|
|
||||||
|
|
||||||
return [event, ...prev]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleSubmit = async (content: string): Promise<boolean> => {
|
const handleSubmit = async (content: string): Promise<boolean> => {
|
||||||
if (content === '') return false
|
if (content === '') return false
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Pagination } from 'components/Pagination'
|
import { Pagination } from 'components/Pagination'
|
||||||
import { kinds, nip19 } from 'nostr-tools'
|
|
||||||
import React, {
|
import React, {
|
||||||
Dispatch,
|
Dispatch,
|
||||||
SetStateAction,
|
SetStateAction,
|
||||||
@ -15,7 +14,7 @@ import { ModCard } from '../components/ModCard'
|
|||||||
import { MOD_FILTER_LIMIT } from '../constants'
|
import { MOD_FILTER_LIMIT } from '../constants'
|
||||||
import { MetadataController } from '../controllers'
|
import { MetadataController } from '../controllers'
|
||||||
import { useAppSelector, useDidMount, useMuteLists } from '../hooks'
|
import { useAppSelector, useDidMount, useMuteLists } from '../hooks'
|
||||||
import { appRoutes, getModPageRoute } from '../routes'
|
import { appRoutes } from '../routes'
|
||||||
import '../styles/filters.css'
|
import '../styles/filters.css'
|
||||||
import '../styles/pagination.css'
|
import '../styles/pagination.css'
|
||||||
import '../styles/search.css'
|
import '../styles/search.css'
|
||||||
@ -192,26 +191,9 @@ export const ModsPage = () => {
|
|||||||
|
|
||||||
<div className='IBMSecMain IBMSMListWrapper'>
|
<div className='IBMSecMain IBMSMListWrapper'>
|
||||||
<div className='IBMSMList'>
|
<div className='IBMSMList'>
|
||||||
{filteredModList.map((mod) => {
|
{filteredModList.map((mod) => (
|
||||||
const route = getModPageRoute(
|
<ModCard key={mod.id} {...mod} />
|
||||||
nip19.naddrEncode({
|
))}
|
||||||
identifier: mod.aTag,
|
|
||||||
pubkey: mod.author,
|
|
||||||
kind: kinds.ClassifiedListing
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ModCard
|
|
||||||
key={mod.id}
|
|
||||||
title={mod.title}
|
|
||||||
gameName={mod.game}
|
|
||||||
summary={mod.summary}
|
|
||||||
imageUrl={mod.featuredImageUrl}
|
|
||||||
route={route}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
} from 'constants.ts'
|
} from 'constants.ts'
|
||||||
import { RelayController } from 'controllers'
|
import { RelayController } from 'controllers'
|
||||||
import { useAppSelector, useGames, useMuteLists } from 'hooks'
|
import { useAppSelector, useGames, useMuteLists } from 'hooks'
|
||||||
import { Filter, kinds, nip19 } from 'nostr-tools'
|
import { Filter, kinds } from 'nostr-tools'
|
||||||
import { Subscription } from 'nostr-tools/abstract-relay'
|
import { Subscription } from 'nostr-tools/abstract-relay'
|
||||||
import React, {
|
import React, {
|
||||||
Dispatch,
|
Dispatch,
|
||||||
@ -24,7 +24,6 @@ import React, {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { useSearchParams } from 'react-router-dom'
|
import { useSearchParams } from 'react-router-dom'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { getModPageRoute } from 'routes'
|
|
||||||
import { ModDetails, MuteLists } from 'types'
|
import { ModDetails, MuteLists } from 'types'
|
||||||
import { extractModData, isModDataComplete, log, LogType } from 'utils'
|
import { extractModData, isModDataComplete, log, LogType } from 'utils'
|
||||||
|
|
||||||
@ -462,26 +461,9 @@ const ModsResult = ({
|
|||||||
<div className='IBMSMList'>
|
<div className='IBMSMList'>
|
||||||
{filteredModList
|
{filteredModList
|
||||||
.slice((page - 1) * MAX_MODS_PER_PAGE, page * MAX_MODS_PER_PAGE)
|
.slice((page - 1) * MAX_MODS_PER_PAGE, page * MAX_MODS_PER_PAGE)
|
||||||
.map((mod) => {
|
.map((mod) => (
|
||||||
const route = getModPageRoute(
|
<ModCard key={mod.id} {...mod} />
|
||||||
nip19.naddrEncode({
|
))}
|
||||||
identifier: mod.aTag,
|
|
||||||
pubkey: mod.author,
|
|
||||||
kind: kinds.ClassifiedListing
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ModCard
|
|
||||||
key={mod.id}
|
|
||||||
title={mod.title}
|
|
||||||
gameName={mod.game}
|
|
||||||
summary={mod.summary}
|
|
||||||
imageUrl={mod.featuredImageUrl}
|
|
||||||
route={route}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Pagination
|
<Pagination
|
||||||
|
@ -1,3 +1,15 @@
|
|||||||
|
import { Event } from 'nostr-tools'
|
||||||
|
|
||||||
|
export enum CommentEventStatus {
|
||||||
|
Publishing = 'Publishing comment...',
|
||||||
|
Published = 'Published!',
|
||||||
|
Failed = 'Failed to publish comment.'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CommentEvent extends Event {
|
||||||
|
status?: CommentEventStatus
|
||||||
|
}
|
||||||
|
|
||||||
export type Game = {
|
export type Game = {
|
||||||
'Game Name': string
|
'Game Name': string
|
||||||
'16 by 9 image': string
|
'16 by 9 image': string
|
||||||
|
Loading…
Reference in New Issue
Block a user