@textbus/collaborate 2.0.0-beta.3 → 2.0.0-beta.33

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,245 +0,0 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- var __param = (this && this.__param) || function (paramIndex, decorator) {
11
- return function (target, key) { decorator(target, key, paramIndex); }
12
- };
13
- import { Inject, Injectable } from '@tanbo/di';
14
- import { createElement, EDITABLE_DOCUMENT, EDITOR_CONTAINER, getLayoutRectByRange, SelectionBridge } from '@textbus/browser';
15
- import { Selection } from '@textbus/core';
16
- import { Subject } from '@tanbo/stream';
17
- let CollaborateCursor = class CollaborateCursor {
18
- constructor(container, document, nativeSelection, selection) {
19
- Object.defineProperty(this, "container", {
20
- enumerable: true,
21
- configurable: true,
22
- writable: true,
23
- value: container
24
- });
25
- Object.defineProperty(this, "document", {
26
- enumerable: true,
27
- configurable: true,
28
- writable: true,
29
- value: document
30
- });
31
- Object.defineProperty(this, "nativeSelection", {
32
- enumerable: true,
33
- configurable: true,
34
- writable: true,
35
- value: nativeSelection
36
- });
37
- Object.defineProperty(this, "selection", {
38
- enumerable: true,
39
- configurable: true,
40
- writable: true,
41
- value: selection
42
- });
43
- Object.defineProperty(this, "canvas", {
44
- enumerable: true,
45
- configurable: true,
46
- writable: true,
47
- value: createElement('canvas', {
48
- styles: {
49
- position: 'absolute',
50
- opacity: 0.5,
51
- left: 0,
52
- top: 0,
53
- width: '100%',
54
- height: '100%',
55
- pointerEvents: 'none'
56
- }
57
- })
58
- });
59
- Object.defineProperty(this, "context", {
60
- enumerable: true,
61
- configurable: true,
62
- writable: true,
63
- value: this.canvas.getContext('2d')
64
- });
65
- Object.defineProperty(this, "tooltips", {
66
- enumerable: true,
67
- configurable: true,
68
- writable: true,
69
- value: createElement('div', {
70
- styles: {
71
- position: 'absolute',
72
- left: 0,
73
- top: 0,
74
- width: '100%',
75
- height: '100%',
76
- pointerEvents: 'none',
77
- fontSize: '12px',
78
- zIndex: 10
79
- }
80
- })
81
- });
82
- Object.defineProperty(this, "onRectsChange", {
83
- enumerable: true,
84
- configurable: true,
85
- writable: true,
86
- value: new Subject()
87
- });
88
- container.prepend(this.canvas, this.tooltips);
89
- this.onRectsChange.subscribe(rects => {
90
- for (const rect of rects) {
91
- this.context.fillStyle = rect.color;
92
- this.context.beginPath();
93
- this.context.rect(rect.x, rect.y, rect.width, rect.height);
94
- this.context.fill();
95
- this.context.closePath();
96
- }
97
- });
98
- }
99
- draw(paths) {
100
- const containerRect = this.container.getBoundingClientRect();
101
- this.canvas.width = containerRect.width;
102
- this.canvas.height = containerRect.height;
103
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
104
- const users = [];
105
- paths.filter(i => {
106
- return i.paths.start.length && i.paths.end.length;
107
- }).forEach(item => {
108
- const startOffset = item.paths.start.pop();
109
- const startSlot = this.selection.findSlotByPaths(item.paths.start);
110
- const endOffset = item.paths.end.pop();
111
- const endSlot = this.selection.findSlotByPaths(item.paths.end);
112
- if (startSlot && endSlot) {
113
- const position = this.nativeSelection.getPositionByRange({
114
- startOffset,
115
- endOffset,
116
- startSlot,
117
- endSlot
118
- });
119
- if (position.start && position.end) {
120
- const nativeRange = this.document.createRange();
121
- nativeRange.setStart(position.start.node, position.start.offset);
122
- nativeRange.setEnd(position.end.node, position.end.offset);
123
- const rects = nativeRange.getClientRects();
124
- const selectionRects = [];
125
- for (let i = rects.length - 1; i >= 0; i--) {
126
- const rect = rects[i];
127
- selectionRects.push({
128
- color: item.color,
129
- username: item.username,
130
- x: rect.x - containerRect.x,
131
- y: rect.y - containerRect.y,
132
- width: rect.width,
133
- height: rect.height,
134
- });
135
- }
136
- this.onRectsChange.next(selectionRects);
137
- const cursorRange = nativeRange.cloneRange();
138
- cursorRange.collapse(!item.paths.focusEnd);
139
- const cursorRect = getLayoutRectByRange(cursorRange);
140
- users.push({
141
- username: item.username,
142
- color: item.color,
143
- x: cursorRect.x - containerRect.x,
144
- y: cursorRect.y - containerRect.y,
145
- width: 2,
146
- height: cursorRect.height
147
- });
148
- }
149
- }
150
- });
151
- this.drawUserCursor(users);
152
- }
153
- drawUserCursor(rects) {
154
- for (let i = 0; i < rects.length; i++) {
155
- const rect = rects[i];
156
- const { cursor, userTip, anchor } = this.getUserCursor(i);
157
- Object.assign(cursor.style, {
158
- left: rect.x + 'px',
159
- top: rect.y + 'px',
160
- width: rect.width + 'px',
161
- height: rect.height + 'px',
162
- background: rect.color,
163
- display: 'block'
164
- });
165
- anchor.style.background = rect.color;
166
- userTip.innerText = rect.username;
167
- userTip.style.background = rect.color;
168
- }
169
- for (let i = rects.length; i < this.tooltips.children.length; i++) {
170
- this.tooltips.removeChild(this.tooltips.children[i]);
171
- }
172
- }
173
- getUserCursor(index) {
174
- let child = this.tooltips.children[index];
175
- if (child) {
176
- const anchor = child.children[0];
177
- return {
178
- cursor: child,
179
- anchor,
180
- userTip: anchor.children[0]
181
- };
182
- }
183
- const userTip = createElement('span', {
184
- styles: {
185
- position: 'absolute',
186
- display: 'none',
187
- left: '50%',
188
- transform: 'translateX(-50%)',
189
- marginBottom: '2px',
190
- bottom: '100%',
191
- whiteSpace: 'nowrap',
192
- color: '#fff',
193
- boxShadow: '0 1px 2px rgba(0,0,0,.1)',
194
- borderRadius: '3px',
195
- padding: '3px 5px',
196
- pointerEvents: 'none',
197
- }
198
- });
199
- const anchor = createElement('span', {
200
- styles: {
201
- position: 'absolute',
202
- top: '-2px',
203
- left: '-2px',
204
- width: '6px',
205
- height: '6px',
206
- pointerEvents: 'auto',
207
- pointer: 'cursor',
208
- },
209
- children: [userTip],
210
- on: {
211
- mouseenter() {
212
- userTip.style.display = 'block';
213
- },
214
- mouseleave() {
215
- userTip.style.display = 'none';
216
- }
217
- }
218
- });
219
- child = createElement('span', {
220
- styles: {
221
- position: 'absolute',
222
- },
223
- children: [
224
- anchor
225
- ]
226
- });
227
- this.tooltips.append(child);
228
- return {
229
- cursor: child,
230
- anchor,
231
- userTip
232
- };
233
- }
234
- };
235
- CollaborateCursor = __decorate([
236
- Injectable(),
237
- __param(0, Inject(EDITOR_CONTAINER)),
238
- __param(1, Inject(EDITABLE_DOCUMENT)),
239
- __metadata("design:paramtypes", [HTMLElement,
240
- Document,
241
- SelectionBridge,
242
- Selection])
243
- ], CollaborateCursor);
244
- export { CollaborateCursor };
245
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGFib3JhdGUtY3Vyc29yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbGxhYi9jb2xsYWJvcmF0ZS1jdXJzb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDOUMsT0FBTyxFQUNMLGFBQWEsRUFDYixpQkFBaUIsRUFDakIsZ0JBQWdCLEVBQ2hCLG9CQUFvQixFQUNwQixlQUFlLEVBQ2hCLE1BQU0sa0JBQWtCLENBQUE7QUFDekIsT0FBTyxFQUFFLFNBQVMsRUFBa0IsTUFBTSxlQUFlLENBQUE7QUFDekQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQXdCdkMsSUFBYSxpQkFBaUIsR0FBOUIsTUFBYSxpQkFBaUI7SUE0QjVCLFlBQThDLFNBQXNCLEVBQ3JCLFFBQWtCLEVBQzdDLGVBQWdDLEVBQ2hDLFNBQW9COzs7OzttQkFITTs7Ozs7O21CQUNDOzs7Ozs7bUJBQzNCOzs7Ozs7bUJBQ0E7O1FBOUJwQjs7OzttQkFBaUIsYUFBYSxDQUFDLFFBQVEsRUFBRTtnQkFDdkMsTUFBTSxFQUFFO29CQUNOLFFBQVEsRUFBRSxVQUFVO29CQUNwQixPQUFPLEVBQUUsR0FBRztvQkFDWixJQUFJLEVBQUUsQ0FBQztvQkFDUCxHQUFHLEVBQUUsQ0FBQztvQkFDTixLQUFLLEVBQUUsTUFBTTtvQkFDYixNQUFNLEVBQUUsTUFBTTtvQkFDZCxhQUFhLEVBQUUsTUFBTTtpQkFDdEI7YUFDRixDQUFzQjtXQUFBO1FBQ3ZCOzs7O21CQUFrQixJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUU7V0FBQTtRQUMvQzs7OzttQkFBbUIsYUFBYSxDQUFDLEtBQUssRUFBRTtnQkFDdEMsTUFBTSxFQUFFO29CQUNOLFFBQVEsRUFBRSxVQUFVO29CQUNwQixJQUFJLEVBQUUsQ0FBQztvQkFDUCxH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dGFibGUgfSBmcm9tICdAdGFuYm8vZGknXG5pbXBvcnQge1xuICBjcmVhdGVFbGVtZW50LFxuICBFRElUQUJMRV9ET0NVTUVOVCxcbiAgRURJVE9SX0NPTlRBSU5FUixcbiAgZ2V0TGF5b3V0UmVjdEJ5UmFuZ2UsXG4gIFNlbGVjdGlvbkJyaWRnZVxufSBmcm9tICdAdGV4dGJ1cy9icm93c2VyJ1xuaW1wb3J0IHsgU2VsZWN0aW9uLCBTZWxlY3Rpb25QYXRocyB9IGZyb20gJ0B0ZXh0YnVzL2NvcmUnXG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAnQHRhbmJvL3N0cmVhbSdcblxuZXhwb3J0IGludGVyZmFjZSBSZW1vdGVTZWxlY3Rpb24ge1xuICBjb2xvcjogc3RyaW5nXG4gIHVzZXJuYW1lOiBzdHJpbmdcbiAgcGF0aHM6IFNlbGVjdGlvblBhdGhzXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VsZWN0aW9uUmVjdCB7XG4gIGNvbG9yOiBzdHJpbmdcbiAgdXNlcm5hbWU6IHN0cmluZ1xuICB4OiBudW1iZXJcbiAgeTogbnVtYmVyXG4gIHdpZHRoOiBudW1iZXJcbiAgaGVpZ2h0OiBudW1iZXJcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZW1vdGVTZWxlY3Rpb25DdXJzb3Ige1xuICBjdXJzb3I6IEhUTUxFbGVtZW50XG4gIGFuY2hvcjogSFRNTEVsZW1lbnRcbiAgdXNlclRpcDogSFRNTEVsZW1lbnRcbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIENvbGxhYm9yYXRlQ3Vyc29yIHtcbiAgcHJpdmF0ZSBjYW52YXMgPSBjcmVhdGVFbGVtZW50KCdjYW52YXMnLCB7XG4gICAgc3R5bGVzOiB7XG4gICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgIG9wYWNpdHk6IDAuNSxcbiAgICAgIGxlZnQ6IDAsXG4gICAgICB0b3A6IDAsXG4gICAgICB3aWR0aDogJzEwMCUnLFxuICAgICAgaGVpZ2h0OiAnMTAwJScsXG4gICAgICBwb2ludGVyRXZlbnRzOiAnbm9uZSdcbiAgICB9XG4gIH0pIGFzIEhUTUxDYW52YXNFbGVtZW50XG4gIHByaXZhdGUgY29udGV4dCA9IHRoaXMuY2FudmFzLmdldENvbnRleHQoJzJkJykhXG4gIHByaXZhdGUgdG9vbHRpcHMgPSBjcmVhdGVFbGVtZW50KCdkaXYnLCB7XG4gICAgc3R5bGVzOiB7XG4gICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgIGxlZnQ6IDAsXG4gICAgICB0b3A6IDAsXG4gICAgICB3aWR0aDogJzEwMCUnLFxuICAgICAgaGVpZ2h0OiAnMTAwJScsXG4gICAgICBwb2ludGVyRXZlbnRzOiAnbm9uZScsXG4gICAgICBmb250U2l6ZTogJzEycHgnLFxuICAgICAgekluZGV4OiAxMFxuICAgIH1cbiAgfSlcblxuICBwcml2YXRlIG9uUmVjdHNDaGFuZ2UgPSBuZXcgU3ViamVjdDxTZWxlY3Rpb25SZWN0W10+KClcblxuICBjb25zdHJ1Y3RvcihASW5qZWN0KEVESVRPUl9DT05UQUlORVIpIHByaXZhdGUgY29udGFpbmVyOiBIVE1MRWxlbWVudCxcbiAgICAgICAgICAgICAgQEluamVjdChFRElUQUJMRV9ET0NVTUVOVCkgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQsXG4gICAgICAgICAgICAgIHByaXZhdGUgbmF0aXZlU2VsZWN0aW9uOiBTZWxlY3Rpb25CcmlkZ2UsXG4gICAgICAgICAgICAgIHByaXZhdGUgc2VsZWN0aW9uOiBTZWxlY3Rpb24pIHtcbiAgICBjb250YWluZXIucHJlcGVuZCh0aGlzLmNhbnZhcywgdGhpcy50b29sdGlwcylcbiAgICB0aGlzLm9uUmVjdHNDaGFuZ2Uuc3Vic2NyaWJlKHJlY3RzID0+IHtcbiAgICAgIGZvciAoY29uc3QgcmVjdCBvZiByZWN0cykge1xuICAgICAgICB0aGlzLmNvbnRleHQuZmlsbFN0eWxlID0gcmVjdC5jb2xvclxuICAgICAgICB0aGlzLmNvbnRleHQuYmVnaW5QYXRoKClcbiAgICAgICAgdGhpcy5jb250ZXh0LnJlY3QocmVjdC54LCByZWN0LnksIHJlY3Qud2lkdGgsIHJlY3QuaGVpZ2h0KVxuICAgICAgICB0aGlzLmNvbnRleHQuZmlsbCgpXG4gICAgICAgIHRoaXMuY29udGV4dC5jbG9zZVBhdGgoKVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICBkcmF3KHBhdGhzOiBSZW1vdGVTZWxlY3Rpb25bXSkge1xuICAgIGNvbnN0IGNvbnRhaW5lclJlY3QgPSB0aGlzLmNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKVxuICAgIHRoaXMuY2FudmFzLndpZHRoID0gY29udGFpbmVyUmVjdC53aWR0aFxuICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IGNvbnRhaW5lclJlY3QuaGVpZ2h0XG4gICAgdGhpcy5jb250ZXh0LmNsZWFyUmVjdCgwLCAwLCB0aGlzLmNhbnZhcy53aWR0aCwgdGhpcy5jYW52YXMuaGVpZ2h0KVxuXG4gICAgY29uc3QgdXNlcnM6IFNlbGVjdGlvblJlY3RbXSA9IFtdXG5cblxuICAgIHBhdGhzLmZpbHRlcihpID0+IHtcbiAgICAgIHJldHVybiBpLnBhdGhzLnN0YXJ0Lmxlbmd0aCAmJiBpLnBhdGhzLmVuZC5sZW5ndGhcbiAgICB9KS5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgY29uc3Qgc3RhcnRPZmZzZXQgPSBpdGVtLnBhdGhzLnN0YXJ0LnBvcCgpIVxuICAgICAgY29uc3Qgc3RhcnRTbG90ID0gdGhpcy5zZWxlY3Rpb24uZmluZFNsb3RCeVBhdGhzKGl0ZW0ucGF0aHMuc3RhcnQpXG4gICAgICBjb25zdCBlbmRPZmZzZXQgPSBpdGVtLnBhdGhzLmVuZC5wb3AoKSFcbiAgICAgIGNvbnN0IGVuZFNsb3QgPSB0aGlzLnNlbGVjdGlvbi5maW5kU2xvdEJ5UGF0aHMoaXRlbS5wYXRocy5lbmQpXG5cbiAgICAgIGlmIChzdGFydFNsb3QgJiYgZW5kU2xvdCkge1xuICAgICAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMubmF0aXZlU2VsZWN0aW9uLmdldFBvc2l0aW9uQnlSYW5nZSh7XG4gICAgICAgICAgc3RhcnRPZmZzZXQsXG4gICAgICAgICAgZW5kT2Zmc2V0LFxuICAgICAgICAgIHN0YXJ0U2xvdCxcbiAgICAgICAgICBlbmRTbG90XG4gICAgICAgIH0pXG4gICAgICAgIGlmIChwb3NpdGlvbi5zdGFydCAmJiBwb3NpdGlvbi5lbmQpIHtcbiAgICAgICAgICBjb25zdCBuYXRpdmVSYW5nZSA9IHRoaXMuZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKVxuICAgICAgICAgIG5hdGl2ZVJhbmdlLnNldFN0YXJ0KHBvc2l0aW9uLnN0YXJ0Lm5vZGUsIHBvc2l0aW9uLnN0YXJ0Lm9mZnNldClcbiAgICAgICAgICBuYXRpdmVSYW5nZS5zZXRFbmQocG9zaXRpb24uZW5kLm5vZGUsIHBvc2l0aW9uLmVuZC5vZmZzZXQpXG5cbiAgICAgICAgICBjb25zdCByZWN0cyA9IG5hdGl2ZVJhbmdlLmdldENsaWVudFJlY3RzKClcbiAgICAgICAgICBjb25zdCBzZWxlY3Rpb25SZWN0czogU2VsZWN0aW9uUmVjdFtdID0gW11cbiAgICAgICAgICBmb3IgKGxldCBpID0gcmVjdHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGNvbnN0IHJlY3QgPSByZWN0c1tpXVxuICAgICAgICAgICAgc2VsZWN0aW9uUmVjdHMucHVzaCh7XG4gICAgICAgICAgICAgIGNvbG9yOiBpdGVtLmNvbG9yLFxuICAgICAgICAgICAgICB1c2VybmFtZTogaXRlbS51c2VybmFtZSxcbiAgICAgICAgICAgICAgeDogcmVjdC54IC0gY29udGFpbmVyUmVjdC54LFxuICAgICAgICAgICAgICB5OiByZWN0LnkgLSBjb250YWluZXJSZWN0LnksXG4gICAgICAgICAgICAgIHdpZHRoOiByZWN0LndpZHRoLFxuICAgICAgICAgICAgICBoZWlnaHQ6IHJlY3QuaGVpZ2h0LFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5vblJlY3RzQ2hhbmdlLm5leHQoc2VsZWN0aW9uUmVjdHMpXG5cbiAgICAgICAgICBjb25zdCBjdXJzb3JSYW5nZSA9IG5hdGl2ZVJhbmdlLmNsb25lUmFuZ2UoKVxuICAgICAgICAgIGN1cnNvclJhbmdlLmNvbGxhcHNlKCFpdGVtLnBhdGhzLmZvY3VzRW5kKVxuXG4gICAgICAgICAgY29uc3QgY3Vyc29yUmVjdCA9IGdldExheW91dFJlY3RCeVJhbmdlKGN1cnNvclJhbmdlKVxuXG4gICAgICAgICAgdXNlcnMucHVzaCh7XG4gICAgICAgICAgICB1c2VybmFtZTogaXRlbS51c2VybmFtZSxcbiAgICAgICAgICAgIGNvbG9yOiBpdGVtLmNvbG9yLFxuICAgICAgICAgICAgeDogY3Vyc29yUmVjdC54IC0gY29udGFpbmVyUmVjdC54LFxuICAgICAgICAgICAgeTogY3Vyc29yUmVjdC55IC0gY29udGFpbmVyUmVjdC55LFxuICAgICAgICAgICAgd2lkdGg6IDIsXG4gICAgICAgICAgICBoZWlnaHQ6IGN1cnNvclJlY3QuaGVpZ2h0XG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pXG4gICAgdGhpcy5kcmF3VXNlckN1cnNvcih1c2VycylcbiAgfVxuXG4gIHByaXZhdGUgZHJhd1VzZXJDdXJzb3IocmVjdHM6IFNlbGVjdGlvblJlY3RbXSkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVjdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHJlY3QgPSByZWN0c1tpXVxuICAgICAgY29uc3Qge2N1cnNvciwgdXNlclRpcCwgYW5jaG9yfSA9IHRoaXMuZ2V0VXNlckN1cnNvcihpKVxuICAgICAgT2JqZWN0LmFzc2lnbihjdXJzb3Iuc3R5bGUsIHtcbiAgICAgICAgbGVmdDogcmVjdC54ICsgJ3B4JyxcbiAgICAgICAgdG9wOiByZWN0LnkgKyAncHgnLFxuICAgICAgICB3aWR0aDogcmVjdC53aWR0aCArICdweCcsXG4gICAgICAgIGhlaWdodDogcmVjdC5oZWlnaHQgKyAncHgnLFxuICAgICAgICBiYWNrZ3JvdW5kOiByZWN0LmNvbG9yLFxuICAgICAgICBkaXNwbGF5OiAnYmxvY2snXG4gICAgICB9KVxuICAgICAgYW5jaG9yLnN0eWxlLmJhY2tncm91bmQgPSByZWN0LmNvbG9yXG4gICAgICB1c2VyVGlwLmlubmVyVGV4dCA9IHJlY3QudXNlcm5hbWVcbiAgICAgIHVzZXJUaXAuc3R5bGUuYmFja2dyb3VuZCA9IHJlY3QuY29sb3JcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gcmVjdHMubGVuZ3RoOyBpIDwgdGhpcy50b29sdGlwcy5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy50b29sdGlwcy5yZW1vdmVDaGlsZCh0aGlzLnRvb2x0aXBzLmNoaWxkcmVuW2ldKVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0VXNlckN1cnNvcihpbmRleDogbnVtYmVyKTogUmVtb3RlU2VsZWN0aW9uQ3Vyc29yIHtcbiAgICBsZXQgY2hpbGQ6IEhUTUxFbGVtZW50ID0gdGhpcy50b29sdGlwcy5jaGlsZHJlbltpbmRleF0gYXMgSFRNTEVsZW1lbnRcbiAgICBpZiAoY2hpbGQpIHtcbiAgICAgIGNvbnN0IGFuY2hvciA9IGNoaWxkLmNoaWxkcmVuWzBdIGFzIEhUTUxFbGVtZW50XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjdXJzb3I6IGNoaWxkLFxuICAgICAgICBhbmNob3IsXG4gICAgICAgIHVzZXJUaXA6IGFuY2hvci5jaGlsZHJlblswXSBhcyBIVE1MRWxlbWVudFxuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCB1c2VyVGlwID0gY3JlYXRlRWxlbWVudCgnc3BhbicsIHtcbiAgICAgIHN0eWxlczoge1xuICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgICAgZGlzcGxheTogJ25vbmUnLFxuICAgICAgICBsZWZ0OiAnNTAlJyxcbiAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlWCgtNTAlKScsXG4gICAgICAgIG1hcmdpbkJvdHRvbTogJzJweCcsXG4gICAgICAgIGJvdHRvbTogJzEwMCUnLFxuICAgICAgICB3aGl0ZVNwYWNlOiAnbm93cmFwJyxcbiAgICAgICAgY29sb3I6ICcjZmZmJyxcbiAgICAgICAgYm94U2hhZG93OiAnMCAxcHggMnB4IHJnYmEoMCwwLDAsLjEpJyxcbiAgICAgICAgYm9yZGVyUmFkaXVzOiAnM3B4JyxcbiAgICAgICAgcGFkZGluZzogJzNweCA1cHgnLFxuICAgICAgICBwb2ludGVyRXZlbnRzOiAnbm9uZScsXG4gICAgICB9XG4gICAgfSlcblxuICAgIGNvbnN0IGFuY2hvciA9IGNyZWF0ZUVsZW1lbnQoJ3NwYW4nLCB7XG4gICAgICBzdHlsZXM6IHtcbiAgICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgICAgIHRvcDogJy0ycHgnLFxuICAgICAgICBsZWZ0OiAnLTJweCcsXG4gICAgICAgIHdpZHRoOiAnNnB4JyxcbiAgICAgICAgaGVpZ2h0OiAnNnB4JyxcbiAgICAgICAgcG9pbnRlckV2ZW50czogJ2F1dG8nLFxuICAgICAgICBwb2ludGVyOiAnY3Vyc29yJyxcbiAgICAgIH0sXG4gICAgICBjaGlsZHJlbjogW3VzZXJUaXBdLFxuICAgICAgb246IHtcbiAgICAgICAgbW91c2VlbnRlcigpIHtcbiAgICAgICAgICB1c2VyVGlwLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snXG4gICAgICAgIH0sXG4gICAgICAgIG1vdXNlbGVhdmUoKSB7XG4gICAgICAgICAgdXNlclRpcC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KVxuICAgIGNoaWxkID0gY3JlYXRlRWxlbWVudCgnc3BhbicsIHtcbiAgICAgIHN0eWxlczoge1xuICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgIH0sXG4gICAgICBjaGlsZHJlbjogW1xuICAgICAgICBhbmNob3JcbiAgICAgIF1cbiAgICB9KVxuICAgIHRoaXMudG9vbHRpcHMuYXBwZW5kKGNoaWxkKVxuICAgIHJldHVybiB7XG4gICAgICBjdXJzb3I6IGNoaWxkLFxuICAgICAgYW5jaG9yLFxuICAgICAgdXNlclRpcFxuICAgIH1cbiAgfVxufVxuIl19
@@ -1 +0,0 @@
1
- export * from './collaborate-cursor'
@@ -1,225 +0,0 @@
1
- import { Inject, Injectable } from '@tanbo/di'
2
- import {
3
- createElement,
4
- EDITABLE_DOCUMENT,
5
- EDITOR_CONTAINER,
6
- getLayoutRectByRange,
7
- SelectionBridge
8
- } from '@textbus/browser'
9
- import { Selection, SelectionPaths } from '@textbus/core'
10
- import { Subject } from '@tanbo/stream'
11
-
12
- export interface RemoteSelection {
13
- color: string
14
- username: string
15
- paths: SelectionPaths
16
- }
17
-
18
- export interface SelectionRect {
19
- color: string
20
- username: string
21
- x: number
22
- y: number
23
- width: number
24
- height: number
25
- }
26
-
27
- export interface RemoteSelectionCursor {
28
- cursor: HTMLElement
29
- anchor: HTMLElement
30
- userTip: HTMLElement
31
- }
32
-
33
- @Injectable()
34
- export class CollaborateCursor {
35
- private canvas = createElement('canvas', {
36
- styles: {
37
- position: 'absolute',
38
- opacity: 0.5,
39
- left: 0,
40
- top: 0,
41
- width: '100%',
42
- height: '100%',
43
- pointerEvents: 'none'
44
- }
45
- }) as HTMLCanvasElement
46
- private context = this.canvas.getContext('2d')!
47
- private tooltips = createElement('div', {
48
- styles: {
49
- position: 'absolute',
50
- left: 0,
51
- top: 0,
52
- width: '100%',
53
- height: '100%',
54
- pointerEvents: 'none',
55
- fontSize: '12px',
56
- zIndex: 10
57
- }
58
- })
59
-
60
- private onRectsChange = new Subject<SelectionRect[]>()
61
-
62
- constructor(@Inject(EDITOR_CONTAINER) private container: HTMLElement,
63
- @Inject(EDITABLE_DOCUMENT) private document: Document,
64
- private nativeSelection: SelectionBridge,
65
- private selection: Selection) {
66
- container.prepend(this.canvas, this.tooltips)
67
- this.onRectsChange.subscribe(rects => {
68
- for (const rect of rects) {
69
- this.context.fillStyle = rect.color
70
- this.context.beginPath()
71
- this.context.rect(rect.x, rect.y, rect.width, rect.height)
72
- this.context.fill()
73
- this.context.closePath()
74
- }
75
- })
76
- }
77
-
78
- draw(paths: RemoteSelection[]) {
79
- const containerRect = this.container.getBoundingClientRect()
80
- this.canvas.width = containerRect.width
81
- this.canvas.height = containerRect.height
82
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
83
-
84
- const users: SelectionRect[] = []
85
-
86
-
87
- paths.filter(i => {
88
- return i.paths.start.length && i.paths.end.length
89
- }).forEach(item => {
90
- const startOffset = item.paths.start.pop()!
91
- const startSlot = this.selection.findSlotByPaths(item.paths.start)
92
- const endOffset = item.paths.end.pop()!
93
- const endSlot = this.selection.findSlotByPaths(item.paths.end)
94
-
95
- if (startSlot && endSlot) {
96
- const position = this.nativeSelection.getPositionByRange({
97
- startOffset,
98
- endOffset,
99
- startSlot,
100
- endSlot
101
- })
102
- if (position.start && position.end) {
103
- const nativeRange = this.document.createRange()
104
- nativeRange.setStart(position.start.node, position.start.offset)
105
- nativeRange.setEnd(position.end.node, position.end.offset)
106
-
107
- const rects = nativeRange.getClientRects()
108
- const selectionRects: SelectionRect[] = []
109
- for (let i = rects.length - 1; i >= 0; i--) {
110
- const rect = rects[i]
111
- selectionRects.push({
112
- color: item.color,
113
- username: item.username,
114
- x: rect.x - containerRect.x,
115
- y: rect.y - containerRect.y,
116
- width: rect.width,
117
- height: rect.height,
118
- })
119
- }
120
- this.onRectsChange.next(selectionRects)
121
-
122
- const cursorRange = nativeRange.cloneRange()
123
- cursorRange.collapse(!item.paths.focusEnd)
124
-
125
- const cursorRect = getLayoutRectByRange(cursorRange)
126
-
127
- users.push({
128
- username: item.username,
129
- color: item.color,
130
- x: cursorRect.x - containerRect.x,
131
- y: cursorRect.y - containerRect.y,
132
- width: 2,
133
- height: cursorRect.height
134
- })
135
- }
136
- }
137
- })
138
- this.drawUserCursor(users)
139
- }
140
-
141
- private drawUserCursor(rects: SelectionRect[]) {
142
- for (let i = 0; i < rects.length; i++) {
143
- const rect = rects[i]
144
- const {cursor, userTip, anchor} = this.getUserCursor(i)
145
- Object.assign(cursor.style, {
146
- left: rect.x + 'px',
147
- top: rect.y + 'px',
148
- width: rect.width + 'px',
149
- height: rect.height + 'px',
150
- background: rect.color,
151
- display: 'block'
152
- })
153
- anchor.style.background = rect.color
154
- userTip.innerText = rect.username
155
- userTip.style.background = rect.color
156
- }
157
-
158
- for (let i = rects.length; i < this.tooltips.children.length; i++) {
159
- this.tooltips.removeChild(this.tooltips.children[i])
160
- }
161
- }
162
-
163
- private getUserCursor(index: number): RemoteSelectionCursor {
164
- let child: HTMLElement = this.tooltips.children[index] as HTMLElement
165
- if (child) {
166
- const anchor = child.children[0] as HTMLElement
167
- return {
168
- cursor: child,
169
- anchor,
170
- userTip: anchor.children[0] as HTMLElement
171
- }
172
- }
173
- const userTip = createElement('span', {
174
- styles: {
175
- position: 'absolute',
176
- display: 'none',
177
- left: '50%',
178
- transform: 'translateX(-50%)',
179
- marginBottom: '2px',
180
- bottom: '100%',
181
- whiteSpace: 'nowrap',
182
- color: '#fff',
183
- boxShadow: '0 1px 2px rgba(0,0,0,.1)',
184
- borderRadius: '3px',
185
- padding: '3px 5px',
186
- pointerEvents: 'none',
187
- }
188
- })
189
-
190
- const anchor = createElement('span', {
191
- styles: {
192
- position: 'absolute',
193
- top: '-2px',
194
- left: '-2px',
195
- width: '6px',
196
- height: '6px',
197
- pointerEvents: 'auto',
198
- pointer: 'cursor',
199
- },
200
- children: [userTip],
201
- on: {
202
- mouseenter() {
203
- userTip.style.display = 'block'
204
- },
205
- mouseleave() {
206
- userTip.style.display = 'none'
207
- }
208
- }
209
- })
210
- child = createElement('span', {
211
- styles: {
212
- position: 'absolute',
213
- },
214
- children: [
215
- anchor
216
- ]
217
- })
218
- this.tooltips.append(child)
219
- return {
220
- cursor: child,
221
- anchor,
222
- userTip
223
- }
224
- }
225
- }