Newer
Older
import React, {
useContext,
useState,
useEffect,
useMemo,
import styled from "styled-components";
import { DocumentHelpers } from "wax-prosemirror-utilities";
import { each, uniqBy, sortBy } from "lodash";
const { view: { main }, app, activeView } = useContext(WaxContext);
const commentPlugin = app.PmPlugins.get("commentPlugin");
const [position, setPosition] = useState();
const setTops = useCallback(() => {
const result = [];
let annotationTop = 0;
let boxHeight = 0;
let top = 0;
const id =
markNode instanceof Mark ? markNode.attrs.id : markNode.node.attrs.id;
const activeComment = commentPlugin.getState(activeView.state).comment;
if (activeComment && id === activeComment.attrs.id) isActive = true;
markNodeEl = document.querySelector(`[data-id="${id}"]`);
if (markNodeEl)
annotationTop =
markNodeEl.getBoundingClientRect().top - WaxSurface.top;
} else {
const panelWrapper = document.getElementsByClassName("panelWrapper");
const panelWrapperHeight = panelWrapper[0].getBoundingClientRect()
.height;
.querySelector(`[data-id="${id}"]`);
markNodeEl.getBoundingClientRect().top - panelWrapperHeight - 50;
const boxEl = document.querySelector(`div[data-box="${id}"]`);
if (boxEl) boxHeight = parseInt(boxEl.offsetHeight);
// 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;
const previousMarkNode =
marksNodes[area][i - 1] instanceof Mark
? marksNodes[area][i - 1].attrs.id
: marksNodes[area][i - 1].node.attrs.id;
}
if (!doesOverlap) b = false;
if (i <= 1) b = false;
i -= 1;
}
}
});
[JSON.stringify(updateMarks(main)), JSON.stringify(setTops())]
const CommentTrackComponent = useMemo(
return <Fragment>{CommentTrackComponent}</Fragment>;
const updateMarks = view => {
const allBlockNodes = DocumentHelpers.findBlockNodes(view.state.doc);
const allInlineNodes = DocumentHelpers.findInlineNodes(view.state.doc);
const finalMarks = [];
allInlineNodes.map(node => {
if (node.node.marks.length > 0) {
node.node.marks.filter(mark => {
if (
mark.type.name === "comment" ||
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 = {};
sortBy(nodesAndMarks, ["pos"]).forEach(markNode => {
const markNodeAttrs = markNode.attrs
? markNode.attrs
: markNode.node.attrs;
if (!groupedMarkNodes[markNodeAttrs.group]) {
groupedMarkNodes[markNodeAttrs.group] = [markNode];
groupedMarkNodes[markNodeAttrs.group].push(markNode);