mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-10 15:35:55 +01:00
🐛 Fix multiple bugs and reformat code
This commit is contained in:
@@ -164,8 +164,9 @@ const AppShelf = (props: any) => {
|
|||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
) : null}
|
) : null}
|
||||||
<Accordion.Item key="Downloads" label="Your downloads">
|
<Accordion.Item key="Downloads" label="Your downloads">
|
||||||
<ModuleMenu module={DownloadsModule} />
|
|
||||||
<Paper
|
<Paper
|
||||||
|
p="lg"
|
||||||
|
radius="lg"
|
||||||
style={{
|
style={{
|
||||||
background: `rgba(${colorScheme === 'dark' ? '37, 38, 43,' : '255, 255, 255,'} \
|
background: `rgba(${colorScheme === 'dark' ? '37, 38, 43,' : '255, 255, 255,'} \
|
||||||
${(config.settings.appOpacity || 100) / 100}`,
|
${(config.settings.appOpacity || 100) / 100}`,
|
||||||
@@ -173,6 +174,7 @@ const AppShelf = (props: any) => {
|
|||||||
${(config.settings.appOpacity || 100) / 100}`,
|
${(config.settings.appOpacity || 100) / 100}`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<ModuleMenu module={DownloadsModule} />
|
||||||
<DownloadComponent />
|
<DownloadComponent />
|
||||||
</Paper>
|
</Paper>
|
||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
/* eslint-disable react/no-children-prop */
|
/* eslint-disable react/no-children-prop */
|
||||||
import { Box, Divider, Indicator, Popover, ScrollArea, createStyles, useMantineTheme } from '@mantine/core';
|
import {
|
||||||
|
Box,
|
||||||
|
Divider,
|
||||||
|
Indicator,
|
||||||
|
Popover,
|
||||||
|
ScrollArea,
|
||||||
|
createStyles,
|
||||||
|
useMantineTheme,
|
||||||
|
} from '@mantine/core';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Calendar } from '@mantine/dates';
|
import { Calendar } from '@mantine/dates';
|
||||||
import { IconCalendar as CalendarIcon } from '@tabler/icons';
|
import { IconCalendar as CalendarIcon } from '@tabler/icons';
|
||||||
@@ -28,7 +36,7 @@ export default function CalendarComponent(props: any) {
|
|||||||
const theme = useMantineTheme();
|
const theme = useMantineTheme();
|
||||||
const { secondaryColor } = useColorTheme();
|
const { secondaryColor } = useColorTheme();
|
||||||
const useStyles = createStyles((theme) => ({
|
const useStyles = createStyles((theme) => ({
|
||||||
weekend: {
|
weekend: {
|
||||||
color: `${secondaryColor} !important`,
|
color: `${secondaryColor} !important`,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
@@ -101,12 +109,13 @@ export default function CalendarComponent(props: any) {
|
|||||||
onChange={(day: any) => {}}
|
onChange={(day: any) => {}}
|
||||||
dayStyle={(date) =>
|
dayStyle={(date) =>
|
||||||
date.getDay() === today.getDay() && date.getDate() === today.getDate()
|
date.getDay() === today.getDay() && date.getDate() === today.getDate()
|
||||||
? { backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[0] }
|
? {
|
||||||
|
backgroundColor:
|
||||||
|
theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[0],
|
||||||
|
}
|
||||||
: {}
|
: {}
|
||||||
}
|
}
|
||||||
dayClassName={(date, modifiers) =>
|
dayClassName={(date, modifiers) => cx({ [classes.weekend]: modifiers.weekend })}
|
||||||
cx({ [classes.weekend]: modifiers.weekend })
|
|
||||||
}
|
|
||||||
renderDay={(renderdate) => (
|
renderDay={(renderdate) => (
|
||||||
<DayComponent
|
<DayComponent
|
||||||
renderdate={renderdate}
|
renderdate={renderdate}
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ import { IconDownload as Download } from '@tabler/icons';
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { NormalizedTorrent } from '@ctrl/shared-torrent';
|
import { NormalizedTorrent } from '@ctrl/shared-torrent';
|
||||||
|
import { useViewportSize } from '@mantine/hooks';
|
||||||
import { IModule } from '../modules';
|
import { IModule } from '../modules';
|
||||||
import { useConfig } from '../../../tools/state';
|
import { useConfig } from '../../../tools/state';
|
||||||
import { AddItemShelfButton } from '../../AppShelf/AddAppShelfItem';
|
import { AddItemShelfButton } from '../../AppShelf/AddAppShelfItem';
|
||||||
import { useSetSafeInterval } from '../../../tools/hooks/useSetSafeInterval';
|
import { useSetSafeInterval } from '../../../tools/hooks/useSetSafeInterval';
|
||||||
import { useViewportSize } from '@mantine/hooks';
|
|
||||||
import { humanFileSize } from '../../../tools/humanFileSize';
|
import { humanFileSize } from '../../../tools/humanFileSize';
|
||||||
|
|
||||||
export const DownloadsModule: IModule = {
|
export const DownloadsModule: IModule = {
|
||||||
@@ -84,17 +84,33 @@ export default function DownloadComponent() {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const DEVICE_WIDTH = 576;
|
||||||
const ths = (
|
const ths = (
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Size</th>
|
<th>Size</th>
|
||||||
{width > 576 ? <th>Down</th> : ``}
|
{width > 576 ? <th>Down</th> : ''}
|
||||||
{width > 576 ? <th>Up</th> : ``}
|
{width > 576 ? <th>Up</th> : ''}
|
||||||
<th>ETA</th>
|
<th>ETA</th>
|
||||||
<th>Progress</th>
|
<th>Progress</th>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
// Convert Seconds to readable format.
|
||||||
|
function calculateETA(givenSeconds: number) {
|
||||||
|
// If its superior than one day return > 1 day
|
||||||
|
if (givenSeconds > 86400) {
|
||||||
|
return '> 1 day';
|
||||||
|
}
|
||||||
|
// Transform the givenSeconds into a readable format. e.g. 1h 2m 3s
|
||||||
|
const hours = Math.floor(givenSeconds / 3600);
|
||||||
|
const minutes = Math.floor((givenSeconds % 3600) / 60);
|
||||||
|
const seconds = Math.floor(givenSeconds % 60);
|
||||||
|
// Only show hours if it's greater than 0.
|
||||||
|
const hoursString = hours > 0 ? `${hours}h ` : '';
|
||||||
|
const minutesString = minutes > 0 ? `${minutes}m ` : '';
|
||||||
|
const secondsString = seconds > 0 ? `${seconds}s` : '';
|
||||||
|
return `${hoursString}${minutesString}${secondsString}`;
|
||||||
|
}
|
||||||
// Loop over qBittorrent torrents merging with deluge torrents
|
// Loop over qBittorrent torrents merging with deluge torrents
|
||||||
const rows = torrents
|
const rows = torrents
|
||||||
.filter((torrent) => !(torrent.progress === 1 && hideComplete))
|
.filter((torrent) => !(torrent.progress === 1 && hideComplete))
|
||||||
@@ -102,29 +118,6 @@ export default function DownloadComponent() {
|
|||||||
const downloadSpeed = torrent.downloadSpeed / 1024 / 1024;
|
const downloadSpeed = torrent.downloadSpeed / 1024 / 1024;
|
||||||
const uploadSpeed = torrent.uploadSpeed / 1024 / 1024;
|
const uploadSpeed = torrent.uploadSpeed / 1024 / 1024;
|
||||||
const size = torrent.totalSelected;
|
const size = torrent.totalSelected;
|
||||||
// Convert Seconds to readable format.
|
|
||||||
function calculateETA(givenSeconds: number) {
|
|
||||||
if (givenSeconds > 86399) { // No
|
|
||||||
return ">1d"
|
|
||||||
}
|
|
||||||
const time = new Date(givenSeconds * 1000).toISOString();
|
|
||||||
const hours = parseInt(time.substring(11,13));
|
|
||||||
const minutes = parseInt(time.substring(14,16));
|
|
||||||
const seconds = parseInt(time.substring(17,19));
|
|
||||||
var str = "";
|
|
||||||
// If tree go brr
|
|
||||||
if (hours > 0) {
|
|
||||||
str = `${hours}h `;
|
|
||||||
}
|
|
||||||
if (minutes > 0) {
|
|
||||||
str = `${str}${minutes}m `
|
|
||||||
}
|
|
||||||
if (seconds > 0) {
|
|
||||||
str = `${str}${seconds}s`;
|
|
||||||
}
|
|
||||||
return str.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr key={torrent.id}>
|
<tr key={torrent.id}>
|
||||||
<td>
|
<td>
|
||||||
@@ -141,19 +134,22 @@ export default function DownloadComponent() {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Text size="xs">{humanFileSize(size)}</Text>
|
<Text size="xs">{humanFileSize(size)}</Text>
|
||||||
</td>
|
</td>
|
||||||
{width > 576 ?
|
{width > 576 ? (
|
||||||
<td>
|
<td>
|
||||||
<Text size="xs">{downloadSpeed > 0 ? `${downloadSpeed.toFixed(1)} Mb/s` : '-'}</Text>
|
<Text size="xs">{downloadSpeed > 0 ? `${downloadSpeed.toFixed(1)} Mb/s` : '-'}</Text>
|
||||||
</td>
|
</td>
|
||||||
:
|
) : (
|
||||||
``}
|
''
|
||||||
{width > 576 ?
|
)}
|
||||||
<td>
|
{width > 576 ? (
|
||||||
<Text size="xs">{uploadSpeed > 0 ? `${uploadSpeed.toFixed(1)} Mb/s` : '-'}</Text>
|
<td>
|
||||||
</td> :
|
<Text size="xs">{uploadSpeed > 0 ? `${uploadSpeed.toFixed(1)} Mb/s` : '-'}</Text>
|
||||||
``}
|
</td>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
<td>
|
<td>
|
||||||
<Text size="xs">{torrent.eta <= 0 ? '∞' : calculateETA(torrent.eta)}</Text>
|
<Text size="xs">{torrent.eta <= 0 ? '∞' : calculateETA(torrent.eta)}</Text>
|
||||||
</td>
|
</td>
|
||||||
@@ -161,7 +157,9 @@ export default function DownloadComponent() {
|
|||||||
<Text>{(torrent.progress * 100).toFixed(1)}%</Text>
|
<Text>{(torrent.progress * 100).toFixed(1)}%</Text>
|
||||||
<Progress
|
<Progress
|
||||||
radius="lg"
|
radius="lg"
|
||||||
color={torrent.state === "paused" ? 'yellow' : (torrent.progress === 1 ? 'green' : 'blue')}
|
color={
|
||||||
|
torrent.state === 'paused' ? 'yellow' : torrent.progress === 1 ? 'green' : 'blue'
|
||||||
|
}
|
||||||
value={torrent.progress * 100}
|
value={torrent.progress * 100}
|
||||||
size="lg"
|
size="lg"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -12,17 +12,6 @@ import { humanFileSize } from '../../../tools/humanFileSize';
|
|||||||
import { IModule } from '../modules';
|
import { IModule } from '../modules';
|
||||||
import { useSetSafeInterval } from '../../../tools/hooks/useSetSafeInterval';
|
import { useSetSafeInterval } from '../../../tools/hooks/useSetSafeInterval';
|
||||||
|
|
||||||
/**
|
|
||||||
* Format bytes as human-readable text.
|
|
||||||
*
|
|
||||||
* @param bytes Number of bytes.
|
|
||||||
* @param si True to use metric (SI) units, aka powers of 1000. False to use
|
|
||||||
* binary (IEC), aka powers of 1024.
|
|
||||||
* @param dp Number of decimal places to display.
|
|
||||||
*
|
|
||||||
* @return Formatted string.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const TotalDownloadsModule: IModule = {
|
export const TotalDownloadsModule: IModule = {
|
||||||
title: 'Download Speed',
|
title: 'Download Speed',
|
||||||
description: 'Show the current download speed of supported services',
|
description: 'Show the current download speed of supported services',
|
||||||
|
|||||||
@@ -1,21 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Format bytes as human-readable text.
|
||||||
|
*
|
||||||
|
* @param bytes Number of bytes.
|
||||||
|
* @param si True to use metric (SI) units, aka powers of 1000. False to use
|
||||||
|
* binary (IEC), aka powers of 1024.
|
||||||
|
* @param dp Number of decimal places to display.
|
||||||
|
*
|
||||||
|
* @return Formatted string.
|
||||||
|
*/
|
||||||
export function humanFileSize(initialBytes: number, si = true, dp = 1) {
|
export function humanFileSize(initialBytes: number, si = true, dp = 1) {
|
||||||
const thresh = si ? 1000 : 1024;
|
const thresh = si ? 1000 : 1024;
|
||||||
let bytes = initialBytes;
|
let bytes = initialBytes;
|
||||||
|
|
||||||
if (Math.abs(bytes) < thresh) {
|
if (Math.abs(bytes) < thresh) {
|
||||||
return `${bytes} B`;
|
return `${bytes} B`;
|
||||||
}
|
|
||||||
|
|
||||||
const units = si
|
|
||||||
? ['kb', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
|
||||||
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
|
||||||
let u = -1;
|
|
||||||
const r = 10 ** dp;
|
|
||||||
|
|
||||||
do {
|
|
||||||
bytes /= thresh;
|
|
||||||
u += 1;
|
|
||||||
} while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
|
|
||||||
|
|
||||||
return `${bytes.toFixed(dp)} ${units[u]}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const units = si
|
||||||
|
? ['kb', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||||
|
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
||||||
|
let u = -1;
|
||||||
|
const r = 10 ** dp;
|
||||||
|
|
||||||
|
do {
|
||||||
|
bytes /= thresh;
|
||||||
|
u += 1;
|
||||||
|
} while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
|
||||||
|
|
||||||
|
return `${bytes.toFixed(dp)} ${units[u]}`;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user