mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-13 08:55:48 +01:00
@@ -24,7 +24,7 @@ export const downloadRouter = createTRPCRouter({
|
||||
.input(
|
||||
z.object({
|
||||
configName: z.string(),
|
||||
})
|
||||
}),
|
||||
)
|
||||
.query(async ({ input }) => {
|
||||
const config = getConfig(input.configName);
|
||||
@@ -44,7 +44,7 @@ export const downloadRouter = createTRPCRouter({
|
||||
return response;
|
||||
} catch (err: any) {
|
||||
Consola.error(
|
||||
`Error communicating with your download client '${app.name}' (${app.id}): ${err}`
|
||||
`Error communicating with your download client '${app.name}' (${app.id}): ${err}`,
|
||||
);
|
||||
failedClients.push(app.id);
|
||||
return {
|
||||
@@ -67,7 +67,7 @@ export const downloadRouter = createTRPCRouter({
|
||||
|
||||
if (failedClients.length > 0) {
|
||||
Consola.warn(
|
||||
`${failedClients.length} download clients failed. Please check your configuration and the above log`
|
||||
`${failedClients.length} download clients failed. Please check your configuration and the above log`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -76,13 +76,31 @@ export const downloadRouter = createTRPCRouter({
|
||||
});
|
||||
|
||||
const GetDataFromClient = async (
|
||||
app: ConfigAppType
|
||||
app: ConfigAppType,
|
||||
): Promise<NormalizedDownloadAppStat | undefined> => {
|
||||
const reduceTorrent = (data: AllClientData): NormalizedDownloadAppStat => ({
|
||||
type: 'torrent',
|
||||
appId: app.id,
|
||||
success: true,
|
||||
torrents: data.torrents,
|
||||
torrents: data.torrents.map((torrent) => ({
|
||||
name: torrent.name,
|
||||
eta: torrent.eta,
|
||||
state: torrent.state,
|
||||
progress: torrent.progress,
|
||||
totalSeeds: torrent.totalSeeds,
|
||||
totalSelected: torrent.totalSelected,
|
||||
totalPeers: torrent.totalPeers,
|
||||
ratio: torrent.ratio,
|
||||
uploadSpeed: torrent.uploadSpeed,
|
||||
downloadSpeed: torrent.downloadSpeed,
|
||||
isCompleted: torrent.isCompleted,
|
||||
totalDownloaded: torrent.totalDownloaded,
|
||||
totalUploaded: torrent.totalUploaded,
|
||||
label: torrent.label,
|
||||
queuePosition: torrent.queuePosition,
|
||||
stateMessage: torrent.stateMessage,
|
||||
dateAdded: torrent.dateAdded
|
||||
})),
|
||||
totalDownload: data.torrents
|
||||
.map((torrent) => torrent.downloadSpeed)
|
||||
.reduce((acc, torrent) => acc + torrent, 0),
|
||||
@@ -100,7 +118,7 @@ const GetDataFromClient = async (
|
||||
await new Deluge({
|
||||
baseUrl: app.url,
|
||||
password: findField(app, 'password'),
|
||||
}).getAllData()
|
||||
}).getAllData(),
|
||||
);
|
||||
}
|
||||
case 'transmission': {
|
||||
@@ -109,7 +127,7 @@ const GetDataFromClient = async (
|
||||
baseUrl: app.url,
|
||||
username: findField(app, 'username'),
|
||||
password: findField(app, 'password'),
|
||||
}).getAllData()
|
||||
}).getAllData(),
|
||||
);
|
||||
}
|
||||
case 'qBittorrent': {
|
||||
@@ -118,7 +136,7 @@ const GetDataFromClient = async (
|
||||
baseUrl: app.url,
|
||||
username: findField(app, 'username'),
|
||||
password: findField(app, 'password'),
|
||||
}).getAllData()
|
||||
}).getAllData(),
|
||||
);
|
||||
}
|
||||
case 'sabnzbd': {
|
||||
|
||||
@@ -13,7 +13,25 @@ export type NormalizedDownloadAppStat = {
|
||||
|
||||
export type TorrentTotalDownload = {
|
||||
type: 'torrent';
|
||||
torrents: NormalizedTorrent[];
|
||||
torrents: {
|
||||
name: string;
|
||||
state: NormalizedTorrent['state'];
|
||||
totalSelected: number;
|
||||
totalPeers: number;
|
||||
totalSeeds: number;
|
||||
eta: number;
|
||||
progress: number;
|
||||
ratio: number;
|
||||
uploadSpeed: number;
|
||||
downloadSpeed: number;
|
||||
isCompleted: boolean;
|
||||
totalDownloaded: number;
|
||||
totalUploaded: number;
|
||||
label?: string;
|
||||
queuePosition: number;
|
||||
stateMessage: string;
|
||||
dateAdded: string;
|
||||
}[];
|
||||
totalDownload: number;
|
||||
totalUpload: number;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import { NormalizedTorrent } from '@ctrl/shared-torrent';
|
||||
import {
|
||||
Badge,
|
||||
Flex,
|
||||
@@ -9,7 +8,6 @@ import {
|
||||
Progress,
|
||||
Stack,
|
||||
Text,
|
||||
createStyles,
|
||||
useMantineTheme
|
||||
} from '@mantine/core';
|
||||
import {
|
||||
@@ -25,9 +23,10 @@ import {
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { humanFileSize } from '~/tools/humanFileSize';
|
||||
import { AppType } from '~/types/app';
|
||||
import { TorrentTotalDownload } from '~/types/api/downloads/queue/NormalizedDownloadQueueResponse';
|
||||
|
||||
interface TorrentQueueItemProps {
|
||||
torrent: NormalizedTorrent;
|
||||
torrent: TorrentTotalDownload['torrents'][0];
|
||||
app?: AppType;
|
||||
width: number;
|
||||
}
|
||||
@@ -147,9 +146,3 @@ export const TorrentQueuePopover = ({ torrent, app }: Omit<TorrentQueueItemProps
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
const useStyles = createStyles(() => ({
|
||||
noTextBreak: {
|
||||
whiteSpace: 'nowrap',
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
import {
|
||||
MRT_Table,
|
||||
useMantineReactTable,
|
||||
type MRT_ColumnDef,
|
||||
} from 'mantine-react-table';
|
||||
|
||||
import { NormalizedTorrent } from '@ctrl/shared-torrent';
|
||||
import { type MRT_ColumnDef, MRT_Table, useMantineReactTable } from 'mantine-react-table';
|
||||
import {
|
||||
Badge,
|
||||
Center,
|
||||
@@ -26,12 +20,13 @@ import duration from 'dayjs/plugin/duration';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useMemo } from 'react';
|
||||
import { useCardStyles } from '~/components/layout/Common/useCardStyles';
|
||||
import { MIN_WIDTH_MOBILE } from '~/constants/constants';
|
||||
import { calculateETA } from '~/tools/client/calculateEta';
|
||||
import { humanFileSize } from '~/tools/humanFileSize';
|
||||
import { NormalizedDownloadQueueResponse } from '~/types/api/downloads/queue/NormalizedDownloadQueueResponse';
|
||||
import { AppIntegrationType } from '~/types/app';
|
||||
import {
|
||||
NormalizedDownloadQueueResponse,
|
||||
TorrentTotalDownload,
|
||||
} from '~/types/api/downloads/queue/NormalizedDownloadQueueResponse';
|
||||
|
||||
import { useGetDownloadClientsQueue } from '../download-speed/useGetNetworkSpeed';
|
||||
import { defineWidget } from '../helper';
|
||||
@@ -41,8 +36,6 @@ import { TorrentQueuePopover } from './TorrentQueueItem';
|
||||
dayjs.extend(duration);
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
const downloadAppTypes: AppIntegrationType['type'][] = ['deluge', 'qBittorrent', 'transmission'];
|
||||
|
||||
const definition = defineWidget({
|
||||
id: 'torrents-status',
|
||||
icon: IconFileDownload,
|
||||
@@ -96,7 +89,6 @@ interface TorrentTileProps {
|
||||
function TorrentTile({ widget }: TorrentTileProps) {
|
||||
const { t } = useTranslation('modules/torrents-status');
|
||||
const { width, ref } = useElementSize();
|
||||
const { classes } = useCardStyles(true);
|
||||
|
||||
const {
|
||||
data,
|
||||
@@ -110,9 +102,9 @@ function TorrentTile({ widget }: TorrentTileProps) {
|
||||
dataUpdatedAt: number;
|
||||
} = useGetDownloadClientsQueue();
|
||||
|
||||
let torrents: NormalizedTorrent[] = [];
|
||||
if(!(isError || !data || data.apps.length === 0 || Object.values(data.apps).length < 1)) {
|
||||
torrents = data.apps.flatMap((app) => (app.type === 'torrent' ? app.torrents : []))
|
||||
let torrents: TorrentTotalDownload['torrents'] = [];
|
||||
if (!(isError || !data || data.apps.length === 0 || Object.values(data.apps).length < 1)) {
|
||||
torrents = data.apps.flatMap((app) => (app.type === 'torrent' ? app.torrents : []));
|
||||
}
|
||||
|
||||
const filteredTorrents = filterTorrents(widget, torrents);
|
||||
@@ -125,12 +117,12 @@ function TorrentTile({ widget }: TorrentTileProps) {
|
||||
const ratioGlobal = getTorrentsRatio(widget, torrents, false);
|
||||
const ratioWithFilter = getTorrentsRatio(widget, torrents, true);
|
||||
|
||||
const columns = useMemo<MRT_ColumnDef<NormalizedTorrent>[]>(() => [
|
||||
const columns = useMemo<MRT_ColumnDef<TorrentTotalDownload['torrents'][0]>[]>(() => [
|
||||
{
|
||||
id: "dateAdded",
|
||||
id: 'dateAdded',
|
||||
accessorFn: (row) => new Date(row.dateAdded),
|
||||
header: "dateAdded",
|
||||
maxSize: 1
|
||||
header: 'dateAdded',
|
||||
maxSize: 1,
|
||||
},
|
||||
{
|
||||
accessorKey: 'name',
|
||||
@@ -147,7 +139,7 @@ function TorrentTile({ widget }: TorrentTileProps) {
|
||||
>
|
||||
<Popover.Target>
|
||||
<Text
|
||||
maw={"30vw"}
|
||||
maw={'30vw'}
|
||||
size="xs"
|
||||
lineClamp={1}
|
||||
>
|
||||
@@ -160,35 +152,35 @@ function TorrentTile({ widget }: TorrentTileProps) {
|
||||
</Popover>
|
||||
),
|
||||
maxSize: 1,
|
||||
size: 1
|
||||
size: 1,
|
||||
},
|
||||
{
|
||||
accessorKey: 'totalSelected',
|
||||
header: t('card.table.header.size'),
|
||||
Cell: ({ cell }) => formatSize(Number(cell.getValue())),
|
||||
sortDescFirst: true,
|
||||
maxSize: 1
|
||||
maxSize: 1,
|
||||
},
|
||||
{
|
||||
accessorKey: 'uploadSpeed',
|
||||
header: t('card.table.header.upload'),
|
||||
Cell: ({ cell }) => formatSpeed(Number(cell.getValue())),
|
||||
sortDescFirst: true,
|
||||
maxSize: 1
|
||||
maxSize: 1,
|
||||
},
|
||||
{
|
||||
accessorKey: 'downloadSpeed',
|
||||
header: t('card.table.header.download'),
|
||||
Cell: ({ cell }) => formatSpeed(Number(cell.getValue())),
|
||||
sortDescFirst: true,
|
||||
maxSize: 1
|
||||
maxSize: 1,
|
||||
},
|
||||
{
|
||||
accessorKey: 'eta',
|
||||
header: t('card.table.header.estimatedTimeOfArrival'),
|
||||
Cell: ({ cell }) => formatETA(Number(cell.getValue())),
|
||||
sortDescFirst: true,
|
||||
maxSize: 1
|
||||
maxSize: 1,
|
||||
},
|
||||
{
|
||||
accessorKey: 'progress',
|
||||
@@ -321,14 +313,14 @@ function TorrentTile({ widget }: TorrentTileProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export const filterTorrents = (widget: ITorrent, torrents: NormalizedTorrent[]) => {
|
||||
export const filterTorrents = (widget: ITorrent, torrents: TorrentTotalDownload['torrents']) => {
|
||||
let result = torrents;
|
||||
if (!widget.properties.displayCompletedTorrents) {
|
||||
result = result.filter(
|
||||
(torrent) =>
|
||||
!torrent.isCompleted ||
|
||||
(widget.properties.displayActiveTorrents &&
|
||||
torrent.uploadSpeed > widget.properties.speedLimitOfActiveTorrents * 1024)
|
||||
torrent.uploadSpeed > widget.properties.speedLimitOfActiveTorrents * 1024),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -336,7 +328,7 @@ export const filterTorrents = (widget: ITorrent, torrents: NormalizedTorrent[])
|
||||
result = filterTorrentsByLabels(
|
||||
result,
|
||||
widget.properties.labelFilter,
|
||||
widget.properties.labelFilterIsWhitelist
|
||||
widget.properties.labelFilterIsWhitelist,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -345,7 +337,7 @@ export const filterTorrents = (widget: ITorrent, torrents: NormalizedTorrent[])
|
||||
return result;
|
||||
};
|
||||
|
||||
const filterStaleTorrent = (widget: ITorrent, torrents: NormalizedTorrent[]) => {
|
||||
const filterStaleTorrent = (widget: ITorrent, torrents: TorrentTotalDownload['torrents']) => {
|
||||
if (widget.properties.displayStaleTorrents) {
|
||||
return torrents;
|
||||
}
|
||||
@@ -354,9 +346,9 @@ const filterStaleTorrent = (widget: ITorrent, torrents: NormalizedTorrent[]) =>
|
||||
};
|
||||
|
||||
const filterTorrentsByLabels = (
|
||||
torrents: NormalizedTorrent[],
|
||||
torrents: TorrentTotalDownload['torrents'],
|
||||
labels: string[],
|
||||
isWhitelist: boolean
|
||||
isWhitelist: boolean,
|
||||
) => {
|
||||
if (isWhitelist) {
|
||||
return torrents.filter((torrent) => torrent.label && labels.includes(torrent.label));
|
||||
@@ -367,8 +359,8 @@ const filterTorrentsByLabels = (
|
||||
|
||||
export const getTorrentsRatio = (
|
||||
widget: ITorrent,
|
||||
torrents: NormalizedTorrent[],
|
||||
applyAllFilter: boolean
|
||||
torrents: TorrentTotalDownload['torrents'],
|
||||
applyAllFilter: boolean,
|
||||
) => {
|
||||
if (applyAllFilter) {
|
||||
torrents = filterTorrents(widget, torrents);
|
||||
@@ -376,13 +368,13 @@ export const getTorrentsRatio = (
|
||||
torrents = filterTorrentsByLabels(
|
||||
torrents,
|
||||
widget.properties.labelFilter,
|
||||
widget.properties.labelFilterIsWhitelist
|
||||
widget.properties.labelFilterIsWhitelist,
|
||||
);
|
||||
}
|
||||
|
||||
let totalDownloadedSum = torrents.reduce(
|
||||
(sum, torrent) => sum + torrent.totalDownloaded,
|
||||
0
|
||||
0,
|
||||
);
|
||||
|
||||
return totalDownloadedSum > 0
|
||||
|
||||
Reference in New Issue
Block a user