Skip to content
Snippets Groups Projects
ActiveComment.js 2.13 KiB
Newer Older
chris's avatar
chris committed
import { minBy, maxBy } from "lodash";
chris's avatar
chris committed
import { Plugin, PluginKey } from "prosemirror-state";
import { Decoration, DecorationSet } from "prosemirror-view";
import { DocumentHelpers } from "wax-prosemirror-utilities";
const activeComment = new PluginKey("activeComment");

const getComment = state => {
  if (state.selection.from !== state.selection.to) return;

  const commentMark = state.schema.marks["comment"];
chris's avatar
chris committed
  const commentOnSelection = DocumentHelpers.findMark(state, commentMark);
  if (commentOnSelection) {
chris's avatar
chris committed
    const commentNodes = DocumentHelpers.findChildrenByMark(
      state.doc,
      commentMark,
      true
    );
chris's avatar
chris committed
    const allCommentsWithSameId = [];

chris's avatar
chris committed
    commentNodes.map(node => {
chris's avatar
chris committed
      node.node.marks.filter(mark => {
        if (
          mark.type.name === "comment" &&
          commentOnSelection.attrs.id === mark.attrs.id
        ) {
          mark.from = node.pos;
          mark.to = node.pos + node.node.text.length;
          allCommentsWithSameId.push(mark);
        }
      });
    });
    if (allCommentsWithSameId.length > 1) {
      const minPos = minBy(allCommentsWithSameId, "from");
      const maxPos = maxBy(allCommentsWithSameId, "to");

      return {
        from: minPos.from,
        to: maxPos.to,
        attrs: commentOnSelection.attrs,
        contained: commentOnSelection.contained
      };
    }
  }

  return commentOnSelection;
chris's avatar
chris committed

export default props => {
  return new Plugin({
    key: activeComment,
    state: {
      init: (_, state) => {
        return { comment: getComment(state) };
      },
      apply(tr, prev, _, newState) {
        const comment = getComment(newState);
        let createDecoration;
        if (comment) {
          createDecoration = DecorationSet.create(newState.doc, [
            Decoration.inline(comment.from, comment.to, {
              class: "active-comment"
            })
          ]);
        }
        return {
          comment,
          createDecoration
        };
      }
    },
chris's avatar
chris committed
    props: {
      decorations: state => {
        const commentPluginState = state && activeComment.getState(state);
        return commentPluginState.createDecoration;