From 2afc6ec5e93f02058a568e42086f93d8e8a45b91 Mon Sep 17 00:00:00 2001 From: swve Date: Wed, 3 Apr 2024 20:19:31 +0200 Subject: [PATCH] feat: add ability to emit content saving notifications --- .../Objects/Editor/EditorWrapper.tsx | 73 ++++++++++++++++--- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/apps/web/components/Objects/Editor/EditorWrapper.tsx b/apps/web/components/Objects/Editor/EditorWrapper.tsx index e668f8f7..8883969a 100644 --- a/apps/web/components/Objects/Editor/EditorWrapper.tsx +++ b/apps/web/components/Objects/Editor/EditorWrapper.tsx @@ -1,5 +1,5 @@ 'use client' -import { default as React, useEffect } from 'react' +import { default as React, useEffect, useRef, useState } from 'react' import Editor from './Editor' import { updateActivity } from '@services/courses/activities' import { toast } from 'react-hot-toast' @@ -22,27 +22,32 @@ interface EditorWrapperProps { function EditorWrapper(props: EditorWrapperProps): JSX.Element { const session = useSession() as any + // Define provider in the state + const [provider, setProvider] = React.useState(null); + /* Collaboration Features */ const collab = getCollaborationServerUrl() - const isCollabEnabledOnThisOrg = props.org.config.config.GeneralConfig.collaboration && collab + const isCollabEnabledOnThisOrg = props.org.config.config.GeneralConfig.collaboration && collab const doc = new Y.Doc() // Store the Y document in the browser new IndexeddbPersistence(props.activity.activity_uuid, doc) - const provider = isCollabEnabledOnThisOrg ? new HocuspocusProvider({ - url: collab, - name: props.activity.activity_uuid, - document: doc, - preserveConnection: false, - }) : null - /* Collaboration Features */ async function setContent(content: any) { let activity = props.activity activity.content = content + + provider?.setAwarenessField("savings_states", { + [session.user.user_uuid]: { + status: 'action_save', + timestamp: new Date().toISOString(), + user: session.user + } + }); + toast.promise(updateActivity(activity, activity.activity_uuid), { loading: 'Saving...', success: Activity saved!, @@ -50,10 +55,54 @@ function EditorWrapper(props: EditorWrapperProps): JSX.Element { }) } + + + // Create a ref to store the last save timestamp of each user + const lastSaveTimestampRef = useRef({}) as any; + useEffect(() => { - - } - , [session]) + // Check if provider is not already set + if (!provider) { + const newProvider = new HocuspocusProvider({ + url: collab, + name: props.activity.activity_uuid, + document: doc, + + // TODO(alpha code): This whole block of code should be improved to something more efficient and less hacky + onAwarenessUpdate: ({ states }) => { + const usersStates = states; + + // Check if a user has saved the document + usersStates.forEach((userState: any) => { + if (userState.savings_states) { + const savingsState = userState.savings_states + + // Check if a user has saved the document + Object.keys(savingsState).forEach(user => { + const userObj = savingsState[user].user; + const status = savingsState[user].status; + const timestamp = savingsState[user].timestamp; + + // Get the current timestamp + const currentTimestamp = new Date().getTime(); + + // If the user has saved the document and the timestamp is close to the current timestamp, show the toast + if (status === 'action_save' && Math.abs(currentTimestamp - new Date(timestamp).getTime()) < 10) { // 5000 milliseconds = 5 seconds + // Update the last save timestamp for this user + lastSaveTimestampRef.current[user] = timestamp; + + toast.success(`${userObj.first_name} ${userObj.last_name} has saved the document`); + } + }); + } + }) + }, + }); + + // Set the new provider + setProvider(newProvider); + } + }, []); {