SubNavButtons.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import React, { useCallback } from 'react';
  2. import { IPageInfoAll, isIPageInfoForEntity, isIPageInfoForOperation } from '~/interfaces/page';
  3. import { useSWRxPageInfo } from '../../stores/page';
  4. import { useSWRBookmarkInfo } from '../../stores/bookmark';
  5. import { useSWRxUsersList } from '../../stores/user';
  6. import { useIsGuestUser } from '~/stores/context';
  7. import SubscribeButton from '../SubscribeButton';
  8. import LikeButtons from '../LikeButtons';
  9. import BookmarkButtons from '../BookmarkButtons';
  10. import SeenUserInfo from '../User/SeenUserInfo';
  11. import { toggleBookmark, toggleLike, toggleSubscribe } from '~/client/services/page-operation';
  12. import { AdditionalMenuItemsRendererProps, PageItemControl } from '../Common/Dropdown/PageItemControl';
  13. type CommonProps = {
  14. isCompactMode?: boolean,
  15. disableSeenUserInfoPopover?: boolean,
  16. showPageControlDropdown?: boolean,
  17. additionalMenuItemRenderer?: React.FunctionComponent<AdditionalMenuItemsRendererProps>,
  18. }
  19. type SubNavButtonsSubstanceProps= CommonProps & {
  20. pageId: string,
  21. revisionId: string,
  22. pageInfo: IPageInfoAll,
  23. }
  24. const SubNavButtonsSubstance = (props: SubNavButtonsSubstanceProps): JSX.Element => {
  25. const {
  26. pageInfo, pageId, isCompactMode, disableSeenUserInfoPopover, showPageControlDropdown, additionalMenuItemRenderer,
  27. } = props;
  28. const { data: isGuestUser } = useIsGuestUser();
  29. const { mutate: mutatePageInfo } = useSWRxPageInfo(pageId);
  30. const { data: bookmarkInfo, mutate: mutateBookmarkInfo } = useSWRBookmarkInfo(pageId);
  31. const likerIds = isIPageInfoForEntity(pageInfo) ? (pageInfo.likerIds ?? []).slice(0, 15) : [];
  32. const seenUserIds = isIPageInfoForEntity(pageInfo) ? (pageInfo.seenUserIds ?? []).slice(0, 15) : [];
  33. // Put in a mixture of seenUserIds and likerIds data to make the cache work
  34. const { data: usersList } = useSWRxUsersList([...likerIds, ...seenUserIds]);
  35. const likers = usersList != null ? usersList.filter(({ _id }) => likerIds.includes(_id)).slice(0, 15) : [];
  36. const seenUsers = usersList != null ? usersList.filter(({ _id }) => seenUserIds.includes(_id)).slice(0, 15) : [];
  37. const subscribeClickhandler = useCallback(async() => {
  38. if (isGuestUser == null || isGuestUser) {
  39. return;
  40. }
  41. if (!isIPageInfoForOperation(pageInfo)) {
  42. return;
  43. }
  44. await toggleSubscribe(pageId, pageInfo.subscriptionStatus);
  45. mutatePageInfo();
  46. }, [isGuestUser, mutatePageInfo, pageId, pageInfo]);
  47. const likeClickhandler = useCallback(async() => {
  48. if (isGuestUser == null || isGuestUser) {
  49. return;
  50. }
  51. if (!isIPageInfoForOperation(pageInfo)) {
  52. return;
  53. }
  54. await toggleLike(pageId, pageInfo.isLiked);
  55. mutatePageInfo();
  56. }, [isGuestUser, mutatePageInfo, pageId, pageInfo]);
  57. const bookmarkClickHandler = useCallback(async() => {
  58. if (isGuestUser == null || isGuestUser) {
  59. return;
  60. }
  61. if (!isIPageInfoForOperation(pageInfo)) {
  62. return;
  63. }
  64. await toggleBookmark(pageId, pageInfo.isBookmarked);
  65. mutatePageInfo();
  66. mutateBookmarkInfo();
  67. }, [isGuestUser, mutateBookmarkInfo, mutatePageInfo, pageId, pageInfo]);
  68. if (!isIPageInfoForOperation(pageInfo)) {
  69. return <></>;
  70. }
  71. const {
  72. sumOfLikers, isLiked, bookmarkCount, isBookmarked,
  73. } = pageInfo;
  74. return (
  75. <div className="d-flex" style={{ gap: '2px' }}>
  76. <span>
  77. <SubscribeButton
  78. status={pageInfo.subscriptionStatus}
  79. onClick={subscribeClickhandler}
  80. />
  81. </span>
  82. <LikeButtons
  83. hideTotalNumber={isCompactMode}
  84. onLikeClicked={likeClickhandler}
  85. sumOfLikers={sumOfLikers}
  86. isLiked={isLiked}
  87. likers={likers}
  88. />
  89. <BookmarkButtons
  90. hideTotalNumber={isCompactMode}
  91. bookmarkCount={bookmarkCount}
  92. isBookmarked={isBookmarked}
  93. bookmarkedUsers={bookmarkInfo?.bookmarkedUsers}
  94. onBookMarkClicked={bookmarkClickHandler}
  95. />
  96. <SeenUserInfo seenUsers={seenUsers} disabled={disableSeenUserInfoPopover} />
  97. { showPageControlDropdown && (
  98. <PageItemControl
  99. pageId={pageId}
  100. pageInfo={pageInfo}
  101. isEnableActions={!isGuestUser}
  102. additionalMenuItemRenderer={additionalMenuItemRenderer}
  103. hideBookmarkMenuItem
  104. />
  105. // <PageManagement
  106. // pageId={pageId}
  107. // revisionId={revisionId}
  108. // path={path}
  109. // isCompactMode={isCompactMode}
  110. // isDeletable={isDeletable}
  111. // isAbleToDeleteCompletely={isAbleToDeleteCompletely}
  112. // >
  113. // </PageManagement>
  114. )}
  115. </div>
  116. );
  117. };
  118. type SubNavButtonsProps= CommonProps & {
  119. pageId: string,
  120. revisionId?: string | null,
  121. };
  122. export const SubNavButtons = (props: SubNavButtonsProps): JSX.Element => {
  123. const { pageId, revisionId } = props;
  124. const { data: pageInfo, error } = useSWRxPageInfo(pageId ?? null);
  125. if (revisionId == null || error != null) {
  126. return <></>;
  127. }
  128. if (!isIPageInfoForOperation(pageInfo)) {
  129. return <></>;
  130. }
  131. return <SubNavButtonsSubstance {...props} pageInfo={pageInfo} pageId={pageId} revisionId={revisionId} />;
  132. };