✨ feat: Return network statistics and update the download statistics component layout.
This commit is contained in:
parent
a844c15ac8
commit
3ce64a3cc3
3 changed files with 95 additions and 33 deletions
|
|
@ -410,7 +410,27 @@ public class TelegramVerticle extends AbstractVerticle {
|
|||
}
|
||||
|
||||
public Future<JsonObject> getDownloadStatistics() {
|
||||
return DataVerticle.fileRepository.getDownloadStatistics(this.telegramRecord.id());
|
||||
return Future.all(DataVerticle.fileRepository.getDownloadStatistics(this.telegramRecord.id()),
|
||||
this.execute(new TdApi.GetNetworkStatistics())
|
||||
).map(r -> {
|
||||
JsonObject jsonObject = r.resultAt(0);
|
||||
TdApi.NetworkStatistics networkStatistics = r.resultAt(1);
|
||||
Tuple2<Long, Long> bytes = Arrays.stream(networkStatistics.entries)
|
||||
.filter(e -> e instanceof TdApi.NetworkStatisticsEntryFile)
|
||||
.map(e -> {
|
||||
TdApi.NetworkStatisticsEntryFile entry = (TdApi.NetworkStatisticsEntryFile) e;
|
||||
return Tuple.tuple(entry.sentBytes, entry.receivedBytes);
|
||||
})
|
||||
.reduce((a, b) -> Tuple.tuple(a.v1 + b.v1, a.v2 + b.v2))
|
||||
.orElse(Tuple.tuple(0L, 0L));
|
||||
|
||||
jsonObject.put("networkStatistics", JsonObject.of()
|
||||
.put("sinceDate", networkStatistics.sinceDate)
|
||||
.put("sentBytes", bytes.v1)
|
||||
.put("receivedBytes", bytes.v2)
|
||||
);
|
||||
return jsonObject;
|
||||
});
|
||||
}
|
||||
|
||||
public Future<TdApi.Proxy> enableProxy(String proxyName) {
|
||||
|
|
|
|||
|
|
@ -2,16 +2,20 @@ import React from "react";
|
|||
import useSWR from "swr";
|
||||
import {
|
||||
AlertTriangle,
|
||||
CheckCircle, CloudDownload,
|
||||
CheckCircle,
|
||||
CloudDownload,
|
||||
Download,
|
||||
File,
|
||||
FileText,
|
||||
Image,
|
||||
Music,
|
||||
PauseCircle,
|
||||
Network,
|
||||
PauseCircle, Upload,
|
||||
Video,
|
||||
} from "lucide-react";
|
||||
import { request } from "@/lib/api"; // Define a fetcher function to handle the API request
|
||||
import { request } from "@/lib/api";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
import { formatDistanceToNow } from "date-fns"; // Define a fetcher function to handle the API request
|
||||
|
||||
// Interface defining the structure of the data returned from the API
|
||||
interface StatisticsData {
|
||||
|
|
@ -24,6 +28,11 @@ interface StatisticsData {
|
|||
video: number;
|
||||
audio: number;
|
||||
file: number;
|
||||
networkStatistics: {
|
||||
sinceDate: number;
|
||||
sentBytes: number;
|
||||
receivedBytes: number;
|
||||
};
|
||||
}
|
||||
|
||||
// Props interface for the component, expecting a telegramId as input
|
||||
|
|
@ -100,8 +109,10 @@ const FileStatistics: React.FC<FileStatisticsProps> = ({ telegramId }) => {
|
|||
<div className="space-y-6 rounded-lg bg-gray-50 p-6">
|
||||
<div className="flex-1 rounded-lg bg-white p-4 shadow-md">
|
||||
<div className="flex items-center space-x-3 border-gray-200">
|
||||
<CloudDownload className="h-6 w-6 text-blue-600" />
|
||||
<h2 className="text-xl font-bold text-gray-800">Download Statistics</h2>
|
||||
<h3 className="text-md flex items-center space-x-2 font-semibold text-gray-700">
|
||||
<CloudDownload className="h-5 w-5 text-blue-600" />
|
||||
<span>Download Statistics</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div className="mt-4 grid grid-cols-2 gap-4 md:grid-cols-5">
|
||||
<div className="rounded-lg bg-gray-50 p-4 shadow-sm">
|
||||
|
|
@ -109,7 +120,7 @@ const FileStatistics: React.FC<FileStatisticsProps> = ({ telegramId }) => {
|
|||
<FileText className="h-5 w-5 text-gray-600" />
|
||||
<span className="text-sm text-gray-600">Total Files</span>
|
||||
</div>
|
||||
<div className="mt-2 text-lg text-center font-semibold text-gray-800">
|
||||
<div className="mt-2 text-center text-lg font-semibold text-gray-800">
|
||||
{total}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -118,7 +129,7 @@ const FileStatistics: React.FC<FileStatisticsProps> = ({ telegramId }) => {
|
|||
<Download className="h-5 w-5 text-blue-600" />
|
||||
<span className="text-sm text-gray-600">Downloading</span>
|
||||
</div>
|
||||
<div className="mt-2 text-lg text-center font-semibold text-gray-800">
|
||||
<div className="mt-2 text-center text-lg font-semibold text-gray-800">
|
||||
{downloading}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -127,7 +138,7 @@ const FileStatistics: React.FC<FileStatisticsProps> = ({ telegramId }) => {
|
|||
<PauseCircle className="h-5 w-5 text-yellow-500" />
|
||||
<span className="text-sm text-gray-600">Paused</span>
|
||||
</div>
|
||||
<div className="mt-2 text-lg text-center font-semibold text-gray-800">
|
||||
<div className="mt-2 text-center text-lg font-semibold text-gray-800">
|
||||
{paused}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -136,7 +147,7 @@ const FileStatistics: React.FC<FileStatisticsProps> = ({ telegramId }) => {
|
|||
<CheckCircle className="h-5 w-5 text-green-600" />
|
||||
<span className="text-sm text-gray-600">Completed</span>
|
||||
</div>
|
||||
<div className="mt-2 text-lg text-center font-semibold text-gray-800">
|
||||
<div className="mt-2 text-center text-lg font-semibold text-gray-800">
|
||||
{completed}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -145,34 +156,65 @@ const FileStatistics: React.FC<FileStatisticsProps> = ({ telegramId }) => {
|
|||
<AlertTriangle className="h-5 w-5 text-red-600" />
|
||||
<span className="text-sm text-gray-600">Error</span>
|
||||
</div>
|
||||
<div className="mt-2 text-lg text-center font-semibold text-gray-800">
|
||||
<div className="mt-2 text-center text-lg font-semibold text-gray-800">
|
||||
{errorCount}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 rounded-lg bg-white p-4 shadow-md">
|
||||
<h3 className="text-md flex items-center space-x-2 font-semibold text-gray-700">
|
||||
<CheckCircle className="h-5 w-5 text-green-600" />
|
||||
<span>Completed by Type</span>
|
||||
</h3>
|
||||
<ul className="mt-4 grid grid-cols-2 gap-4">
|
||||
{completedTypes.map((type) => (
|
||||
<li
|
||||
key={type.label}
|
||||
className="rounded-lg bg-gray-50 p-3 shadow-sm"
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
{type.icon}
|
||||
<span className="text-sm text-gray-600">{type.label}</span>
|
||||
</div>
|
||||
<div className="mt-2 text-lg font-semibold text-gray-800">
|
||||
{type.value}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
|
||||
<div className="flex-1 rounded-lg bg-white p-4 shadow-md md:col-span-2">
|
||||
<h3 className="text-md flex items-center space-x-2 font-semibold text-gray-700">
|
||||
<CheckCircle className="h-5 w-5 text-green-600" />
|
||||
<span>Completed by Type</span>
|
||||
</h3>
|
||||
<ul className="mt-4 grid grid-cols-2 gap-4">
|
||||
{completedTypes.map((type) => (
|
||||
<li
|
||||
key={type.label}
|
||||
className="rounded-lg bg-gray-50 p-3 shadow-sm"
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
{type.icon}
|
||||
<span className="text-sm text-gray-600">{type.label}</span>
|
||||
</div>
|
||||
<div className="mt-2 text-lg font-semibold text-gray-800">
|
||||
{type.value}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 rounded-lg bg-white p-4 shadow-md">
|
||||
<h3 className="text-md flex items-center space-x-2 font-semibold text-gray-700">
|
||||
<Network className="h-5 w-5 text-gray-500" />
|
||||
<span>Network Statistics</span>
|
||||
</h3>
|
||||
<div className="mt-4 h-full">
|
||||
<div className="flex justify-center items-center space-x-2 rounded-lg bg-gray-50 p-4 shadow-sm">
|
||||
<Upload className="h-5 w-5 text-yellow-500" />
|
||||
<span className="text-lg font-semibold text-gray-800">
|
||||
{prettyBytes(data.networkStatistics.sentBytes)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-4 flex justify-center items-center space-x-2 rounded-lg bg-gray-50 p-4 shadow-sm">
|
||||
<Download className="h-5 w-5 text-blue-600" />
|
||||
<span className="text-lg font-semibold text-gray-800">
|
||||
{prettyBytes(data.networkStatistics.receivedBytes)}
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-2 text-right text-sm text-gray-400">
|
||||
Since: {formatDistanceToNow(
|
||||
new Date(data.networkStatistics.sinceDate * 1000),
|
||||
{
|
||||
addSuffix: true,
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export const SettingsDialog: React.FC = () => {
|
|||
<SettingsForm />
|
||||
</TabsContent>
|
||||
<TabsContent value="statistics" className="h-full overflow-hidden">
|
||||
<div className="flex flex-col overflow-y-scroll">
|
||||
<div className="h-full flex flex-col overflow-y-scroll">
|
||||
{accountId ? (
|
||||
<FileStatistics telegramId={accountId} />
|
||||
) : (
|
||||
|
|
|
|||
Loading…
Reference in a new issue