| 1 | export interface IncomingSharePresentationState { |
| 2 | readonly presentedShareId: string | null; |
| 3 | readonly dismissedShareId: string | null; |
| 4 | } |
| 5 | |
| 6 | export interface IncomingSharePresentationTransition { |
| 7 | readonly state: IncomingSharePresentationState; |
| 8 | readonly shareIdToPresent: string | null; |
| 9 | } |
| 10 | |
| 11 | export const EMPTY_INCOMING_SHARE_PRESENTATION_STATE: IncomingSharePresentationState = { |
| 12 | presentedShareId: null, |
| 13 | dismissedShareId: null, |
| 14 | }; |
| 15 | |
| 16 | /** |
| 17 | * Tracks presentation by durable share id rather than object identity. A user |
| 18 | * dismissal suppresses only that inbox item until it is consumed or replaced. |
| 19 | */ |
| 20 | export function transitionIncomingSharePresentation( |
| 21 | state: IncomingSharePresentationState, |
| 22 | input: { |
| 23 | readonly isShareSheetPresented: boolean; |
| 24 | readonly pendingShareId: string | null; |
| 25 | }, |
| 26 | ): IncomingSharePresentationTransition { |
| 27 | if (input.isShareSheetPresented) { |
| 28 | if (state.presentedShareId !== null && input.pendingShareId !== state.presentedShareId) { |
| 29 | // Consumption may happen while the sheet remains mounted. Forget the |
| 30 | // old presentation immediately so a later handoff may reuse its id. |
| 31 | return { |
| 32 | state: EMPTY_INCOMING_SHARE_PRESENTATION_STATE, |
| 33 | shareIdToPresent: null, |
| 34 | }; |
| 35 | } |
| 36 | return { state, shareIdToPresent: null }; |
| 37 | } |
| 38 | |
| 39 | let nextState = state; |
| 40 | if (state.presentedShareId !== null) { |
| 41 | if (input.pendingShareId === state.presentedShareId) { |
| 42 | return { |
| 43 | state: { |
| 44 | presentedShareId: null, |
| 45 | dismissedShareId: state.presentedShareId, |
| 46 | }, |
| 47 | shareIdToPresent: null, |
| 48 | }; |
| 49 | } |
| 50 | nextState = { ...state, presentedShareId: null }; |
| 51 | } |
| 52 | |
| 53 | if (input.pendingShareId === null) { |
| 54 | return { |
| 55 | state: EMPTY_INCOMING_SHARE_PRESENTATION_STATE, |
| 56 | shareIdToPresent: null, |
| 57 | }; |
| 58 | } |
| 59 | |
| 60 | if (nextState.dismissedShareId === input.pendingShareId) { |
| 61 | return { state: nextState, shareIdToPresent: null }; |
| 62 | } |
| 63 | |
| 64 | return { |
| 65 | state: { |
| 66 | presentedShareId: input.pendingShareId, |
| 67 | dismissedShareId: null, |
| 68 | }, |
| 69 | shareIdToPresent: input.pendingShareId, |
| 70 | }; |
| 71 | } |