Files
outline/shared/editor/marks/Comment.ts
Tom Moor fc8c20149f feat: Comments (#4911)
* Comment model

* Framework, model, policy, presenter, api endpoint etc

* Iteration, first pass of UI

* fixes, refactors

* Comment commands

* comment socket support

* typing indicators

* comment component, styling

* wip

* right sidebar resize

* fix: CMD+Enter submit

* Add usePersistedState
fix: Main page scrolling on comment highlight

* drafts

* Typing indicator

* refactor

* policies

* Click thread to highlight
Improve comment timestamps

* padding

* Comment menu v1

* Change comments to use editor

* Basic comment editing

* fix: Hide commenting button when disabled at team level

* Enable opening sidebar without mark

* Move selected comment to location state

* Add comment delete confirmation

* Add comment count to document meta

* fix: Comment sidebar togglable
Add copy link to comment

* stash

* Restore History changes

* Refactor right sidebar to allow for comment animation

* Update to new router best practices

* stash

* Various improvements

* stash

* Handle click outside

* Fix incorrect placeholder in input
fix: Input box appearing on other sessions erroneously

* stash

* fix: Don't leave orphaned child comments

* styling

* stash

* Enable comment toggling again

* Edit styling, merge conflicts

* fix: Cannot navigate from insights to comments

* Remove draft comment mark on click outside

* Fix: Empty comment sidebar, tsc

* Remove public toggle

* fix: All comments are recessed
fix: Comments should not be printed

* fix: Associated mark should be removed on comment delete

* Revert unused changes

* Empty state, basic RTL support

* Create dont toggle comment mark

* Make it feel more snappy

* Highlight active comment in text

* fix animation

* RTL support

* Add reply CTA

* Translations
2023-02-25 12:03:05 -08:00

108 lines
2.7 KiB
TypeScript

import { toggleMark } from "prosemirror-commands";
import { MarkSpec, MarkType, Schema } from "prosemirror-model";
import { EditorState, Plugin } from "prosemirror-state";
import { v4 as uuidv4 } from "uuid";
import collapseSelection from "../commands/collapseSelection";
import { Command } from "../lib/Extension";
import chainTransactions from "../lib/chainTransactions";
import isMarkActive from "../queries/isMarkActive";
import { Dispatch } from "../types";
import Mark from "./Mark";
export default class Comment extends Mark {
get name() {
return "comment";
}
get schema(): MarkSpec {
return {
attrs: {
id: {},
userId: {},
},
inclusive: false,
parseDOM: [{ tag: "span.comment" }],
toDOM: (node) => [
"span",
{ class: "comment", id: `comment-${node.attrs.id}` },
],
};
}
keys({ type }: { type: MarkType }): Record<string, Command> {
return this.options.onCreateCommentMark
? {
"Mod-Alt-m": (state: EditorState, dispatch: Dispatch) => {
if (isMarkActive(state.schema.marks.comment)(state)) {
return false;
}
chainTransactions(
toggleMark(type, {
id: uuidv4(),
userId: this.options.userId,
}),
collapseSelection()
)(state, dispatch);
return true;
},
}
: {};
}
commands({ type }: { type: MarkType; schema: Schema }) {
return this.options.onCreateCommentMark
? () => (state: EditorState, dispatch: Dispatch) => {
if (isMarkActive(state.schema.marks.comment)(state)) {
return false;
}
chainTransactions(
toggleMark(type, {
id: uuidv4(),
userId: this.options.userId,
}),
collapseSelection()
)(state, dispatch);
return true;
}
: undefined;
}
toMarkdown() {
return {
open: "",
close: "",
mixable: true,
expelEnclosingWhitespace: true,
};
}
get plugins(): Plugin[] {
return [
new Plugin({
props: {
handleDOMEvents: {
mousedown: (view, event: MouseEvent) => {
if (
!(event.target instanceof HTMLSpanElement) ||
!event.target.classList.contains("comment")
) {
this.options?.onClickCommentMark?.();
return false;
}
const commentId = event.target.id.replace("comment-", "");
this.options?.onClickCommentMark?.(commentId);
return false;
},
},
},
}),
];
}
}