UNPKG

@ledgerhq/live-common

Version:
74 lines 2.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SYNC_SETTLE_GUARD_MS = void 0; exports.useSyncLifecycle = useSyncLifecycle; const react_1 = require("react"); function syncPhaseReducer(state, action) { switch (action.type) { case "SYNC_BEGIN": return "syncing"; case "SYNC_COMPLETE": return action.hasError ? "failed" : "synced"; default: return state; } } function getInitialSyncPhase(isBalanceLoading, hasAnySyncError) { if (isBalanceLoading) return "syncing"; if (hasAnySyncError) return "failed"; return "synced"; } /** * After `isSyncSettled` becomes true while leaving a syncing cycle, wait this * long before committing the phase. If `isSyncSettled` bounces back to false * during this window (sub-account discovery, retry, etc.), the timer resets. * This prevents the syncing → synced → failed flash. */ exports.SYNC_SETTLE_GUARD_MS = 3_000; /** * FSM driving the TopBar indicator and balance shimmer. * * Phases: syncing -> synced | failed. * * SYNC_BEGIN fires on cold start / manual refresh. * SYNC_COMPLETE fires on settle, deferred by SYNC_SETTLE_GUARD_MS * when leaving syncing to absorb bouncing settle states. */ function useSyncLifecycle(isBalanceLoading, stableSyncPending, hasAnySyncError) { const isSyncSettled = !isBalanceLoading && !stableSyncPending; const hasAnySyncErrorRef = (0, react_1.useRef)(hasAnySyncError); hasAnySyncErrorRef.current = hasAnySyncError; const prevSettledRef = (0, react_1.useRef)(isSyncSettled); const wasSyncingRef = (0, react_1.useRef)(!isSyncSettled); const [phase, dispatch] = (0, react_1.useReducer)(syncPhaseReducer, getInitialSyncPhase(isBalanceLoading, hasAnySyncError)); (0, react_1.useEffect)(() => { if (isBalanceLoading) { wasSyncingRef.current = true; dispatch({ type: "SYNC_BEGIN" }); } }, [isBalanceLoading]); (0, react_1.useEffect)(() => { const wasSettled = prevSettledRef.current; prevSettledRef.current = isSyncSettled; if (!isSyncSettled || wasSettled) return; if (wasSyncingRef.current) { if (hasAnySyncErrorRef.current) { wasSyncingRef.current = false; dispatch({ type: "SYNC_COMPLETE", hasError: true }); return; } const timer = setTimeout(() => { wasSyncingRef.current = false; dispatch({ type: "SYNC_COMPLETE", hasError: hasAnySyncErrorRef.current }); }, exports.SYNC_SETTLE_GUARD_MS); return () => clearTimeout(timer); } dispatch({ type: "SYNC_COMPLETE", hasError: hasAnySyncErrorRef.current }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [isSyncSettled]); return phase; } //# sourceMappingURL=useSyncLifecycle.js.map