feat: added the ability to unblock the posts #26

Merged
s merged 1 commits from unblock into staging 2024-08-29 13:28:55 +00:00
2 changed files with 166 additions and 8 deletions

View File

@ -3,7 +3,14 @@ import { EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { formatDate } from 'date-fns'
import { Filter, kinds, nip19, UnsignedEvent } from 'nostr-tools'
import { Dispatch, SetStateAction, useCallback, useRef, useState } from 'react'
import {
Dispatch,
SetStateAction,
useCallback,
useEffect,
useRef,
useState
} from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { toast } from 'react-toastify'
import { BlogCard } from '../components/BlogCard'
@ -212,6 +219,63 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
const [isLoading, setIsLoading] = useState(false)
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
const [showReportPopUp, setShowReportPopUp] = useState(false)
const [isBlocked, setIsBlocked] = useState(false)
const [isAddedToNSFW, setIsAddedToNSFW] = useState(false)
useEffect(() => {
if (userState.auth && userState.user?.pubkey) {
const pubkey = userState.user.pubkey as string
const muteListFilter: Filter = {
kinds: [kinds.Mutelist],
authors: [pubkey]
}
RelayController.getInstance()
.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)
}
})
if (
userState.user.npub &&
userState.user.npub === import.meta.env.VITE_REPORTING_NPUB
) {
const nsfwListFilter: Filter = {
kinds: [kinds.Curationsets],
authors: [pubkey],
'#d': ['nsfw']
}
RelayController.getInstance()
.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)
}
})
}
}
}, [userState, aTag])
const handleBlock = async () => {
let hexPubkey: string
@ -258,6 +322,7 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
if (alreadyExists) {
setIsLoading(false)
setIsBlocked(true)
return toast.warn(`Mod reference is already in user's mute list`)
}
@ -282,7 +347,53 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
setLoadingSpinnerDesc('Updating mute list event')
await signAndPublish(unsignedEvent)
const isUpdated = await signAndPublish(unsignedEvent)
if (isUpdated) {
setIsBlocked(true)
}
setIsLoading(false)
}
const handleUnblock = async () => {
const pubkey = userState.user?.pubkey as string
const filter: Filter = {
kinds: [kinds.Mutelist],
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.
const muteListEvent =
await RelayController.getInstance().fetchEventFromUserRelays(
filter,
pubkey,
UserRelaysType.Write
)
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,
kind: muteListEvent.kind,
content: muteListEvent.content,
created_at: now(),
tags: tags.filter((item) => item[0] !== 'a' || item[1] !== aTag)
}
setLoadingSpinnerDesc('Updating mute list event')
const isUpdated = await signAndPublish(unsignedEvent)
if (isUpdated) {
setIsBlocked(false)
}
setIsLoading(false)
}
@ -317,6 +428,7 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
if (alreadyExists) {
setIsLoading(false)
setIsAddedToNSFW(true)
return toast.warn(`Mod reference is already in user's nsfw list`)
}
@ -344,7 +456,53 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
setLoadingSpinnerDesc('Updating nsfw list event')
await signAndPublish(unsignedEvent)
const isUpdated = await signAndPublish(unsignedEvent)
if (isUpdated) {
setIsAddedToNSFW(true)
}
setIsLoading(false)
}
const handleUnblockNSFW = async () => {
const pubkey = userState.user?.pubkey as string
const filter: Filter = {
kinds: [kinds.Curationsets],
authors: [pubkey],
'#d': ['nsfw']
}
setIsLoading(true)
setLoadingSpinnerDesc('Finding NSFW list')
const nsfwListEvent =
await RelayController.getInstance().fetchEventFromUserRelays(
filter,
pubkey,
UserRelaysType.Write
)
if (!nsfwListEvent) {
toast.error(`Couldn't get nsfw list event from relays`)
return
}
const tags = nsfwListEvent.tags
const unsignedEvent: UnsignedEvent = {
pubkey: nsfwListEvent.pubkey,
kind: nsfwListEvent.kind,
content: nsfwListEvent.content,
created_at: now(),
tags: tags.filter((item) => item[0] !== 'a' || item[1] !== aTag)
}
setLoadingSpinnerDesc('Updating nsfw list event')
const isUpdated = await signAndPublish(unsignedEvent)
if (isUpdated) {
setIsAddedToNSFW(false)
}
setIsLoading(false)
}
@ -456,7 +614,7 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
</a>
<a
className='dropdown-item dropdownMainMenuItem'
onClick={handleBlock}
onClick={isBlocked ? handleUnblock : handleBlock}
>
<svg
xmlns='http://www.w3.org/2000/svg'
@ -468,12 +626,12 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
>
<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>
Block Post
{isBlocked ? 'Unblock' : 'Block'} Post
</a>
{isAdmin && (
<a
className='dropdown-item dropdownMainMenuItem'
onClick={handleBlockNSFW}
onClick={isAddedToNSFW ? handleUnblockNSFW : handleBlockNSFW}
>
<svg
xmlns='http://www.w3.org/2000/svg'
@ -485,7 +643,7 @@ const Game = ({ naddr, game, author, aTag }: GameProps) => {
>
<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>
Block Post NSFW
{isAddedToNSFW ? 'Un-mark' : 'Mark'} as NSFW
</a>
)}
</div>

View File

@ -138,7 +138,7 @@ export const extractZapAmount = (event: Event): number => {
* Signs and publishes an event to user's relays.
*
* @param unsignedEvent - The event object which needs to be signed before publishing.
* @returns - A promise that resolves to an array of relay URLs where the event was successfully published, or null if the operation failed.
* @returns - A promise that resolves to boolean indicating whether the event was successfully signed and published
*/
export const signAndPublish = async (unsignedEvent: UnsignedEvent) => {
// Sign the event. This returns a signed event or null if signing fails.