PagePresentationModal.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import React, { useCallback } from 'react';
  2. import type { PresentationProps } from '@growi/presentation';
  3. import { useFullScreen } from '@growi/ui/dist/utils';
  4. import dynamic from 'next/dynamic';
  5. import type { ReactMarkdownOptions } from 'react-markdown/lib/react-markdown';
  6. import {
  7. Modal, ModalBody,
  8. } from 'reactstrap';
  9. import { useIsEnabledMarp } from '~/stores/context';
  10. import { usePagePresentationModal } from '~/stores/modal';
  11. import { useSWRxCurrentPage } from '~/stores/page';
  12. import { usePresentationViewOptions } from '~/stores/renderer';
  13. import { useNextThemes } from '~/stores/use-next-themes';
  14. import styles from './PagePresentationModal.module.scss';
  15. const Presentation = dynamic<PresentationProps>(() => import('./Presentation/Presentation').then(mod => mod.Presentation), {
  16. ssr: false,
  17. loading: () => (
  18. <i className="fa fa-4x fa-spinner fa-pulse text-muted"></i>
  19. ),
  20. });
  21. const PagePresentationModal = (): JSX.Element => {
  22. const { data: presentationModalData, close: closePresentationModal } = usePagePresentationModal();
  23. const { isDarkMode } = useNextThemes();
  24. const fullscreen = useFullScreen();
  25. const { data: currentPage } = useSWRxCurrentPage();
  26. const { data: rendererOptions } = usePresentationViewOptions();
  27. const { data: isEnabledMarp } = useIsEnabledMarp();
  28. const toggleFullscreenHandler = useCallback(() => {
  29. if (fullscreen.active) {
  30. fullscreen.exit();
  31. }
  32. else {
  33. fullscreen.enter();
  34. }
  35. }, [fullscreen]);
  36. const closeHandler = useCallback(() => {
  37. if (fullscreen.active) {
  38. fullscreen.exit();
  39. }
  40. closePresentationModal();
  41. }, [fullscreen, closePresentationModal]);
  42. const isOpen = presentationModalData?.isOpened ?? false;
  43. if (!isOpen) {
  44. return <></>;
  45. }
  46. const markdown = currentPage?.revision.body;
  47. return (
  48. <Modal
  49. isOpen={isOpen}
  50. toggle={closeHandler}
  51. data-testid="page-presentation-modal"
  52. className={`grw-presentation-modal ${styles['grw-presentation-modal']}`}
  53. >
  54. <div className="grw-presentation-controls d-flex">
  55. <button className="close btn-fullscreen" type="button" aria-label="fullscreen" onClick={toggleFullscreenHandler}>
  56. <i className={`${fullscreen.active ? 'icon-size-actual' : 'icon-size-fullscreen'}`} aria-hidden></i>
  57. </button>
  58. <button className="close btn-close" type="button" aria-label="close" onClick={closeHandler}>
  59. <i className="ti ti-close" aria-hidden></i>
  60. </button>
  61. </div>
  62. <ModalBody className="modal-body d-flex justify-content-center align-items-center">
  63. { rendererOptions != null && isEnabledMarp != null && (
  64. <Presentation
  65. options={{
  66. rendererOptions: rendererOptions as ReactMarkdownOptions,
  67. revealOptions: {
  68. embedded: true,
  69. hash: true,
  70. },
  71. isDarkMode,
  72. }}
  73. isEnabledMarp={isEnabledMarp}
  74. >
  75. {markdown}
  76. </Presentation>
  77. ) }
  78. </ModalBody>
  79. </Modal>
  80. );
  81. };
  82. export default PagePresentationModal;