✨ 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() {
|
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) {
|
public Future<TdApi.Proxy> enableProxy(String proxyName) {
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,20 @@ import React from "react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import {
|
import {
|
||||||
AlertTriangle,
|
AlertTriangle,
|
||||||
CheckCircle, CloudDownload,
|
CheckCircle,
|
||||||
|
CloudDownload,
|
||||||
Download,
|
Download,
|
||||||
File,
|
File,
|
||||||
FileText,
|
FileText,
|
||||||
Image,
|
Image,
|
||||||
Music,
|
Music,
|
||||||
PauseCircle,
|
Network,
|
||||||
|
PauseCircle, Upload,
|
||||||
Video,
|
Video,
|
||||||
} from "lucide-react";
|
} 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 defining the structure of the data returned from the API
|
||||||
interface StatisticsData {
|
interface StatisticsData {
|
||||||
|
|
@ -24,6 +28,11 @@ interface StatisticsData {
|
||||||
video: number;
|
video: number;
|
||||||
audio: number;
|
audio: number;
|
||||||
file: number;
|
file: number;
|
||||||
|
networkStatistics: {
|
||||||
|
sinceDate: number;
|
||||||
|
sentBytes: number;
|
||||||
|
receivedBytes: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Props interface for the component, expecting a telegramId as input
|
// 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="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-1 rounded-lg bg-white p-4 shadow-md">
|
||||||
<div className="flex items-center space-x-3 border-gray-200">
|
<div className="flex items-center space-x-3 border-gray-200">
|
||||||
<CloudDownload className="h-6 w-6 text-blue-600" />
|
<h3 className="text-md flex items-center space-x-2 font-semibold text-gray-700">
|
||||||
<h2 className="text-xl font-bold text-gray-800">Download Statistics</h2>
|
<CloudDownload className="h-5 w-5 text-blue-600" />
|
||||||
|
<span>Download Statistics</span>
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 grid grid-cols-2 gap-4 md:grid-cols-5">
|
<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">
|
<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" />
|
<FileText className="h-5 w-5 text-gray-600" />
|
||||||
<span className="text-sm text-gray-600">Total Files</span>
|
<span className="text-sm text-gray-600">Total Files</span>
|
||||||
</div>
|
</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}
|
{total}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -118,7 +129,7 @@ const FileStatistics: React.FC<FileStatisticsProps> = ({ telegramId }) => {
|
||||||
<Download className="h-5 w-5 text-blue-600" />
|
<Download className="h-5 w-5 text-blue-600" />
|
||||||
<span className="text-sm text-gray-600">Downloading</span>
|
<span className="text-sm text-gray-600">Downloading</span>
|
||||||
</div>
|
</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}
|
{downloading}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -127,7 +138,7 @@ const FileStatistics: React.FC<FileStatisticsProps> = ({ telegramId }) => {
|
||||||
<PauseCircle className="h-5 w-5 text-yellow-500" />
|
<PauseCircle className="h-5 w-5 text-yellow-500" />
|
||||||
<span className="text-sm text-gray-600">Paused</span>
|
<span className="text-sm text-gray-600">Paused</span>
|
||||||
</div>
|
</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}
|
{paused}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -136,7 +147,7 @@ const FileStatistics: React.FC<FileStatisticsProps> = ({ telegramId }) => {
|
||||||
<CheckCircle className="h-5 w-5 text-green-600" />
|
<CheckCircle className="h-5 w-5 text-green-600" />
|
||||||
<span className="text-sm text-gray-600">Completed</span>
|
<span className="text-sm text-gray-600">Completed</span>
|
||||||
</div>
|
</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}
|
{completed}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -145,34 +156,65 @@ const FileStatistics: React.FC<FileStatisticsProps> = ({ telegramId }) => {
|
||||||
<AlertTriangle className="h-5 w-5 text-red-600" />
|
<AlertTriangle className="h-5 w-5 text-red-600" />
|
||||||
<span className="text-sm text-gray-600">Error</span>
|
<span className="text-sm text-gray-600">Error</span>
|
||||||
</div>
|
</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}
|
{errorCount}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-1 rounded-lg bg-white p-4 shadow-md">
|
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
|
||||||
<h3 className="text-md flex items-center space-x-2 font-semibold text-gray-700">
|
<div className="flex-1 rounded-lg bg-white p-4 shadow-md md:col-span-2">
|
||||||
<CheckCircle className="h-5 w-5 text-green-600" />
|
<h3 className="text-md flex items-center space-x-2 font-semibold text-gray-700">
|
||||||
<span>Completed by Type</span>
|
<CheckCircle className="h-5 w-5 text-green-600" />
|
||||||
</h3>
|
<span>Completed by Type</span>
|
||||||
<ul className="mt-4 grid grid-cols-2 gap-4">
|
</h3>
|
||||||
{completedTypes.map((type) => (
|
<ul className="mt-4 grid grid-cols-2 gap-4">
|
||||||
<li
|
{completedTypes.map((type) => (
|
||||||
key={type.label}
|
<li
|
||||||
className="rounded-lg bg-gray-50 p-3 shadow-sm"
|
key={type.label}
|
||||||
>
|
className="rounded-lg bg-gray-50 p-3 shadow-sm"
|
||||||
<div className="flex items-center space-x-2">
|
>
|
||||||
{type.icon}
|
<div className="flex items-center space-x-2">
|
||||||
<span className="text-sm text-gray-600">{type.label}</span>
|
{type.icon}
|
||||||
</div>
|
<span className="text-sm text-gray-600">{type.label}</span>
|
||||||
<div className="mt-2 text-lg font-semibold text-gray-800">
|
</div>
|
||||||
{type.value}
|
<div className="mt-2 text-lg font-semibold text-gray-800">
|
||||||
</div>
|
{type.value}
|
||||||
</li>
|
</div>
|
||||||
))}
|
</li>
|
||||||
</ul>
|
))}
|
||||||
|
</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>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ export const SettingsDialog: React.FC = () => {
|
||||||
<SettingsForm />
|
<SettingsForm />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="statistics" className="h-full overflow-hidden">
|
<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 ? (
|
{accountId ? (
|
||||||
<FileStatistics telegramId={accountId} />
|
<FileStatistics telegramId={accountId} />
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue