mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-05 22:38:48 +00:00
* 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
88 lines
3 KiB
JavaScript
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;
|