Files
desktop/app/providers/TransportProvider/TransportProvider.tsx
rosetta 83f38dc63f 'init'
2026-01-30 05:01:05 +02:00

140 lines
4.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { createContext, useEffect, useRef, useState } from "react";
import { PacketRequestTransport } from "../ProtocolProvider/protocol/packets/packet.requesttransport";
import { useSender } from "../ProtocolProvider/useSender";
import { usePacket } from "../ProtocolProvider/usePacket";
import { useConsoleLogger } from "@/app/hooks/useConsoleLogger";
interface TransportContextValue {
transportServer: string | null;
uploadFile: (id: string, content: string) => Promise<any>;
downloadFile: (id: string, tag: string) => Promise<string>;
uploading: TransportState[];
downloading: TransportState[];
}
export const TransportContext = createContext<TransportContextValue | null>(null);
interface TransportProviderProps {
children: React.ReactNode;
}
export interface TransportState {
id: string;
progress: number;
}
/**
* Этот провайдер занимается тем, что передает
* файлы на сервер и получает их с сервера
*/
export function TransportProvider(props: TransportProviderProps) {
const transportServerRef = useRef<string | null>(null);
const [uploading, setUploading] = useState<TransportState[]>([]);
const [downloading, setDownloading] = useState<TransportState[]>([]);
const send = useSender();
const { info } = useConsoleLogger('TransportProvider');
useEffect(() => {
let packet = new PacketRequestTransport();
send(packet);
}, []);
usePacket(0x0F, (packet: PacketRequestTransport) => {
transportServerRef.current = packet.getTransportServer();
info(`Transport server ${transportServerRef.current}`);
});
const uploadFile = async (id: string, content: string) => {
return new Promise((resolve, reject) => {
if (!transportServerRef.current) {
throw new Error("Transport server is not set");
}
setUploading(prev => [...prev, { id: id, progress: 0 }]);
const formData = new FormData();
formData.append('file', new Blob([content]), id);
const xhr = new XMLHttpRequest();
xhr.open('POST', `${transportServerRef.current}/u`);
xhr.upload.onprogress = (event) => {
if (event.lengthComputable) {
const progress = Math.round((event.loaded / event.total) * 100);
setUploading(prev =>
prev.map(u =>
u.id === id ? { ...u, progress } : u
)
);
}
};
xhr.onload = () => {
resolve(JSON.parse(xhr.responseText).t);
setUploading(prev => prev.filter(u => u.id !== id));
};
xhr.onerror = () => {
reject();
setUploading(prev => prev.filter(u => u.id !== id));
};
xhr.send(formData);
});
}
/**
* Скачивает файл с транспортного сервера
* @param tag тег файла
* @param chachaDecryptedKey ключ для расшифровки файла
*/
const downloadFile = (id: string, tag : string) : Promise<string> => {
return new Promise((resolve, reject) => {
if (!transportServerRef.current) {
throw new Error("Transport server is not set");
}
setDownloading(prev => [...prev, { id: id, progress: 0 }]);
const xhr = new XMLHttpRequest();
xhr.open('GET', `${transportServerRef.current}/d/${tag}`);
xhr.responseType = 'text';
xhr.onprogress = (event) => {
if (event.lengthComputable) {
const progress = Math.round((event.loaded / event.total) * 100);
setDownloading(prev =>
prev.map(u =>
u.id === id ? { ...u, progress } : u
)
);
}
};
xhr.onload = async () => {
if(xhr.status != 200){
reject();
return;
}
setDownloading(prev => prev.filter(u => u.id !== tag));
let blob = xhr.responseText;
resolve(blob);
};
xhr.onerror = () => {
setDownloading(prev => prev.filter(u => u.id !== tag));
reject();
};
xhr.send();
});
}
return (
<TransportContext.Provider value={{
transportServer: transportServerRef.current,
uploadFile,
downloadFile,
uploading,
downloading
}}>
{props.children}
</TransportContext.Provider>
)
}