import React, { useCallback, useEffect, useState } from "react"; import Translate from "@docusaurus/Translate"; import { usePagination } from "react-use-pagination"; import Admonition from "@theme/Admonition"; import Paginate from "@/components/Paginate"; import ResourceCard from "@/components/Resource/Card"; import Searcher from "@/components/Searcher"; import StoreToolbar, { type Action } from "@/components/Store/Toolbar"; import { authorFilter, tagFilter } from "@/libs/filter"; import { useSearchControl } from "@/libs/search"; import { fetchRegistryData, loadFailedTitle } from "@/libs/store"; import { useToolbar } from "@/libs/toolbar"; import type { Adapter } from "@/types/adapter"; export default function AdapterPage(): JSX.Element { const [adapters, setAdapters] = useState(null); const adapterCount = adapters?.length ?? 0; const loading = adapters === null; const [error, setError] = useState(null); const { filteredResources: filteredAdapters, searcherTags, addFilter, onSearchQueryChange, onSearchQuerySubmit, onSearchBackspace, onSearchClear, onSearchTagClick, } = useSearchControl(adapters ?? []); const filteredAdapterCount = filteredAdapters.length; const { startIndex, endIndex, totalPages, currentPage, setNextPage, setPreviousPage, setPage, previousEnabled, nextEnabled, } = usePagination({ totalItems: filteredAdapters.length, initialPageSize: 12, }); const currentAdapters = filteredAdapters.slice(startIndex, endIndex + 1); // load adapters asynchronously useEffect(() => { fetchRegistryData("adapter") .then(setAdapters) .catch((e) => { setError(e); console.error(e); }); }, []); const { filters: filterTools } = useToolbar({ resources: adapters ?? [], addFilter, }); const actionTool: Action = { label: "发布适配器", icon: ["fas", "plus"], onClick: () => { // TODO: open adapter release modal window.open( "https://github.com/nonebot/nonebot2/issues/new?template=adapter_publish.yml" ); }, }; const onCardClick = useCallback((adapter: Adapter) => { // TODO: open adapter modal console.log(adapter, "clicked"); }, []); const onCardTagClick = useCallback( (tag: string) => { addFilter(tagFilter(tag)); }, [addFilter] ); const onCardAuthorClick = useCallback( (author: string) => { addFilter(authorFilter(author)); }, [addFilter] ); return ( <>

{adapterCount === filteredAdapterCount ? ( {"当前共有 {adapterCount} 个适配器"} ) : ( {"当前共有 {filteredAdapterCount} / {adapterCount} 个插件"} )}

{error ? ( {error.message} ) : loading ? (

) : (
{currentAdapters.map((adapter, index) => ( onCardClick(adapter)} onTagClick={onCardTagClick} onAuthorClick={() => onCardAuthorClick(adapter.author)} /> ))}
)} ); }