@textbus/collaborate 4.0.0 → 4.0.2
Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,6 @@
|
|
1
|
-
import { Observable } from '@tanbo/stream';
|
2
1
|
import { HocuspocusProviderConfiguration } from '@hocuspocus/provider';
|
3
2
|
import { SyncConnector } from '../sync-connector';
|
4
3
|
export declare class HocuspocusConnector extends SyncConnector {
|
5
|
-
onLoad: Observable<void>;
|
6
|
-
onStateChange: Observable<any>;
|
7
|
-
private loadEvent;
|
8
|
-
private stateChangeEvent;
|
9
4
|
private provide;
|
10
5
|
constructor(config: HocuspocusProviderConfiguration);
|
11
6
|
setLocalStateField(key: string, data: Record<string, any>): void;
|
@@ -1,12 +1,7 @@
|
|
1
1
|
import { Doc as YDoc } from 'yjs';
|
2
|
-
import { Observable } from '@tanbo/stream';
|
3
2
|
import { SyncConnector } from '../sync-connector';
|
4
3
|
export declare class YWebsocketConnector extends SyncConnector {
|
5
|
-
onLoad: Observable<void>;
|
6
|
-
onStateChange: Observable<any>;
|
7
4
|
private provide;
|
8
|
-
private loadEvent;
|
9
|
-
private stateChangeEvent;
|
10
5
|
constructor(url: string, roomName: string, yDoc: YDoc);
|
11
6
|
setLocalStateField(key: string, data: Record<string, any>): void;
|
12
7
|
onDestroy(): void;
|
package/bundles/index.esm.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import { Subject, map, filter, Subscription } from '@tanbo/stream';
|
2
1
|
import { HocuspocusProvider } from '@hocuspocus/provider';
|
2
|
+
import { Subject, map, filter, Subscription } from '@tanbo/stream';
|
3
3
|
import { WebsocketProvider } from 'y-websocket';
|
4
4
|
import { Injectable, Inject, Optional } from '@viewfly/core';
|
5
5
|
import { makeError, HISTORY_STACK_SIZE, ChangeOrigin, createObjectProxy, createArrayProxy, Slot, RootComponentRef, Scheduler, Registry, Selection, History } from '@textbus/core';
|
@@ -9,15 +9,17 @@ import { Doc, UndoManager, Map, Array as Array$1, Text, createAbsolutePositionFr
|
|
9
9
|
* 协作通信通用接口
|
10
10
|
*/
|
11
11
|
class SyncConnector {
|
12
|
+
constructor() {
|
13
|
+
this.loadEvent = new Subject();
|
14
|
+
this.stateChangeEvent = new Subject();
|
15
|
+
this.onLoad = this.loadEvent.asObservable();
|
16
|
+
this.onStateChange = this.stateChangeEvent.asObservable();
|
17
|
+
}
|
12
18
|
}
|
13
19
|
|
14
20
|
class HocuspocusConnector extends SyncConnector {
|
15
21
|
constructor(config) {
|
16
22
|
super();
|
17
|
-
this.loadEvent = new Subject();
|
18
|
-
this.stateChangeEvent = new Subject();
|
19
|
-
this.onLoad = this.loadEvent.asObservable();
|
20
|
-
this.onStateChange = this.stateChangeEvent.asObservable();
|
21
23
|
this.provide = new HocuspocusProvider(Object.assign(Object.assign({}, config), { onSynced: (data) => {
|
22
24
|
var _a;
|
23
25
|
(_a = config.onSynced) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
@@ -25,9 +27,13 @@ class HocuspocusConnector extends SyncConnector {
|
|
25
27
|
}, onAwarenessUpdate: (data) => {
|
26
28
|
var _a;
|
27
29
|
(_a = config.onAwarenessUpdate) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
28
|
-
data.states.
|
29
|
-
|
30
|
+
const states = data.states.map(state => {
|
31
|
+
return {
|
32
|
+
clientId: state.clientId,
|
33
|
+
state: Object.assign({}, state)
|
34
|
+
};
|
30
35
|
});
|
36
|
+
this.stateChangeEvent.next(states);
|
31
37
|
} }));
|
32
38
|
}
|
33
39
|
setLocalStateField(key, data) {
|
@@ -42,8 +48,6 @@ class HocuspocusConnector extends SyncConnector {
|
|
42
48
|
class YWebsocketConnector extends SyncConnector {
|
43
49
|
constructor(url, roomName, yDoc) {
|
44
50
|
super();
|
45
|
-
this.loadEvent = new Subject();
|
46
|
-
this.stateChangeEvent = new Subject();
|
47
51
|
this.onLoad = this.loadEvent.asObservable();
|
48
52
|
this.onStateChange = this.stateChangeEvent.asObservable();
|
49
53
|
this.provide = new WebsocketProvider(url, roomName, yDoc);
|
@@ -53,9 +57,14 @@ class YWebsocketConnector extends SyncConnector {
|
|
53
57
|
}
|
54
58
|
});
|
55
59
|
this.provide.awareness.on('update', () => {
|
56
|
-
|
57
|
-
|
60
|
+
const syncStates = [];
|
61
|
+
this.provide.awareness.getStates().forEach((state, id) => {
|
62
|
+
syncStates.push({
|
63
|
+
clientId: id,
|
64
|
+
state: state,
|
65
|
+
});
|
58
66
|
});
|
67
|
+
this.stateChangeEvent.next(syncStates);
|
59
68
|
});
|
60
69
|
}
|
61
70
|
setLocalStateField(key, data) {
|
@@ -619,7 +628,7 @@ let Collaborate = class Collaborate {
|
|
619
628
|
sharedSlot.removeAttribute(action.name);
|
620
629
|
}
|
621
630
|
}
|
622
|
-
});
|
631
|
+
}, true);
|
623
632
|
});
|
624
633
|
this.slotMap.set(localSlot, sharedSlot);
|
625
634
|
localSlot.__changeMarker__.destroyCallbacks.push(() => {
|
@@ -684,7 +693,7 @@ let Collaborate = class Collaborate {
|
|
684
693
|
break;
|
685
694
|
}
|
686
695
|
}
|
687
|
-
});
|
696
|
+
}, !localArray.__changeMarker__.irrevocableUpdate);
|
688
697
|
});
|
689
698
|
const syncRemote = (ev, tr) => {
|
690
699
|
this.runRemoteUpdate(tr, () => {
|
@@ -745,14 +754,14 @@ let Collaborate = class Collaborate {
|
|
745
754
|
break;
|
746
755
|
}
|
747
756
|
}
|
748
|
-
});
|
757
|
+
}, !localObject.__changeMarker__.irrevocableUpdate);
|
749
758
|
});
|
750
759
|
localObject.__changeMarker__.destroyCallbacks.push(function () {
|
751
760
|
sharedObject.unobserve(syncRemote);
|
752
761
|
sub.unsubscribe();
|
753
762
|
});
|
754
763
|
}
|
755
|
-
runLocalUpdate(fn, record
|
764
|
+
runLocalUpdate(fn, record) {
|
756
765
|
if (this.updateFromRemote) {
|
757
766
|
return;
|
758
767
|
}
|
@@ -813,15 +822,18 @@ let UserActivity = class UserActivity {
|
|
813
822
|
this.subscription.add(this.selection.onChange.subscribe(() => {
|
814
823
|
const selection = this.selection.getPaths();
|
815
824
|
this.syncConnector.setLocalStateField('selection', Object.assign(Object.assign({}, userinfo), { selection }));
|
816
|
-
}), this.syncConnector.onStateChange.subscribe((
|
825
|
+
}), this.syncConnector.onStateChange.subscribe((states) => {
|
817
826
|
const users = [];
|
818
827
|
const remoteSelections = [];
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
828
|
+
states.forEach(item => {
|
829
|
+
const state = item.state;
|
830
|
+
if (state.user) {
|
831
|
+
users.push(state.user);
|
832
|
+
}
|
833
|
+
if (state.selection) {
|
834
|
+
remoteSelections.push(state.selection);
|
835
|
+
}
|
836
|
+
});
|
825
837
|
const selections = remoteSelections.filter(i => i.id !== userinfo.id);
|
826
838
|
this.userChangeEvent.next(users);
|
827
839
|
this.stateChangeEvent.next(selections);
|
package/bundles/index.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
'use strict';
|
2
2
|
|
3
|
-
var stream = require('@tanbo/stream');
|
4
3
|
var provider = require('@hocuspocus/provider');
|
4
|
+
var stream = require('@tanbo/stream');
|
5
5
|
var yWebsocket = require('y-websocket');
|
6
6
|
var core$1 = require('@viewfly/core');
|
7
7
|
var core = require('@textbus/core');
|
@@ -11,15 +11,17 @@ var yjs = require('yjs');
|
|
11
11
|
* 协作通信通用接口
|
12
12
|
*/
|
13
13
|
class SyncConnector {
|
14
|
+
constructor() {
|
15
|
+
this.loadEvent = new stream.Subject();
|
16
|
+
this.stateChangeEvent = new stream.Subject();
|
17
|
+
this.onLoad = this.loadEvent.asObservable();
|
18
|
+
this.onStateChange = this.stateChangeEvent.asObservable();
|
19
|
+
}
|
14
20
|
}
|
15
21
|
|
16
22
|
class HocuspocusConnector extends SyncConnector {
|
17
23
|
constructor(config) {
|
18
24
|
super();
|
19
|
-
this.loadEvent = new stream.Subject();
|
20
|
-
this.stateChangeEvent = new stream.Subject();
|
21
|
-
this.onLoad = this.loadEvent.asObservable();
|
22
|
-
this.onStateChange = this.stateChangeEvent.asObservable();
|
23
25
|
this.provide = new provider.HocuspocusProvider(Object.assign(Object.assign({}, config), { onSynced: (data) => {
|
24
26
|
var _a;
|
25
27
|
(_a = config.onSynced) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
@@ -27,9 +29,13 @@ class HocuspocusConnector extends SyncConnector {
|
|
27
29
|
}, onAwarenessUpdate: (data) => {
|
28
30
|
var _a;
|
29
31
|
(_a = config.onAwarenessUpdate) === null || _a === void 0 ? void 0 : _a.call(config, data);
|
30
|
-
data.states.
|
31
|
-
|
32
|
+
const states = data.states.map(state => {
|
33
|
+
return {
|
34
|
+
clientId: state.clientId,
|
35
|
+
state: Object.assign({}, state)
|
36
|
+
};
|
32
37
|
});
|
38
|
+
this.stateChangeEvent.next(states);
|
33
39
|
} }));
|
34
40
|
}
|
35
41
|
setLocalStateField(key, data) {
|
@@ -44,8 +50,6 @@ class HocuspocusConnector extends SyncConnector {
|
|
44
50
|
class YWebsocketConnector extends SyncConnector {
|
45
51
|
constructor(url, roomName, yDoc) {
|
46
52
|
super();
|
47
|
-
this.loadEvent = new stream.Subject();
|
48
|
-
this.stateChangeEvent = new stream.Subject();
|
49
53
|
this.onLoad = this.loadEvent.asObservable();
|
50
54
|
this.onStateChange = this.stateChangeEvent.asObservable();
|
51
55
|
this.provide = new yWebsocket.WebsocketProvider(url, roomName, yDoc);
|
@@ -55,9 +59,14 @@ class YWebsocketConnector extends SyncConnector {
|
|
55
59
|
}
|
56
60
|
});
|
57
61
|
this.provide.awareness.on('update', () => {
|
58
|
-
|
59
|
-
|
62
|
+
const syncStates = [];
|
63
|
+
this.provide.awareness.getStates().forEach((state, id) => {
|
64
|
+
syncStates.push({
|
65
|
+
clientId: id,
|
66
|
+
state: state,
|
67
|
+
});
|
60
68
|
});
|
69
|
+
this.stateChangeEvent.next(syncStates);
|
61
70
|
});
|
62
71
|
}
|
63
72
|
setLocalStateField(key, data) {
|
@@ -621,7 +630,7 @@ exports.Collaborate = class Collaborate {
|
|
621
630
|
sharedSlot.removeAttribute(action.name);
|
622
631
|
}
|
623
632
|
}
|
624
|
-
});
|
633
|
+
}, true);
|
625
634
|
});
|
626
635
|
this.slotMap.set(localSlot, sharedSlot);
|
627
636
|
localSlot.__changeMarker__.destroyCallbacks.push(() => {
|
@@ -686,7 +695,7 @@ exports.Collaborate = class Collaborate {
|
|
686
695
|
break;
|
687
696
|
}
|
688
697
|
}
|
689
|
-
});
|
698
|
+
}, !localArray.__changeMarker__.irrevocableUpdate);
|
690
699
|
});
|
691
700
|
const syncRemote = (ev, tr) => {
|
692
701
|
this.runRemoteUpdate(tr, () => {
|
@@ -747,14 +756,14 @@ exports.Collaborate = class Collaborate {
|
|
747
756
|
break;
|
748
757
|
}
|
749
758
|
}
|
750
|
-
});
|
759
|
+
}, !localObject.__changeMarker__.irrevocableUpdate);
|
751
760
|
});
|
752
761
|
localObject.__changeMarker__.destroyCallbacks.push(function () {
|
753
762
|
sharedObject.unobserve(syncRemote);
|
754
763
|
sub.unsubscribe();
|
755
764
|
});
|
756
765
|
}
|
757
|
-
runLocalUpdate(fn, record
|
766
|
+
runLocalUpdate(fn, record) {
|
758
767
|
if (this.updateFromRemote) {
|
759
768
|
return;
|
760
769
|
}
|
@@ -815,15 +824,18 @@ exports.UserActivity = class UserActivity {
|
|
815
824
|
this.subscription.add(this.selection.onChange.subscribe(() => {
|
816
825
|
const selection = this.selection.getPaths();
|
817
826
|
this.syncConnector.setLocalStateField('selection', Object.assign(Object.assign({}, userinfo), { selection }));
|
818
|
-
}), this.syncConnector.onStateChange.subscribe((
|
827
|
+
}), this.syncConnector.onStateChange.subscribe((states) => {
|
819
828
|
const users = [];
|
820
829
|
const remoteSelections = [];
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
830
|
+
states.forEach(item => {
|
831
|
+
const state = item.state;
|
832
|
+
if (state.user) {
|
833
|
+
users.push(state.user);
|
834
|
+
}
|
835
|
+
if (state.selection) {
|
836
|
+
remoteSelections.push(state.selection);
|
837
|
+
}
|
838
|
+
});
|
827
839
|
const selections = remoteSelections.filter(i => i.id !== userinfo.id);
|
828
840
|
this.userChangeEvent.next(users);
|
829
841
|
this.stateChangeEvent.next(selections);
|
@@ -1,10 +1,31 @@
|
|
1
|
-
import { Observable } from '@tanbo/stream';
|
1
|
+
import { Observable, Subject } from '@tanbo/stream';
|
2
|
+
export interface SyncState {
|
3
|
+
clientId: number;
|
4
|
+
state: Record<string, any>;
|
5
|
+
}
|
2
6
|
/**
|
3
7
|
* 协作通信通用接口
|
4
8
|
*/
|
5
9
|
export declare abstract class SyncConnector {
|
6
|
-
|
7
|
-
|
10
|
+
/**
|
11
|
+
* 当文档加载完成时触发的观察者
|
12
|
+
*/
|
13
|
+
onLoad: Observable<void>;
|
14
|
+
/**
|
15
|
+
* 当文档 awareness 状态变更时触发的观察者
|
16
|
+
*/
|
17
|
+
onStateChange: Observable<SyncState[]>;
|
18
|
+
protected loadEvent: Subject<void>;
|
19
|
+
protected stateChangeEvent: Subject<SyncState[]>;
|
20
|
+
protected constructor();
|
21
|
+
/**
|
22
|
+
* 设置 awareness 状态
|
23
|
+
* @param key 状态的 key
|
24
|
+
* @param data 状态值
|
25
|
+
*/
|
8
26
|
abstract setLocalStateField(key: string, data: Record<string, any>): void;
|
27
|
+
/**
|
28
|
+
* 当文档销毁时调用
|
29
|
+
*/
|
9
30
|
abstract onDestroy(): void;
|
10
31
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@textbus/collaborate",
|
3
|
-
"version": "4.0.
|
3
|
+
"version": "4.0.2",
|
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/index.js",
|
6
6
|
"module": "./bundles/index.esm.js",
|
@@ -27,7 +27,7 @@
|
|
27
27
|
"dependencies": {
|
28
28
|
"@hocuspocus/provider": "^2.13.6",
|
29
29
|
"@tanbo/stream": "^1.2.5",
|
30
|
-
"@textbus/core": "^4.0.
|
30
|
+
"@textbus/core": "^4.0.1",
|
31
31
|
"@viewfly/core": "^1.0.0-alpha.22",
|
32
32
|
"y-websocket": "^1.4.3",
|
33
33
|
"yjs": "^13.6.14"
|
@@ -50,5 +50,5 @@
|
|
50
50
|
"bugs": {
|
51
51
|
"url": "https://github.com/textbus/textbus.git/issues"
|
52
52
|
},
|
53
|
-
"gitHead": "
|
53
|
+
"gitHead": "7ff0b269f64ca78bf19a243d61ea39cac898f671"
|
54
54
|
}
|