Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
CommentPlugin.js 1.73 KiB
/* eslint-disable consistent-return */
import { inRange, last, sortBy } from 'lodash';
import { Plugin, PluginKey } from 'prosemirror-state';
import { Decoration, DecorationSet } from 'prosemirror-view';

const commentPlugin = new PluginKey('commentPlugin');

const getComment = (state, context) => {
  const {
    options: { comments },
  } = context;
  if (!comments?.length) return;
  let commentData = comments.filter(comment =>
    inRange(state.selection.from, comment.data.pmFrom, comment.data.pmTo),
  );

  commentData = sortBy(commentData, ['data.pmFrom']);
  if (commentData.length > 0) {
    if (
      (state.selection.from !== state.selection.to &&
        last(commentData).data.conversation.length === 0) ||
      (state.selection.from === state.selection.to &&
        last(commentData).data.conversation.length !== 0)
    ) {
      return last(commentData);
    }
    return undefined;
  }
  return undefined;
};

export default (key, context) => {
  return new Plugin({
    key: commentPlugin,
    state: {
      init: (_, state) => {
        return { comment: getComment(state, context) };
      },
      apply(tr, prev, _, newState) {
        const comment = getComment(newState, context);
        let createDecoration;
        if (comment) {
          createDecoration = DecorationSet.create(newState.doc, [
            Decoration.inline(comment.data.pmFrom, comment.data.pmTo, {
              class: 'active-comment',
            }),
          ]);
        }
        return {
          comment,
          createDecoration,
        };
      },
    },
    props: {
      decorations: state => {
        const commentPluginState = state && commentPlugin.getState(state);
        return commentPluginState.createDecoration;
      },
    },
  });
};