feat: add toggle to hide untrusted posts (#435)
This commit is contained in:
committed by
Cody Tseng
parent
9da5e6663e
commit
98bf906916
@@ -19,6 +19,8 @@ import PullToRefresh from 'react-simple-pull-to-refresh'
|
|||||||
import NoteCard, { NoteCardLoadingSkeleton } from '../NoteCard'
|
import NoteCard, { NoteCardLoadingSkeleton } from '../NoteCard'
|
||||||
import { PictureNoteCardMasonry } from '../PictureNoteCardMasonry'
|
import { PictureNoteCardMasonry } from '../PictureNoteCardMasonry'
|
||||||
import Tabs from '../Tabs'
|
import Tabs from '../Tabs'
|
||||||
|
import { useUserTrust } from '@/providers/UserTrustProvider'
|
||||||
|
import { useFeed } from '@/providers/FeedProvider'
|
||||||
|
|
||||||
const LIMIT = 100
|
const LIMIT = 100
|
||||||
const ALGO_LIMIT = 500
|
const ALGO_LIMIT = 500
|
||||||
@@ -60,14 +62,17 @@ export default function NoteList({
|
|||||||
const [filterType, setFilterType] = useState<Exclude<TNoteListMode, 'postsAndReplies'>>('posts')
|
const [filterType, setFilterType] = useState<Exclude<TNoteListMode, 'postsAndReplies'>>('posts')
|
||||||
const bottomRef = useRef<HTMLDivElement | null>(null)
|
const bottomRef = useRef<HTMLDivElement | null>(null)
|
||||||
const topRef = useRef<HTMLDivElement | null>(null)
|
const topRef = useRef<HTMLDivElement | null>(null)
|
||||||
|
const { isUserTrusted, hideUntrustedNotes } = useUserTrust()
|
||||||
|
const { feedInfo } = useFeed()
|
||||||
const filteredNewEvents = useMemo(() => {
|
const filteredNewEvents = useMemo(() => {
|
||||||
return newEvents.filter((event: Event) => {
|
return newEvents.filter((event: Event) => {
|
||||||
return (
|
return (
|
||||||
(!filterMutedNotes || !mutePubkeys.includes(event.pubkey)) &&
|
(!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(() => {
|
useEffect(() => {
|
||||||
switch (listMode) {
|
switch (listMode) {
|
||||||
@@ -341,7 +346,11 @@ export default function NoteList({
|
|||||||
<div>
|
<div>
|
||||||
{events
|
{events
|
||||||
.slice(0, showCount)
|
.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) => (
|
.map((event) => (
|
||||||
<NoteCard
|
<NoteCard
|
||||||
key={event.id}
|
key={event.id}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export const StorageKey = {
|
|||||||
HIDE_UNTRUSTED_INTERACTIONS: 'hideUntrustedInteractions',
|
HIDE_UNTRUSTED_INTERACTIONS: 'hideUntrustedInteractions',
|
||||||
HIDE_UNTRUSTED_NOTIFICATIONS: 'hideUntrustedNotifications',
|
HIDE_UNTRUSTED_NOTIFICATIONS: 'hideUntrustedNotifications',
|
||||||
TRANSLATION_SERVICE_CONFIG_MAP: 'translationServiceConfigMap',
|
TRANSLATION_SERVICE_CONFIG_MAP: 'translationServiceConfigMap',
|
||||||
|
HIDE_UNTRUSTED_NOTES: 'hideUntrustedNotes',
|
||||||
HIDE_UNTRUSTED_EVENTS: 'hideUntrustedEvents', // deprecated
|
HIDE_UNTRUSTED_EVENTS: 'hideUntrustedEvents', // deprecated
|
||||||
ACCOUNT_RELAY_LIST_EVENT_MAP: 'accountRelayListEventMap', // deprecated
|
ACCOUNT_RELAY_LIST_EVENT_MAP: 'accountRelayListEventMap', // deprecated
|
||||||
ACCOUNT_FOLLOW_LIST_EVENT_MAP: 'accountFollowListEventMap', // deprecated
|
ACCOUNT_FOLLOW_LIST_EVENT_MAP: 'accountFollowListEventMap', // deprecated
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ import { useTheme } from '@/providers/ThemeProvider'
|
|||||||
import { SelectValue } from '@radix-ui/react-select'
|
import { SelectValue } from '@radix-ui/react-select'
|
||||||
import { forwardRef, HTMLProps, useState } from 'react'
|
import { forwardRef, HTMLProps, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { useUserTrust } from '@/providers/UserTrustProvider'
|
||||||
|
|
||||||
const GeneralSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
|
const GeneralSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
|
||||||
const { t, i18n } = useTranslation()
|
const { t, i18n } = useTranslation()
|
||||||
const [language, setLanguage] = useState<TLanguage>(i18n.language as TLanguage)
|
const [language, setLanguage] = useState<TLanguage>(i18n.language as TLanguage)
|
||||||
const { themeSetting, setThemeSetting } = useTheme()
|
const { themeSetting, setThemeSetting } = useTheme()
|
||||||
const { autoplay, setAutoplay } = useAutoplay()
|
const { autoplay, setAutoplay } = useAutoplay()
|
||||||
|
const { hideUntrustedNotes, updateHideUntrustedNotes } = useUserTrust()
|
||||||
|
|
||||||
const handleLanguageChange = (value: TLanguage) => {
|
const handleLanguageChange = (value: TLanguage) => {
|
||||||
i18n.changeLanguage(value)
|
i18n.changeLanguage(value)
|
||||||
@@ -63,6 +65,12 @@ const GeneralSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
|
|||||||
</Label>
|
</Label>
|
||||||
<Switch id="autoplay" checked={autoplay} onCheckedChange={setAutoplay} />
|
<Switch id="autoplay" checked={autoplay} onCheckedChange={setAutoplay} />
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
<SettingItem>
|
||||||
|
<Label htmlFor="hideUntrustedNotes" className="text-base font-normal">
|
||||||
|
{t('Hide untrusted posts')}
|
||||||
|
</Label>
|
||||||
|
<Switch id="hideUntrustedNotes" checked={hideUntrustedNotes} onCheckedChange={updateHideUntrustedNotes} />
|
||||||
|
</SettingItem>
|
||||||
</div>
|
</div>
|
||||||
</SecondaryPageLayout>
|
</SecondaryPageLayout>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import { useNostr } from './NostrProvider'
|
|||||||
type TUserTrustContext = {
|
type TUserTrustContext = {
|
||||||
hideUntrustedInteractions: boolean
|
hideUntrustedInteractions: boolean
|
||||||
hideUntrustedNotifications: boolean
|
hideUntrustedNotifications: boolean
|
||||||
|
hideUntrustedNotes: boolean
|
||||||
updateHideUntrustedInteractions: (hide: boolean) => void
|
updateHideUntrustedInteractions: (hide: boolean) => void
|
||||||
updateHideUntrustedNotifications: (hide: boolean) => void
|
updateHideUntrustedNotifications: (hide: boolean) => void
|
||||||
|
updateHideUntrustedNotes: (hide: boolean) => void
|
||||||
isUserTrusted: (pubkey: string) => boolean
|
isUserTrusted: (pubkey: string) => boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,6 +33,9 @@ export function UserTrustProvider({ children }: { children: React.ReactNode }) {
|
|||||||
const [hideUntrustedNotifications, setHideUntrustedNotifications] = useState(() =>
|
const [hideUntrustedNotifications, setHideUntrustedNotifications] = useState(() =>
|
||||||
storage.getHideUntrustedNotifications()
|
storage.getHideUntrustedNotifications()
|
||||||
)
|
)
|
||||||
|
const [hideUntrustedNotes, setHideUntrustedNotes] = useState(() =>
|
||||||
|
storage.getHideUntrustedNotes ? storage.getHideUntrustedNotes() : false
|
||||||
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!currentPubkey) return
|
if (!currentPubkey) return
|
||||||
@@ -66,13 +71,22 @@ export function UserTrustProvider({ children }: { children: React.ReactNode }) {
|
|||||||
storage.setHideUntrustedNotifications(hide)
|
storage.setHideUntrustedNotifications(hide)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateHideUntrustedNotes = (hide: boolean) => {
|
||||||
|
setHideUntrustedNotes(hide)
|
||||||
|
if (storage.setHideUntrustedNotes) {
|
||||||
|
storage.setHideUntrustedNotes(hide)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UserTrustContext.Provider
|
<UserTrustContext.Provider
|
||||||
value={{
|
value={{
|
||||||
hideUntrustedInteractions,
|
hideUntrustedInteractions,
|
||||||
hideUntrustedNotifications,
|
hideUntrustedNotifications,
|
||||||
|
hideUntrustedNotes,
|
||||||
updateHideUntrustedInteractions,
|
updateHideUntrustedInteractions,
|
||||||
updateHideUntrustedNotifications,
|
updateHideUntrustedNotifications,
|
||||||
|
updateHideUntrustedNotes,
|
||||||
isUserTrusted
|
isUserTrusted
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class LocalStorageService {
|
|||||||
private autoplay: boolean = true
|
private autoplay: boolean = true
|
||||||
private hideUntrustedInteractions: boolean = false
|
private hideUntrustedInteractions: boolean = false
|
||||||
private hideUntrustedNotifications: boolean = false
|
private hideUntrustedNotifications: boolean = false
|
||||||
|
private hideUntrustedNotes: boolean = false
|
||||||
private translationServiceConfigMap: Record<string, TTranslationServiceConfig> = {}
|
private translationServiceConfigMap: Record<string, TTranslationServiceConfig> = {}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -95,8 +96,9 @@ class LocalStorageService {
|
|||||||
window.localStorage.getItem(StorageKey.MEDIA_UPLOAD_SERVICE) ?? DEFAULT_NIP_96_SERVICE
|
window.localStorage.getItem(StorageKey.MEDIA_UPLOAD_SERVICE) ?? DEFAULT_NIP_96_SERVICE
|
||||||
|
|
||||||
this.autoplay = window.localStorage.getItem(StorageKey.AUTOPLAY) !== 'false'
|
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'
|
window.localStorage.getItem(StorageKey.HIDE_UNTRUSTED_EVENTS) === 'true'
|
||||||
const storedHideUntrustedInteractions = window.localStorage.getItem(
|
const storedHideUntrustedInteractions = window.localStorage.getItem(
|
||||||
StorageKey.HIDE_UNTRUSTED_INTERACTIONS
|
StorageKey.HIDE_UNTRUSTED_INTERACTIONS
|
||||||
@@ -106,10 +108,11 @@ class LocalStorageService {
|
|||||||
)
|
)
|
||||||
this.hideUntrustedInteractions = storedHideUntrustedInteractions
|
this.hideUntrustedInteractions = storedHideUntrustedInteractions
|
||||||
? storedHideUntrustedInteractions === 'true'
|
? storedHideUntrustedInteractions === 'true'
|
||||||
: hideUntrustedEvents
|
: hideUntrustedNotes
|
||||||
this.hideUntrustedNotifications = storedHideUntrustedNotifications
|
this.hideUntrustedNotifications = storedHideUntrustedNotifications
|
||||||
? storedHideUntrustedNotifications === 'true'
|
? storedHideUntrustedNotifications === 'true'
|
||||||
: hideUntrustedEvents
|
: hideUntrustedNotes
|
||||||
|
this.hideUntrustedNotes = hideUntrustedNotes
|
||||||
|
|
||||||
const translationServiceConfigMapStr = window.localStorage.getItem(
|
const translationServiceConfigMapStr = window.localStorage.getItem(
|
||||||
StorageKey.TRANSLATION_SERVICE_CONFIG_MAP
|
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) {
|
getTranslationServiceConfig(pubkey?: string | null) {
|
||||||
return this.translationServiceConfigMap[pubkey ?? '_'] ?? { service: 'jumble' }
|
return this.translationServiceConfigMap[pubkey ?? '_'] ?? { service: 'jumble' }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user