1 import type { Action, Reducer } from 'redux';
3 import { objectDelete } from '@proton/pass/utils/object/delete';
4 import { partialMerge } from '@proton/pass/utils/object/merge';
5 import { getEpoch } from '@proton/pass/utils/time/epoch';
7 import { requestInvalidate, requestProgress } from './actions';
8 import type { RequestState } from './types';
9 import { isActionWithRequest } from './utils';
11 const requestReducer: Reducer<RequestState> = (state = {}, action: Action) => {
12 if (isActionWithRequest(action)) {
13 const { request } = action.meta;
14 const nextState = { ...state };
16 switch (request.status) {
18 nextState[request.id] = {
28 const ongoing = nextState[request.id];
29 if (ongoing?.status !== 'start') return state;
30 nextState[request.id] = { ...ongoing, progress: request.progress };
36 return objectDelete(state, request.id);
40 const now = getEpoch();
41 if (!request.maxAge) return objectDelete(state, request.id);
43 /** If there was a `maxAge` specified, store the
44 * resulting payload in the `data` field. This should
45 * ideally only be used for state not being tracked in
46 * any other reducer (HOT data) */
47 nextState[request.id] = {
48 status: request.status,
49 maxAge: request.maxAge,
52 if ('data' in request) return request.data;
53 if ('payload' in action) return action.payload;
62 if (requestProgress.match(action) && state[action.payload.requestId]?.status === 'start') {
63 return partialMerge(state, {
64 [action.payload.requestId]: { progress: action.payload.progress },
68 if (requestInvalidate.match(action)) return objectDelete(state, action.payload.requestId);
73 export default requestReducer;