@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
182 lines • 6.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createAction = void 0;
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const react_1 = require("react");
const logs_1 = require("@ledgerhq/logs");
const observable_1 = require("../../observable");
const app_1 = require("./app");
const implementations_1 = require("./implementations");
const getLatestFirmwareForDeviceUseCase_1 = require("../../device/use-cases/getLatestFirmwareForDeviceUseCase");
const mapResult = ({ deviceInfo, device, result }) => deviceInfo && device
? {
device,
deviceInfo,
result,
}
: null;
const getInitialState = (device) => ({
isLoading: device === undefined || !!device,
requestQuitApp: false,
unresponsive: false,
isLocked: false,
allowManagerRequested: false,
allowManagerGranted: false,
device,
deviceInfo: null,
deviceId: null,
result: null,
error: null,
});
const reducer = (state, e) => {
switch (e.type) {
case "unresponsiveDevice":
return { ...state, unresponsive: true };
case "lockedDevice":
return { ...state, isLocked: true };
case "deviceChange":
return getInitialState(e.device);
case "error":
return {
...getInitialState(state.device),
error: e.error,
isLoading: false,
isLocked: false,
};
case "appDetected":
return {
...state,
unresponsive: false,
isLocked: false,
requestQuitApp: true,
};
case "osu":
case "bootloader":
return {
...state,
isLoading: false,
unresponsive: false,
isLocked: false,
requestQuitApp: false,
deviceInfo: e.deviceInfo,
};
case "listingApps":
return {
...state,
isLoading: true,
requestQuitApp: false,
unresponsive: false,
isLocked: false,
deviceInfo: e.deviceInfo,
};
case "device-permission-requested":
return {
...state,
unresponsive: false,
isLocked: false,
allowManagerRequested: true,
};
case "device-permission-granted":
return {
...state,
unresponsive: false,
isLocked: false,
allowManagerRequested: false,
allowManagerGranted: true,
};
case "device-id":
return {
...state,
deviceId: e.deviceId,
};
case "result":
return {
...state,
isLoading: false,
unresponsive: false,
isLocked: false,
result: e.result,
};
}
return state;
};
const createAction = (task) => {
const useHook = (device, request = {}) => {
const [state, setState] = (0, react_1.useState)(() => getInitialState());
const [resetIndex, setResetIndex] = (0, react_1.useState)(0);
const deviceSubject = (0, observable_1.useReplaySubject)(device);
// repair modal will interrupt everything and be rendered instead of the background content
const [repairModalOpened, setRepairModalOpened] = (0, react_1.useState)(null);
(0, react_1.useEffect)(() => {
if (request?.cancelExecution)
return;
const impl = (0, implementations_1.getImplementation)(app_1.currentMode)({
deviceSubject,
task,
request,
retryableWithDelayDisconnectedErrors: [],
});
if (repairModalOpened)
return;
const sub = impl
.pipe((0, operators_1.tap)((e) => (0, logs_1.log)("actions-manager-event", e.type, e)), (0, operators_1.debounce)((e) => ("replaceable" in e && e.replaceable ? (0, rxjs_1.interval)(100) : (0, rxjs_1.of)(null))), (0, operators_1.scan)(reducer, getInitialState()))
.subscribe(setState);
return () => {
sub.unsubscribe();
};
}, [deviceSubject, resetIndex, repairModalOpened, request]);
const { deviceInfo } = state;
(0, react_1.useEffect)(() => {
if (!deviceInfo)
return;
// Preload latest firmware in parallel
(0, getLatestFirmwareForDeviceUseCase_1.getLatestFirmwareForDeviceUseCase)(deviceInfo).catch((e) => {
(0, logs_1.log)("warn", e.message);
});
}, [deviceInfo]);
const onRepairModal = (0, react_1.useCallback)(open => {
setRepairModalOpened(open
? {
auto: false,
}
: null);
}, []);
const closeRepairModal = (0, react_1.useCallback)(() => {
// Sets isBootloader to true to avoid having the renderBootloaderStep rendered,
// on which the user could re-trigger a bootloader repairing scenario that is not needed
setState(prevState => {
return {
...prevState,
deviceInfo: prevState.deviceInfo
? { ...prevState.deviceInfo, isBootloader: false }
: null,
};
});
setRepairModalOpened(null);
}, []);
const onRetry = (0, react_1.useCallback)(() => {
setResetIndex(currIndex => currIndex + 1);
setState(s => getInitialState(s.device));
}, []);
const onAutoRepair = (0, react_1.useCallback)(() => {
setRepairModalOpened({
auto: true,
});
}, []);
return {
...state,
repairModalOpened,
onRetry,
onAutoRepair,
closeRepairModal,
onRepairModal,
};
};
return {
useHook,
mapResult,
};
};
exports.createAction = createAction;
//# sourceMappingURL=manager.js.map