feat: add toggle to hide untrusted posts (#435)

This commit is contained in:
captain-stacks
2025-07-05 09:40:47 -07:00
committed by Cody Tseng
parent 9da5e6663e
commit 98bf906916
5 changed files with 53 additions and 6 deletions

View File

@@ -19,6 +19,8 @@ import PullToRefresh from 'react-simple-pull-to-refresh'
import NoteCard, { NoteCardLoadingSkeleton } from '../NoteCard'
import { PictureNoteCardMasonry } from '../PictureNoteCardMasonry'
import Tabs from '../Tabs'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useFeed } from '@/providers/FeedProvider'
const LIMIT = 100
const ALGO_LIMIT = 500
@@ -60,14 +62,17 @@ export default function NoteList({
const [filterType, setFilterType] = useState<Exclude<TNoteListMode, 'postsAndReplies'>>('posts')
const bottomRef = useRef<HTMLDivElement | null>(null)
const topRef = useRef<HTMLDivElement | null>(null)
const { isUserTrusted, hideUntrustedNotes } = useUserTrust()
const { feedInfo } = useFeed()
const filteredNewEvents = useMemo(() => {
return newEvents.filter((event: Event) => {
return (
(!filterMutedNotes || !mutePubkeys.includes(event.pubkey)) &&
(listMode !== 'posts' || !isReplyNoteEvent(event))
(listMode !== 'posts' || !isReplyNoteEvent(event)) &&
(!hideUntrustedNotes || isUserTrusted(event.pubkey))
)
})
}, [newEvents, listMode, filterMutedNotes, mutePubkeys])
}, [newEvents, listMode, filterMutedNotes, mutePubkeys, hideUntrustedNotes])
useEffect(() => {
switch (listMode) {
@@ -341,7 +346,11 @@ export default function NoteList({
<div>
{events
.slice(0, showCount)
.filter((event: Event) => listMode !== 'posts' || !isReplyNoteEvent(event))
.filter((event: Event) =>
(listMode !== 'posts' || !isReplyNoteEvent(event)) &&
(author
|| (feedInfo.feedType !== 'relay' && feedInfo.feedType !== 'relays')
|| !hideUntrustedNotes || isUserTrusted(event.pubkey)))
.map((event) => (
<NoteCard
key={event.id}

View File

@@ -19,6 +19,7 @@ export const StorageKey = {
HIDE_UNTRUSTED_INTERACTIONS: 'hideUntrustedInteractions',
HIDE_UNTRUSTED_NOTIFICATIONS: 'hideUntrustedNotifications',
TRANSLATION_SERVICE_CONFIG_MAP: 'translationServiceConfigMap',
HIDE_UNTRUSTED_NOTES: 'hideUntrustedNotes',
HIDE_UNTRUSTED_EVENTS: 'hideUntrustedEvents', // deprecated
ACCOUNT_RELAY_LIST_EVENT_MAP: 'accountRelayListEventMap', // deprecated
ACCOUNT_FOLLOW_LIST_EVENT_MAP: 'accountFollowListEventMap', // deprecated

View File

@@ -9,12 +9,14 @@ import { useTheme } from '@/providers/ThemeProvider'
import { SelectValue } from '@radix-ui/react-select'
import { forwardRef, HTMLProps, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useUserTrust } from '@/providers/UserTrustProvider'
const GeneralSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
const { t, i18n } = useTranslation()
const [language, setLanguage] = useState<TLanguage>(i18n.language as TLanguage)
const { themeSetting, setThemeSetting } = useTheme()
const { autoplay, setAutoplay } = useAutoplay()
const { hideUntrustedNotes, updateHideUntrustedNotes } = useUserTrust()
const handleLanguageChange = (value: TLanguage) => {
i18n.changeLanguage(value)
@@ -63,6 +65,12 @@ const GeneralSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
</Label>
<Switch id="autoplay" checked={autoplay} onCheckedChange={setAutoplay} />
</SettingItem>
<SettingItem>
<Label htmlFor="hideUntrustedNotes" className="text-base font-normal">
{t('Hide untrusted posts')}
</Label>
<Switch id="hideUntrustedNotes" checked={hideUntrustedNotes} onCheckedChange={updateHideUntrustedNotes} />
</SettingItem>
</div>
</SecondaryPageLayout>
)

View File

@@ -6,8 +6,10 @@ import { useNostr } from './NostrProvider'
type TUserTrustContext = {
hideUntrustedInteractions: boolean
hideUntrustedNotifications: boolean
hideUntrustedNotes: boolean
updateHideUntrustedInteractions: (hide: boolean) => void
updateHideUntrustedNotifications: (hide: boolean) => void
updateHideUntrustedNotes: (hide: boolean) => void
isUserTrusted: (pubkey: string) => boolean
}
@@ -31,6 +33,9 @@ export function UserTrustProvider({ children }: { children: React.ReactNode }) {
const [hideUntrustedNotifications, setHideUntrustedNotifications] = useState(() =>
storage.getHideUntrustedNotifications()
)
const [hideUntrustedNotes, setHideUntrustedNotes] = useState(() =>
storage.getHideUntrustedNotes ? storage.getHideUntrustedNotes() : false
)
useEffect(() => {
if (!currentPubkey) return
@@ -66,13 +71,22 @@ export function UserTrustProvider({ children }: { children: React.ReactNode }) {
storage.setHideUntrustedNotifications(hide)
}
const updateHideUntrustedNotes = (hide: boolean) => {
setHideUntrustedNotes(hide)
if (storage.setHideUntrustedNotes) {
storage.setHideUntrustedNotes(hide)
}
}
return (
<UserTrustContext.Provider
value={{
hideUntrustedInteractions,
hideUntrustedNotifications,
hideUntrustedNotes,
updateHideUntrustedInteractions,
updateHideUntrustedNotifications,
updateHideUntrustedNotes,
isUserTrusted
}}
>

View File

@@ -28,6 +28,7 @@ class LocalStorageService {
private autoplay: boolean = true
private hideUntrustedInteractions: boolean = false
private hideUntrustedNotifications: boolean = false
private hideUntrustedNotes: boolean = false
private translationServiceConfigMap: Record<string, TTranslationServiceConfig> = {}
constructor() {
@@ -95,8 +96,9 @@ class LocalStorageService {
window.localStorage.getItem(StorageKey.MEDIA_UPLOAD_SERVICE) ?? DEFAULT_NIP_96_SERVICE
this.autoplay = window.localStorage.getItem(StorageKey.AUTOPLAY) !== 'false'
this.hideUntrustedNotes = window.localStorage.getItem(StorageKey.HIDE_UNTRUSTED_NOTES) === 'true'
const hideUntrustedEvents =
const hideUntrustedNotes =
window.localStorage.getItem(StorageKey.HIDE_UNTRUSTED_EVENTS) === 'true'
const storedHideUntrustedInteractions = window.localStorage.getItem(
StorageKey.HIDE_UNTRUSTED_INTERACTIONS
@@ -106,10 +108,11 @@ class LocalStorageService {
)
this.hideUntrustedInteractions = storedHideUntrustedInteractions
? storedHideUntrustedInteractions === 'true'
: hideUntrustedEvents
: hideUntrustedNotes
this.hideUntrustedNotifications = storedHideUntrustedNotifications
? storedHideUntrustedNotifications === 'true'
: hideUntrustedEvents
: hideUntrustedNotes
this.hideUntrustedNotes = hideUntrustedNotes
const translationServiceConfigMapStr = window.localStorage.getItem(
StorageKey.TRANSLATION_SERVICE_CONFIG_MAP
@@ -301,6 +304,18 @@ class LocalStorageService {
)
}
getHideUntrustedNotes() {
return this.hideUntrustedNotes
}
setHideUntrustedNotes(hideUntrustedNotes: boolean) {
this.hideUntrustedNotes = hideUntrustedNotes
window.localStorage.setItem(
StorageKey.HIDE_UNTRUSTED_NOTES,
hideUntrustedNotes.toString()
)
}
getTranslationServiceConfig(pubkey?: string | null) {
return this.translationServiceConfigMap[pubkey ?? '_'] ?? { service: 'jumble' }
}