Newer
Older
/* eslint react/prop-types: 0 */
import React, { useContext, useState, useMemo, useCallback } from 'react';
import useDeepCompareEffect from 'use-deep-compare-effect';
import { each, uniqBy, sortBy, groupBy } from 'lodash';
import {
WaxContext,
ApplicationContext,
DocumentHelpers,
} from 'wax-prosemirror-core';
import CommentDecorationPluginKey from '../plugins/CommentDecorationPluginKey';
export default ({ area, users }) => {
const { app } = useContext(ApplicationContext);
const trakChangePlugin = app.PmPlugins.get('trackChangePlugin');
const [isFirstRun, setFirstRun] = useState(true);
const setTops = useCallback(() => {
const result = [];
let annotationTop = 0;
let boxHeight = 0;
let top = 0;
let panelWrapper = {};
let panelWrapperHeight = {};
if (main) {
WaxSurface = main.dom.getBoundingClientRect();
WaxSurfaceMarginTop = window.getComputedStyle(main.dom).marginTop;
let id = '';
if (markNode?.node?.attrs.id) {
id = markNode.node.attrs.id;
} else if (markNode?.attrs?.id) {
id = markNode.attrs.id;
} else {
id = markNode.id;
}
if (trakChangePlugin)
activeTrackChange = trakChangePlugin.getState(activeView.state)
.trackChange;
(activeTrackChange && id === activeTrackChange.attrs.id)
)
isActive = true;
if (!markNodeEl && marksNodes[area][pos - 1]) {
markNodeEl = document.querySelector(
`[data-id="${marksNodes[area][pos - 1].id}"]`,
);
}
if (markNodeEl) {
markNodeEl.getBoundingClientRect().top -
WaxSurface.top +
parseInt(WaxSurfaceMarginTop.slice(0, -2), 10);
panelWrapper = document.getElementsByClassName('panelWrapper');
panelWrapperHeight = panelWrapper[0].getBoundingClientRect().height;
markNodeEl = document
.querySelector('#notes-container')
.querySelector(`[data-id="${id}"]`);
if (markNodeEl) {
const WaxContainerTop = document
.querySelector('#wax-container')
.getBoundingClientRect().top;
markNodeEl.getBoundingClientRect().top -
panelWrapperHeight -
WaxContainerTop -
50;
}
if (markNodeEl) {
boxEl = document.querySelector(`div[data-box="${id}"]`);
}
if (boxEl) {
boxHeight = parseInt(boxEl.offsetHeight, 10);
// where the box should move to
top = annotationTop;
}
// if the above comment box has already taken up the height, move down
if (pos > 0) {
const previousEndHeight = previousBox.endHeight;
if (annotationTop < previousEndHeight) {
top = previousEndHeight + 2;
}
}
// store where the box ends to be aware of overlaps in the next box
allCommentsTop.push({ [id]: result[pos] });
// if active, move as many boxes above as needed to bring it to the annotation's height
if (isActive) {
let b = true;
let i = pos;
// first one active, none above
const boxAboveEnds = boxAbove.endHeight;
const currentTop = result[i];
const doesOverlap = boxAboveEnds > currentTop;
if (doesOverlap) {
const overlap = boxAboveEnds - currentTop;
result[i - 1] -= overlap;
let previousMarkNode = '';
if (marksNodes[area][i - 1]?.node?.attrs.id) {
previousMarkNode = marksNodes[area][i - 1].node.attrs.id;
} else if (marksNodes[area][i - 1]?.attrs?.id) {
previousMarkNode = marksNodes[area][i - 1].attrs.id;
} else {
previousMarkNode = marksNodes[area][i - 1].id;
}
}
if (!doesOverlap) b = false;
if (i <= 1) b = false;
i -= 1;
}
}
});
return allCommentsTop;
});
const recalculateTops = () => {
setTimeout(() => {
setPosition(setTops());
});
};
if (app.config.get('config.YjsService')) {
setMarksNodes(
updateMarks(
pmViews,
CommentDecorationPluginKey?.getState(
activeView.state,
)?.allCommentsDataList(),
),
);
} else {
setMarksNodes(
updateMarks(
pmViews,
CommentDecorationPluginKey?.getState(
activeView.state,
)?.allCommentsList(),
),
);
}
setPosition(setTops());
setFirstRun(false);
}, 400);
} else {
CommentDecorationPluginKey?.getState(activeView.state)?.allCommentsList(),
const CommentTrackComponent = useMemo(
[marksNodes[area] || [], position, users, context.options.activeComment],
const updateMarks = (views, comments) => {
const newComments = groupBy(comments, comm => comm.data.group) || [];
...DocumentHelpers.findInlineNodes(views[eachView].state.doc),
const allBlockNodes = DocumentHelpers.findBlockNodes(views.main.state.doc);
allInlineNodes.map(node => {
if (node.node.marks.length > 0) {
node.node.marks.filter(mark => {
if (
mark.type.name === 'insertion' ||
mark.type.name === 'deletion' ||
mark.type.name === 'format_change'
finalMarks.push(mark);
}
});
}
allBlockNodes.map(node => {
if (node.node.attrs.track && node.node.attrs.track.length > 0) {
finalNodes.push(node);
}
});
const nodesAndMarks = [...uniqBy(finalMarks, 'attrs.id'), ...finalNodes];
const groupedMarkNodes = { main: [], notes: [] };
const markNodeAttrs = markNode.attrs
? markNode.attrs
: markNode.node.attrs;
if (!groupedMarkNodes[markNodeAttrs.group]) {
groupedMarkNodes[markNodeAttrs.group] = [markNode];
groupedMarkNodes[markNodeAttrs.group].push(markNode);
groupedMarkNodes.main = groupedMarkNodes.main.concat(newComments.main);
if (newComments?.notes?.length > 0)
groupedMarkNodes.notes = groupedMarkNodes.notes.concat(newComments.notes);
main: sortBy(groupedMarkNodes.main, ['data.pmFrom']),