UNPKG

@ledgerhq/live-common

Version:
86 lines 4.56 kB
import { useState, useEffect, useCallback } from "react"; import isEqual from "lodash/isEqual"; import { DeviceOnboardingStatePollingError } from "@ledgerhq/errors"; import { getOnboardingStatePolling as defaultGetOnboardingStatePolling } from "../../hw/getOnboardingStatePolling"; /** * Polls the current device onboarding state, and notify the hook consumer of * any allowed errors and fatal errors * @param getOnboardingStatePolling A polling function, by default set to live-common/hw/getOnboardingStatePolling. * This dependency injection is needed for LLD to have the polling working on the internal thread * @param device A Device object * @param pollingPeriodMs The period in ms after which the device onboarding state is fetched again * @param stopPolling Flag to stop or continue the polling * @returns An object containing: * - onboardingState: the device state during the onboarding * - allowedError: any error that is allowed and does not stop the polling * - fatalError: any error that is fatal and stops the polling * - lockedDevice: a boolean set to true if the device is currently locked, false otherwise * - resetStates: a function to reset the values of: onboardingState, allowedError, fatalError and lockedDevice */ export const useOnboardingStatePolling = ({ getOnboardingStatePolling = defaultGetOnboardingStatePolling, device, pollingPeriodMs, stopPolling = false, allowedErrorChecks = [], }) => { const [onboardingState, setOnboardingState] = useState(null); const [allowedError, setAllowedError] = useState(null); const [fatalError, setFatalError] = useState(null); const [lockedDevice, setLockedDevice] = useState(false); useEffect(() => { let onboardingStatePollingSubscription; // If stopPolling is updated and set to true, the useEffect hook will call its // cleanup function (return) and the polling won't restart with the below condition if (device && !stopPolling) { onboardingStatePollingSubscription = getOnboardingStatePolling({ deviceId: device.deviceId, pollingPeriodMs, allowedErrorChecks, }).subscribe({ next: (onboardingStatePollingResult) => { if (onboardingStatePollingResult) { setFatalError(null); setLockedDevice(onboardingStatePollingResult.lockedDevice); // Only updates if the new allowedError is different setAllowedError(prevAllowedError => getNewAllowedErrorIfChanged(prevAllowedError, onboardingStatePollingResult.allowedError)); // Does not update the onboarding state if an allowed error occurred if (!onboardingStatePollingResult.allowedError) { // Only updates if the new onboardingState is different setOnboardingState(prevOnboardingState => getNewOnboardingStateIfChanged(prevOnboardingState, onboardingStatePollingResult.onboardingState)); } } }, error: error => { setAllowedError(null); setLockedDevice(false); setFatalError(error instanceof Error ? error : new DeviceOnboardingStatePollingError(`Error from: ${error?.name ?? error} ${error?.message}`)); }, }); } return () => { onboardingStatePollingSubscription?.unsubscribe(); }; }, [ device, pollingPeriodMs, setOnboardingState, setAllowedError, setFatalError, stopPolling, getOnboardingStatePolling, ]); const resetStates = useCallback(() => { setOnboardingState(null); setAllowedError(null); setFatalError(null); setLockedDevice(false); }, []); return { onboardingState, allowedError, fatalError, lockedDevice, resetStates }; }; const getNewOnboardingStateIfChanged = (prevOnboardingState, newOnboardingState) => { return isEqual(prevOnboardingState, newOnboardingState) ? prevOnboardingState : newOnboardingState; }; const getNewAllowedErrorIfChanged = (prevError, newError) => { // Only interested if the errors are instances of the same Error class return prevError?.constructor === newError?.constructor ? prevError : newError; }; //# sourceMappingURL=useOnboardingStatePolling.js.map