From 0ff49cc215f7119736a5cd31ae5a9482c3abd840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor?= Date: Wed, 6 Mar 2024 10:41:48 -0300 Subject: [PATCH 1/2] improvement: use patched subscriptions for both user list and current user --- .../users/loaded-user-list/hook-manager.tsx | 4 +- .../user-list-participants/component.tsx | 21 ++++------ .../imports/ui/core/hooks/useCurrentUser.ts | 2 +- .../ui/core/hooks/useLoadedUserList.ts | 39 +++++++++++++++---- 4 files changed, 42 insertions(+), 24 deletions(-) diff --git a/bigbluebutton-html5/imports/ui/components/plugins-engine/data-consumption/domain/users/loaded-user-list/hook-manager.tsx b/bigbluebutton-html5/imports/ui/components/plugins-engine/data-consumption/domain/users/loaded-user-list/hook-manager.tsx index 59b5d7ffef..1042455c6d 100644 --- a/bigbluebutton-html5/imports/ui/components/plugins-engine/data-consumption/domain/users/loaded-user-list/hook-manager.tsx +++ b/bigbluebutton-html5/imports/ui/components/plugins-engine/data-consumption/domain/users/loaded-user-list/hook-manager.tsx @@ -7,11 +7,11 @@ import { import { DataConsumptionHooks } from 'bigbluebutton-html-plugin-sdk/dist/cjs/data-consumption/enums'; import { UpdatedEventDetails } from 'bigbluebutton-html-plugin-sdk/dist/cjs/core/types'; import formatLoadedUserListDataFromGraphql from './utils'; -import { useLoadedUserList } from '/imports/ui/core/hooks/useLoadedUserList'; +import { useLocalUserList } from '/imports/ui/core/hooks/useLoadedUserList'; const LoadedUserListHookContainer = () => { const [sendSignal, setSendSignal] = useState(false); - const [usersData] = useLoadedUserList((user: Partial) => ({ + const [usersData] = useLocalUserList((user: Partial) => ({ userId: user.userId, name: user.name, role: user.role, diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-participants/component.tsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-participants/component.tsx index 16902accf1..fcd649de52 100644 --- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-participants/component.tsx +++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-list-participants/component.tsx @@ -24,8 +24,8 @@ import useCurrentUser from '/imports/ui/core/hooks/useCurrentUser'; import { layoutSelect } from '/imports/ui/components/layout/context'; import { Layout } from '/imports/ui/components/layout/layoutTypes'; import Service from '/imports/ui/components/user-list/service'; -import { USER_LIST_SUBSCRIPTION } from '/imports/ui/core/graphql/queries/users'; -import { setLoadedUserList } from '/imports/ui/core/hooks/useLoadedUserList'; +import { setLocalUserList, useLoadedUserList } from '/imports/ui/core/hooks/useLoadedUserList'; +import { GraphqlDataHookSubscriptionResponse } from '/imports/ui/Types/hook'; interface UserListParticipantsProps { users: Array; @@ -206,21 +206,14 @@ const UserListParticipantsContainer: React.FC = () => { } = useSubscription(USER_AGGREGATE_COUNT_SUBSCRIPTION); const count = countData?.user_aggregate?.aggregate?.count || 0; - useEffect(() => { - return () => { - setLoadedUserList([]); - }; + useEffect(() => () => { + setLocalUserList([]); }, []); const { data: usersData, - } = useSubscription(USER_LIST_SUBSCRIPTION, { - variables: { - offset, - limit, - }, - }); - const { user: users } = (usersData || {}); + } = useLoadedUserList({ offset, limit }, (u) => u) as GraphqlDataHookSubscriptionResponse>; + const users = usersData ?? []; const { data: currentUser } = useCurrentUser((c: Partial) => ({ isModerator: c.isModerator, @@ -232,7 +225,7 @@ const UserListParticipantsContainer: React.FC = () => { const presentationPage = presentationData?.pres_page_curr[0] || {}; const pageId = presentationPage?.pageId; - setLoadedUserList(users); + setLocalUserList(users); return ( <> (CURRENT_USER_SUBSCRIPTION); +const useCurrentUserSubscription = createUseSubscription(CURRENT_USER_SUBSCRIPTION, {}, true); const useCurrentUser = (fn: (c: Partial) => Partial) => { const response = useCurrentUserSubscription(fn); diff --git a/bigbluebutton-html5/imports/ui/core/hooks/useLoadedUserList.ts b/bigbluebutton-html5/imports/ui/core/hooks/useLoadedUserList.ts index 6e1c6bc3b4..63a87d2839 100644 --- a/bigbluebutton-html5/imports/ui/core/hooks/useLoadedUserList.ts +++ b/bigbluebutton-html5/imports/ui/core/hooks/useLoadedUserList.ts @@ -1,8 +1,10 @@ import { makeVar, useReactiveVar } from '@apollo/client'; import { isEqual } from 'radash'; import { User } from '../../Types/user'; +import { useCreateUseSubscription } from './createUseSubscription'; +import { USER_LIST_SUBSCRIPTION } from '../graphql/queries/users'; -const createLoadedUserListDataGathering = (): [ +const createLocalUserListDataGathering = (): [ (fn: (c: Partial) => Partial) => [ Partial[], (result: Partial[]) => void, @@ -11,7 +13,7 @@ const createLoadedUserListDataGathering = (): [ ] => { const loadedUserList = makeVar[]>([]); - const setLoadedUserList = (result: Partial[]): void => { + const setLocalUserList = (result: Partial[]): void => { const gatheredUserList = loadedUserList(); const hasUsers = gatheredUserList && gatheredUserList.length > 0; const shouldAdd = !hasUsers || !isEqual(gatheredUserList, result); @@ -24,18 +26,41 @@ const createLoadedUserListDataGathering = (): [ } }; - const useLoadedUserList = (fn: ((c: Partial) => Partial)): [ + const useLocalUserList = (fn: ((c: Partial) => Partial)): [ Partial[], (result: Partial[]) => void, ] => { const gatheredLoadedUserList = useReactiveVar(loadedUserList); const loadedUserListData = Object.values(gatheredLoadedUserList).filter((i) => Array.isArray(i)).flat(); - return [loadedUserListData.map(fn), setLoadedUserList]; + return [loadedUserListData.map(fn), setLocalUserList]; }; - return [useLoadedUserList, setLoadedUserList]; + return [useLocalUserList, setLocalUserList]; }; -const [useLoadedUserList, setLoadedUserList] = createLoadedUserListDataGathering(); +const useLoadedUserList = ( + variables: { offset: number, limit: number }, + fn: (c: Partial) => Partial, +) => { + const useLoadedUserListSubscription = useCreateUseSubscription( + USER_LIST_SUBSCRIPTION, + variables, + true, + ); + const loadedUserList = useLoadedUserListSubscription(fn); + return loadedUserList; +}; -export { useLoadedUserList, setLoadedUserList }; +const [useLocalUserList, setLocalUserList] = createLocalUserListDataGathering(); + +export { + useLoadedUserList, + useLocalUserList, + setLocalUserList, +}; + +export default { + useLoadedUserList, + useLocalUserList, + setLocalUserList, +}; From 0f6d5205e496123acf43e571d48df7bebe973eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor?= Date: Thu, 7 Mar 2024 17:38:49 -0300 Subject: [PATCH 2/2] fix: prevent patching objects in place --- .../imports/ui/core/hooks/createUseSubscription.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigbluebutton-html5/imports/ui/core/hooks/createUseSubscription.ts b/bigbluebutton-html5/imports/ui/core/hooks/createUseSubscription.ts index 4cb35964e9..e9088520cb 100644 --- a/bigbluebutton-html5/imports/ui/core/hooks/createUseSubscription.ts +++ b/bigbluebutton-html5/imports/ui/core/hooks/createUseSubscription.ts @@ -4,7 +4,7 @@ import { } from 'react'; import { gql, useApolloClient } from '@apollo/client'; import R from 'ramda'; -import { applyPatch } from 'fast-json-patch'; +import { applyPatch, deepClone } from 'fast-json-patch'; import { GraphqlDataHookSubscriptionResponse } from '../../Types/hook'; function createUseSubscription( @@ -55,7 +55,7 @@ function createUseSubscription( const { data } = response; let currentData: T[] = []; if (usePatchedSubscription && data.patch) { - const patchedData = applyPatch(dataRef.current, data.patch).newDocument; + const patchedData = applyPatch(deepClone(dataRef.current), data.patch).newDocument; currentData = [...patchedData]; } else { const resultSetKey = Object.keys(data)[0];