From b5b502b4332a430ff835ef8b0d35dbfe84988061 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:40:20 -0800 Subject: [PATCH] Enhancement: use lighter endpoints for qbittorrent (#6388) --- src/widgets/qbittorrent/component.jsx | 51 ++++++++++++---------- src/widgets/qbittorrent/component.test.jsx | 35 +++++++++++---- src/widgets/qbittorrent/widget.js | 8 ++++ 3 files changed, 63 insertions(+), 31 deletions(-) diff --git a/src/widgets/qbittorrent/component.jsx b/src/widgets/qbittorrent/component.jsx index c8f9f6ead..73dfacb5c 100644 --- a/src/widgets/qbittorrent/component.jsx +++ b/src/widgets/qbittorrent/component.jsx @@ -10,13 +10,28 @@ export default function Component({ service }) { const { t } = useTranslation(); const { widget } = service; - const { data: torrentData, error: torrentError } = useWidgetAPI(widget, "torrents"); + const { data: transferData, error: transferError } = useWidgetAPI(widget, "transfer"); + const { data: totalCountData, error: totalCountError } = useWidgetAPI(widget, "torrentCount"); + const { data: completedCountData, error: completedCountError } = useWidgetAPI(widget, "torrentCount", { + filter: "completed", + }); + const { data: leechTorrentData, error: leechTorrentError } = useWidgetAPI( + widget, + widget?.enableLeechProgress ? "torrents" : "", + widget?.enableLeechProgress ? { filter: "downloading" } : undefined, + ); - if (torrentError) { - return ; + const apiError = transferError || totalCountError || completedCountError || leechTorrentError; + if (apiError) { + return ; } - if (!torrentData) { + if ( + !transferData || + totalCountData === undefined || + completedCountData === undefined || + (widget?.enableLeechProgress && !leechTorrentData) + ) { return ( @@ -27,24 +42,15 @@ export default function Component({ service }) { ); } - let rateDl = 0; - let rateUl = 0; - let completed = 0; - const leechTorrents = []; + const rateDl = Number(transferData?.dl_info_speed ?? 0); + const rateUl = Number(transferData?.up_info_speed ?? 0); + const totalCount = Number(totalCountData?.all ?? totalCountData?.count ?? totalCountData ?? 0); + const completedCount = Number( + completedCountData?.completed ?? completedCountData?.count ?? completedCountData?.all ?? completedCountData ?? 0, + ); + const leech = Math.max(0, totalCount - completedCount); - for (let i = 0; i < torrentData.length; i += 1) { - const torrent = torrentData[i]; - rateDl += torrent.dlspeed; - rateUl += torrent.upspeed; - if (torrent.progress === 1) { - completed += 1; - } - if (torrent.state.includes("DL") || torrent.state === "downloading") { - leechTorrents.push(torrent); - } - } - - const leech = torrentData.length - completed; + const leechTorrents = Array.isArray(leechTorrentData) ? [...leechTorrentData] : []; const statePriority = [ "downloading", "forcedDL", @@ -55,7 +61,6 @@ export default function Component({ service }) { "queuedDL", "pausedDL", ]; - leechTorrents.sort((firstTorrent, secondTorrent) => { const firstStateIndex = statePriority.indexOf(firstTorrent.state); const secondStateIndex = statePriority.indexOf(secondTorrent.state); @@ -70,7 +75,7 @@ export default function Component({ service }) { - + {widget?.enableLeechProgress && diff --git a/src/widgets/qbittorrent/component.test.jsx b/src/widgets/qbittorrent/component.test.jsx index a4e222b75..df8ae51c8 100644 --- a/src/widgets/qbittorrent/component.test.jsx +++ b/src/widgets/qbittorrent/component.test.jsx @@ -34,19 +34,38 @@ describe("widgets/qbittorrent/component", () => { expect(screen.getByText("qbittorrent.upload")).toBeInTheDocument(); }); - it("computes leech/seed counts and upload/download rates, and can render leech progress entries", () => { - useWidgetAPI.mockReturnValue({ - data: [ - { name: "A", dlspeed: 10, upspeed: 1, progress: 1, state: "uploading" }, - { name: "B", dlspeed: 5, upspeed: 2, progress: 0.5, state: "downloading", eta: 60, size: 100, amount_left: 50 }, - ], - error: undefined, + it("uses lightweight endpoints for counts/rates and filtered torrents for leech progress", () => { + useWidgetAPI.mockImplementation((_widget, endpoint, query) => { + if (endpoint === "transfer") { + return { data: { dl_info_speed: 15, up_info_speed: 3 }, error: undefined }; + } + if (endpoint === "torrentCount" && !query) { + return { data: 2, error: undefined }; + } + if (endpoint === "torrentCount" && query?.filter === "completed") { + return { data: 1, error: undefined }; + } + if (endpoint === "torrents" && query?.filter === "downloading") { + return { + data: [ + { + name: "B", + progress: 0.5, + state: "downloading", + eta: 60, + size: 100, + amount_left: 50, + }, + ], + error: undefined, + }; + } + return { data: undefined, error: undefined }; }); const service = { widget: { type: "qbittorrent", enableLeechProgress: true } }; const { container } = renderWithProviders(, { settings: { hideErrors: false } }); - // total=2, completed=1 => leech=1 expectBlockValue(container, "qbittorrent.leech", 1); expectBlockValue(container, "qbittorrent.seed", 1); expectBlockValue(container, "qbittorrent.download", 15); diff --git a/src/widgets/qbittorrent/widget.js b/src/widgets/qbittorrent/widget.js index 182ac9d1b..9ec167faf 100644 --- a/src/widgets/qbittorrent/widget.js +++ b/src/widgets/qbittorrent/widget.js @@ -4,8 +4,16 @@ const widget = { proxyHandler: qbittorrentProxyHandler, mappings: { + transfer: { + endpoint: "transfer/info", + }, + torrentCount: { + endpoint: "torrents/count", + optionalParams: ["filter"], + }, torrents: { endpoint: "torrents/info", + optionalParams: ["filter"], }, }, };