ToolJet/frontend/src/Editor/RealtimeCursors.jsx
Nakul Nagargade 0a82e50afb
Move Editor's version manager regarding states to zustand store (#6593)
* Move version manager editor states to zustand

* Update appDataStore to appVersionsManagerStore

* Move released version popup state to global

* Move isVersionReleased to global store

* Rename appVersionsManagerStore to appVersionStore and destructure zustand data inside components

* Remove closeCreateVersionModalPrompt and showCreateVersionModalPrompt

* Refactor isVersionReleased

* Resolve code comments

* update action on clicking release version btn

* Resolve code comments

* Resolve code comments

* Resolve code comments

* Fix isVersionReleased not getting updated on editor mount

* Fix released version error message not shaking on editng released version

* Resolve code comments

* Fix preview in query giving internal server error
2023-06-29 15:30:10 +05:30

88 lines
3 KiB
JavaScript

/* eslint-disable import/no-unresolved */
import React from 'react';
import { useOthers, useSelf, useUpdatePresence } from '@y-presence/react';
import { useEventListener } from '@/_hooks/use-event-listener';
import { xorWith, isEqual } from 'lodash';
import { Cursor } from './Cursor';
import { USER_COLORS } from '@/_helpers/constants';
import { userService, authenticationService } from '@/_services';
import { useAppVersionStore } from '@/_stores/appVersionStore';
import { shallow } from 'zustand/shallow';
const RealtimeCursors = ({ editingPageId }) => {
const others = useOthers();
const unavailableColors = others.map((other) => other?.presence?.color);
const availableColors = xorWith(USER_COLORS, unavailableColors, isEqual);
const { editingVersionId } = useAppVersionStore(
(state) => ({
editingVersionId: state?.editingVersion?.id,
}),
shallow
);
const self = useSelf();
const updatePresence = useUpdatePresence();
React.useEffect(() => {
updatePresence({ color: availableColors[Math.floor(Math.random() * availableColors.length)] });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useEffect(() => {
updatePresence({ editingVersionId, editingPageId });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [editingVersionId, editingPageId]);
React.useEffect(() => {
async function fetchAvatar(avatarId) {
const blob = await userService.getAvatar(avatarId);
const fileReader = new FileReader();
fileReader.onload = (e) => {
updatePresence({ image: e.target.result });
};
fileReader.readAsDataURL(blob);
}
const currentSession = authenticationService.currentSessionValue;
const currentUser = currentSession?.current_user;
if (currentUser.avatar_id) fetchAvatar(currentUser.avatar_id);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const othersOnSameVersionAndPage = others.filter(
(other) =>
other?.presence?.editingVersionId === self?.presence.editingVersionId &&
other?.presence?.editingPageId === self?.presence.editingPageId
);
const handlePointerMove = React.useCallback(
(e) => {
const element = document.getElementById('real-canvas');
if (element?.parentNode?.matches(':hover')) {
const { left: offsetFromLeftOfCanvas, top: offsetFromTopOfCanvas } = document
.getElementsByClassName('real-canvas')[0]
.getBoundingClientRect();
const x = Math.round(e.pageX - offsetFromLeftOfCanvas);
const y = Math.round(e.pageY - offsetFromTopOfCanvas);
updatePresence({
x,
y,
});
}
},
[updatePresence]
);
useEventListener('mousemove', handlePointerMove);
return (
<>
{othersOnSameVersionAndPage?.map(({ id, presence }) => {
if (!presence) return null;
return <Cursor key={id} name={presence.firstName} color={presence.color} x={presence.x} y={presence.y} />;
})}
</>
);
};
export default RealtimeCursors;