all filters fully functional. reporting system added. multiple fixes. #27
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user