diff --git a/src/components/Note/Zap.tsx b/src/components/Note/Zap.tsx
index 50ccf96a..0acd545e 100644
--- a/src/components/Note/Zap.tsx
+++ b/src/components/Note/Zap.tsx
@@ -1,7 +1,6 @@
import { useFetchEvent } from '@/hooks'
import { usePaymentAttestationStatus } from '@/hooks/usePaymentAttestationStatus'
import { getZapInfoFromEvent } from '@/lib/event-metadata'
-import { shouldHideInteractions } from '@/lib/event-filtering'
import { formatAmount } from '@/lib/lightning'
import { openNoteFromFetchOrCache } from '@/lib/navigation-related-events'
import { relayHintsFromEventTags } from '@/lib/relay-list-builder'
@@ -64,12 +63,6 @@ export default function Zap({
const secondaryPage = useSecondaryPageOptional()
const push = secondaryPage?.push ?? ((url: string) => { window.location.href = url })
- const inQuietMode = targetEvent ? shouldHideInteractions(targetEvent) : false
-
- if (inQuietMode) {
- return null
- }
-
if (!zapInfo || !zapInfo.senderPubkey) {
return (
diff --git a/src/components/Note/index.tsx b/src/components/Note/index.tsx
index 874753c0..ee750ba8 100644
--- a/src/components/Note/index.tsx
+++ b/src/components/Note/index.tsx
@@ -8,7 +8,6 @@ import {
isNip25ReactionKind,
isNsfwEvent
} from '@/lib/event'
-import { shouldHideInteractions } from '@/lib/event-filtering'
import { mergeNip84MarkedIntervals, renderPlaintextWithNip84MergedMarks } from '@/lib/nip84-op-body-marks'
import { getCachedThreadContextEvents } from '@/lib/navigation-related-events'
import { relayHintsFromEventTags } from '@/lib/relay-list-builder'
@@ -383,8 +382,7 @@ export default function Note({
}
if (
nip84HighlightEvents?.length &&
- displayEvent.kind === kinds.ShortTextNote &&
- !shouldHideInteractions(displayEvent)
+ displayEvent.kind === kinds.ShortTextNote
) {
const merged = mergeNip84MarkedIntervals(
displayEvent.content ?? '',
diff --git a/src/components/NoteBoostBadges/index.tsx b/src/components/NoteBoostBadges/index.tsx
index 7d98645c..132caea9 100644
--- a/src/components/NoteBoostBadges/index.tsx
+++ b/src/components/NoteBoostBadges/index.tsx
@@ -1,6 +1,5 @@
import { ExtendedKind } from '@/constants'
import { useNoteStatsById } from '@/hooks/useNoteStatsById'
-import { shouldHideInteractions } from '@/lib/event-filtering'
import { cn } from '@/lib/utils'
import { Event } from 'nostr-tools'
import { useMemo } from 'react'
@@ -22,7 +21,7 @@ export default function NoteBoostBadges({ event, className }: { event: Event; cl
return [...(noteStats?.reposts ?? [])].sort((a, b) => b.created_at - a.created_at)
}, [noteStats, event.kind])
- if (shouldHideInteractions(event) || boosters.length === 0) {
+ if (boosters.length === 0) {
return null
}
diff --git a/src/components/NoteInteractions/index.tsx b/src/components/NoteInteractions/index.tsx
index 221f0002..7052222f 100644
--- a/src/components/NoteInteractions/index.tsx
+++ b/src/components/NoteInteractions/index.tsx
@@ -1,10 +1,8 @@
import { Separator } from '@/components/ui/separator'
import { ExtendedKind } from '@/constants'
-import { shouldHideInteractions } from '@/lib/event-filtering'
import { Event } from 'nostr-tools'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
-import HideUntrustedContentButton from '../HideUntrustedContentButton'
import ReplyNoteList from '../ReplyNoteList'
import ReplySort, { ReplySortOption } from './ReplySort'
@@ -32,11 +30,6 @@ export default function NoteInteractions({
const isDiscussion = event.kind === ExtendedKind.DISCUSSION
const showQuotes = showQuotesProp ?? !isDiscussion
- // Hide interactions if event is in quiet mode
- if (shouldHideInteractions(event)) {
- return null
- }
-
return (
<>
@@ -47,7 +40,6 @@ export default function NoteInteractions({
{isDiscussion && (
)}
-
diff --git a/src/components/NoteList/index.tsx b/src/components/NoteList/index.tsx
index 8236176f..cd7dbf70 100644
--- a/src/components/NoteList/index.tsx
+++ b/src/components/NoteList/index.tsx
@@ -38,7 +38,6 @@ import { useDeletedEventSafe } from '@/providers/DeletedEventProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { muteSetHas } from '@/lib/mute-set'
import { useNostr } from '@/providers/NostrProvider'
-import { useUserTrust } from '@/contexts/user-trust-context'
import client from '@/services/client.service'
import noteStatsService from '@/services/note-stats.service'
import indexedDb from '@/services/indexed-db.service'
@@ -658,7 +657,6 @@ const NoteList = forwardRef(
allowKindlessRelayExplore = false,
filterMutedNotes = true,
hideReplies = false,
- hideUntrustedNotes = false,
areAlgoRelays = false,
relayCapabilityReady = true,
pinnedEventIds = [],
@@ -796,7 +794,6 @@ const NoteList = forwardRef(
allowKindlessRelayExplore?: boolean
filterMutedNotes?: boolean
hideReplies?: boolean
- hideUntrustedNotes?: boolean
areAlgoRelays?: boolean
/**
* When false (e.g. home relay feed waiting on `getRelayInfos`), skip timeline subscribe so
@@ -851,7 +848,6 @@ const NoteList = forwardRef(
) => {
const { t } = useTranslation()
const { startLogin, pubkey } = useNostr()
- const { isUserTrusted } = useUserTrust()
const { mutePubkeySet } = useMuteList()
const contentPolicy = useContentPolicyOptional()
const hideContentMentioningMutedUsers = contentPolicy?.hideContentMentioningMutedUsers ?? false
@@ -1309,7 +1305,6 @@ const NoteList = forwardRef(
if (pinnedEventHexIdSet.has(evt.id)) return true
if (isEventDeleted(evt)) return true
if (hideReplies && isReplyNoteEvent(evt)) return true
- if (hideUntrustedNotes && !isUserTrusted(evt.pubkey)) return true
if (filterMutedNotes && muteSetHas(mutePubkeySet, evt.pubkey)) return true
if (
filterMutedNotes &&
@@ -1345,7 +1340,6 @@ const NoteList = forwardRef(
[
filterMutedNotes,
hideReplies,
- hideUntrustedNotes,
hideContentMentioningMutedUsers,
mutePubkeySet,
pinnedEventIds,
diff --git a/src/components/NoteStats/LikeButton.tsx b/src/components/NoteStats/LikeButton.tsx
index f9741e30..3f0baf50 100644
--- a/src/components/NoteStats/LikeButton.tsx
+++ b/src/components/NoteStats/LikeButton.tsx
@@ -9,7 +9,6 @@ import { Skeleton } from '@/components/ui/skeleton'
import { ExtendedKind } from '@/constants'
import { useNoteStatsById } from '@/hooks/useNoteStatsById'
import { useReplyUnderDiscussionRoot } from '@/hooks/useReplyUnderDiscussionRoot'
-import { shouldHideInteractions } from '@/lib/event-filtering'
import { createDeletionRequestDraftEvent, createReactionDraftEvent } from '@/lib/draft-event'
import {
DISCUSSION_DOWNVOTE_DISPLAY,
@@ -23,7 +22,6 @@ import {
import { useNoteStatsRelayHints } from '@/hooks/useNoteStatsRelayHints'
import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
-import { useUserTrust } from '@/contexts/user-trust-context'
import { eventService } from '@/services/client.service'
import noteStatsService from '@/services/note-stats.service'
import type { TNoteStats } from '@/services/note-stats.service'
@@ -66,11 +64,9 @@ export function LikeButtonWithStats({
const { isSmallScreen } = useScreenSize()
const { pubkey, publish, checkLogin } = useNostr()
const { relays: statsRelays } = useNoteStatsRelayHints()
- const { hideUntrustedInteractions, isUserTrusted } = useUserTrust()
const [liking, setLiking] = useState(false)
const [isEmojiReactionsOpen, setIsEmojiReactionsOpen] = useState(false)
const isDiscussion = event.kind === ExtendedKind.DISCUSSION
- const inQuietMode = shouldHideInteractions(event)
const isReplyToDiscussion = isReplyToDiscussionProp ?? false
const showDiscussionVotes = isDiscussion || isReplyToDiscussion
@@ -78,9 +74,7 @@ export function LikeButtonWithStats({
const { myLastEmoji, likeCount, upVoteCount, downVoteCount } = useMemo(() => {
const stats = noteStats || {}
- const likes = hideUntrustedInteractions
- ? stats.likes?.filter((like) => isUserTrusted(like.pubkey))
- : stats.likes
+ const likes = stats.likes
const myLike = likes?.find((like) => {
if (like.pubkey !== pubkey) return false
@@ -101,7 +95,7 @@ export function LikeButtonWithStats({
upVoteCount,
downVoteCount
}
- }, [noteStats, pubkey, hideUntrustedInteractions, showDiscussionVotes])
+ }, [noteStats, pubkey, showDiscussionVotes])
/** Same idea as {@link ReplyButton}: merged likes (thread fetch / publish) can exist before snapshot sets `updatedAt`. */
const showLikeCount = !hideCount && (statsLoaded || (likeCount ?? 0) > 0)
@@ -258,7 +252,7 @@ export function LikeButtonWithStats({
{liking ? (
) : myLastEmoji && !useIconOnlyLikeTrigger ? (
-
+
) : (
)}
diff --git a/src/components/NoteStats/NoteStatsCountHover.tsx b/src/components/NoteStats/NoteStatsCountHover.tsx
index 713a6d4f..d6a14814 100644
--- a/src/components/NoteStats/NoteStatsCountHover.tsx
+++ b/src/components/NoteStats/NoteStatsCountHover.tsx
@@ -14,14 +14,12 @@ import {
aggregateZapsByPubkey,
dedupeBoostersByPubkey,
emojiStatsKey,
- filterStatsInteractors,
groupReactionsByEmoji,
MAX_NOTE_STATS_INTERACTORS_SHOWN
} from '@/lib/note-stats-interactors'
import { cn } from '@/lib/utils'
import type { TNoteStats } from '@/services/note-stats.service'
import { useNoteFeedProfileContext } from '@/providers/NoteFeedProfileContext'
-import { useUserTrust } from '@/contexts/user-trust-context'
import { TEmoji } from '@/types'
import { useMemo, useState, type PointerEvent, type ReactNode } from 'react'
import { useTranslation } from 'react-i18next'
@@ -240,11 +238,10 @@ export function BoostCountHover({
children: ReactNode
}) {
const { t } = useTranslation()
- const { hideUntrustedInteractions, isUserTrusted } = useUserTrust()
const pubkeys = useMemo(() => {
- const filtered = filterStatsInteractors(noteStats?.reposts, hideUntrustedInteractions, isUserTrusted)
+ const filtered = noteStats?.reposts ?? []
return dedupeBoostersByPubkey(filtered).map((r) => r.pubkey)
- }, [noteStats?.reposts, hideUntrustedInteractions, isUserTrusted])
+ }, [noteStats?.reposts])
return (
{
- let likes = filterStatsInteractors(noteStats?.likes, hideUntrustedInteractions, isUserTrusted)
+ let likes = noteStats?.likes ?? []
if (emojiFilter) likes = likes.filter((l) => emojiFilter(l.emoji))
return {
groups: groupReactionsByEmoji(likes),
title: titleProp ?? t('Liked by:')
}
- }, [noteStats?.likes, hideUntrustedInteractions, isUserTrusted, emojiFilter, titleProp, t])
+ }, [noteStats?.likes, emojiFilter, titleProp, t])
const total = groups.reduce((n, g) => n + g.pubkeys.length, 0)
@@ -303,10 +299,8 @@ export function DiscussionVoteCountHover({
const { t } = useTranslation()
const emojiFilter = vote === 'up' ? isDiscussionUpvoteEmoji : isDiscussionDownvoteEmoji
- const { hideUntrustedInteractions, isUserTrusted } = useUserTrust()
const pubkeys = useMemo(() => {
- const likes = filterStatsInteractors(noteStats?.likes, hideUntrustedInteractions, isUserTrusted)
- .filter((l) => emojiFilter(l.emoji))
+ const likes = (noteStats?.likes ?? []).filter((l) => emojiFilter(l.emoji))
const byPk = new Map()
for (const l of likes) {
const pk = l.pubkey.toLowerCase()
@@ -316,7 +310,7 @@ export function DiscussionVoteCountHover({
return [...byPk.entries()]
.sort((a, b) => b[1] - a[1])
.map(([pk]) => pk)
- }, [noteStats?.likes, hideUntrustedInteractions, isUserTrusted, emojiFilter])
+ }, [noteStats?.likes, emojiFilter])
const title = (
@@ -345,11 +339,10 @@ export function ZapCountHover({
children: ReactNode
}) {
const { t } = useTranslation()
- const { hideUntrustedInteractions, isUserTrusted } = useUserTrust()
const zappers = useMemo(() => {
- const filtered = filterStatsInteractors(noteStats?.zaps, hideUntrustedInteractions, isUserTrusted)
+ const filtered = noteStats?.zaps ?? []
return aggregateZapsByPubkey(filtered)
- }, [noteStats?.zaps, hideUntrustedInteractions, isUserTrusted])
+ }, [noteStats?.zaps])
return (
{
const hasReplied = pubkey
? noteStats?.replies?.some((reply) => reply.pubkey === pubkey)
: false
return {
- replyCount: hideUntrustedInteractions
- ? noteStats?.replies?.filter((reply) => isUserTrusted(reply.pubkey)).length ?? 0
- : noteStats?.replies?.length ?? 0,
+ replyCount: noteStats?.replies?.length ?? 0,
hasReplied
}
- }, [noteStats, event.id, hideUntrustedInteractions, isUserTrusted, pubkey])
+ }, [noteStats, event.id, pubkey])
const statsLoaded = noteStats?.updatedAt != null
const replyCountLabel = statsLoaded
? replyCount >= 100
diff --git a/src/components/NoteStats/RepostButton.tsx b/src/components/NoteStats/RepostButton.tsx
index dd58163e..c4fda1e2 100644
--- a/src/components/NoteStats/RepostButton.tsx
+++ b/src/components/NoteStats/RepostButton.tsx
@@ -15,7 +15,6 @@ import { cn } from '@/lib/utils'
import { useNoteStatsRelayHints } from '@/hooks/useNoteStatsRelayHints'
import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
-import { useUserTrust } from '@/contexts/user-trust-context'
import noteStatsService from '@/services/note-stats.service'
import type { TNoteStats } from '@/services/note-stats.service'
import { PencilLine, Repeat } from 'lucide-react'
@@ -37,7 +36,6 @@ type RepostButtonProps = {
export function RepostButtonWithStats({ event, hideCount = false, noteStats }: RepostButtonProps) {
const { t } = useTranslation()
const { isSmallScreen } = useScreenSize()
- const { hideUntrustedInteractions, isUserTrusted } = useUserTrust()
const { publish, checkLogin, pubkey } = useNostr()
const { relays: statsRelays } = useNoteStatsRelayHints()
const [reposting, setReposting] = useState(false)
@@ -46,12 +44,10 @@ export function RepostButtonWithStats({ event, hideCount = false, noteStats }: R
const statsLoaded = noteStats?.updatedAt != null
const { repostCount, hasReposted } = useMemo(() => {
return {
- repostCount: hideUntrustedInteractions
- ? noteStats?.reposts?.filter((repost) => isUserTrusted(repost.pubkey)).length
- : noteStats?.reposts?.length,
+ repostCount: noteStats?.reposts?.length,
hasReposted: pubkey ? noteStats?.repostPubkeySet?.has(pubkey) : false
}
- }, [noteStats, event.id, hideUntrustedInteractions, isUserTrusted])
+ }, [noteStats, event.id, pubkey])
const showRepostCount = !hideCount && (statsLoaded || (repostCount ?? 0) > 0)
const canRepost = !hasReposted && !reposting
diff --git a/src/components/NoteStats/index.tsx b/src/components/NoteStats/index.tsx
index 236305fe..b3382197 100644
--- a/src/components/NoteStats/index.tsx
+++ b/src/components/NoteStats/index.tsx
@@ -7,7 +7,6 @@ import { useRssUrlThreadQueryRelays } from '@/hooks/useRssUrlThreadQueryRelays'
import noteStatsService from '@/services/note-stats.service'
import { ExtendedKind } from '@/constants'
import { useReplyUnderDiscussionRoot } from '@/hooks/useReplyUnderDiscussionRoot'
-import { shouldHideInteractions } from '@/lib/event-filtering'
import { normalizeAnyRelayUrl } from '@/lib/url'
import { Event } from 'nostr-tools'
import { useEffect, useRef, useState } from 'react'
@@ -59,9 +58,6 @@ export default function NoteStats({
const isDiscussion = event.kind === ExtendedKind.DISCUSSION
const isReplyToDiscussion = useReplyUnderDiscussionRoot(event)
- // Hide interaction counts if event is in quiet mode
- const hideInteractions = shouldHideInteractions(event)
-
/** Synthetic RSS article root: no boost/quote/zap bar entries that normal notes have. */
const isRssArticleRoot = event.kind === ExtendedKind.RSS_THREAD_ROOT
/** Match {@link RssUrlThreadStatsBar}: inbox/favorites/fast-read merge — plain hints miss many #i indexers. */
@@ -119,19 +115,18 @@ export default function NoteStats({
const interactionButtons = (
<>
-
+
{!isDiscussion && !isReplyToDiscussion && !isRssArticleRoot && (
-
+
)}
{!isRssArticleRoot && (
-
+
)}
>
)
diff --git a/src/components/PostEditor/PostContent.tsx b/src/components/PostEditor/PostContent.tsx
index 4632bbac..d3a6fec2 100644
--- a/src/components/PostEditor/PostContent.tsx
+++ b/src/components/PostEditor/PostContent.tsx
@@ -801,7 +801,7 @@ export default function PostContent({
const createDraftEvent = useCallback(async (cleanedText: string): Promise => {
const uploadImetaTagsOpt = mediaImetaTags.length > 0 ? mediaImetaTags : undefined
- // Get expiration and quiet settings
+ // Get expiration settings
const isChattingKind = (kind: number) =>
kind === kinds.ShortTextNote ||
kind === ExtendedKind.COMMENT ||
@@ -810,9 +810,6 @@ export default function PostContent({
const addExpirationTag = storage.getDefaultExpirationEnabled()
const expirationMonths = storage.getDefaultExpirationMonths()
- const addQuietTag = storage.getDefaultQuietEnabled()
- const quietDays = storage.getDefaultQuietDays()
-
// Determine if we should use protected event tag
let shouldUseProtectedEvent = false
if (parentEvent) {
@@ -828,8 +825,6 @@ export default function PostContent({
isNsfw,
addExpirationTag: false,
expirationMonths,
- addQuietTag,
- quietDays,
mediaImetaTags: uploadImetaTagsOpt
})
} else if (parentEvent && parentEvent.kind === ExtendedKind.PUBLIC_MESSAGE) {
@@ -839,8 +834,6 @@ export default function PostContent({
isNsfw,
addExpirationTag: false,
expirationMonths,
- addQuietTag,
- quietDays,
mediaImetaTags: uploadImetaTagsOpt
})
}
@@ -885,8 +878,6 @@ export default function PostContent({
isNsfw,
addExpirationTag: addExpirationTag && isChattingKind(ExtendedKind.VOICE_COMMENT),
expirationMonths,
- addQuietTag,
- quietDays,
mediaImetaTags: uploadImetaTagsOpt
}
)
@@ -907,8 +898,6 @@ export default function PostContent({
isNsfw,
addExpirationTag: addExpirationTag && isChattingKind(ExtendedKind.VOICE),
expirationMonths,
- addQuietTag,
- quietDays,
mediaImetaTags: uploadImetaTagsOpt
}
)
@@ -922,8 +911,6 @@ export default function PostContent({
isNsfw,
addExpirationTag: false,
expirationMonths,
- addQuietTag,
- quietDays,
mediaImetaTags: uploadImetaTagsOpt
}
)
@@ -938,8 +925,6 @@ export default function PostContent({
isNsfw,
addExpirationTag: false,
expirationMonths,
- addQuietTag,
- quietDays,
mediaImetaTags: uploadImetaTagsOpt
}
)
@@ -988,9 +973,7 @@ export default function PostContent({
addClientTag,
isNsfw,
addExpirationTag: false,
- expirationMonths,
- addQuietTag,
- quietDays
+ expirationMonths
})
} else if (isWikiArticle) {
return await createWikiArticleDraftEvent(cleanedText, mentions, {
@@ -1002,9 +985,7 @@ export default function PostContent({
addClientTag,
isNsfw,
addExpirationTag: false,
- expirationMonths,
- addQuietTag,
- quietDays
+ expirationMonths
})
} else if (isNostrSpecification) {
const affectedKinds = parseNostrSpecAffectedKinds(nostrSpecAffectedKindRows)
@@ -1017,9 +998,7 @@ export default function PostContent({
addClientTag,
isNsfw,
addExpirationTag: false,
- expirationMonths,
- addQuietTag,
- quietDays
+ expirationMonths
})
} else if (isPublicationContent) {
return await createPublicationContentDraftEvent(cleanedText, mentions, {
@@ -1031,9 +1010,7 @@ export default function PostContent({
addClientTag,
isNsfw,
addExpirationTag: false,
- expirationMonths,
- addQuietTag,
- quietDays
+ expirationMonths
})
}
@@ -1119,8 +1096,6 @@ export default function PostContent({
isNsfw,
addExpirationTag: false,
expirationMonths,
- addQuietTag,
- quietDays,
mediaImetaTags: uploadImetaTagsOpt
}
)
@@ -1135,8 +1110,6 @@ export default function PostContent({
isNsfw,
addExpirationTag: addExpirationTag && isChattingKind(ExtendedKind.COMMENT),
expirationMonths,
- addQuietTag,
- quietDays,
mediaImetaTags: uploadImetaTagsOpt
})
}
@@ -1148,8 +1121,6 @@ export default function PostContent({
isNsfw,
addExpirationTag: false,
expirationMonths,
- addQuietTag,
- quietDays,
mediaImetaTags: uploadImetaTagsOpt
})
}
@@ -1162,8 +1133,6 @@ export default function PostContent({
isNsfw,
addExpirationTag: addExpirationTag && isChattingKind(kinds.ShortTextNote),
expirationMonths,
- addQuietTag,
- quietDays,
mediaImetaTags: uploadImetaTagsOpt
})
}, [
diff --git a/src/components/Profile/ProfileFeed.tsx b/src/components/Profile/ProfileFeed.tsx
index b3ca9941..b45ca55d 100644
--- a/src/components/Profile/ProfileFeed.tsx
+++ b/src/components/Profile/ProfileFeed.tsx
@@ -136,7 +136,6 @@ const ProfileFeed = forwardRef<
mergeTimelineWhenSubRequestFiltersMatch
pinnedEventIds={pinnedEventIds}
hideReplies={false}
- hideUntrustedNotes={false}
filterMutedNotes={false}
showKind1OPs={showKind1OPs}
showKind1Replies={showKind1Replies}
diff --git a/src/components/RelayInfo/RelayReviewsPreview.tsx b/src/components/RelayInfo/RelayReviewsPreview.tsx
index 74b6120d..48b5180e 100644
--- a/src/components/RelayInfo/RelayReviewsPreview.tsx
+++ b/src/components/RelayInfo/RelayReviewsPreview.tsx
@@ -26,7 +26,6 @@ import { cn, isTouchDevice } from '@/lib/utils'
import { useMuteList } from '@/contexts/mute-list-context'
import { muteSetHas } from '@/lib/mute-set'
import { useNostr } from '@/providers/NostrProvider'
-import { useUserTrust } from '@/contexts/user-trust-context'
import { queryService } from '@/services/client.service'
import { getSessionFeedSnapshot } from '@/services/session-feed-snapshot.service'
import { WheelGesturesPlugin } from 'embla-carousel-wheel-gestures'
@@ -42,7 +41,6 @@ export default function RelayReviewsPreview({ relayUrl }: { relayUrl: string })
const { push } = useSecondaryPage()
const { pubkey, checkLogin, relayList } = useNostr()
const { favoriteRelays, blockedRelays } = useFavoriteRelays()
- const { hideUntrustedNotes, isUserTrusted } = useUserTrust()
const { mutePubkeySet } = useMuteList()
const [showEditor, setShowEditor] = useState(false)
const [myReview, setMyReview] = useState(null)
@@ -68,7 +66,6 @@ export default function RelayReviewsPreview({ relayUrl }: { relayUrl: string })
const ingestReviewEvent = useCallback(
(evt: NostrEvent) => {
if (muteSetHas(mutePubkeySet, evt.pubkey)) return
- if (hideUntrustedNotes && !isUserTrusted(evt.pubkey)) return
const stars = getStarsFromRelayReviewEvent(evt)
if (!stars) return
@@ -84,7 +81,7 @@ export default function RelayReviewsPreview({ relayUrl }: { relayUrl: string })
return [...filtered, evt].sort((a, b) => compareEvents(b, a))
})
},
- [pubkey, mutePubkeySet, hideUntrustedNotes, isUserTrusted]
+ [pubkey, mutePubkeySet]
)
useEffect(() => {
@@ -104,7 +101,6 @@ export default function RelayReviewsPreview({ relayUrl }: { relayUrl: string })
if (evt.kind !== ExtendedKind.RELAY_REVIEW || !relayReviewEventTargetsRelay(evt, relayUrl))
continue
if (muteSetHas(mutePubkeySet, evt.pubkey)) continue
- if (hideUntrustedNotes && !isUserTrusted(evt.pubkey)) continue
const st = getStarsFromRelayReviewEvent(evt)
if (!st) continue
if (pubkey && evt.pubkey === pubkey) {
diff --git a/src/components/ReplyNoteList/index.tsx b/src/components/ReplyNoteList/index.tsx
index 3f6e2731..abfac536 100644
--- a/src/components/ReplyNoteList/index.tsx
+++ b/src/components/ReplyNoteList/index.tsx
@@ -30,7 +30,6 @@ import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { useReplyIngress } from '@/hooks/useReplyIngress'
-import { useUserTrust } from '@/contexts/user-trust-context'
import { useCurrentRelays } from '@/providers/CurrentRelaysProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import {
@@ -109,7 +108,6 @@ function ReplyNoteList({
}) {
const { t } = useTranslation()
const { navigateToNote } = useSmartNoteNavigation()
- const { hideUntrustedInteractions, isUserTrusted, isTrustLoaded } = useUserTrust()
const noteStats = useNoteStatsById(event.id)
const { mutePubkeySet } = useMuteList()
const { hideContentMentioningMutedUsers } = useContentPolicy()
@@ -1138,26 +1136,12 @@ function ReplyNoteList({
if (isSuperchatKind(item.kind)) return true
// Backlink rows (quotes, highlights, …): show even when author is not in the trust list.
if (isQuote) return true
- if (isTrustLoaded && hideUntrustedInteractions && !isUserTrusted(item.pubkey)) {
- if (rootInfo?.type !== 'I') {
- const repliesForThisReply = repliesMap.get(item.id)
- if (
- !repliesForThisReply ||
- repliesForThisReply.events.every((evt) => !isUserTrusted(evt.pubkey))
- ) {
- return false
- }
- }
- }
return true
},
[
mutePubkeySet,
hideContentMentioningMutedUsers,
quoteUiIdSet,
- isTrustLoaded,
- hideUntrustedInteractions,
- isUserTrusted,
rootInfo?.type,
repliesMap,
event,
diff --git a/src/components/RssUrlThreadStatsBar/index.tsx b/src/components/RssUrlThreadStatsBar/index.tsx
index 5fa14782..9008dddd 100644
--- a/src/components/RssUrlThreadStatsBar/index.tsx
+++ b/src/components/RssUrlThreadStatsBar/index.tsx
@@ -1,5 +1,4 @@
import { useNoteStatsById } from '@/hooks/useNoteStatsById'
-import { useUserTrust } from '@/contexts/user-trust-context'
import { cn } from '@/lib/utils'
import noteStatsService from '@/services/note-stats.service'
import { useRssUrlThreadQueryRelays } from '@/hooks/useRssUrlThreadQueryRelays'
@@ -21,7 +20,6 @@ export default function RssUrlThreadStatsBar({
const { relayUrls: statsRelays, relayMergeTier, currentRelaysKey } = useRssUrlThreadQueryRelays()
const statsRelaysRef = useRef(statsRelays)
statsRelaysRef.current = statsRelays
- const { hideUntrustedInteractions, isUserTrusted } = useUserTrust()
const noteStats = useNoteStatsById(event.id)
const [loading, setLoading] = useState(false)
@@ -38,23 +36,14 @@ export default function RssUrlThreadStatsBar({
const replies = noteStats?.replies ?? []
const likes = noteStats?.likes ?? []
const highlights = noteStats?.highlights ?? []
- const trustedReplyCount = hideUntrustedInteractions
- ? replies.filter((r) => isUserTrusted(r.pubkey)).length
- : replies.length
- const trustedReactionCount = hideUntrustedInteractions
- ? likes.filter((l) => isUserTrusted(l.pubkey)).length
- : likes.length
- const trustedHighlightCount = hideUntrustedInteractions
- ? highlights.filter((h) => isUserTrusted(h.pubkey)).length
- : highlights.length
const bookmarkCountInner = noteStats?.bookmarkPubkeySet?.size ?? 0
return {
- replyCount: trustedReplyCount,
- reactionCount: trustedReactionCount,
- highlightCount: trustedHighlightCount,
+ replyCount: replies.length,
+ reactionCount: likes.length,
+ highlightCount: highlights.length,
bookmarkCount: bookmarkCountInner
}
- }, [noteStats, hideUntrustedInteractions, isUserTrusted])
+ }, [noteStats])
return (
+
-
+
- {/* Full-bleed banner at xl: span entire sidebar column (undo pl-4 + pr-6) */}
-
+ {/* Full-bleed banner at xl: cancel horizontal inset without widening scroll overflow */}
+
@@ -50,7 +54,7 @@ export default function PrimaryPageSidebar() {
-
+
diff --git a/src/constants.ts b/src/constants.ts
index 26d4c098..8b79c8b5 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -341,10 +341,7 @@ export const StorageKey = {
/** Per-pubkey ms timestamps: last full network hydrate (see ACCOUNT_SESSION_NETWORK_HYDRATE_MIN_INTERVAL_MS). */
ACCOUNT_NETWORK_HYDRATE_AT_MAP: 'accountNetworkHydrateAtMap',
AUTOPLAY: 'autoplay',
- HIDE_UNTRUSTED_INTERACTIONS: 'hideUntrustedInteractions',
- HIDE_UNTRUSTED_NOTIFICATIONS: 'hideUntrustedNotifications',
MEDIA_UPLOAD_SERVICE_CONFIG_MAP: 'mediaUploadServiceConfigMap',
- HIDE_UNTRUSTED_NOTES: 'hideUntrustedNotes',
DEFAULT_SHOW_NSFW: 'defaultShowNsfw',
DISMISSED_TOO_MANY_RELAYS_ALERT: 'dismissedTooManyRelaysAlert',
SHOW_KINDS: 'showKinds',
@@ -363,10 +360,6 @@ export const StorageKey = {
SHOW_RECOMMENDED_RELAYS_PANEL: 'showRecommendedRelaysPanel',
DEFAULT_EXPIRATION_ENABLED: 'defaultExpirationEnabled',
DEFAULT_EXPIRATION_MONTHS: 'defaultExpirationMonths',
- DEFAULT_QUIET_ENABLED: 'defaultQuietEnabled',
- DEFAULT_QUIET_DAYS: 'defaultQuietDays',
- RESPECT_QUIET_TAGS: 'respectQuietTags',
- GLOBAL_QUIET_MODE: 'globalQuietMode',
SHOW_RSS_FEED: 'showRssFeed',
PANE_MODE: 'paneMode',
ADD_RANDOM_RELAYS_TO_PUBLISH: 'addRandomRelaysToPublish',
diff --git a/src/contexts/user-trust-context.tsx b/src/contexts/user-trust-context.tsx
deleted file mode 100644
index 8c8d6294..00000000
--- a/src/contexts/user-trust-context.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import { createContext, useContext } from 'react'
-
-export type TUserTrustContext = {
- isTrustLoaded: boolean
- hideUntrustedInteractions: boolean
- hideUntrustedNotifications: boolean
- hideUntrustedNotes: boolean
- updateHideUntrustedInteractions: (hide: boolean) => void
- updateHideUntrustedNotifications: (hide: boolean) => void
- updateHideUntrustedNotes: (hide: boolean) => void
- isUserTrusted: (pubkey: string) => boolean
-}
-
-/**
- * Lives in a dedicated module so lazy chunks (e.g. NoteListPage → NormalFeed) share the same
- * context instance as App’s UserTrustProvider. Importing useUserTrust from UserTrustProvider into
- * those chunks can duplicate the module and break Provider matching.
- */
-export const UserTrustContext = createContext
(undefined)
-
-export function useUserTrust(): TUserTrustContext {
- const context = useContext(UserTrustContext)
- if (!context) {
- throw new Error('useUserTrust must be used within a UserTrustProvider')
- }
- return context
-}
diff --git a/src/hooks/useConsoleLogBuffer.ts b/src/hooks/useConsoleLogBuffer.ts
new file mode 100644
index 00000000..b5959f9f
--- /dev/null
+++ b/src/hooks/useConsoleLogBuffer.ts
@@ -0,0 +1,19 @@
+import {
+ getConsoleLogBuffer,
+ subscribeConsoleLogBuffer,
+ type ConsoleLogEntry
+} from '@/lib/console-log-buffer'
+import { useSyncExternalStore } from 'react'
+
+function subscribe(onStoreChange: () => void) {
+ return subscribeConsoleLogBuffer(onStoreChange)
+}
+
+function getSnapshot(): ConsoleLogEntry[] {
+ return getConsoleLogBuffer()
+}
+
+/** Live view of the global console log ring buffer (see Settings → Cache). */
+export function useConsoleLogBuffer(): ConsoleLogEntry[] {
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot)
+}
diff --git a/src/index.css b/src/index.css
index 292b33a1..66c3406d 100644
--- a/src/index.css
+++ b/src/index.css
@@ -297,6 +297,27 @@
border-right: 1px solid hsl(var(--sidebar-border));
}
+ /* Reserve a right gutter so the track sits beside labels, not over icons/text. */
+ .imwald-sidebar__scroll {
+ direction: ltr;
+ scrollbar-gutter: stable;
+ scrollbar-width: thin;
+ }
+ .imwald-sidebar__scroll::-webkit-scrollbar {
+ width: 8px;
+ }
+ .imwald-sidebar__scroll::-webkit-scrollbar-thumb {
+ border-radius: 9999px;
+ background-color: hsl(var(--muted-foreground) / 0.35);
+ }
+ .imwald-sidebar__scroll::-webkit-scrollbar-thumb:hover {
+ background-color: hsl(var(--muted-foreground) / 0.5);
+ }
+ .imwald-sidebar__scroll::-webkit-scrollbar-track {
+ border-radius: 9999px;
+ background-color: hsl(var(--muted) / 0.35);
+ }
+
.imwald-sidebar__atmosphere {
position: absolute;
inset: 0;
diff --git a/src/lib/console-log-buffer.ts b/src/lib/console-log-buffer.ts
new file mode 100644
index 00000000..536f6dc7
--- /dev/null
+++ b/src/lib/console-log-buffer.ts
@@ -0,0 +1,131 @@
+export type ConsoleLogEntry = {
+ type: string
+ message: string
+ formattedParts?: Array<{ text: string; style?: string }>
+ timestamp: number
+}
+
+const MAX_ENTRIES = 1000
+
+const buffer: ConsoleLogEntry[] = []
+const listeners = new Set<() => void>()
+let initialized = false
+
+function notifyListeners() {
+ for (const listener of listeners) {
+ listener()
+ }
+}
+
+function formatArgs(args: unknown[]): { message: string; formattedParts: Array<{ text: string; style?: string }> } {
+ if (args.length > 0 && typeof args[0] === 'string' && args[0].includes('%c')) {
+ const formatString = args[0]
+ const parts = formatString.split(/%c/g)
+ const formattedParts: Array<{ text: string; style?: string }> = []
+
+ for (let i = 0; i < parts.length; i++) {
+ const text = parts[i]
+ const style = i < args.length - 1 && typeof args[i + 1] === 'string' ? String(args[i + 1]) : undefined
+ formattedParts.push({ text, style })
+ }
+
+ const remainingArgs = args.slice(parts.length)
+ if (remainingArgs.length > 0) {
+ const remainingText = remainingArgs
+ .map((arg) => {
+ if (typeof arg === 'object') {
+ try {
+ return JSON.stringify(arg, null, 2)
+ } catch {
+ return String(arg)
+ }
+ }
+ return String(arg)
+ })
+ .join(' ')
+ if (formattedParts.length > 0) {
+ formattedParts[formattedParts.length - 1].text += ' ' + remainingText
+ } else {
+ formattedParts.push({ text: remainingText })
+ }
+ }
+
+ return { message: formattedParts.map((p) => p.text).join(''), formattedParts }
+ }
+
+ const message = args
+ .map((arg) => {
+ if (typeof arg === 'object') {
+ try {
+ return JSON.stringify(arg, null, 2)
+ } catch {
+ return String(arg)
+ }
+ }
+ return String(arg)
+ })
+ .join(' ')
+
+ return { message, formattedParts: [{ text: message }] }
+}
+
+function captureLog(type: string, ...args: unknown[]) {
+ const { message, formattedParts } = formatArgs(args)
+ buffer.push({ type, message, formattedParts, timestamp: Date.now() })
+ if (buffer.length > MAX_ENTRIES) {
+ buffer.splice(0, buffer.length - MAX_ENTRIES)
+ }
+ notifyListeners()
+}
+
+/** Ring buffer of recent console output (installed at app startup). */
+export function getConsoleLogBuffer(): ConsoleLogEntry[] {
+ return [...buffer]
+}
+
+export function clearConsoleLogBuffer() {
+ buffer.length = 0
+ notifyListeners()
+}
+
+export function subscribeConsoleLogBuffer(listener: () => void): () => void {
+ listeners.add(listener)
+ return () => listeners.delete(listener)
+}
+
+/** Wrap console.* after other patches (e.g. error-suppression) so all output is retained. */
+export function initConsoleLogCapture() {
+ if (initialized || typeof window === 'undefined') return
+ initialized = true
+
+ const originalLog = console.log.bind(console)
+ const originalError = console.error.bind(console)
+ const originalWarn = console.warn.bind(console)
+ const originalInfo = console.info.bind(console)
+ const originalDebug = console.debug.bind(console)
+
+ console.log = (...args: unknown[]) => {
+ captureLog('log', ...args)
+ originalLog(...args)
+ }
+ console.error = (...args: unknown[]) => {
+ captureLog('error', ...args)
+ originalError(...args)
+ }
+ console.warn = (...args: unknown[]) => {
+ captureLog('warn', ...args)
+ originalWarn(...args)
+ }
+ console.info = (...args: unknown[]) => {
+ captureLog('info', ...args)
+ originalInfo(...args)
+ }
+ console.debug = (...args: unknown[]) => {
+ captureLog('debug', ...args)
+ originalDebug(...args)
+ }
+}
+
+if (typeof window !== 'undefined') {
+ initConsoleLogCapture()
+}
diff --git a/src/lib/draft-event.ts b/src/lib/draft-event.ts
index 3e66dd68..8af4d801 100644
--- a/src/lib/draft-event.ts
+++ b/src/lib/draft-event.ts
@@ -229,8 +229,6 @@ export async function createShortTextNoteDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
/** NIP-94 imeta rows from uploads (audio/video/images as plain URLs in content). */
mediaImetaTags?: string[][]
} = {}
@@ -280,9 +278,6 @@ export async function createShortTextNoteDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
const baseDraft = {
kind: kinds.ShortTextNote,
@@ -317,8 +312,6 @@ export async function createCommentDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
mediaImetaTags?: string[][]
} = {}
): Promise {
@@ -403,9 +396,6 @@ export async function createCommentDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
const baseDraft = {
kind: ExtendedKind.COMMENT,
@@ -425,8 +415,6 @@ export async function createPublicMessageReplyDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
mediaImetaTags?: string[][] // Allow media imeta tags for audio/video
} = {}
): Promise {
@@ -478,9 +466,6 @@ export async function createPublicMessageReplyDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
// console.log('📝 Final public message reply draft tags:', {
// pTags: tags.filter(tag => tag[0] === 'p'),
@@ -505,8 +490,6 @@ export async function createPublicMessageDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
mediaImetaTags?: string[][] // Allow media imeta tags for audio/video
} = {}
): Promise {
@@ -538,9 +521,6 @@ export async function createPublicMessageDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
const baseDraft = {
kind: ExtendedKind.PUBLIC_MESSAGE,
@@ -1146,16 +1126,12 @@ export async function createPollDraftEvent(
isNsfw,
addExpirationTag,
expirationMonths,
- addQuietTag,
- quietDays,
mediaImetaTags
}: {
addClientTag?: boolean // accepted for API compat; client tag is added in publish()
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
mediaImetaTags?: string[][]
} = {}
): Promise {
@@ -1210,9 +1186,6 @@ export async function createPollDraftEvent(
tags.push(buildExpirationTag(expirationMonths))
}
- if (addQuietTag && quietDays) {
- tags.push(buildQuietTag(quietDays))
- }
const baseDraft = {
content: transformedEmojisContent.trim(),
@@ -1658,10 +1631,6 @@ function buildExpirationTag(months: number): string[] {
return ['expiration', expirationTime.toString()]
}
-function buildQuietTag(days: number): string[] {
- const quietEndTime = dayjs().add(days, 'day').unix()
- return ['quiet', quietEndTime.toString()]
-}
function trimTagEnd(tag: string[]) {
let endIndex = tag.length - 1
@@ -1691,8 +1660,6 @@ export async function createHighlightDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
mediaImetaTags?: string[][]
}
): Promise {
@@ -1818,9 +1785,6 @@ export async function createHighlightDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options?.addQuietTag && options?.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
mergeUploadImetaTagsInto(tags, options?.mediaImetaTags)
@@ -1843,8 +1807,6 @@ export async function createVoiceDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
/** Extra NIP-94 rows from uploads (merged after content-derived imeta, deduped by URL). */
mediaImetaTags?: string[][]
} = {}
@@ -1871,9 +1833,6 @@ export async function createVoiceDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
return setDraftEventCache({
kind: ExtendedKind.VOICE,
@@ -1894,8 +1853,6 @@ export async function createVoiceCommentDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
/** NIP-94 rows from file upload (merged before `imetaTags`; deduped by URL). */
mediaImetaTags?: string[][]
} = {}
@@ -1979,9 +1936,6 @@ export async function createVoiceCommentDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
return setDraftEventCache({
kind: ExtendedKind.VOICE_COMMENT,
@@ -2000,8 +1954,6 @@ export async function createPictureDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
mediaImetaTags?: string[][]
} = {}
): Promise {
@@ -2026,9 +1978,6 @@ export async function createPictureDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
// Kind 20 caption is user text only; the file URL lives in `imeta`. Many indexers and caches
// still deliver full tags, but mirroring the URL in `content` matches kind-1-style clients and
@@ -2060,8 +2009,6 @@ export async function createVideoDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
mediaImetaTags?: string[][]
} = {}
): Promise {
@@ -2086,9 +2033,6 @@ export async function createVideoDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
return setDraftEventCache({
kind: videoKind, // NIP-71: 21, 22, or 34235
@@ -2113,8 +2057,6 @@ export async function createLongFormArticleDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
} = {}
): Promise {
const { content: transformedEmojisContent, emojiTags } = transformCustomEmojisInContent(content)
@@ -2161,9 +2103,6 @@ export async function createLongFormArticleDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
return setDraftEventCache({
kind: kinds.LongFormArticle,
@@ -2194,8 +2133,6 @@ export async function createWikiArticleDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
}
): Promise {
const { content: transformedEmojisContent, emojiTags } = transformCustomEmojisInContent(content)
@@ -2231,9 +2168,6 @@ export async function createWikiArticleDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
return setDraftEventCache({
kind: ExtendedKind.WIKI_ARTICLE,
@@ -2256,8 +2190,6 @@ export async function createNostrSpecificationDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
}
): Promise {
const { content: transformedEmojisContent, emojiTags } = transformCustomEmojisInContent(content)
@@ -2295,9 +2227,6 @@ export async function createNostrSpecificationDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
return setDraftEventCache({
kind: ExtendedKind.NOSTR_SPECIFICATION,
@@ -2319,8 +2248,6 @@ export async function createPublicationContentDraftEvent(
isNsfw?: boolean
addExpirationTag?: boolean
expirationMonths?: number
- addQuietTag?: boolean
- quietDays?: number
}
): Promise {
const { content: transformedEmojisContent, emojiTags } = transformCustomEmojisInContent(content)
@@ -2356,9 +2283,6 @@ export async function createPublicationContentDraftEvent(
tags.push(buildExpirationTag(options.expirationMonths))
}
- if (options.addQuietTag && options.quietDays) {
- tags.push(buildQuietTag(options.quietDays))
- }
return setDraftEventCache({
kind: ExtendedKind.PUBLICATION_CONTENT,
diff --git a/src/lib/event-filtering.ts b/src/lib/event-filtering.ts
index 954d6616..72041113 100644
--- a/src/lib/event-filtering.ts
+++ b/src/lib/event-filtering.ts
@@ -1,6 +1,5 @@
import { Event } from 'nostr-tools'
import dayjs from 'dayjs'
-import storage from '@/services/local-storage.service'
/**
* Check if an event has expired based on its expiration tag
@@ -19,41 +18,6 @@ function isEventExpired(event: Event): boolean {
return dayjs().unix() > expirationTime
}
-/**
- * Check if an event is in quiet mode based on its quiet tag
- */
-function isEventInQuietMode(event: Event): boolean {
- const quietTag = event.tags.find(tag => tag[0] === 'quiet')
- if (!quietTag || !quietTag[1]) {
- return false
- }
-
- const quietEndTime = parseInt(quietTag[1])
- if (isNaN(quietEndTime)) {
- return false
- }
-
- return dayjs().unix() < quietEndTime
-}
-
-/**
- * Check if interactions should be hidden for an event based on quiet settings
- */
-export function shouldHideInteractions(event: Event): boolean {
- // Check global quiet mode first
- if (storage.getGlobalQuietMode()) {
- return true
- }
-
- // Check if we should respect quiet tags
- if (!storage.getRespectQuietTags()) {
- return false
- }
-
- // Check if the event is in quiet mode
- return isEventInQuietMode(event)
-}
-
/**
* Check if an event should be filtered out completely (expired)
*/
diff --git a/src/lib/note-stats-interactors.ts b/src/lib/note-stats-interactors.ts
index cd58ef9a..1a12fdd8 100644
--- a/src/lib/note-stats-interactors.ts
+++ b/src/lib/note-stats-interactors.ts
@@ -3,16 +3,6 @@ import { TEmoji } from '@/types'
export const MAX_NOTE_STATS_INTERACTORS_SHOWN = 32
-export function filterStatsInteractors(
- items: T[] | undefined,
- hideUntrusted: boolean,
- isUserTrusted: (pk: string) => boolean
-): T[] {
- if (!items?.length) return []
- if (!hideUntrusted) return items
- return items.filter((item) => isUserTrusted(item.pubkey))
-}
-
export function emojiStatsKey(emoji: TEmoji | string): string {
return typeof emoji === 'string' ? emoji : emoji.shortcode
}
diff --git a/src/main.tsx b/src/main.tsx
index 5edcfe96..4a63ca8b 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,6 +1,7 @@
import './index.css'
import './polyfill'
import './lib/error-suppression'
+import './lib/console-log-buffer'
import storage from './services/local-storage.service'
import './services/lightning.service'
import './lib/debug-utils'
diff --git a/src/pages/primary/SpellsPage/index.tsx b/src/pages/primary/SpellsPage/index.tsx
index 02ce0da0..8ff686db 100644
--- a/src/pages/primary/SpellsPage/index.tsx
+++ b/src/pages/primary/SpellsPage/index.tsx
@@ -1,4 +1,3 @@
-import HideUntrustedContentButton from '@/components/HideUntrustedContentButton'
import NoteList, { type TNoteListRef } from '@/components/NoteList'
import StoredAccountSwitchSelect from '@/components/StoredAccountSwitchSelect'
import { RefreshButton } from '@/components/RefreshButton'
@@ -29,7 +28,6 @@ import { useBookmarks } from '@/providers/bookmarks-context'
import { useNostr } from '@/providers/NostrProvider'
import { useNotificationThreadWatchOptional } from '@/providers/NotificationThreadWatchProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
-import { useUserTrust } from '@/contexts/user-trust-context'
import { dedupeFollowSetEventsByD } from '@/lib/follow-set-spell'
import client, { queryService } from '@/services/client.service'
import indexedDb from '@/services/indexed-db.service'
@@ -88,7 +86,6 @@ const SpellsPage = forwardRef(function SpellsPage(
followListEvent
} = useNostr()
const { addBookmark, removeBookmark } = useBookmarks()
- const { hideUntrustedNotifications } = useUserTrust()
const notificationThreadWatch = useNotificationThreadWatchOptional()
const eventsIFollowListEvent = notificationThreadWatch?.eventsIFollowListEvent ?? null
const eventsIMutedListEvent = notificationThreadWatch?.eventsIMutedListEvent ?? null
@@ -1054,7 +1051,6 @@ const SpellsPage = forwardRef(function SpellsPage(
{notificationsFeedPubkey ? (
) : null}
-
) : null}
@@ -1105,9 +1101,6 @@ const SpellsPage = forwardRef(function SpellsPage(
? notificationsMentionExtraHide
: undefined
}
- hideUntrustedNotes={
- selectedFauxSpell === 'notifications' ? hideUntrustedNotifications : false
- }
showPaymentAttestationAction={selectedFauxSpell === 'notifications'}
/>
diff --git a/src/pages/secondary/GeneralSettingsPage/index.tsx b/src/pages/secondary/GeneralSettingsPage/index.tsx
index 402512c9..8aba8e9d 100644
--- a/src/pages/secondary/GeneralSettingsPage/index.tsx
+++ b/src/pages/secondary/GeneralSettingsPage/index.tsx
@@ -17,10 +17,8 @@ import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useFontSize } from '@/providers/FontSizeProvider'
import { useTheme } from '@/providers/ThemeProvider'
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
-import { useUserTrust } from '@/contexts/user-trust-context'
import { TMediaAutoLoadPolicy } from '@/types'
import { SelectValue } from '@radix-ui/react-select'
-import { ExternalLink } from 'lucide-react'
import { forwardRef, HTMLProps, useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
@@ -42,7 +40,6 @@ const GeneralSettingsPage = forwardRef(({ index, hideTitlebar = false }: { index
mediaAutoLoadPolicy,
setMediaAutoLoadPolicy
} = useContentPolicy()
- const { hideUntrustedNotes, updateHideUntrustedNotes } = useUserTrust()
const {
notificationListStyle,
updateNotificationListStyle,
@@ -202,16 +199,6 @@ const GeneralSettingsPage = forwardRef(({ index, hideTitlebar = false }: { index
onCheckedChange={updateAddRandomRelaysToPublish}
/>
-
-
-
-
{/* DEPRECATED: Double-panel setting removed for technical debt reduction */}
-
-
-
)
diff --git a/src/pages/secondary/PostSettingsPage/QuietSettings.tsx b/src/pages/secondary/PostSettingsPage/QuietSettings.tsx
deleted file mode 100644
index f67cbb59..00000000
--- a/src/pages/secondary/PostSettingsPage/QuietSettings.tsx
+++ /dev/null
@@ -1,108 +0,0 @@
-import { Label } from '@/components/ui/label'
-import { Switch } from '@/components/ui/switch'
-import { Input } from '@/components/ui/input'
-import storage from '@/services/local-storage.service'
-import { useEffect, useState } from 'react'
-import { useTranslation } from 'react-i18next'
-
-export default function QuietSettings() {
- const { t } = useTranslation()
- const [enabled, setEnabled] = useState(false)
- const [days, setDays] = useState(7)
- const [respectQuietTags, setRespectQuietTags] = useState(true)
- const [globalQuietMode, setGlobalQuietMode] = useState(false)
-
- useEffect(() => {
- setEnabled(storage.getDefaultQuietEnabled())
- setDays(storage.getDefaultQuietDays())
- setRespectQuietTags(storage.getRespectQuietTags())
- setGlobalQuietMode(storage.getGlobalQuietMode())
- }, [])
-
- const handleEnabledChange = (checked: boolean) => {
- setEnabled(checked)
- storage.setDefaultQuietEnabled(checked)
- }
-
- const handleDaysChange = (value: string) => {
- const num = parseInt(value)
- if (!isNaN(num) && num >= 0 && Number.isInteger(num)) {
- setDays(num)
- storage.setDefaultQuietDays(num)
- }
- }
-
- const handleRespectQuietTagsChange = (checked: boolean) => {
- setRespectQuietTags(checked)
- storage.setRespectQuietTags(checked)
- }
-
- const handleGlobalQuietModeChange = (checked: boolean) => {
- setGlobalQuietMode(checked)
- storage.setGlobalQuietMode(checked)
- }
-
- return (
-
-
-
-
-
-
-
- {t('Posts will automatically include quiet tags')}
-
-
-
- {enabled && (
-
-
-
handleDaysChange(e.target.value)}
- className="w-24"
- />
-
- {t('Posts will be quiet for this many days')}
-
-
- )}
-
-
-
-
-
-
-
- {t('Hide interactions on posts with quiet tags')}
-
-
-
-
-
-
-
-
-
- {t('Hide interactions on all posts')}
-
-
-
- )
-}
diff --git a/src/pages/secondary/PostSettingsPage/index.tsx b/src/pages/secondary/PostSettingsPage/index.tsx
index 8b058a34..e411ac9f 100644
--- a/src/pages/secondary/PostSettingsPage/index.tsx
+++ b/src/pages/secondary/PostSettingsPage/index.tsx
@@ -5,7 +5,6 @@ import { forwardRef, useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import MediaUploadServiceSetting from './MediaUploadServiceSetting'
import ExpirationSettings from './ExpirationSettings'
-import QuietSettings from './QuietSettings'
import PublishSuccessToastSetting from './PublishSuccessToastSetting'
const PostSettingsPage = forwardRef(({ index, hideTitlebar = false }: { index?: number; hideTitlebar?: boolean }, ref) => {
@@ -40,10 +39,6 @@ const PostSettingsPage = forwardRef(({ index, hideTitlebar = false }: { index?:
{t('Expiration Tags')}
-
-
{t('Quiet Tags')}
-
-
)
diff --git a/src/providers/UserTrustProvider.tsx b/src/providers/UserTrustProvider.tsx
deleted file mode 100644
index 7a4fda8b..00000000
--- a/src/providers/UserTrustProvider.tsx
+++ /dev/null
@@ -1,100 +0,0 @@
-import { getPubkeysFromPTags } from '@/lib/tag'
-import storage from '@/services/local-storage.service'
-import { replaceableEventService } from '@/services/client.service'
-import { UserTrustContext } from '@/contexts/user-trust-context'
-import { kinds } from 'nostr-tools'
-import { type ReactNode, useCallback, useEffect, useState } from 'react'
-import { useNostr } from './NostrProvider'
-
-const wotSet = new Set
()
-
-export function UserTrustProvider({ children }: { children: ReactNode }) {
- const { pubkey: currentPubkey } = useNostr()
- const [isTrustLoaded, setIsTrustLoaded] = useState(false)
- const [hideUntrustedInteractions, setHideUntrustedInteractions] = useState(() =>
- storage.getHideUntrustedInteractions()
- )
- const [hideUntrustedNotifications, setHideUntrustedNotifications] = useState(() =>
- storage.getHideUntrustedNotifications()
- )
- const [hideUntrustedNotes, setHideUntrustedNotes] = useState(() =>
- storage.getHideUntrustedNotes()
- )
-
- useEffect(() => {
- if (!currentPubkey) {
- setIsTrustLoaded(false)
- return
- }
-
- // Clear wotSet when account changes to avoid cross-account contamination
- wotSet.clear()
- setIsTrustLoaded(false)
-
- const initWoT = async () => {
- try {
- const followListEvent = await replaceableEventService.fetchReplaceableEvent(currentPubkey, kinds.Contacts)
- const followings = followListEvent ? getPubkeysFromPTags(followListEvent.tags) : []
- followings.forEach((pubkey) => wotSet.add(pubkey.toLowerCase()))
-
- const batchSize = 20
- for (let i = 0; i < followings.length; i += batchSize) {
- const batch = followings.slice(i, i + batchSize)
- await Promise.allSettled(
- batch.map(async (pubkey) => {
- const innerFollow = await replaceableEventService.fetchReplaceableEvent(pubkey, kinds.Contacts)
- const _followings = innerFollow ? getPubkeysFromPTags(innerFollow.tags) : []
- _followings.forEach((following) => {
- wotSet.add(following.toLowerCase())
- })
- })
- )
- await new Promise((resolve) => setTimeout(resolve, 200))
- }
- } finally {
- setIsTrustLoaded(true)
- }
- }
- void initWoT()
- }, [currentPubkey])
-
- const isUserTrusted = useCallback(
- (pubkey: string) => {
- if (!currentPubkey || pubkey.toLowerCase() === currentPubkey.toLowerCase()) return true
- return wotSet.has(pubkey.toLowerCase())
- },
- [currentPubkey]
- )
-
- const updateHideUntrustedInteractions = (hide: boolean) => {
- setHideUntrustedInteractions(hide)
- storage.setHideUntrustedInteractions(hide)
- }
-
- const updateHideUntrustedNotifications = (hide: boolean) => {
- setHideUntrustedNotifications(hide)
- storage.setHideUntrustedNotifications(hide)
- }
-
- const updateHideUntrustedNotes = (hide: boolean) => {
- setHideUntrustedNotes(hide)
- storage.setHideUntrustedNotes(hide)
- }
-
- return (
-
- {children}
-
- )
-}
diff --git a/src/services/local-storage.service.ts b/src/services/local-storage.service.ts
index 51bab52b..9a91e5ec 100644
--- a/src/services/local-storage.service.ts
+++ b/src/services/local-storage.service.ts
@@ -59,9 +59,6 @@ const SETTINGS_KEYS = [
StorageKey.QUICK_ZAP,
StorageKey.INCLUDE_PUBLIC_ZAP_RECEIPT,
StorageKey.AUTOPLAY,
- StorageKey.HIDE_UNTRUSTED_INTERACTIONS,
- StorageKey.HIDE_UNTRUSTED_NOTIFICATIONS,
- StorageKey.HIDE_UNTRUSTED_NOTES,
StorageKey.MEDIA_UPLOAD_SERVICE_CONFIG_MAP,
StorageKey.DEFAULT_SHOW_NSFW,
StorageKey.DISMISSED_TOO_MANY_RELAYS_ALERT,
@@ -81,10 +78,6 @@ const SETTINGS_KEYS = [
StorageKey.SHOW_LIVE_ACTIVITIES_BANNER,
StorageKey.DEFAULT_EXPIRATION_ENABLED,
StorageKey.DEFAULT_EXPIRATION_MONTHS,
- StorageKey.DEFAULT_QUIET_ENABLED,
- StorageKey.DEFAULT_QUIET_DAYS,
- StorageKey.RESPECT_QUIET_TAGS,
- StorageKey.GLOBAL_QUIET_MODE,
StorageKey.SHOW_RSS_FEED,
StorageKey.PANE_MODE,
StorageKey.RESTRICT_RELAYS_TO_METADATA_LISTS
@@ -108,9 +101,6 @@ class LocalStorageService {
private includePublicZapReceipt: boolean = true
private mediaUploadService: string = DEFAULT_NIP_96_SERVICE
private autoplay: boolean = true
- private hideUntrustedInteractions: boolean = false
- private hideUntrustedNotifications: boolean = false
- private hideUntrustedNotes: boolean = false
private mediaUploadServiceConfigMap: Record = {}
private defaultShowNsfw: boolean = false
private dismissedTooManyRelaysAlert: boolean = false
@@ -127,10 +117,6 @@ class LocalStorageService {
private shownCreateWalletGuideToastPubkeys: Set = new Set()
private defaultExpirationEnabled: boolean = false
private defaultExpirationMonths: number = 6
- private defaultQuietEnabled: boolean = false
- private defaultQuietDays: number = 7
- private respectQuietTags: boolean = true
- private globalQuietMode: boolean = false
private showRssFeed: boolean = true
private panelMode: 'single' | 'double' = 'single'
private addRandomRelaysToPublish: boolean = false
@@ -219,25 +205,6 @@ class LocalStorageService {
this.autoplay = window.localStorage.getItem(StorageKey.AUTOPLAY) !== 'false'
- const hideUntrustedEvents =
- window.localStorage.getItem(StorageKey.HIDE_UNTRUSTED_EVENTS) === 'true'
- const storedHideUntrustedInteractions = window.localStorage.getItem(
- StorageKey.HIDE_UNTRUSTED_INTERACTIONS
- )
- const storedHideUntrustedNotifications = window.localStorage.getItem(
- StorageKey.HIDE_UNTRUSTED_NOTIFICATIONS
- )
- const storedHideUntrustedNotes = window.localStorage.getItem(StorageKey.HIDE_UNTRUSTED_NOTES)
- this.hideUntrustedInteractions = storedHideUntrustedInteractions
- ? storedHideUntrustedInteractions === 'true'
- : hideUntrustedEvents
- this.hideUntrustedNotifications = storedHideUntrustedNotifications
- ? storedHideUntrustedNotifications === 'true'
- : hideUntrustedEvents
- this.hideUntrustedNotes = storedHideUntrustedNotes
- ? storedHideUntrustedNotes === 'true'
- : hideUntrustedEvents
-
const mediaUploadServiceConfigMapStr = window.localStorage.getItem(
StorageKey.MEDIA_UPLOAD_SERVICE_CONFIG_MAP
)
@@ -419,7 +386,7 @@ class LocalStorageService {
? new Set(JSON.parse(shownCreateWalletGuideToastPubkeysStr))
: new Set()
- // Initialize expiration and quiet settings
+ // Initialize expiration settings
const defaultExpirationEnabledStr = window.localStorage.getItem(StorageKey.DEFAULT_EXPIRATION_ENABLED)
this.defaultExpirationEnabled = defaultExpirationEnabledStr === 'true'
@@ -431,23 +398,6 @@ class LocalStorageService {
}
}
- const defaultQuietEnabledStr = window.localStorage.getItem(StorageKey.DEFAULT_QUIET_ENABLED)
- this.defaultQuietEnabled = defaultQuietEnabledStr === 'true'
-
- const defaultQuietDaysStr = window.localStorage.getItem(StorageKey.DEFAULT_QUIET_DAYS)
- if (defaultQuietDaysStr) {
- const num = parseInt(defaultQuietDaysStr)
- if (!isNaN(num) && num >= 0 && Number.isInteger(num)) {
- this.defaultQuietDays = num
- }
- }
-
- const respectQuietTagsStr = window.localStorage.getItem(StorageKey.RESPECT_QUIET_TAGS)
- this.respectQuietTags = respectQuietTagsStr === null ? true : respectQuietTagsStr === 'true'
-
- const globalQuietModeStr = window.localStorage.getItem(StorageKey.GLOBAL_QUIET_MODE)
- this.globalQuietMode = globalQuietModeStr === 'true'
-
const showRssFeedStr = window.localStorage.getItem(StorageKey.SHOW_RSS_FEED)
this.showRssFeed = showRssFeedStr === null ? true : showRssFeedStr === 'true' // Default to true
@@ -617,12 +567,6 @@ class LocalStorageService {
const includeReceiptStr = get(StorageKey.INCLUDE_PUBLIC_ZAP_RECEIPT)
if (includeReceiptStr != null) this.includePublicZapReceipt = includeReceiptStr !== 'false'
this.autoplay = get(StorageKey.AUTOPLAY) !== 'false'
- const hideInteractions = get(StorageKey.HIDE_UNTRUSTED_INTERACTIONS)
- if (hideInteractions != null) this.hideUntrustedInteractions = hideInteractions === 'true'
- const hideNotifications = get(StorageKey.HIDE_UNTRUSTED_NOTIFICATIONS)
- if (hideNotifications != null) this.hideUntrustedNotifications = hideNotifications === 'true'
- const hideNotes = get(StorageKey.HIDE_UNTRUSTED_NOTES)
- if (hideNotes != null) this.hideUntrustedNotes = hideNotes === 'true'
const mediaConfigStr = get(StorageKey.MEDIA_UPLOAD_SERVICE_CONFIG_MAP)
if (mediaConfigStr != null) this.mediaUploadServiceConfigMap = JSON.parse(mediaConfigStr) as Record
this.defaultShowNsfw = get(StorageKey.DEFAULT_SHOW_NSFW) === 'true'
@@ -658,15 +602,6 @@ class LocalStorageService {
const num = parseInt(defaultExpirationMonthsStr)
if (!isNaN(num) && num >= 0) this.defaultExpirationMonths = num
}
- this.defaultQuietEnabled = get(StorageKey.DEFAULT_QUIET_ENABLED) === 'true'
- const defaultQuietDaysStr = get(StorageKey.DEFAULT_QUIET_DAYS)
- if (defaultQuietDaysStr != null) {
- const num = parseInt(defaultQuietDaysStr)
- if (!isNaN(num) && num >= 0) this.defaultQuietDays = num
- }
- const respectQuietStr = get(StorageKey.RESPECT_QUIET_TAGS)
- if (respectQuietStr != null) this.respectQuietTags = respectQuietStr === 'true'
- this.globalQuietMode = get(StorageKey.GLOBAL_QUIET_MODE) === 'true'
const showRssStr = get(StorageKey.SHOW_RSS_FEED)
if (showRssStr != null) this.showRssFeed = showRssStr === 'true'
const paneStr = get(StorageKey.PANE_MODE)
@@ -866,38 +801,6 @@ class LocalStorageService {
this.persistSetting(StorageKey.AUTOPLAY, autoplay.toString())
}
- getHideUntrustedInteractions() {
- return this.hideUntrustedInteractions
- }
-
- setHideUntrustedInteractions(hideUntrustedInteractions: boolean) {
- this.hideUntrustedInteractions = hideUntrustedInteractions
- this.persistSetting(
- StorageKey.HIDE_UNTRUSTED_INTERACTIONS,
- hideUntrustedInteractions.toString()
- )
- }
-
- getHideUntrustedNotifications() {
- return this.hideUntrustedNotifications
- }
-
- setHideUntrustedNotifications(hideUntrustedNotifications: boolean) {
- this.hideUntrustedNotifications = hideUntrustedNotifications
- this.persistSetting(
- StorageKey.HIDE_UNTRUSTED_NOTIFICATIONS,
- hideUntrustedNotifications.toString()
- )
- }
-
- getHideUntrustedNotes() {
- return this.hideUntrustedNotes
- }
-
- setHideUntrustedNotes(hideUntrustedNotes: boolean) {
- this.hideUntrustedNotes = hideUntrustedNotes
- this.persistSetting(StorageKey.HIDE_UNTRUSTED_NOTES, hideUntrustedNotes.toString())
- }
getMediaUploadServiceConfig(pubkey?: string | null): TMediaUploadServiceConfig {
const defaultConfig = { type: 'nip96', service: this.mediaUploadService } as const
@@ -1083,45 +986,6 @@ class LocalStorageService {
}
}
- // Quiet settings
- getDefaultQuietEnabled() {
- return this.defaultQuietEnabled
- }
-
- setDefaultQuietEnabled(enabled: boolean) {
- this.defaultQuietEnabled = enabled
- this.persistSetting(StorageKey.DEFAULT_QUIET_ENABLED, enabled.toString())
- }
-
- getDefaultQuietDays() {
- return this.defaultQuietDays
- }
-
- setDefaultQuietDays(days: number) {
- if (Number.isInteger(days) && days >= 0) {
- this.defaultQuietDays = days
- this.persistSetting(StorageKey.DEFAULT_QUIET_DAYS, days.toString())
- }
- }
-
- getRespectQuietTags() {
- return this.respectQuietTags
- }
-
- setRespectQuietTags(respect: boolean) {
- this.respectQuietTags = respect
- this.persistSetting(StorageKey.RESPECT_QUIET_TAGS, respect.toString())
- }
-
- getGlobalQuietMode() {
- return this.globalQuietMode
- }
-
- setGlobalQuietMode(enabled: boolean) {
- this.globalQuietMode = enabled
- this.persistSetting(StorageKey.GLOBAL_QUIET_MODE, enabled.toString())
- }
-
getShowRssFeed() {
return this.showRssFeed
}