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, SYNCHRONIZATION } export type ProtocolContextType = [Protocol|null, ProtocolState, (state: ProtocolState) => void]; export const ProtocolContext = createContext([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("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 ( {props.children} ); }