all filters fully functional. reporting system added. multiple fixes. #27

Merged
freakoverse merged 13 commits from staging into master 2024-08-29 17:40:03 +00:00
2 changed files with 103 additions and 40 deletions
Showing only changes of commit e1da323c2f - Show all commits

View File

@ -131,24 +131,21 @@ export class MetadataController {
return ndkRelayList[userRelaysType] return ndkRelayList[userRelaysType]
} }
public getMuteLists = async (pubkey?: string): Promise<MuteLists> => { public getMuteLists = async (
// Create sets to collect all unique muted authors and replaceable event Identifiers pubkey?: string
const mutedAuthors = new Set<string>() ): Promise<{
const mutedEvents = new Set<string>() admin: MuteLists
user: MuteLists
}> => {
const adminMutedAuthors = new Set<string>()
const adminMutedPosts = new Set<string>()
// construct an array of npubs with dedicated reporting npub and provided pubkey const adminHexKey = npubToHex(this.reportingNpub)
const npubs = [this.reportingNpub]
if (pubkey) npubs.push(pubkey)
// Create an array of promises to fetch mute lists for each npub
const promises = npubs.map(async (npub) => {
const hexKey = npubToHex(npub)
if (!hexKey) return
if (adminHexKey) {
const muteListEvent = await this.ndk.fetchEvent({ const muteListEvent = await this.ndk.fetchEvent({
kinds: [kinds.Mutelist], kinds: [kinds.Mutelist],
authors: [hexKey] authors: [adminHexKey]
}) })
if (muteListEvent) { if (muteListEvent) {
@ -156,19 +153,49 @@ export class MetadataController {
list.items.forEach((item) => { list.items.forEach((item) => {
if (item[0] === 'p') { if (item[0] === 'p') {
mutedAuthors.add(item[1]) adminMutedAuthors.add(item[1])
} else if (item[0] === 'a') { } else if (item[0] === 'a') {
mutedEvents.add(item[1]) adminMutedPosts.add(item[1])
} }
}) })
} }
}) }
await Promise.allSettled(promises) const userMutedAuthors = new Set<string>()
const userMutedPosts = new Set<string>()
if (pubkey) {
const userHexKey = npubToHex(pubkey)
if (userHexKey) {
const muteListEvent = await this.ndk.fetchEvent({
kinds: [kinds.Mutelist],
authors: [userHexKey]
})
if (muteListEvent) {
const list = NDKList.from(muteListEvent)
list.items.forEach((item) => {
if (item[0] === 'p') {
userMutedAuthors.add(item[1])
} else if (item[0] === 'a') {
userMutedPosts.add(item[1])
}
})
}
}
}
return { return {
authors: Array.from(mutedAuthors), admin: {
replaceableEvents: Array.from(mutedEvents) authors: Array.from(adminMutedAuthors),
replaceableEvents: Array.from(adminMutedPosts)
},
user: {
authors: Array.from(userMutedAuthors),
replaceableEvents: Array.from(userMutedPosts)
}
} }
} }

View File

@ -36,7 +36,8 @@ enum NSFWFilter {
enum ModeratedFilter { enum ModeratedFilter {
Moderated = 'Moderated', Moderated = 'Moderated',
Unmoderated = 'Unmoderated' Unmoderated = 'Unmoderated',
Unmoderated_Fully = 'Unmoderated Fully'
} }
interface FilterOptions { interface FilterOptions {
@ -56,9 +57,18 @@ export const ModsPage = () => {
source: window.location.host, source: window.location.host,
moderated: ModeratedFilter.Moderated moderated: ModeratedFilter.Moderated
}) })
const [muteLists, setMuteLists] = useState<MuteLists>({ const [muteLists, setMuteLists] = useState<{
authors: [], admin: MuteLists
replaceableEvents: [] user: MuteLists
}>({
admin: {
authors: [],
replaceableEvents: []
},
user: {
authors: [],
replaceableEvents: []
}
}) })
const [nsfwList, setNSFWList] = useState<string[]>([]) const [nsfwList, setNSFWList] = useState<string[]>([])
@ -139,11 +149,24 @@ export const ModsPage = () => {
let filtered = nsfwFilter(mods) let filtered = nsfwFilter(mods)
const isAdmin = userState.user?.npub === import.meta.env.VITE_REPORTING_NPUB
const isUnmoderatedFully =
filterOptions.moderated === ModeratedFilter.Unmoderated_Fully
// Only apply filtering if the user is not an admin or the admin has not selected "Unmoderated Fully"
if (!(isAdmin && isUnmoderatedFully)) {
filtered = filtered.filter(
(mod) =>
!muteLists.admin.authors.includes(mod.author) &&
!muteLists.admin.replaceableEvents.includes(mod.aTag)
)
}
if (filterOptions.moderated === ModeratedFilter.Moderated) { if (filterOptions.moderated === ModeratedFilter.Moderated) {
filtered = filtered.filter( filtered = filtered.filter(
(mod) => (mod) =>
!muteLists.authors.includes(mod.author) && !muteLists.user.authors.includes(mod.author) &&
!muteLists.replaceableEvents.includes(mod.aTag) !muteLists.user.replaceableEvents.includes(mod.aTag)
) )
} }
@ -155,6 +178,7 @@ export const ModsPage = () => {
return filtered return filtered
}, [ }, [
userState.user?.npub,
filterOptions.sort, filterOptions.sort,
filterOptions.moderated, filterOptions.moderated,
filterOptions.nsfw, filterOptions.nsfw,
@ -250,6 +274,8 @@ type FiltersProps = {
const Filters = React.memo( const Filters = React.memo(
({ filterOptions, setFilterOptions }: FiltersProps) => { ({ filterOptions, setFilterOptions }: FiltersProps) => {
const userState = useAppSelector((state) => state.user)
return ( return (
<div className='IBMSecMain'> <div className='IBMSecMain'>
<div className='FiltersMain'> <div className='FiltersMain'>
@ -293,20 +319,30 @@ const Filters = React.memo(
{filterOptions.moderated} {filterOptions.moderated}
</button> </button>
<div className='dropdown-menu dropdownMainMenu'> <div className='dropdown-menu dropdownMainMenu'>
{Object.values(ModeratedFilter).map((item, index) => ( {Object.values(ModeratedFilter).map((item, index) => {
<div if (item === ModeratedFilter.Unmoderated_Fully) {
key={`moderatedFilterItem-${index}`} const isAdmin =
className='dropdown-item dropdownMainMenuItem' userState.user?.npub ===
onClick={() => import.meta.env.VITE_REPORTING_NPUB
setFilterOptions((prev) => ({
...prev, if (!isAdmin) return null
moderated: item }
}))
} return (
> <div
{item} key={`moderatedFilterItem-${index}`}
</div> className='dropdown-item dropdownMainMenuItem'
))} onClick={() =>
setFilterOptions((prev) => ({
...prev,
moderated: item
}))
}
>
{item}
</div>
)
})}
</div> </div>
</div> </div>
</div> </div>