// Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import type { ReadonlyDeep } from 'type-fest'; // State // eslint-disable-next-line local-rules/type-alias-readonlydeep export type InboxStateType = Readonly<{ firstEnvelopeTimestamp: number | undefined; envelopeTimestamp: number | undefined; }>; // Actions const SET_ENVELOPE_TIMESTAMP = 'INBOX/SET_INBOX_ENVELOPE_TIMESTAMP'; type SetInboxEnvelopeTimestampActionType = ReadonlyDeep<{ type: typeof SET_ENVELOPE_TIMESTAMP; payload: { envelopeTimestamp: number | undefined; }; }>; export type InboxActionType = ReadonlyDeep; // Action Creators export const actions = { setInboxEnvelopeTimestamp, }; function setInboxEnvelopeTimestamp( envelopeTimestamp: number | undefined ): SetInboxEnvelopeTimestampActionType { return { type: SET_ENVELOPE_TIMESTAMP, payload: { envelopeTimestamp }, }; } // Reducer export function getEmptyState(): InboxStateType { return { firstEnvelopeTimestamp: undefined, envelopeTimestamp: undefined, }; } export function reducer( state: Readonly = getEmptyState(), action: Readonly ): InboxStateType { if (!state) { return getEmptyState(); } if (action.type === SET_ENVELOPE_TIMESTAMP) { const { payload } = action; const { envelopeTimestamp: providedTimestamp } = payload; // Ensure monotonicity let { envelopeTimestamp } = state; if (providedTimestamp !== undefined) { envelopeTimestamp = Math.max( providedTimestamp, envelopeTimestamp ?? providedTimestamp ); } const firstEnvelopeTimestamp = state.firstEnvelopeTimestamp ?? envelopeTimestamp; return { ...state, envelopeTimestamp, firstEnvelopeTimestamp, }; } return state; }