modal.ts 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import type { Reducer } from '@reduxjs/toolkit';
  2. import { Record as ImmutableRecord, Stack } from 'immutable';
  3. import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose';
  4. import type { ModalType } from '../actions/modal';
  5. import { openModal, closeModal } from '../actions/modal';
  6. import { TIMELINE_DELETE } from '../actions/timelines';
  7. export type ModalProps = Record<string, unknown>;
  8. interface Modal {
  9. modalType: ModalType;
  10. modalProps: ModalProps;
  11. }
  12. const Modal = ImmutableRecord<Modal>({
  13. modalType: 'ACTIONS',
  14. modalProps: ImmutableRecord({})(),
  15. });
  16. interface ModalState {
  17. ignoreFocus: boolean;
  18. stack: Stack<ImmutableRecord<Modal>>;
  19. }
  20. const initialState = ImmutableRecord<ModalState>({
  21. ignoreFocus: false,
  22. stack: Stack(),
  23. })();
  24. type State = typeof initialState;
  25. interface PopModalOption {
  26. modalType: ModalType | undefined;
  27. ignoreFocus: boolean;
  28. }
  29. const popModal = (
  30. state: State,
  31. { modalType, ignoreFocus }: PopModalOption,
  32. ): State => {
  33. if (
  34. modalType === undefined ||
  35. modalType === state.get('stack').get(0)?.get('modalType')
  36. ) {
  37. return state
  38. .set('ignoreFocus', !!ignoreFocus)
  39. .update('stack', (stack) => stack.shift());
  40. } else {
  41. return state;
  42. }
  43. };
  44. const pushModal = (
  45. state: State,
  46. modalType: ModalType,
  47. modalProps: ModalProps,
  48. ): State => {
  49. return state.withMutations((record) => {
  50. record.set('ignoreFocus', false);
  51. record.update('stack', (stack) =>
  52. stack.unshift(Modal({ modalType, modalProps })),
  53. );
  54. });
  55. };
  56. export const modalReducer: Reducer<State> = (state = initialState, action) => {
  57. if (openModal.match(action))
  58. return pushModal(
  59. state,
  60. action.payload.modalType,
  61. action.payload.modalProps,
  62. );
  63. else if (closeModal.match(action)) return popModal(state, action.payload);
  64. // TODO: type those actions
  65. else if (action.type === COMPOSE_UPLOAD_CHANGE_SUCCESS)
  66. return popModal(state, { modalType: 'FOCAL_POINT', ignoreFocus: false });
  67. else if (action.type === TIMELINE_DELETE)
  68. return state.update('stack', (stack) =>
  69. stack.filterNot(
  70. (modal) => modal.get('modalProps').statusId === action.id,
  71. ),
  72. );
  73. else return state;
  74. };