Skip to content

Commit

Permalink
Merge pull request #2098 from daostack/feature/CW-2045-enable-follow-…
Browse files Browse the repository at this point in the history
…space

Enable follow\unfollow space #2045
  • Loading branch information
MeyerPV authored Sep 25, 2023
2 parents 8b99305 + 9f3248e commit 527b63e
Show file tree
Hide file tree
Showing 34 changed files with 448 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@ const DiscussionFeedCard = forwardRef<FeedItemRef, DiscussionFeedCardProps>(
fetchFeedItemUserMetadata,
} = useFeedItemUserMetadata();
const { data: common } = useCommon(isHome ? commonId : "");
const feedItemFollow = useFeedItemFollow(item.id, commonId);
const feedItemFollow = useFeedItemFollow(
{ feedItemId: item.id, commonId },
{ withSubscription: true },
);
const menuItems = useMenuItems(
{
commonId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,10 @@ const ProposalFeedCard = forwardRef<FeedItemRef, ProposalFeedCardProps>(
onOpen: onShareModalOpen,
onClose: onShareModalClose,
} = useModal(false);
const feedItemFollow = useFeedItemFollow(item.id, commonId);
const feedItemFollow = useFeedItemFollow(
{ feedItemId: item.id, commonId },
{ withSubscription: true },
);
const menuItems = useMenuItems(
{
commonId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ interface FollowFeedItemButtonProps {

const FollowFeedItemButton: FC<FollowFeedItemButtonProps> = (props) => {
const { feedItemId, commonId } = props;
const { isDisabled, isFollowing, onFollowToggle } = useFeedItemFollow(
const { isDisabled, isFollowing, onFollowToggle } = useFeedItemFollow({
feedItemId,
commonId,
);
});

return (
<ButtonIcon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@
overflow: hidden;
}

.commonMainInfoWrapper {
display: flex;
align-items: center;
column-gap: 8px;
}

.commonName {
margin: 0;
font-family: PoppinsSans, sans-serif;
Expand Down
28 changes: 17 additions & 11 deletions src/pages/commonFeed/components/HeaderContent/HeaderContent.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { FC } from "react";
import { NavLink } from "react-router-dom";
import classNames from "classnames";
import { InviteFriendsButton } from "@/pages/common/components";
import { useRoutesContext } from "@/shared/contexts";
import { useCommonFollow } from "@/shared/hooks/useCases";
import { useIsTabletView } from "@/shared/hooks/viewport";
import { RightArrowThinIcon } from "@/shared/icons";
import { RightArrowThinIcon, StarIcon } from "@/shared/icons";
import {
CirclesPermissions,
Common,
Expand All @@ -13,7 +13,7 @@ import {
} from "@/shared/models";
import { CommonAvatar, TopNavigationOpenSidenavButton } from "@/shared/ui-kit";
import { checkIsProject, getPluralEnding } from "@/shared/utils";
import { NewStreamButton, ShareButton } from "./components";
import { ActionsButton, NewStreamButton } from "./components";
import styles from "./HeaderContent.module.scss";

interface HeaderContentProps {
Expand All @@ -29,7 +29,11 @@ const HeaderContent: FC<HeaderContentProps> = (props) => {
props;
const { getCommonPageAboutTabPath } = useRoutesContext();
const isMobileVersion = useIsTabletView();
const commonFollow = useCommonFollow(common.id, commonMember);
const isProject = checkIsProject(common);
const showFollowIcon = commonFollow.isFollowInProgress
? !commonMember?.isFollowing
: commonMember?.isFollowing;

return (
<div className={classNames(styles.container, className)}>
Expand All @@ -52,7 +56,10 @@ const HeaderContent: FC<HeaderContentProps> = (props) => {
/>

<div className={styles.commonInfoWrapper}>
<h1 className={styles.commonName}>{common.name}</h1>
<div className={styles.commonMainInfoWrapper}>
<h1 className={styles.commonName}>{common.name}</h1>
{showFollowIcon && <StarIcon stroke="currentColor" />}
</div>
<p className={styles.commonMembersAmount}>
{commonMembersAmount} member{getPluralEnding(commonMembersAmount)}
</p>
Expand All @@ -66,13 +73,12 @@ const HeaderContent: FC<HeaderContentProps> = (props) => {
governance={governance}
isMobileVersion={isMobileVersion}
/>
{!isMobileVersion && (
<InviteFriendsButton
isMobileVersion={isMobileVersion}
common={common}
TriggerComponent={ShareButton}
/>
)}
<ActionsButton
common={common}
commonMember={commonMember}
commonFollow={commonFollow}
isMobileVersion={isMobileVersion}
/>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, { FC } from "react";
import { ShareModal } from "@/shared/components";
import { useModal } from "@/shared/hooks";
import { CommonFollowState } from "@/shared/hooks/useCases/useCommonFollow";
import { CirclesPermissions, Common, CommonMember } from "@/shared/models";
import { DesktopMenu, MenuButton } from "@/shared/ui-kit";
import { StaticLinkType, generateStaticShareLink } from "@/shared/utils";
import { useMenuItems } from "./hooks";

interface ActionsButtonProps {
common: Common;
commonMember: (CommonMember & CirclesPermissions) | null;
commonFollow: CommonFollowState;
isMobileVersion: boolean;
}

const ActionsButton: FC<ActionsButtonProps> = (props) => {
const { common, commonMember, commonFollow, isMobileVersion } = props;
const {
isShowing: isShareModalOpen,
onOpen: onShareModalOpen,
onClose: onShareModalClose,
} = useModal(false);
const items = useMenuItems(
{
common,
commonMember,
isMobileVersion,
isFollowInProgress: commonFollow.isFollowInProgress,
},
{
share: onShareModalOpen,
onFollowToggle: commonFollow.onFollowToggle,
},
);
const shareLink = generateStaticShareLink(StaticLinkType.Common, common);

return (
<>
{items.length > 0 && (
<DesktopMenu triggerEl={<MenuButton />} items={items} />
)}
<ShareModal
sourceUrl={shareLink}
isShowing={isShareModalOpen}
onClose={onShareModalClose}
/>
</>
);
};

export default ActionsButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./useMenuItems";
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from "react";
import { CommonFollowState } from "@/shared/hooks/useCases";
import { FollowIcon, Share3Icon, UnfollowIcon } from "@/shared/icons";
import { MenuItem as Item } from "@/shared/interfaces";
import { CommonFeedMenuItem } from "../../../../../constants";
import {
Options as GetAllowedItemsOptions,
getAllowedItems,
} from "../../../../../utils";

interface Actions {
share: () => void;
onFollowToggle: CommonFollowState["onFollowToggle"];
}

export const useMenuItems = (
options: GetAllowedItemsOptions,
actions: Actions,
): Item[] => {
const { common } = options;
const { share, onFollowToggle } = actions;

const items: Item[] = [
{
id: CommonFeedMenuItem.Share,
text: "Share",
onClick: share,
icon: <Share3Icon />,
},
{
id: CommonFeedMenuItem.Follow,
text: `Follow ${common.name}`,
onClick: () => onFollowToggle(),
icon: <FollowIcon />,
},
{
id: CommonFeedMenuItem.Mute,
text: `Unfollow ${common.name}`,
onClick: () => onFollowToggle(),
icon: <UnfollowIcon />,
},
];

return getAllowedItems(items, options);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as ActionsButton } from "./ActionsButton";
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./NewStreamButton";
export * from "./ShareButton";
export * from "./ActionsButton";
5 changes: 5 additions & 0 deletions src/pages/commonFeed/constants/commonFeedMenuItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum CommonFeedMenuItem {
Share = "share",
Follow = "follow",
Mute = "mute",
}
3 changes: 2 additions & 1 deletion src/pages/commonFeed/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const MIN_CHAT_WIDTH = 384;
export * from "./commonFeedMenuItem";
export * from "./minChatWidth";
1 change: 1 addition & 0 deletions src/pages/commonFeed/constants/minChatWidth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const MIN_CHAT_WIDTH = 384;
24 changes: 24 additions & 0 deletions src/pages/commonFeed/utils/getAllowedItems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { MenuItem as Item } from "@/shared/interfaces";
import { CirclesPermissions, Common, CommonMember } from "@/shared/models";
import { CommonFeedMenuItem } from "../constants";

export interface Options {
common: Common;
commonMember: (CommonMember & CirclesPermissions) | null;
isFollowInProgress: boolean;
isMobileVersion: boolean;
}

const MENU_ITEM_TO_CHECK_FUNCTION_MAP: Record<
CommonFeedMenuItem,
(options: Options) => boolean
> = {
[CommonFeedMenuItem.Share]: ({ isMobileVersion }) => !isMobileVersion,
[CommonFeedMenuItem.Follow]: ({ commonMember, isFollowInProgress }) =>
!isFollowInProgress && Boolean(commonMember && !commonMember.isFollowing),
[CommonFeedMenuItem.Mute]: ({ commonMember, isFollowInProgress }) =>
!isFollowInProgress && Boolean(commonMember?.isFollowing),
};

export const getAllowedItems = (items: Item[], options: Options): Item[] =>
items.filter(({ id }) => MENU_ITEM_TO_CHECK_FUNCTION_MAP[id](options));
1 change: 1 addition & 0 deletions src/pages/commonFeed/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./generateSplitViewMaxSizeGetter";
export * from "./getLastMessage";
export * from "./getAllowedItems";
13 changes: 11 additions & 2 deletions src/services/Common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { commonMembersSubCollection } from "@/pages/OldCommon/store/api";
import { store } from "@/shared/appConfig";
import {
ApiEndpoint,
DocChange,
GovernanceActions,
ProposalsTypes,
} from "@/shared/constants";
Expand Down Expand Up @@ -337,8 +338,8 @@ class CommonService {

if (docChange) {
callback(docChange.doc.data(), {
isAdded: docChange.type === "added",
isRemoved: docChange.type === "removed",
isAdded: docChange.type === DocChange.Added,
isRemoved: docChange.type === DocChange.Removed,
});
}
});
Expand Down Expand Up @@ -381,6 +382,14 @@ class CommonService {
args: { circleId, commonId, userId },
});
};

public followCommon = async (commonId: string): Promise<void> => {
await Api.post(ApiEndpoint.FollowCommon, { commonId });
};

public muteCommon = async (commonId: string): Promise<void> => {
await Api.post(ApiEndpoint.MuteCommon, { commonId });
};
}

export default new CommonService();
32 changes: 32 additions & 0 deletions src/services/FeedItemFollows.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ApiEndpoint } from "@/shared/constants";
import { DocChange } from "@/shared/constants/docChange";
import { UnsubscribeFunction } from "@/shared/interfaces";
import { FollowFeedItemPayload } from "@/shared/interfaces/api";
import {
Expand Down Expand Up @@ -36,6 +37,37 @@ class FeedItemFollowsService {
return snapshot.docs[0]?.data() || null;
};

public subscribeToUserFeedItemFollowData = (
userId: string,
feedItemId: string,
callback: (
userFeedItemFollowData: FeedItemFollow | null,
statuses: {
isAdded: boolean;
isRemoved: boolean;
isModified: boolean;
},
) => void,
): UnsubscribeFunction => {
const query = this.getFeedItemFollowsSubCollection(userId).where(
"feedItemId",
"==",
feedItemId,
);

return query.onSnapshot((snapshot) => {
const docChange = snapshot.docChanges()[0];

if (docChange) {
callback(docChange.doc.data(), {
isAdded: docChange.type === DocChange.Added,
isRemoved: docChange.type === DocChange.Removed,
isModified: docChange.type === DocChange.Modified,
});
}
});
};

public getUserFeedItemFollowDataWithMetadata = async (
userId: string,
feedItemId: string,
Expand Down
5 changes: 5 additions & 0 deletions src/shared/constants/docChange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum DocChange {
Added = "added",
Removed = "removed",
Modified = "modified",
}
2 changes: 2 additions & 0 deletions src/shared/constants/endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export const ApiEndpoint = {
CreateReport: "/moderation/report",
HideContent: "/moderation/hide",
ShowContent: "/moderation/show",
FollowCommon: "/commons/follow",
MuteCommon: "/commons/mute",
LeaveCommon: "/commons/leave",
CreateSubscription: "/commons/immediate-contribution",
UpdateSubscription: "/subscriptions/update",
Expand Down
1 change: 1 addition & 0 deletions src/shared/constants/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ export * from "./viewportBreakpoint";
export * from "./currencyTypes";
export * from "./systemDiscussionMessage";
export * from "./theme";
export * from "./docChange";
1 change: 1 addition & 0 deletions src/shared/hooks/useCases/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ export { useDiscussionMessagesById } from "./useDiscussionMessagesById";
export { useUserPendingJoin } from "./useUserPendingJoin";
export { useCommonMemberWithUserInfo } from "./useCommonMemberWithUserInfo";
export { useEligibleVoters } from "./useEligibleVoters";
export * from "./useCommonFollow";
Loading

0 comments on commit 527b63e

Please sign in to comment.