فهرست منبع

Simplify sonarr / radarr queues, better handle some errors

shamoon 2 سال پیش
والد
کامیت
dd4ee44302

+ 4 - 2
public/locales/en/common.json

@@ -195,14 +195,16 @@
         "wanted": "Wanted",
         "wanted": "Wanted",
         "queued": "Queued",
         "queued": "Queued",
         "series": "Series",
         "series": "Series",
-        "queue": "Queue"
+        "queue": "Queue",
+        "unknown": "Unknown"
     },
     },
     "radarr": {
     "radarr": {
         "wanted": "Wanted",
         "wanted": "Wanted",
         "missing": "Missing",
         "missing": "Missing",
         "queued": "Queued",
         "queued": "Queued",
         "movies": "Movies",
         "movies": "Movies",
-        "queue": "Queue"
+        "queue": "Queue",
+        "unknown": "Unknown"
     },
     },
     "lidarr": {
     "lidarr": {
         "wanted": "Wanted",
         "wanted": "Wanted",

+ 0 - 31
src/components/services/widget/block-list.jsx

@@ -1,31 +0,0 @@
-import { useTranslation } from "next-i18next";
-import { useCallback, useState } from 'react';
-import classNames from "classnames";
-
-import ResolvedIcon from '../../resolvedicon';
-
-
-export default function BlockList({ label, children, childHeight }) {
-  const { t } = useTranslation();
-  const [isOpen, setOpen] = useState(false);
-
-  const changeState = useCallback(() => setOpen(!isOpen), [isOpen, setOpen]);
-
-  return (
-    <div
-      className={classNames(
-        "bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 w-full p-1",
-        children === undefined ? "animate-pulse" : ""
-      )}>
-      <button type="button" onClick={changeState} className="w-full flex-1 flex flex-col items-center justify-center text-center">
-        <div className="font-bold text-xs uppercase">{t(label)}</div>
-        <ResolvedIcon icon={isOpen ? "mdi-chevron-down" : "mdi-chevron-up"} />
-      </button>
-      <div
-        className="w-full flex-1 flex flex-col items-center justify-center text-center overflow-hidden transition-height duration-500"
-        style={{height: isOpen ? childHeight * (children?.length ?? 1) : 0}}>
-        {children}
-      </div>
-    </div>
-  );
-}

+ 3 - 13
src/components/widgets/queue/queueEntry.jsx

@@ -1,22 +1,12 @@
-import {BsFillPlayFill, BsPauseFill} from "react-icons/bs";
-
-export default function QueueEntry({ status, title, activity, timeLeft, progress}) {
+export default function QueueEntry({ title, activity, timeLeft, progress}) {
   return (
   return (
-    <div className="text-theme-700 dark:text-theme-200 relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1 flex">
+    <div className="text-theme-700 dark:text-theme-200 relative h-5 rounded-md bg-theme-200/50 dark:bg-theme-900/20 m-1 px-1 flex">
       <div
       <div
-        className="absolute h-5 rounded-md bg-theme-200 dark:bg-theme-900/40 z-0"
+        className="absolute h-5 rounded-md bg-theme-200 dark:bg-theme-900/40 z-0 -ml-1"
         style={{
         style={{
           width: `${progress}%`,
           width: `${progress}%`,
         }}
         }}
       />
       />
-      <div className="text-xs z-10 self-center ml-1">
-        {status === "paused" && (
-          <BsPauseFill className="inline-block w-4 h-4 cursor-pointer -mt-[1px] mr-1 opacity-80" />
-        )}
-        {status !== "paused" && (
-          <BsFillPlayFill className="inline-block w-4 h-4 cursor-pointer -mt-[1px] mr-1 opacity-80" />
-        )}
-      </div>
       <div className="text-xs z-10 self-center ml-2 relative h-4 grow mr-2">
       <div className="text-xs z-10 self-center ml-2 relative h-4 grow mr-2">
         <div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden text-left">{title}</div>
         <div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden text-left">{title}</div>
       </div>
       </div>

+ 22 - 32
src/widgets/radarr/component.jsx

@@ -5,9 +5,12 @@ import QueueEntry from "../../components/widgets/queue/queueEntry";
 
 
 import Container from "components/services/widget/container";
 import Container from "components/services/widget/container";
 import Block from "components/services/widget/block";
 import Block from "components/services/widget/block";
-import BlockList from "components/services/widget/block-list";
 import useWidgetAPI from "utils/proxy/use-widget-api";
 import useWidgetAPI from "utils/proxy/use-widget-api";
 
 
+function getProgress(sizeLeft, size) {
+  return sizeLeft === 0 ? 100 : (1 - sizeLeft / size) * 100
+}
+
 export default function Component({ service }) {
 export default function Component({ service }) {
   const { t } = useTranslation();
   const { t } = useTranslation();
   const { widget } = service;
   const { widget } = service;
@@ -16,7 +19,6 @@ export default function Component({ service }) {
   const { data: queuedData, error: queuedError } = useWidgetAPI(widget, "queue/status");
   const { data: queuedData, error: queuedError } = useWidgetAPI(widget, "queue/status");
   const { data: queueDetailsData, error: queueDetailsError } = useWidgetAPI(widget, "queue/details");
   const { data: queueDetailsData, error: queueDetailsError } = useWidgetAPI(widget, "queue/details");
 
 
-  // information taken from the Radarr docs: https://radarr.video/docs/api/
   const formatDownloadState = useCallback((downloadState) => {
   const formatDownloadState = useCallback((downloadState) => {
     switch (downloadState) {
     switch (downloadState) {
       case "importPending":
       case "importPending":
@@ -33,26 +35,19 @@ export default function Component({ service }) {
     return <Container service={service} error={finalError} />;
     return <Container service={service} error={finalError} />;
   }
   }
 
 
-  const enableQueue = widget?.enableQueue;
-
   if (!moviesData || !queuedData || !queueDetailsData) {
   if (!moviesData || !queuedData || !queueDetailsData) {
     return (
     return (
-      <>
-        <Container service={service}>
-          <Block label="radarr.wanted" />
-          <Block label="radarr.missing" />
-          <Block label="radarr.queued" />
-          <Block label="radarr.movies" />
-        </Container>
-        { enableQueue &&
-          <Container service={service}>
-            <BlockList label="radarr.queued" />
-          </Container>
-        }
-      </>
+      <Container service={service}>
+        <Block label="radarr.wanted" />
+        <Block label="radarr.missing" />
+        <Block label="radarr.queued" />
+        <Block label="radarr.movies" />
+      </Container>
     );
     );
   }
   }
 
 
+  const enableQueue = widget?.enableQueue && Array.isArray(queueDetailsData) && queueDetailsData.length > 0;
+
   return (
   return (
     <>
     <>
       <Container service={service}>
       <Container service={service}>
@@ -61,21 +56,16 @@ export default function Component({ service }) {
         <Block label="radarr.queued" value={t("common.number", { value: queuedData.totalCount })} />
         <Block label="radarr.queued" value={t("common.number", { value: queuedData.totalCount })} />
         <Block label="radarr.movies" value={t("common.number", { value: moviesData.have })} />
         <Block label="radarr.movies" value={t("common.number", { value: moviesData.have })} />
       </Container>
       </Container>
-      { enableQueue &&
-        <Container service={service}>
-          <BlockList label="radarr.queue" childHeight={24}>
-            {Array.isArray(queueDetailsData) ? queueDetailsData.map((queueEntry) => (
-              <QueueEntry
-                progress={(1 - queueEntry.sizeLeft / queueEntry.size) * 100}
-                status={queueEntry.status}
-                timeLeft={queueEntry.timeLeft}
-                title={moviesData.all.find((entry) => entry.id === queueEntry.movieId)?.title}
-                activity={formatDownloadState(queueEntry.trackedDownloadState)}
-                key={queueEntry.movieId}
-              />
-            )) : undefined}
-          </BlockList>
-        </Container>
+      {enableQueue &&
+        queueDetailsData.map((queueEntry) => (
+          <QueueEntry
+            progress={getProgress(queueEntry.sizeLeft, queueEntry.size)}
+            timeLeft={queueEntry.timeLeft}
+            title={moviesData.all.find((entry) => entry.id === queueEntry.movieId)?.title ?? t("radarr.unknown")}
+            activity={formatDownloadState(queueEntry.trackedDownloadState)}
+            key={`${queueEntry.movieId}-${queueEntry.sizeLeft}`}
+          />
+        ))
       }
       }
     </>
     </>
   );
   );

+ 1 - 1
src/widgets/radarr/widget.js

@@ -29,7 +29,7 @@ const widget = {
         timeLeft: entry.timeleft,
         timeLeft: entry.timeleft,
         size: entry.size,
         size: entry.size,
         sizeLeft: entry.sizeleft,
         sizeLeft: entry.sizeleft,
-        movieId: entry.movieId,
+        movieId: entry.movieId ?? entry.id,
         status: entry.status
         status: entry.status
       })).sort((a, b) => {
       })).sort((a, b) => {
         const downloadingA = a.trackedDownloadState === "downloading"
         const downloadingA = a.trackedDownloadState === "downloading"

+ 31 - 31
src/widgets/sonarr/component.jsx

@@ -6,7 +6,20 @@ import QueueEntry from "../../components/widgets/queue/queueEntry";
 import Container from "components/services/widget/container";
 import Container from "components/services/widget/container";
 import Block from "components/services/widget/block";
 import Block from "components/services/widget/block";
 import useWidgetAPI from "utils/proxy/use-widget-api";
 import useWidgetAPI from "utils/proxy/use-widget-api";
-import BlockList from 'components/services/widget/block-list';
+
+function getProgress(sizeLeft, size) {
+  return sizeLeft === 0 ? 100 : (1 - sizeLeft / size) * 100
+}
+
+function getTitle(queueEntry, seriesData) {
+  let title = ''
+  const seriesTitle = seriesData.find((entry) => entry.id === queueEntry.seriesId)?.title;
+  if (seriesTitle) title += `${seriesTitle}: `;
+  const { episodeTitle } = queueEntry;
+  if (episodeTitle) title += episodeTitle;
+  if (title === '') return null;
+  return title;
+}
 
 
 export default function Component({ service }) {
 export default function Component({ service }) {
   const { t } = useTranslation();
   const { t } = useTranslation();
@@ -17,7 +30,6 @@ export default function Component({ service }) {
   const { data: seriesData, error: seriesError } = useWidgetAPI(widget, "series");
   const { data: seriesData, error: seriesError } = useWidgetAPI(widget, "series");
   const { data: queueDetailsData, error: queueDetailsError } = useWidgetAPI(widget, "queue/details");
   const { data: queueDetailsData, error: queueDetailsError } = useWidgetAPI(widget, "queue/details");
 
 
-  // information taken from the Sonarr docs: https://sonarr.tv/docs/api/
   const formatDownloadState = useCallback((downloadState) => {
   const formatDownloadState = useCallback((downloadState) => {
     switch (downloadState) {
     switch (downloadState) {
       case "importPending":
       case "importPending":
@@ -34,25 +46,18 @@ export default function Component({ service }) {
     return <Container service={service} error={finalError} />;
     return <Container service={service} error={finalError} />;
   }
   }
 
 
-  const enableQueue = widget?.enableQueue;
-
   if (!wantedData || !queuedData || !seriesData || !queueDetailsData) {
   if (!wantedData || !queuedData || !seriesData || !queueDetailsData) {
     return (
     return (
-      <>
-        <Container service={service}>
-          <Block label="sonarr.wanted" />
-          <Block label="sonarr.queued" />
-          <Block label="sonarr.series" />
-        </Container>
-        { enableQueue &&
-          <Container service={service}>
-            <BlockList label="sonarr.queued" />
-          </Container>
-        }
-      </>
+      <Container service={service}>
+        <Block label="sonarr.wanted" />
+        <Block label="sonarr.queued" />
+        <Block label="sonarr.series" />
+      </Container>
     );
     );
   }
   }
 
 
+  const enableQueue = widget?.enableQueue && Array.isArray(queueDetailsData) && queueDetailsData.length > 0;
+
   return (
   return (
     <>
     <>
       <Container service={service}>
       <Container service={service}>
@@ -60,21 +65,16 @@ export default function Component({ service }) {
         <Block label="sonarr.queued" value={t("common.number", { value: queuedData.totalRecords })} />
         <Block label="sonarr.queued" value={t("common.number", { value: queuedData.totalRecords })} />
         <Block label="sonarr.series" value={t("common.number", { value: seriesData.length })} />
         <Block label="sonarr.series" value={t("common.number", { value: seriesData.length })} />
       </Container>
       </Container>
-      { enableQueue &&
-        <Container service={service}>
-          <BlockList label="sonarr.queue" childHeight={24}>
-            {Array.isArray(queueDetailsData) ? queueDetailsData.map((queueEntry) => (
-              <QueueEntry
-                progress={(1 - queueEntry.sizeLeft / queueEntry.size) * 100}
-                status={queueEntry.status}
-                timeLeft={queueEntry.timeLeft}
-                title={`${seriesData.find((entry) => entry.id === queueEntry.seriesId)?.title  } • ${  queueEntry.episodeTitle}`}
-                activity={formatDownloadState(queueEntry.trackedDownloadState)}
-                key={queueEntry.episodeId}
-              />
-            )) : undefined}
-          </BlockList>
-        </Container>
+      {enableQueue && 
+        queueDetailsData.map((queueEntry) => (
+          <QueueEntry
+            progress={getProgress(queueEntry.sizeLeft, queueEntry.size)}
+            timeLeft={queueEntry.timeLeft}
+            title={getTitle(queueEntry, seriesData) ?? t("sonarr.unknown")}
+            activity={formatDownloadState(queueEntry.trackedDownloadState)}
+            key={`${queueEntry.seriesId}-${queueEntry.sizeLeft}`}
+          />
+        ))
       }
       }
     </>
     </>
   );
   );

+ 3 - 3
src/widgets/sonarr/widget.js

@@ -34,9 +34,9 @@ const widget = {
         size: entry.size,
         size: entry.size,
         sizeLeft: entry.sizeleft,
         sizeLeft: entry.sizeleft,
         seriesId: entry.seriesId,
         seriesId: entry.seriesId,
-        episodeTitle: entry.episode?.title,
-        episodeId: entry.episodeId,
-        status: entry.status
+        episodeTitle: entry.episode?.title ?? entry.title,
+        episodeId: entry.episodeId ?? entry.id,
+        status: entry.status,
       })).sort((a, b) => {
       })).sort((a, b) => {
         const downloadingA = a.trackedDownloadState === "downloading"
         const downloadingA = a.trackedDownloadState === "downloading"
         const downloadingB = b.trackedDownloadState === "downloading"
         const downloadingB = b.trackedDownloadState === "downloading"

+ 0 - 3
tailwind.config.js

@@ -29,9 +29,6 @@ module.exports = {
         '3xl': '1800px',
         '3xl': '1800px',
         // => @media (min-width: 1800px) { ... }
         // => @media (min-width: 1800px) { ... }
       },
       },
-      transitionProperty: {
-        'height': 'height'
-      },
     },
     },
   },
   },
   plugins: [tailwindForms, tailwindScrollbars],
   plugins: [tailwindForms, tailwindScrollbars],