UNPKG

@ledgerhq/live-common

Version:
141 lines 5.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useAppsRunner = void 0; exports.useNotEnoughMemoryToInstall = useNotEnoughMemoryToInstall; exports.useAppsSections = useAppsSections; exports.useAppInstallProgress = useAppInstallProgress; exports.useAppInstallNeedsDeps = useAppInstallNeedsDeps; exports.useAppUninstallNeedsDeps = useAppUninstallNeedsDeps; const react_1 = require("react"); const filtering_1 = require("./filtering"); const logic_1 = require("./logic"); const runner_1 = require("./runner"); const featureFlags_1 = require("../featureFlags"); // use for React apps. support dynamic change of the state. const useAppsRunner = (listResult, exec, appsToRestore) => { // $FlowFixMe for ledger-live-mobile older react/flow version const [state, dispatch] = (0, react_1.useReducer)(logic_1.reducer, null, () => (0, logic_1.initState)(listResult, appsToRestore)); const nextAppOp = (0, react_1.useMemo)(() => (0, logic_1.getNextAppOp)(state), [state]); const appOp = state.currentAppOp || nextAppOp; (0, react_1.useEffect)(() => { dispatch({ type: "reset", initialState: (0, logic_1.initState)(listResult, appsToRestore), }); }, [listResult, appsToRestore]); (0, react_1.useEffect)(() => { if (appOp) { const sub = (0, runner_1.runAppOp)({ state, appOp, exec }).subscribe(event => { dispatch({ type: "onRunnerEvent", event, }); }); return () => { sub.unsubscribe(); }; } // we only want to redo the effect on appOp changes here // eslint-disable-next-line react-hooks/exhaustive-deps }, [listResult, appOp, exec]); return [state, dispatch]; }; exports.useAppsRunner = useAppsRunner; function useNotEnoughMemoryToInstall(state, name) { return (0, react_1.useMemo)(() => (0, logic_1.isOutOfMemoryState)((0, logic_1.predictOptimisticState)((0, logic_1.reducer)(state, { type: "install", name, }))), [name, state]); } function useAppsSections(state, opts) { const { updateAllQueue, appByName, installed, installQueue, apps } = state; const appsUpdating = (0, react_1.useMemo)(() => updateAllQueue.map(name => appByName[name]).filter(Boolean), [appByName, updateAllQueue]); const updatableAppList = (0, react_1.useMemo)(() => apps.filter(({ name }) => installed.some(i => i.name === name && !i.updated)), [apps, installed]); const { getFeature, isFeature } = (0, featureFlags_1.useFeatureFlags)(); const update = appsUpdating.length > 0 ? appsUpdating : updatableAppList; const filterParam = (0, react_1.useMemo)(() => ({ query: opts.query, installedApps: installed, type: [opts.appFilter], getFeature, isFeature, }), [getFeature, installed, isFeature, opts.appFilter, opts.query]); const catalog = (0, filtering_1.useSortedFilteredApps)(apps, filterParam, opts.sort); const installedAppList = (0, filtering_1.useSortedFilteredApps)(apps, { query: opts.query, installedApps: installed, installQueue, type: ["installed"], getFeature, isFeature, }, { type: "default", order: "asc", }); const device = installedAppList.sort(({ name: _name }, { name }) => { // place install queue on top of list // with the app being installed at the top let pos1 = installQueue.indexOf(_name); let pos2 = installQueue.indexOf(name); pos1 = pos1 < 0 ? Number.MAX_VALUE : pos1; pos2 = pos2 < 0 ? Number.MAX_VALUE : pos2; return pos1 - pos2; }); return { update, catalog, device, }; } function useAppInstallProgress(state, name) { const { currentProgressSubject, currentAppOp } = state; const [progress, setProgress] = (0, react_1.useState)(0); (0, react_1.useEffect)(() => { if (!currentAppOp || !currentProgressSubject || currentAppOp.name !== name) { setProgress(0); return; } const sub = currentProgressSubject.subscribe(setProgress); return () => sub.unsubscribe(); }, [currentProgressSubject, currentAppOp, name]); if (currentProgressSubject && currentAppOp && currentAppOp.name === name) { return progress; } return 0; } // if the app needs deps to be installed, we want to display a modal // this should returns all params the modal also need (so we don't do things twice) function useAppInstallNeedsDeps(state, app) { const { appByName, installed: installedList, installQueue } = state; const res = (0, react_1.useMemo)(() => { const dependencies = (app.dependencies || []) .map(name => appByName[name]) .filter(dep => dep && !installedList.some(app => app.name === dep.name) && !installQueue.includes(dep.name)); if (dependencies.length) { return { app, dependencies, }; } return null; }, [appByName, app, installQueue, installedList]); return res; } // if the app needs deps to be installed, we want to display a modal // this should returns all params the modal also need (so we don't do things twice) function useAppUninstallNeedsDeps(state, app) { const { apps, installed } = state; const res = (0, react_1.useMemo)(() => { const dependents = apps.filter(a => installed.some(i => i.name === a.name) && a.dependencies.includes(app.name)); if (dependents.length) { return { dependents, app, }; } return null; }, [app, apps, installed]); return res; } //# sourceMappingURL=react.js.map