SubNavButtons.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import React, {
  2. FC, useCallback, useState, useEffect,
  3. } from 'react';
  4. import AppContainer from '../../client/services/AppContainer';
  5. import NavigationContainer from '../../client/services/NavigationContainer';
  6. import { withUnstatedContainers } from '../UnstatedUtils';
  7. import PageReactionButtons from '../PageReactionButtons';
  8. import PageManagement from '../Page/PageManagement';
  9. import { useSWRPageInfo } from '../../stores/page';
  10. import { useSWRBookmarkInfo } from '../../stores/bookmark';
  11. import { toastError } from '../../client/util/apiNotification';
  12. import { apiv3Put } from '../../client/util/apiv3-client';
  13. import { useSWRxLikerList } from '../../stores/user';
  14. type SubNavButtonsProps= {
  15. appContainer: AppContainer,
  16. navigationContainer: NavigationContainer,
  17. isCompactMode?: boolean,
  18. pageId: string,
  19. revisionId: string,
  20. path: string,
  21. willShowPageManagement: boolean,
  22. isDeletable: boolean,
  23. isAbleToDeleteCompletely: boolean,
  24. }
  25. const SubNavButtons: FC<SubNavButtonsProps> = (props: SubNavButtonsProps) => {
  26. const {
  27. appContainer, navigationContainer, isCompactMode, pageId, revisionId, path, willShowPageManagement, isDeletable, isAbleToDeleteCompletely,
  28. } = props;
  29. const { editorMode } = navigationContainer.state;
  30. const isViewMode = editorMode === 'view';
  31. const { isGuestUser } = appContainer;
  32. const { data: pageInfo, error: pageInfoError, mutate: mutatePageInfo } = useSWRPageInfo(pageId);
  33. const { data: likers } = useSWRxLikerList(pageInfo?.likerIds);
  34. const { data: bookmarkInfo, error: bookmarkInfoError, mutate: mutateBookmarkInfo } = useSWRBookmarkInfo(pageId);
  35. const likeClickhandler = useCallback(async() => {
  36. const { isGuestUser } = appContainer;
  37. if (isGuestUser) {
  38. return;
  39. }
  40. try {
  41. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  42. await apiv3Put('/page/likes', { pageId, bool: !pageInfo!.isLiked });
  43. mutatePageInfo();
  44. }
  45. catch (err) {
  46. toastError(err);
  47. }
  48. }, [pageInfo]);
  49. const bookmarkClickHandler = useCallback(async() => {
  50. if (isGuestUser) {
  51. return;
  52. }
  53. try {
  54. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  55. await apiv3Put('/bookmarks', { pageId, bool: !bookmarkInfo!.isBookmarked });
  56. mutateBookmarkInfo();
  57. }
  58. catch (err) {
  59. toastError(err);
  60. }
  61. }, [bookmarkInfo]);
  62. if (pageInfoError != null || pageInfo == null) {
  63. return <></>;
  64. }
  65. if (bookmarkInfoError != null || bookmarkInfo == null) {
  66. return <></>;
  67. }
  68. const { sumOfLikers, isLiked } = pageInfo;
  69. const { sumOfBookmarks, isBookmarked } = bookmarkInfo;
  70. return (
  71. <>
  72. {isViewMode && (
  73. <PageReactionButtons
  74. sumOfLikers={sumOfLikers}
  75. isLiked={isLiked}
  76. likers={likers || []}
  77. onLikeClicked={likeClickhandler}
  78. sumOfBookmarks={sumOfBookmarks}
  79. isBookmarked={isBookmarked}
  80. onBookMarkClicked={bookmarkClickHandler}
  81. >
  82. </PageReactionButtons>
  83. )}
  84. {willShowPageManagement && (
  85. <PageManagement
  86. pageId={pageId}
  87. revisionId={revisionId}
  88. path={path}
  89. isCompactMode={isCompactMode}
  90. isDeletable={isDeletable}
  91. isAbleToDeleteCompletely={isAbleToDeleteCompletely}
  92. >
  93. </PageManagement>
  94. )}
  95. </>
  96. );
  97. };
  98. /**
  99. * Wrapper component for using unstated
  100. */
  101. const SubNavButtonsUnstatedWrapper = withUnstatedContainers(SubNavButtons, [AppContainer, NavigationContainer]);
  102. // wrapping tsx component returned by withUnstatedContainers to avoid type error when this component used in other tsx components.
  103. const SubNavButtonsWrapper = (props) => {
  104. return <SubNavButtonsUnstatedWrapper {...props}></SubNavButtonsUnstatedWrapper>;
  105. };
  106. export default SubNavButtonsWrapper;