diff --git a/src/widgets/qbittorrent/component.jsx b/src/widgets/qbittorrent/component.jsx
index d3836a6ba1a..1b10edeb10e 100644
--- a/src/widgets/qbittorrent/component.jsx
+++ b/src/widgets/qbittorrent/component.jsx
@@ -1,9 +1,106 @@
+import { BsDownload, BsPause, BsUpload, BsExclamationTriangle, BsThreeDots, BsCheckLg } from "react-icons/bs";
import { useTranslation } from "next-i18next";
import Container from "components/services/widget/container";
import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
+function secondsToTime(totalSeconds) {
+ const seconds = Math.floor((totalSeconds) % 60);
+ const minutes = Math.floor((totalSeconds / 60) % 60);
+ const hours = Math.floor((totalSeconds / (60 * 60)) % 24);
+ return { hours, minutes, seconds };
+}
+
+function secondsToString(totalSeconds) {
+ const { hours, minutes, seconds } = secondsToTime(totalSeconds);
+ const parts = [];
+ if (hours > 0) {
+ parts.push(hours);
+ }
+ parts.push(minutes);
+ parts.push(seconds);
+
+ return parts.map((part) => part.toString().padStart(2, "0")).join(":");
+}
+
+function getIconFromTorrentState(state) {
+ switch(state) {
+ case 'pausedUP':
+ case 'pausedDL':
+ return ;
+ case 'uploading':
+ case 'queuedUP':
+ case 'stalledUP':
+ case 'checkingUP':
+ case 'forcedUP':
+ return ;
+ case 'allocating':
+ case 'downloading':
+ case 'metaDL':
+ case 'queuedDL':
+ case 'stalledDL':
+ case 'checkingDL':
+ case 'forcedDL':
+ return ;
+ case 'checkingResumeData':
+ case 'moving':
+ return ;
+ case 'missingFiles':
+ case 'error':
+ default:
+ return ;
+ }
+}
+
+function readEtaFromTorrent(state) {
+ switch(state) {
+ case 'allocating':
+ case 'downloading':
+ case 'metaDL':
+ case 'queuedDL':
+ case 'stalledDL':
+ case 'checkingDL':
+ case 'forcedDL':
+ return true;
+ case 'error':
+ default:
+ return false;
+ }
+}
+
+function TorrentEntry({ torrent }) {
+ const { state, name, progress, eta, upspeed, dlspeed } = torrent;
+ const { t } = useTranslation();
+
+ return (
+
+
+
+ {getIconFromTorrentState(state)}
+
+
+
+ {t("common.byterate", { value: dlspeed, decimals: 1 })}
+
+
+ {t("common.byterate", { value: upspeed, decimals: 1 })}
+
+
+ {readEtaFromTorrent(state) === true ? secondsToString(eta) :
+ }
+
+
+ );
+}
+
export default function Component({ service }) {
const { t } = useTranslation();
@@ -40,13 +137,20 @@ export default function Component({ service }) {
}
const leech = torrentData.length - completed;
-
+ const torrentsEnabled = service.widget.fields === null || service.widget.fields?.includes('torrents');
return (
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ {torrentData.map((torrent) => (
+
+ ))}
+
+
);
}