mods refactor and added repost tag system #163

Merged
freakoverse merged 15 commits from staging into master 2024-11-28 22:57:20 +00:00
7 changed files with 132 additions and 19 deletions
Showing only changes of commit 376164cbf4 - Show all commits

View File

@ -0,0 +1,15 @@
import { useState } from 'react'
import { useNDKContext } from './useNDKContext'
import { useDidMount } from './useDidMount'
import { CurationSetIdentifiers, getReportingSet } from 'utils'
export const useCuratedSet = (type: CurationSetIdentifiers) => {
const ndkContext = useNDKContext()
const [curatedSet, setCuratedSet] = useState<string[]>([])
useDidMount(async () => {
setCuratedSet(await getReportingSet(type, ndkContext))
})
return curatedSet
}

View File

@ -514,9 +514,12 @@ const Body = ({
{repost && (
<div className='IBMSMSMBSSTagsTag IBMSMSMBSSTagsTagRepost'>
<p>
REPOST. Original Author:{' '}
{!!originalAuthor && (
REPOST
{originalAuthor && originalAuthor !== '' && (
<>
. Original Author:{' '}
<OriginalAuthor value={originalAuthor} fallback={true} />
</>
)}
</p>
</div>

View File

@ -12,10 +12,12 @@ import {
NSFWFilter
} from 'types'
import {
CurationSetIdentifiers,
DEFAULT_FILTER_OPTIONS,
extractBlogCardDetails,
extractModData,
getLocalStorageItem,
getReportingSet,
log,
LogType
} from 'utils'
@ -83,7 +85,8 @@ export const modRouteLoader =
ndkContext.fetchEvent(modFilter),
ndkContext.fetchEvents(latestFilter),
ndkContext.getMuteLists(loggedInUserPubkey), // Pass pubkey for logged-in users
ndkContext.getNSFWList()
getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
getReportingSet(CurationSetIdentifiers.Repost, ndkContext)
])
const result: ModPageLoaderResult = {
@ -205,6 +208,28 @@ export const modRouteLoader =
log(true, LogType.Error, 'Issue fetching nsfw list', nsfwList.reason)
}
const repostList = settled[4]
if (repostList.status === 'fulfilled' && repostList.value) {
// Check if the mod is marked as Repost
// Mark it as Repost only if it's missing the tag
if (result.mod) {
const isMissingRepostTag =
!result.mod.repost &&
result.mod.aTag &&
repostList.value.includes(result.mod.aTag)
if (isMissingRepostTag) {
result.mod.repost = true
}
if (result.mod.aTag && repostList.value.includes(result.mod.aTag)) {
result.isRepost = true
}
}
} else if (repostList.status === 'rejected') {
log(true, LogType.Error, 'Issue fetching nsfw list', repostList.reason)
}
// Filter latest, sort and take only three
result.latest = result.latest
.filter(

View File

@ -19,8 +19,13 @@ import '../styles/pagination.css'
import '../styles/search.css'
import '../styles/styles.css'
import { FilterOptions, ModDetails } from '../types'
import { DEFAULT_FILTER_OPTIONS, scrollIntoView } from 'utils'
import {
CurationSetIdentifiers,
DEFAULT_FILTER_OPTIONS,
scrollIntoView
} from 'utils'
import { SearchInput } from 'components/SearchInput'
import { useCuratedSet } from 'hooks/useCuratedSet'
export const ModsPage = () => {
const scrollTargetRef = useRef<HTMLDivElement>(null)
@ -97,6 +102,14 @@ export const ModsPage = () => {
muteLists
)
// Add repost tag to mods included in repostList
const repostList = useCuratedSet(CurationSetIdentifiers.Repost)
const filteredModListRepost = filteredModList.map((mod) => {
return !mod.repost && repostList.includes(mod.aTag)
? { ...mod, repost: true }
: mod
})
return (
<>
{isFetching && <LoadingSpinner desc='Fetching mod details from relays' />}
@ -111,7 +124,7 @@ export const ModsPage = () => {
<div className='IBMSecMain IBMSMListWrapper'>
<div className='IBMSMList'>
{filteredModList.map((mod) => (
{filteredModListRepost.map((mod) => (
<ModCard key={mod.id} {...mod} />
))}
</div>

View File

@ -10,9 +10,7 @@ import {
useAppSelector,
useFilteredMods,
useLocalStorage,
useMuteLists,
useNDKContext,
useNSFWList
useNDKContext
} from 'hooks'
import { kinds, UnsignedEvent } from 'nostr-tools'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
@ -47,7 +45,10 @@ export const ProfilePage = () => {
profilePubkey,
profile,
isBlocked: _isBlocked,
isOwnProfile
isOwnProfile,
repostList,
muteLists,
nsfwList
} = useLoaderData() as ProfilePageLoaderResult
const scrollTargetRef = useRef<HTMLDivElement>(null)
const { ndk, publish, fetchEventFromUserRelays, fetchMods } = useNDKContext()
@ -200,8 +201,6 @@ export const ProfilePage = () => {
const [filterOptions] = useLocalStorage<FilterOptions>(filterKey, {
...DEFAULT_FILTER_OPTIONS
})
const muteLists = useMuteLists()
const nsfwList = useNSFWList()
const handleNext = useCallback(() => {
setIsLoading(true)
@ -263,6 +262,7 @@ export const ProfilePage = () => {
break
}
}, [filterOptions.source, tab, fetchMods, profilePubkey])
const filteredModList = useFilteredMods(
mods,
userState,
@ -272,6 +272,13 @@ export const ProfilePage = () => {
profilePubkey
)
// Add repost tag to mods included in repostList
const filteredModListRepost = filteredModList.map((mod) => {
return !mod.repost && repostList.includes(mod.aTag)
? { ...mod, repost: true }
: mod
})
return (
<div className='InnerBodyMain'>
<div className='ContainerMain'>
@ -422,7 +429,7 @@ export const ProfilePage = () => {
<ModFilter filterKey={filterKey} author={profilePubkey} />
<div className='IBMSMList IBMSMListAlt'>
{filteredModList.map((mod) => (
{filteredModListRepost.map((mod) => (
<ModCard key={mod.id} {...mod} />
))}
</div>

View File

@ -4,7 +4,13 @@ import { LoaderFunctionArgs, redirect } from 'react-router-dom'
import { appRoutes, getProfilePageRoute } from 'routes'
import { store } from 'store'
import { MuteLists, UserProfile } from 'types'
import { log, LogType, npubToHex } from 'utils'
import {
CurationSetIdentifiers,
getReportingSet,
log,
LogType,
npubToHex
} from 'utils'
export interface ProfilePageLoaderResult {
profilePubkey: string
@ -16,6 +22,7 @@ export interface ProfilePageLoaderResult {
user: MuteLists
}
nsfwList: string[]
repostList: string[]
}
export const profileRouteLoader =
@ -87,7 +94,8 @@ export const profileRouteLoader =
replaceableEvents: []
}
},
nsfwList: []
nsfwList: [],
repostList: []
}
// Check if user the user is logged in
@ -98,7 +106,8 @@ export const profileRouteLoader =
const settled = await Promise.allSettled([
ndkContext.findMetadata(profilePubkey),
ndkContext.getMuteLists(userPubkey),
ndkContext.getNSFWList()
getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
getReportingSet(CurationSetIdentifiers.Repost, ndkContext)
])
// Check the profile event result
@ -138,10 +147,23 @@ export const profileRouteLoader =
log(
true,
LogType.Error,
'Failed to fetch mutelist.',
'Failed to fetch nsfwlist.',
nsfwListResult.reason
)
}
// Check the profile event result
const repostListResult = settled[3]
if (repostListResult.status === 'fulfilled' && repostListResult.value) {
result.repostList = repostListResult.value
} else if (repostListResult.status === 'rejected') {
log(
true,
LogType.Error,
'Failed to fetch repost list.',
repostListResult.reason
)
}
return result
}

View File

@ -1,9 +1,9 @@
import { NDKFilter } from '@nostr-dev-kit/ndk'
import { NDKFilter, NDKList } from '@nostr-dev-kit/ndk'
import { NDKContextType } from 'contexts/NDKContext'
import { UnsignedEvent, kinds } from 'nostr-tools'
import { toast } from 'react-toastify'
import { UserRelaysType } from 'types'
import { now, signAndPublish } from './nostr'
import { now, npubToHex, signAndPublish } from './nostr'
interface CurationSetArgs {
dTag: CurationSetIdentifiers
@ -54,6 +54,34 @@ export async function createCurationSet(
return isUpdated
}
export async function getReportingSet(
dTag: CurationSetIdentifiers,
ndkContext: NDKContextType
) {
const result: string[] = []
const reportingNpub = import.meta.env.VITE_REPORTING_NPUB
const hexKey = npubToHex(reportingNpub)
if (hexKey) {
const event = await ndkContext.fetchEvent({
kinds: [kinds.Curationsets],
authors: [hexKey],
'#d': [dTag]
})
if (event) {
const list = NDKList.from(event)
list.items.forEach((item) => {
if (item[0] === 'a') {
result.push(item[1])
}
})
}
}
return result
}
export async function getCurationSet({
dTag,
pubkey,