1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
import { Plugin, EditorState } from "prosemirror-state"
import './FormattedTextBoxComment.scss'
import { ResolvedPos, Mark } from "prosemirror-model";
import { EditorView } from "prosemirror-view";
import { Doc } from "../../../new_fields/Doc";
export let selectionSizePlugin = new Plugin({
view(editorView) { return new SelectionSizeTooltip(editorView); }
})
export function findOtherUserMark(marks: Mark[]): Mark | undefined {
return marks.find(m => m.attrs.userid && m.attrs.userid !== Doc.CurrentUserEmail);
}
export function findUserMark(marks: Mark[]): Mark | undefined {
return marks.find(m => m.attrs.userid);
}
export function findStartOfMark(rpos: ResolvedPos, view: EditorView, finder: (marks: Mark[]) => Mark | undefined) {
let before = 0;
let nbef = rpos.nodeBefore;
while (nbef && finder(nbef.marks)) {
before += nbef.nodeSize;
rpos = view.state.doc.resolve(rpos.pos - nbef.nodeSize);
rpos && (nbef = rpos.nodeBefore);
}
return before;
}
export function findEndOfMark(rpos: ResolvedPos, view: EditorView, finder: (marks: Mark[]) => Mark | undefined) {
let after = 0;
let naft = rpos.nodeAfter;
while (naft && finder(naft.marks)) {
after += naft.nodeSize;
rpos = view.state.doc.resolve(rpos.pos + naft.nodeSize);
rpos && (naft = rpos.nodeAfter);
}
return after;
}
export class SelectionSizeTooltip {
static tooltip: HTMLElement;
static start: number;
static end: number;
static mark: Mark;
static opened: boolean;
static textBox: any;
constructor(view: any) {
if (!SelectionSizeTooltip.tooltip) {
const root = document.getElementById("root");
SelectionSizeTooltip.tooltip = document.createElement("div");
SelectionSizeTooltip.tooltip.className = "FormattedTextBox-tooltip";
SelectionSizeTooltip.tooltip.style.pointerEvents = "all";
SelectionSizeTooltip.tooltip.onpointerdown = (e: PointerEvent) => {
SelectionSizeTooltip.opened = !SelectionSizeTooltip.opened;
SelectionSizeTooltip.textBox.setAnnotation(
SelectionSizeTooltip.start, SelectionSizeTooltip.end, SelectionSizeTooltip.mark,
SelectionSizeTooltip.opened, e.button == 2);
};
root && root.appendChild(SelectionSizeTooltip.tooltip);
}
this.update(view, undefined);
}
public static Hide() {
SelectionSizeTooltip.textBox = undefined;
SelectionSizeTooltip.tooltip && (SelectionSizeTooltip.tooltip.style.display = "none");
}
public static SetState(textBox: any, opened: boolean, start: number, end: number, mark: Mark) {
SelectionSizeTooltip.textBox = textBox;
SelectionSizeTooltip.start = start;
SelectionSizeTooltip.end = end;
SelectionSizeTooltip.mark = mark;
SelectionSizeTooltip.opened = opened;
SelectionSizeTooltip.textBox && SelectionSizeTooltip.tooltip && (SelectionSizeTooltip.tooltip.style.display = "");
}
update(view: EditorView, lastState?: EditorState) {
let state = view.state;
// Don't do anything if the document/selection didn't change
if (lastState && lastState.doc.eq(state.doc) &&
lastState.selection.eq(state.selection)) return;
if (state.selection.$from) {
let nbef = findStartOfMark(state.selection.$from, view, findOtherUserMark);
let naft = findEndOfMark(state.selection.$from, view, findOtherUserMark);
let child = state.selection.$from.nodeBefore;
let mark = child && findOtherUserMark(child.marks);
if (mark && child && nbef && naft) {
SelectionSizeTooltip.tooltip.textContent = mark.attrs.userid;
// These are in screen coordinates
// let start = view.coordsAtPos(state.selection.from), end = view.coordsAtPos(state.selection.to);
let start = view.coordsAtPos(state.selection.from - nbef), end = view.coordsAtPos(state.selection.from - nbef);
// The box in which the tooltip is positioned, to use as base
let box = (document.getElementById("main-div") as any).getBoundingClientRect();
// Find a center-ish x position from the selection endpoints (when
// crossing lines, end may be more to the left)
let left = Math.max((start.left + end.left) / 2, start.left + 3);
SelectionSizeTooltip.tooltip.style.left = (left - box.left) + "px";
SelectionSizeTooltip.tooltip.style.bottom = (box.bottom - start.top) + "px";
}
}
}
destroy() { SelectionSizeTooltip.tooltip.style.display = "none" }
}
|