getEventKey(event), [event])
const replies = useThread(eventKey)
@@ -69,6 +70,7 @@ export default function ReplyNote({
return
}
+ const trustScoreThreshold = getMinTrustScore(SPECIAL_TRUST_SCORE_FILTER_ID.INTERACTIONS)
for (const reply of replies) {
if (mutePubkeySet.has(reply.pubkey)) {
continue
@@ -76,7 +78,7 @@ export default function ReplyNote({
if (hideContentMentioningMutedUsers && isMentioningMutedUsers(reply, mutePubkeySet)) {
continue
}
- if (!(await meetsMinTrustScore(reply.pubkey))) {
+ if (trustScoreThreshold && !(await meetsMinTrustScore(reply.pubkey, trustScoreThreshold))) {
continue
}
setHasReplies(true)
@@ -86,7 +88,13 @@ export default function ReplyNote({
}
checkHasReplies()
- }, [replies, minTrustScore, meetsMinTrustScore, mutePubkeySet, hideContentMentioningMutedUsers])
+ }, [
+ replies,
+ getMinTrustScore,
+ meetsMinTrustScore,
+ mutePubkeySet,
+ hideContentMentioningMutedUsers
+ ])
return (
@@ -28,10 +29,15 @@ export default function RepostList({ event }: { event: Event }) {
useEffect(() => {
const filterReposts = async () => {
const reposts = noteStats?.reposts ?? []
+ const trustScoreThreshold = getMinTrustScore(SPECIAL_TRUST_SCORE_FILTER_ID.INTERACTIONS)
+ if (!trustScoreThreshold) {
+ setFilteredReposts([...reposts].sort((a, b) => b.created_at - a.created_at))
+ return
+ }
const filtered = (
await Promise.all(
reposts.map(async (repost) => {
- if (await meetsMinTrustScore(repost.pubkey)) {
+ if (await meetsMinTrustScore(repost.pubkey, trustScoreThreshold)) {
return repost
}
})
@@ -45,7 +51,7 @@ export default function RepostList({ event }: { event: Event }) {
setFilteredReposts(filtered)
}
filterReposts()
- }, [noteStats, event.id, minTrustScore, meetsMinTrustScore])
+ }, [noteStats, event.id, getMinTrustScore, meetsMinTrustScore])
const [showCount, setShowCount] = useState(SHOW_COUNT)
const bottomRef = useRef(null)
diff --git a/src/components/SearchResult/index.tsx b/src/components/SearchResult/index.tsx
index 91671d3..823f8d8 100644
--- a/src/components/SearchResult/index.tsx
+++ b/src/components/SearchResult/index.tsx
@@ -1,4 +1,4 @@
-import { SEARCHABLE_RELAY_URLS } from '@/constants'
+import { SEARCHABLE_RELAY_URLS, SPECIAL_TRUST_SCORE_FILTER_ID } from '@/constants'
import { getDefaultRelayUrls } from '@/lib/relay'
import { TSearchParams } from '@/types'
import NormalFeed from '../NormalFeed'
@@ -20,6 +20,7 @@ export default function SearchResult({ searchParams }: { searchParams: TSearchPa
if (searchParams.type === 'notes') {
return (
@@ -28,13 +29,20 @@ export default function SearchResult({ searchParams }: { searchParams: TSearchPa
if (searchParams.type === 'hashtag') {
return (
)
}
if (searchParams.type === 'nak') {
- return
+ return (
+
+ )
}
return
}
diff --git a/src/components/StuffStats/LikeButton.tsx b/src/components/StuffStats/LikeButton.tsx
index de1729f..9399aaa 100644
--- a/src/components/StuffStats/LikeButton.tsx
+++ b/src/components/StuffStats/LikeButton.tsx
@@ -1,6 +1,6 @@
import { Drawer, DrawerContent, DrawerOverlay } from '@/components/ui/drawer'
import { Popover, PopoverAnchor, PopoverContent } from '@/components/ui/popover'
-import { LONG_PRESS_THRESHOLD } from '@/constants'
+import { LONG_PRESS_THRESHOLD, SPECIAL_TRUST_SCORE_FILTER_ID } from '@/constants'
import { useStuff } from '@/hooks/useStuff'
import { useStuffStatsById } from '@/hooks/useStuffStatsById'
import {
@@ -28,7 +28,7 @@ export default function LikeButton({ stuff }: { stuff: Event | string }) {
const { t } = useTranslation()
const { isSmallScreen } = useScreenSize()
const { pubkey, publish, checkLogin } = useNostr()
- const { meetsMinTrustScore } = useUserTrust()
+ const { getMinTrustScore, meetsMinTrustScore } = useUserTrust()
const { quickReaction, quickReactionEmoji } = useUserPreferences()
const { event, externalContent, stuffKey } = useStuff(stuff)
const [liking, setLiking] = useState(false)
@@ -49,9 +49,15 @@ export default function LikeButton({ stuff }: { stuff: Event | string }) {
const stats = noteStats || {}
const likes = stats.likes || []
let count = 0
+
+ const trustScoreThreshold = getMinTrustScore(SPECIAL_TRUST_SCORE_FILTER_ID.INTERACTIONS)
+ if (!trustScoreThreshold) {
+ setLikeCount(likes.length)
+ return
+ }
await Promise.all(
likes.map(async (like) => {
- if (await meetsMinTrustScore(like.pubkey)) {
+ if (await meetsMinTrustScore(like.pubkey, trustScoreThreshold)) {
count++
}
})
@@ -59,7 +65,7 @@ export default function LikeButton({ stuff }: { stuff: Event | string }) {
setLikeCount(count)
}
filterLikes()
- }, [noteStats, meetsMinTrustScore])
+ }, [noteStats, meetsMinTrustScore, getMinTrustScore])
useEffect(() => {
setTimeout(() => setIsPickerOpen(false), 100)
diff --git a/src/components/StuffStats/RepostButton.tsx b/src/components/StuffStats/RepostButton.tsx
index 7983a33..6d51fa1 100644
--- a/src/components/StuffStats/RepostButton.tsx
+++ b/src/components/StuffStats/RepostButton.tsx
@@ -21,11 +21,12 @@ import { useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import PostEditor from '../PostEditor'
import { formatCount } from './utils'
+import { SPECIAL_TRUST_SCORE_FILTER_ID } from '@/constants'
export default function RepostButton({ stuff }: { stuff: Event | string }) {
const { t } = useTranslation()
const { isSmallScreen } = useScreenSize()
- const { meetsMinTrustScore } = useUserTrust()
+ const { getMinTrustScore, meetsMinTrustScore } = useUserTrust()
const { publish, checkLogin, pubkey } = useNostr()
const { event, stuffKey } = useStuff(stuff)
const noteStats = useStuffStatsById(stuffKey)
@@ -46,9 +47,15 @@ export default function RepostButton({ stuff }: { stuff: Event | string }) {
const reposts = noteStats?.reposts || []
let count = 0
+
+ const trustScoreThreshold = getMinTrustScore(SPECIAL_TRUST_SCORE_FILTER_ID.INTERACTIONS)
+ if (!trustScoreThreshold) {
+ setRepostCount(reposts.length)
+ return
+ }
await Promise.all(
reposts.map(async (repost) => {
- if (await meetsMinTrustScore(repost.pubkey)) {
+ if (await meetsMinTrustScore(repost.pubkey, trustScoreThreshold)) {
count++
}
})
@@ -56,7 +63,7 @@ export default function RepostButton({ stuff }: { stuff: Event | string }) {
setRepostCount(count)
}
filterReposts()
- }, [noteStats, event, meetsMinTrustScore])
+ }, [noteStats, event, meetsMinTrustScore, getMinTrustScore])
const canRepost = !hasReposted && !reposting && !!event
const repost = async () => {
diff --git a/src/components/TrendingNotes/index.tsx b/src/components/TrendingNotes/index.tsx
index f1206a8..51c7503 100644
--- a/src/components/TrendingNotes/index.tsx
+++ b/src/components/TrendingNotes/index.tsx
@@ -1,4 +1,4 @@
-import { TRENDING_NOTES_RELAY_URLS } from '@/constants'
+import { SPECIAL_TRUST_SCORE_FILTER_ID, TRENDING_NOTES_RELAY_URLS } from '@/constants'
import { simplifyUrl } from '@/lib/url'
import { useTranslation } from 'react-i18next'
import NormalFeed from '../NormalFeed'
@@ -19,6 +19,7 @@ export default function TrendingNotes() {
diff --git a/src/components/TrustScoreFilter/index.tsx b/src/components/TrustScoreFilter/index.tsx
index 22fd4e2..da160e0 100644
--- a/src/components/TrustScoreFilter/index.tsx
+++ b/src/components/TrustScoreFilter/index.tsx
@@ -28,20 +28,22 @@ function getDescription(score: number, t: (key: string, options?: any) => string
}
export default function TrustScoreFilter({
+ filterId,
onOpenChange
}: {
+ filterId: string
onOpenChange?: (open: boolean) => void
}) {
const { t } = useTranslation()
const { isSmallScreen } = useScreenSize()
- const { minTrustScore, updateMinTrustScore } = useUserTrust()
+ const { getMinTrustScore, updateMinTrustScore } = useUserTrust()
const [open, setOpen] = useState(false)
- const [temporaryScore, setTemporaryScore] = useState(minTrustScore)
+ const [temporaryScore, setTemporaryScore] = useState(0)
const debounceTimerRef = useRef(null)
useEffect(() => {
- setTemporaryScore(minTrustScore)
- }, [minTrustScore])
+ setTemporaryScore(getMinTrustScore(filterId))
+ }, [getMinTrustScore, filterId])
// Debounced update function
const handleScoreChange = (newScore: number) => {
@@ -54,7 +56,7 @@ export default function TrustScoreFilter({
// Set new timer for debounced update
debounceTimerRef.current = setTimeout(() => {
- updateMinTrustScore(newScore)
+ updateMinTrustScore(filterId, newScore)
}, 300) // 300ms debounce delay
}
@@ -81,7 +83,7 @@ export default function TrustScoreFilter({
size="titlebar-icon"
className={cn(
'relative',
- minTrustScore === 0
+ temporaryScore === 0
? 'text-muted-foreground hover:text-foreground'
: 'text-primary hover:text-primary-hover'
)}
@@ -89,10 +91,10 @@ export default function TrustScoreFilter({
setOpen(true)
}}
>
- {minTrustScore < 100 ? : }
- {minTrustScore > 0 && minTrustScore < 100 && (
+ {temporaryScore < 100 ? : }
+ {temporaryScore > 0 && temporaryScore < 100 && (
- {minTrustScore}
+ {temporaryScore}
)}
diff --git a/src/components/UserAggregationList/index.tsx b/src/components/UserAggregationList/index.tsx
index 6d6601c..4c684df 100644
--- a/src/components/UserAggregationList/index.tsx
+++ b/src/components/UserAggregationList/index.tsx
@@ -55,6 +55,7 @@ const UserAggregationList = forwardRef<
areAlgoRelays?: boolean
showRelayCloseReason?: boolean
isPubkeyFeed?: boolean
+ trustScoreThreshold?: number
}
>(
(
@@ -64,7 +65,8 @@ const UserAggregationList = forwardRef<
filterMutedNotes = true,
areAlgoRelays = false,
showRelayCloseReason = false,
- isPubkeyFeed = false
+ isPubkeyFeed = false,
+ trustScoreThreshold
},
ref
) => {
@@ -282,7 +284,10 @@ const UserAggregationList = forwardRef<
) {
return null
}
- if (!(await meetsMinTrustScore(evt.pubkey))) {
+ if (
+ trustScoreThreshold &&
+ !(await meetsMinTrustScore(evt.pubkey, trustScoreThreshold))
+ ) {
return null
}
@@ -300,7 +305,8 @@ const UserAggregationList = forwardRef<
filterMutedNotes,
hideContentMentioningMutedUsers,
isMentioningMutedUsers,
- meetsMinTrustScore
+ meetsMinTrustScore,
+ trustScoreThreshold
]
)
diff --git a/src/constants.ts b/src/constants.ts
index b7f3a86..d05a1b9 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -41,9 +41,10 @@ export const StorageKey = {
QUICK_REACTION: 'quickReaction',
QUICK_REACTION_EMOJI: 'quickReactionEmoji',
NSFW_DISPLAY_POLICY: 'nsfwDisplayPolicy',
- MIN_TRUST_SCORE: 'minTrustScore',
DEFAULT_RELAY_URLS: 'defaultRelayUrls',
MUTED_WORDS: 'mutedWords',
+ MIN_TRUST_SCORE: 'minTrustScore',
+ MIN_TRUST_SCORE_MAP: 'minTrustScoreMap',
ENABLE_LIVE_FEED: 'enableLiveFeed', // deprecated
HIDE_UNTRUSTED_NOTES: 'hideUntrustedNotes', // deprecated
HIDE_UNTRUSTED_INTERACTIONS: 'hideUntrustedInteractions', // deprecated
@@ -472,3 +473,13 @@ export type TPrimaryColor = keyof typeof PRIMARY_COLORS
export const LONG_PRESS_THRESHOLD = 400
export const SPAMMER_PERCENTILE_THRESHOLD = 60
+
+export const SPECIAL_TRUST_SCORE_FILTER_ID = {
+ DEFAULT: 'default',
+ INTERACTIONS: 'interactions',
+ NOTIFICATIONS: 'notifications',
+ SEARCH: 'search',
+ HASHTAG: 'hashtag',
+ NAK: 'nak',
+ TRENDING: 'trending'
+}
diff --git a/src/hooks/useFilteredReplies.tsx b/src/hooks/useFilteredReplies.tsx
index 74d637c..dfd35ea 100644
--- a/src/hooks/useFilteredReplies.tsx
+++ b/src/hooks/useFilteredReplies.tsx
@@ -6,10 +6,11 @@ import { useUserTrust } from '@/providers/UserTrustProvider'
import { NostrEvent } from 'nostr-tools'
import { useEffect, useState } from 'react'
import { useAllDescendantThreads } from './useThread'
+import { SPECIAL_TRUST_SCORE_FILTER_ID } from '@/constants'
export function useFilteredReplies(stuffKey: string) {
const { pubkey } = useNostr()
- const { minTrustScore, meetsMinTrustScore } = useUserTrust()
+ const { getMinTrustScore, meetsMinTrustScore } = useUserTrust()
const { mutePubkeySet } = useMuteList()
const { hideContentMentioningMutedUsers } = useContentPolicy()
const allThreads = useAllDescendantThreads(stuffKey)
@@ -22,6 +23,7 @@ export function useFilteredReplies(stuffKey: string) {
const thread = allThreads.get(stuffKey) || []
const filtered: NostrEvent[] = []
+ const trustScoreThreshold = getMinTrustScore(SPECIAL_TRUST_SCORE_FILTER_ID.INTERACTIONS)
await Promise.all(
thread.map(async (evt) => {
const key = getEventKey(evt)
@@ -31,7 +33,7 @@ export function useFilteredReplies(stuffKey: string) {
if (mutePubkeySet.has(evt.pubkey)) return
if (hideContentMentioningMutedUsers && isMentioningMutedUsers(evt, mutePubkeySet)) return
- const meetsTrust = await meetsMinTrustScore(evt.pubkey)
+ const meetsTrust = await meetsMinTrustScore(evt.pubkey, trustScoreThreshold)
if (!meetsTrust) {
const replyKey = getEventKey(evt)
const repliesForThisReply = allThreads.get(replyKey)
@@ -39,7 +41,7 @@ export function useFilteredReplies(stuffKey: string) {
if (repliesForThisReply && repliesForThisReply.length > 0) {
let hasTrustedReply = false
for (const reply of repliesForThisReply) {
- if (await meetsMinTrustScore(reply.pubkey)) {
+ if (await meetsMinTrustScore(reply.pubkey, trustScoreThreshold)) {
hasTrustedReply = true
break
}
@@ -63,7 +65,7 @@ export function useFilteredReplies(stuffKey: string) {
allThreads,
mutePubkeySet,
hideContentMentioningMutedUsers,
- minTrustScore,
+ getMinTrustScore,
meetsMinTrustScore
])
@@ -84,7 +86,7 @@ export function useFilteredReplies(stuffKey: string) {
export function useFilteredAllReplies(stuffKey: string) {
const { pubkey } = useNostr()
const allThreads = useAllDescendantThreads(stuffKey)
- const { minTrustScore, meetsMinTrustScore } = useUserTrust()
+ const { getMinTrustScore, meetsMinTrustScore } = useUserTrust()
const { mutePubkeySet } = useMuteList()
const { hideContentMentioningMutedUsers } = useContentPolicy()
const [replies, setReplies] = useState([])
@@ -94,6 +96,7 @@ export function useFilteredAllReplies(stuffKey: string) {
const filterReplies = async () => {
const replyKeySet = new Set()
const replyEvents: NostrEvent[] = []
+ const trustScoreThreshold = getMinTrustScore(SPECIAL_TRUST_SCORE_FILTER_ID.INTERACTIONS)
let parentKeys = [stuffKey]
while (parentKeys.length > 0) {
@@ -108,7 +111,7 @@ export function useFilteredAllReplies(stuffKey: string) {
if (hideContentMentioningMutedUsers && isMentioningMutedUsers(evt, mutePubkeySet))
return
- const meetsTrust = await meetsMinTrustScore(evt.pubkey)
+ const meetsTrust = await meetsMinTrustScore(evt.pubkey, trustScoreThreshold)
if (!meetsTrust) {
const replyKey = getEventKey(evt)
const repliesForThisReply = allThreads.get(replyKey)
@@ -116,7 +119,7 @@ export function useFilteredAllReplies(stuffKey: string) {
if (repliesForThisReply && repliesForThisReply.length > 0) {
let hasTrustedReply = false
for (const reply of repliesForThisReply) {
- if (await meetsMinTrustScore(reply.pubkey)) {
+ if (await meetsMinTrustScore(reply.pubkey, trustScoreThreshold)) {
hasTrustedReply = true
break
}
@@ -141,7 +144,7 @@ export function useFilteredAllReplies(stuffKey: string) {
allThreads,
mutePubkeySet,
hideContentMentioningMutedUsers,
- minTrustScore,
+ getMinTrustScore,
meetsMinTrustScore
])
diff --git a/src/i18n/locales/ar.ts b/src/i18n/locales/ar.ts
index 5c0f0d8..7ff9688 100644
--- a/src/i18n/locales/ar.ts
+++ b/src/i18n/locales/ar.ts
@@ -663,6 +663,7 @@ export default {
'Invalid relay URL': 'عنوان URL للمرحل غير صالح',
'Muted words': 'الكلمات المحظورة',
'Add muted word': 'إضافة كلمة محظورة',
- 'Zap Details': 'تفاصيل Zap'
+ 'Zap Details': 'تفاصيل Zap',
+ 'Default trust score filter threshold ({{n}}%)': 'عتبة مرشح درجة الثقة الافتراضية ({{n}}%)'
}
}
diff --git a/src/i18n/locales/de.ts b/src/i18n/locales/de.ts
index 9c527a0..d950f26 100644
--- a/src/i18n/locales/de.ts
+++ b/src/i18n/locales/de.ts
@@ -685,6 +685,8 @@ export default {
'Invalid relay URL': 'Ungültige Relay-URL',
'Muted words': 'Stummgeschaltete Wörter',
'Add muted word': 'Stummgeschaltetes Wort hinzufügen',
- 'Zap Details': 'Zap-Details'
+ 'Zap Details': 'Zap-Details',
+ 'Default trust score filter threshold ({{n}}%)':
+ 'Standard-Vertrauenswert-Filter-Schwelle ({{n}}%)'
}
}
diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts
index c24f506..37e8838 100644
--- a/src/i18n/locales/en.ts
+++ b/src/i18n/locales/en.ts
@@ -668,6 +668,7 @@ export default {
'Invalid relay URL': 'Invalid relay URL',
'Muted words': 'Muted words',
'Add muted word': 'Add muted word',
- 'Zap Details': 'Zap Details'
+ 'Zap Details': 'Zap Details',
+ 'Default trust score filter threshold ({{n}}%)': 'Default trust score filter threshold ({{n}}%)'
}
}
diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts
index 06baa5e..79eb862 100644
--- a/src/i18n/locales/es.ts
+++ b/src/i18n/locales/es.ts
@@ -679,6 +679,8 @@ export default {
'Invalid relay URL': 'URL de relé no válida',
'Muted words': 'Palabras silenciadas',
'Add muted word': 'Agregar palabra silenciada',
- 'Zap Details': 'Detalles del Zap'
+ 'Zap Details': 'Detalles del Zap',
+ 'Default trust score filter threshold ({{n}}%)':
+ 'Umbral predeterminado del filtro de puntuación de confianza ({{n}}%)'
}
}
diff --git a/src/i18n/locales/fa.ts b/src/i18n/locales/fa.ts
index e72717d..642e705 100644
--- a/src/i18n/locales/fa.ts
+++ b/src/i18n/locales/fa.ts
@@ -674,6 +674,7 @@ export default {
'Invalid relay URL': 'آدرس URL رله نامعتبر است',
'Muted words': 'کلمات بیصدا شده',
'Add muted word': 'افزودن کلمه بیصدا',
- 'Zap Details': 'جزئیات زپ'
+ 'Zap Details': 'جزئیات زپ',
+ 'Default trust score filter threshold ({{n}}%)': 'آستانه فیلتر امتیاز اعتماد پیشفرض ({{n}}%)'
}
}
diff --git a/src/i18n/locales/fr.ts b/src/i18n/locales/fr.ts
index 3e5d6b7..ab7e34c 100644
--- a/src/i18n/locales/fr.ts
+++ b/src/i18n/locales/fr.ts
@@ -683,6 +683,8 @@ export default {
'Invalid relay URL': 'URL de relais non valide',
'Muted words': 'Mots masqués',
'Add muted word': 'Ajouter un mot masqué',
- 'Zap Details': 'Détails du Zap'
+ 'Zap Details': 'Détails du Zap',
+ 'Default trust score filter threshold ({{n}}%)':
+ 'Seuil par défaut du filtre de score de confiance ({{n}}%)'
}
}
diff --git a/src/i18n/locales/hi.ts b/src/i18n/locales/hi.ts
index 24bdfdc..92912cf 100644
--- a/src/i18n/locales/hi.ts
+++ b/src/i18n/locales/hi.ts
@@ -675,6 +675,7 @@ export default {
'Invalid relay URL': 'अमान्य रिले URL',
'Muted words': 'म्यूट किए गए शब्द',
'Add muted word': 'म्यूट शब्द जोड़ें',
- 'Zap Details': 'जैप विवरण'
+ 'Zap Details': 'जैप विवरण',
+ 'Default trust score filter threshold ({{n}}%)': 'डिफ़ॉल्ट विश्वास स्कोर फ़िल्टर सीमा ({{n}}%)'
}
}
diff --git a/src/i18n/locales/hu.ts b/src/i18n/locales/hu.ts
index e8d8f99..900a4c6 100644
--- a/src/i18n/locales/hu.ts
+++ b/src/i18n/locales/hu.ts
@@ -668,6 +668,8 @@ export default {
'Invalid relay URL': 'Érvénytelen továbbító URL',
'Muted words': 'Némított szavak',
'Add muted word': 'Némított szó hozzáadása',
- 'Zap Details': 'Zap Részletek'
+ 'Zap Details': 'Zap Részletek',
+ 'Default trust score filter threshold ({{n}}%)':
+ 'Alapértelmezett bizalmi pontszám szűrő küszöbérték ({{n}}%)'
}
}
diff --git a/src/i18n/locales/it.ts b/src/i18n/locales/it.ts
index 5bb2251..d0fe2e4 100644
--- a/src/i18n/locales/it.ts
+++ b/src/i18n/locales/it.ts
@@ -679,6 +679,8 @@ export default {
'Invalid relay URL': 'URL relay non valido',
'Muted words': 'Parole silenziate',
'Add muted word': 'Aggiungi parola silenziata',
- 'Zap Details': 'Dettagli Zap'
+ 'Zap Details': 'Dettagli Zap',
+ 'Default trust score filter threshold ({{n}}%)':
+ 'Soglia predefinita del filtro del punteggio di fiducia ({{n}}%)'
}
}
diff --git a/src/i18n/locales/ja.ts b/src/i18n/locales/ja.ts
index dfa477a..3a143a7 100644
--- a/src/i18n/locales/ja.ts
+++ b/src/i18n/locales/ja.ts
@@ -673,6 +673,7 @@ export default {
'Invalid relay URL': '無効なリレーURL',
'Muted words': 'ミュートワード',
'Add muted word': 'ミュートワードを追加',
- 'Zap Details': 'Zapの詳細'
+ 'Zap Details': 'Zapの詳細',
+ 'Default trust score filter threshold ({{n}}%)': 'デフォルトの信頼スコアフィルター閾値 ({{n}}%)'
}
}
diff --git a/src/i18n/locales/ko.ts b/src/i18n/locales/ko.ts
index 599ccd5..6c9f15b 100644
--- a/src/i18n/locales/ko.ts
+++ b/src/i18n/locales/ko.ts
@@ -669,6 +669,7 @@ export default {
'Invalid relay URL': '유효하지 않은 릴레이 URL',
'Muted words': '차단 단어',
'Add muted word': '차단 단어 추가',
- 'Zap Details': '잽 세부 정보'
+ 'Zap Details': '잽 세부 정보',
+ 'Default trust score filter threshold ({{n}}%)': '기본 신뢰 점수 필터 임계값 ({{n}}%)'
}
}
diff --git a/src/i18n/locales/pl.ts b/src/i18n/locales/pl.ts
index eb025f6..03069a9 100644
--- a/src/i18n/locales/pl.ts
+++ b/src/i18n/locales/pl.ts
@@ -680,6 +680,7 @@ export default {
'Invalid relay URL': 'Nieprawidłowy adres URL przekaźnika',
'Muted words': 'Wyciszone słowa',
'Add muted word': 'Dodaj wyciszone słowo',
- 'Zap Details': 'Szczegóły zapu'
+ 'Zap Details': 'Szczegóły zapu',
+ 'Default trust score filter threshold ({{n}}%)': 'Domyślny próg filtra wyniku zaufania ({{n}}%)'
}
}
diff --git a/src/i18n/locales/pt-BR.ts b/src/i18n/locales/pt-BR.ts
index 4e65b52..606ccd3 100644
--- a/src/i18n/locales/pt-BR.ts
+++ b/src/i18n/locales/pt-BR.ts
@@ -676,6 +676,8 @@ export default {
'Invalid relay URL': 'URL de relé inválida',
'Muted words': 'Palavras silenciadas',
'Add muted word': 'Adicionar palavra silenciada',
- 'Zap Details': 'Detalhes do Zap'
+ 'Zap Details': 'Detalhes do Zap',
+ 'Default trust score filter threshold ({{n}}%)':
+ 'Limite padrão do filtro de pontuação de confiança ({{n}}%)'
}
}
diff --git a/src/i18n/locales/pt-PT.ts b/src/i18n/locales/pt-PT.ts
index b7ab2eb..2146bba 100644
--- a/src/i18n/locales/pt-PT.ts
+++ b/src/i18n/locales/pt-PT.ts
@@ -679,6 +679,8 @@ export default {
'Invalid relay URL': 'URL de relay inválido',
'Muted words': 'Palavras silenciadas',
'Add muted word': 'Adicionar palavra silenciada',
- 'Zap Details': 'Detalhes do Zap'
+ 'Zap Details': 'Detalhes do Zap',
+ 'Default trust score filter threshold ({{n}}%)':
+ 'Limite predefinido do filtro de pontuação de confiança ({{n}}%)'
}
}
diff --git a/src/i18n/locales/ru.ts b/src/i18n/locales/ru.ts
index 2a7b309..79ce9b7 100644
--- a/src/i18n/locales/ru.ts
+++ b/src/i18n/locales/ru.ts
@@ -679,6 +679,8 @@ export default {
'Invalid relay URL': 'Неверный URL реле',
'Muted words': 'Заблокированные слова',
'Add muted word': 'Добавить заблокированное слово',
- 'Zap Details': 'Детали запа'
+ 'Zap Details': 'Детали запа',
+ 'Default trust score filter threshold ({{n}}%)':
+ 'Порог фильтра рейтинга доверия по умолчанию ({{n}}%)'
}
}
diff --git a/src/i18n/locales/th.ts b/src/i18n/locales/th.ts
index fabc437..89146cb 100644
--- a/src/i18n/locales/th.ts
+++ b/src/i18n/locales/th.ts
@@ -664,6 +664,8 @@ export default {
'Invalid relay URL': 'URL รีเลย์ไม่ถูกต้อง',
'Muted words': 'คำที่ถูกปิดเสียง',
'Add muted word': 'เพิ่มคำที่ถูกปิดเสียง',
- 'Zap Details': 'รายละเอียดซาตส์'
+ 'Zap Details': 'รายละเอียดซาตส์',
+ 'Default trust score filter threshold ({{n}}%)':
+ 'เกณฑ์ตัวกรองคะแนนความไว้วางใจเริ่มต้น ({{n}}%)'
}
}
diff --git a/src/i18n/locales/zh-TW.ts b/src/i18n/locales/zh-TW.ts
index 14a39ab..e61ddfe 100644
--- a/src/i18n/locales/zh-TW.ts
+++ b/src/i18n/locales/zh-TW.ts
@@ -647,6 +647,7 @@ export default {
'Invalid relay URL': '無效的中繼地址',
'Muted words': '屏蔽詞',
'Add muted word': '添加屏蔽詞',
- 'Zap Details': '打閃詳情'
+ 'Zap Details': '打閃詳情',
+ 'Default trust score filter threshold ({{n}}%)': '預設信任分數過濾閾值 ({{n}}%)'
}
}
diff --git a/src/i18n/locales/zh.ts b/src/i18n/locales/zh.ts
index ce74f16..3f129ae 100644
--- a/src/i18n/locales/zh.ts
+++ b/src/i18n/locales/zh.ts
@@ -652,6 +652,7 @@ export default {
'Invalid relay URL': '无效的中继地址',
'Muted words': '屏蔽词',
'Add muted word': '添加屏蔽词',
- 'Zap Details': '打闪详情'
+ 'Zap Details': '打闪详情',
+ 'Default trust score filter threshold ({{n}}%)': '默认信任分数过滤阈值 ({{n}}%)'
}
}
diff --git a/src/lib/notification.ts b/src/lib/notification.ts
index 5bceced..c34835a 100644
--- a/src/lib/notification.ts
+++ b/src/lib/notification.ts
@@ -13,7 +13,7 @@ export async function notificationFilter(
pubkey?: string | null
mutePubkeySet: Set
hideContentMentioningMutedUsers?: boolean
- meetsMinTrustScore: (pubkey: string, minScore?: number) => Promise
+ meetsMinTrustScore: (pubkey: string) => Promise
}
): Promise {
if (
diff --git a/src/pages/primary/NoteListPage/RelaysFeed.tsx b/src/pages/primary/NoteListPage/RelaysFeed.tsx
index 05604de..1abb03d 100644
--- a/src/pages/primary/NoteListPage/RelaysFeed.tsx
+++ b/src/pages/primary/NoteListPage/RelaysFeed.tsx
@@ -2,12 +2,20 @@ import NormalFeed from '@/components/NormalFeed'
import { checkAlgoRelay } from '@/lib/relay'
import { useFeed } from '@/providers/FeedProvider'
import relayInfoService from '@/services/relay-info.service'
-import { useEffect, useState } from 'react'
+import { useEffect, useMemo, useState } from 'react'
export default function RelaysFeed() {
- const { relayUrls } = useFeed()
+ const { relayUrls, feedInfo } = useFeed()
const [isReady, setIsReady] = useState(false)
const [areAlgoRelays, setAreAlgoRelays] = useState(false)
+ const trustScoreFilterId = useMemo(() => {
+ if (feedInfo?.feedType === 'relay' && feedInfo.id) {
+ return `relay-${feedInfo.id}`
+ } else if (feedInfo?.feedType === 'relays' && feedInfo.id) {
+ return `relays-${feedInfo.id}`
+ }
+ return 'relays-default'
+ }, [feedInfo])
useEffect(() => {
const init = async () => {
@@ -24,6 +32,7 @@ export default function RelaysFeed() {
return (
{t('Notifications')}
-
+
)
}
diff --git a/src/pages/secondary/FollowPackPage/index.tsx b/src/pages/secondary/FollowPackPage/index.tsx
index ba07c3a..0445ff7 100644
--- a/src/pages/secondary/FollowPackPage/index.tsx
+++ b/src/pages/secondary/FollowPackPage/index.tsx
@@ -4,6 +4,7 @@ import ProfileList from '@/components/ProfileList'
import { Skeleton } from '@/components/ui/skeleton'
import { useFetchEvent } from '@/hooks/useFetchEvent'
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
+import { getEventKey } from '@/lib/event'
import { getFollowPackInfoFromEvent } from '@/lib/event-metadata'
import { cn } from '@/lib/utils'
import { useNostr } from '@/providers/NostrProvider'
@@ -96,7 +97,9 @@ const FollowPackPage = forwardRef(({ id, index }: { id?: string; index?: number
{/* Content */}
{tab === 'users' && }
- {tab === 'feed' && pubkeys.length > 0 && }
+ {tab === 'feed' && pubkeys.length > 0 && (
+
+ )}
)
@@ -104,7 +107,7 @@ const FollowPackPage = forwardRef(({ id, index }: { id?: string; index?: number
FollowPackPage.displayName = 'FollowPackPage'
export default FollowPackPage
-function Feed({ pubkeys }: { pubkeys: string[] }) {
+function Feed({ trustScoreFilterId, pubkeys }: { trustScoreFilterId: string; pubkeys: string[] }) {
const { pubkey: myPubkey } = useNostr()
const [subRequests, setSubRequests] = useState([])
@@ -112,5 +115,5 @@ function Feed({ pubkeys }: { pubkeys: string[] }) {
client.generateSubRequestsForPubkeys(pubkeys, myPubkey).then(setSubRequests)
}, [pubkeys, myPubkey])
- return
+ return
}
diff --git a/src/pages/secondary/GeneralSettingsPage/DefaultTrustScoreFilter.tsx b/src/pages/secondary/GeneralSettingsPage/DefaultTrustScoreFilter.tsx
new file mode 100644
index 0000000..c00abab
--- /dev/null
+++ b/src/pages/secondary/GeneralSettingsPage/DefaultTrustScoreFilter.tsx
@@ -0,0 +1,29 @@
+import { Label } from '@/components/ui/label'
+import { Slider } from '@/components/ui/slider'
+import { SPECIAL_TRUST_SCORE_FILTER_ID } from '@/constants'
+import { useUserTrust } from '@/providers/UserTrustProvider'
+import { useTranslation } from 'react-i18next'
+import SettingItem from './SettingItem'
+
+export default function DefaultTrustScoreFilter() {
+ const { t } = useTranslation()
+ const { minTrustScore, updateMinTrustScore } = useUserTrust()
+
+ return (
+
+
+
+ updateMinTrustScore(SPECIAL_TRUST_SCORE_FILTER_ID.DEFAULT, value)
+ }
+ min={0}
+ max={100}
+ step={5}
+ className="w-full"
+ />
+
+ )
+}
diff --git a/src/pages/secondary/GeneralSettingsPage/index.tsx b/src/pages/secondary/GeneralSettingsPage/index.tsx
index 6e40c26..fc574c8 100644
--- a/src/pages/secondary/GeneralSettingsPage/index.tsx
+++ b/src/pages/secondary/GeneralSettingsPage/index.tsx
@@ -19,6 +19,7 @@ import { SelectValue } from '@radix-ui/react-select'
import { RotateCcw } from 'lucide-react'
import { forwardRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
+import DefaultTrustScoreFilter from './DefaultTrustScoreFilter'
import MutedWords from './MutedWords'
import SettingItem from './SettingItem'
@@ -150,6 +151,7 @@ const GeneralSettingsPage = forwardRef(({ index }: { index?: number }, ref) => {
+