Files
desktop/app/providers/ProtocolProvider/ProtocolProvider.tsx
2026-02-13 17:13:21 +02:00

99 lines
4.1 KiB
TypeScript

import Protocol from "@/app/providers/ProtocolProvider/protocol/protocol";
import { createContext, useEffect, useMemo, useState } from "react";
import { usePublicKey } from "../AccountProvider/usePublicKey";
import { usePrivateKeyHash } from "../AccountProvider/usePrivateKeyHash";
import { useLogger } from "@/app/hooks/useLogger";
import { useMemory } from "../MemoryProvider/useMemory";
import { useNavigate } from "react-router-dom";
import { useSystemInformation } from "../SystemProvider/useSystemInformation";
export enum ProtocolState {
CONNECTED,
HANDSHAKE_EXCHANGE,
DISCONNECTED,
RECONNECTING,
DEVICE_VERIFICATION_REQUIRED
}
export const ProtocolContext = createContext<[Protocol|null, ProtocolState]>([null, ProtocolState.DISCONNECTED]);
interface ProtocolProviderProps {
children: React.ReactNode;
serverAddress : string;
}
export function ProtocolProvider(props : ProtocolProviderProps) {
const publicKey = usePublicKey();
const privateKey = usePrivateKeyHash();
const protocol = useMemo(() => {
return new Protocol(props.serverAddress)
}, [props.serverAddress]);
const log = useLogger('ProtocolProvider');
const [connect, setConnect] = useState(ProtocolState.DISCONNECTED);
const [_, setOnlineSubscribes] = useMemory<string[]>("online_subscribes", [], true);
const systemInfo = useSystemInformation();
const navigate = useNavigate();
useEffect(() => {
if(publicKey.trim() == ""
|| privateKey.trim() == "" || systemInfo.id == "") {
return;
}
const device = {
deviceId: systemInfo.id,
deviceName: systemInfo.name,
deviceOs: systemInfo.os
}
protocol.connect();
const connect = () => {
console.info("Connected to server, starting handshake exchange");
protocol.startHandshakeExchange(publicKey, privateKey, device);
/**
* Сбрасываем подписки на онлайн статусы пользователей
* так как при переподключении они слетают
*/
setOnlineSubscribes([]);
}
const reconnect = () => {
log("Connection lost, reconnecting and starting handshake exchange");
setConnect(ProtocolState.RECONNECTING);
}
const handshake_start = () => {
log("Handshake exchange started");
setConnect(ProtocolState.HANDSHAKE_EXCHANGE);
}
const handshake_complete = () => {
log("Handshake exchange complete");
setConnect(ProtocolState.CONNECTED);
}
const handshake_need_device_verification = () => {
log("Handshake exchange needs device verification");
setConnect(ProtocolState.DEVICE_VERIFICATION_REQUIRED);
navigate('/deviceconfirm');
}
protocol.on('connect', connect);
protocol.on('reconnect', reconnect);
protocol.on('handshake_start', handshake_start);
protocol.on('handshake_complete', handshake_complete);
protocol.on('handshake_need_device_verification', handshake_need_device_verification);
return () => {
/**
* Отключаем все обработчики событий при размонтировании компонента, чтобы избежать
* утечек памяти и некорректного поведения при повторном монтировании
*/
protocol.off('connect', connect);
protocol.off('reconnect', reconnect);
protocol.off('handshake_start', handshake_start);
protocol.off('handshake_complete', handshake_complete);
protocol.off('handshake_need_device_verification', handshake_need_device_verification);
}
}, [publicKey, privateKey, systemInfo.id]);
return (
<ProtocolContext.Provider value={[protocol, connect]}>
{props.children}
</ProtocolContext.Provider>
);
}