import { BackupTrustInfo, CryptoApi, CryptoEvent, CryptoEventHandlerMap, KeyBackupInfo, } from 'matrix-js-sdk/lib/crypto-api'; import { useCallback, useEffect, useState } from 'react'; import { useMatrixClient } from './useMatrixClient'; import { useAlive } from './useAlive'; export const useKeyBackupStatusChange = ( onChange: CryptoEventHandlerMap[CryptoEvent.KeyBackupStatus] ) => { const mx = useMatrixClient(); useEffect(() => { mx.on(CryptoEvent.KeyBackupStatus, onChange); return () => { mx.removeListener(CryptoEvent.KeyBackupStatus, onChange); }; }, [mx, onChange]); }; export const useKeyBackupStatus = (crypto: CryptoApi): boolean => { const alive = useAlive(); const [status, setStatus] = useState(false); useEffect(() => { crypto.getActiveSessionBackupVersion().then((v) => { if (alive()) { setStatus(typeof v === 'string'); } }); }, [crypto, alive]); useKeyBackupStatusChange(setStatus); return status; }; export const useKeyBackupSessionsRemainingChange = ( onChange: CryptoEventHandlerMap[CryptoEvent.KeyBackupSessionsRemaining] ) => { const mx = useMatrixClient(); useEffect(() => { mx.on(CryptoEvent.KeyBackupSessionsRemaining, onChange); return () => { mx.removeListener(CryptoEvent.KeyBackupSessionsRemaining, onChange); }; }, [mx, onChange]); }; export const useKeyBackupFailedChange = ( onChange: CryptoEventHandlerMap[CryptoEvent.KeyBackupFailed] ) => { const mx = useMatrixClient(); useEffect(() => { mx.on(CryptoEvent.KeyBackupFailed, onChange); return () => { mx.removeListener(CryptoEvent.KeyBackupFailed, onChange); }; }, [mx, onChange]); }; export const useKeyBackupDecryptionKeyCached = ( onChange: CryptoEventHandlerMap[CryptoEvent.KeyBackupDecryptionKeyCached] ) => { const mx = useMatrixClient(); useEffect(() => { mx.on(CryptoEvent.KeyBackupDecryptionKeyCached, onChange); return () => { mx.removeListener(CryptoEvent.KeyBackupDecryptionKeyCached, onChange); }; }, [mx, onChange]); }; export const useKeyBackupSync = (): [number, string | undefined] => { const [remaining, setRemaining] = useState(0); const [failure, setFailure] = useState(); useKeyBackupSessionsRemainingChange( useCallback((count) => { setRemaining(count); setFailure(undefined); }, []) ); useKeyBackupFailedChange( useCallback((f) => { if (typeof f === 'string') { setFailure(f); setRemaining(0); } }, []) ); return [remaining, failure]; }; export const useKeyBackupInfo = (crypto: CryptoApi): KeyBackupInfo | undefined | null => { const alive = useAlive(); const [info, setInfo] = useState(); const fetchInfo = useCallback(() => { crypto.getKeyBackupInfo().then((i) => { if (alive()) { setInfo(i); } }); }, [crypto, alive]); useEffect(() => { fetchInfo(); }, [fetchInfo]); useKeyBackupStatusChange(fetchInfo); useKeyBackupSessionsRemainingChange( useCallback( (remainingCount) => { if (remainingCount === 0) { fetchInfo(); } }, [fetchInfo] ) ); return info; }; export const useKeyBackupTrust = ( crypto: CryptoApi, backupInfo: KeyBackupInfo ): BackupTrustInfo | undefined => { const alive = useAlive(); const [trust, setTrust] = useState(); const fetchTrust = useCallback(() => { crypto.isKeyBackupTrusted(backupInfo).then((t) => { if (alive()) { setTrust(t); } }); }, [crypto, alive, backupInfo]); useEffect(() => { fetchTrust(); }, [fetchTrust]); useKeyBackupStatusChange(fetchTrust); useKeyBackupDecryptionKeyCached(fetchTrust); return trust; };