@textbus/collaborate 4.0.0-alpha.28 → 4.0.0-alpha.30

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.
@@ -1,5 +1,14 @@
1
- import { Module } from '@textbus/core';
1
+ import { Module, Textbus } from '@textbus/core';
2
2
  import { Provider } from '@viewfly/core';
3
+ import { UserInfo } from './user-activity';
4
+ export interface CollaborateConfig {
5
+ url: string;
6
+ roomName: string;
7
+ userinfo: UserInfo;
8
+ }
3
9
  export declare class CollaborateModule implements Module {
10
+ config: CollaborateConfig;
4
11
  providers: Provider[];
12
+ constructor(config: CollaborateConfig);
13
+ setup(textbus: Textbus): Promise<(() => void) | void> | (() => void) | void;
5
14
  }
@@ -1,7 +1,8 @@
1
1
  import { Injectable, Inject, Optional } from '@viewfly/core';
2
- import { Subject, map, filter } from '@tanbo/stream';
2
+ import { Subject, map, filter, Subscription } from '@tanbo/stream';
3
3
  import { makeError, HISTORY_STACK_SIZE, ChangeOrigin, createObjectProxy, createArrayProxy, Slot, RootComponentRef, Scheduler, Registry, Selection, History } from '@textbus/core';
4
4
  import { Doc, UndoManager, Map, Array as Array$1, Text, createAbsolutePositionFromRelativePosition, createRelativePositionFromTypeIndex } from 'yjs';
5
+ import { WebsocketProvider } from 'y-websocket';
5
6
 
6
7
  /******************************************************************************
7
8
  Copyright (c) Microsoft Corporation.
@@ -729,16 +730,82 @@ function remoteFormatsToLocal(registry, attrs) {
729
730
  return formats;
730
731
  }
731
732
 
733
+ let UserActivity = class UserActivity {
734
+ constructor(websocketProvider, selection) {
735
+ this.websocketProvider = websocketProvider;
736
+ this.selection = selection;
737
+ this.stateChangeEvent = new Subject();
738
+ this.userChangeEvent = new Subject();
739
+ this.subscription = new Subscription();
740
+ this.onStateChange = this.stateChangeEvent.asObservable();
741
+ this.onUserChange = this.userChangeEvent.asObservable();
742
+ }
743
+ init(userinfo) {
744
+ const provide = this.websocketProvider;
745
+ provide.awareness.setLocalStateField('user', userinfo);
746
+ this.subscription.add(this.selection.onChange.subscribe(() => {
747
+ const selection = this.selection.getPaths();
748
+ provide.awareness.setLocalStateField('selection', Object.assign(Object.assign({}, userinfo), { selection }));
749
+ }));
750
+ provide.awareness.on('update', () => {
751
+ const users = [];
752
+ const remoteSelections = [];
753
+ provide.awareness.getStates().forEach(state => {
754
+ if (state.user) {
755
+ users.push(state.user);
756
+ }
757
+ if (state.selection) {
758
+ remoteSelections.push(state.selection);
759
+ }
760
+ });
761
+ const selections = remoteSelections.filter(i => i.id !== userinfo.id);
762
+ this.userChangeEvent.next(users);
763
+ this.stateChangeEvent.next(selections);
764
+ });
765
+ }
766
+ destroy() {
767
+ this.subscription.unsubscribe();
768
+ }
769
+ };
770
+ UserActivity = __decorate([
771
+ Injectable(),
772
+ __metadata("design:paramtypes", [WebsocketProvider,
773
+ Selection])
774
+ ], UserActivity);
775
+
732
776
  class CollaborateModule {
733
- constructor() {
777
+ constructor(config) {
778
+ this.config = config;
734
779
  this.providers = [
735
780
  Collaborate,
781
+ UserActivity,
736
782
  {
737
783
  provide: History,
738
784
  useExisting: Collaborate
785
+ }, {
786
+ provide: WebsocketProvider,
787
+ useFactory: (collab) => {
788
+ return new WebsocketProvider(this.config.url, this.config.roomName, collab.yDoc);
789
+ },
790
+ deps: [Collaborate]
739
791
  }
740
792
  ];
741
793
  }
794
+ setup(textbus) {
795
+ const provide = textbus.get(WebsocketProvider);
796
+ const userActivity = textbus.get(UserActivity);
797
+ userActivity.init(this.config.userinfo);
798
+ return new Promise((resolve) => {
799
+ provide.on('sync', (is) => {
800
+ if (is) {
801
+ resolve(() => {
802
+ provide.disconnect();
803
+ userActivity.destroy();
804
+ });
805
+ }
806
+ });
807
+ });
808
+ }
742
809
  }
743
810
 
744
- export { Collaborate, CollaborateModule, CustomUndoManagerConfig };
811
+ export { Collaborate, CollaborateModule, CustomUndoManagerConfig, UserActivity };
package/bundles/index.js CHANGED
@@ -4,6 +4,7 @@ var core$1 = require('@viewfly/core');
4
4
  var stream = require('@tanbo/stream');
5
5
  var core = require('@textbus/core');
6
6
  var yjs = require('yjs');
7
+ var yWebsocket = require('y-websocket');
7
8
 
8
9
  /******************************************************************************
9
10
  Copyright (c) Microsoft Corporation.
@@ -731,16 +732,82 @@ function remoteFormatsToLocal(registry, attrs) {
731
732
  return formats;
732
733
  }
733
734
 
735
+ exports.UserActivity = class UserActivity {
736
+ constructor(websocketProvider, selection) {
737
+ this.websocketProvider = websocketProvider;
738
+ this.selection = selection;
739
+ this.stateChangeEvent = new stream.Subject();
740
+ this.userChangeEvent = new stream.Subject();
741
+ this.subscription = new stream.Subscription();
742
+ this.onStateChange = this.stateChangeEvent.asObservable();
743
+ this.onUserChange = this.userChangeEvent.asObservable();
744
+ }
745
+ init(userinfo) {
746
+ const provide = this.websocketProvider;
747
+ provide.awareness.setLocalStateField('user', userinfo);
748
+ this.subscription.add(this.selection.onChange.subscribe(() => {
749
+ const selection = this.selection.getPaths();
750
+ provide.awareness.setLocalStateField('selection', Object.assign(Object.assign({}, userinfo), { selection }));
751
+ }));
752
+ provide.awareness.on('update', () => {
753
+ const users = [];
754
+ const remoteSelections = [];
755
+ provide.awareness.getStates().forEach(state => {
756
+ if (state.user) {
757
+ users.push(state.user);
758
+ }
759
+ if (state.selection) {
760
+ remoteSelections.push(state.selection);
761
+ }
762
+ });
763
+ const selections = remoteSelections.filter(i => i.id !== userinfo.id);
764
+ this.userChangeEvent.next(users);
765
+ this.stateChangeEvent.next(selections);
766
+ });
767
+ }
768
+ destroy() {
769
+ this.subscription.unsubscribe();
770
+ }
771
+ };
772
+ exports.UserActivity = __decorate([
773
+ core$1.Injectable(),
774
+ __metadata("design:paramtypes", [yWebsocket.WebsocketProvider,
775
+ core.Selection])
776
+ ], exports.UserActivity);
777
+
734
778
  class CollaborateModule {
735
- constructor() {
779
+ constructor(config) {
780
+ this.config = config;
736
781
  this.providers = [
737
782
  exports.Collaborate,
783
+ exports.UserActivity,
738
784
  {
739
785
  provide: core.History,
740
786
  useExisting: exports.Collaborate
787
+ }, {
788
+ provide: yWebsocket.WebsocketProvider,
789
+ useFactory: (collab) => {
790
+ return new yWebsocket.WebsocketProvider(this.config.url, this.config.roomName, collab.yDoc);
791
+ },
792
+ deps: [exports.Collaborate]
741
793
  }
742
794
  ];
743
795
  }
796
+ setup(textbus) {
797
+ const provide = textbus.get(yWebsocket.WebsocketProvider);
798
+ const userActivity = textbus.get(exports.UserActivity);
799
+ userActivity.init(this.config.userinfo);
800
+ return new Promise((resolve) => {
801
+ provide.on('sync', (is) => {
802
+ if (is) {
803
+ resolve(() => {
804
+ provide.disconnect();
805
+ userActivity.destroy();
806
+ });
807
+ }
808
+ });
809
+ });
810
+ }
744
811
  }
745
812
 
746
813
  exports.CollaborateModule = CollaborateModule;
@@ -1,2 +1,3 @@
1
1
  export * from './collaborate';
2
2
  export * from './collaborate-module';
3
+ export * from './user-activity';
@@ -0,0 +1,23 @@
1
+ import { Observable } from '@tanbo/stream';
2
+ import { Selection, SelectionPaths } from '@textbus/core';
3
+ import { WebsocketProvider } from 'y-websocket';
4
+ export interface UserInfo {
5
+ username: string;
6
+ color: string;
7
+ id: string;
8
+ }
9
+ export interface ActivityInfo extends UserInfo {
10
+ selection: SelectionPaths;
11
+ }
12
+ export declare class UserActivity {
13
+ private websocketProvider;
14
+ private selection;
15
+ onStateChange: Observable<ActivityInfo[]>;
16
+ onUserChange: Observable<UserInfo[]>;
17
+ private stateChangeEvent;
18
+ private userChangeEvent;
19
+ private subscription;
20
+ constructor(websocketProvider: WebsocketProvider, selection: Selection);
21
+ init(userinfo: UserInfo): void;
22
+ destroy(): void;
23
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textbus/collaborate",
3
- "version": "4.0.0-alpha.28",
3
+ "version": "4.0.0-alpha.30",
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",
@@ -26,11 +26,11 @@
26
26
  ],
27
27
  "dependencies": {
28
28
  "@tanbo/stream": "^1.2.3",
29
- "@textbus/core": "^4.0.0-alpha.28",
29
+ "@textbus/core": "^4.0.0-alpha.30",
30
30
  "@viewfly/core": "^0.6.0",
31
31
  "reflect-metadata": "^0.1.13",
32
- "y-protocols": "^1.0.5",
33
- "yjs": "^13.6.7"
32
+ "y-websocket": "^1.4.3",
33
+ "yjs": "^13.6.14"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@rollup/plugin-commonjs": "^23.0.2",
@@ -50,5 +50,5 @@
50
50
  "bugs": {
51
51
  "url": "https://github.com/textbus/textbus.git/issues"
52
52
  },
53
- "gitHead": "afb457beb39742c7e00f78b71cd24e13443bae56"
53
+ "gitHead": "9b14d8cf2a2473f31a36b51ee3d988ddecf776fb"
54
54
  }