NestedPage.hooks.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import { useCallback, useEffect, useMemo } from 'react';
  2. import { PageController } from '$app/stores/effects/workspace/page/page_controller';
  3. import { Page, pagesActions } from '$app_reducers/pages/slice';
  4. import { useAppDispatch, useAppSelector } from '$app/stores/store';
  5. import { ViewLayoutPB } from '@/services/backend';
  6. import { useNavigate, useParams } from 'react-router-dom';
  7. import { pageTypeMap } from '$app/constants';
  8. import { useTranslation } from 'react-i18next';
  9. export function useLoadChildPages(pageId: string) {
  10. const dispatch = useAppDispatch();
  11. const childPages = useAppSelector((state) => state.pages.childPages[pageId]);
  12. const collapsed = useAppSelector((state) => !state.pages.expandedPages[pageId]);
  13. const toggleCollapsed = useCallback(() => {
  14. if (collapsed) {
  15. dispatch(pagesActions.expandPage(pageId));
  16. } else {
  17. dispatch(pagesActions.collapsePage(pageId));
  18. }
  19. }, [dispatch, pageId, collapsed]);
  20. const controller = useMemo(() => {
  21. return new PageController(pageId);
  22. }, [pageId]);
  23. const onChildPagesChanged = useCallback(
  24. (childPages: Page[]) => {
  25. dispatch(
  26. pagesActions.addChildPages({
  27. id: pageId,
  28. childPages,
  29. })
  30. );
  31. },
  32. [dispatch, pageId]
  33. );
  34. const onPageCollapsed = useCallback(async () => {
  35. dispatch(pagesActions.removeChildPages(pageId));
  36. await controller.unsubscribe();
  37. }, [dispatch, pageId, controller]);
  38. const onPageExpanded = useCallback(async () => {
  39. const childPages = await controller.getChildPages();
  40. dispatch(
  41. pagesActions.addChildPages({
  42. id: pageId,
  43. childPages,
  44. })
  45. );
  46. await controller.subscribe({
  47. onChildPagesChanged,
  48. });
  49. }, [controller, dispatch, onChildPagesChanged, pageId]);
  50. useEffect(() => {
  51. if (collapsed) {
  52. onPageCollapsed();
  53. } else {
  54. onPageExpanded();
  55. }
  56. }, [collapsed, onPageCollapsed, onPageExpanded]);
  57. useEffect(() => {
  58. return () => {
  59. controller.dispose();
  60. };
  61. }, [controller]);
  62. return {
  63. toggleCollapsed,
  64. collapsed,
  65. childPages,
  66. };
  67. }
  68. export function usePageActions(pageId: string) {
  69. const page = useAppSelector((state) => state.pages.map[pageId]);
  70. const { t } = useTranslation();
  71. const dispatch = useAppDispatch();
  72. const navigate = useNavigate();
  73. const controller = useMemo(() => {
  74. return new PageController(pageId);
  75. }, [pageId]);
  76. const onPageClick = useCallback(() => {
  77. const pageType = pageTypeMap[page.layout];
  78. navigate(`/page/${pageType}/${pageId}`);
  79. }, [navigate, page.layout, pageId]);
  80. const onAddPage = useCallback(
  81. async (layout: ViewLayoutPB) => {
  82. const newViewId = await controller.createPage({
  83. layout,
  84. name: t('document.title.placeholder'),
  85. });
  86. dispatch(pagesActions.expandPage(pageId));
  87. const pageType = pageTypeMap[layout];
  88. navigate(`/page/${pageType}/${newViewId}`);
  89. },
  90. [t, controller, dispatch, navigate, pageId]
  91. );
  92. const onDeletePage = useCallback(async () => {
  93. await controller.deletePage();
  94. }, [controller]);
  95. const onDuplicatePage = useCallback(async () => {
  96. await controller.duplicatePage();
  97. }, [controller]);
  98. const onRenamePage = useCallback(
  99. async (name: string) => {
  100. await controller.updatePage({
  101. id: pageId,
  102. name,
  103. });
  104. },
  105. [controller, pageId]
  106. );
  107. useEffect(() => {
  108. return () => {
  109. controller.dispose();
  110. };
  111. }, [controller]);
  112. return {
  113. onAddPage,
  114. onPageClick,
  115. onRenamePage,
  116. onDeletePage,
  117. onDuplicatePage,
  118. };
  119. }
  120. export function useSelectedPage(pageId: string) {
  121. const id = useParams().id;
  122. return id === pageId;
  123. }