Browse Source

bug-fixes

imwald
Silberengel 1 month ago
parent
commit
18e980e5de
  1. 2
      src/components/BottomNavigationBar/BottomNavigationBarItem.tsx
  2. 6
      src/components/BottomNavigationBar/HomeButton.tsx
  3. 2
      src/components/ContentPreview/FollowPackPreview.tsx
  4. 2
      src/components/ContentPreview/index.tsx
  5. 8
      src/components/Explore/ExploreFavoriteRelays.tsx
  6. 277
      src/components/FavoriteRelaysFeedPicker/index.tsx
  7. 2
      src/components/FollowButton/index.tsx
  8. 2
      src/components/HideUntrustedContentButton/index.tsx
  9. 4
      src/components/LatestFromFollowsSection/index.tsx
  10. 2
      src/components/MuteButton/index.tsx
  11. 2
      src/components/NormalFeed/index.tsx
  12. 2
      src/components/Note/index.tsx
  13. 2
      src/components/NoteBoostBadges/index.tsx
  14. 2
      src/components/NoteCard/RepostNoteCard.tsx
  15. 2
      src/components/NoteCard/index.tsx
  16. 4
      src/components/NoteList/index.tsx
  17. 2
      src/components/NoteOptions/useMenuActions.tsx
  18. 2
      src/components/NoteStats/LikeButton.tsx
  19. 2
      src/components/NoteStats/Likes.tsx
  20. 2
      src/components/NoteStats/ReplyButton.tsx
  21. 2
      src/components/NoteStats/RepostButton.tsx
  22. 2
      src/components/PostEditor/Mentions.tsx
  23. 2
      src/components/Profile/SmartMuteLink.tsx
  24. 2
      src/components/ProfileOptions/index.tsx
  25. 2
      src/components/QuoteList/index.tsx
  26. 4
      src/components/RelayInfo/RelayReviewsPreview.tsx
  27. 2
      src/components/ReplyNote/index.tsx
  28. 4
      src/components/ReplyNoteList/index.tsx
  29. 6
      src/components/Sidebar/HomeButton.tsx
  30. 27
      src/contexts/mute-list-context.tsx
  31. 26
      src/contexts/user-trust-context.tsx
  32. 5
      src/i18n/locales/ar.ts
  33. 5
      src/i18n/locales/de.ts
  34. 5
      src/i18n/locales/en.ts
  35. 5
      src/i18n/locales/es.ts
  36. 5
      src/i18n/locales/fa.ts
  37. 5
      src/i18n/locales/fr.ts
  38. 5
      src/i18n/locales/hi.ts
  39. 5
      src/i18n/locales/it.ts
  40. 5
      src/i18n/locales/ja.ts
  41. 5
      src/i18n/locales/ko.ts
  42. 5
      src/i18n/locales/pl.ts
  43. 5
      src/i18n/locales/pt-BR.ts
  44. 5
      src/i18n/locales/pt-PT.ts
  45. 5
      src/i18n/locales/ru.ts
  46. 5
      src/i18n/locales/th.ts
  47. 5
      src/i18n/locales/zh.ts
  48. 34
      src/pages/primary/NoteListPage/index.tsx
  49. 2
      src/pages/primary/SpellsPage/index.tsx
  50. 2
      src/pages/secondary/GeneralSettingsPage/index.tsx
  51. 2
      src/pages/secondary/MuteListPage/index.tsx
  52. 27
      src/providers/MuteListProvider.tsx
  53. 25
      src/providers/UserTrustProvider.tsx

2
src/components/BottomNavigationBar/BottomNavigationBarItem.tsx

@ -10,7 +10,7 @@ export default function BottomNavigationBarItem({ @@ -10,7 +10,7 @@ export default function BottomNavigationBarItem({
}: {
children: React.ReactNode
active?: boolean
/** Slightly larger icon (e.g. favorites feed). */
/** Slightly larger icon (e.g. home feed). */
prominent?: boolean
onClick: MouseEventHandler
}) {

6
src/components/BottomNavigationBar/HomeButton.tsx

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
import { cn } from '@/lib/utils'
import { usePrimaryPage } from '@/contexts/primary-page-context'
import { usePrimaryNoteView } from '@/contexts/primary-note-view-context'
import { Star } from 'lucide-react'
import { House } from 'lucide-react'
import BottomNavigationBarItem from './BottomNavigationBarItem'
/** Favorites feed (primary “home” destination in the bar). */
/** Home feed (primary timeline). */
export default function HomeButton() {
const { navigate, current, display } = usePrimaryPage()
const { primaryViewType, setPrimaryNoteView } = usePrimaryNoteView()
@ -23,7 +23,7 @@ export default function HomeButton() { @@ -23,7 +23,7 @@ export default function HomeButton() {
}
}}
>
<Star
<House
strokeWidth={active ? 2.4 : 2}
className={cn(active && 'fill-green-500/30 dark:fill-green-400/35')}
/>

2
src/components/ContentPreview/FollowPackPreview.tsx

@ -2,7 +2,7 @@ import { getPubkeysFromPTags } from '@/lib/tag' @@ -2,7 +2,7 @@ import { getPubkeysFromPTags } from '@/lib/tag'
import logger from '@/lib/logger'
import { cn } from '@/lib/utils'
import { useFollowList } from '@/providers/FollowListProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { Event } from 'nostr-tools'
import { Users } from 'lucide-react'

2
src/components/ContentPreview/index.tsx

@ -2,7 +2,7 @@ import { ExtendedKind } from '@/constants' @@ -2,7 +2,7 @@ import { ExtendedKind } from '@/constants'
import { isMentioningMutedUsers } from '@/lib/event'
import { cn } from '@/lib/utils'
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { Event, kinds } from 'nostr-tools'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'

8
src/components/Explore/ExploreFavoriteRelays.tsx

@ -6,6 +6,7 @@ import { toRelay, toRelaySettings } from '@/lib/link' @@ -6,6 +6,7 @@ import { toRelay, toRelaySettings } from '@/lib/link'
import { normalizeUrl, simplifyUrl } from '@/lib/url'
import { usePrimaryPage } from '@/contexts/primary-page-context'
import { useSecondaryPage, useSmartRelayNavigation } from '@/PageManager'
import { useFeed } from '@/providers/FeedProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import { cn } from '@/lib/utils'
import { Newspaper, Settings } from 'lucide-react'
@ -60,6 +61,7 @@ export default function ExploreFavoriteRelays() { @@ -60,6 +61,7 @@ export default function ExploreFavoriteRelays() {
const { t } = useTranslation()
const { navigate } = usePrimaryPage()
const { push } = useSecondaryPage()
const { switchFeed } = useFeed()
const { favoriteRelays, blockedRelays } = useFavoriteRelays()
const blockedSet = useMemo(
@ -97,10 +99,12 @@ export default function ExploreFavoriteRelays() { @@ -97,10 +99,12 @@ export default function ExploreFavoriteRelays() {
variant="outline"
size="sm"
className="h-8 gap-1.5 px-2.5 font-medium"
onClick={() => navigate('feed')}
onClick={() => {
void switchFeed('all-favorites').then(() => navigate('feed'))
}}
>
<Newspaper className="size-4 shrink-0" strokeWidth={2.5} />
<span>{t('Favorites Feed')}</span>
<span>{t('Favorite Relays')}</span>
</Button>
<Button
type="button"

277
src/components/FavoriteRelaysFeedPicker/index.tsx

@ -0,0 +1,277 @@ @@ -0,0 +1,277 @@
import { Button } from '@/components/ui/button'
import {
Select,
SelectContent,
SelectItem,
SelectLabel,
SelectSeparator,
SelectTrigger,
SelectValue
} from '@/components/ui/select'
import { getFavoritesFeedRelayUrls } from '@/lib/favorites-feed-relays'
import { toRelaySettings } from '@/lib/link'
import { normalizeUrl, simplifyUrl } from '@/lib/url'
import { cn } from '@/lib/utils'
import { useSecondaryPage } from '@/PageManager'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import { useFeed } from '@/providers/FeedProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { SquarePen } from 'lucide-react'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
const ALL_FAVORITES_VALUE = '__all_favorites__'
function relaySetToSelectValue(id: string) {
return `rs:${encodeURIComponent(id)}`
}
function selectValueToRelaySetId(v: string) {
if (!v.startsWith('rs:')) return null
return decodeURIComponent(v.slice(3))
}
/** Top-of-feed control: all favorites, single relays, and relay sets. */
export default function FavoriteRelaysFeedPicker() {
const { t } = useTranslation()
const { isSmallScreen } = useScreenSize()
const { push } = useSecondaryPage()
const { favoriteRelays, blockedRelays, relaySets } = useFavoriteRelays()
const { feedInfo, switchFeed } = useFeed()
const openFavoriteRelaySettings = () => {
push(toRelaySettings('favorite-relays'))
}
const settingsLabel = t('Relay settings')
const urls = useMemo(
() => getFavoritesFeedRelayUrls(favoriteRelays, blockedRelays),
[favoriteRelays, blockedRelays]
)
const currentRelayKey =
feedInfo.feedType === 'relay' && feedInfo.id ? normalizeUrl(feedInfo.id) || feedInfo.id : null
const allActive = feedInfo.feedType === 'all-favorites'
const relaySetIdActive = feedInfo.feedType === 'relays' && feedInfo.id ? feedInfo.id : null
const orphanRelaySetId =
relaySetIdActive && !relaySets.some((s) => s.id === relaySetIdActive) ? relaySetIdActive : null
const selectValue = allActive
? ALL_FAVORITES_VALUE
: relaySetIdActive
? relaySetToSelectValue(relaySetIdActive)
: currentRelayKey
? currentRelayKey
: ALL_FAVORITES_VALUE
/** Values that exist in the mobile Select (for controlled `value` validation). */
const selectItems = useMemo(() => {
const items: { value: string }[] = [{ value: ALL_FAVORITES_VALUE }]
for (const url of urls) {
items.push({ value: normalizeUrl(url) || url })
}
if (
!allActive &&
feedInfo.feedType === 'relay' &&
feedInfo.id &&
!items.some((i) => i.value === currentRelayKey)
) {
items.push({ value: normalizeUrl(feedInfo.id) || feedInfo.id })
}
for (const set of relaySets) {
items.push({ value: relaySetToSelectValue(set.id) })
}
if (orphanRelaySetId) {
items.push({ value: relaySetToSelectValue(orphanRelaySetId) })
}
return items
}, [
urls,
allActive,
feedInfo.feedType,
feedInfo.id,
currentRelayKey,
relaySets,
orphanRelaySetId
])
const resolvedSelectValue = selectItems.some((i) => i.value === selectValue)
? selectValue
: ALL_FAVORITES_VALUE
const resolveRelayUrl = (value: string) => {
if (value === ALL_FAVORITES_VALUE) return null
const fromList = urls.find((u) => (normalizeUrl(u) || u) === value)
return fromList ?? value
}
const onPickValue = (v: string) => {
if (v === ALL_FAVORITES_VALUE) {
void switchFeed('all-favorites')
return
}
const setId = selectValueToRelaySetId(v)
if (setId) {
void switchFeed('relays', { activeRelaySetId: setId })
return
}
const relay = resolveRelayUrl(v)
if (relay) void switchFeed('relay', { relay })
}
if (urls.length === 0 && relaySets.length === 0) return null
const editSettingsButton = (
<Button
type="button"
variant="outline"
size="icon"
className="h-9 w-9 shrink-0"
title={settingsLabel}
aria-label={settingsLabel}
onClick={(e) => {
e.stopPropagation()
openFavoriteRelaySettings()
}}
>
<SquarePen className="size-4" />
</Button>
)
if (isSmallScreen) {
return (
<div
className="flex w-full min-w-0 items-center gap-1.5 border-b border-border/80 bg-background px-2 py-1.5"
aria-label={t('Favorite Relays')}
>
<div className="min-w-0 flex-1">
<Select value={resolvedSelectValue} onValueChange={onPickValue}>
<SelectTrigger className="h-9 w-full font-mono text-xs">
<SelectValue placeholder={t('Favorite Relays')} />
</SelectTrigger>
<SelectContent position="popper" className="z-[120] max-h-[min(24rem,70vh)]">
<SelectItem value={ALL_FAVORITES_VALUE} className="text-xs">
{t('All favorite relays')}
</SelectItem>
{urls.map((url) => {
const v = normalizeUrl(url) || url
return (
<SelectItem key={v} value={v} className="font-mono text-xs" title={url}>
{simplifyUrl(url)}
</SelectItem>
)
})}
{relaySets.length > 0 || orphanRelaySetId ? (
<>
<SelectSeparator />
<SelectLabel className="pl-2">{t('Relay sets')}</SelectLabel>
{relaySets.map((set) => (
<SelectItem
key={set.id}
value={relaySetToSelectValue(set.id)}
className="text-xs font-sans"
>
{set.name}
</SelectItem>
))}
{orphanRelaySetId ? (
<SelectItem
value={relaySetToSelectValue(orphanRelaySetId)}
className="font-mono text-xs"
>
{orphanRelaySetId}
</SelectItem>
) : null}
</>
) : null}
</SelectContent>
</Select>
</div>
{editSettingsButton}
</div>
)
}
return (
<div
className="flex w-full min-w-0 items-center gap-1.5 border-b border-border/80 bg-background px-2 py-1.5"
role="toolbar"
aria-label={t('Favorite Relays')}
>
<div className="flex min-w-0 flex-1 gap-1.5 overflow-x-auto pb-0.5 scrollbar-hide [scrollbar-gutter:stable]">
<button
type="button"
className={cn(
'shrink-0 rounded-full border px-3 py-1 text-xs font-semibold transition-colors',
allActive
? 'border-primary bg-primary/15 text-foreground'
: 'border-border bg-muted/40 text-muted-foreground hover:bg-accent'
)}
onClick={() => void switchFeed('all-favorites')}
>
{t('All favorite relays')}
</button>
{urls.map((url) => {
const key = normalizeUrl(url) || url
const active = feedInfo.feedType === 'relay' && currentRelayKey === key
return (
<button
key={key}
type="button"
className={cn(
'max-w-[11rem] shrink-0 truncate rounded-full border px-3 py-1 font-mono text-xs font-semibold transition-colors',
active
? 'border-primary bg-primary/15 text-foreground'
: 'border-border bg-muted/40 text-muted-foreground hover:bg-accent'
)}
title={url}
onClick={() => void switchFeed('relay', { relay: url })}
>
{simplifyUrl(url)}
</button>
)
})}
{(relaySets.length > 0 || orphanRelaySetId) && (
<div className="mx-0.5 shrink-0 self-stretch border-l border-border/80" aria-hidden />
)}
{relaySets.map((set) => {
const active = feedInfo.feedType === 'relays' && feedInfo.id === set.id
return (
<button
key={set.id}
type="button"
className={cn(
'max-w-[10rem] shrink-0 truncate rounded-full border px-3 py-1 text-xs font-semibold transition-colors',
active
? 'border-primary bg-primary/15 text-foreground'
: 'border-border bg-muted/40 text-muted-foreground hover:bg-accent'
)}
title={set.name}
onClick={() => void switchFeed('relays', { activeRelaySetId: set.id })}
>
{set.name}
</button>
)
})}
{orphanRelaySetId ? (
<button
type="button"
className={cn(
'max-w-[10rem] shrink-0 truncate rounded-full border px-3 py-1 font-mono text-xs font-semibold transition-colors',
'border-primary bg-primary/15 text-foreground'
)}
title={orphanRelaySetId}
onClick={() => void switchFeed('relays', { activeRelaySetId: orphanRelaySetId })}
>
{orphanRelaySetId}
</button>
) : null}
</div>
{editSettingsButton}
</div>
)
}

2
src/components/FollowButton/index.tsx

@ -12,7 +12,7 @@ import { @@ -12,7 +12,7 @@ import {
import { Button } from '@/components/ui/button'
import { Skeleton } from '@/components/ui/skeleton'
import { useFollowList } from '@/providers/FollowListProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'

2
src/components/HideUntrustedContentButton/index.tsx

@ -10,7 +10,7 @@ import { @@ -10,7 +10,7 @@ import {
AlertDialogTrigger
} from '@/components/ui/alert-dialog'
import { Button, buttonVariants } from '@/components/ui/button'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import { VariantProps } from 'class-variance-authority'
import { Shield, ShieldCheck } from 'lucide-react'
import { useTranslation } from 'react-i18next'

4
src/components/LatestFromFollowsSection/index.tsx

@ -10,9 +10,9 @@ import { cn } from '@/lib/utils' @@ -10,9 +10,9 @@ import { cn } from '@/lib/utils'
import { useSecondaryPage } from '@/PageManager'
import { useDeletedEvent } from '@/providers/DeletedEventProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import { queryService, replaceableEventService } from '@/services/client.service'
import type { TRelayList } from '@/types'
import logger from '@/lib/logger'

2
src/components/MuteButton/index.tsx

@ -7,7 +7,7 @@ import { @@ -7,7 +7,7 @@ import {
DropdownMenuItem,
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { BellOff } from 'lucide-react'

2
src/components/NormalFeed/index.tsx

@ -2,7 +2,7 @@ import NoteList, { TNoteListRef } from '@/components/NoteList' @@ -2,7 +2,7 @@ import NoteList, { TNoteListRef } from '@/components/NoteList'
import { RefreshButton } from '@/components/RefreshButton'
import Tabs, { TabDefinition } from '@/components/Tabs'
import { useKindFilter } from '@/providers/KindFilterProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import storage from '@/services/local-storage.service'
import { TFeedSubRequest, TNoteListMode } from '@/types'
import { forwardRef, useLayoutEffect, useMemo, useRef, useState } from 'react'

2
src/components/Note/index.tsx

@ -6,7 +6,7 @@ import { toNote } from '@/lib/link' @@ -6,7 +6,7 @@ import { toNote } from '@/lib/link'
import logger from '@/lib/logger'
import client from '@/services/client.service'
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import type { HighlightData } from '@/components/PostEditor/HighlightEditor'
import { Event, kinds } from 'nostr-tools'

2
src/components/NoteBoostBadges/index.tsx

@ -2,7 +2,7 @@ import { ExtendedKind } from '@/constants' @@ -2,7 +2,7 @@ import { ExtendedKind } from '@/constants'
import { useNoteStatsById } from '@/hooks/useNoteStatsById'
import { shouldHideInteractions } from '@/lib/event-filtering'
import { cn } from '@/lib/utils'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import { Event } from 'nostr-tools'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'

2
src/components/NoteCard/RepostNoteCard.tsx

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import { isMentioningMutedUsers } from '@/lib/event'
import { tagNameEquals } from '@/lib/tag'
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import client from '@/services/client.service'
import { eventService } from '@/services/client.service'
import { Event, kinds, nip19, verifyEvent } from 'nostr-tools'

2
src/components/NoteCard/index.tsx

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import { Skeleton } from '@/components/ui/skeleton'
import { isMentioningMutedUsers } from '@/lib/event'
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { Event, kinds } from 'nostr-tools'
import { memo, useMemo } from 'react'
import MainNoteCard from './MainNoteCard'

4
src/components/NoteList/index.tsx

@ -19,9 +19,9 @@ import { getZapInfoFromEvent } from '@/lib/event-metadata' @@ -19,9 +19,9 @@ import { getZapInfoFromEvent } from '@/lib/event-metadata'
import { isTouchDevice } from '@/lib/utils'
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useDeletedEvent } from '@/providers/DeletedEventProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import { useZap } from '@/providers/ZapProvider'
import client from '@/services/client.service'
import { TFeedSubRequest } from '@/types'

2
src/components/NoteOptions/useMenuActions.tsx

@ -10,7 +10,7 @@ import { buildPinListTagsAfterToggle, fetchLatestReplaceableListEvent } from '@/ @@ -10,7 +10,7 @@ import { buildPinListTagsAfterToggle, fetchLatestReplaceableListEvent } from '@/
import { generateBech32IdFromATag } from '@/lib/tag'
import { useCurrentRelays } from '@/providers/CurrentRelaysProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { FAST_READ_RELAY_URLS, FAST_WRITE_RELAY_URLS } from '@/constants'
import client from '@/services/client.service'

2
src/components/NoteStats/LikeButton.tsx

@ -12,7 +12,7 @@ import { createDeletionRequestDraftEvent, createReactionDraftEvent } from '@/lib @@ -12,7 +12,7 @@ import { createDeletionRequestDraftEvent, createReactionDraftEvent } from '@/lib
import { getRootEventHexId } from '@/lib/event'
import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import { eventService } from '@/services/client.service'
import noteStatsService from '@/services/note-stats.service'
import { TEmoji } from '@/types'

2
src/components/NoteStats/Likes.tsx

@ -7,7 +7,7 @@ import { shouldHideInteractions } from '@/lib/event-filtering' @@ -7,7 +7,7 @@ import { shouldHideInteractions } from '@/lib/event-filtering'
import { createReactionDraftEvent } from '@/lib/draft-event'
import { cn } from '@/lib/utils'
import { useNostr } from '@/providers/NostrProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import noteStatsService from '@/services/note-stats.service'
import { TEmoji } from '@/types'
import { Event } from 'nostr-tools'

2
src/components/NoteStats/ReplyButton.tsx

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import { useNoteStatsById } from '@/hooks/useNoteStatsById'
import { cn } from '@/lib/utils'
import { useNostr } from '@/providers/NostrProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import { MessageCircle } from 'lucide-react'
import { Event } from 'nostr-tools'
import { useMemo, useState } from 'react'

2
src/components/NoteStats/RepostButton.tsx

@ -13,7 +13,7 @@ import { getNoteBech32Id } from '@/lib/event' @@ -13,7 +13,7 @@ import { getNoteBech32Id } from '@/lib/event'
import { cn } from '@/lib/utils'
import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import noteStatsService from '@/services/note-stats.service'
import { PencilLine, Repeat } from 'lucide-react'
import { Event } from 'nostr-tools'

2
src/components/PostEditor/Mentions.tsx

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
import { Button } from '@/components/ui/button'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { eventService } from '@/services/client.service'
import { NOSTR_URI_FOR_REPLY_PUBKEYS_REGEX } from '@/lib/content-patterns'

2
src/components/Profile/SmartMuteLink.tsx

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
import { toMuteList } from '@/lib/link'
import { useSmartMuteListNavigation } from '@/PageManager'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useTranslation } from 'react-i18next'
export default function SmartMuteLink() {

2
src/components/ProfileOptions/index.tsx

@ -9,7 +9,7 @@ import { @@ -9,7 +9,7 @@ import {
import { buildHiveTalkJoinUrl, roomIdForPubkeys } from '@/lib/hivetalk'
import { formatPubkey, pubkeyToNpub } from '@/lib/pubkey'
import { normalizeUrl } from '@/lib/url'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import { useCurrentRelays } from '@/providers/CurrentRelaysProvider'

2
src/components/QuoteList/index.tsx

@ -3,7 +3,7 @@ import { getReplaceableCoordinateFromEvent, isReplaceableEvent } from '@/lib/eve @@ -3,7 +3,7 @@ import { getReplaceableCoordinateFromEvent, isReplaceableEvent } from '@/lib/eve
import { normalizeUrl } from '@/lib/url'
import { useCurrentRelays } from '@/providers/CurrentRelaysProvider'
import { useNostr } from '@/providers/NostrProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import client from '@/services/client.service'
import dayjs from 'dayjs'
import { Event, kinds } from 'nostr-tools'

4
src/components/RelayInfo/RelayReviewsPreview.tsx

@ -13,9 +13,9 @@ import { getStarsFromRelayReviewEvent } from '@/lib/event-metadata' @@ -13,9 +13,9 @@ import { getStarsFromRelayReviewEvent } from '@/lib/event-metadata'
import { toRelayReviews } from '@/lib/link'
import { normalizeUrl } from '@/lib/url'
import { cn, isTouchDevice } from '@/lib/utils'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import { queryService } from '@/services/client.service'
import { WheelGesturesPlugin } from 'embla-carousel-wheel-gestures'
import type { NostrEvent } from 'nostr-tools'

2
src/components/ReplyNote/index.tsx

@ -5,7 +5,7 @@ import { isMentioningMutedUsers } from '@/lib/event' @@ -5,7 +5,7 @@ import { isMentioningMutedUsers } from '@/lib/event'
import { toNote } from '@/lib/link'
import client from '@/services/client.service'
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { Event } from 'nostr-tools'
import { useMemo, useState } from 'react'

4
src/components/ReplyNoteList/index.tsx

@ -17,10 +17,10 @@ import { toNote } from '@/lib/link' @@ -17,10 +17,10 @@ import { toNote } from '@/lib/link'
import { generateBech32IdFromETag } from '@/lib/tag'
import { useSmartNoteNavigation, useSecondaryPage } from '@/PageManager'
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { useReply } from '@/providers/ReplyProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import { useCurrentRelays } from '@/providers/CurrentRelaysProvider'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import client from '@/services/client.service'

6
src/components/Sidebar/HomeButton.tsx

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import { cn } from '@/lib/utils'
import { usePrimaryPage } from '@/contexts/primary-page-context'
import { usePrimaryNoteView } from '@/contexts/primary-note-view-context'
import { Star } from 'lucide-react'
import { House } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import SidebarItem from './SidebarItem'
@ -13,7 +13,7 @@ export default function HomeButton() { @@ -13,7 +13,7 @@ export default function HomeButton() {
return (
<SidebarItem
title={t('Favorites Feed')}
title={t('Favorite Relays')}
onClick={() => navigate('feed')}
active={active}
className={cn(
@ -22,7 +22,7 @@ export default function HomeButton() { @@ -22,7 +22,7 @@ export default function HomeButton() {
active && 'bg-green-500/15 opacity-100 hover:bg-green-500/15 dark:bg-green-500/20'
)}
>
<Star
<House
strokeWidth={active ? 2.75 : 2.35}
className={cn(active && 'fill-green-500/30 dark:fill-green-400/35')}
/>

27
src/contexts/mute-list-context.tsx

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
import { createContext, useContext } from 'react'
export type TMuteListContext = {
mutePubkeySet: Set<string>
changing: boolean
getMutePubkeys: () => string[]
getMuteType: (pubkey: string) => 'public' | 'private' | null
mutePubkeyPublicly: (pubkey: string) => Promise<void>
mutePubkeyPrivately: (pubkey: string) => Promise<void>
unmutePubkey: (pubkey: string) => Promise<void>
switchToPublicMute: (pubkey: string) => Promise<void>
switchToPrivateMute: (pubkey: string) => Promise<void>
}
/**
* Dedicated module so lazy chunks share the same context as MuteListProvider (avoids duplicate
* createContext when useMuteList is imported from MuteListProvider.tsx in a lazy-loaded bundle).
*/
export const MuteListContext = createContext<TMuteListContext | undefined>(undefined)
export function useMuteList(): TMuteListContext {
const context = useContext(MuteListContext)
if (!context) {
throw new Error('useMuteList must be used within a MuteListProvider')
}
return context
}

26
src/contexts/user-trust-context.tsx

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
import { createContext, useContext } from 'react'
export type TUserTrustContext = {
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 Apps UserTrustProvider. Importing useUserTrust from UserTrustProvider into
* those chunks can duplicate the module and break Provider matching.
*/
export const UserTrustContext = createContext<TUserTrustContext | undefined>(undefined)
export function useUserTrust(): TUserTrustContext {
const context = useContext(UserTrustContext)
if (!context) {
throw new Error('useUserTrust must be used within a UserTrustProvider')
}
return context
}

5
src/i18n/locales/ar.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'نشر',
Home: 'الرئيسية',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'الريلايات المفضلة',
'All favorite relays': 'جميع الريلايات المفضلة',
'Pinned note': 'Pinned note',
'Relay settings': 'إعدادات الريلاي',
Settings: 'الإعدادات',
@ -419,7 +420,6 @@ export default { @@ -419,7 +420,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'لا توجد مزيد من الردود',
'Relay sets': 'مجموعات الريلاي',
'Favorite Relays': 'الريلايات المفضلة',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": 'المفضلات من المتابعين',
@ -894,7 +894,6 @@ export default { @@ -894,7 +894,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/de.ts

@ -8,7 +8,8 @@ export default { @@ -8,7 +8,8 @@ export default {
Post: 'Beitrag',
Home: 'Startseite',
Feed: 'Feed',
'Favorites Feed': 'Favoriten',
'Favorite Relays': 'Lieblings-Relays',
'All favorite relays': 'Alle Lieblingsrelais',
'Pinned note': 'Angehefteter Beitrag',
'Relay settings': 'Relay-Einstellungen',
Settings: 'Einstellungen',
@ -445,7 +446,6 @@ export default { @@ -445,7 +446,6 @@ export default {
'{{count}} externe Relays durchsucht; die Note wurde nicht gefunden.',
'no more replies': 'keine weiteren Antworten',
'Relay sets': 'Relay-Sets',
'Favorite Relays': 'Lieblings-Relays',
'Search for Relays': 'Relays suchen',
'Using app default relays': 'Standard-Relays der App',
"Following's Favorites": 'Favoriten der Folgenden',
@ -934,7 +934,6 @@ export default { @@ -934,7 +934,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/en.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'Post',
Home: 'Home',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'Favorite Relays',
'All favorite relays': 'All favorite relays',
'Pinned note': 'Pinned note',
'Relay settings': 'Relays and Storage Settings',
Settings: 'Settings',
@ -437,7 +438,6 @@ export default { @@ -437,7 +438,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'no more replies',
'Relay sets': 'Relay sets',
'Favorite Relays': 'Favorite Relays',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": "Following's Favorites",
@ -911,7 +911,6 @@ export default { @@ -911,7 +911,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/es.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'Publicar',
Home: 'Inicio',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'Relés favoritos',
'All favorite relays': 'Todos los relés favoritos',
'Pinned note': 'Pinned note',
'Relay settings': 'Configuración de relés',
Settings: 'Ajustes',
@ -423,7 +424,6 @@ export default { @@ -423,7 +424,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'no hay más respuestas',
'Relay sets': 'Conjuntos de relés',
'Favorite Relays': 'Relés favoritos',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": 'Favoritos de los seguidos',
@ -902,7 +902,6 @@ export default { @@ -902,7 +902,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/fa.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'ارسال',
Home: 'خانه',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'رلههای مورد علاقه',
'All favorite relays': 'همهٔ رلههای مورد علاقه',
'Pinned note': 'Pinned note',
'Relay settings': 'تنظیمات رله',
Settings: 'تنظیمات',
@ -422,7 +423,6 @@ export default { @@ -422,7 +423,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'پاسخ بیشتری وجود ندارد',
'Relay sets': 'مجموعههای رله',
'Favorite Relays': 'رلههای مورد علاقه',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": 'مورد علاقه دنبال شوندهها',
@ -898,7 +898,6 @@ export default { @@ -898,7 +898,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/fr.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'Publier',
Home: 'Accueil',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'Relais favoris',
'All favorite relays': 'Tous les relais favoris',
'Pinned note': 'Pinned note',
'Relay settings': 'Paramètres du relais',
Settings: 'Paramètres',
@ -422,7 +423,6 @@ export default { @@ -422,7 +423,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'aucune autre réponse',
'Relay sets': 'Groupes de relais',
'Favorite Relays': 'Relais favoris',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": "Following's Favorites",
@ -907,7 +907,6 @@ export default { @@ -907,7 +907,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/hi.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'पट',
Home: 'हम',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'पसि',
'All favorite relays': 'सभ पसि',
'Pinned note': 'Pinned note',
'Relay settings': 'रििस',
Settings: 'सिस',
@ -423,7 +424,6 @@ export default { @@ -423,7 +424,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'कई और उततर नह',
'Relay sets': 'रिट',
'Favorite Relays': 'पसि',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": 'फग क पस',
@ -900,7 +900,6 @@ export default { @@ -900,7 +900,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/it.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'Pubblica',
Home: 'Inizio',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'Relay preferiti',
'All favorite relays': 'Tutti i relay preferiti',
'Pinned note': 'Pinned note',
'Relay settings': 'Impostazioni Relay',
Settings: 'Impostazioni',
@ -423,7 +424,6 @@ export default { @@ -423,7 +424,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'niente più repliche',
'Relay sets': 'Set di Relay',
'Favorite Relays': 'Relay preferiti',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": 'Preferiti dei seguiti',
@ -903,7 +903,6 @@ export default { @@ -903,7 +903,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/ja.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: '投稿',
Home: 'ホーム',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'お気に入りのリレイ',
'All favorite relays': 'すべてのお気に入りリレイ',
'Pinned note': 'Pinned note',
'Relay settings': 'リレイ設定',
Settings: '設定',
@ -420,7 +421,6 @@ export default { @@ -420,7 +421,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'これ以上の返信はありません',
'Relay sets': 'リレイセット',
'Favorite Relays': 'お気に入りのリレイ',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": 'フォロー中のお気に入り',
@ -898,7 +898,6 @@ export default { @@ -898,7 +898,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/ko.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: '노트 게시',
Home: '홈',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': '즐겨찾는 릴레이',
'All favorite relays': '모든 즐겨찾는 릴레이',
'Pinned note': 'Pinned note',
'Relay settings': '릴레이 설정',
Settings: '설정',
@ -419,7 +420,6 @@ export default { @@ -419,7 +420,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': '더 이상 답글 없음',
'Relay sets': '릴레이 세트',
'Favorite Relays': '즐겨찾는 릴레이',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": '팔로잉의 즐겨찾기',
@ -896,7 +896,6 @@ export default { @@ -896,7 +896,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/pl.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'Publikuj',
Home: 'Strona Główna',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'Ulubione transmitery',
'All favorite relays': 'Wszystkie ulubione transmitery',
'Pinned note': 'Pinned note',
'Relay settings': 'Ustawienia transmiterów',
Settings: 'Ustawienia',
@ -420,7 +421,6 @@ export default { @@ -420,7 +421,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'brak kolejnych odpowiedzi',
'Relay sets': 'Zestawy transmiterów',
'Favorite Relays': 'Ulubione transmitery',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": 'Ulubione transmitery obserwowanych',
@ -901,7 +901,6 @@ export default { @@ -901,7 +901,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/pt-BR.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'Postar',
Home: 'Início',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'Relays favoritos',
'All favorite relays': 'Todos os relays favoritos',
'Pinned note': 'Pinned note',
'Relay settings': 'Configurações de relay',
Settings: 'Configurações',
@ -422,7 +423,6 @@ export default { @@ -422,7 +423,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'não há mais respostas',
'Relay sets': 'Conjuntos de relay',
'Favorite Relays': 'Relays favoritos',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": 'Favoritos de quem você segue',
@ -900,7 +900,6 @@ export default { @@ -900,7 +900,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/pt-PT.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'Postar',
Home: 'Início',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'Relés Favoritos',
'All favorite relays': 'Todos os relés favoritos',
'Pinned note': 'Pinned note',
'Relay settings': 'Configurações de Relé',
Settings: 'Configurações',
@ -422,7 +423,6 @@ export default { @@ -422,7 +423,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'não há mais respostas',
'Relay sets': 'Conjuntos de Relé',
'Favorite Relays': 'Relés Favoritos',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": 'Favoritos de quem você segue',
@ -902,7 +902,6 @@ export default { @@ -902,7 +902,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/ru.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'Опубликовать',
Home: 'Главная',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'Избранные ретрансляторы',
'All favorite relays': 'Все избранные ретрансляторы',
'Pinned note': 'Pinned note',
'Relay settings': 'Настройки ретрансляции',
Settings: 'Настройки',
@ -423,7 +424,6 @@ export default { @@ -423,7 +424,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'больше нет ответов',
'Relay sets': 'Наборы ретрансляторов',
'Favorite Relays': 'Избранные ретрансляторы',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": 'Избранные ретрансляторы подписчиков',
@ -903,7 +903,6 @@ export default { @@ -903,7 +903,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/th.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: 'โพสต',
Home: 'หนาหลก',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': 'รเลยโปรด',
'All favorite relays': 'รเลยโปรดทงหมด',
'Pinned note': 'Pinned note',
'Relay settings': 'การตงคารเลย',
Settings: 'การตงคา',
@ -419,7 +420,6 @@ export default { @@ -419,7 +420,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': 'ไมการตอบกลบเพมเตม',
'Relay sets': 'ชดรเลย',
'Favorite Relays': 'รเลยโปรด',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": 'รายการโปรดของผดตาม',
@ -893,7 +893,6 @@ export default { @@ -893,7 +893,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

5
src/i18n/locales/zh.ts

@ -6,7 +6,8 @@ export default { @@ -6,7 +6,8 @@ export default {
Post: '发布笔记',
Home: '主页',
Feed: 'Feed',
'Favorites Feed': 'Favorites Feed',
'Favorite Relays': '收藏的服务器',
'All favorite relays': '所有收藏服务器',
'Pinned note': 'Pinned note',
'Relay settings': '服务器设置',
Settings: '设置',
@ -418,7 +419,6 @@ export default { @@ -418,7 +419,6 @@ export default {
'Searched {{count}} external relays; the note was still not found.',
'no more replies': '没有更多回复了',
'Relay sets': '服务器组',
'Favorite Relays': '收藏的服务器',
'Search for Relays': 'Search for Relays',
'Using app default relays': 'Using app default relays',
"Following's Favorites": '关注人的收藏',
@ -888,7 +888,6 @@ export default { @@ -888,7 +888,6 @@ export default {
'Adding…': 'Adding…',
'Advanced Options': 'Advanced Options',
'All Topics': 'All Topics',
'All favorite relays': 'All favorite relays',
'All feeds from OPML file are already added': 'All feeds from OPML file are already added',
'All items deleted successfully': 'All items deleted successfully',
'Already blocked': 'Already blocked',

34
src/pages/primary/NoteListPage/index.tsx

@ -19,10 +19,12 @@ import React, { @@ -19,10 +19,12 @@ import React, {
useCallback,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState
} from 'react'
import { useTranslation } from 'react-i18next'
import FavoriteRelaysFeedPicker from '@/components/FavoriteRelaysFeedPicker'
import HelpAndAccountMenu from '@/components/HelpAndAccountMenu'
import FollowingFeed from './FollowingFeed'
import RelaysFeed from './RelaysFeed'
@ -146,6 +148,34 @@ const NoteListPage = forwardRef<TPageRef>((_, ref) => { @@ -146,6 +148,34 @@ const NoteListPage = forwardRef<TPageRef>((_, ref) => {
)
}
const showFavoriteRelaysPicker =
isReady &&
(feedInfo.feedType === 'all-favorites' ||
feedInfo.feedType === 'relay' ||
feedInfo.feedType === 'relays')
const feedPageTitle = useMemo(
() =>
feedInfo.feedType === 'following'
? t('Following')
: feedInfo.feedType === 'bookmarks'
? t('Bookmarks')
: feedInfo.feedType === 'relays'
? t('relayType_relay_set')
: t('Favorite Relays'),
[feedInfo.feedType, t]
)
const subHeader = (
<>
<div className="w-full min-w-0 border-b border-border/80 bg-background px-3 py-2 sm:px-4">
<h1 className="text-lg font-semibold leading-tight tracking-tight">{feedPageTitle}</h1>
</div>
{showFavoriteRelaysPicker ? <FavoriteRelaysFeedPicker /> : null}
{homeSubHeader}
</>
)
return (
<PrimaryPageLayout
pageName="feed"
@ -161,7 +191,7 @@ const NoteListPage = forwardRef<TPageRef>((_, ref) => { @@ -161,7 +191,7 @@ const NoteListPage = forwardRef<TPageRef>((_, ref) => {
}
/>
}
subHeader={homeSubHeader ?? undefined}
subHeader={subHeader}
displayScrollToTopButton
>
<div className="min-w-0 pt-2">
@ -192,6 +222,7 @@ function NoteListPageTitlebar({ @@ -192,6 +222,7 @@ function NoteListPageTitlebar({
const { navigate, current, display } = usePrimaryPage()
const { primaryViewType, setPrimaryNoteView } = usePrimaryNoteView()
const exploreActive = display && current === 'explore' && primaryViewType === null
return (
<div className="relative flex gap-1 items-center h-full justify-between">
<div className="flex min-w-0 flex-1 items-center gap-1 h-full pl-1 sm:pl-3">
@ -214,7 +245,6 @@ function NoteListPageTitlebar({ @@ -214,7 +245,6 @@ function NoteListPageTitlebar({
<Compass />
</Button>
)}
<div className="min-w-0 truncate text-lg font-semibold">{t('Favorites Feed')}</div>
</div>
{isSmallScreen && (
<div className="absolute left-1/2 transform -translate-x-1/2 z-10">

2
src/pages/primary/SpellsPage/index.tsx

@ -29,7 +29,7 @@ import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider' @@ -29,7 +29,7 @@ import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import { useKindFilter } from '@/providers/KindFilterProvider'
import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import client from '@/services/client.service'
import indexedDb from '@/services/indexed-db.service'
import storage from '@/services/local-storage.service'

2
src/pages/secondary/GeneralSettingsPage/index.tsx

@ -16,7 +16,7 @@ import { useContentPolicy } from '@/providers/ContentPolicyProvider' @@ -16,7 +16,7 @@ import { useContentPolicy } from '@/providers/ContentPolicyProvider'
import { useFontSize } from '@/providers/FontSizeProvider'
import { useTheme } from '@/providers/ThemeProvider'
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useUserTrust } from '@/contexts/user-trust-context'
import { TMediaAutoLoadPolicy } from '@/types'
import { SelectValue } from '@radix-ui/react-select'
import { ExternalLink } from 'lucide-react'

2
src/pages/secondary/MuteListPage/index.tsx

@ -8,7 +8,7 @@ import Username from '@/components/Username' @@ -8,7 +8,7 @@ import Username from '@/components/Username'
import { useFetchProfile } from '@/hooks'
import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
import { usePrimaryNoteView } from '@/contexts/primary-note-view-context'
import { useMuteList } from '@/providers/MuteListProvider'
import { useMuteList } from '@/contexts/mute-list-context'
import { useNostr } from '@/providers/NostrProvider'
import { Lock, Unlock } from 'lucide-react'
import { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react'

27
src/providers/MuteListProvider.tsx

@ -6,12 +6,13 @@ import { @@ -6,12 +6,13 @@ import {
removePubkeyFromPTags
} from '@/lib/replaceable-list-latest'
import { getPubkeysFromPTags } from '@/lib/tag'
import { MuteListContext } from '@/contexts/mute-list-context'
import client from '@/services/client.service'
import indexedDb from '@/services/indexed-db.service'
import { kinds } from 'nostr-tools'
import dayjs from 'dayjs'
import { Event } from 'nostr-tools'
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'
import { useCallback, useEffect, useMemo, useState, type ReactNode } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from 'sonner'
import { z } from 'zod'
@ -19,29 +20,7 @@ import { useNostr } from './NostrProvider' @@ -19,29 +20,7 @@ import { useNostr } from './NostrProvider'
import { useFavoriteRelays } from './FavoriteRelaysProvider'
import logger from '@/lib/logger'
type TMuteListContext = {
mutePubkeySet: Set<string>
changing: boolean
getMutePubkeys: () => string[]
getMuteType: (pubkey: string) => 'public' | 'private' | null
mutePubkeyPublicly: (pubkey: string) => Promise<void>
mutePubkeyPrivately: (pubkey: string) => Promise<void>
unmutePubkey: (pubkey: string) => Promise<void>
switchToPublicMute: (pubkey: string) => Promise<void>
switchToPrivateMute: (pubkey: string) => Promise<void>
}
const MuteListContext = createContext<TMuteListContext | undefined>(undefined)
export const useMuteList = () => {
const context = useContext(MuteListContext)
if (!context) {
throw new Error('useMuteList must be used within a MuteListProvider')
}
return context
}
export function MuteListProvider({ children }: { children: React.ReactNode }) {
export function MuteListProvider({ children }: { children: ReactNode }) {
const { t } = useTranslation()
const {
pubkey: accountPubkey,

25
src/providers/UserTrustProvider.tsx

@ -2,32 +2,13 @@ import { replaceableEventService } from '@/services/client.service' @@ -2,32 +2,13 @@ import { replaceableEventService } from '@/services/client.service'
import { getPubkeysFromPTags } from '@/lib/tag'
import { kinds } from 'nostr-tools'
import storage from '@/services/local-storage.service'
import { createContext, useCallback, useContext, useEffect, useState } from 'react'
import { UserTrustContext } from '@/contexts/user-trust-context'
import { type ReactNode, useCallback, useEffect, useState } from 'react'
import { useNostr } from './NostrProvider'
type TUserTrustContext = {
hideUntrustedInteractions: boolean
hideUntrustedNotifications: boolean
hideUntrustedNotes: boolean
updateHideUntrustedInteractions: (hide: boolean) => void
updateHideUntrustedNotifications: (hide: boolean) => void
updateHideUntrustedNotes: (hide: boolean) => void
isUserTrusted: (pubkey: string) => boolean
}
const UserTrustContext = createContext<TUserTrustContext | undefined>(undefined)
export const useUserTrust = () => {
const context = useContext(UserTrustContext)
if (!context) {
throw new Error('useUserTrust must be used within a UserTrustProvider')
}
return context
}
const wotSet = new Set<string>()
export function UserTrustProvider({ children }: { children: React.ReactNode }) {
export function UserTrustProvider({ children }: { children: ReactNode }) {
const { pubkey: currentPubkey } = useNostr()
const [hideUntrustedInteractions, setHideUntrustedInteractions] = useState(() =>
storage.getHideUntrustedInteractions()

Loading…
Cancel
Save