Skip to content
Snippets Groups Projects
CommentPlugin.js 2.23 KiB
Newer Older
chris's avatar
chris committed
/* eslint-disable consistent-return */
chris's avatar
chris committed
import { inRange, last, sortBy } from 'lodash';
chris's avatar
chris committed
import { Plugin, PluginKey } from 'prosemirror-state';
import { Decoration, DecorationSet } from 'prosemirror-view';
import { CommentDecorationPluginKey } from './CommentDecorationPlugin';
chris's avatar
chris committed
const commentPlugin = new PluginKey('commentPlugin');
chris's avatar
chris committed
const getComment = (state, context) => {
  const commentsMap = CommentDecorationPluginKey.getState(state).getMap();
chris's avatar
chris committed
  const commentsDataMap = CommentDecorationPluginKey.getState(
    state,
  ).getCommentsDataMap();
  if (commentsMap.size === 0) return;
  let commentData = [];

  commentsMap.forEach(comment => {
    if (inRange(state.selection.from, comment.data.pmFrom, comment.data.pmTo)) {
      commentData.push(comment);
chris's avatar
chris committed
    } else if (state.selection.from === state.selection.to) {
      context.setOption({ activeComment: undefined });
chris's avatar
chris committed

chris's avatar
chris committed
  commentData = sortBy(commentData, ['data.pmFrom']);
chris's avatar
chris committed

chris's avatar
chris committed
  if (commentData.length > 0) {
chris's avatar
chris committed
      (state.selection.from !== state.selection.to &&
chris's avatar
chris committed
        commentsDataMap.get(last(commentData)?.id)?.data?.conversation
          .length === 0) ||
chris's avatar
chris committed
      (state.selection.from === state.selection.to &&
chris's avatar
chris committed
        commentsDataMap.get(last(commentData)?.id)?.data?.conversation
          .length !== 0)
chris's avatar
chris committed
      context.setOption({ activeComment: last(commentData) });
chris's avatar
chris committed
      return last(commentData);
    return undefined;
chris's avatar
chris committed
  }
chris's avatar
chris committed

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