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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.29",
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.29",
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": "005a72f3cbc2c642fef5cdb584b690bbc8f8caf0"
54
54
  }