import { toMap } from '@proton/shared/lib/helpers/object' ; import { Draft } from 'immer' ; import { PayloadAction } from '@reduxjs/toolkit' ; import isTruthy from '@proton/shared/lib/helpers/isTruthy' ; import { diff , range } from '@proton/shared/lib/helpers/array' ; import { Message } from '@proton/shared/lib/interfaces/mail/Message' ; import { newState } from './elementsSlice' ; import { ElementsState , ESResults , EventUpdates , NewStateParams , OptimisticDelete , OptimisticUpdates , QueryParams , QueryResults , RetryData , } from './elementsTypes' ; import { Element } from '../../models/element' ; import { isMessage as testIsMessage , parseLabelIDsInEvent } from '../../helpers/elements' ; import { newRetry } from './helpers/elementQuery' ; import { MAX_ELEMENT_LIST_LOAD_RETRIES , PAGE_SIZE } from '../../constants' ; export const globalReset = ( state ) => { Object . assign ( state , newState ( ) ) ; } ; export const reset = ( state , action ) => { Object . assign ( state , newState ( action . payload ) ) ; } ; export const updatePage = ( state , action ) => { state . page = action . payload ; } ; export const retry = ( state , action ) => { state . beforeFirstLoad = false ; state . invalidated = false ; state . pendingRequest = false ; state . retry = action . payload ; } ; export const loadPending = ( state , action ) => { state . pendingRequest = true ; state . page = action . meta . arg . page ; } ; export const loadFulfilled = ( state , action ) => { const { page , params } = action . meta . arg ; const { Total , Elements } = action . payload ; Object . assign ( state , { beforeFirstLoad : false , invalidated : false , pendingRequest : false , page , total : Total , retry : newRetry ( state . retry , params , undefined ) , } ) ; state . pages . push ( page ) ; Object . assign ( state . elements , toMap ( Elements , 'ID' ) ) ; } ; export const manualPending = ( state ) => { state . pendingRequest = true ; } ; export const manualFulfilled = ( state ) => { state . pendingRequest = false ; } ; export const removeExpired = ( state , action ) => { delete state . elements [ action . payload . ID || '' ] ; } ; export const invalidate = ( state ) => { state . invalidated = true ; } ; export const eventUpdatesPending = ( state , action ) => { const { toCreate , toUpdate , toDelete } = action . meta . arg ; toCreate . forEach ( ( element ) => { state . elements [ element . ID || '' ] = element ; } ) ; toUpdate . forEach ( ( element ) => { const existingElement = state . elements [ element . ID || '' ] ; if ( existingElement ) { state . elements [ element . ID || '' ] = parseLabelIDsInEvent ( existingElement , element ) ; } } ) ; toDelete . forEach ( ( elementID ) => { delete state . elements [ elementID ] ; } ) ; } ; export const eventUpdatesFulfilled = ( state , action ) => { action . payload . filter ( isTruthy ) . forEach ( ( element ) => { state . elements [ element . ID || '' ] = element ; } ) ; } ; export const addESResults = ( state , action ) => { const total = action . payload . elements . length ; const pages = range ( 0 , Math . ceil ( total / PAGE_SIZE ) ) ; Object . assign ( state , { bypassFilter : [ ] , beforeFirstLoad : false , invalidated : false , pendingRequest : false , page : action . payload . page , total , pages , elements : toMap ( action . payload . elements , 'ID' ) , retry : { payload : undefined , count : MAX_ELEMENT_LIST_LOAD_RETRIES , error : undefined } , } ) ; } ; export const optimisticUpdates = ( state , action ) => { action . payload . elements . forEach ( ( element ) => { if ( element . ID ) { state . elements [ element . ID ] = element ; } } ) ; if ( action . payload . isMove ) { const elementIDs = action . payload . elements . map ( ( { ID } ) => ID || '' ) ; state . bypassFilter = diff ( state . bypassFilter , elementIDs ) ; } if ( action . payload . bypass ) { const { conversationMode } = action . payload ; action . payload . elements . forEach ( ( element ) => { const isMessage = testIsMessage ( element ) ; const id = ( isMessage && conversationMode ? ( element as Message ) . ConversationID : element . ID ) || '' ; if ( ! state . bypassFilter . includes ( id ) ) { state . bypassFilter . push ( id ) ; } } ) ; } } ; export const optimisticDelete = ( state , action ) => { action . payload . elementIDs . forEach ( ( elementID ) => { delete state . elements [ elementID ] ; } ) ; } ; export const optimisticEmptyLabel = ( state ) => { state . elements = { } ; state . page = 0 ; } ;