From 6a47202c786eff51502695ee7226bdb062a8bd44 Mon Sep 17 00:00:00 2001 From: swve Date: Fri, 5 Apr 2024 00:49:14 +0200 Subject: [PATCH] feat: add live users avatar indicators --- .../Objects/Editor/ActiveAvatars.tsx | 67 +++++++++++++++++++ apps/web/components/Objects/Editor/Editor.tsx | 14 ++-- .../Objects/Editor/EditorWrapper.tsx | 12 +++- .../Objects/Editor/MouseMovements.tsx | 21 ++++-- apps/web/components/Objects/UserAvatar.tsx | 1 - 5 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 apps/web/components/Objects/Editor/ActiveAvatars.tsx diff --git a/apps/web/components/Objects/Editor/ActiveAvatars.tsx b/apps/web/components/Objects/Editor/ActiveAvatars.tsx new file mode 100644 index 00000000..db84a79f --- /dev/null +++ b/apps/web/components/Objects/Editor/ActiveAvatars.tsx @@ -0,0 +1,67 @@ +import React, { useEffect, useState } from 'react' +import UserAvatar from '../UserAvatar' +import { useSession } from '@components/Contexts/SessionContext' +import { getUserAvatarMediaDirectory } from '@services/media/media'; +import { getCollaborationServerUrl } from '@services/config/config'; +import { useOrg } from '@components/Contexts/OrgContext'; + +type ActiveAvatarsProps = { + mouseMovements: any; + userRandomColor: string; +} + +function ActiveAvatars(props: ActiveAvatarsProps) { + const session = useSession() as any; + const org = useOrg() as any; + const [activeUsers, setActiveUsers] = useState({} as any); + + /* Collaboration Features */ + const collab = getCollaborationServerUrl() + const isCollabEnabledOnThisOrg = org?.config.config.GeneralConfig.collaboration && collab + + // Get users from the mouseMovements object + useEffect(() => { + const users: any = {}; + Object.keys(props.mouseMovements).forEach((key) => { + users[props.mouseMovements[key].user.user_uuid] = props.mouseMovements[key].user; + }); + + // Remove the current user from the list + delete users[session.user.user_uuid]; + + setActiveUsers(users); + } + , [props.mouseMovements, session.user, org]); + + + return ( +
+ +
+ {isCollabEnabledOnThisOrg && Object.keys(activeUsers).map((key) => ( +
+ +
+
+ ))} + {session.isAuthenticated && ( +
+ +
+ )} +
+
+ ) +} + +export default ActiveAvatars \ No newline at end of file diff --git a/apps/web/components/Objects/Editor/Editor.tsx b/apps/web/components/Objects/Editor/Editor.tsx index 8779b264..d5dedaad 100644 --- a/apps/web/components/Objects/Editor/Editor.tsx +++ b/apps/web/components/Objects/Editor/Editor.tsx @@ -48,6 +48,7 @@ import UserAvatar from '../UserAvatar' import randomColor from 'randomcolor' import Collaboration from '@tiptap/extension-collaboration' import CollaborationCursor from '@tiptap/extension-collaboration-cursor' +import ActiveAvatars from './ActiveAvatars' interface Editor { content: string @@ -59,6 +60,7 @@ interface Editor { hocuspocusProvider: any, isCollabEnabledOnThisOrg: boolean userRandomColor: string + mouseMovements: any setContent: (content: string) => void } @@ -137,13 +139,14 @@ function Editor(props: Editor) { ...(props.isCollabEnabledOnThisOrg ? [ Collaboration.configure({ document: props.hocuspocusProvider?.document, + }), CollaborationCursor.configure({ provider: props.hocuspocusProvider, user: { name: props.session.user.first_name + ' ' + props.session.user.last_name, - color: props.userRandomColor , + color: props.userRandomColor, }, }), ] : []), @@ -267,14 +270,7 @@ function Editor(props: Editor) { /> - {!session.isAuthenticated && Loading} - {session.isAuthenticated && ( - - )} + diff --git a/apps/web/components/Objects/Editor/EditorWrapper.tsx b/apps/web/components/Objects/Editor/EditorWrapper.tsx index e910f76b..f82694c3 100644 --- a/apps/web/components/Objects/Editor/EditorWrapper.tsx +++ b/apps/web/components/Objects/Editor/EditorWrapper.tsx @@ -100,6 +100,14 @@ function EditorWrapper(props: EditorWrapperProps): JSX.Element { document: doc, // TODO(alpha code): This whole block of code should be improved to something more efficient and less hacky + onConnect: () => { + // Set the online page instance ID + setOnlinePageInstanceID(uuidv4()); + + // Set the user color + setThisPageColor(randomColor({ luminosity: 'light' }) as string); + }, + onAwarenessUpdate: ({ states }) => { const usersStates = states; /* Showing user mouse movement */ @@ -121,6 +129,7 @@ function EditorWrapper(props: EditorWrapperProps): JSX.Element { }; } ); + } }); @@ -162,7 +171,7 @@ function EditorWrapper(props: EditorWrapperProps): JSX.Element { return ( <> - + {!session.isLoading && ()} diff --git a/apps/web/components/Objects/Editor/MouseMovements.tsx b/apps/web/components/Objects/Editor/MouseMovements.tsx index 8c0b7070..403cd1b6 100644 --- a/apps/web/components/Objects/Editor/MouseMovements.tsx +++ b/apps/web/components/Objects/Editor/MouseMovements.tsx @@ -1,5 +1,6 @@ -import { m, motion } from "framer-motion"; -import React from 'react' +import { getCollaborationServerUrl } from "@services/config/config"; +import { motion } from "framer-motion"; +import React, { useEffect } from 'react' interface User { user_uuid: string; @@ -18,12 +19,24 @@ interface Movement { interface MouseMovementsProps { movements: Record; onlinePageInstanceID: string; + org ?: any; } -function MouseMovements({ movements, onlinePageInstanceID }: MouseMovementsProps): JSX.Element { +function MouseMovements({ movements, onlinePageInstanceID, org }: MouseMovementsProps): JSX.Element { + + + /* Collaboration config */ + const collab = getCollaborationServerUrl() + const isCollabEnabledOnThisOrg = org?.config.config.GeneralConfig.collaboration && collab + + useEffect(() => { + + } + , [movements, org]); + return (
- {Object.keys(movements).map((key) => ( + {isCollabEnabledOnThisOrg && Object.keys(movements).map((key) => ( movements[key].onlinePageInstanceID !== onlinePageInstanceID && (