From 4b407d393cb791564383ac2124bf5b9dece1b182 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 11:40:50 +0400 Subject: [PATCH 01/17] add logic to get and update user activity --- src/services/UserActivity.ts | 41 +++++++++++++++++++++++++++++++ src/services/index.ts | 1 + src/shared/models/UserActivity.ts | 3 +++ src/shared/models/index.tsx | 1 + src/shared/models/shared.tsx | 1 + 5 files changed, 47 insertions(+) create mode 100644 src/services/UserActivity.ts create mode 100644 src/shared/models/UserActivity.ts diff --git a/src/services/UserActivity.ts b/src/services/UserActivity.ts new file mode 100644 index 0000000000..9b21a9ce19 --- /dev/null +++ b/src/services/UserActivity.ts @@ -0,0 +1,41 @@ +import { Collection, UserActivity } from "@/shared/models"; +import { firestoreDataConverter } from "@/shared/utils"; +import firebase, { isFirestoreCacheError } from "@/shared/utils/firebase"; + +const userActivityConverter = firestoreDataConverter(); + +class UserActivityService { + private getUsersActivityCollection = () => + firebase + .firestore() + .collection(Collection.UsersActivity) + .withConverter(userActivityConverter); + + public getUserActivity = async ( + userId: string, + cached = false, + ): Promise => { + try { + const snapshot = await this.getUsersActivityCollection() + .doc(userId) + .get({ source: cached ? "cache" : "default" }); + + return snapshot?.data() || null; + } catch (error) { + if (cached && isFirestoreCacheError(error)) { + return this.getUserActivity(userId); + } else { + throw error; + } + } + }; + + public updateUserActivity = async ( + userId: string, + data: Partial, + ): Promise => { + await this.getUsersActivityCollection().doc(userId).update(data); + }; +} + +export default new UserActivityService(); diff --git a/src/services/index.ts b/src/services/index.ts index 4baa44fd2f..b5b8adc604 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -18,5 +18,6 @@ export { default as PayMeService } from "./PayMeService"; export { default as ProjectService } from "./Project"; export { default as ProposalService } from "./Proposal"; export { default as UserService } from "./User"; +export { default as UserActivityService } from "./UserActivity"; export { default as DiscussionMessageService } from "./DiscussionMessage"; export { default as NotionService } from "./Notion"; diff --git a/src/shared/models/UserActivity.ts b/src/shared/models/UserActivity.ts new file mode 100644 index 0000000000..3451afaa49 --- /dev/null +++ b/src/shared/models/UserActivity.ts @@ -0,0 +1,3 @@ +export interface UserActivity { + lastVisitedCommon?: string; +} diff --git a/src/shared/models/index.tsx b/src/shared/models/index.tsx index d1c61c51e4..fbb74b0468 100644 --- a/src/shared/models/index.tsx +++ b/src/shared/models/index.tsx @@ -24,4 +24,5 @@ export * from "./BankAccountDetails"; export * from "./Currency"; export * from "./SupportersData"; export * from "./Timestamp"; +export * from "./UserActivity"; export * from "./NotionIntegration"; diff --git a/src/shared/models/shared.tsx b/src/shared/models/shared.tsx index 8ff4b09431..60980a54d1 100644 --- a/src/shared/models/shared.tsx +++ b/src/shared/models/shared.tsx @@ -33,6 +33,7 @@ export enum Collection { Supporters = "supporters", Notifications = "notification", BankAccountDetails = "bankAccountDetails", + UsersActivity = "usersActivity", } export enum SubCollections { From 6ed61416242a05b87350d6c47cdd4e01cf86c41d Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 11:55:36 +0400 Subject: [PATCH 02/17] create use-case to update user activity --- src/shared/hooks/useCases/index.ts | 1 + .../hooks/useCases/useUserActivityUpdate.ts | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/shared/hooks/useCases/useUserActivityUpdate.ts diff --git a/src/shared/hooks/useCases/index.ts b/src/shared/hooks/useCases/index.ts index 51b09e439f..4694e458e0 100644 --- a/src/shared/hooks/useCases/index.ts +++ b/src/shared/hooks/useCases/index.ts @@ -23,6 +23,7 @@ export { useProposalById } from "./useProposalById"; export { useRootCommonMembershipIntro } from "./useRootCommonMembershipIntro"; export { useSubCommons } from "./useSubCommons"; export { useSupportersData } from "./useSupportersData"; +export { useUserActivityUpdate } from "./useUserActivityUpdate"; export { useUserById } from "./useUserById"; export { default as useUserCards } from "./useUserCards"; export { useUserCommonIds } from "./useUserCommonIds"; diff --git a/src/shared/hooks/useCases/useUserActivityUpdate.ts b/src/shared/hooks/useCases/useUserActivityUpdate.ts new file mode 100644 index 0000000000..b4a0064766 --- /dev/null +++ b/src/shared/hooks/useCases/useUserActivityUpdate.ts @@ -0,0 +1,22 @@ +import { useCallback } from "react"; +import { Logger, UserActivityService } from "@/services"; +import { UserActivity } from "@/shared/models"; + +interface Return { + updateUserActivity: (userId: string, data: Partial) => void; +} + +export const useUserActivityUpdate = (): Return => { + const updateUserActivity = useCallback( + async (userId: string, data: Partial) => { + try { + await UserActivityService.updateUserActivity(userId, data); + } catch (error) { + Logger.error(error); + } + }, + [], + ); + + return { updateUserActivity }; +}; From 28bf1842c54c3e39413e9a15714135eb07086574 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 14:01:56 +0400 Subject: [PATCH 03/17] add logic to store last visited common by user --- src/pages/commonFeed/CommonFeed.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/pages/commonFeed/CommonFeed.tsx b/src/pages/commonFeed/CommonFeed.tsx index cef65399b3..8b1ba8bc81 100644 --- a/src/pages/commonFeed/CommonFeed.tsx +++ b/src/pages/commonFeed/CommonFeed.tsx @@ -27,7 +27,11 @@ import { } from "@/shared/constants"; import { useRoutesContext } from "@/shared/contexts"; import { useAuthorizedModal, useQueryParams } from "@/shared/hooks"; -import { useCommonFeedItems, useUserCommonIds } from "@/shared/hooks/useCases"; +import { + useCommonFeedItems, + useUserActivityUpdate, + useUserCommonIds, +} from "@/shared/hooks/useCases"; import { useCommonPinnedFeedItems } from "@/shared/hooks/useCases/useCommonPinnedFeedItems"; import { SidebarIcon } from "@/shared/icons"; import { @@ -114,6 +118,7 @@ const CommonFeedComponent: FC = (props) => { fetched: isCommonDataFetched, fetchCommonData, } = useCommonData(userId); + const { updateUserActivity } = useUserActivityUpdate(); const parentCommonId = commonData?.common.directParent?.commonId; const anotherCommonId = userCommonIds[0] === commonId ? userCommonIds[1] : userCommonIds[0]; @@ -447,6 +452,16 @@ const CommonFeedComponent: FC = (props) => { }; }, [commonId]); + useEffect(() => { + if (!userId) { + return; + } + + updateUserActivity(userId, { + lastVisitedCommon: commonId, + }); + }, [userId, commonId]); + if (!isDataFetched) { const headerEl = renderLoadingHeader ? ( renderLoadingHeader() From 0317aff2cc028ad05e79933282dce29201d4135c Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 14:05:20 +0400 Subject: [PATCH 04/17] fix user activity update method --- src/services/UserActivity.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/services/UserActivity.ts b/src/services/UserActivity.ts index 9b21a9ce19..20733a2578 100644 --- a/src/services/UserActivity.ts +++ b/src/services/UserActivity.ts @@ -34,7 +34,9 @@ class UserActivityService { userId: string, data: Partial, ): Promise => { - await this.getUsersActivityCollection().doc(userId).update(data); + await this.getUsersActivityCollection() + .doc(userId) + .set(data, { merge: true }); }; } From de5557d8df6cc4f67d8ea28a86cd48b79234b12d Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 14:11:32 +0400 Subject: [PATCH 05/17] refactor user activity use-case to be more generic --- src/pages/commonFeed/CommonFeed.tsx | 12 ++++-------- src/shared/hooks/useCases/index.ts | 2 +- .../{useUserActivityUpdate.ts => useUserActivity.ts} | 12 ++++++++---- 3 files changed, 13 insertions(+), 13 deletions(-) rename src/shared/hooks/useCases/{useUserActivityUpdate.ts => useUserActivity.ts} (63%) diff --git a/src/pages/commonFeed/CommonFeed.tsx b/src/pages/commonFeed/CommonFeed.tsx index 8b1ba8bc81..07cee3e329 100644 --- a/src/pages/commonFeed/CommonFeed.tsx +++ b/src/pages/commonFeed/CommonFeed.tsx @@ -29,7 +29,7 @@ import { useRoutesContext } from "@/shared/contexts"; import { useAuthorizedModal, useQueryParams } from "@/shared/hooks"; import { useCommonFeedItems, - useUserActivityUpdate, + useUserActivity, useUserCommonIds, } from "@/shared/hooks/useCases"; import { useCommonPinnedFeedItems } from "@/shared/hooks/useCases/useCommonPinnedFeedItems"; @@ -118,7 +118,7 @@ const CommonFeedComponent: FC = (props) => { fetched: isCommonDataFetched, fetchCommonData, } = useCommonData(userId); - const { updateUserActivity } = useUserActivityUpdate(); + const { updateUserActivity } = useUserActivity(userId); const parentCommonId = commonData?.common.directParent?.commonId; const anotherCommonId = userCommonIds[0] === commonId ? userCommonIds[1] : userCommonIds[0]; @@ -453,14 +453,10 @@ const CommonFeedComponent: FC = (props) => { }, [commonId]); useEffect(() => { - if (!userId) { - return; - } - - updateUserActivity(userId, { + updateUserActivity({ lastVisitedCommon: commonId, }); - }, [userId, commonId]); + }, [updateUserActivity, commonId]); if (!isDataFetched) { const headerEl = renderLoadingHeader ? ( diff --git a/src/shared/hooks/useCases/index.ts b/src/shared/hooks/useCases/index.ts index 4694e458e0..72c3a2816f 100644 --- a/src/shared/hooks/useCases/index.ts +++ b/src/shared/hooks/useCases/index.ts @@ -23,7 +23,7 @@ export { useProposalById } from "./useProposalById"; export { useRootCommonMembershipIntro } from "./useRootCommonMembershipIntro"; export { useSubCommons } from "./useSubCommons"; export { useSupportersData } from "./useSupportersData"; -export { useUserActivityUpdate } from "./useUserActivityUpdate"; +export { useUserActivity } from "./useUserActivity"; export { useUserById } from "./useUserById"; export { default as useUserCards } from "./useUserCards"; export { useUserCommonIds } from "./useUserCommonIds"; diff --git a/src/shared/hooks/useCases/useUserActivityUpdate.ts b/src/shared/hooks/useCases/useUserActivity.ts similarity index 63% rename from src/shared/hooks/useCases/useUserActivityUpdate.ts rename to src/shared/hooks/useCases/useUserActivity.ts index b4a0064766..9dddef80ba 100644 --- a/src/shared/hooks/useCases/useUserActivityUpdate.ts +++ b/src/shared/hooks/useCases/useUserActivity.ts @@ -3,19 +3,23 @@ import { Logger, UserActivityService } from "@/services"; import { UserActivity } from "@/shared/models"; interface Return { - updateUserActivity: (userId: string, data: Partial) => void; + updateUserActivity: (data: Partial) => void; } -export const useUserActivityUpdate = (): Return => { +export const useUserActivity = (userId?: string): Return => { const updateUserActivity = useCallback( - async (userId: string, data: Partial) => { + async (data: Partial) => { + if (!userId) { + return; + } + try { await UserActivityService.updateUserActivity(userId, data); } catch (error) { Logger.error(error); } }, - [], + [userId], ); return { updateUserActivity }; From 95fce21e828c479530ca55cd27bd38248690716c Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 14:22:28 +0400 Subject: [PATCH 06/17] add subscription to user activity use-case --- src/services/UserActivity.ts | 37 +++++++++----------- src/shared/hooks/useCases/useUserActivity.ts | 33 +++++++++++++++-- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/src/services/UserActivity.ts b/src/services/UserActivity.ts index 20733a2578..12ef932d2e 100644 --- a/src/services/UserActivity.ts +++ b/src/services/UserActivity.ts @@ -1,6 +1,7 @@ +import { UnsubscribeFunction } from "@/shared/interfaces"; import { Collection, UserActivity } from "@/shared/models"; import { firestoreDataConverter } from "@/shared/utils"; -import firebase, { isFirestoreCacheError } from "@/shared/utils/firebase"; +import firebase from "@/shared/utils/firebase"; const userActivityConverter = firestoreDataConverter(); @@ -11,25 +12,6 @@ class UserActivityService { .collection(Collection.UsersActivity) .withConverter(userActivityConverter); - public getUserActivity = async ( - userId: string, - cached = false, - ): Promise => { - try { - const snapshot = await this.getUsersActivityCollection() - .doc(userId) - .get({ source: cached ? "cache" : "default" }); - - return snapshot?.data() || null; - } catch (error) { - if (cached && isFirestoreCacheError(error)) { - return this.getUserActivity(userId); - } else { - throw error; - } - } - }; - public updateUserActivity = async ( userId: string, data: Partial, @@ -38,6 +20,21 @@ class UserActivityService { .doc(userId) .set(data, { merge: true }); }; + + public subscribeToUserActivity = ( + userId: string, + callback: (userActivity: UserActivity) => void, + ): UnsubscribeFunction => { + const query = this.getUsersActivityCollection().doc(userId); + + return query.onSnapshot((snapshot) => { + const userActivity = snapshot.data(); + + if (userActivity) { + callback(userActivity); + } + }); + }; } export default new UserActivityService(); diff --git a/src/shared/hooks/useCases/useUserActivity.ts b/src/shared/hooks/useCases/useUserActivity.ts index 9dddef80ba..46fd284b7e 100644 --- a/src/shared/hooks/useCases/useUserActivity.ts +++ b/src/shared/hooks/useCases/useUserActivity.ts @@ -1,12 +1,17 @@ -import { useCallback } from "react"; +import { useCallback, useEffect } from "react"; import { Logger, UserActivityService } from "@/services"; +import { useLoadingState } from "@/shared/hooks"; +import { LoadingState } from "@/shared/interfaces"; import { UserActivity } from "@/shared/models"; -interface Return { +interface Return extends LoadingState { updateUserActivity: (data: Partial) => void; } export const useUserActivity = (userId?: string): Return => { + const [userActivityState, setUserActivityState] = + useLoadingState(null, { loading: true }); + const updateUserActivity = useCallback( async (data: Partial) => { if (!userId) { @@ -22,5 +27,27 @@ export const useUserActivity = (userId?: string): Return => { [userId], ); - return { updateUserActivity }; + useEffect(() => { + if (!userId) { + return; + } + + const unsubscribe = UserActivityService.subscribeToUserActivity( + userId, + (updatedUserActivity) => { + setUserActivityState({ + loading: false, + fetched: true, + data: updatedUserActivity, + }); + }, + ); + + return unsubscribe; + }, [userId]); + + return { + ...userActivityState, + updateUserActivity, + }; }; From fc55fca0686c88a036bf003841912f5e996400d7 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 14:35:30 +0400 Subject: [PATCH 07/17] remove breadcrumbs data from cache --- src/store/store.tsx | 8 +++++++- src/store/transforms.ts | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/store/store.tsx b/src/store/store.tsx index f62f433117..232a0bc8e5 100644 --- a/src/store/store.tsx +++ b/src/store/store.tsx @@ -22,6 +22,7 @@ import { inboxTransform, lastCommonFromFeedTransform, cacheTransform, + multipleSpacesLayoutTransform, } from "./transforms"; const persistConfig: PersistConfig = { @@ -37,7 +38,12 @@ const persistConfig: PersistConfig = { "multipleSpacesLayout", ], stateReconciler: autoMergeLevel2, - transforms: [inboxTransform, lastCommonFromFeedTransform, cacheTransform], + transforms: [ + inboxTransform, + lastCommonFromFeedTransform, + cacheTransform, + multipleSpacesLayoutTransform, + ], }; const sagaMiddleware = createSagaMiddleware(); diff --git a/src/store/transforms.ts b/src/store/transforms.ts index 625133dfc4..86030684a0 100644 --- a/src/store/transforms.ts +++ b/src/store/transforms.ts @@ -1,9 +1,10 @@ import { createTransform } from "redux-persist"; import { deserializeFeedLayoutItemWithFollowData } from "@/shared/interfaces"; import { convertObjectDatesToFirestoreTimestamps } from "@/shared/utils"; +import { MultipleSpacesLayoutState } from "@/store/states"; import { getFeedLayoutItemDateForSorting } from "@/store/states/inbox/utils"; -import { CommonLayoutState } from "./states/commonLayout"; import { CacheState } from "./states/cache"; +import { CommonLayoutState } from "./states/commonLayout"; import { InboxItems, InboxState, @@ -89,7 +90,18 @@ export const cacheTransform = createTransform( (inboundState: CacheState) => inboundState, (outboundState: CacheState) => ({ ...outboundState, - discussionMessagesStates: {} + discussionMessagesStates: {}, }), { whitelist: ["cache"] }, ); + +export const multipleSpacesLayoutTransform = createTransform( + (inboundState: MultipleSpacesLayoutState) => ({ + ...inboundState, + breadcrumbs: null, + previousBreadcrumbs: null, + backUrl: null, + }), + (outboundState: MultipleSpacesLayoutState) => outboundState, + { whitelist: ["multipleSpacesLayout"] }, +); From cee21a7f2ce3b8e08918e2c7ae008932dd583967 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 14:36:27 +0400 Subject: [PATCH 08/17] use last visited by user common id in "My Spaces" --- .../Header/components/Navigation/Navigation.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx b/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx index b5a2baa7a0..c61c9e1224 100644 --- a/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx +++ b/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx @@ -4,12 +4,13 @@ import { useLocation } from "react-router"; import classNames from "classnames"; import { authentificated, + selectUser, selectUserStreamsWithNotificationsAmount, } from "@/pages/Auth/store/selectors"; import { InboxItemType, ROUTE_PATHS } from "@/shared/constants"; import { useRoutesContext } from "@/shared/contexts"; import { useModal } from "@/shared/hooks"; -import { useUserCommonIds } from "@/shared/hooks/useCases"; +import { useUserActivity, useUserCommonIds } from "@/shared/hooks/useCases"; import { BlocksIcon, InboxIcon } from "@/shared/icons"; import { CommonSidenavLayoutTab, @@ -44,13 +45,20 @@ const Navigation: FC = (props) => { const previousBreadcrumbs = useSelector( selectMultipleSpacesLayoutPreviousBreadcrumbs, ); + const user = useSelector(selectUser()); + const userId = user?.uid; const { data: userCommonIds } = useUserCommonIds(); + const { data: userActivity } = useUserActivity(userId); const breadcrumbs = previousBreadcrumbs || currentBreadcrumbs; const breadcrumbsCommonId = breadcrumbs?.type === InboxItemType.FeedItemFollow ? breadcrumbs.activeCommonId : ""; - const mySpacesCommonId = breadcrumbsCommonId || userCommonIds[0] || ""; + const mySpacesCommonId = + breadcrumbsCommonId || + userActivity?.lastVisitedCommon || + userCommonIds[0] || + ""; const mySpacesPagePath = ( mySpacesCommonId ? getCommonPagePath(mySpacesCommonId) : "" ) as ROUTE_PATHS; From 17a2840e2bcb5069f6077a2cd1cdfba09e9e31bb Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 14:49:22 +0400 Subject: [PATCH 09/17] use last visited by user common id to Spaces tab click handler --- .../components/LayoutTabs/LayoutTabs.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx b/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx index d698b0fb55..1931bd7a57 100644 --- a/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx +++ b/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx @@ -4,12 +4,13 @@ import { useHistory } from "react-router-dom"; import classNames from "classnames"; import { authentificated, + selectUser, selectUserStreamsWithNotificationsAmount, } from "@/pages/Auth/store/selectors"; import { Tab, Tabs } from "@/shared/components"; import { useRoutesContext } from "@/shared/contexts"; import { useModal } from "@/shared/hooks"; -import { useUserCommonIds } from "@/shared/hooks/useCases"; +import { useUserActivity, useUserCommonIds } from "@/shared/hooks/useCases"; import { Avatar2Icon, Blocks2Icon, InboxIcon } from "@/shared/icons"; import { CreateCommonPrompt } from "@/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/components"; import { selectCommonLayoutLastCommonFromFeed } from "@/store/states"; @@ -41,7 +42,10 @@ const LayoutTabs: FC = (props) => { const userStreamsWithNotificationsAmount = useSelector( selectUserStreamsWithNotificationsAmount(), ); + const user = useSelector(selectUser()); + const userId = user?.uid; const { data: userCommonIds } = useUserCommonIds(); + const { data: userActivity } = useUserActivity(userId); const { isShowing: isCreateCommonPromptOpen, onOpen: onCreateCommonPromptOpen, @@ -81,7 +85,10 @@ const LayoutTabs: FC = (props) => { } as CSSProperties; const handleSpacesClick = () => { - const commonForRedirectId = lastCommonIdFromFeed?.id || userCommonIds[0]; + const commonForRedirectId = + lastCommonIdFromFeed?.id || + userActivity?.lastVisitedCommon || + userCommonIds[0]; if (commonForRedirectId) { history.push(getCommonPagePath(commonForRedirectId)); From f54671f22558d6df03f260ade89f6bbe319828f0 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 15:11:20 +0400 Subject: [PATCH 10/17] remove previous breadcrumbs related logic --- src/pages/commonFeed/CommonFeedPage.tsx | 2 +- .../components/Navigation/Navigation.tsx | 18 +----------------- .../states/multipleSpacesLayout/actions.ts | 4 ++-- .../states/multipleSpacesLayout/constants.ts | 2 +- .../states/multipleSpacesLayout/reducer.ts | 6 +----- .../states/multipleSpacesLayout/selectors.ts | 4 ---- src/store/states/multipleSpacesLayout/types.ts | 1 - src/store/transforms.ts | 1 - 8 files changed, 6 insertions(+), 32 deletions(-) diff --git a/src/pages/commonFeed/CommonFeedPage.tsx b/src/pages/commonFeed/CommonFeedPage.tsx index e5feeb8e05..233a90a473 100644 --- a/src/pages/commonFeed/CommonFeedPage.tsx +++ b/src/pages/commonFeed/CommonFeedPage.tsx @@ -95,7 +95,7 @@ const CommonFeedPage: FC = () => { useEffect(() => { return () => { - dispatch(multipleSpacesLayoutActions.moveBreadcrumbsToPrevious()); + dispatch(multipleSpacesLayoutActions.clearBreadcrumbs()); }; }, []); diff --git a/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx b/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx index c61c9e1224..0133191d91 100644 --- a/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx +++ b/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx @@ -16,10 +16,6 @@ import { CommonSidenavLayoutTab, getActiveLayoutTab, } from "@/shared/layouts/CommonSidenavLayout"; -import { - selectMultipleSpacesLayoutBreadcrumbs, - selectMultipleSpacesLayoutPreviousBreadcrumbs, -} from "@/store/states"; import { CreateCommonPrompt, NavigationItem } from "./components"; import { NavigationItemOptions } from "./types"; import styles from "./Navigation.module.scss"; @@ -41,24 +37,12 @@ const Navigation: FC = (props) => { const userStreamsWithNotificationsAmount = useSelector( selectUserStreamsWithNotificationsAmount(), ); - const currentBreadcrumbs = useSelector(selectMultipleSpacesLayoutBreadcrumbs); - const previousBreadcrumbs = useSelector( - selectMultipleSpacesLayoutPreviousBreadcrumbs, - ); const user = useSelector(selectUser()); const userId = user?.uid; const { data: userCommonIds } = useUserCommonIds(); const { data: userActivity } = useUserActivity(userId); - const breadcrumbs = previousBreadcrumbs || currentBreadcrumbs; - const breadcrumbsCommonId = - breadcrumbs?.type === InboxItemType.FeedItemFollow - ? breadcrumbs.activeCommonId - : ""; const mySpacesCommonId = - breadcrumbsCommonId || - userActivity?.lastVisitedCommon || - userCommonIds[0] || - ""; + userActivity?.lastVisitedCommon || userCommonIds[0] || ""; const mySpacesPagePath = ( mySpacesCommonId ? getCommonPagePath(mySpacesCommonId) : "" ) as ROUTE_PATHS; diff --git a/src/store/states/multipleSpacesLayout/actions.ts b/src/store/states/multipleSpacesLayout/actions.ts index cb8210e550..251514f6d0 100644 --- a/src/store/states/multipleSpacesLayout/actions.ts +++ b/src/store/states/multipleSpacesLayout/actions.ts @@ -36,8 +36,8 @@ export const setBreadcrumbsData = createStandardAction( MultipleSpacesLayoutActionType.SET_BREADCRUMBS_DATA, )(); -export const moveBreadcrumbsToPrevious = createStandardAction( - MultipleSpacesLayoutActionType.MOVE_BREADCRUMBS_TO_PREVIOUS, +export const clearBreadcrumbs = createStandardAction( + MultipleSpacesLayoutActionType.CLEAR_BREADCRUMBS, )(); export const addOrUpdateProjectInBreadcrumbs = createStandardAction( diff --git a/src/store/states/multipleSpacesLayout/constants.ts b/src/store/states/multipleSpacesLayout/constants.ts index 7c5574dedb..6811fa17ad 100644 --- a/src/store/states/multipleSpacesLayout/constants.ts +++ b/src/store/states/multipleSpacesLayout/constants.ts @@ -10,7 +10,7 @@ export enum MultipleSpacesLayoutActionType { SET_BREADCRUMBS_DATA = "@MULTIPLE_SPACES_LAYOUT/SET_BREADCRUMBS_DATA", - MOVE_BREADCRUMBS_TO_PREVIOUS = "@MULTIPLE_SPACES_LAYOUT/MOVE_BREADCRUMBS_TO_PREVIOUS", + CLEAR_BREADCRUMBS = "@MULTIPLE_SPACES_LAYOUT/CLEAR_BREADCRUMBS", ADD_OR_UPDATE_PROJECT_IN_BREADCRUMBS = "@MULTIPLE_SPACES_LAYOUT/ADD_OR_UPDATE_PROJECT_IN_BREADCRUMBS", diff --git a/src/store/states/multipleSpacesLayout/reducer.ts b/src/store/states/multipleSpacesLayout/reducer.ts index 25fd6537ec..a05f3f182e 100644 --- a/src/store/states/multipleSpacesLayout/reducer.ts +++ b/src/store/states/multipleSpacesLayout/reducer.ts @@ -10,7 +10,6 @@ type Action = ActionType; const initialState: MultipleSpacesLayoutState = { breadcrumbs: null, - previousBreadcrumbs: null, backUrl: null, mainWidth: window.innerWidth, }; @@ -49,11 +48,8 @@ export const reducer = createReducer( nextState.breadcrumbs = payload && { ...payload }; }), ) - .handleAction(actions.moveBreadcrumbsToPrevious, (state) => + .handleAction(actions.clearBreadcrumbs, (state) => produce(state, (nextState) => { - nextState.previousBreadcrumbs = nextState.breadcrumbs && { - ...nextState.breadcrumbs, - }; nextState.breadcrumbs = null; }), ) diff --git a/src/store/states/multipleSpacesLayout/selectors.ts b/src/store/states/multipleSpacesLayout/selectors.ts index fff25a04d6..6c5600bd0a 100644 --- a/src/store/states/multipleSpacesLayout/selectors.ts +++ b/src/store/states/multipleSpacesLayout/selectors.ts @@ -3,10 +3,6 @@ import { AppState } from "@/shared/interfaces"; export const selectMultipleSpacesLayoutBreadcrumbs = (state: AppState) => state.multipleSpacesLayout.breadcrumbs; -export const selectMultipleSpacesLayoutPreviousBreadcrumbs = ( - state: AppState, -) => state.multipleSpacesLayout.previousBreadcrumbs; - export const selectMultipleSpacesLayoutBackUrl = (state: AppState) => state.multipleSpacesLayout.backUrl; diff --git a/src/store/states/multipleSpacesLayout/types.ts b/src/store/states/multipleSpacesLayout/types.ts index 3e2976f09f..8ba7a3534d 100644 --- a/src/store/states/multipleSpacesLayout/types.ts +++ b/src/store/states/multipleSpacesLayout/types.ts @@ -27,7 +27,6 @@ export type MultipleSpacesLayoutBreadcrumbs = export interface MultipleSpacesLayoutState { breadcrumbs: MultipleSpacesLayoutBreadcrumbs | null; - previousBreadcrumbs: MultipleSpacesLayoutBreadcrumbs | null; backUrl: string | null; mainWidth: number; } diff --git a/src/store/transforms.ts b/src/store/transforms.ts index 86030684a0..f407415742 100644 --- a/src/store/transforms.ts +++ b/src/store/transforms.ts @@ -99,7 +99,6 @@ export const multipleSpacesLayoutTransform = createTransform( (inboundState: MultipleSpacesLayoutState) => ({ ...inboundState, breadcrumbs: null, - previousBreadcrumbs: null, backUrl: null, }), (outboundState: MultipleSpacesLayoutState) => outboundState, From d68f5a9f26fe375ca7ff0578e10202d84af97408 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 15:21:41 +0400 Subject: [PATCH 11/17] remove root common from last common from feed --- src/pages/commonFeed/CommonFeed.tsx | 14 -------------- src/store/states/commonLayout/types.ts | 21 ++++++--------------- src/store/store.tsx | 8 +------- src/store/transforms.ts | 22 ---------------------- 4 files changed, 7 insertions(+), 58 deletions(-) diff --git a/src/pages/commonFeed/CommonFeed.tsx b/src/pages/commonFeed/CommonFeed.tsx index 07cee3e329..919a4b9030 100644 --- a/src/pages/commonFeed/CommonFeed.tsx +++ b/src/pages/commonFeed/CommonFeed.tsx @@ -421,7 +421,6 @@ const CommonFeedComponent: FC = (props) => { useEffect(() => { return () => { const common = stateRef.current?.data?.common; - const rootCommon = stateRef.current?.data?.rootCommon; dispatch( commonLayoutActions.setLastCommonFromFeed({ @@ -432,19 +431,6 @@ const CommonFeedComponent: FC = (props) => { image: common.image, isProject: checkIsProject(common), memberCount: common.memberCount, - rootCommon: common.rootCommonId - ? { - id: common.rootCommonId, - data: rootCommon - ? { - name: rootCommon.name, - image: rootCommon.image, - isProject: false, - memberCount: rootCommon.memberCount, - } - : null, - } - : null, } : null, }), diff --git a/src/store/states/commonLayout/types.ts b/src/store/states/commonLayout/types.ts index fbe4fc9664..7e16b8515a 100644 --- a/src/store/states/commonLayout/types.ts +++ b/src/store/states/commonLayout/types.ts @@ -1,22 +1,13 @@ import { ProjectsStateItem } from "../projects"; -interface LastCommonFromFeedData { - name: string; - image: string; - isProject: boolean; - memberCount: number; -} - interface LastCommonFromFeed { id: string; - data: - | (LastCommonFromFeedData & { - rootCommon: { - id: string; - data: LastCommonFromFeedData | null; - } | null; - }) - | null; + data: { + name: string; + image: string; + isProject: boolean; + memberCount: number; + } | null; } export interface CommonLayoutState { diff --git a/src/store/store.tsx b/src/store/store.tsx index 232a0bc8e5..e82f8979ad 100644 --- a/src/store/store.tsx +++ b/src/store/store.tsx @@ -20,7 +20,6 @@ import rootReducer from "./reducer"; import appSagas from "./saga"; import { inboxTransform, - lastCommonFromFeedTransform, cacheTransform, multipleSpacesLayoutTransform, } from "./transforms"; @@ -38,12 +37,7 @@ const persistConfig: PersistConfig = { "multipleSpacesLayout", ], stateReconciler: autoMergeLevel2, - transforms: [ - inboxTransform, - lastCommonFromFeedTransform, - cacheTransform, - multipleSpacesLayoutTransform, - ], + transforms: [inboxTransform, cacheTransform, multipleSpacesLayoutTransform], }; const sagaMiddleware = createSagaMiddleware(); diff --git a/src/store/transforms.ts b/src/store/transforms.ts index f407415742..0bde9e2597 100644 --- a/src/store/transforms.ts +++ b/src/store/transforms.ts @@ -4,7 +4,6 @@ import { convertObjectDatesToFirestoreTimestamps } from "@/shared/utils"; import { MultipleSpacesLayoutState } from "@/store/states"; import { getFeedLayoutItemDateForSorting } from "@/store/states/inbox/utils"; import { CacheState } from "./states/cache"; -import { CommonLayoutState } from "./states/commonLayout"; import { InboxItems, InboxState, @@ -65,27 +64,6 @@ export const inboxTransform = createTransform( { whitelist: ["inbox"] }, ); -export const lastCommonFromFeedTransform = createTransform( - (inboundState: CommonLayoutState) => { - const rootCommon = inboundState.lastCommonFromFeed?.data?.rootCommon; - - return { - ...inboundState, - lastCommonFromFeed: rootCommon - ? { - id: rootCommon.id, - data: rootCommon.data && { - ...rootCommon.data, - rootCommon: null, - }, - } - : inboundState.lastCommonFromFeed, - }; - }, - (outboundState: CommonLayoutState) => outboundState, - { whitelist: ["commonLayout"] }, -); - export const cacheTransform = createTransform( (inboundState: CacheState) => inboundState, (outboundState: CacheState) => ({ From af62d59cc4e47df2a86ebea55cdabbef6fd542ae Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 15:24:14 +0400 Subject: [PATCH 12/17] update last common from feed usage in layout tabs --- .../components/LayoutTabs/LayoutTabs.tsx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx b/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx index 1931bd7a57..dec0d59f1a 100644 --- a/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx +++ b/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx @@ -1,5 +1,5 @@ import React, { CSSProperties, FC, ReactNode } from "react"; -import { useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { useHistory } from "react-router-dom"; import classNames from "classnames"; import { @@ -13,7 +13,10 @@ import { useModal } from "@/shared/hooks"; import { useUserActivity, useUserCommonIds } from "@/shared/hooks/useCases"; import { Avatar2Icon, Blocks2Icon, InboxIcon } from "@/shared/icons"; import { CreateCommonPrompt } from "@/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/components"; -import { selectCommonLayoutLastCommonFromFeed } from "@/store/states"; +import { + commonLayoutActions, + selectCommonLayoutLastCommonFromFeed, +} from "@/store/states"; import { LayoutTab } from "../../constants"; import { getActiveLayoutTab, getLayoutTabName } from "./utils"; import styles from "./LayoutTabs.module.scss"; @@ -32,6 +35,7 @@ interface TabConfiguration { const LayoutTabs: FC = (props) => { const { className } = props; + const dispatch = useDispatch(); const history = useHistory(); const { getCommonPagePath, getInboxPagePath, getProfilePagePath } = useRoutesContext(); @@ -85,10 +89,15 @@ const LayoutTabs: FC = (props) => { } as CSSProperties; const handleSpacesClick = () => { + if ( + lastCommonIdFromFeed && + lastCommonIdFromFeed.id !== userActivity?.lastVisitedCommon + ) { + dispatch(commonLayoutActions.setLastCommonFromFeed(null)); + } + const commonForRedirectId = - lastCommonIdFromFeed?.id || - userActivity?.lastVisitedCommon || - userCommonIds[0]; + userActivity?.lastVisitedCommon || userCommonIds[0]; if (commonForRedirectId) { history.push(getCommonPagePath(commonForRedirectId)); From f7df2144df32fcfa2d292eb56c2700a533702e36 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 15:41:38 +0400 Subject: [PATCH 13/17] add method to get user activity --- src/services/UserActivity.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/services/UserActivity.ts b/src/services/UserActivity.ts index 12ef932d2e..4de4e458be 100644 --- a/src/services/UserActivity.ts +++ b/src/services/UserActivity.ts @@ -1,7 +1,7 @@ import { UnsubscribeFunction } from "@/shared/interfaces"; import { Collection, UserActivity } from "@/shared/models"; import { firestoreDataConverter } from "@/shared/utils"; -import firebase from "@/shared/utils/firebase"; +import firebase, { isFirestoreCacheError } from "@/shared/utils/firebase"; const userActivityConverter = firestoreDataConverter(); @@ -12,6 +12,25 @@ class UserActivityService { .collection(Collection.UsersActivity) .withConverter(userActivityConverter); + public getUserActivity = async ( + userId: string, + cached = false, + ): Promise => { + try { + const snapshot = await this.getUsersActivityCollection() + .doc(userId) + .get({ source: cached ? "cache" : "default" }); + + return snapshot?.data() || null; + } catch (error) { + if (cached && isFirestoreCacheError(error)) { + return this.getUserActivity(userId); + } else { + throw error; + } + } + }; + public updateUserActivity = async ( userId: string, data: Partial, From 5227d92d7e8e6d3a914a4c3f8e4d70880fbb27ce Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 15:46:38 +0400 Subject: [PATCH 14/17] add last visited common in sidenav data fetch --- .../states/commonLayout/saga/getCommons.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/store/states/commonLayout/saga/getCommons.ts b/src/store/states/commonLayout/saga/getCommons.ts index 72ed1e171b..78b2956aac 100644 --- a/src/store/states/commonLayout/saga/getCommons.ts +++ b/src/store/states/commonLayout/saga/getCommons.ts @@ -1,6 +1,11 @@ import { call, put, select } from "redux-saga/effects"; import { selectUser } from "@/pages/Auth/store/selectors"; -import { CommonService, GovernanceService, ProjectService } from "@/services"; +import { + CommonService, + GovernanceService, + ProjectService, + UserActivityService, +} from "@/services"; import { Awaited } from "@/shared/interfaces"; import { User } from "@/shared/models"; import { compareCommonsByLastActivity, isError } from "@/shared/utils"; @@ -70,11 +75,20 @@ const getProjectsInfo = async ( export function* getCommons( action: ReturnType, ) { - const { payload: commonId = "" } = action; + let { payload: commonId = "" } = action; try { const user = (yield select(selectUser())) as User | null; const userId = user?.uid; + + if (!commonId && userId) { + const userActivity = (yield call( + UserActivityService.getUserActivity, + userId, + )) as Awaited>; + commonId = userActivity?.lastVisitedCommon || ""; + } + const { data, currentCommonId } = (yield call( getProjectsInfo, commonId, From ccd140ad7b8068463516b6305020bbf1fd711937 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 16:53:49 +0400 Subject: [PATCH 15/17] update user activity use-case to use last common from feed --- src/shared/hooks/useCases/useUserActivity.ts | 37 +++++++++++++------ .../components/LayoutTabs/LayoutTabs.tsx | 22 ++--------- .../components/Navigation/Navigation.tsx | 5 +-- 3 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/shared/hooks/useCases/useUserActivity.ts b/src/shared/hooks/useCases/useUserActivity.ts index 46fd284b7e..1379a0f51d 100644 --- a/src/shared/hooks/useCases/useUserActivity.ts +++ b/src/shared/hooks/useCases/useUserActivity.ts @@ -1,19 +1,31 @@ import { useCallback, useEffect } from "react"; +import { useDispatch, useSelector } from "react-redux"; import { Logger, UserActivityService } from "@/services"; -import { useLoadingState } from "@/shared/hooks"; -import { LoadingState } from "@/shared/interfaces"; import { UserActivity } from "@/shared/models"; +import { + commonLayoutActions, + selectCommonLayoutLastCommonFromFeed, +} from "@/store/states"; -interface Return extends LoadingState { +interface Return { + lastVisitedCommon?: string; updateUserActivity: (data: Partial) => void; } export const useUserActivity = (userId?: string): Return => { - const [userActivityState, setUserActivityState] = - useLoadingState(null, { loading: true }); + const dispatch = useDispatch(); + const lastCommonFromFeed = useSelector(selectCommonLayoutLastCommonFromFeed); const updateUserActivity = useCallback( async (data: Partial) => { + if (data.lastVisitedCommon) { + dispatch( + commonLayoutActions.setLastCommonFromFeed({ + id: data.lastVisitedCommon, + data: null, + }), + ); + } if (!userId) { return; } @@ -35,11 +47,14 @@ export const useUserActivity = (userId?: string): Return => { const unsubscribe = UserActivityService.subscribeToUserActivity( userId, (updatedUserActivity) => { - setUserActivityState({ - loading: false, - fetched: true, - data: updatedUserActivity, - }); + if (updatedUserActivity.lastVisitedCommon) { + dispatch( + commonLayoutActions.setLastCommonFromFeed({ + id: updatedUserActivity.lastVisitedCommon, + data: null, + }), + ); + } }, ); @@ -47,7 +62,7 @@ export const useUserActivity = (userId?: string): Return => { }, [userId]); return { - ...userActivityState, + lastVisitedCommon: lastCommonFromFeed?.id, updateUserActivity, }; }; diff --git a/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx b/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx index dec0d59f1a..40d759d824 100644 --- a/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx +++ b/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx @@ -1,5 +1,5 @@ import React, { CSSProperties, FC, ReactNode } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useSelector } from "react-redux"; import { useHistory } from "react-router-dom"; import classNames from "classnames"; import { @@ -13,10 +13,6 @@ import { useModal } from "@/shared/hooks"; import { useUserActivity, useUserCommonIds } from "@/shared/hooks/useCases"; import { Avatar2Icon, Blocks2Icon, InboxIcon } from "@/shared/icons"; import { CreateCommonPrompt } from "@/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/components"; -import { - commonLayoutActions, - selectCommonLayoutLastCommonFromFeed, -} from "@/store/states"; import { LayoutTab } from "../../constants"; import { getActiveLayoutTab, getLayoutTabName } from "./utils"; import styles from "./LayoutTabs.module.scss"; @@ -35,13 +31,9 @@ interface TabConfiguration { const LayoutTabs: FC = (props) => { const { className } = props; - const dispatch = useDispatch(); const history = useHistory(); const { getCommonPagePath, getInboxPagePath, getProfilePagePath } = useRoutesContext(); - const lastCommonIdFromFeed = useSelector( - selectCommonLayoutLastCommonFromFeed, - ); const isAuthenticated = useSelector(authentificated()); const userStreamsWithNotificationsAmount = useSelector( selectUserStreamsWithNotificationsAmount(), @@ -49,7 +41,7 @@ const LayoutTabs: FC = (props) => { const user = useSelector(selectUser()); const userId = user?.uid; const { data: userCommonIds } = useUserCommonIds(); - const { data: userActivity } = useUserActivity(userId); + const { lastVisitedCommon } = useUserActivity(userId); const { isShowing: isCreateCommonPromptOpen, onOpen: onCreateCommonPromptOpen, @@ -89,15 +81,7 @@ const LayoutTabs: FC = (props) => { } as CSSProperties; const handleSpacesClick = () => { - if ( - lastCommonIdFromFeed && - lastCommonIdFromFeed.id !== userActivity?.lastVisitedCommon - ) { - dispatch(commonLayoutActions.setLastCommonFromFeed(null)); - } - - const commonForRedirectId = - userActivity?.lastVisitedCommon || userCommonIds[0]; + const commonForRedirectId = lastVisitedCommon || userCommonIds[0]; if (commonForRedirectId) { history.push(getCommonPagePath(commonForRedirectId)); diff --git a/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx b/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx index 0133191d91..962edabb97 100644 --- a/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx +++ b/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx @@ -40,9 +40,8 @@ const Navigation: FC = (props) => { const user = useSelector(selectUser()); const userId = user?.uid; const { data: userCommonIds } = useUserCommonIds(); - const { data: userActivity } = useUserActivity(userId); - const mySpacesCommonId = - userActivity?.lastVisitedCommon || userCommonIds[0] || ""; + const { lastVisitedCommon } = useUserActivity(userId); + const mySpacesCommonId = lastVisitedCommon || userCommonIds[0] || ""; const mySpacesPagePath = ( mySpacesCommonId ? getCommonPagePath(mySpacesCommonId) : "" ) as ROUTE_PATHS; From e5d45150e7e4dcb49fca2e02b2dd968246f05d75 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 16:58:05 +0400 Subject: [PATCH 16/17] change useUserActivity to useLastVisitedCommon --- src/pages/commonFeed/CommonFeed.tsx | 42 +++++++++---------- src/pages/commonFeed/CommonFeedPage.tsx | 11 +++-- src/shared/hooks/useCases/index.ts | 2 +- ...serActivity.ts => useLastVisitedCommon.ts} | 38 ++++++++--------- .../components/LayoutTabs/LayoutTabs.tsx | 9 ++-- .../components/Navigation/Navigation.tsx | 11 +++-- 6 files changed, 60 insertions(+), 53 deletions(-) rename src/shared/hooks/useCases/{useUserActivity.ts => useLastVisitedCommon.ts} (56%) diff --git a/src/pages/commonFeed/CommonFeed.tsx b/src/pages/commonFeed/CommonFeed.tsx index 919a4b9030..97bd7b46fa 100644 --- a/src/pages/commonFeed/CommonFeed.tsx +++ b/src/pages/commonFeed/CommonFeed.tsx @@ -29,7 +29,7 @@ import { useRoutesContext } from "@/shared/contexts"; import { useAuthorizedModal, useQueryParams } from "@/shared/hooks"; import { useCommonFeedItems, - useUserActivity, + useLastVisitedCommon, useUserCommonIds, } from "@/shared/hooks/useCases"; import { useCommonPinnedFeedItems } from "@/shared/hooks/useCases/useCommonPinnedFeedItems"; @@ -118,7 +118,7 @@ const CommonFeedComponent: FC = (props) => { fetched: isCommonDataFetched, fetchCommonData, } = useCommonData(userId); - const { updateUserActivity } = useUserActivity(userId); + const { updateLastVisitedCommon } = useLastVisitedCommon(userId); const parentCommonId = commonData?.common.directParent?.commonId; const anotherCommonId = userCommonIds[0] === commonId ? userCommonIds[1] : userCommonIds[0]; @@ -419,30 +419,28 @@ const CommonFeedComponent: FC = (props) => { }, [rootCommonMember?.id]); useEffect(() => { - return () => { + const updateLastVisited = () => { const common = stateRef.current?.data?.common; - dispatch( - commonLayoutActions.setLastCommonFromFeed({ - id: commonId, - data: common - ? { - name: common.name, - image: common.image, - isProject: checkIsProject(common), - memberCount: common.memberCount, - } - : null, - }), - ); + updateLastVisitedCommon({ + id: commonId, + data: common + ? { + name: common.name, + image: common.image, + isProject: checkIsProject(common), + memberCount: common.memberCount, + } + : null, + }); }; - }, [commonId]); - useEffect(() => { - updateUserActivity({ - lastVisitedCommon: commonId, - }); - }, [updateUserActivity, commonId]); + updateLastVisited(); + + return () => { + updateLastVisited(); + }; + }, [updateLastVisitedCommon, commonId]); if (!isDataFetched) { const headerEl = renderLoadingHeader ? ( diff --git a/src/pages/commonFeed/CommonFeedPage.tsx b/src/pages/commonFeed/CommonFeedPage.tsx index 233a90a473..256c09382e 100644 --- a/src/pages/commonFeed/CommonFeedPage.tsx +++ b/src/pages/commonFeed/CommonFeedPage.tsx @@ -1,12 +1,13 @@ import React, { FC, useEffect, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useParams } from "react-router-dom"; +import { selectUser } from "@/pages/Auth/store/selectors"; import { InboxItemType } from "@/shared/constants"; import { MainRoutesProvider } from "@/shared/contexts"; +import { useLastVisitedCommon } from "@/shared/hooks/useCases"; import { MultipleSpacesLayoutPageContent } from "@/shared/layouts"; import { multipleSpacesLayoutActions, - selectCommonLayoutLastCommonFromFeed, selectMultipleSpacesLayoutMainWidth, } from "@/store/states"; import BaseCommonFeedPage, { @@ -59,7 +60,9 @@ const CommonFeedPage: FC = () => { const { id: commonId } = useParams(); const dispatch = useDispatch(); const layoutMainWidth = useSelector(selectMultipleSpacesLayoutMainWidth); - const lastCommonFromFeed = useSelector(selectCommonLayoutLastCommonFromFeed); + const user = useSelector(selectUser()); + const userId = user?.uid; + const { lastVisitedCommon } = useLastVisitedCommon(userId); const onActiveItemDataChange = useActiveItemDataChange(); const feedLayoutSettings = useMemo( () => ({ @@ -68,13 +71,13 @@ const CommonFeedPage: FC = () => { }), [layoutMainWidth], ); - const lastCommonFromFeedData = lastCommonFromFeed?.data; + const lastCommonFromFeedData = lastVisitedCommon?.data; const renderLoadingHeader = lastCommonFromFeedData ? () => ( ) => void; + lastVisitedCommon: CommonLayoutState["lastCommonFromFeed"]; + updateLastVisitedCommon: ( + data: CommonLayoutState["lastCommonFromFeed"], + ) => void; } -export const useUserActivity = (userId?: string): Return => { +export const useLastVisitedCommon = (userId?: string): Return => { const dispatch = useDispatch(); - const lastCommonFromFeed = useSelector(selectCommonLayoutLastCommonFromFeed); + const lastVisitedCommon = useSelector(selectCommonLayoutLastCommonFromFeed); - const updateUserActivity = useCallback( - async (data: Partial) => { - if (data.lastVisitedCommon) { - dispatch( - commonLayoutActions.setLastCommonFromFeed({ - id: data.lastVisitedCommon, - data: null, - }), - ); - } - if (!userId) { + const updateLastVisitedCommon = useCallback< + Return["updateLastVisitedCommon"] + >( + async (data) => { + dispatch(commonLayoutActions.setLastCommonFromFeed(data)); + + if (!userId || !data?.id) { return; } try { - await UserActivityService.updateUserActivity(userId, data); + await UserActivityService.updateUserActivity(userId, { + lastVisitedCommon: data.id, + }); } catch (error) { Logger.error(error); } @@ -62,7 +62,7 @@ export const useUserActivity = (userId?: string): Return => { }, [userId]); return { - lastVisitedCommon: lastCommonFromFeed?.id, - updateUserActivity, + lastVisitedCommon, + updateLastVisitedCommon, }; }; diff --git a/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx b/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx index 40d759d824..de37d17d22 100644 --- a/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx +++ b/src/shared/layouts/CommonSidenavLayout/components/LayoutTabs/LayoutTabs.tsx @@ -10,7 +10,10 @@ import { import { Tab, Tabs } from "@/shared/components"; import { useRoutesContext } from "@/shared/contexts"; import { useModal } from "@/shared/hooks"; -import { useUserActivity, useUserCommonIds } from "@/shared/hooks/useCases"; +import { + useLastVisitedCommon, + useUserCommonIds, +} from "@/shared/hooks/useCases"; import { Avatar2Icon, Blocks2Icon, InboxIcon } from "@/shared/icons"; import { CreateCommonPrompt } from "@/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/components"; import { LayoutTab } from "../../constants"; @@ -41,7 +44,7 @@ const LayoutTabs: FC = (props) => { const user = useSelector(selectUser()); const userId = user?.uid; const { data: userCommonIds } = useUserCommonIds(); - const { lastVisitedCommon } = useUserActivity(userId); + const { lastVisitedCommon } = useLastVisitedCommon(userId); const { isShowing: isCreateCommonPromptOpen, onOpen: onCreateCommonPromptOpen, @@ -81,7 +84,7 @@ const LayoutTabs: FC = (props) => { } as CSSProperties; const handleSpacesClick = () => { - const commonForRedirectId = lastVisitedCommon || userCommonIds[0]; + const commonForRedirectId = lastVisitedCommon?.id || userCommonIds[0]; if (commonForRedirectId) { history.push(getCommonPagePath(commonForRedirectId)); diff --git a/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx b/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx index 962edabb97..ed1a2b51e0 100644 --- a/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx +++ b/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Navigation/Navigation.tsx @@ -7,10 +7,13 @@ import { selectUser, selectUserStreamsWithNotificationsAmount, } from "@/pages/Auth/store/selectors"; -import { InboxItemType, ROUTE_PATHS } from "@/shared/constants"; +import { ROUTE_PATHS } from "@/shared/constants"; import { useRoutesContext } from "@/shared/contexts"; import { useModal } from "@/shared/hooks"; -import { useUserActivity, useUserCommonIds } from "@/shared/hooks/useCases"; +import { + useLastVisitedCommon, + useUserCommonIds, +} from "@/shared/hooks/useCases"; import { BlocksIcon, InboxIcon } from "@/shared/icons"; import { CommonSidenavLayoutTab, @@ -40,8 +43,8 @@ const Navigation: FC = (props) => { const user = useSelector(selectUser()); const userId = user?.uid; const { data: userCommonIds } = useUserCommonIds(); - const { lastVisitedCommon } = useUserActivity(userId); - const mySpacesCommonId = lastVisitedCommon || userCommonIds[0] || ""; + const { lastVisitedCommon } = useLastVisitedCommon(userId); + const mySpacesCommonId = lastVisitedCommon?.id || userCommonIds[0] || ""; const mySpacesPagePath = ( mySpacesCommonId ? getCommonPagePath(mySpacesCommonId) : "" ) as ROUTE_PATHS; From bd9b723cd21f7187965a173f18a01a7df8d1c1f0 Mon Sep 17 00:00:00 2001 From: Andrey Mikhadyuk Date: Wed, 29 Nov 2023 19:08:48 +0400 Subject: [PATCH 17/17] fix apple and google icons props cases --- src/shared/icons/auth/apple.icon.tsx | 4 ++-- src/shared/icons/auth/google.icon.tsx | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/shared/icons/auth/apple.icon.tsx b/src/shared/icons/auth/apple.icon.tsx index fff3aeb538..1344f4b37e 100644 --- a/src/shared/icons/auth/apple.icon.tsx +++ b/src/shared/icons/auth/apple.icon.tsx @@ -12,8 +12,8 @@ const AppleIcon: FC = () => { xmlns="http://www.w3.org/2000/svg" > diff --git a/src/shared/icons/auth/google.icon.tsx b/src/shared/icons/auth/google.icon.tsx index 2fd35cb30c..33719d667c 100644 --- a/src/shared/icons/auth/google.icon.tsx +++ b/src/shared/icons/auth/google.icon.tsx @@ -12,26 +12,26 @@ const GoogleIcon: FC = () => { xmlns="http://www.w3.org/2000/svg" >