feat: favorite relays (#250)
This commit is contained in:
parent
fab9ff88b5
commit
c739d9d28c
63 changed files with 1081 additions and 982 deletions
|
|
@ -1,67 +1,71 @@
|
|||
import { toRelaySettings } from '@/lib/link'
|
||||
import { simplifyUrl } from '@/lib/url'
|
||||
import { SecondaryPageLink } from '@/PageManager'
|
||||
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
|
||||
import { useFeed } from '@/providers/FeedProvider'
|
||||
import { useNostr } from '@/providers/NostrProvider'
|
||||
import { useRelaySets } from '@/providers/RelaySetsProvider'
|
||||
import { Circle, CircleCheck } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import RelayIcon from '../RelayIcon'
|
||||
import RelaySetCard from '../RelaySetCard'
|
||||
import SaveRelayDropdownMenu from '../SaveRelayDropdownMenu'
|
||||
import { UsersRound } from 'lucide-react'
|
||||
|
||||
export default function FeedSwitcher({ close }: { close?: () => void }) {
|
||||
const { t } = useTranslation()
|
||||
const { feedType, switchFeed, activeRelaySetId, temporaryRelayUrls } = useFeed()
|
||||
const { pubkey } = useNostr()
|
||||
const { relaySets } = useRelaySets()
|
||||
const { relaySets, favoriteRelays } = useFavoriteRelays()
|
||||
const { feedInfo, switchFeed, temporaryRelayUrls } = useFeed()
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{pubkey && (
|
||||
<FeedSwitcherItem
|
||||
itemName={t('Following')}
|
||||
isActive={feedType === 'following'}
|
||||
isActive={feedInfo.feedType === 'following'}
|
||||
onClick={() => {
|
||||
if (!pubkey) return
|
||||
switchFeed('following', { pubkey })
|
||||
close?.()
|
||||
}}
|
||||
/>
|
||||
>
|
||||
<div className="flex gap-2 items-center">
|
||||
<div className="flex justify-center items-center w-6 h-6 shrink-0">
|
||||
<UsersRound className="size-4" />
|
||||
</div>
|
||||
<div>{t('Following')}</div>
|
||||
</div>
|
||||
</FeedSwitcherItem>
|
||||
)}
|
||||
{temporaryRelayUrls.length > 0 && (
|
||||
<FeedSwitcherItem
|
||||
key="temporary"
|
||||
isActive={feedInfo.feedType === 'temporary'}
|
||||
temporary
|
||||
onClick={() => {
|
||||
switchFeed('temporary')
|
||||
close?.()
|
||||
}}
|
||||
controls={<SaveRelayDropdownMenu urls={temporaryRelayUrls} />}
|
||||
>
|
||||
{temporaryRelayUrls.length === 1 ? simplifyUrl(temporaryRelayUrls[0]) : t('Temporary')}
|
||||
</FeedSwitcherItem>
|
||||
)}
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between px-2">
|
||||
<div className="text-muted-foreground text-sm font-semibold">{t('relay sets')}</div>
|
||||
<div className="flex justify-end items-center text-sm">
|
||||
<SecondaryPageLink
|
||||
to={toRelaySettings()}
|
||||
className="text-highlight text-sm font-semibold"
|
||||
className="text-highlight font-semibold"
|
||||
onClick={() => close?.()}
|
||||
>
|
||||
{t('edit')}
|
||||
</SecondaryPageLink>
|
||||
</div>
|
||||
{temporaryRelayUrls.length > 0 && (
|
||||
<FeedSwitcherItem
|
||||
key="temporary"
|
||||
itemName={
|
||||
temporaryRelayUrls.length === 1 ? simplifyUrl(temporaryRelayUrls[0]) : t('Temporary')
|
||||
}
|
||||
isActive={feedType === 'temporary'}
|
||||
temporary
|
||||
onClick={() => {
|
||||
switchFeed('temporary')
|
||||
close?.()
|
||||
}}
|
||||
controls={<SaveRelayDropdownMenu urls={temporaryRelayUrls} />}
|
||||
/>
|
||||
)}
|
||||
{relaySets
|
||||
.filter((set) => set.relayUrls.length > 0)
|
||||
.map((set) => (
|
||||
<RelaySetCard
|
||||
key={set.id}
|
||||
relaySet={set}
|
||||
select={feedType === 'relays' && set.id === activeRelaySetId}
|
||||
showConnectionStatus={feedType === 'relays' && set.id === activeRelaySetId}
|
||||
select={feedInfo.feedType === 'relays' && set.id === feedInfo.id}
|
||||
onSelectChange={(select) => {
|
||||
if (!select) return
|
||||
switchFeed('relays', { activeRelaySetId: set.id })
|
||||
|
|
@ -69,19 +73,34 @@ export default function FeedSwitcher({ close }: { close?: () => void }) {
|
|||
}}
|
||||
/>
|
||||
))}
|
||||
{favoriteRelays.map((relay) => (
|
||||
<FeedSwitcherItem
|
||||
key={relay}
|
||||
isActive={feedInfo.feedType === 'relay' && feedInfo.id === relay}
|
||||
onClick={() => {
|
||||
switchFeed('relay', { relay })
|
||||
close?.()
|
||||
}}
|
||||
>
|
||||
<div className="flex gap-2 items-center w-full">
|
||||
<RelayIcon url={relay} />
|
||||
<div className="flex-1 w-0 truncate">{simplifyUrl(relay)}</div>
|
||||
</div>
|
||||
</FeedSwitcherItem>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FeedSwitcherItem({
|
||||
itemName,
|
||||
children,
|
||||
isActive,
|
||||
temporary = false,
|
||||
onClick,
|
||||
controls
|
||||
}: {
|
||||
itemName: string
|
||||
children: React.ReactNode
|
||||
isActive: boolean
|
||||
temporary?: boolean
|
||||
onClick: () => void
|
||||
|
|
@ -93,20 +112,9 @@ function FeedSwitcherItem({
|
|||
onClick={onClick}
|
||||
>
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex gap-2 items-center">
|
||||
<FeedToggle isActive={isActive} />
|
||||
<div className="font-semibold">{itemName}</div>
|
||||
</div>
|
||||
<div className="font-semibold flex-1">{children}</div>
|
||||
{controls}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function FeedToggle({ isActive }: { isActive: boolean }) {
|
||||
return isActive ? (
|
||||
<CircleCheck size={18} className="text-highlight shrink-0" />
|
||||
) : (
|
||||
<Circle size={18} className="text-muted-foreground shrink-0" />
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue