@textbus/collaborate 2.0.0-alpha.46 → 2.0.0-alpha.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,16 +6,13 @@ export interface RemoteSelection {
6
6
  paths: SelectionPaths;
7
7
  }
8
8
  export interface SelectionRect {
9
+ color: string;
10
+ username: string;
9
11
  x: number;
10
12
  y: number;
11
13
  width: number;
12
14
  height: number;
13
15
  }
14
- export interface SelectionInfo {
15
- color: string;
16
- username: string;
17
- rects: SelectionRect[];
18
- }
19
16
  export interface RemoteSelectionCursor {
20
17
  cursor: HTMLElement;
21
18
  anchor: HTMLElement;
@@ -11,7 +11,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
13
  import { Inject, Injectable } from '@tanbo/di';
14
- import { createElement, EDITABLE_DOCUMENT, EDITOR_CONTAINER, SelectionBridge } from '@textbus/browser';
14
+ import { createElement, EDITABLE_DOCUMENT, EDITOR_CONTAINER, getLayoutRectByRange, SelectionBridge } from '@textbus/browser';
15
15
  import { Selection } from '@textbus/core';
16
16
  import { Subject } from '@tanbo/stream';
17
17
  let CollaborateCursor = class CollaborateCursor {
@@ -74,7 +74,8 @@ let CollaborateCursor = class CollaborateCursor {
74
74
  width: '100%',
75
75
  height: '100%',
76
76
  pointerEvents: 'none',
77
- fontSize: '12px'
77
+ fontSize: '12px',
78
+ zIndex: 10
78
79
  }
79
80
  })
80
81
  });
@@ -86,11 +87,9 @@ let CollaborateCursor = class CollaborateCursor {
86
87
  });
87
88
  container.appendChild(this.canvas);
88
89
  container.appendChild(this.tooltips);
89
- this.onRectsChange.subscribe(info => {
90
- const color = info.color;
91
- const rects = info.rects;
90
+ this.onRectsChange.subscribe(rects => {
92
91
  for (const rect of rects) {
93
- this.context.fillStyle = color;
92
+ this.context.fillStyle = rect.color;
94
93
  this.context.beginPath();
95
94
  this.context.rect(rect.x, rect.y, rect.width, rect.height);
96
95
  this.context.fill();
@@ -126,54 +125,48 @@ let CollaborateCursor = class CollaborateCursor {
126
125
  for (let i = rects.length - 1; i >= 0; i--) {
127
126
  const rect = rects[i];
128
127
  selectionRects.push({
128
+ color: item.color,
129
+ username: item.username,
129
130
  x: rect.x,
130
131
  y: rect.y,
131
132
  width: rect.width,
132
133
  height: rect.height,
133
134
  });
134
135
  }
135
- if (rects.length === 0) {
136
- const rect = nativeRange.getBoundingClientRect();
137
- if (rect.x !== 0 || rect.y !== 0 || rect.width !== 0 || rect.height !== 0) {
138
- selectionRects.push({
139
- x: rect.x,
140
- y: rect.y,
141
- width: 1,
142
- height: rect.height,
143
- });
144
- }
145
- }
146
- const info = Object.assign(Object.assign({}, item), { rects: selectionRects });
147
- this.onRectsChange.next(info);
148
- users.push(info);
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,
144
+ y: cursorRect.y,
145
+ width: 2,
146
+ height: cursorRect.height
147
+ });
149
148
  }
150
149
  }
151
150
  });
152
151
  this.drawUserCursor(users);
153
152
  }
154
- drawUserCursor(users) {
155
- for (let i = 0; i < users.length; i++) {
156
- const user = users[i];
157
- const last = user.rects[user.rects.length - 1];
153
+ drawUserCursor(rects) {
154
+ for (let i = 0; i < rects.length; i++) {
155
+ const rect = rects[i];
158
156
  const { cursor, userTip, anchor } = this.getUserCursor(i);
159
- if (!last) {
160
- cursor.style.display = 'none';
161
- }
162
- else {
163
- Object.assign(cursor.style, {
164
- left: last.x + last.width + 'px',
165
- top: last.y + 'px',
166
- width: '2px',
167
- height: last.height + 'px',
168
- background: user.color,
169
- display: 'block'
170
- });
171
- anchor.style.background = user.color;
172
- userTip.innerText = user.username;
173
- userTip.style.background = user.color;
174
- }
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;
175
168
  }
176
- for (let i = users.length; i < this.tooltips.children.length; i++) {
169
+ for (let i = rects.length; i < this.tooltips.children.length; i++) {
177
170
  this.tooltips.removeChild(this.tooltips.children[i]);
178
171
  }
179
172
  }
@@ -216,12 +209,10 @@ let CollaborateCursor = class CollaborateCursor {
216
209
  children: [userTip],
217
210
  on: {
218
211
  mouseenter() {
219
- anchor.style.transform = 'scale(1.2)';
220
212
  userTip.style.display = 'block';
221
213
  },
222
214
  mouseleave() {
223
215
  userTip.style.display = 'none';
224
- anchor.style.transform = '';
225
216
  }
226
217
  }
227
218
  });
@@ -1 +1 @@
1
- {"version":3,"file":"collaborate-cursor.js","sourceRoot":"","sources":["../../src/collab/collaborate-cursor.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inject, Injectable } from '@tanbo/di'\nimport { createElement, EDITABLE_DOCUMENT, EDITOR_CONTAINER, SelectionBridge } from '@textbus/browser'\nimport { Selection, SelectionPaths } from '@textbus/core'\nimport { Subject } from '@tanbo/stream'\n\nexport interface RemoteSelection {\n color: string\n username: string\n paths: SelectionPaths\n}\n\nexport interface SelectionRect {\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface SelectionInfo {\n color: string\n username: string\n rects: SelectionRect[]\n}\n\nexport interface RemoteSelectionCursor {\n cursor: HTMLElement\n anchor: HTMLElement\n userTip: HTMLElement\n}\n\n@Injectable()\nexport class CollaborateCursor {\n private canvas = createElement('canvas', {\n styles: {\n position: 'absolute',\n opacity: 0.5,\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none'\n }\n }) as HTMLCanvasElement\n private context = this.canvas.getContext('2d')!\n private tooltips = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n fontSize: '12px'\n }\n })\n\n private onRectsChange = new Subject<SelectionInfo>()\n\n constructor(@Inject(EDITOR_CONTAINER) private container: HTMLElement,\n @Inject(EDITABLE_DOCUMENT) private document: Document,\n private nativeSelection: SelectionBridge,\n private selection: Selection) {\n container.appendChild(this.canvas)\n container.appendChild(this.tooltips)\n this.onRectsChange.subscribe(info => {\n const color = info.color\n const rects = info.rects\n for (const rect of rects) {\n this.context.fillStyle = color\n this.context.beginPath()\n this.context.rect(rect.x, rect.y, rect.width, rect.height)\n this.context.fill()\n this.context.closePath()\n }\n })\n }\n\n draw(paths: RemoteSelection[]) {\n this.canvas.width = this.container.offsetWidth\n this.canvas.height = this.container.offsetHeight\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)\n\n const users: SelectionInfo[] = []\n\n paths.filter(i => {\n return i.paths.start.length && i.paths.end.length\n }).forEach(item => {\n const startOffset = item.paths.start.pop()!\n const startSlot = this.selection.findSlotByPaths(item.paths.start)\n const endOffset = item.paths.end.pop()!\n const endSlot = this.selection.findSlotByPaths(item.paths.end)\n\n if (startSlot && endSlot) {\n const position = this.nativeSelection.getPositionByRange({\n startOffset,\n endOffset,\n startSlot,\n endSlot\n })\n if (position.start && position.end) {\n const nativeRange = this.document.createRange()\n nativeRange.setStart(position.start.node, position.start.offset)\n nativeRange.setEnd(position.end.node, position.end.offset)\n\n const rects = nativeRange.getClientRects()\n const selectionRects: SelectionRect[] = []\n for (let i = rects.length - 1; i >= 0; i--) {\n const rect = rects[i]\n selectionRects.push({\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n })\n }\n\n if (rects.length === 0) {\n const rect = nativeRange.getBoundingClientRect()\n if (rect.x !== 0 || rect.y !== 0 || rect.width !== 0 || rect.height !== 0) {\n selectionRects.push({\n x: rect.x,\n y: rect.y,\n width: 1,\n height: rect.height,\n })\n }\n }\n const info: SelectionInfo = {\n ...item,\n rects: selectionRects\n }\n this.onRectsChange.next(info)\n\n users.push(info)\n }\n }\n })\n this.drawUserCursor(users)\n }\n\n private drawUserCursor(users: SelectionInfo[]) {\n for (let i = 0; i < users.length; i++) {\n const user = users[i]\n const last = user.rects[user.rects.length - 1]\n\n const {cursor, userTip, anchor} = this.getUserCursor(i)\n if (!last) {\n cursor.style.display = 'none'\n } else {\n Object.assign(cursor.style, {\n left: last.x + last.width + 'px',\n top: last.y + 'px',\n width: '2px',\n height: last.height + 'px',\n background: user.color,\n display: 'block'\n })\n anchor.style.background = user.color\n userTip.innerText = user.username\n userTip.style.background = user.color\n }\n }\n\n for (let i = users.length; i < this.tooltips.children.length; i++) {\n this.tooltips.removeChild(this.tooltips.children[i])\n }\n }\n\n private getUserCursor(index: number): RemoteSelectionCursor {\n let child: HTMLElement = this.tooltips.children[index] as HTMLElement\n if (child) {\n const anchor = child.children[0] as HTMLElement\n return {\n cursor: child,\n anchor,\n userTip: anchor.children[0] as HTMLElement\n }\n }\n const userTip = createElement('span', {\n styles: {\n position: 'absolute',\n display: 'none',\n left: '50%',\n transform: 'translateX(-50%)',\n marginBottom: '2px',\n bottom: '100%',\n whiteSpace: 'nowrap',\n color: '#fff',\n boxShadow: '0 1px 2px rgba(0,0,0,.1)',\n borderRadius: '3px',\n padding: '3px 5px',\n pointerEvents: 'none',\n }\n })\n\n const anchor = createElement('span', {\n styles: {\n position: 'absolute',\n top: '-2px',\n left: '-2px',\n width: '6px',\n height: '6px',\n pointerEvents: 'auto',\n pointer: 'cursor',\n },\n children: [userTip],\n on: {\n mouseenter() {\n anchor.style.transform = 'scale(1.2)'\n userTip.style.display = 'block'\n },\n mouseleave() {\n userTip.style.display = 'none'\n anchor.style.transform = ''\n }\n }\n })\n child = createElement('span', {\n styles: {\n position: 'absolute',\n },\n children: [\n anchor\n ]\n })\n this.tooltips.append(child)\n return {\n cursor: child,\n anchor,\n userTip\n }\n }\n}\n"]}
1
+ {"version":3,"file":"collaborate-cursor.js","sourceRoot":"","sources":["../../src/collab/collaborate-cursor.ts"],"names":[],"mappings":"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","sourcesContent":["import { Inject, Injectable } from '@tanbo/di'\nimport {\n createElement,\n EDITABLE_DOCUMENT,\n EDITOR_CONTAINER,\n getLayoutRectByRange,\n SelectionBridge\n} from '@textbus/browser'\nimport { Selection, SelectionPaths } from '@textbus/core'\nimport { Subject } from '@tanbo/stream'\n\nexport interface RemoteSelection {\n color: string\n username: string\n paths: SelectionPaths\n}\n\nexport interface SelectionRect {\n color: string\n username: string\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface RemoteSelectionCursor {\n cursor: HTMLElement\n anchor: HTMLElement\n userTip: HTMLElement\n}\n\n@Injectable()\nexport class CollaborateCursor {\n private canvas = createElement('canvas', {\n styles: {\n position: 'absolute',\n opacity: 0.5,\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none'\n }\n }) as HTMLCanvasElement\n private context = this.canvas.getContext('2d')!\n private tooltips = createElement('div', {\n styles: {\n position: 'absolute',\n left: 0,\n top: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n fontSize: '12px',\n zIndex: 10\n }\n })\n\n private onRectsChange = new Subject<SelectionRect[]>()\n\n constructor(@Inject(EDITOR_CONTAINER) private container: HTMLElement,\n @Inject(EDITABLE_DOCUMENT) private document: Document,\n private nativeSelection: SelectionBridge,\n private selection: Selection) {\n container.appendChild(this.canvas)\n container.appendChild(this.tooltips)\n this.onRectsChange.subscribe(rects => {\n for (const rect of rects) {\n this.context.fillStyle = rect.color\n this.context.beginPath()\n this.context.rect(rect.x, rect.y, rect.width, rect.height)\n this.context.fill()\n this.context.closePath()\n }\n })\n }\n\n draw(paths: RemoteSelection[]) {\n this.canvas.width = this.container.offsetWidth\n this.canvas.height = this.container.offsetHeight\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)\n\n const users: SelectionRect[] = []\n\n paths.filter(i => {\n return i.paths.start.length && i.paths.end.length\n }).forEach(item => {\n const startOffset = item.paths.start.pop()!\n const startSlot = this.selection.findSlotByPaths(item.paths.start)\n const endOffset = item.paths.end.pop()!\n const endSlot = this.selection.findSlotByPaths(item.paths.end)\n\n if (startSlot && endSlot) {\n const position = this.nativeSelection.getPositionByRange({\n startOffset,\n endOffset,\n startSlot,\n endSlot\n })\n if (position.start && position.end) {\n const nativeRange = this.document.createRange()\n nativeRange.setStart(position.start.node, position.start.offset)\n nativeRange.setEnd(position.end.node, position.end.offset)\n\n const rects = nativeRange.getClientRects()\n const selectionRects: SelectionRect[] = []\n for (let i = rects.length - 1; i >= 0; i--) {\n const rect = rects[i]\n selectionRects.push({\n color: item.color,\n username: item.username,\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n })\n }\n this.onRectsChange.next(selectionRects)\n\n const cursorRange = nativeRange.cloneRange()\n cursorRange.collapse(!item.paths.focusEnd)\n\n const cursorRect = getLayoutRectByRange(cursorRange)\n\n users.push({\n username: item.username,\n color: item.color,\n x: cursorRect.x,\n y: cursorRect.y,\n width: 2,\n height: cursorRect.height\n })\n }\n }\n })\n this.drawUserCursor(users)\n }\n\n private drawUserCursor(rects: SelectionRect[]) {\n for (let i = 0; i < rects.length; i++) {\n const rect = rects[i]\n const {cursor, userTip, anchor} = this.getUserCursor(i)\n Object.assign(cursor.style, {\n left: rect.x + 'px',\n top: rect.y + 'px',\n width: rect.width + 'px',\n height: rect.height + 'px',\n background: rect.color,\n display: 'block'\n })\n anchor.style.background = rect.color\n userTip.innerText = rect.username\n userTip.style.background = rect.color\n }\n\n for (let i = rects.length; i < this.tooltips.children.length; i++) {\n this.tooltips.removeChild(this.tooltips.children[i])\n }\n }\n\n private getUserCursor(index: number): RemoteSelectionCursor {\n let child: HTMLElement = this.tooltips.children[index] as HTMLElement\n if (child) {\n const anchor = child.children[0] as HTMLElement\n return {\n cursor: child,\n anchor,\n userTip: anchor.children[0] as HTMLElement\n }\n }\n const userTip = createElement('span', {\n styles: {\n position: 'absolute',\n display: 'none',\n left: '50%',\n transform: 'translateX(-50%)',\n marginBottom: '2px',\n bottom: '100%',\n whiteSpace: 'nowrap',\n color: '#fff',\n boxShadow: '0 1px 2px rgba(0,0,0,.1)',\n borderRadius: '3px',\n padding: '3px 5px',\n pointerEvents: 'none',\n }\n })\n\n const anchor = createElement('span', {\n styles: {\n position: 'absolute',\n top: '-2px',\n left: '-2px',\n width: '6px',\n height: '6px',\n pointerEvents: 'auto',\n pointer: 'cursor',\n },\n children: [userTip],\n on: {\n mouseenter() {\n userTip.style.display = 'block'\n },\n mouseleave() {\n userTip.style.display = 'none'\n }\n }\n })\n child = createElement('span', {\n styles: {\n position: 'absolute',\n },\n children: [\n anchor\n ]\n })\n this.tooltips.append(child)\n return {\n cursor: child,\n anchor,\n userTip\n }\n }\n}\n"]}
@@ -1,9 +1,11 @@
1
- import { YEvent } from 'yjs';
2
- import { ComponentInstance, Registry, Translator } from '@textbus/core';
1
+ import { Doc as YDoc, YEvent } from 'yjs';
2
+ import { ComponentInstance, Registry, Selection, Translator } from '@textbus/core';
3
3
  export declare class RemoteToLocal {
4
+ private yDoc;
4
5
  private translator;
6
+ private selection;
5
7
  private registry;
6
- constructor(translator: Translator, registry: Registry);
8
+ constructor(yDoc: YDoc, translator: Translator, selection: Selection, registry: Registry);
7
9
  transform(events: YEvent[], rootComponent: ComponentInstance): void;
8
10
  private applySharedComponentToComponent;
9
11
  private applySharedSlotToSlot;
@@ -1,14 +1,26 @@
1
- import { YArrayEvent, YMapEvent, YTextEvent } from 'yjs';
1
+ import { YArrayEvent, YMapEvent, YTextEvent, } from 'yjs';
2
2
  import { makeError } from '@textbus/core';
3
3
  const collaborateErrorFn = makeError('Collaborate');
4
4
  export class RemoteToLocal {
5
- constructor(translator, registry) {
5
+ constructor(yDoc, translator, selection, registry) {
6
+ Object.defineProperty(this, "yDoc", {
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true,
10
+ value: yDoc
11
+ });
6
12
  Object.defineProperty(this, "translator", {
7
13
  enumerable: true,
8
14
  configurable: true,
9
15
  writable: true,
10
16
  value: translator
11
17
  });
18
+ Object.defineProperty(this, "selection", {
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true,
22
+ value: selection
23
+ });
12
24
  Object.defineProperty(this, "registry", {
13
25
  enumerable: true,
14
26
  configurable: true,
@@ -88,6 +100,7 @@ export class RemoteToLocal {
88
100
  }
89
101
  if (ev instanceof YTextEvent) {
90
102
  slot.retain(0);
103
+ let offset = 0;
91
104
  ev.delta.forEach(action => {
92
105
  if (Reflect.has(action, 'retain')) {
93
106
  if (action.attributes) {
@@ -102,15 +115,18 @@ export class RemoteToLocal {
102
115
  slot.insert(action.insert, action.attributes ? Object.keys(action.attributes).map(key => {
103
116
  return [this.registry.getFormatter(key), action.attributes[key]];
104
117
  }) : []);
118
+ offset += action.insert.length;
105
119
  }
106
120
  else {
107
121
  const component = this.createComponentBySharedComponent(action.insert);
108
122
  slot.insert(component);
123
+ offset += 1;
109
124
  }
110
125
  }
111
126
  else if (action.delete) {
112
127
  slot.retain(slot.index);
113
128
  slot.delete(action.delete);
129
+ offset -= action.delete;
114
130
  }
115
131
  else if (action.attributes) {
116
132
  slot.updateState(draft => {
@@ -118,6 +134,14 @@ export class RemoteToLocal {
118
134
  });
119
135
  }
120
136
  });
137
+ if (this.selection.isSelected) {
138
+ if (slot === this.selection.startSlot) {
139
+ this.selection.setStart(slot, this.selection.startOffset + offset);
140
+ }
141
+ if (slot === this.selection.endSlot) {
142
+ this.selection.setEnd(slot, this.selection.endOffset + offset);
143
+ }
144
+ }
121
145
  }
122
146
  else if (ev instanceof YMapEvent) {
123
147
  ev.keysChanged.forEach(key => {
@@ -1 +1 @@
1
- {"version":3,"file":"remote-to-local.js","sourceRoot":"","sources":["../../src/collab/remote-to-local.ts"],"names":[],"mappings":"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","sourcesContent":["import { Map as YMap, YArrayEvent, YEvent, YMapEvent, Text as YText, YTextEvent, Array as YArray } from 'yjs'\nimport { ComponentInstance, ComponentLiteral, makeError, Registry, Slot, Translator } from '@textbus/core'\n\ntype YPath = [number, string][]\nconst collaborateErrorFn = makeError('Collaborate')\n\nexport class RemoteToLocal {\n constructor(private translator: Translator,\n private registry: Registry) {\n }\n\n transform(events: YEvent[], rootComponent: ComponentInstance) {\n events.forEach(ev => {\n const path: YPath = []\n\n for (let i = 0; i < ev.path.length; i += 2) {\n path.push(ev.path.slice(i, i + 2) as [number, string])\n }\n\n const slot = rootComponent.slots.get(0)\n\n if (!slot) {\n throw collaborateErrorFn('cannot find child slot in root component!')\n }\n\n if (path.length) {\n const componentIndex = path.shift()![0] as number\n const component = slot.getContentAtIndex(componentIndex) as ComponentInstance\n this.applySharedComponentToComponent(ev, path, component)\n return\n }\n\n this.applySharedSlotToSlot(ev, path, slot)\n })\n }\n\n private applySharedComponentToComponent(ev: YEvent, path: YPath, component: ComponentInstance) {\n if (path.length) {\n const childPath = path.shift()!\n const slot = component.slots.get(childPath[0])!\n this.applySharedSlotToSlot(ev, path, slot)\n return\n }\n if (ev instanceof YMapEvent) {\n ev.keysChanged.forEach(key => {\n if (key === 'state') {\n const state = (ev.target as YMap<any>).get('state')\n component.updateState(draft => {\n Object.assign(draft, state)\n })\n }\n })\n } else if (ev instanceof YArrayEvent) {\n const slots = component.slots\n ev.delta.forEach(action => {\n if (Reflect.has(action, 'retain')) {\n slots.retain(action.retain!)\n } else if (action.insert) {\n (action.insert as Array<YMap<any>>).forEach(item => {\n slots.insert(this.createSlotBySharedSlot(item))\n })\n } else if (action.delete) {\n slots.retain(slots.index)\n slots.delete(action.delete)\n }\n })\n }\n }\n\n private applySharedSlotToSlot(ev: YEvent, path: YPath, slot: Slot) {\n if (path.length) {\n path.shift()\n const delta = (ev.target.parent as YText).toDelta()\n let componentIndex = 0\n for (let i = 0; i < delta.length; i++) {\n const action = delta[i]\n if (action.insert === ev.target) {\n break\n }\n componentIndex += typeof action.insert === 'string' ? action.insert.length : 1\n }\n const component = slot.getContentAtIndex(componentIndex) as ComponentInstance\n this.applySharedComponentToComponent(ev, path, component)\n return\n }\n\n if (ev instanceof YTextEvent) {\n slot.retain(0)\n ev.delta.forEach(action => {\n if (Reflect.has(action, 'retain')) {\n if (action.attributes) {\n slot.retain(action.retain!, Object.keys(action.attributes).map(key => {\n return [this.registry.getFormatter(key)!, action.attributes![key]]\n }))\n }\n slot.retain(action.retain!)\n } else if (action.insert) {\n if (typeof action.insert === 'string') {\n slot.insert(action.insert, action.attributes ? Object.keys(action.attributes).map(key => {\n return [this.registry.getFormatter(key)!, action.attributes![key]]\n }) : [])\n } else {\n const component = this.createComponentBySharedComponent(action.insert as YMap<any>)\n slot.insert(component)\n }\n } else if (action.delete) {\n slot.retain(slot.index)\n slot.delete(action.delete)\n } else if (action.attributes) {\n slot.updateState(draft => {\n Object.assign(draft, action.attributes)\n })\n }\n })\n } else if (ev instanceof YMapEvent) {\n ev.keysChanged.forEach(key => {\n if (key === 'state') {\n const state = (ev.target as YMap<any>).get('state')\n slot.updateState(draft => {\n Object.assign(draft, state)\n })\n }\n })\n }\n }\n\n private createComponentBySharedComponent(yMap: YMap<any>): ComponentInstance {\n const slots = yMap.get('slots') as YArray<YMap<any>>\n const componentLiteral: ComponentLiteral = {\n state: yMap.get('state'),\n name: yMap.get('name'),\n slots: slots.map(sharedSlot => {\n return this.createSlotBySharedSlot(sharedSlot).toJSON()\n })\n }\n return this.translator.createComponent(componentLiteral)!\n }\n\n private createSlotBySharedSlot(sharedSlot: YMap<any>): Slot {\n const content = sharedSlot.get('content') as YText\n const delta = content.toDelta()\n\n const slot = this.translator.createSlot({\n schema: sharedSlot.get('schema'),\n state: sharedSlot.get('state'),\n formats: {},\n content: []\n })\n\n for (const action of delta) {\n if (action.insert) {\n if (typeof action.insert === 'string') {\n slot.insert(action.insert, action.attributes ? Object.keys(action.attributes).map(key => {\n return [this.registry.getFormatter(key)!, action.attributes![key]]\n }) : [])\n } else {\n slot.insert(this.createComponentBySharedComponent(action.insert))\n }\n } else {\n throw collaborateErrorFn('Unexpected delta action.')\n }\n }\n return slot\n }\n}\n"]}
1
+ {"version":3,"file":"remote-to-local.js","sourceRoot":"","sources":["../../src/collab/remote-to-local.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Doc as YDoc,\n Map as YMap,\n YArrayEvent,\n YEvent,\n YMapEvent,\n Text as YText,\n YTextEvent,\n Array as YArray,\n} from 'yjs'\nimport { ComponentInstance, ComponentLiteral, makeError, Registry, Selection, Slot, Translator } from '@textbus/core'\n\ntype YPath = [number, string][]\nconst collaborateErrorFn = makeError('Collaborate')\n\nexport class RemoteToLocal {\n constructor(private yDoc: YDoc,\n private translator: Translator,\n private selection: Selection,\n private registry: Registry) {\n }\n\n transform(events: YEvent[], rootComponent: ComponentInstance) {\n events.forEach(ev => {\n const path: YPath = []\n\n for (let i = 0; i < ev.path.length; i += 2) {\n path.push(ev.path.slice(i, i + 2) as [number, string])\n }\n\n const slot = rootComponent.slots.get(0)\n\n if (!slot) {\n throw collaborateErrorFn('cannot find child slot in root component!')\n }\n\n if (path.length) {\n const componentIndex = path.shift()![0] as number\n const component = slot.getContentAtIndex(componentIndex) as ComponentInstance\n this.applySharedComponentToComponent(ev, path, component)\n return\n }\n\n this.applySharedSlotToSlot(ev, path, slot)\n })\n }\n\n private applySharedComponentToComponent(ev: YEvent, path: YPath, component: ComponentInstance) {\n if (path.length) {\n const childPath = path.shift()!\n const slot = component.slots.get(childPath[0])!\n this.applySharedSlotToSlot(ev, path, slot)\n return\n }\n if (ev instanceof YMapEvent) {\n ev.keysChanged.forEach(key => {\n if (key === 'state') {\n const state = (ev.target as YMap<any>).get('state')\n component.updateState(draft => {\n Object.assign(draft, state)\n })\n }\n })\n } else if (ev instanceof YArrayEvent) {\n const slots = component.slots\n ev.delta.forEach(action => {\n if (Reflect.has(action, 'retain')) {\n slots.retain(action.retain!)\n } else if (action.insert) {\n (action.insert as Array<YMap<any>>).forEach(item => {\n slots.insert(this.createSlotBySharedSlot(item))\n })\n } else if (action.delete) {\n slots.retain(slots.index)\n slots.delete(action.delete)\n }\n })\n }\n }\n\n private applySharedSlotToSlot(ev: YEvent, path: YPath, slot: Slot) {\n if (path.length) {\n path.shift()\n const delta = (ev.target.parent as YText).toDelta()\n let componentIndex = 0\n for (let i = 0; i < delta.length; i++) {\n const action = delta[i]\n if (action.insert === ev.target) {\n break\n }\n componentIndex += typeof action.insert === 'string' ? action.insert.length : 1\n }\n const component = slot.getContentAtIndex(componentIndex) as ComponentInstance\n this.applySharedComponentToComponent(ev, path, component)\n return\n }\n if (ev instanceof YTextEvent) {\n slot.retain(0)\n let offset = 0\n ev.delta.forEach(action => {\n if (Reflect.has(action, 'retain')) {\n if (action.attributes) {\n slot.retain(action.retain!, Object.keys(action.attributes).map(key => {\n return [this.registry.getFormatter(key)!, action.attributes![key]]\n }))\n }\n slot.retain(action.retain!)\n } else if (action.insert) {\n if (typeof action.insert === 'string') {\n slot.insert(action.insert, action.attributes ? Object.keys(action.attributes).map(key => {\n return [this.registry.getFormatter(key)!, action.attributes![key]]\n }) : [])\n offset += action.insert.length\n } else {\n const component = this.createComponentBySharedComponent(action.insert as YMap<any>)\n slot.insert(component)\n offset += 1\n }\n } else if (action.delete) {\n slot.retain(slot.index)\n slot.delete(action.delete)\n offset -= action.delete\n } else if (action.attributes) {\n slot.updateState(draft => {\n Object.assign(draft, action.attributes)\n })\n }\n })\n if (this.selection.isSelected) {\n if (slot === this.selection.startSlot) {\n this.selection.setStart(slot, this.selection.startOffset! + offset)\n }\n if (slot === this.selection.endSlot) {\n this.selection.setEnd(slot, this.selection.endOffset! + offset)\n }\n }\n } else if (ev instanceof YMapEvent) {\n ev.keysChanged.forEach(key => {\n if (key === 'state') {\n const state = (ev.target as YMap<any>).get('state')\n slot.updateState(draft => {\n Object.assign(draft, state)\n })\n }\n })\n }\n }\n\n private createComponentBySharedComponent(yMap: YMap<any>): ComponentInstance {\n const slots = yMap.get('slots') as YArray<YMap<any>>\n const componentLiteral: ComponentLiteral = {\n state: yMap.get('state'),\n name: yMap.get('name'),\n slots: slots.map(sharedSlot => {\n return this.createSlotBySharedSlot(sharedSlot).toJSON()\n })\n }\n return this.translator.createComponent(componentLiteral)!\n }\n\n private createSlotBySharedSlot(sharedSlot: YMap<any>): Slot {\n const content = sharedSlot.get('content') as YText\n const delta = content.toDelta()\n\n const slot = this.translator.createSlot({\n schema: sharedSlot.get('schema'),\n state: sharedSlot.get('state'),\n formats: {},\n content: []\n })\n\n for (const action of delta) {\n if (action.insert) {\n if (typeof action.insert === 'string') {\n slot.insert(action.insert, action.attributes ? Object.keys(action.attributes).map(key => {\n return [this.registry.getFormatter(key)!, action.attributes![key]]\n }) : [])\n } else {\n slot.insert(this.createComponentBySharedComponent(action.insert))\n }\n } else {\n throw collaborateErrorFn('Unexpected delta action.')\n }\n }\n return slot\n }\n}\n"]}
@@ -104,7 +104,7 @@ let Collaborate = class Collaborate {
104
104
  enumerable: true,
105
105
  configurable: true,
106
106
  writable: true,
107
- value: new RemoteToLocal(this.translator, this.registry)
107
+ value: new RemoteToLocal(this.yDoc, this.translator, this.selection, this.registry)
108
108
  });
109
109
  Object.defineProperty(this, "backEvent", {
110
110
  enumerable: true,
@@ -1 +1 @@
1
- {"version":3,"file":"collaborate.js","sourceRoot":"","sources":["../src/collaborate.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@tanbo/di'\nimport { debounceTime, filter, Observable, Subject, Subscription, tap } from '@tanbo/stream'\nimport {\n RootComponentRef,\n Starter,\n Operation,\n Translator,\n Registry,\n Selection,\n SelectionPaths,\n History, Renderer\n} from '@textbus/core'\nimport { Doc as YDoc, UndoManager } from 'yjs'\nimport { LocalToRemote } from './collab/local-to-remote'\nimport { RemoteToLocal } from './collab/remote-to-local'\nimport { CollaborateCursor, RemoteSelection } from './collab/_api'\n\n@Injectable()\nexport class Collaborate implements History {\n onSelectionChange: Observable<SelectionPaths>\n yDoc = new YDoc()\n onBack: Observable<void>\n onForward: Observable<void>\n onChange: Observable<any>\n onPush: Observable<void>\n\n get canBack() {\n return this.manager?.canUndo()\n }\n\n get canForward() {\n return this.manager?.canRedo()\n }\n\n private localToRemote = new LocalToRemote()\n private remoteToLocal = new RemoteToLocal(this.translator, this.registry)\n\n private backEvent = new Subject<void>()\n private forwardEvent = new Subject<void>()\n private changeEvent = new Subject<void>()\n private pushEvent = new Subject<void>()\n\n private manager!: UndoManager\n\n private subscriptions: Subscription[] = []\n private updateFromSelf = true\n\n private selectionChangeEvent = new Subject<SelectionPaths>()\n\n constructor(private rootComponentRef: RootComponentRef,\n private collaborateCursor: CollaborateCursor,\n private translator: Translator,\n private renderer: Renderer,\n private registry: Registry,\n private selection: Selection,\n private starter: Starter) {\n this.onSelectionChange = this.selectionChangeEvent.asObservable()\n this.onBack = this.backEvent.asObservable()\n this.onForward = this.forwardEvent.asObservable()\n this.onChange = this.changeEvent.asObservable()\n this.onPush = this.pushEvent.asObservable()\n }\n\n setup() {\n this.subscriptions.push(\n this.starter.onReady.subscribe(() => {\n this.listen2()\n }),\n this.selection.onChange.subscribe(() => {\n const paths = this.selection.getPaths()\n this.selectionChangeEvent.next(paths)\n })\n )\n }\n\n updateRemoteSelection(paths: RemoteSelection[]) {\n this.collaborateCursor.draw(paths)\n }\n\n listen() {\n //\n }\n\n back() {\n if (this.canBack) {\n this.manager.undo()\n }\n }\n\n forward() {\n if (this.canForward) {\n this.manager.redo()\n }\n }\n\n destroy() {\n this.subscriptions.forEach(i => i.unsubscribe())\n }\n\n private listen2() {\n const root = this.yDoc.getText('content')\n const rootComponent = this.rootComponentRef.component!\n this.manager = new UndoManager(root, {\n trackedOrigins: new Set<any>([this.yDoc])\n })\n root.observeDeep((events, transaction) => {\n if (transaction.origin === this.yDoc) {\n return\n }\n this.updateFromSelf = false\n\n this.remoteToLocal.transform(events, rootComponent)\n this.renderer.render()\n this.selection.restore()\n this.updateFromSelf = true\n })\n const operations: Operation[] = []\n this.subscriptions.push(\n this.rootComponentRef.component.changeMarker.onChange.pipe(\n filter(() => {\n return this.updateFromSelf\n }),\n tap(op => {\n operations.push(op)\n }),\n debounceTime(1)\n ).subscribe(() => {\n this.yDoc.transact(() => {\n operations.forEach(operation => {\n this.localToRemote.transform(operation, root)\n })\n operations.length = 0\n }, this.yDoc)\n this.renderer.render()\n this.selection.restore()\n })\n )\n }\n}\n"]}
1
+ {"version":3,"file":"collaborate.js","sourceRoot":"","sources":["../src/collaborate.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@tanbo/di'\nimport { debounceTime, filter, Observable, Subject, Subscription, tap } from '@tanbo/stream'\nimport {\n RootComponentRef,\n Starter,\n Operation,\n Translator,\n Registry,\n Selection,\n SelectionPaths,\n History, Renderer\n} from '@textbus/core'\nimport { Doc as YDoc, UndoManager } from 'yjs'\nimport { LocalToRemote } from './collab/local-to-remote'\nimport { RemoteToLocal } from './collab/remote-to-local'\nimport { CollaborateCursor, RemoteSelection } from './collab/_api'\n\n@Injectable()\nexport class Collaborate implements History {\n onSelectionChange: Observable<SelectionPaths>\n yDoc = new YDoc()\n onBack: Observable<void>\n onForward: Observable<void>\n onChange: Observable<any>\n onPush: Observable<void>\n\n get canBack() {\n return this.manager?.canUndo()\n }\n\n get canForward() {\n return this.manager?.canRedo()\n }\n\n private localToRemote = new LocalToRemote()\n private remoteToLocal = new RemoteToLocal(this.yDoc, this.translator, this.selection, this.registry)\n\n private backEvent = new Subject<void>()\n private forwardEvent = new Subject<void>()\n private changeEvent = new Subject<void>()\n private pushEvent = new Subject<void>()\n\n private manager!: UndoManager\n\n private subscriptions: Subscription[] = []\n private updateFromSelf = true\n\n private selectionChangeEvent = new Subject<SelectionPaths>()\n\n constructor(private rootComponentRef: RootComponentRef,\n private collaborateCursor: CollaborateCursor,\n private translator: Translator,\n private renderer: Renderer,\n private registry: Registry,\n private selection: Selection,\n private starter: Starter) {\n this.onSelectionChange = this.selectionChangeEvent.asObservable()\n this.onBack = this.backEvent.asObservable()\n this.onForward = this.forwardEvent.asObservable()\n this.onChange = this.changeEvent.asObservable()\n this.onPush = this.pushEvent.asObservable()\n }\n\n setup() {\n this.subscriptions.push(\n this.starter.onReady.subscribe(() => {\n this.listen2()\n }),\n this.selection.onChange.subscribe(() => {\n const paths = this.selection.getPaths()\n this.selectionChangeEvent.next(paths)\n })\n )\n }\n\n updateRemoteSelection(paths: RemoteSelection[]) {\n this.collaborateCursor.draw(paths)\n }\n\n listen() {\n //\n }\n\n back() {\n if (this.canBack) {\n this.manager.undo()\n }\n }\n\n forward() {\n if (this.canForward) {\n this.manager.redo()\n }\n }\n\n destroy() {\n this.subscriptions.forEach(i => i.unsubscribe())\n }\n\n private listen2() {\n const root = this.yDoc.getText('content')\n const rootComponent = this.rootComponentRef.component!\n this.manager = new UndoManager(root, {\n trackedOrigins: new Set<any>([this.yDoc])\n })\n root.observeDeep((events, transaction) => {\n if (transaction.origin === this.yDoc) {\n return\n }\n this.updateFromSelf = false\n\n this.remoteToLocal.transform(events, rootComponent)\n this.renderer.render()\n this.selection.restore()\n this.updateFromSelf = true\n })\n const operations: Operation[] = []\n this.subscriptions.push(\n this.rootComponentRef.component.changeMarker.onChange.pipe(\n filter(() => {\n return this.updateFromSelf\n }),\n tap(op => {\n operations.push(op)\n }),\n debounceTime(1)\n ).subscribe(() => {\n this.yDoc.transact(() => {\n operations.forEach(operation => {\n this.localToRemote.transform(operation, root)\n })\n operations.length = 0\n }, this.yDoc)\n this.renderer.render()\n this.selection.restore()\n })\n )\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textbus/collaborate",
3
- "version": "2.0.0-alpha.46",
3
+ "version": "2.0.0-alpha.49",
4
4
  "description": "Textbus is a rich text editor and framework that is highly customizable and extensible to achieve rich wysiwyg effects.",
5
5
  "main": "./bundles/public-api.js",
6
6
  "module": "./bundles/public-api.js",
@@ -27,8 +27,8 @@
27
27
  "dependencies": {
28
28
  "@tanbo/di": "^1.0.5",
29
29
  "@tanbo/stream": "^0.0.12",
30
- "@textbus/browser": "^2.0.0-alpha.44",
31
- "@textbus/core": "^2.0.0-alpha.44",
30
+ "@textbus/browser": "^2.0.0-alpha.49",
31
+ "@textbus/core": "^2.0.0-alpha.49",
32
32
  "reflect-metadata": "^0.1.13",
33
33
  "y-protocols": "^1.0.5",
34
34
  "yjs": "^13.5.27"
@@ -44,5 +44,5 @@
44
44
  "bugs": {
45
45
  "url": "https://github.com/textbus/textbus.git/issues"
46
46
  },
47
- "gitHead": "18e9f273a01b6567d2f3a0c2c9c74b0e6864efbb"
47
+ "gitHead": "d9380c6a3c90fb72af03b9e16db5edd9c5ea3714"
48
48
  }
@@ -1,5 +1,11 @@
1
1
  import { Inject, Injectable } from '@tanbo/di'
2
- import { createElement, EDITABLE_DOCUMENT, EDITOR_CONTAINER, SelectionBridge } from '@textbus/browser'
2
+ import {
3
+ createElement,
4
+ EDITABLE_DOCUMENT,
5
+ EDITOR_CONTAINER,
6
+ getLayoutRectByRange,
7
+ SelectionBridge
8
+ } from '@textbus/browser'
3
9
  import { Selection, SelectionPaths } from '@textbus/core'
4
10
  import { Subject } from '@tanbo/stream'
5
11
 
@@ -10,18 +16,14 @@ export interface RemoteSelection {
10
16
  }
11
17
 
12
18
  export interface SelectionRect {
19
+ color: string
20
+ username: string
13
21
  x: number
14
22
  y: number
15
23
  width: number
16
24
  height: number
17
25
  }
18
26
 
19
- export interface SelectionInfo {
20
- color: string
21
- username: string
22
- rects: SelectionRect[]
23
- }
24
-
25
27
  export interface RemoteSelectionCursor {
26
28
  cursor: HTMLElement
27
29
  anchor: HTMLElement
@@ -50,11 +52,12 @@ export class CollaborateCursor {
50
52
  width: '100%',
51
53
  height: '100%',
52
54
  pointerEvents: 'none',
53
- fontSize: '12px'
55
+ fontSize: '12px',
56
+ zIndex: 10
54
57
  }
55
58
  })
56
59
 
57
- private onRectsChange = new Subject<SelectionInfo>()
60
+ private onRectsChange = new Subject<SelectionRect[]>()
58
61
 
59
62
  constructor(@Inject(EDITOR_CONTAINER) private container: HTMLElement,
60
63
  @Inject(EDITABLE_DOCUMENT) private document: Document,
@@ -62,11 +65,9 @@ export class CollaborateCursor {
62
65
  private selection: Selection) {
63
66
  container.appendChild(this.canvas)
64
67
  container.appendChild(this.tooltips)
65
- this.onRectsChange.subscribe(info => {
66
- const color = info.color
67
- const rects = info.rects
68
+ this.onRectsChange.subscribe(rects => {
68
69
  for (const rect of rects) {
69
- this.context.fillStyle = color
70
+ this.context.fillStyle = rect.color
70
71
  this.context.beginPath()
71
72
  this.context.rect(rect.x, rect.y, rect.width, rect.height)
72
73
  this.context.fill()
@@ -80,7 +81,7 @@ export class CollaborateCursor {
80
81
  this.canvas.height = this.container.offsetHeight
81
82
  this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
82
83
 
83
- const users: SelectionInfo[] = []
84
+ const users: SelectionRect[] = []
84
85
 
85
86
  paths.filter(i => {
86
87
  return i.paths.start.length && i.paths.end.length
@@ -107,61 +108,53 @@ export class CollaborateCursor {
107
108
  for (let i = rects.length - 1; i >= 0; i--) {
108
109
  const rect = rects[i]
109
110
  selectionRects.push({
111
+ color: item.color,
112
+ username: item.username,
110
113
  x: rect.x,
111
114
  y: rect.y,
112
115
  width: rect.width,
113
116
  height: rect.height,
114
117
  })
115
118
  }
119
+ this.onRectsChange.next(selectionRects)
116
120
 
117
- if (rects.length === 0) {
118
- const rect = nativeRange.getBoundingClientRect()
119
- if (rect.x !== 0 || rect.y !== 0 || rect.width !== 0 || rect.height !== 0) {
120
- selectionRects.push({
121
- x: rect.x,
122
- y: rect.y,
123
- width: 1,
124
- height: rect.height,
125
- })
126
- }
127
- }
128
- const info: SelectionInfo = {
129
- ...item,
130
- rects: selectionRects
131
- }
132
- this.onRectsChange.next(info)
121
+ const cursorRange = nativeRange.cloneRange()
122
+ cursorRange.collapse(!item.paths.focusEnd)
123
+
124
+ const cursorRect = getLayoutRectByRange(cursorRange)
133
125
 
134
- users.push(info)
126
+ users.push({
127
+ username: item.username,
128
+ color: item.color,
129
+ x: cursorRect.x,
130
+ y: cursorRect.y,
131
+ width: 2,
132
+ height: cursorRect.height
133
+ })
135
134
  }
136
135
  }
137
136
  })
138
137
  this.drawUserCursor(users)
139
138
  }
140
139
 
141
- private drawUserCursor(users: SelectionInfo[]) {
142
- for (let i = 0; i < users.length; i++) {
143
- const user = users[i]
144
- const last = user.rects[user.rects.length - 1]
145
-
140
+ private drawUserCursor(rects: SelectionRect[]) {
141
+ for (let i = 0; i < rects.length; i++) {
142
+ const rect = rects[i]
146
143
  const {cursor, userTip, anchor} = this.getUserCursor(i)
147
- if (!last) {
148
- cursor.style.display = 'none'
149
- } else {
150
- Object.assign(cursor.style, {
151
- left: last.x + last.width + 'px',
152
- top: last.y + 'px',
153
- width: '2px',
154
- height: last.height + 'px',
155
- background: user.color,
156
- display: 'block'
157
- })
158
- anchor.style.background = user.color
159
- userTip.innerText = user.username
160
- userTip.style.background = user.color
161
- }
144
+ Object.assign(cursor.style, {
145
+ left: rect.x + 'px',
146
+ top: rect.y + 'px',
147
+ width: rect.width + 'px',
148
+ height: rect.height + 'px',
149
+ background: rect.color,
150
+ display: 'block'
151
+ })
152
+ anchor.style.background = rect.color
153
+ userTip.innerText = rect.username
154
+ userTip.style.background = rect.color
162
155
  }
163
156
 
164
- for (let i = users.length; i < this.tooltips.children.length; i++) {
157
+ for (let i = rects.length; i < this.tooltips.children.length; i++) {
165
158
  this.tooltips.removeChild(this.tooltips.children[i])
166
159
  }
167
160
  }
@@ -206,12 +199,10 @@ export class CollaborateCursor {
206
199
  children: [userTip],
207
200
  on: {
208
201
  mouseenter() {
209
- anchor.style.transform = 'scale(1.2)'
210
202
  userTip.style.display = 'block'
211
203
  },
212
204
  mouseleave() {
213
205
  userTip.style.display = 'none'
214
- anchor.style.transform = ''
215
206
  }
216
207
  }
217
208
  })
@@ -1,11 +1,22 @@
1
- import { Map as YMap, YArrayEvent, YEvent, YMapEvent, Text as YText, YTextEvent, Array as YArray } from 'yjs'
2
- import { ComponentInstance, ComponentLiteral, makeError, Registry, Slot, Translator } from '@textbus/core'
1
+ import {
2
+ Doc as YDoc,
3
+ Map as YMap,
4
+ YArrayEvent,
5
+ YEvent,
6
+ YMapEvent,
7
+ Text as YText,
8
+ YTextEvent,
9
+ Array as YArray,
10
+ } from 'yjs'
11
+ import { ComponentInstance, ComponentLiteral, makeError, Registry, Selection, Slot, Translator } from '@textbus/core'
3
12
 
4
13
  type YPath = [number, string][]
5
14
  const collaborateErrorFn = makeError('Collaborate')
6
15
 
7
16
  export class RemoteToLocal {
8
- constructor(private translator: Translator,
17
+ constructor(private yDoc: YDoc,
18
+ private translator: Translator,
19
+ private selection: Selection,
9
20
  private registry: Registry) {
10
21
  }
11
22
 
@@ -83,9 +94,9 @@ export class RemoteToLocal {
83
94
  this.applySharedComponentToComponent(ev, path, component)
84
95
  return
85
96
  }
86
-
87
97
  if (ev instanceof YTextEvent) {
88
98
  slot.retain(0)
99
+ let offset = 0
89
100
  ev.delta.forEach(action => {
90
101
  if (Reflect.has(action, 'retain')) {
91
102
  if (action.attributes) {
@@ -99,19 +110,30 @@ export class RemoteToLocal {
99
110
  slot.insert(action.insert, action.attributes ? Object.keys(action.attributes).map(key => {
100
111
  return [this.registry.getFormatter(key)!, action.attributes![key]]
101
112
  }) : [])
113
+ offset += action.insert.length
102
114
  } else {
103
115
  const component = this.createComponentBySharedComponent(action.insert as YMap<any>)
104
116
  slot.insert(component)
117
+ offset += 1
105
118
  }
106
119
  } else if (action.delete) {
107
120
  slot.retain(slot.index)
108
121
  slot.delete(action.delete)
122
+ offset -= action.delete
109
123
  } else if (action.attributes) {
110
124
  slot.updateState(draft => {
111
125
  Object.assign(draft, action.attributes)
112
126
  })
113
127
  }
114
128
  })
129
+ if (this.selection.isSelected) {
130
+ if (slot === this.selection.startSlot) {
131
+ this.selection.setStart(slot, this.selection.startOffset! + offset)
132
+ }
133
+ if (slot === this.selection.endSlot) {
134
+ this.selection.setEnd(slot, this.selection.endOffset! + offset)
135
+ }
136
+ }
115
137
  } else if (ev instanceof YMapEvent) {
116
138
  ev.keysChanged.forEach(key => {
117
139
  if (key === 'state') {
@@ -33,7 +33,7 @@ export class Collaborate implements History {
33
33
  }
34
34
 
35
35
  private localToRemote = new LocalToRemote()
36
- private remoteToLocal = new RemoteToLocal(this.translator, this.registry)
36
+ private remoteToLocal = new RemoteToLocal(this.yDoc, this.translator, this.selection, this.registry)
37
37
 
38
38
  private backEvent = new Subject<void>()
39
39
  private forwardEvent = new Subject<void>()