UNPKG

@ledgerhq/live-common

Version:
114 lines (102 loc) 3.52 kB
import { useCallback, useEffect, useState } from "react"; import { log } from "@ledgerhq/logs"; import { BatteryStatusFlags } from "@ledgerhq/types-devices"; import { getBatteryStatusesAction, GetBatteryStatusesActionState, initialState, } from "../actions/getBatteryStatuses"; import { BatteryStatusTypes } from "../../hw/getBatteryStatus"; import { useEnv } from "../../env.react"; export type UseBatteryStatusesArgs = { deviceId?: string; deviceName: string | null; statuses: BatteryStatusTypes[]; enabled: boolean; }; /** * Hook used to query one or multiple battery statuses for Ledger Stax. The state will contain an array of with all the * requested statuses in corresponding order. * * @param deviceId * @param statuses A list of status types to query * * @returns An object containing: * - the current state of the request * - a boolean that informs if the request is complete * - a function to trigger an retrigger the device action */ export const useBatteryStatuses = ({ deviceId, deviceName, statuses, enabled, }: UseBatteryStatusesArgs): { batteryStatusesState: GetBatteryStatusesActionState; requestCompleted: boolean; triggerRequest: () => void; cancelRequest: () => void; isBatteryLow: boolean; lowBatteryPercentage: number; } => { const [batteryStatusesState, setBatteryStatusesState] = useState<GetBatteryStatusesActionState>(initialState); const [requestCompleted, setRequestCompleted] = useState<boolean>(false); const [nonce, setNonce] = useState(0); // when passing a function to useState, the function is used as an initializer, // i.e its return value will be the initial state value, // cf. https://react.dev/reference/react/useState#parameters const [cancelRequest, setCancelRequest] = useState(() => () => {}); const [isBatteryLow, setIsBatteryLow] = useState<boolean>(false); const lowBatteryPercentage = useEnv("LOW_BATTERY_PERCENTAGE"); useEffect(() => { if (!enabled) return; if (nonce > 0 && deviceId) { const sub = getBatteryStatusesAction({ deviceId, deviceName, statuses, }).subscribe({ next: state => { if (state.error?.type === "UnknownApdu") { setBatteryStatusesState({ ...state, error: null }); } else { setBatteryStatusesState(state); } // no battery status flags available if (state.batteryStatuses.length <= 1) return; const [percentage, statusFlags] = state.batteryStatuses as [number, BatteryStatusFlags]; if (percentage < lowBatteryPercentage && statusFlags.charging === 0) { setIsBatteryLow(true); } }, complete: () => { setRequestCompleted(true); }, error: err => log("error", "error while retrieving the battery statuses", err), }); setCancelRequest(() => () => { sub.unsubscribe(); setRequestCompleted(false); setBatteryStatusesState(initialState); }); return () => { sub.unsubscribe(); }; } }, [deviceId, deviceName, lowBatteryPercentage, statuses, nonce, enabled]); const triggerRequest = useCallback(() => { setRequestCompleted(false); setIsBatteryLow(false); setBatteryStatusesState(initialState); setNonce(nonce => nonce + 1); }, []); return { batteryStatusesState, triggerRequest, requestCompleted, cancelRequest, isBatteryLow, lowBatteryPercentage, }; };