refactor: add repost tag if missing
This commit is contained in:
parent
35cedba3db
commit
376164cbf4
15
src/hooks/useCuratedSet.tsx
Normal file
15
src/hooks/useCuratedSet.tsx
Normal 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
|
||||||
|
}
|
@ -514,9 +514,12 @@ const Body = ({
|
|||||||
{repost && (
|
{repost && (
|
||||||
<div className='IBMSMSMBSSTagsTag IBMSMSMBSSTagsTagRepost'>
|
<div className='IBMSMSMBSSTagsTag IBMSMSMBSSTagsTagRepost'>
|
||||||
<p>
|
<p>
|
||||||
REPOST. Original Author:{' '}
|
REPOST
|
||||||
{!!originalAuthor && (
|
{originalAuthor && originalAuthor !== '' && (
|
||||||
<OriginalAuthor value={originalAuthor} fallback={true} />
|
<>
|
||||||
|
. Original Author:{' '}
|
||||||
|
<OriginalAuthor value={originalAuthor} fallback={true} />
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,10 +12,12 @@ import {
|
|||||||
NSFWFilter
|
NSFWFilter
|
||||||
} from 'types'
|
} from 'types'
|
||||||
import {
|
import {
|
||||||
|
CurationSetIdentifiers,
|
||||||
DEFAULT_FILTER_OPTIONS,
|
DEFAULT_FILTER_OPTIONS,
|
||||||
extractBlogCardDetails,
|
extractBlogCardDetails,
|
||||||
extractModData,
|
extractModData,
|
||||||
getLocalStorageItem,
|
getLocalStorageItem,
|
||||||
|
getReportingSet,
|
||||||
log,
|
log,
|
||||||
LogType
|
LogType
|
||||||
} from 'utils'
|
} from 'utils'
|
||||||
@ -83,7 +85,8 @@ export const modRouteLoader =
|
|||||||
ndkContext.fetchEvent(modFilter),
|
ndkContext.fetchEvent(modFilter),
|
||||||
ndkContext.fetchEvents(latestFilter),
|
ndkContext.fetchEvents(latestFilter),
|
||||||
ndkContext.getMuteLists(loggedInUserPubkey), // Pass pubkey for logged-in users
|
ndkContext.getMuteLists(loggedInUserPubkey), // Pass pubkey for logged-in users
|
||||||
ndkContext.getNSFWList()
|
getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
|
||||||
|
getReportingSet(CurationSetIdentifiers.Repost, ndkContext)
|
||||||
])
|
])
|
||||||
|
|
||||||
const result: ModPageLoaderResult = {
|
const result: ModPageLoaderResult = {
|
||||||
@ -205,6 +208,28 @@ export const modRouteLoader =
|
|||||||
log(true, LogType.Error, 'Issue fetching nsfw list', nsfwList.reason)
|
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
|
// Filter latest, sort and take only three
|
||||||
result.latest = result.latest
|
result.latest = result.latest
|
||||||
.filter(
|
.filter(
|
||||||
|
@ -19,8 +19,13 @@ import '../styles/pagination.css'
|
|||||||
import '../styles/search.css'
|
import '../styles/search.css'
|
||||||
import '../styles/styles.css'
|
import '../styles/styles.css'
|
||||||
import { FilterOptions, ModDetails } from '../types'
|
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 { SearchInput } from 'components/SearchInput'
|
||||||
|
import { useCuratedSet } from 'hooks/useCuratedSet'
|
||||||
|
|
||||||
export const ModsPage = () => {
|
export const ModsPage = () => {
|
||||||
const scrollTargetRef = useRef<HTMLDivElement>(null)
|
const scrollTargetRef = useRef<HTMLDivElement>(null)
|
||||||
@ -97,6 +102,14 @@ export const ModsPage = () => {
|
|||||||
muteLists
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
{isFetching && <LoadingSpinner desc='Fetching mod details from relays' />}
|
{isFetching && <LoadingSpinner desc='Fetching mod details from relays' />}
|
||||||
@ -111,7 +124,7 @@ export const ModsPage = () => {
|
|||||||
|
|
||||||
<div className='IBMSecMain IBMSMListWrapper'>
|
<div className='IBMSecMain IBMSMListWrapper'>
|
||||||
<div className='IBMSMList'>
|
<div className='IBMSMList'>
|
||||||
{filteredModList.map((mod) => (
|
{filteredModListRepost.map((mod) => (
|
||||||
<ModCard key={mod.id} {...mod} />
|
<ModCard key={mod.id} {...mod} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,9 +10,7 @@ import {
|
|||||||
useAppSelector,
|
useAppSelector,
|
||||||
useFilteredMods,
|
useFilteredMods,
|
||||||
useLocalStorage,
|
useLocalStorage,
|
||||||
useMuteLists,
|
useNDKContext
|
||||||
useNDKContext,
|
|
||||||
useNSFWList
|
|
||||||
} from 'hooks'
|
} from 'hooks'
|
||||||
import { kinds, UnsignedEvent } from 'nostr-tools'
|
import { kinds, UnsignedEvent } from 'nostr-tools'
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
@ -47,7 +45,10 @@ export const ProfilePage = () => {
|
|||||||
profilePubkey,
|
profilePubkey,
|
||||||
profile,
|
profile,
|
||||||
isBlocked: _isBlocked,
|
isBlocked: _isBlocked,
|
||||||
isOwnProfile
|
isOwnProfile,
|
||||||
|
repostList,
|
||||||
|
muteLists,
|
||||||
|
nsfwList
|
||||||
} = useLoaderData() as ProfilePageLoaderResult
|
} = useLoaderData() as ProfilePageLoaderResult
|
||||||
const scrollTargetRef = useRef<HTMLDivElement>(null)
|
const scrollTargetRef = useRef<HTMLDivElement>(null)
|
||||||
const { ndk, publish, fetchEventFromUserRelays, fetchMods } = useNDKContext()
|
const { ndk, publish, fetchEventFromUserRelays, fetchMods } = useNDKContext()
|
||||||
@ -200,8 +201,6 @@ export const ProfilePage = () => {
|
|||||||
const [filterOptions] = useLocalStorage<FilterOptions>(filterKey, {
|
const [filterOptions] = useLocalStorage<FilterOptions>(filterKey, {
|
||||||
...DEFAULT_FILTER_OPTIONS
|
...DEFAULT_FILTER_OPTIONS
|
||||||
})
|
})
|
||||||
const muteLists = useMuteLists()
|
|
||||||
const nsfwList = useNSFWList()
|
|
||||||
|
|
||||||
const handleNext = useCallback(() => {
|
const handleNext = useCallback(() => {
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
@ -263,6 +262,7 @@ export const ProfilePage = () => {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}, [filterOptions.source, tab, fetchMods, profilePubkey])
|
}, [filterOptions.source, tab, fetchMods, profilePubkey])
|
||||||
|
|
||||||
const filteredModList = useFilteredMods(
|
const filteredModList = useFilteredMods(
|
||||||
mods,
|
mods,
|
||||||
userState,
|
userState,
|
||||||
@ -272,6 +272,13 @@ export const ProfilePage = () => {
|
|||||||
profilePubkey
|
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 (
|
return (
|
||||||
<div className='InnerBodyMain'>
|
<div className='InnerBodyMain'>
|
||||||
<div className='ContainerMain'>
|
<div className='ContainerMain'>
|
||||||
@ -422,7 +429,7 @@ export const ProfilePage = () => {
|
|||||||
<ModFilter filterKey={filterKey} author={profilePubkey} />
|
<ModFilter filterKey={filterKey} author={profilePubkey} />
|
||||||
|
|
||||||
<div className='IBMSMList IBMSMListAlt'>
|
<div className='IBMSMList IBMSMListAlt'>
|
||||||
{filteredModList.map((mod) => (
|
{filteredModListRepost.map((mod) => (
|
||||||
<ModCard key={mod.id} {...mod} />
|
<ModCard key={mod.id} {...mod} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,13 @@ import { LoaderFunctionArgs, redirect } from 'react-router-dom'
|
|||||||
import { appRoutes, getProfilePageRoute } from 'routes'
|
import { appRoutes, getProfilePageRoute } from 'routes'
|
||||||
import { store } from 'store'
|
import { store } from 'store'
|
||||||
import { MuteLists, UserProfile } from 'types'
|
import { MuteLists, UserProfile } from 'types'
|
||||||
import { log, LogType, npubToHex } from 'utils'
|
import {
|
||||||
|
CurationSetIdentifiers,
|
||||||
|
getReportingSet,
|
||||||
|
log,
|
||||||
|
LogType,
|
||||||
|
npubToHex
|
||||||
|
} from 'utils'
|
||||||
|
|
||||||
export interface ProfilePageLoaderResult {
|
export interface ProfilePageLoaderResult {
|
||||||
profilePubkey: string
|
profilePubkey: string
|
||||||
@ -16,6 +22,7 @@ export interface ProfilePageLoaderResult {
|
|||||||
user: MuteLists
|
user: MuteLists
|
||||||
}
|
}
|
||||||
nsfwList: string[]
|
nsfwList: string[]
|
||||||
|
repostList: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const profileRouteLoader =
|
export const profileRouteLoader =
|
||||||
@ -87,7 +94,8 @@ export const profileRouteLoader =
|
|||||||
replaceableEvents: []
|
replaceableEvents: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
nsfwList: []
|
nsfwList: [],
|
||||||
|
repostList: []
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if user the user is logged in
|
// Check if user the user is logged in
|
||||||
@ -98,7 +106,8 @@ export const profileRouteLoader =
|
|||||||
const settled = await Promise.allSettled([
|
const settled = await Promise.allSettled([
|
||||||
ndkContext.findMetadata(profilePubkey),
|
ndkContext.findMetadata(profilePubkey),
|
||||||
ndkContext.getMuteLists(userPubkey),
|
ndkContext.getMuteLists(userPubkey),
|
||||||
ndkContext.getNSFWList()
|
getReportingSet(CurationSetIdentifiers.NSFW, ndkContext),
|
||||||
|
getReportingSet(CurationSetIdentifiers.Repost, ndkContext)
|
||||||
])
|
])
|
||||||
|
|
||||||
// Check the profile event result
|
// Check the profile event result
|
||||||
@ -138,10 +147,23 @@ export const profileRouteLoader =
|
|||||||
log(
|
log(
|
||||||
true,
|
true,
|
||||||
LogType.Error,
|
LogType.Error,
|
||||||
'Failed to fetch mutelist.',
|
'Failed to fetch nsfwlist.',
|
||||||
nsfwListResult.reason
|
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
|
return result
|
||||||
}
|
}
|
||||||
|
@ -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 { NDKContextType } from 'contexts/NDKContext'
|
||||||
import { UnsignedEvent, kinds } from 'nostr-tools'
|
import { UnsignedEvent, kinds } from 'nostr-tools'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { UserRelaysType } from 'types'
|
import { UserRelaysType } from 'types'
|
||||||
import { now, signAndPublish } from './nostr'
|
import { now, npubToHex, signAndPublish } from './nostr'
|
||||||
|
|
||||||
interface CurationSetArgs {
|
interface CurationSetArgs {
|
||||||
dTag: CurationSetIdentifiers
|
dTag: CurationSetIdentifiers
|
||||||
@ -54,6 +54,34 @@ export async function createCurationSet(
|
|||||||
return isUpdated
|
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({
|
export async function getCurationSet({
|
||||||
dTag,
|
dTag,
|
||||||
pubkey,
|
pubkey,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user