diff --git a/src/components/FeedSwitcher/index.tsx b/src/components/FeedSwitcher/index.tsx index 055fc3e4..eac0e09f 100644 --- a/src/components/FeedSwitcher/index.tsx +++ b/src/components/FeedSwitcher/index.tsx @@ -6,7 +6,8 @@ import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider' import { useFeed } from '@/providers/FeedProvider' import { useNostr } from '@/providers/NostrProvider' import { usePinnedUsers } from '@/providers/PinnedUsersProvider' -import { Star, UsersRound } from 'lucide-react' +import { Settings2, Star, UsersRound } from 'lucide-react' +import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import RelayIcon from '../RelayIcon' import RelaySetCard from '../RelaySetCard' @@ -17,81 +18,112 @@ export default function FeedSwitcher({ close }: { close?: () => void }) { const { relaySets, favoriteRelays } = useFavoriteRelays() const { feedInfo, switchFeed } = useFeed() const { pinnedPubkeySet } = usePinnedUsers() + const filteredRelaySets = useMemo( + () => relaySets.filter((set) => set.relayUrls.length > 0), + [relaySets] + ) + const hasRelays = filteredRelaySets.length > 0 || favoriteRelays.length > 0 return ( -
- { - if (!pubkey) return - switchFeed('following', { pubkey }) - close?.() - }} - > -
-
- -
-
{t('Following')}
-
-
- - { - if (!pubkey) return - switchFeed('pinned', { pubkey }) - close?.() - }} - > -
-
- -
-
{t('Special Follow')}
-
-
- -
- close?.()} - > - {t('edit')} - -
- {relaySets - .filter((set) => set.relayUrls.length > 0) - .map((set) => ( - { - if (!select) return - switchFeed('relays', { activeRelaySetId: set.id }) +
+ {/* Personal Feeds Section */} +
+ +
+ { + if (!pubkey) return + switchFeed('following', { pubkey }) close?.() }} + > +
+
+ +
+
{t('Following')}
+
+
+ + { + if (!pubkey) return + switchFeed('pinned', { pubkey }) + close?.() + }} + > +
+
+ +
+
{t('Special Follow')}
+
+
+
+
+ + {/* Relay Feeds Section */} + {hasRelays && ( +
+ close?.()} + > + + {t('edit')} + + } /> - ))} - {favoriteRelays.map((relay) => ( - { - switchFeed('relay', { relay }) - close?.() - }} - > -
- -
{simplifyUrl(relay)}
+
+ {filteredRelaySets.map((set) => ( + { + if (!select) return + switchFeed('relays', { activeRelaySetId: set.id }) + close?.() + }} + /> + ))} + {favoriteRelays.map((relay) => ( + { + switchFeed('relay', { relay }) + close?.() + }} + > +
+ +
{simplifyUrl(relay)}
+
+
+ ))}
- - ))} +
+ )} +
+ ) +} + +function SectionHeader({ title, action }: { title: string; action?: React.ReactNode }) { + return ( +
+

+ {title} +

+ {action}
) } @@ -100,30 +132,29 @@ function FeedSwitcherItem({ children, isActive, disabled, - onClick, - controls + onClick }: { children: React.ReactNode isActive: boolean disabled?: boolean onClick: () => void - controls?: React.ReactNode }) { return (
{ if (disabled) return onClick() }} > -
-
{children}
- {controls} +
+
{children}
) diff --git a/src/components/MailboxSetting/MailboxRelay.tsx b/src/components/MailboxSetting/MailboxRelay.tsx index 8854ce16..8caab1ea 100644 --- a/src/components/MailboxSetting/MailboxRelay.tsx +++ b/src/components/MailboxSetting/MailboxRelay.tsx @@ -52,7 +52,7 @@ export default function MailboxRelay({ onClick={() => push(toRelay(mailboxRelay.url))} > -
{mailboxRelay.url}
+
{mailboxRelay.url}
diff --git a/src/components/RelayIcon/index.tsx b/src/components/RelayIcon/index.tsx index e0df1010..e3eddb39 100644 --- a/src/components/RelayIcon/index.tsx +++ b/src/components/RelayIcon/index.tsx @@ -1,17 +1,19 @@ -import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' import { useFetchRelayInfo } from '@/hooks' import { cn } from '@/lib/utils' import { Server } from 'lucide-react' import { useMemo } from 'react' +import Image from '../Image' export default function RelayIcon({ url, className, - iconSize = 14 + classNames }: { url?: string className?: string - iconSize?: number + classNames?: { + fallback?: string + } }) { const { relayInfo } = useFetchRelayInfo(url) const iconUrl = useMemo(() => { @@ -23,12 +25,21 @@ export default function RelayIcon({ return `${u.protocol === 'wss:' ? 'https:' : 'http:'}//${u.host}/favicon.ico` }, [url, relayInfo]) + const fallback = + + if (!iconUrl) { + return fallback + } + return ( - - - - - - + ) } diff --git a/src/components/RelaySetCard/index.tsx b/src/components/RelaySetCard/index.tsx index ae01c75c..a709b72a 100644 --- a/src/components/RelaySetCard/index.tsx +++ b/src/components/RelaySetCard/index.tsx @@ -1,3 +1,4 @@ +import { cn } from '@/lib/utils' import { TRelaySet } from '@/types' import { ChevronDown, FolderClosed } from 'lucide-react' import { useState } from 'react' @@ -18,17 +19,22 @@ export default function RelaySetCard({ return (
onSelectChange(!select)} > -
-
-
- +
+
+
+
-
{relaySet.name}
+
{relaySet.name}
-
+
{t('n relays', { n: relaySet.relayUrls.length })} @@ -50,16 +56,16 @@ function RelayUrlsExpandToggle({ }) { return (
{ e.stopPropagation() onExpandChange(!expand) }} > -
{children}
+
{children}
) @@ -69,11 +75,11 @@ function RelayUrls({ urls }: { urls: string[] }) { if (!urls) return null return ( -
+
{urls.map((url) => ( -
- -
{url}
+
+ +
{url}
))}
diff --git a/src/i18n/locales/ar.ts b/src/i18n/locales/ar.ts index 950544e0..31822ab5 100644 --- a/src/i18n/locales/ar.ts +++ b/src/i18n/locales/ar.ts @@ -581,6 +581,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'متابعة خاصة', - 'Unfollow Special': 'إلغاء المتابعة الخاصة' + 'Unfollow Special': 'إلغاء المتابعة الخاصة', + 'Personal Feeds': 'التدفقات الشخصية', + 'Relay Feeds': 'تدفقات الترحيل' } } diff --git a/src/i18n/locales/de.ts b/src/i18n/locales/de.ts index 16006329..ae72aa7b 100644 --- a/src/i18n/locales/de.ts +++ b/src/i18n/locales/de.ts @@ -597,6 +597,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'Besonders Folgen', - 'Unfollow Special': 'Besonders Entfolgen' + 'Unfollow Special': 'Besonders Entfolgen', + 'Personal Feeds': 'Persönliche Feeds', + 'Relay Feeds': 'Relay-Feeds' } } diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index ce64f2a4..31f36bfc 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -584,6 +584,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'Special Follow', - 'Unfollow Special': 'Unfollow Special' + 'Unfollow Special': 'Unfollow Special', + 'Personal Feeds': 'Personal Feeds', + 'Relay Feeds': 'Relay Feeds' } } diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts index a4d4939b..5674ccaf 100644 --- a/src/i18n/locales/es.ts +++ b/src/i18n/locales/es.ts @@ -593,6 +593,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'Seguir Especial', - 'Unfollow Special': 'Dejar de Seguir Especial' + 'Unfollow Special': 'Dejar de Seguir Especial', + 'Personal Feeds': 'Feeds Personales', + 'Relay Feeds': 'Feeds de Relays' } } diff --git a/src/i18n/locales/fa.ts b/src/i18n/locales/fa.ts index 352b5463..52dcde24 100644 --- a/src/i18n/locales/fa.ts +++ b/src/i18n/locales/fa.ts @@ -587,6 +587,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'دنبال کردن ویژه', - 'Unfollow Special': 'لغو دنبال کردن ویژه' + 'Unfollow Special': 'لغو دنبال کردن ویژه', + 'Personal Feeds': 'فیدهای شخصی', + 'Relay Feeds': 'فیدهای رله' } } diff --git a/src/i18n/locales/fr.ts b/src/i18n/locales/fr.ts index 834bba50..242e4bcd 100644 --- a/src/i18n/locales/fr.ts +++ b/src/i18n/locales/fr.ts @@ -596,6 +596,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'Suivre Spécial', - 'Unfollow Special': 'Ne Plus Suivre Spécial' + 'Unfollow Special': 'Ne Plus Suivre Spécial', + 'Personal Feeds': 'Flux Personnels', + 'Relay Feeds': 'Flux de Relais' } } diff --git a/src/i18n/locales/hi.ts b/src/i18n/locales/hi.ts index 668b5e52..cccd7ee3 100644 --- a/src/i18n/locales/hi.ts +++ b/src/i18n/locales/hi.ts @@ -588,6 +588,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'विशेष फ़ॉलो', - 'Unfollow Special': 'विशेष अनफ़ॉलो' + 'Unfollow Special': 'विशेष अनफ़ॉलो', + 'Personal Feeds': 'व्यक्तिगत फ़ीड', + 'Relay Feeds': 'रिले फ़ीड' } } diff --git a/src/i18n/locales/hu.ts b/src/i18n/locales/hu.ts index bdadedc0..c2f94a5f 100644 --- a/src/i18n/locales/hu.ts +++ b/src/i18n/locales/hu.ts @@ -582,6 +582,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'Különleges Követés', - 'Unfollow Special': 'Különleges Követés Megszüntetése' + 'Unfollow Special': 'Különleges Követés Megszüntetése', + 'Personal Feeds': 'Személyes Feedek', + 'Relay Feeds': 'Relay Feedek' } } diff --git a/src/i18n/locales/it.ts b/src/i18n/locales/it.ts index c7cbe072..38ff9112 100644 --- a/src/i18n/locales/it.ts +++ b/src/i18n/locales/it.ts @@ -592,6 +592,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'Segui Speciale', - 'Unfollow Special': 'Smetti di Seguire Speciale' + 'Unfollow Special': 'Smetti di Seguire Speciale', + 'Personal Feeds': 'Feed Personali', + 'Relay Feeds': 'Feed di Relay' } } diff --git a/src/i18n/locales/ja.ts b/src/i18n/locales/ja.ts index fcd31df5..09456bd5 100644 --- a/src/i18n/locales/ja.ts +++ b/src/i18n/locales/ja.ts @@ -587,6 +587,8 @@ export default { 'Show directly': '直接表示', 'Click to view': 'クリックして表示', 'Special Follow': '特別フォロー', - 'Unfollow Special': '特別フォロー解除' + 'Unfollow Special': '特別フォロー解除', + 'Personal Feeds': '個人フィード', + 'Relay Feeds': 'リレーフィード' } } diff --git a/src/i18n/locales/ko.ts b/src/i18n/locales/ko.ts index 96464b6d..d6e5644f 100644 --- a/src/i18n/locales/ko.ts +++ b/src/i18n/locales/ko.ts @@ -586,6 +586,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': '특별 팔로우', - 'Unfollow Special': '특별 팔로우 해제' + 'Unfollow Special': '특별 팔로우 해제', + 'Personal Feeds': '개인 피드', + 'Relay Feeds': '릴레이 피드' } } diff --git a/src/i18n/locales/pl.ts b/src/i18n/locales/pl.ts index 397d2d78..7b359c2f 100644 --- a/src/i18n/locales/pl.ts +++ b/src/i18n/locales/pl.ts @@ -593,6 +593,8 @@ export default { 'Show directly': 'Pokaż bezpośrednio', 'Click to view': 'Wyświetl', 'Special Follow': 'Specjalne Śledzenie', - 'Unfollow Special': 'Cofnij Specjalne Śledzenie' + 'Unfollow Special': 'Cofnij Specjalne Śledzenie', + 'Personal Feeds': 'Osobiste Kanały', + 'Relay Feeds': 'Kanały Przekaźników' } } diff --git a/src/i18n/locales/pt-BR.ts b/src/i18n/locales/pt-BR.ts index eb9ae947..140804da 100644 --- a/src/i18n/locales/pt-BR.ts +++ b/src/i18n/locales/pt-BR.ts @@ -588,6 +588,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'Seguir Especial', - 'Unfollow Special': 'Deixar de Seguir Especial' + 'Unfollow Special': 'Deixar de Seguir Especial', + 'Personal Feeds': 'Feeds Pessoais', + 'Relay Feeds': 'Feeds de Relays' } } diff --git a/src/i18n/locales/pt-PT.ts b/src/i18n/locales/pt-PT.ts index 46b982b0..f732aab8 100644 --- a/src/i18n/locales/pt-PT.ts +++ b/src/i18n/locales/pt-PT.ts @@ -591,6 +591,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'Seguir Especial', - 'Unfollow Special': 'Deixar de Seguir Especial' + 'Unfollow Special': 'Deixar de Seguir Especial', + 'Personal Feeds': 'Feeds Pessoais', + 'Relay Feeds': 'Feeds de Relays' } } diff --git a/src/i18n/locales/ru.ts b/src/i18n/locales/ru.ts index f80f9818..ff173676 100644 --- a/src/i18n/locales/ru.ts +++ b/src/i18n/locales/ru.ts @@ -593,6 +593,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'Особая Подписка', - 'Unfollow Special': 'Отменить Особую Подписку' + 'Unfollow Special': 'Отменить Особую Подписку', + 'Personal Feeds': 'Личные Ленты', + 'Relay Feeds': 'Ленты Релеев' } } diff --git a/src/i18n/locales/th.ts b/src/i18n/locales/th.ts index ab35b77b..e0318514 100644 --- a/src/i18n/locales/th.ts +++ b/src/i18n/locales/th.ts @@ -580,6 +580,8 @@ export default { 'Show directly': 'Show directly', 'Click to view': 'Click to view', 'Special Follow': 'ติดตามพิเศษ', - 'Unfollow Special': 'ยกเลิกติดตามพิเศษ' + 'Unfollow Special': 'ยกเลิกติดตามพิเศษ', + 'Personal Feeds': 'ฟีดส่วนตัว', + 'Relay Feeds': 'ฟีดรีเลย์' } } diff --git a/src/i18n/locales/zh.ts b/src/i18n/locales/zh.ts index b363094a..308b8c0c 100644 --- a/src/i18n/locales/zh.ts +++ b/src/i18n/locales/zh.ts @@ -573,6 +573,8 @@ export default { 'Show directly': '直接显示', 'Click to view': '点击查看', 'Special Follow': '特别关注', - 'Unfollow Special': '取消特别关注' + 'Unfollow Special': '取消特别关注', + 'Personal Feeds': '个人订阅', + 'Relay Feeds': '中继订阅' } } diff --git a/src/pages/primary/NoteListPage/FeedButton.tsx b/src/pages/primary/NoteListPage/FeedButton.tsx index a7256052..ef75c555 100644 --- a/src/pages/primary/NoteListPage/FeedButton.tsx +++ b/src/pages/primary/NoteListPage/FeedButton.tsx @@ -1,4 +1,5 @@ import FeedSwitcher from '@/components/FeedSwitcher' +import RelayIcon from '@/components/RelayIcon' import { Drawer, DrawerContent } from '@/components/ui/drawer' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover' import { simplifyUrl } from '@/lib/url' @@ -19,10 +20,13 @@ export default function FeedButton({ className }: { className?: string }) { <> setOpen(true)} /> - +
setOpen(false)} />
@@ -37,12 +41,14 @@ export default function FeedButton({ className }: { className?: string }) { - - setOpen(false)} /> + +
e.stopPropagation()} + onTouchMove={(e) => e.stopPropagation()} + > + setOpen(false)} /> +
) @@ -79,6 +85,10 @@ const FeedSwitcherTrigger = forwardRef { if (feedInfo?.feedType === 'following') return if (feedInfo?.feedType === 'pinned') return + if (feedInfo?.feedType === 'relay' && feedInfo.id) { + return + } + return }, [feedInfo])