fix: 🐛

This commit is contained in:
codytseng
2025-01-26 20:19:18 +08:00
parent 2873b9bdd8
commit 8ef1afc4b9
5 changed files with 37 additions and 15 deletions

View File

@@ -240,13 +240,13 @@ function ListModeSwitch({
setListMode: (listMode: TNoteListMode) => void setListMode: (listMode: TNoteListMode) => void
}) { }) {
const { t } = useTranslation() const { t } = useTranslation()
const { deepBrowsing } = useDeepBrowsing() const { deepBrowsing, lastScrollTop } = useDeepBrowsing()
return ( return (
<div <div
className={cn( className={cn(
'sticky top-12 bg-background z-10 duration-700 transition-transform', 'sticky top-12 bg-background z-10 duration-700 transition-transform',
deepBrowsing ? '-translate-y-[calc(100%+12rem)]' : '' deepBrowsing && lastScrollTop > 800 ? '-translate-y-[calc(100%+12rem)]' : ''
)} )}
> >
<div className="flex"> <div className="flex">

View File

@@ -80,7 +80,7 @@ function formatSoftware(software: string) {
return parts[parts.length - 1] return parts[parts.length - 1]
} }
function RelayBadges({ relayInfo }: { relayInfo: TRelayInfo }) { export function RelayBadges({ relayInfo }: { relayInfo: TRelayInfo }) {
return ( return (
<div className="flex gap-2"> <div className="flex gap-2">
{relayInfo.supported_nips?.includes(42) && ( {relayInfo.supported_nips?.includes(42) && (

View File

@@ -2,10 +2,11 @@ import { SecondaryPageLink } from '@/PageManager'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { CommandDialog, CommandInput, CommandItem, CommandList } from '@/components/ui/command' import { CommandDialog, CommandInput, CommandItem, CommandList } from '@/components/ui/command'
import { useSearchProfiles } from '@/hooks' 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 { generateImageByPubkey } from '@/lib/pubkey'
import { normalizeUrl } from '@/lib/url'
import { TProfile } from '@/types' 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 { nip19 } from 'nostr-tools'
import { Dispatch, useEffect, useMemo, useState } from 'react' import { Dispatch, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
@@ -15,6 +16,13 @@ export function SearchDialog({ open, setOpen }: { open: boolean; setOpen: Dispat
const [input, setInput] = useState('') const [input, setInput] = useState('')
const [debouncedInput, setDebouncedInput] = useState(input) const [debouncedInput, setDebouncedInput] = useState(input)
const { profiles } = useSearchProfiles(debouncedInput, 10) const { profiles } = useSearchProfiles(debouncedInput, 10)
const normalizedUrl = useMemo(() => {
try {
return normalizeUrl(debouncedInput)
} catch {
return undefined
}
}, [debouncedInput])
const list = useMemo(() => { const list = useMemo(() => {
const search = input.trim() const search = input.trim()
@@ -47,6 +55,7 @@ export function SearchDialog({ open, setOpen }: { open: boolean; setOpen: Dispat
return ( return (
<> <>
{!!normalizedUrl && <RelayItem url={normalizedUrl} onClick={() => setOpen(false)} />}
<NormalItem search={search} onClick={() => setOpen(false)} /> <NormalItem search={search} onClick={() => setOpen(false)} />
<HashtagItem search={search} onClick={() => setOpen(false)} /> <HashtagItem search={search} onClick={() => setOpen(false)} />
{profiles.map((profile) => ( {profiles.map((profile) => (
@@ -61,7 +70,7 @@ export function SearchDialog({ open, setOpen }: { open: boolean; setOpen: Dispat
)} )}
</> </>
) )
}, [input, profiles, setOpen]) }, [input, debouncedInput, profiles, setOpen])
useEffect(() => { useEffect(() => {
const handler = setTimeout(() => { const handler = setTimeout(() => {
@@ -146,3 +155,14 @@ function ProfileItem({ profile, onClick }: { profile: TProfile; onClick?: () =>
</SecondaryPageLink> </SecondaryPageLink>
) )
} }
function RelayItem({ url, onClick }: { url: string; onClick?: () => void }) {
return (
<SecondaryPageLink to={toRelay(url)} onClick={onClick}>
<CommandItem>
<Server className="text-muted-foreground" />
<div className="font-semibold truncate">{url}</div>
</CommandItem>
</SecondaryPageLink>
)
}

View File

@@ -2,11 +2,12 @@ import client from '@/services/client.service'
import { TRelayInfo } from '@/types' import { TRelayInfo } from '@/types'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
export function useFetchRelayInfo(url: string) { export function useFetchRelayInfo(url?: string) {
const [isFetching, setIsFetching] = useState(true) const [isFetching, setIsFetching] = useState(true)
const [relayInfo, setRelayInfo] = useState<TRelayInfo | undefined>(undefined) const [relayInfo, setRelayInfo] = useState<TRelayInfo | undefined>(undefined)
useEffect(() => { useEffect(() => {
if (!url) return
const fetchRelayInfos = async () => { const fetchRelayInfos = async () => {
setIsFetching(true) setIsFetching(true)
const timer = setTimeout(() => { const timer = setTimeout(() => {

View File

@@ -1,4 +1,4 @@
import { createContext, useContext, useEffect, useState } from 'react' import { createContext, useContext, useEffect, useRef, useState } from 'react'
type TDeepBrowsingContext = { type TDeepBrowsingContext = {
deepBrowsing: boolean deepBrowsing: boolean
@@ -25,9 +25,12 @@ export function DeepBrowsingProvider({
scrollAreaRef?: React.RefObject<HTMLDivElement> scrollAreaRef?: React.RefObject<HTMLDivElement>
}) { }) {
const [deepBrowsing, setDeepBrowsing] = useState(false) const [deepBrowsing, setDeepBrowsing] = useState(false)
const [lastScrollTop, setLastScrollTop] = useState(0) const lastScrollTopRef = useRef(
(!scrollAreaRef ? window.scrollY : scrollAreaRef.current?.scrollTop) || 0
)
useEffect(() => { useEffect(() => {
setDeepBrowsing(false)
if (!active) return if (!active) return
const handleScroll = () => { const handleScroll = () => {
@@ -43,19 +46,17 @@ export function DeepBrowsingProvider({
} }
const scrollTop = (!scrollAreaRef ? window.scrollY : scrollAreaRef.current?.scrollTop) || 0 const scrollTop = (!scrollAreaRef ? window.scrollY : scrollAreaRef.current?.scrollTop) || 0
const diff = scrollTop - lastScrollTop const diff = scrollTop - lastScrollTopRef.current
lastScrollTopRef.current = scrollTop
if (scrollTop <= 800) { if (scrollTop <= 800) {
setDeepBrowsing(false) setDeepBrowsing(false)
setLastScrollTop(scrollTop)
return return
} }
if (diff > 20) { if (diff > 20) {
setDeepBrowsing(true) setDeepBrowsing(true)
setLastScrollTop(scrollTop)
} else if (diff < -20) { } else if (diff < -20) {
setDeepBrowsing(false) setDeepBrowsing(false)
setLastScrollTop(scrollTop)
} }
} }
@@ -70,10 +71,10 @@ export function DeepBrowsingProvider({
return () => { return () => {
scrollAreaRef.current?.removeEventListener('scroll', handleScroll) scrollAreaRef.current?.removeEventListener('scroll', handleScroll)
} }
}, [lastScrollTop, active]) }, [active])
return ( return (
<DeepBrowsingContext.Provider value={{ deepBrowsing, lastScrollTop }}> <DeepBrowsingContext.Provider value={{ deepBrowsing, lastScrollTop: lastScrollTopRef.current }}>
{children} {children}
</DeepBrowsingContext.Provider> </DeepBrowsingContext.Provider>
) )