/* * Copyright (c) 2021 - 2023, Ludvig Lundgren and the autobrr contributors. * SPDX-License-Identifier: GPL-2.0-or-later */ import { useState, useMemo } from "react"; import { useQuery } from "@tanstack/react-query"; import { Switch } from "@headlessui/react"; import { IndexerAddForm, IndexerUpdateForm } from "@forms"; import { useToggle } from "@hooks/hooks"; import { classNames } from "@utils"; import { EmptySimple } from "@components/emptystates"; import { APIClient } from "@api/APIClient"; import { componentMapType } from "@forms/settings/DownloadClientForms"; export const indexerKeys = { all: ["indexers"] as const, lists: () => [...indexerKeys.all, "list"] as const, // list: (indexers: string[], sortOrder: string) => [...indexerKeys.lists(), { indexers, sortOrder }] as const, details: () => [...indexerKeys.all, "detail"] as const, detail: (id: number) => [...indexerKeys.details(), id] as const }; interface SortConfig { key: keyof ListItemProps["indexer"] | "enabled"; direction: "ascending" | "descending"; } function useSort(items: ListItemProps["indexer"][], config?: SortConfig) { const [sortConfig, setSortConfig] = useState(config); const sortedItems = useMemo(() => { if (!sortConfig) { return items; } const sortableItems = [...items]; sortableItems.sort((a, b) => { const aValue = sortConfig.key === "enabled" ? (a[sortConfig.key] ?? false) as number | boolean | string : a[sortConfig.key] as number | boolean | string; const bValue = sortConfig.key === "enabled" ? (b[sortConfig.key] ?? false) as number | boolean | string : b[sortConfig.key] as number | boolean | string; if (aValue < bValue) { return sortConfig.direction === "ascending" ? -1 : 1; } if (aValue > bValue) { return sortConfig.direction === "ascending" ? 1 : -1; } return 0; }); return sortableItems; }, [items, sortConfig]); const requestSort = (key: keyof ListItemProps["indexer"]) => { let direction: "ascending" | "descending" = "ascending"; if ( sortConfig && sortConfig.key === key && sortConfig.direction === "ascending" ) { direction = "descending"; } setSortConfig({ key, direction }); }; const getSortIndicator = (key: keyof ListItemProps["indexer"]) => { if (!sortConfig || sortConfig.key !== key) { return ""; } return sortConfig.direction === "ascending" ? "↑" : "↓"; }; return { items: sortedItems, requestSort, sortConfig, getSortIndicator }; } const ImplementationBadgeIRC = () => ( IRC ); const ImplementationBadgeTorznab = () => ( Torznab ); const ImplementationBadgeNewznab = () => ( Newznab ); const ImplementationBadgeRSS = () => ( RSS ); export const ImplementationBadges: componentMapType = { irc: , torznab: , newznab: , rss: }; interface ListItemProps { indexer: IndexerDefinition; } const ListItem = ({ indexer }: ListItemProps) => { const [updateIsOpen, toggleUpdate] = useToggle(false); return (
  • Enable
    {indexer.name}
    {ImplementationBadges[indexer.implementation]}
    Edit
  • ); }; function IndexerSettings() { const [addIndexerIsOpen, toggleAddIndexer] = useToggle(false); const { error, data } = useQuery({ queryKey: indexerKeys.lists(), queryFn: APIClient.indexers.getAll, refetchOnWindowFocus: false }); const sortedIndexers = useSort(data || []); if (error) { return (

    An error has occurred

    ); } return (

    Indexers

    Indexer settings for IRC, RSS, Newznab, and Torznab based indexers.
    Generic feeds can be added here by selecting the Generic indexer.

    {data && data.length > 0 ? (
    1. sortedIndexers.requestSort("enabled")} > Enabled {sortedIndexers.getSortIndicator("enabled")}
      sortedIndexers.requestSort("name")} > Name {sortedIndexers.getSortIndicator("name")}
      sortedIndexers.requestSort("implementation")} > Implementation {sortedIndexers.getSortIndicator("implementation")}
    2. {sortedIndexers.items.map((indexer, idx) => ( ))}
    ) : ( )}
    ); } export default IndexerSettings;