94 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			94 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
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;
 | 
						|
  }
 | 
						|
}
 |