From 27e8c12cfe2d5591559f23fc8524edad46a7265d Mon Sep 17 00:00:00 2001 From: Igor Katson Date: Wed, 22 Nov 2023 20:52:50 +0000 Subject: [PATCH] The UI looks good now --- crates/librqbit/webui/src/index.tsx | 92 +++++++++++++++++------------ 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/crates/librqbit/webui/src/index.tsx b/crates/librqbit/webui/src/index.tsx index 835bd0e..61753ea 100644 --- a/crates/librqbit/webui/src/index.tsx +++ b/crates/librqbit/webui/src/index.tsx @@ -93,41 +93,56 @@ interface TorrentStats { }; time_remaining: { human_readable: string; + duration: { + secs: number, + } } | null; } const TorrentRow: React.FC<{ - detailsResponse: TorrentDetails, statsResponse: TorrentStats -}> = ({ detailsResponse, statsResponse }) => { + id: number, detailsResponse: TorrentDetails, statsResponse: TorrentStats +}> = ({ id, detailsResponse, statsResponse }) => { const totalBytes = statsResponse.snapshot.total_bytes; const downloadedBytes = statsResponse.snapshot.have_bytes; const finished = totalBytes == downloadedBytes; const downloadPercentage = (downloadedBytes / totalBytes) * 100; + let classes = [ + ]; + if (id % 2 == 0) { + classes.push('bg-light'); + } + return ( - - {getLargestFileName(detailsResponse)} - {`${formatBytes(totalBytes)}`} - - + + +
+ {getLargestFileName(detailsResponse)} +
- {statsResponse.download_speed.human_readable} + {`${formatBytes(totalBytes)}`} + + + + {statsResponse.download_speed.human_readable} {getCompletionETA(statsResponse)} - {`${statsResponse.snapshot.peer_stats.live} / ${statsResponse.snapshot.peer_stats.seen}`} - + {`${statsResponse.snapshot.peer_stats.live} / ${statsResponse.snapshot.peer_stats.seen}`} +
); } const Column: React.FC<{ label: string, + size?: number, children?: any -}> = ({ children }) => ( - +}> = ({ size, label, children }) => ( + +
{label}
{children} - + ); -const Torrent = ({ torrent }) => { +const Torrent = ({ id, torrent }) => { const defaultDetails: TorrentDetails = { info_hash: '', files: [] @@ -202,7 +217,7 @@ const Torrent = ({ torrent }) => { return clear; }, []); - return + return } const TorrentsList = (props: { torrents: Array, loading: boolean }) => { @@ -222,24 +237,11 @@ const TorrentsList = (props: { torrents: Array, loading: boolean }) = ) } return ( - - - - - - - - - - - - - {props.torrents.map((t: TorrentId) => - - )} - - -
NameSizeProgressDownload SpeedETAPeers
+ <> + {props.torrents.map((t: TorrentId) => + + )} + ) }; @@ -334,14 +336,14 @@ const Root = () => { } return - +

rqbit web 0.0.1-alpha

- +
} @@ -608,13 +610,29 @@ function getLargestFileName(torrentDetails: TorrentDetails): string { // Function to get the completion ETA of a torrent function getCompletionETA(stats: TorrentStats): string { - if (stats.time_remaining) { - return stats.time_remaining.human_readable; + if (stats.time_remaining && stats.time_remaining.duration) { + return formatSecondsToTime(stats.time_remaining.duration.secs); } else { return 'N/A'; } } +function formatSecondsToTime(seconds: number) { + const hours = Math.floor(seconds / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + const remainingSeconds = seconds % 60; + + const formatUnit = (value, unit) => (value > 0 ? `${value}${unit}` : ''); + + if (hours > 0) { + return `${formatUnit(hours, 'h')} ${formatUnit(minutes, 'm')}`.trim(); + } else if (minutes > 0) { + return `${formatUnit(minutes, 'm')} ${formatUnit(remainingSeconds, 's')}`.trim(); + } else { + return `${formatUnit(remainingSeconds, 's')}`.trim(); + } +} + function customSetInterval(asyncCallback: any, interval: number) { let timeoutId: number; let currentInterval: number = interval;