diff --git a/src/components/NoteList/index.tsx b/src/components/NoteList/index.tsx index c4d0a734..710bcf7e 100644 --- a/src/components/NoteList/index.tsx +++ b/src/components/NoteList/index.tsx @@ -240,13 +240,13 @@ function ListModeSwitch({ setListMode: (listMode: TNoteListMode) => void }) { const { t } = useTranslation() - const { deepBrowsing } = useDeepBrowsing() + const { deepBrowsing, lastScrollTop } = useDeepBrowsing() return (
800 ? '-translate-y-[calc(100%+12rem)]' : '' )} >
diff --git a/src/components/RelayInfo/index.tsx b/src/components/RelayInfo/index.tsx index 30a8c68f..6d12802f 100644 --- a/src/components/RelayInfo/index.tsx +++ b/src/components/RelayInfo/index.tsx @@ -80,7 +80,7 @@ function formatSoftware(software: string) { return parts[parts.length - 1] } -function RelayBadges({ relayInfo }: { relayInfo: TRelayInfo }) { +export function RelayBadges({ relayInfo }: { relayInfo: TRelayInfo }) { return (
{relayInfo.supported_nips?.includes(42) && ( diff --git a/src/components/SearchDialog/index.tsx b/src/components/SearchDialog/index.tsx index 2499ed25..c1faba17 100644 --- a/src/components/SearchDialog/index.tsx +++ b/src/components/SearchDialog/index.tsx @@ -2,10 +2,11 @@ import { SecondaryPageLink } from '@/PageManager' import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' import { CommandDialog, CommandInput, CommandItem, CommandList } from '@/components/ui/command' import { useSearchProfiles } from '@/hooks' -import { toNote, toNoteList, toProfile, toProfileList } from '@/lib/link' +import { toNote, toNoteList, toProfile, toProfileList, toRelay } from '@/lib/link' import { generateImageByPubkey } from '@/lib/pubkey' +import { normalizeUrl } from '@/lib/url' import { TProfile } from '@/types' -import { Hash, Notebook, UserRound } from 'lucide-react' +import { Hash, Notebook, Server, UserRound } from 'lucide-react' import { nip19 } from 'nostr-tools' import { Dispatch, useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -15,6 +16,13 @@ export function SearchDialog({ open, setOpen }: { open: boolean; setOpen: Dispat const [input, setInput] = useState('') const [debouncedInput, setDebouncedInput] = useState(input) const { profiles } = useSearchProfiles(debouncedInput, 10) + const normalizedUrl = useMemo(() => { + try { + return normalizeUrl(debouncedInput) + } catch { + return undefined + } + }, [debouncedInput]) const list = useMemo(() => { const search = input.trim() @@ -47,6 +55,7 @@ export function SearchDialog({ open, setOpen }: { open: boolean; setOpen: Dispat return ( <> + {!!normalizedUrl && setOpen(false)} />} setOpen(false)} /> setOpen(false)} /> {profiles.map((profile) => ( @@ -61,7 +70,7 @@ export function SearchDialog({ open, setOpen }: { open: boolean; setOpen: Dispat )} ) - }, [input, profiles, setOpen]) + }, [input, debouncedInput, profiles, setOpen]) useEffect(() => { const handler = setTimeout(() => { @@ -146,3 +155,14 @@ function ProfileItem({ profile, onClick }: { profile: TProfile; onClick?: () => ) } + +function RelayItem({ url, onClick }: { url: string; onClick?: () => void }) { + return ( + + + +
{url}
+
+
+ ) +} diff --git a/src/hooks/useFetchRelayInfo.tsx b/src/hooks/useFetchRelayInfo.tsx index b515eca8..cb09cd70 100644 --- a/src/hooks/useFetchRelayInfo.tsx +++ b/src/hooks/useFetchRelayInfo.tsx @@ -2,11 +2,12 @@ import client from '@/services/client.service' import { TRelayInfo } from '@/types' import { useEffect, useState } from 'react' -export function useFetchRelayInfo(url: string) { +export function useFetchRelayInfo(url?: string) { const [isFetching, setIsFetching] = useState(true) const [relayInfo, setRelayInfo] = useState(undefined) useEffect(() => { + if (!url) return const fetchRelayInfos = async () => { setIsFetching(true) const timer = setTimeout(() => { diff --git a/src/providers/DeepBrowsingProvider.tsx b/src/providers/DeepBrowsingProvider.tsx index 8348f233..d6951b8f 100644 --- a/src/providers/DeepBrowsingProvider.tsx +++ b/src/providers/DeepBrowsingProvider.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext, useEffect, useState } from 'react' +import { createContext, useContext, useEffect, useRef, useState } from 'react' type TDeepBrowsingContext = { deepBrowsing: boolean @@ -25,9 +25,12 @@ export function DeepBrowsingProvider({ scrollAreaRef?: React.RefObject }) { const [deepBrowsing, setDeepBrowsing] = useState(false) - const [lastScrollTop, setLastScrollTop] = useState(0) + const lastScrollTopRef = useRef( + (!scrollAreaRef ? window.scrollY : scrollAreaRef.current?.scrollTop) || 0 + ) useEffect(() => { + setDeepBrowsing(false) if (!active) return const handleScroll = () => { @@ -43,19 +46,17 @@ export function DeepBrowsingProvider({ } const scrollTop = (!scrollAreaRef ? window.scrollY : scrollAreaRef.current?.scrollTop) || 0 - const diff = scrollTop - lastScrollTop + const diff = scrollTop - lastScrollTopRef.current + lastScrollTopRef.current = scrollTop if (scrollTop <= 800) { setDeepBrowsing(false) - setLastScrollTop(scrollTop) return } if (diff > 20) { setDeepBrowsing(true) - setLastScrollTop(scrollTop) } else if (diff < -20) { setDeepBrowsing(false) - setLastScrollTop(scrollTop) } } @@ -70,10 +71,10 @@ export function DeepBrowsingProvider({ return () => { scrollAreaRef.current?.removeEventListener('scroll', handleScroll) } - }, [lastScrollTop, active]) + }, [active]) return ( - + {children} )