2024-10-14 19:20:43 +05:00
|
|
|
import { NDKFilter, NDKKind } from '@nostr-dev-kit/ndk'
|
2024-08-27 15:53:34 +05:00
|
|
|
import Link from '@tiptap/extension-link'
|
|
|
|
import { EditorContent, useEditor } from '@tiptap/react'
|
|
|
|
import StarterKit from '@tiptap/starter-kit'
|
2024-09-04 11:28:15 +05:00
|
|
|
import FsLightbox from 'fslightbox-react'
|
2024-11-05 16:43:08 +01:00
|
|
|
import { kinds, nip19, UnsignedEvent } from 'nostr-tools'
|
2024-09-10 11:41:54 +05:00
|
|
|
import { useEffect, useRef, useState } from 'react'
|
2024-09-25 21:12:42 +05:00
|
|
|
import { Link as ReactRouterLink, useParams } from 'react-router-dom'
|
2024-08-06 15:46:38 +05:00
|
|
|
import { toast } from 'react-toastify'
|
2024-09-10 11:41:54 +05:00
|
|
|
import { BlogCard } from '../../components/BlogCard'
|
|
|
|
import { LoadingSpinner } from '../../components/LoadingSpinner'
|
|
|
|
import { ProfileSection } from '../../components/ProfileSection'
|
2024-10-21 11:11:35 +02:00
|
|
|
import {
|
|
|
|
useAppSelector,
|
|
|
|
useBodyScrollDisable,
|
|
|
|
useDidMount,
|
2024-10-28 13:46:46 +01:00
|
|
|
useNDKContext,
|
|
|
|
useNSFWList
|
2024-10-21 11:11:35 +02:00
|
|
|
} from '../../hooks'
|
2024-09-25 21:12:42 +05:00
|
|
|
import { getGamePageRoute, getModsEditPageRoute } from '../../routes'
|
2024-09-10 11:41:54 +05:00
|
|
|
import '../../styles/comments.css'
|
|
|
|
import '../../styles/downloads.css'
|
|
|
|
import '../../styles/innerPage.css'
|
|
|
|
import '../../styles/popup.css'
|
|
|
|
import '../../styles/post.css'
|
|
|
|
import '../../styles/reactions.css'
|
|
|
|
import '../../styles/styles.css'
|
|
|
|
import '../../styles/tabs.css'
|
|
|
|
import '../../styles/tags.css'
|
|
|
|
import '../../styles/write.css'
|
2024-11-05 16:43:08 +01:00
|
|
|
import {
|
|
|
|
BlogCardDetails,
|
|
|
|
DownloadUrl,
|
|
|
|
ModDetails,
|
|
|
|
UserRelaysType
|
|
|
|
} from '../../types'
|
2024-08-06 15:46:38 +05:00
|
|
|
import {
|
|
|
|
copyTextToClipboard,
|
2024-08-14 15:06:13 +05:00
|
|
|
downloadFile,
|
2024-08-06 15:46:38 +05:00
|
|
|
extractModData,
|
|
|
|
getFilenameFromUrl,
|
|
|
|
log,
|
2024-08-13 15:51:05 +05:00
|
|
|
LogType,
|
2024-08-28 22:03:43 +05:00
|
|
|
now,
|
|
|
|
npubToHex,
|
|
|
|
sendDMUsingRandomKey,
|
2024-09-10 11:41:54 +05:00
|
|
|
signAndPublish
|
|
|
|
} from '../../utils'
|
2024-11-05 13:57:39 +01:00
|
|
|
import { Comments } from '../../components/comment'
|
2024-10-23 17:39:33 +02:00
|
|
|
import { CheckboxField } from 'components/Inputs'
|
2024-11-05 13:57:39 +01:00
|
|
|
import { PublishDetails } from 'components/Internal/PublishDetails'
|
|
|
|
import { Interactions } from 'components/Internal/Interactions'
|
2024-11-05 16:43:08 +01:00
|
|
|
import { extractBlogCardDetails } from 'utils/blog'
|
2024-08-06 15:46:38 +05:00
|
|
|
|
2024-09-03 15:13:51 +05:00
|
|
|
export const ModPage = () => {
|
2024-08-26 17:11:33 +05:00
|
|
|
const { naddr } = useParams()
|
2024-10-14 19:20:43 +05:00
|
|
|
const { fetchEvent } = useNDKContext()
|
2024-10-28 13:46:46 +01:00
|
|
|
const [mod, setMod] = useState<ModDetails>()
|
2024-07-25 21:12:12 +05:00
|
|
|
const [isFetching, setIsFetching] = useState(true)
|
2024-09-10 11:41:54 +05:00
|
|
|
const [commentCount, setCommentCount] = useState(0)
|
2024-07-25 20:05:28 +05:00
|
|
|
|
2024-10-28 13:46:46 +01:00
|
|
|
// Make sure to mark non-nsfw mods as NSFW if found in nsfwList
|
|
|
|
const nsfwList = useNSFWList()
|
|
|
|
const isMissingNsfwTag =
|
|
|
|
!mod?.nsfw && mod?.aTag && nsfwList && nsfwList.includes(mod.aTag)
|
|
|
|
const modData = isMissingNsfwTag
|
|
|
|
? ({ ...mod, nsfw: true } as ModDetails)
|
|
|
|
: mod
|
|
|
|
|
2024-07-25 20:05:28 +05:00
|
|
|
useDidMount(async () => {
|
2024-08-26 17:11:33 +05:00
|
|
|
if (naddr) {
|
|
|
|
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
|
2024-10-21 16:39:56 +05:00
|
|
|
const { identifier, kind, pubkey } = decoded.data
|
2024-07-25 20:05:28 +05:00
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
const filter: NDKFilter = {
|
2024-08-26 17:11:33 +05:00
|
|
|
'#a': [identifier],
|
|
|
|
authors: [pubkey],
|
|
|
|
kinds: [kind]
|
2024-07-25 20:05:28 +05:00
|
|
|
}
|
|
|
|
|
2024-10-21 16:39:56 +05:00
|
|
|
fetchEvent(filter)
|
2024-07-25 20:05:28 +05:00
|
|
|
.then((event) => {
|
|
|
|
if (event) {
|
|
|
|
const extracted = extractModData(event)
|
2024-10-28 13:46:46 +01:00
|
|
|
setMod(extracted)
|
2024-07-25 20:05:28 +05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
2024-07-25 21:12:12 +05:00
|
|
|
log(
|
|
|
|
true,
|
|
|
|
LogType.Error,
|
|
|
|
'An error occurred in fetching mod details from relays',
|
|
|
|
err
|
|
|
|
)
|
|
|
|
toast.error('An error occurred in fetching mod details from relays')
|
|
|
|
})
|
|
|
|
.finally(() => {
|
|
|
|
setIsFetching(false)
|
2024-07-25 20:05:28 +05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
const oldDownloadListRef = useRef<HTMLDivElement>(null)
|
|
|
|
|
|
|
|
const handleViewOldLinks = () => {
|
|
|
|
if (oldDownloadListRef.current) {
|
|
|
|
// Toggle styles
|
|
|
|
if (oldDownloadListRef.current.style.height === '0px') {
|
|
|
|
// Enable styles
|
|
|
|
oldDownloadListRef.current.style.padding = ''
|
|
|
|
oldDownloadListRef.current.style.height = ''
|
|
|
|
oldDownloadListRef.current.style.border = ''
|
|
|
|
} else {
|
|
|
|
// Disable styles
|
|
|
|
oldDownloadListRef.current.style.padding = '0'
|
|
|
|
oldDownloadListRef.current.style.height = '0'
|
|
|
|
oldDownloadListRef.current.style.border = 'unset'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-25 21:12:12 +05:00
|
|
|
if (isFetching)
|
|
|
|
return <LoadingSpinner desc='Fetching mod details from relays' />
|
|
|
|
|
2024-07-25 20:05:28 +05:00
|
|
|
if (!modData) return null
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className='InnerBodyMain'>
|
|
|
|
<div className='ContainerMain'>
|
|
|
|
<div className='IBMSecMainGroup IBMSecMainGroupAlt'>
|
|
|
|
<div className='IBMSMSplitMain'>
|
|
|
|
<div className='IBMSMSplitMainBigSide'>
|
|
|
|
<div className='IBMSMSplitMainBigSideSec'>
|
2024-08-19 11:41:11 +05:00
|
|
|
<Game
|
2024-08-26 17:11:33 +05:00
|
|
|
naddr={naddr!}
|
2024-08-19 11:41:11 +05:00
|
|
|
game={modData.game}
|
|
|
|
author={modData.author}
|
2024-08-28 22:03:43 +05:00
|
|
|
aTag={modData.aTag}
|
2024-08-19 11:41:11 +05:00
|
|
|
/>
|
2024-07-25 20:45:31 +05:00
|
|
|
<Body
|
|
|
|
featuredImageUrl={modData.featuredImageUrl}
|
|
|
|
title={modData.title}
|
|
|
|
body={modData.body}
|
|
|
|
screenshotsUrls={modData.screenshotsUrls}
|
|
|
|
tags={modData.tags}
|
2024-08-08 21:47:38 +05:00
|
|
|
nsfw={modData.nsfw}
|
2024-07-25 20:45:31 +05:00
|
|
|
/>
|
2024-09-10 11:41:54 +05:00
|
|
|
<Interactions
|
2024-11-05 13:57:39 +01:00
|
|
|
addressable={modData}
|
2024-09-10 11:41:54 +05:00
|
|
|
commentCount={commentCount}
|
|
|
|
/>
|
2024-07-25 20:45:31 +05:00
|
|
|
<PublishDetails
|
|
|
|
published_at={modData.published_at}
|
|
|
|
edited_at={modData.edited_at}
|
2024-08-06 15:46:38 +05:00
|
|
|
site={modData.rTag}
|
2024-07-25 20:45:31 +05:00
|
|
|
/>
|
2024-07-25 20:05:28 +05:00
|
|
|
</div>
|
|
|
|
<div className='IBMSMSplitMainBigSideSec'>
|
|
|
|
<div className='IBMSMSMBSSDownloadsWrapper'>
|
|
|
|
<h4 className='IBMSMSMBSSDownloadsTitle'>Mod Download</h4>
|
|
|
|
{modData.downloadUrls.length > 0 && (
|
|
|
|
<div className='IBMSMSMBSSDownloadsPrime'>
|
2024-08-14 12:08:58 +05:00
|
|
|
<Download {...modData.downloadUrls[0]} />
|
2024-07-25 20:05:28 +05:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
{modData.downloadUrls.length > 1 && (
|
|
|
|
<>
|
|
|
|
<div className='IBMSMSMBSSDownloadsActions'>
|
|
|
|
<button
|
|
|
|
className='btn btnMain'
|
|
|
|
id='viewOldLinks'
|
|
|
|
type='button'
|
|
|
|
onClick={handleViewOldLinks}
|
|
|
|
>
|
|
|
|
View other links
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
ref={oldDownloadListRef}
|
|
|
|
id='oldDownloadList'
|
|
|
|
className='IBMSMSMBSSDownloads'
|
|
|
|
style={{ padding: 0, height: '0px', border: 'unset' }}
|
|
|
|
>
|
|
|
|
{modData.downloadUrls
|
|
|
|
.slice(1)
|
|
|
|
.map((download, index) => (
|
|
|
|
<Download
|
|
|
|
key={`downloadUrl-${index}`}
|
2024-08-14 12:08:58 +05:00
|
|
|
{...download}
|
2024-07-25 20:05:28 +05:00
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
2024-11-05 16:43:08 +01:00
|
|
|
<DisplayModAuthorBlogs />
|
2024-07-25 20:05:28 +05:00
|
|
|
<div className='IBMSMSplitMainBigSideSec'>
|
2024-09-10 11:41:54 +05:00
|
|
|
<Comments
|
2024-11-05 13:57:39 +01:00
|
|
|
addressable={modData}
|
2024-09-10 11:41:54 +05:00
|
|
|
setCommentCount={setCommentCount}
|
|
|
|
/>
|
2024-07-25 20:05:28 +05:00
|
|
|
</div>
|
|
|
|
</div>
|
2024-09-03 13:05:37 +05:00
|
|
|
<ProfileSection pubkey={modData.author} />
|
2024-07-25 20:05:28 +05:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-07-25 20:45:31 +05:00
|
|
|
type GameProps = {
|
2024-08-26 17:11:33 +05:00
|
|
|
naddr: string
|
2024-07-25 20:45:31 +05:00
|
|
|
game: string
|
2024-08-06 15:46:38 +05:00
|
|
|
author: string
|
2024-08-28 22:03:43 +05:00
|
|
|
aTag: string
|
2024-07-25 20:45:31 +05:00
|
|
|
}
|
|
|
|
|
2024-08-28 22:03:43 +05:00
|
|
|
const Game = ({ naddr, game, author, aTag }: GameProps) => {
|
2024-10-21 16:39:56 +05:00
|
|
|
const { ndk, fetchEventFromUserRelays, publish } = useNDKContext()
|
2024-10-14 19:20:43 +05:00
|
|
|
|
2024-08-06 15:46:38 +05:00
|
|
|
const userState = useAppSelector((state) => state.user)
|
2024-08-28 22:03:43 +05:00
|
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
|
|
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
|
|
|
const [showReportPopUp, setShowReportPopUp] = useState(false)
|
2024-08-29 18:26:06 +05:00
|
|
|
const [isBlocked, setIsBlocked] = useState(false)
|
|
|
|
const [isAddedToNSFW, setIsAddedToNSFW] = useState(false)
|
|
|
|
|
2024-10-21 11:11:35 +02:00
|
|
|
useBodyScrollDisable(showReportPopUp)
|
|
|
|
|
2024-08-29 18:26:06 +05:00
|
|
|
useEffect(() => {
|
|
|
|
if (userState.auth && userState.user?.pubkey) {
|
|
|
|
const pubkey = userState.user.pubkey as string
|
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
const muteListFilter: NDKFilter = {
|
|
|
|
kinds: [NDKKind.MuteList],
|
2024-08-29 18:26:06 +05:00
|
|
|
authors: [pubkey]
|
|
|
|
}
|
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
fetchEventFromUserRelays(
|
|
|
|
muteListFilter,
|
|
|
|
pubkey,
|
|
|
|
UserRelaysType.Write
|
|
|
|
).then((event) => {
|
|
|
|
if (event) {
|
|
|
|
// get a list of tags
|
|
|
|
const tags = event.tags
|
|
|
|
const blocked =
|
|
|
|
tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !== -1
|
|
|
|
|
|
|
|
setIsBlocked(blocked)
|
|
|
|
}
|
|
|
|
})
|
2024-08-29 18:26:06 +05:00
|
|
|
|
|
|
|
if (
|
|
|
|
userState.user.npub &&
|
|
|
|
userState.user.npub === import.meta.env.VITE_REPORTING_NPUB
|
|
|
|
) {
|
2024-10-14 19:20:43 +05:00
|
|
|
const nsfwListFilter: NDKFilter = {
|
|
|
|
kinds: [NDKKind.ArticleCurationSet],
|
2024-08-29 18:26:06 +05:00
|
|
|
authors: [pubkey],
|
|
|
|
'#d': ['nsfw']
|
|
|
|
}
|
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
fetchEventFromUserRelays(
|
|
|
|
nsfwListFilter,
|
|
|
|
pubkey,
|
|
|
|
UserRelaysType.Write
|
|
|
|
).then((event) => {
|
|
|
|
if (event) {
|
|
|
|
// get a list of tags
|
|
|
|
const tags = event.tags
|
|
|
|
const existsInNSFWList =
|
|
|
|
tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !==
|
|
|
|
-1
|
|
|
|
|
|
|
|
setIsAddedToNSFW(existsInNSFWList)
|
|
|
|
}
|
|
|
|
})
|
2024-08-29 18:26:06 +05:00
|
|
|
}
|
|
|
|
}
|
2024-10-14 19:20:43 +05:00
|
|
|
}, [userState, aTag, fetchEventFromUserRelays])
|
2024-08-28 22:03:43 +05:00
|
|
|
|
|
|
|
const handleBlock = async () => {
|
|
|
|
let hexPubkey: string
|
|
|
|
|
|
|
|
setIsLoading(true)
|
|
|
|
setLoadingSpinnerDesc('Getting user pubkey')
|
|
|
|
|
|
|
|
if (userState.auth && userState.user?.pubkey) {
|
|
|
|
hexPubkey = userState.user.pubkey as string
|
|
|
|
} else {
|
|
|
|
hexPubkey = (await window.nostr?.getPublicKey()) as string
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hexPubkey) {
|
|
|
|
toast.error('Could not get pubkey for updating mute list')
|
|
|
|
setIsLoading(false)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
setLoadingSpinnerDesc(`Finding user's mute list`)
|
|
|
|
|
|
|
|
// Define the event filter to search for the user's mute list events.
|
|
|
|
// We look for events of a specific kind (Mutelist) authored by the given hexPubkey.
|
2024-10-14 19:20:43 +05:00
|
|
|
const filter: NDKFilter = {
|
|
|
|
kinds: [NDKKind.MuteList],
|
2024-08-28 22:03:43 +05:00
|
|
|
authors: [hexPubkey]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch the mute list event from the relays. This returns the event containing the user's mute list.
|
2024-10-14 19:20:43 +05:00
|
|
|
const muteListEvent = await fetchEventFromUserRelays(
|
|
|
|
filter,
|
|
|
|
hexPubkey,
|
|
|
|
UserRelaysType.Write
|
|
|
|
)
|
2024-08-28 22:03:43 +05:00
|
|
|
|
|
|
|
let unsignedEvent: UnsignedEvent
|
|
|
|
|
|
|
|
if (muteListEvent) {
|
|
|
|
// get a list of tags
|
|
|
|
const tags = muteListEvent.tags
|
|
|
|
const alreadyExists =
|
|
|
|
tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !== -1
|
|
|
|
|
|
|
|
if (alreadyExists) {
|
|
|
|
setIsLoading(false)
|
2024-08-29 18:26:06 +05:00
|
|
|
setIsBlocked(true)
|
2024-08-28 22:03:43 +05:00
|
|
|
return toast.warn(`Mod reference is already in user's mute list`)
|
|
|
|
}
|
|
|
|
|
|
|
|
tags.push(['a', aTag])
|
|
|
|
|
|
|
|
unsignedEvent = {
|
|
|
|
pubkey: muteListEvent.pubkey,
|
2024-10-14 19:20:43 +05:00
|
|
|
kind: NDKKind.MuteList,
|
2024-08-28 22:03:43 +05:00
|
|
|
content: muteListEvent.content,
|
|
|
|
created_at: now(),
|
|
|
|
tags: [...tags]
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unsignedEvent = {
|
|
|
|
pubkey: hexPubkey,
|
2024-10-14 19:20:43 +05:00
|
|
|
kind: NDKKind.MuteList,
|
2024-08-28 22:03:43 +05:00
|
|
|
content: '',
|
|
|
|
created_at: now(),
|
|
|
|
tags: [['a', aTag]]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setLoadingSpinnerDesc('Updating mute list event')
|
|
|
|
|
2024-10-21 16:39:56 +05:00
|
|
|
const isUpdated = await signAndPublish(unsignedEvent, ndk, publish)
|
2024-08-29 18:26:06 +05:00
|
|
|
if (isUpdated) {
|
|
|
|
setIsBlocked(true)
|
|
|
|
}
|
|
|
|
setIsLoading(false)
|
|
|
|
}
|
|
|
|
|
|
|
|
const handleUnblock = async () => {
|
|
|
|
const pubkey = userState.user?.pubkey as string
|
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
const filter: NDKFilter = {
|
|
|
|
kinds: [NDKKind.MuteList],
|
2024-08-29 18:26:06 +05:00
|
|
|
authors: [pubkey]
|
|
|
|
}
|
|
|
|
|
|
|
|
setIsLoading(true)
|
|
|
|
setLoadingSpinnerDesc(`Finding user's mute list`)
|
|
|
|
|
|
|
|
// Fetch the mute list event from the relays. This returns the event containing the user's mute list.
|
2024-10-14 19:20:43 +05:00
|
|
|
const muteListEvent = await fetchEventFromUserRelays(
|
|
|
|
filter,
|
|
|
|
pubkey,
|
|
|
|
UserRelaysType.Write
|
|
|
|
)
|
2024-08-29 18:26:06 +05:00
|
|
|
|
|
|
|
if (!muteListEvent) {
|
|
|
|
toast.error(`Couldn't get user's mute list event from relays`)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
const tags = muteListEvent.tags
|
|
|
|
|
|
|
|
const unsignedEvent: UnsignedEvent = {
|
|
|
|
pubkey: muteListEvent.pubkey,
|
2024-10-14 19:20:43 +05:00
|
|
|
kind: NDKKind.MuteList,
|
2024-08-29 18:26:06 +05:00
|
|
|
content: muteListEvent.content,
|
|
|
|
created_at: now(),
|
|
|
|
tags: tags.filter((item) => item[0] !== 'a' || item[1] !== aTag)
|
|
|
|
}
|
|
|
|
|
|
|
|
setLoadingSpinnerDesc('Updating mute list event')
|
2024-10-21 16:39:56 +05:00
|
|
|
const isUpdated = await signAndPublish(unsignedEvent, ndk, publish)
|
2024-08-29 18:26:06 +05:00
|
|
|
if (isUpdated) {
|
|
|
|
setIsBlocked(false)
|
|
|
|
}
|
|
|
|
|
2024-08-28 22:03:43 +05:00
|
|
|
setIsLoading(false)
|
|
|
|
}
|
|
|
|
|
|
|
|
const handleBlockNSFW = async () => {
|
|
|
|
const pubkey = userState.user?.pubkey as string | undefined
|
|
|
|
|
|
|
|
if (!pubkey) return
|
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
const filter: NDKFilter = {
|
|
|
|
kinds: [NDKKind.ArticleCurationSet],
|
2024-08-28 22:03:43 +05:00
|
|
|
authors: [pubkey],
|
|
|
|
'#d': ['nsfw']
|
|
|
|
}
|
|
|
|
|
|
|
|
setIsLoading(true)
|
|
|
|
setLoadingSpinnerDesc('Finding NSFW list')
|
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
const nsfwListEvent = await fetchEventFromUserRelays(
|
|
|
|
filter,
|
|
|
|
pubkey,
|
|
|
|
UserRelaysType.Write
|
|
|
|
)
|
2024-08-28 22:03:43 +05:00
|
|
|
|
|
|
|
let unsignedEvent: UnsignedEvent
|
|
|
|
|
|
|
|
if (nsfwListEvent) {
|
|
|
|
// get a list of tags
|
|
|
|
const tags = nsfwListEvent.tags
|
|
|
|
const alreadyExists =
|
|
|
|
tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !== -1
|
|
|
|
|
|
|
|
if (alreadyExists) {
|
|
|
|
setIsLoading(false)
|
2024-08-29 18:26:06 +05:00
|
|
|
setIsAddedToNSFW(true)
|
2024-08-28 22:03:43 +05:00
|
|
|
return toast.warn(`Mod reference is already in user's nsfw list`)
|
|
|
|
}
|
|
|
|
|
|
|
|
tags.push(['a', aTag])
|
|
|
|
|
|
|
|
unsignedEvent = {
|
|
|
|
pubkey: nsfwListEvent.pubkey,
|
2024-10-14 19:20:43 +05:00
|
|
|
kind: NDKKind.ArticleCurationSet,
|
2024-08-28 22:03:43 +05:00
|
|
|
content: nsfwListEvent.content,
|
|
|
|
created_at: now(),
|
|
|
|
tags: [...tags]
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unsignedEvent = {
|
|
|
|
pubkey: pubkey,
|
2024-10-14 19:20:43 +05:00
|
|
|
kind: NDKKind.ArticleCurationSet,
|
2024-08-28 22:03:43 +05:00
|
|
|
content: '',
|
|
|
|
created_at: now(),
|
|
|
|
tags: [
|
|
|
|
['a', aTag],
|
|
|
|
['d', 'nsfw']
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setLoadingSpinnerDesc('Updating nsfw list event')
|
|
|
|
|
2024-10-21 16:39:56 +05:00
|
|
|
const isUpdated = await signAndPublish(unsignedEvent, ndk, publish)
|
2024-08-29 18:26:06 +05:00
|
|
|
if (isUpdated) {
|
|
|
|
setIsAddedToNSFW(true)
|
|
|
|
}
|
|
|
|
setIsLoading(false)
|
|
|
|
}
|
|
|
|
|
|
|
|
const handleUnblockNSFW = async () => {
|
|
|
|
const pubkey = userState.user?.pubkey as string
|
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
const filter: NDKFilter = {
|
|
|
|
kinds: [NDKKind.ArticleCurationSet],
|
2024-08-29 18:26:06 +05:00
|
|
|
authors: [pubkey],
|
|
|
|
'#d': ['nsfw']
|
|
|
|
}
|
|
|
|
|
|
|
|
setIsLoading(true)
|
|
|
|
setLoadingSpinnerDesc('Finding NSFW list')
|
|
|
|
|
2024-10-14 19:20:43 +05:00
|
|
|
const nsfwListEvent = await fetchEventFromUserRelays(
|
|
|
|
filter,
|
|
|
|
pubkey,
|
|
|
|
UserRelaysType.Write
|
|
|
|
)
|
2024-08-29 18:26:06 +05:00
|
|
|
|
|
|
|
if (!nsfwListEvent) {
|
|
|
|
toast.error(`Couldn't get nsfw list event from relays`)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
const tags = nsfwListEvent.tags
|
|
|
|
|
|
|
|
const unsignedEvent: UnsignedEvent = {
|
|
|
|
pubkey: nsfwListEvent.pubkey,
|
2024-10-14 19:20:43 +05:00
|
|
|
kind: NDKKind.ArticleCurationSet,
|
2024-08-29 18:26:06 +05:00
|
|
|
content: nsfwListEvent.content,
|
|
|
|
created_at: now(),
|
|
|
|
tags: tags.filter((item) => item[0] !== 'a' || item[1] !== aTag)
|
|
|
|
}
|
|
|
|
|
|
|
|
setLoadingSpinnerDesc('Updating nsfw list event')
|
2024-10-21 16:39:56 +05:00
|
|
|
const isUpdated = await signAndPublish(unsignedEvent, ndk, publish)
|
2024-08-29 18:26:06 +05:00
|
|
|
if (isUpdated) {
|
|
|
|
setIsAddedToNSFW(false)
|
|
|
|
}
|
|
|
|
|
2024-08-28 22:03:43 +05:00
|
|
|
setIsLoading(false)
|
|
|
|
}
|
|
|
|
|
|
|
|
const isAdmin =
|
|
|
|
userState.user?.npub &&
|
|
|
|
userState.user.npub === import.meta.env.VITE_REPORTING_NPUB
|
2024-08-06 15:46:38 +05:00
|
|
|
|
2024-09-25 21:12:42 +05:00
|
|
|
const gameRoute = getGamePageRoute(game)
|
|
|
|
const editRoute = getModsEditPageRoute(naddr)
|
|
|
|
|
2024-07-25 20:45:31 +05:00
|
|
|
return (
|
2024-08-28 22:03:43 +05:00
|
|
|
<>
|
|
|
|
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
|
|
|
<div className='IBMSMSMBSSModFor'>
|
|
|
|
<p className='IBMSMSMBSSModForPara'>
|
|
|
|
Mod for:
|
2024-09-25 21:12:42 +05:00
|
|
|
<ReactRouterLink className='IBMSMSMBSSModForLink' to={gameRoute}>
|
2024-08-28 22:03:43 +05:00
|
|
|
{game}
|
2024-09-25 21:12:42 +05:00
|
|
|
</ReactRouterLink>
|
2024-08-28 22:03:43 +05:00
|
|
|
</p>
|
|
|
|
<div className='dropdown dropdownMain' style={{ flexGrow: 'unset' }}>
|
|
|
|
<button
|
|
|
|
className='btn btnMain btnMainDropdown'
|
|
|
|
aria-expanded='false'
|
|
|
|
data-bs-toggle='dropdown'
|
|
|
|
type='button'
|
|
|
|
style={{
|
|
|
|
borderRadius: '5px',
|
|
|
|
background: 'unset',
|
|
|
|
padding: '5px'
|
|
|
|
}}
|
2024-07-25 20:45:31 +05:00
|
|
|
>
|
2024-08-28 22:03:43 +05:00
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='-192 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
>
|
|
|
|
<path d='M64 360C94.93 360 120 385.1 120 416C120 446.9 94.93 472 64 472C33.07 472 8 446.9 8 416C8 385.1 33.07 360 64 360zM64 200C94.93 200 120 225.1 120 256C120 286.9 94.93 312 64 312C33.07 312 8 286.9 8 256C8 225.1 33.07 200 64 200zM64 152C33.07 152 8 126.9 8 96C8 65.07 33.07 40 64 40C94.93 40 120 65.07 120 96C120 126.9 94.93 152 64 152z'></path>
|
|
|
|
</svg>
|
|
|
|
</button>
|
|
|
|
<div className={`dropdown-menu dropdown-menu-end dropdownMainMenu`}>
|
|
|
|
{userState.auth && userState.user?.pubkey === author && (
|
2024-09-25 21:12:42 +05:00
|
|
|
<ReactRouterLink
|
2024-08-28 22:03:43 +05:00
|
|
|
className='dropdown-item dropdownMainMenuItem'
|
2024-09-25 21:12:42 +05:00
|
|
|
to={editRoute}
|
2024-08-28 22:03:43 +05:00
|
|
|
>
|
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='0 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMSSS_Author_Top_Icon'
|
|
|
|
>
|
|
|
|
<path d='M362.7 19.32C387.7-5.678 428.3-5.678 453.3 19.32L492.7 58.75C517.7 83.74 517.7 124.3 492.7 149.3L444.3 197.7L314.3 67.72L362.7 19.32zM421.7 220.3L188.5 453.4C178.1 463.8 165.2 471.5 151.1 475.6L30.77 511C22.35 513.5 13.24 511.2 7.03 504.1C.8198 498.8-1.502 489.7 .976 481.2L36.37 360.9C40.53 346.8 48.16 333.9 58.57 323.5L291.7 90.34L421.7 220.3z'></path>
|
|
|
|
</svg>
|
|
|
|
Edit
|
2024-09-25 21:12:42 +05:00
|
|
|
</ReactRouterLink>
|
2024-08-28 22:03:43 +05:00
|
|
|
)}
|
|
|
|
|
2024-08-06 15:46:38 +05:00
|
|
|
<a
|
|
|
|
className='dropdown-item dropdownMainMenuItem'
|
2024-08-28 22:03:43 +05:00
|
|
|
onClick={() => {
|
|
|
|
copyTextToClipboard(window.location.href).then((isCopied) => {
|
|
|
|
if (isCopied) toast.success('Url copied to clipboard!')
|
|
|
|
})
|
|
|
|
}}
|
2024-08-06 15:46:38 +05:00
|
|
|
>
|
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='0 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMSSS_Author_Top_Icon'
|
|
|
|
>
|
2024-08-28 22:03:43 +05:00
|
|
|
<path d='M384 96L384 0h-112c-26.51 0-48 21.49-48 48v288c0 26.51 21.49 48 48 48H464c26.51 0 48-21.49 48-48V128h-95.1C398.4 128 384 113.6 384 96zM416 0v96h96L416 0zM192 352V128h-144c-26.51 0-48 21.49-48 48v288c0 26.51 21.49 48 48 48h192c26.51 0 48-21.49 48-48L288 416h-32C220.7 416 192 387.3 192 352z'></path>
|
2024-08-06 15:46:38 +05:00
|
|
|
</svg>
|
2024-08-28 22:03:43 +05:00
|
|
|
Copy URL
|
2024-08-06 15:46:38 +05:00
|
|
|
</a>
|
2024-08-28 22:03:43 +05:00
|
|
|
<a className='dropdown-item dropdownMainMenuItem' href='#'>
|
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='0 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMSSS_Author_Top_Icon'
|
|
|
|
>
|
|
|
|
<path d='M503.7 226.2l-176 151.1c-15.38 13.3-39.69 2.545-39.69-18.16V272.1C132.9 274.3 66.06 312.8 111.4 457.8c5.031 16.09-14.41 28.56-28.06 18.62C39.59 444.6 0 383.8 0 322.3c0-152.2 127.4-184.4 288-186.3V56.02c0-20.67 24.28-31.46 39.69-18.16l176 151.1C514.8 199.4 514.8 216.6 503.7 226.2z'></path>
|
|
|
|
</svg>
|
|
|
|
Share
|
|
|
|
</a>
|
|
|
|
<a
|
|
|
|
className='dropdown-item dropdownMainMenuItem'
|
|
|
|
id='reportPost'
|
|
|
|
onClick={() => setShowReportPopUp(true)}
|
2024-07-25 20:45:31 +05:00
|
|
|
>
|
2024-08-28 22:03:43 +05:00
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='0 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMSSS_Author_Top_Icon'
|
|
|
|
>
|
|
|
|
<path d='M506.3 417l-213.3-364c-16.33-28-57.54-28-73.98 0l-213.2 364C-10.59 444.9 9.849 480 42.74 480h426.6C502.1 480 522.6 445 506.3 417zM232 168c0-13.25 10.75-24 24-24S280 154.8 280 168v128c0 13.25-10.75 24-23.1 24S232 309.3 232 296V168zM256 416c-17.36 0-31.44-14.08-31.44-31.44c0-17.36 14.07-31.44 31.44-31.44s31.44 14.08 31.44 31.44C287.4 401.9 273.4 416 256 416z'></path>
|
|
|
|
</svg>
|
|
|
|
Report
|
|
|
|
</a>
|
|
|
|
<a
|
|
|
|
className='dropdown-item dropdownMainMenuItem'
|
2024-08-29 18:26:06 +05:00
|
|
|
onClick={isBlocked ? handleUnblock : handleBlock}
|
2024-07-25 20:45:31 +05:00
|
|
|
>
|
2024-08-28 22:03:43 +05:00
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='-32 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMSSS_Author_Top_Icon'
|
|
|
|
>
|
|
|
|
<path d='M323.5 51.25C302.8 70.5 284 90.75 267.4 111.1C240.1 73.62 206.2 35.5 168 0C69.75 91.12 0 210 0 281.6C0 408.9 100.2 512 224 512s224-103.1 224-230.4C448 228.4 396 118.5 323.5 51.25zM304.1 391.9C282.4 407 255.8 416 226.9 416c-72.13 0-130.9-47.73-130.9-125.2c0-38.63 24.24-72.64 65.13-83.3c10.14-2.656 19.94 4.78 19.94 15.27c0 6.941-4.469 13.16-11.16 15.19c-17.5 4.578-34.41 23.94-34.41 52.84c0 50.81 39.31 94.81 91.41 94.81c24.66 0 45.22-6.5 63.19-18.75c11.75-8 27.91 3.469 23.91 16.69C314.6 384.7 309.8 388.4 304.1 391.9z'></path>
|
|
|
|
</svg>
|
2024-08-29 18:26:06 +05:00
|
|
|
{isBlocked ? 'Unblock' : 'Block'} Post
|
2024-08-28 22:03:43 +05:00
|
|
|
</a>
|
|
|
|
{isAdmin && (
|
|
|
|
<a
|
|
|
|
className='dropdown-item dropdownMainMenuItem'
|
2024-08-29 18:26:06 +05:00
|
|
|
onClick={isAddedToNSFW ? handleUnblockNSFW : handleBlockNSFW}
|
2024-08-28 22:03:43 +05:00
|
|
|
>
|
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='-32 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMSSS_Author_Top_Icon'
|
|
|
|
>
|
|
|
|
<path d='M323.5 51.25C302.8 70.5 284 90.75 267.4 111.1C240.1 73.62 206.2 35.5 168 0C69.75 91.12 0 210 0 281.6C0 408.9 100.2 512 224 512s224-103.1 224-230.4C448 228.4 396 118.5 323.5 51.25zM304.1 391.9C282.4 407 255.8 416 226.9 416c-72.13 0-130.9-47.73-130.9-125.2c0-38.63 24.24-72.64 65.13-83.3c10.14-2.656 19.94 4.78 19.94 15.27c0 6.941-4.469 13.16-11.16 15.19c-17.5 4.578-34.41 23.94-34.41 52.84c0 50.81 39.31 94.81 91.41 94.81c24.66 0 45.22-6.5 63.19-18.75c11.75-8 27.91 3.469 23.91 16.69C314.6 384.7 309.8 388.4 304.1 391.9z'></path>
|
|
|
|
</svg>
|
2024-08-29 18:26:06 +05:00
|
|
|
{isAddedToNSFW ? 'Un-mark' : 'Mark'} as NSFW
|
2024-08-28 22:03:43 +05:00
|
|
|
</a>
|
|
|
|
)}
|
|
|
|
</div>
|
2024-07-25 20:45:31 +05:00
|
|
|
</div>
|
|
|
|
</div>
|
2024-08-28 22:03:43 +05:00
|
|
|
{showReportPopUp && (
|
|
|
|
<ReportPopup
|
|
|
|
aTag={aTag}
|
|
|
|
handleClose={() => setShowReportPopUp(false)}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
type ReportPopupProps = {
|
|
|
|
aTag: string
|
|
|
|
handleClose: () => void
|
|
|
|
}
|
|
|
|
|
2024-10-23 17:39:33 +02:00
|
|
|
const MOD_REPORT_REASONS = [
|
|
|
|
{ label: 'Actually CP', key: 'actuallyCP' },
|
|
|
|
{ label: 'Spam', key: 'spam' },
|
|
|
|
{ label: 'Scam', key: 'scam' },
|
|
|
|
{ label: 'Not a game mod', key: 'notAGameMod' },
|
|
|
|
{ label: 'Stolen game mod', key: 'stolenGameMod' },
|
|
|
|
{ label: `Wasn't tagged NSFW`, key: 'wasntTaggedNSFW' },
|
|
|
|
{ label: 'Other reason', key: 'otherReason' }
|
|
|
|
]
|
|
|
|
|
2024-08-28 22:03:43 +05:00
|
|
|
const ReportPopup = ({ aTag, handleClose }: ReportPopupProps) => {
|
2024-10-21 16:39:56 +05:00
|
|
|
const { ndk, fetchEventFromUserRelays, publish } = useNDKContext()
|
2024-08-28 22:03:43 +05:00
|
|
|
const userState = useAppSelector((state) => state.user)
|
2024-10-23 17:39:33 +02:00
|
|
|
const [selectedOptions, setSelectedOptions] = useState(
|
|
|
|
MOD_REPORT_REASONS.reduce((acc: { [key: string]: boolean }, cur) => {
|
|
|
|
acc[cur.key] = false
|
|
|
|
return acc
|
|
|
|
}, {})
|
|
|
|
)
|
2024-08-28 22:03:43 +05:00
|
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
|
|
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
|
|
|
|
|
|
|
const handleCheckboxChange = (option: keyof typeof selectedOptions) => {
|
|
|
|
setSelectedOptions((prevState) => ({
|
|
|
|
...prevState,
|
|
|
|
[option]: !prevState[option]
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
const handleSubmit = async () => {
|
|
|
|
const selectedOptionsCount = Object.values(selectedOptions).filter(
|
|
|
|
(isSelected) => isSelected
|
|
|
|
).length
|
|
|
|
|
|
|
|
if (selectedOptionsCount === 0) {
|
|
|
|
toast.error('At least one option should be checked!')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
let hexPubkey: string
|
|
|
|
|
|
|
|
setIsLoading(true)
|
|
|
|
setLoadingSpinnerDesc('Getting user pubkey')
|
|
|
|
|
|
|
|
if (userState.auth && userState.user?.pubkey) {
|
|
|
|
hexPubkey = userState.user.pubkey as string
|
|
|
|
} else {
|
|
|
|
hexPubkey = (await window.nostr?.getPublicKey()) as string
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hexPubkey) {
|
|
|
|
toast.error('Could not get pubkey for reporting mod!')
|
|
|
|
setIsLoading(false)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-10-21 17:51:00 +05:00
|
|
|
const reportingNpub = import.meta.env.VITE_REPORTING_NPUB
|
|
|
|
const reportingPubkey = npubToHex(reportingNpub)
|
2024-08-28 22:03:43 +05:00
|
|
|
|
|
|
|
if (reportingPubkey === hexPubkey) {
|
|
|
|
setLoadingSpinnerDesc(`Finding user's mute list`)
|
|
|
|
// Define the event filter to search for the user's mute list events.
|
|
|
|
// We look for events of a specific kind (Mutelist) authored by the given hexPubkey.
|
2024-10-14 19:20:43 +05:00
|
|
|
const filter: NDKFilter = {
|
|
|
|
kinds: [NDKKind.MuteList],
|
2024-08-28 22:03:43 +05:00
|
|
|
authors: [hexPubkey]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch the mute list event from the relays. This returns the event containing the user's mute list.
|
2024-10-14 19:20:43 +05:00
|
|
|
const muteListEvent = await fetchEventFromUserRelays(
|
|
|
|
filter,
|
|
|
|
hexPubkey,
|
|
|
|
UserRelaysType.Write
|
|
|
|
)
|
2024-08-28 22:03:43 +05:00
|
|
|
|
|
|
|
let unsignedEvent: UnsignedEvent
|
|
|
|
|
|
|
|
if (muteListEvent) {
|
|
|
|
// get a list of tags
|
|
|
|
const tags = muteListEvent.tags
|
|
|
|
const alreadyExists =
|
|
|
|
tags.findIndex((item) => item[0] === 'a' && item[1] === aTag) !== -1
|
|
|
|
|
|
|
|
if (alreadyExists) {
|
|
|
|
setIsLoading(false)
|
|
|
|
return toast.warn(`Mod reference is already in user's mute list`)
|
|
|
|
}
|
|
|
|
|
|
|
|
tags.push(['a', aTag])
|
|
|
|
|
|
|
|
unsignedEvent = {
|
|
|
|
pubkey: muteListEvent.pubkey,
|
2024-10-14 19:20:43 +05:00
|
|
|
kind: NDKKind.MuteList,
|
2024-08-28 22:03:43 +05:00
|
|
|
content: muteListEvent.content,
|
|
|
|
created_at: now(),
|
|
|
|
tags: [...tags]
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unsignedEvent = {
|
|
|
|
pubkey: hexPubkey,
|
2024-10-14 19:20:43 +05:00
|
|
|
kind: NDKKind.MuteList,
|
2024-08-28 22:03:43 +05:00
|
|
|
content: '',
|
|
|
|
created_at: now(),
|
|
|
|
tags: [['a', aTag]]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setLoadingSpinnerDesc('Updating mute list event')
|
2024-10-21 16:39:56 +05:00
|
|
|
const isUpdated = await signAndPublish(unsignedEvent, ndk, publish)
|
2024-08-28 22:03:43 +05:00
|
|
|
if (isUpdated) handleClose()
|
|
|
|
} else {
|
|
|
|
const href = window.location.href
|
|
|
|
let message = `I'd like to report ${href} due to following reasons:\n`
|
|
|
|
|
|
|
|
Object.entries(selectedOptions).forEach(([key, value]) => {
|
|
|
|
if (value) {
|
|
|
|
message += `* ${key}\n`
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
setLoadingSpinnerDesc('Sending report')
|
2024-10-21 16:39:56 +05:00
|
|
|
const isSent = await sendDMUsingRandomKey(
|
|
|
|
message,
|
|
|
|
reportingPubkey!,
|
|
|
|
ndk,
|
|
|
|
publish
|
|
|
|
)
|
2024-08-28 22:03:43 +05:00
|
|
|
if (isSent) handleClose()
|
|
|
|
}
|
|
|
|
setIsLoading(false)
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
|
|
|
<div className='popUpMain'>
|
|
|
|
<div className='ContainerMain'>
|
|
|
|
<div className='popUpMainCardWrapper'>
|
|
|
|
<div className='popUpMainCard popUpMainCardQR'>
|
|
|
|
<div className='popUpMainCardTop'>
|
|
|
|
<div className='popUpMainCardTopInfo'>
|
|
|
|
<h3>Report Post</h3>
|
|
|
|
</div>
|
|
|
|
<div className='popUpMainCardTopClose' onClick={handleClose}>
|
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='-96 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
style={{ zIndex: 1 }}
|
|
|
|
>
|
|
|
|
<path d='M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z'></path>
|
|
|
|
</svg>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className='pUMCB_Zaps'>
|
|
|
|
<div className='pUMCB_ZapsInside'>
|
|
|
|
<div className='inputLabelWrapperMain'>
|
|
|
|
<label
|
|
|
|
className='form-label labelMain'
|
|
|
|
style={{ fontWeight: 'bold' }}
|
|
|
|
>
|
|
|
|
Why are you reporting this?
|
|
|
|
</label>
|
2024-10-23 17:39:33 +02:00
|
|
|
{MOD_REPORT_REASONS.map((r) => (
|
|
|
|
<CheckboxField
|
|
|
|
key={r.key}
|
|
|
|
label={r.label}
|
|
|
|
name={r.key}
|
|
|
|
isChecked={selectedOptions[r.key]}
|
|
|
|
handleChange={() => handleCheckboxChange(r.key)}
|
2024-08-28 17:40:33 +00:00
|
|
|
/>
|
2024-10-23 17:39:33 +02:00
|
|
|
))}
|
2024-08-28 22:03:43 +05:00
|
|
|
</div>
|
|
|
|
<button
|
|
|
|
className='btn btnMain pUMCB_Report'
|
|
|
|
type='button'
|
|
|
|
style={{ width: '100%' }}
|
|
|
|
onClick={handleSubmit}
|
|
|
|
>
|
|
|
|
Submit Report
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</>
|
2024-07-25 20:45:31 +05:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
type BodyProps = {
|
|
|
|
featuredImageUrl: string
|
|
|
|
title: string
|
|
|
|
body: string
|
|
|
|
screenshotsUrls: string[]
|
|
|
|
tags: string[]
|
2024-08-08 21:47:38 +05:00
|
|
|
nsfw: boolean
|
2024-07-25 20:45:31 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
const Body = ({
|
|
|
|
featuredImageUrl,
|
|
|
|
title,
|
|
|
|
body,
|
|
|
|
screenshotsUrls,
|
2024-08-08 21:47:38 +05:00
|
|
|
tags,
|
|
|
|
nsfw
|
2024-07-25 20:45:31 +05:00
|
|
|
}: BodyProps) => {
|
|
|
|
const postBodyRef = useRef<HTMLDivElement>(null)
|
|
|
|
const viewFullPostBtnRef = useRef<HTMLDivElement>(null)
|
|
|
|
|
2024-08-29 23:01:41 +05:00
|
|
|
const [lightBoxController, setLightBoxController] = useState({
|
|
|
|
toggler: false,
|
|
|
|
slide: 1
|
|
|
|
})
|
|
|
|
|
|
|
|
const openLightBoxOnSlide = (slide: number) => {
|
|
|
|
setLightBoxController((prev) => ({
|
|
|
|
toggler: !prev.toggler,
|
|
|
|
slide
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2024-07-25 20:45:31 +05:00
|
|
|
const viewFullPost = () => {
|
|
|
|
if (postBodyRef.current && viewFullPostBtnRef.current) {
|
|
|
|
postBodyRef.current.style.maxHeight = 'unset'
|
|
|
|
postBodyRef.current.style.padding = 'unset'
|
|
|
|
viewFullPostBtnRef.current.style.display = 'none'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-27 15:53:34 +05:00
|
|
|
const editor = useEditor({
|
|
|
|
content: body,
|
|
|
|
extensions: [StarterKit, Link],
|
|
|
|
editable: false
|
|
|
|
})
|
|
|
|
|
2024-07-25 20:45:31 +05:00
|
|
|
return (
|
2024-08-29 23:01:41 +05:00
|
|
|
<>
|
|
|
|
<div className='IBMSMSMBSSPost'>
|
2024-07-25 20:45:31 +05:00
|
|
|
<div
|
2024-08-29 23:01:41 +05:00
|
|
|
className='IBMSMSMBSSPostPicture'
|
|
|
|
style={{
|
|
|
|
background: `url(${featuredImageUrl}) center / cover no-repeat`
|
|
|
|
}}
|
|
|
|
></div>
|
|
|
|
<div className='IBMSMSMBSSPostInside'>
|
|
|
|
<div className='IBMSMSMBSSPostTitle'>
|
|
|
|
<h1 className='IBMSMSMBSSPostTitleHeading'>{title}</h1>
|
2024-07-25 20:45:31 +05:00
|
|
|
</div>
|
2024-08-29 23:01:41 +05:00
|
|
|
<div
|
|
|
|
ref={postBodyRef}
|
|
|
|
className='IBMSMSMBSSPostBody'
|
|
|
|
style={{ maxHeight: '250px', padding: '0 10px' }}
|
|
|
|
>
|
|
|
|
<EditorContent editor={editor} />
|
|
|
|
<div ref={viewFullPostBtnRef} className='IBMSMSMBSSPostBodyHide'>
|
2024-11-21 20:45:27 +00:00
|
|
|
<div className='IBMSMSMBSSPostBodyHideText'>
|
|
|
|
<p onClick={viewFullPost}>Read Full</p>
|
|
|
|
</div>
|
2024-08-08 21:47:38 +05:00
|
|
|
</div>
|
2024-08-29 23:01:41 +05:00
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSShots'>
|
|
|
|
{screenshotsUrls.map((url, index) => (
|
|
|
|
<img
|
|
|
|
className='IBMSMSMBSSShotsImg'
|
|
|
|
src={url}
|
|
|
|
alt={`ScreenShot-${index}`}
|
|
|
|
key={url}
|
|
|
|
onClick={() => openLightBoxOnSlide(index + 1)}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSTags'>
|
|
|
|
{nsfw && (
|
|
|
|
<div className='IBMSMSMBSSTagsTag IBMSMSMBSSTagsTagNSFW'>
|
|
|
|
<p>NSFW</p>
|
|
|
|
</div>
|
|
|
|
)}
|
2024-08-08 21:47:38 +05:00
|
|
|
|
2024-08-29 23:01:41 +05:00
|
|
|
{tags.map((tag, index) => (
|
|
|
|
<a className='IBMSMSMBSSTagsTag' href='#' key={`tag-${index}`}>
|
|
|
|
{tag}
|
|
|
|
</a>
|
|
|
|
))}
|
|
|
|
</div>
|
2024-07-25 20:45:31 +05:00
|
|
|
</div>
|
|
|
|
</div>
|
2024-08-29 23:01:41 +05:00
|
|
|
<FsLightbox
|
|
|
|
toggler={lightBoxController.toggler}
|
|
|
|
sources={screenshotsUrls}
|
|
|
|
slide={lightBoxController.slide}
|
|
|
|
/>
|
|
|
|
</>
|
2024-07-25 20:45:31 +05:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-08-14 12:08:58 +05:00
|
|
|
const Download = ({
|
|
|
|
url,
|
|
|
|
hash,
|
|
|
|
signatureKey,
|
|
|
|
malwareScanLink,
|
|
|
|
modVersion,
|
|
|
|
customNote
|
|
|
|
}: DownloadUrl) => {
|
|
|
|
const [showAuthDetails, setShowAuthDetails] = useState(false)
|
2024-07-25 20:05:28 +05:00
|
|
|
|
2024-08-06 15:46:38 +05:00
|
|
|
const handleDownload = () => {
|
|
|
|
// Get the filename from the URL
|
|
|
|
const filename = getFilenameFromUrl(url)
|
|
|
|
|
2024-08-14 15:06:13 +05:00
|
|
|
downloadFile(url, filename)
|
2024-08-06 15:46:38 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className='IBMSMSMBSSDownloadsElement'>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInside'>
|
|
|
|
<button
|
|
|
|
className='btn btnMain IBMSMSMBSSDownloadsElementBtn'
|
|
|
|
type='button'
|
|
|
|
onClick={handleDownload}
|
|
|
|
>
|
|
|
|
Download
|
|
|
|
</button>
|
|
|
|
</div>
|
2024-09-24 09:17:25 +00:00
|
|
|
{/*temporarily commented out the WoT rating for download links within a mod post
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInside'>
|
|
|
|
<p>Ratings (WIP):</p>
|
|
|
|
<div className='tabsMain'>
|
|
|
|
<ul className='nav nav-tabs tabsMainTop' role='tablist'>
|
|
|
|
<li className='nav-item tabsMainTopTab' role='presentation'>
|
|
|
|
<a
|
|
|
|
className='nav-link active tabsMainTopTabLink'
|
|
|
|
role='tab'
|
|
|
|
data-bs-toggle='tab'
|
|
|
|
href='#tab-1'
|
|
|
|
>
|
|
|
|
WoT
|
|
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li className='nav-item tabsMainTopTab' role='presentation'>
|
|
|
|
<a
|
|
|
|
className='nav-link tabsMainTopTabLink'
|
|
|
|
role='tab'
|
|
|
|
data-bs-toggle='tab'
|
|
|
|
href='#tab-2'
|
|
|
|
>
|
|
|
|
All
|
|
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
<div className='tab-content tabsMainBottom'>
|
|
|
|
<div
|
|
|
|
className='tab-pane active tabsMainBottomContent'
|
|
|
|
role='tabpanel'
|
|
|
|
id='tab-1'
|
|
|
|
>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideReactions'>
|
|
|
|
<div
|
|
|
|
data-bs-toggle='tooltip'
|
|
|
|
data-bss-tooltip=''
|
|
|
|
className='IBMSMSMBSSDEIReactionsElement IBMSMSMBSSDEIReactionsElementActive'
|
|
|
|
title='Clean'
|
|
|
|
>
|
|
|
|
<div className='IBMSMSMBSSDEIReactionsElementIconWrapper'>
|
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='0 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMBSSDEIReactionsElementIcon'
|
|
|
|
>
|
|
|
|
<path d='M512 165.4c0 127.9-70.05 235.3-175.3 270.1c-20.04 7.938-41.83 12.46-64.69 12.46c-64.9 0-125.2-36.51-155.7-94.47c-54.13 49.93-68.71 107-68.96 108.1C44.72 472.6 34.87 480 24.02 480c-1.844 0-3.727-.2187-5.602-.6562c-12.89-3.098-20.84-16.08-17.75-28.96c9.598-39.5 90.47-226.4 335.3-226.4C344.8 224 352 216.8 352 208S344.8 192 336 192C228.6 192 151 226.6 96.29 267.6c.1934-10.82 1.242-21.84 3.535-33.05c13.47-65.81 66.04-119 131.4-134.2c28.33-6.562 55.68-6.013 80.93-.0054c56 13.32 118.2-7.412 149.3-61.24c5.664-9.828 20.02-9.516 24.66 .8282C502.7 76.76 512 121.9 512 165.4z' />
|
|
|
|
</svg>
|
|
|
|
</div>
|
|
|
|
<p className='IBMSMSMBSSDEIReactionsElementText'>420</p>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
data-bs-toggle='tooltip'
|
|
|
|
data-bss-tooltip=''
|
|
|
|
className='IBMSMSMBSSDEIReactionsElement'
|
|
|
|
title='Broken link'
|
|
|
|
>
|
|
|
|
<div className='IBMSMSMBSSDEIReactionsElementIconWrapper'>
|
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='0 -64 640 640'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMBSSDEIReactionsElementIcon'
|
|
|
|
>
|
|
|
|
<path d='M185.7 120.3C242.5 75.82 324.7 79.73 376.1 131.1C420.1 175.1 430.9 239.6 406.7 293.5L438.6 318.4L534.5 222.5C566 191 566 139.1 534.5 108.5C506.7 80.63 462.7 76.1 430.7 99.9L429.1 101C414.7 111.3 394.7 107.1 384.5 93.58C374.2 79.2 377.5 59.21 391.9 48.94L393.5 47.82C451 6.732 529.8 13.25 579.8 63.24C636.3 119.7 636.3 211.3 579.8 267.7L489.3 358.2L630.8 469.1C641.2 477.3 643.1 492.4 634.9 502.8C626.7 513.2 611.6 515.1 601.2 506.9L9.196 42.89C-1.236 34.71-3.065 19.63 5.112 9.196C13.29-1.236 28.37-3.065 38.81 5.112L185.7 120.3zM238.1 161.1L353.4 251.7C359.3 225.5 351.7 197.2 331.7 177.2C306.6 152.1 269.1 147 238.1 161.1V161.1zM263 380C233.1 350.1 218.7 309.8 220.9 270L406.6 416.4C357.4 431 301.9 418.9 263 380V380zM116.6 187.9L167.2 227.8L105.5 289.5C73.99 320.1 73.99 372 105.5 403.5C133.3 431.4 177.3 435 209.3 412.1L210.9 410.1C225.3 400.7 245.3 404 255.5 418.4C265.8 432.8 262.5 452.8 248.1 463.1L246.5 464.2C188.1 505.3 110.2 498.7 60.21 448.8C3.741 392.3 3.741 300.7 60.21 244.3L116.6 187.9z' />
|
|
|
|
</svg>
|
|
|
|
</div>
|
|
|
|
<p className='IBMSMSMBSSDEIReactionsElementText'>420</p>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
data-bs-toggle='tooltip'
|
|
|
|
data-bss-tooltip=''
|
|
|
|
className='IBMSMSMBSSDEIReactionsElement'
|
|
|
|
title='Has virus'
|
|
|
|
>
|
|
|
|
<div className='IBMSMSMBSSDEIReactionsElementIconWrapper'>
|
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='0 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMBSSDEIReactionsElementIcon'
|
|
|
|
>
|
|
|
|
<path d='M288 43.55C288 93.44 348.3 118.4 383.6 83.15L391.8 74.98C404.3 62.48 424.5 62.48 437 74.98C449.5 87.48 449.5 107.7 437 120.2L368.7 188.6C352.7 204.3 341.4 224.8 337.6 249.8L168.3 420.1C148.4 448.6 104.5 448.6 84.63 420.1C64.73 391.5 64.73 347.6 84.63 319.1L172.4 231.3C208.7 197 233.6 154.3 233.6 104.4C233.6 54.47 173.3 29.5 138 64.73L130.1 72.9C117.6 85.4 97.41 85.4 84.94 72.9C72.44 60.4 72.44 40.17 84.94 27.67L153.2-41.52C194.8-83.6 295.2-83.6 336.7-41.52C375.5 2.213 377.4 55.78 288 43.55zM121.4 169.3L44.88 245.8C25.35 265.6 25.35 295.7 44.88 315.5L138.4 408.9C147.4 417.1 166.5 421.6 181.5 417.1L296.7 295.7C306.2 272.4 318.5 253.3 333.3 239.8L237.2 142.2C222.4 123.2 204.1 105.3 181.5 105.3C159.1 105.3 141.3 123.2 126.6 142.2L121.4 169.3zM250.7 419.8L299.4 428.2C316.8 433.6 335.5 423.6 336.8 410.8L342.8 236.8C344.1 225 336.8 213.2 325.4 211.4L146.2 160.1C134.7 158.8 120.5 174.7 121.1 185.7L127.8 359.6C128.4 370.9 143.8 382.3 156.1 376.4L250.7 419.8z' />
|
|
|
|
</svg>
|
|
|
|
</div>
|
|
|
|
<p className='IBMSMSMBSSDEIReactionsElementText'>420</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
className='tab-pane tabsMainBottomContent'
|
|
|
|
role='tabpanel'
|
|
|
|
id='tab-2'
|
|
|
|
>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideReactions'>
|
|
|
|
<div
|
|
|
|
data-bs-toggle='tooltip'
|
|
|
|
data-bss-tooltip=''
|
|
|
|
className='IBMSMSMBSSDEIReactionsElement IBMSMSMBSSDEIReactionsElementActive'
|
|
|
|
title='Clean'
|
|
|
|
>
|
|
|
|
<div className='IBMSMSMBSSDEIReactionsElementIconWrapper'>
|
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='0 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMBSSDEIReactionsElementIcon'
|
|
|
|
>
|
|
|
|
<path d='M512 165.4c0 127.9-70.05 235.3-175.3 270.1c-20.04 7.938-41.83 12.46-64.69 12.46c-64.9 0-125.2-36.51-155.7-94.47c-54.13 49.93-68.71 107-68.96 108.1C44.72 472.6 34.87 480 24.02 480c-1.844 0-3.727-.2187-5.602-.6562c-12.89-3.098-20.84-16.08-17.75-28.96c9.598-39.5 90.47-226.4 335.3-226.4C344.8 224 352 216.8 352 208S344.8 192 336 192C228.6 192 151 226.6 96.29 267.6c.1934-10.82 1.242-21.84 3.535-33.05c13.47-65.81 66.04-119 131.4-134.2c28.33-6.562 55.68-6.013 80.93-.0054c56 13.32 118.2-7.412 149.3-61.24c5.664-9.828 20.02-9.516 24.66 .8282C502.7 76.76 512 121.9 512 165.4z' />
|
|
|
|
</svg>
|
|
|
|
</div>
|
|
|
|
<p className='IBMSMSMBSSDEIReactionsElementText'>4,200</p>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
data-bs-toggle='tooltip'
|
|
|
|
data-bss-tooltip=''
|
|
|
|
className='IBMSMSMBSSDEIReactionsElement'
|
|
|
|
title='Broken link'
|
|
|
|
>
|
|
|
|
<div className='IBMSMSMBSSDEIReactionsElementIconWrapper'>
|
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='0 -64 640 640'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMBSSDEIReactionsElementIcon'
|
|
|
|
>
|
|
|
|
<path d='M185.7 120.3C242.5 75.82 324.7 79.73 376.1 131.1C420.1 175.1 430.9 239.6 406.7 293.5L438.6 318.4L534.5 222.5C566 191 566 139.1 534.5 108.5C506.7 80.63 462.7 76.1 430.7 99.9L429.1 101C414.7 111.3 394.7 107.1 384.5 93.58C374.2 79.2 377.5 59.21 391.9 48.94L393.5 47.82C451 6.732 529.8 13.25 579.8 63.24C636.3 119.7 636.3 211.3 579.8 267.7L489.3 358.2L630.8 469.1C641.2 477.3 643.1 492.4 634.9 502.8C626.7 513.2 611.6 515.1 601.2 506.9L9.196 42.89C-1.236 34.71-3.065 19.63 5.112 9.196C13.29-1.236 28.37-3.065 38.81 5.112L185.7 120.3zM238.1 161.1L353.4 251.7C359.3 225.5 351.7 197.2 331.7 177.2C306.6 152.1 269.1 147 238.1 161.1V161.1zM263 380C233.1 350.1 218.7 309.8 220.9 270L406.6 416.4C357.4 431 301.9 418.9 263 380V380zM116.6 187.9L167.2 227.8L105.5 289.5C73.99 320.1 73.99 372 105.5 403.5C133.3 431.4 177.3 435 209.3 412.1L210.9 410.1C225.3 400.7 245.3 404 255.5 418.4C265.8 432.8 262.5 452.8 248.1 463.1L246.5 464.2C188.1 505.3 110.2 498.7 60.21 448.8C3.741 392.3 3.741 300.7 60.21 244.3L116.6 187.9z' />
|
|
|
|
</svg>
|
|
|
|
</div>
|
|
|
|
<p className='IBMSMSMBSSDEIReactionsElementText'>4,200</p>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
data-bs-toggle='tooltip'
|
|
|
|
data-bss-tooltip=''
|
|
|
|
className='IBMSMSMBSSDEIReactionsElement'
|
|
|
|
title='Has virus'
|
|
|
|
>
|
|
|
|
<div className='IBMSMSMBSSDEIReactionsElementIconWrapper'>
|
|
|
|
<svg
|
|
|
|
xmlns='http://www.w3.org/2000/svg'
|
|
|
|
viewBox='0 0 512 512'
|
|
|
|
width='1em'
|
|
|
|
height='1em'
|
|
|
|
fill='currentColor'
|
|
|
|
className='IBMSMSMBSSDEIReactionsElementIcon'
|
|
|
|
>
|
|
|
|
<path d='M288 43.55C288 93.44 348.3 118.4 383.6 83.15L391.8 74.98C404.3 62.48 424.5 62.48 437 74.98C449.5 87.48 449.5 107.7 437 120.2L368.7 188.6C352.7 204.3 341.4 224.8 337.6 249.8L168.3 420.1C148.4 448.6 104.5 448.6 84.63 420.1C64.73 391.5 64.73 347.6 84.63 319.1L172.4 231.3C208.7 197 233.6 154.3 233.6 104.4C233.6 54.47 173.3 29.5 138 64.73L130.1 72.9C117.6 85.4 97.41 85.4 84.94 72.9C72.44 60.4 72.44 40.17 84.94 27.67L153.2-41.52C194.8-83.6 295.2-83.6 336.7-41.52C375.5 2.213 377.4 55.78 288 43.55zM121.4 169.3L44.88 245.8C25.35 265.6 25.35 295.7 44.88 315.5L138.4 408.9C147.4 417.1 166.5 421.6 181.5 417.1L296.7 295.7C306.2 272.4 318.5 253.3 333.3 239.8L237.2 142.2C222.4 123.2 204.1 105.3 181.5 105.3C159.1 105.3 141.3 123.2 126.6 142.2L121.4 169.3zM250.7 419.8L299.4 428.2C316.8 433.6 335.5 423.6 336.8 410.8L342.8 236.8C344.1 225 336.8 213.2 325.4 211.4L146.2 160.1C134.7 158.8 120.5 174.7 121.1 185.7L127.8 359.6C128.4 370.9 143.8 382.3 156.1 376.4L250.7 419.8z' />
|
|
|
|
</svg>
|
|
|
|
</div>
|
|
|
|
<p className='IBMSMSMBSSDEIReactionsElementText'>4,200</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>*/}
|
2024-08-14 12:08:58 +05:00
|
|
|
<div className='IBMSMSMBSSDownloadsElementInside IBMSMSMBSSDownloadsElementInsideAlt'>
|
|
|
|
<p
|
|
|
|
className='IBMSMSMBSSDownloadsElementInsideAltText'
|
|
|
|
onClick={() => setShowAuthDetails((prev) => !prev)}
|
|
|
|
>
|
|
|
|
Authentication Details
|
|
|
|
</p>
|
|
|
|
{showAuthDetails && (
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTable'>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRow'>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol IBMSMSMBSSDownloadsElementInsideAltTableRowColFirst'>
|
2024-09-30 15:17:32 +05:00
|
|
|
<p>Download URL</p>
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol'>
|
|
|
|
<p>{url}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRow'>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol IBMSMSMBSSDownloadsElementInsideAltTableRowColFirst'>
|
2024-08-14 12:08:58 +05:00
|
|
|
<p>SHA-256 hash</p>
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol'>
|
|
|
|
<p>{hash}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRow'>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol IBMSMSMBSSDownloadsElementInsideAltTableRowColFirst'>
|
|
|
|
<p>Signature from</p>
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol'>
|
|
|
|
<p>{signatureKey}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRow'>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol IBMSMSMBSSDownloadsElementInsideAltTableRowColFirst'>
|
|
|
|
<p>Scan</p>
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol'>
|
|
|
|
<p>{malwareScanLink}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRow'>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol IBMSMSMBSSDownloadsElementInsideAltTableRowColFirst'>
|
|
|
|
<p>Mod Version</p>
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol'>
|
|
|
|
<p>{modVersion}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRow'>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol IBMSMSMBSSDownloadsElementInsideAltTableRowColFirst'>
|
|
|
|
<p>Note</p>
|
|
|
|
</div>
|
|
|
|
<div className='IBMSMSMBSSDownloadsElementInsideAltTableRowCol'>
|
|
|
|
<p>{customNote}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
2024-07-25 20:05:28 +05:00
|
|
|
</div>
|
2024-08-06 15:46:38 +05:00
|
|
|
)
|
|
|
|
}
|
2024-11-05 16:43:08 +01:00
|
|
|
|
|
|
|
const DisplayModAuthorBlogs = () => {
|
|
|
|
const { naddr } = useParams()
|
|
|
|
const [blogs, setBlogs] = useState<Partial<BlogCardDetails>[]>()
|
|
|
|
const { fetchEvents } = useNDKContext()
|
|
|
|
|
|
|
|
useDidMount(() => {
|
|
|
|
const fetchBlogs = async () => {
|
|
|
|
try {
|
|
|
|
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
|
|
|
|
const { pubkey } = decoded.data
|
|
|
|
const latestBlogPosts = await fetchEvents({
|
|
|
|
authors: [pubkey],
|
|
|
|
kinds: [kinds.LongFormArticle],
|
|
|
|
limit: 3
|
|
|
|
})
|
|
|
|
setBlogs(latestBlogPosts.map(extractBlogCardDetails))
|
|
|
|
} catch (error) {
|
|
|
|
log(
|
|
|
|
true,
|
|
|
|
LogType.Error,
|
|
|
|
'An error occurred in fetching blog details from relays',
|
|
|
|
error
|
|
|
|
)
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fetchBlogs()
|
|
|
|
})
|
|
|
|
|
|
|
|
if (!blogs?.length) return null
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className='IBMSMSplitMainBigSideSec'>
|
|
|
|
<div className='IBMSMSMBSSPostsWrapper'>
|
|
|
|
<h4 className='IBMSMSMBSSPostsTitle'>Creator's Blog Posts</h4>
|
|
|
|
<div className='IBMSMList IBMSMListAlt'>
|
|
|
|
{blogs?.map((b) => (
|
|
|
|
<BlogCard key={b.id} {...b} />
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|