~cytrogen/masto-fe

ref: abdb58840ae4d1e6c5e0355952871bcff62ffbc5 masto-fe/app/javascript/flavours/glitch/reducers/modal.ts -rw-r--r-- 2.3 KiB
abdb5884 — Claire Merge commit '57f592fed50747f3c97718a2761e17bafe6c8698' into glitch-soc/merge-upstream 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { Record as ImmutableRecord, Stack } from 'immutable';

import type { PayloadAction } from '@reduxjs/toolkit';

import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose';
import type { ModalType } from '../actions/modal';
import { openModal, closeModal } from '../actions/modal';
import { TIMELINE_DELETE } from '../actions/timelines';

type ModalProps = Record<string, unknown>;
interface Modal {
  modalType: ModalType;
  modalProps: ModalProps;
}

const Modal = ImmutableRecord<Modal>({
  modalType: 'ACTIONS',
  modalProps: ImmutableRecord({})(),
});

interface ModalState {
  ignoreFocus: boolean;
  stack: Stack<ImmutableRecord<Modal>>;
}

const initialState = ImmutableRecord<ModalState>({
  ignoreFocus: false,
  stack: Stack(),
})();
type State = typeof initialState;

interface PopModalOption {
  modalType: ModalType | undefined;
  ignoreFocus: boolean;
}
const popModal = (
  state: State,
  { modalType, ignoreFocus }: PopModalOption,
): State => {
  if (
    modalType === undefined ||
    modalType === state.get('stack').get(0)?.get('modalType')
  ) {
    return state
      .set('ignoreFocus', !!ignoreFocus)
      .update('stack', (stack) => stack.shift());
  } else {
    return state;
  }
};

const pushModal = (
  state: State,
  modalType: ModalType,
  modalProps: ModalProps,
): State => {
  return state.withMutations((record) => {
    record.set('ignoreFocus', false);
    record.update('stack', (stack) =>
      stack.unshift(Modal({ modalType, modalProps })),
    );
  });
};

export function modalReducer(
  state: State = initialState,
  action: PayloadAction<{
    modalType: ModalType;
    ignoreFocus: boolean;
    modalProps: Record<string, unknown>;
  }>,
) {
  switch (action.type) {
    case openModal.type:
      return pushModal(
        state,
        action.payload.modalType,
        action.payload.modalProps,
      );
    case closeModal.type:
      return popModal(state, action.payload);
    case COMPOSE_UPLOAD_CHANGE_SUCCESS:
      return popModal(state, { modalType: 'FOCAL_POINT', ignoreFocus: false });
    case TIMELINE_DELETE:
      return state.update('stack', (stack) =>
        stack.filterNot(
          // @ts-expect-error TIMELINE_DELETE action is not typed yet.
          (modal) => modal.get('modalProps').statusId === action.id,
        ),
      );
    default:
      return state;
  }
}