From c11fc56209c12d6bc3f899f0c490166a5860d5c1 Mon Sep 17 00:00:00 2001 From: codytseng Date: Sun, 9 Nov 2025 13:28:58 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=F0=9F=92=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/RelayList/index.tsx | 91 ------------------------ src/services/relay-info.service.ts | 109 ++++++----------------------- 2 files changed, 23 insertions(+), 177 deletions(-) delete mode 100644 src/components/RelayList/index.tsx diff --git a/src/components/RelayList/index.tsx b/src/components/RelayList/index.tsx deleted file mode 100644 index 731fa1c9..00000000 --- a/src/components/RelayList/index.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { usePrimaryPage } from '@/PageManager' -import relayInfoService from '@/services/relay-info.service' -import { TRelayInfo } from '@/types' -import { useEffect, useRef, useState } from 'react' -import { useTranslation } from 'react-i18next' -import RelaySimpleInfo, { RelaySimpleInfoSkeleton } from '../RelaySimpleInfo' -import SearchInput from '../SearchInput' - -export default function RelayList() { - const { t } = useTranslation() - const { navigate } = usePrimaryPage() - const [loading, setLoading] = useState(true) - const [relays, setRelays] = useState([]) - const [showCount, setShowCount] = useState(20) - const [input, setInput] = useState('') - const [debouncedInput, setDebouncedInput] = useState(input) - const bottomRef = useRef(null) - - useEffect(() => { - const search = async () => { - const relayInfos = await relayInfoService.search(debouncedInput) - setShowCount(20) - setRelays(relayInfos) - setLoading(false) - } - search() - }, [debouncedInput]) - - useEffect(() => { - const handler = setTimeout(() => { - setDebouncedInput(input) - }, 1000) - - return () => { - clearTimeout(handler) - } - }, [input]) - - useEffect(() => { - const options = { - root: null, - rootMargin: '10px', - threshold: 1 - } - - const observerInstance = new IntersectionObserver((entries) => { - if (entries[0].isIntersecting && showCount < relays.length) { - setShowCount((prev) => prev + 20) - } - }, options) - - const currentBottomRef = bottomRef.current - if (currentBottomRef) { - observerInstance.observe(currentBottomRef) - } - - return () => { - if (observerInstance && currentBottomRef) { - observerInstance.unobserve(currentBottomRef) - } - } - }, [showCount, relays]) - - const handleInputChange = (e: React.ChangeEvent) => { - setInput(e.target.value) - } - - return ( -
-
- -
- {relays.slice(0, showCount).map((relay) => ( - { - e.stopPropagation() - navigate('relay', { url: relay.url }) - }} - /> - ))} - {showCount < relays.length &&
} - {loading && } - {!loading && relays.length === 0 && ( -
{t('no relays found')}
- )} -
- ) -} diff --git a/src/services/relay-info.service.ts b/src/services/relay-info.service.ts index 2a4091f2..f451b869 100644 --- a/src/services/relay-info.service.ts +++ b/src/services/relay-info.service.ts @@ -2,7 +2,6 @@ import { simplifyUrl } from '@/lib/url' import indexDb from '@/services/indexed-db.service' import { TAwesomeRelayCollection, TRelayInfo } from '@/types' import DataLoader from 'dataloader' -import FlexSearch from 'flexsearch' class RelayInfoService { static instance: RelayInfoService @@ -14,19 +13,7 @@ class RelayInfoService { return RelayInfoService.instance } - private initPromise: Promise | null = null private awesomeRelayCollections: Promise | null = null - private relayInfoMap = new Map() - private relayInfoIndex = new FlexSearch.Index({ - tokenize: 'forward', - encode: (str) => - str - // eslint-disable-next-line no-control-regex - .replace(/[^\x00-\x7F]/g, (match) => ` ${match} `) - .trim() - .toLocaleLowerCase() - .split(/\s+/) - }) private fetchDataloader = new DataLoader( async (urls) => { const results = await Promise.allSettled(urls.map((url) => this._getRelayInfo(url))) @@ -34,25 +21,6 @@ class RelayInfoService { }, { maxBatchSize: 1 } ) - private relayUrlsForRandom: string[] = [] - - async search(query: string) { - if (this.initPromise) { - await this.initPromise - } - - if (!query) { - const arr = Array.from(this.relayInfoMap.values()) - for (let i = arr.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)) - ;[arr[i], arr[j]] = [arr[j], arr[i]] - } - return arr - } - - const result = await this.relayInfoIndex.searchAsync(query) - return result.map((url) => this.relayInfoMap.get(url as string)).filter(Boolean) as TRelayInfo[] - } async getRelayInfos(urls: string[]) { if (urls.length === 0) { @@ -66,28 +34,6 @@ class RelayInfoService { return this.fetchDataloader.load(url) } - async getRandomRelayInfos(count: number) { - if (this.initPromise) { - await this.initPromise - } - - const relayInfos: TRelayInfo[] = [] - while (relayInfos.length < count) { - const randomIndex = Math.floor(Math.random() * this.relayUrlsForRandom.length) - const url = this.relayUrlsForRandom[randomIndex] - this.relayUrlsForRandom.splice(randomIndex, 1) - if (this.relayUrlsForRandom.length === 0) { - this.relayUrlsForRandom = Array.from(this.relayInfoMap.keys()) - } - - const relayInfo = this.relayInfoMap.get(url) - if (relayInfo) { - relayInfos.push(relayInfo) - } - } - return relayInfos - } - async getAwesomeRelayCollections() { if (this.awesomeRelayCollections) return this.awesomeRelayCollections @@ -111,23 +57,35 @@ class RelayInfoService { } private async _getRelayInfo(url: string) { - const exist = this.relayInfoMap.get(url) - if (exist) { - return exist + const fetchRelayInfo = async (background: boolean) => { + const nip11 = await this.fetchRelayNip11(url) + const relayInfo = { + ...(nip11 ?? {}), + url, + shortUrl: simplifyUrl(url) + } + + if (!Array.isArray(relayInfo.supported_nips)) { + relayInfo.supported_nips = [] + } + + await indexDb.putRelayInfo(relayInfo) + + if (background) { + this.fetchDataloader.clear(url) + this.fetchDataloader.prime(url, relayInfo) + } + + return relayInfo } const storedRelayInfo = await indexDb.getRelayInfo(url) if (storedRelayInfo) { - return await this.addRelayInfo(storedRelayInfo) + fetchRelayInfo(true) // Update in background + return storedRelayInfo } - const nip11 = await this.fetchRelayNip11(url) - const relayInfo = { - ...(nip11 ?? {}), - url, - shortUrl: simplifyUrl(url) - } - return await this.addRelayInfo(relayInfo) + return fetchRelayInfo(false) } private async fetchRelayNip11(url: string) { @@ -141,27 +99,6 @@ class RelayInfoService { return undefined } } - - private async addRelayInfo(relayInfo: TRelayInfo) { - if (!Array.isArray(relayInfo.supported_nips)) { - relayInfo.supported_nips = [] - } - - this.relayInfoMap.set(relayInfo.url, relayInfo) - await Promise.allSettled([ - this.relayInfoIndex.addAsync( - relayInfo.url, - [ - relayInfo.shortUrl, - ...relayInfo.shortUrl.split('.'), - relayInfo.name ?? '', - relayInfo.description ?? '' - ].join(' ') - ), - indexDb.putRelayInfo(relayInfo) - ]) - return relayInfo - } } const instance = RelayInfoService.getInstance()