@netless/forge-imagery-doc 0.1.1 → 0.1.3

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,14 +1,14 @@
1
- import {AbstractApplication} from "@netless/forge-room";
2
- import {Whiteboard, WhiteboardApplication, WhiteboardPermissionFlag} from "@netless/forge-whiteboard";
3
- import * as Y from "yjs";
4
-
5
- import {ImageryDoc} from "./ImageryDoc";
6
- import {LazyImage} from "./LazyImage";
7
- import {Container} from "./Container";
8
- import {ImageryDocPermissionFlag, ImageryDocPermissions} from "./ImageryDocPermissions";
9
- import {FooterView} from "./FooterView";
10
- import {ContinuousContainer} from "./ContinuousContainer";
11
- import {SingleContainer} from "./SingleContainer";
1
+ import { AbstractApplication } from '@netless/forge-room';
2
+ import { Whiteboard, WhiteboardApplication, WhiteboardPermissionFlag } from '@netless/forge-whiteboard';
3
+ import * as Y from 'yjs';
4
+
5
+ import { ImageryDoc } from './ImageryDoc';
6
+ import { LazyImage } from './LazyImage';
7
+ import { Container } from './Container';
8
+ import { ImageryDocPermissionFlag, ImageryDocPermissions } from './ImageryDocPermissions';
9
+ import { FooterView } from './FooterView';
10
+ import { ContinuousContainer } from './ContinuousContainer';
11
+ import { SingleContainer } from './SingleContainer';
12
12
 
13
13
  export interface ImageryDocOption {
14
14
  images: {
@@ -20,206 +20,219 @@ export interface ImageryDocOption {
20
20
  * 从指定的白板 id 继承白板权限以及工具栏配置
21
21
  */
22
22
  inheritWhiteboardId?: string;
23
- displayMode: "continuous" | "single";
23
+ displayMode: 'continuous' | 'single';
24
24
  }
25
25
 
26
- export const IMAGERY_DOC_APP_NAME = "imagery_doc";
26
+ export const IMAGERY_DOC_APP_NAME = 'imagery_doc';
27
27
 
28
28
  /**
29
29
  * 需用户自行保证 ImageryDocApplication.view 的高宽比一致
30
30
  */
31
31
  export class ImageryDocApplication extends AbstractApplication<ImageryDocOption, ImageryDoc> {
32
32
 
33
- static applicationName = IMAGERY_DOC_APP_NAME;
34
-
35
- public readonly name: string = IMAGERY_DOC_APP_NAME;
36
-
37
- public emitter: ImageryDoc = new ImageryDoc();
38
-
39
- private whiteboardApp!: WhiteboardApplication;
40
- private whiteboard!: Whiteboard;
41
- private container!: Container;
42
- private rootView: HTMLDivElement = document.createElement("div");
43
- private contentContainer: HTMLDivElement = document.createElement("div");
44
- private whiteboardContainer: HTMLDivElement = document.createElement("div");
45
- private footerContainer: HTMLDivElement = document.createElement("div");
46
- private permissions!: ImageryDocPermissions;
47
- private footer: FooterView;
48
- private images: LazyImage[] = [];
49
-
50
- public constructor() {
51
- super();
52
- this.rootView.setAttribute("data-forge-app", "imagery-doc");
53
- this.rootView.style.background = "red";
54
- this.rootView.style.overflow = "hidden";
55
-
56
- this.contentContainer.style.width = "100%";
57
- this.contentContainer.style.height = "100%";
58
- this.contentContainer.style.display = "flex";
59
- this.contentContainer.style.flexDirection = "column";
60
-
61
- this.footer = new FooterView(this.emitter);
62
- this.rootView.appendChild(this.contentContainer);
63
-
64
- this.emitter.on("renderStart", pageIndex => {
65
- this.footer.prevPageState(pageIndex !== 0);
66
- this.footer.nextPageState(pageIndex !== this.images.length - 1);
67
- });
68
-
69
- const that = this;
70
- Object.defineProperty(this.emitter, "footView", {
71
- get(): HTMLDivElement {
72
- return that.footerContainer;
73
- }
74
- });
75
- Object.defineProperty(this.emitter, "view", {
76
- get(): any {
77
- return that.rootView;
78
- }
79
- });
80
- Object.defineProperty(this.emitter, "permissions", {
81
- get(): any {
82
- return that.permissions;
83
- }
84
- });
85
- Object.defineProperty(this.emitter, "pageIndex", {
86
- get(): any {
87
- return that.container.pageIndex;
88
- }
89
- });
90
- Object.defineProperty(this.emitter, "pageCount", {
91
- get(): any {
92
- return that.images.length;
93
- }
94
- });
95
- Object.defineProperty(this.emitter, "goto", {
96
- get(): any {
97
- return (index: number) => {
98
- if (that.permissions.hasPermission(ImageryDocPermissionFlag.switchPage)) {
99
- that.container.goto(index);
100
- }
101
- };
102
- }
103
- });
104
- Object.defineProperty(this.emitter, "imgContent", {
105
- get(): any {
106
- return (index: number) => {
107
- return that.images[index].getImgContent();
108
- };
109
- }
110
- });
111
- Object.defineProperty(this.emitter, "imgSize", {
112
- get(): any {
113
- return (index: number) => {
114
- return {
115
- width: that.images[index].width,
116
- height: that.images[index].height
117
- }
118
- };
119
- }
120
- });
33
+ static applicationName = IMAGERY_DOC_APP_NAME;
34
+
35
+ public readonly name: string = IMAGERY_DOC_APP_NAME;
36
+
37
+ public emitter: ImageryDoc = new ImageryDoc();
38
+
39
+ private whiteboardApp!: WhiteboardApplication;
40
+ private whiteboard!: Whiteboard;
41
+ private container!: Container;
42
+ private rootView: HTMLDivElement = document.createElement('div');
43
+ private contentContainer: HTMLDivElement = document.createElement('div');
44
+ private whiteboardContainer: HTMLDivElement = document.createElement('div');
45
+ private footerContainer: HTMLDivElement = document.createElement('div');
46
+ private permissions!: ImageryDocPermissions;
47
+ private footer: FooterView;
48
+ private images: LazyImage[] = [];
49
+
50
+ public constructor() {
51
+ super();
52
+ this.rootView.setAttribute('data-forge-app', 'imagery-doc');
53
+ this.rootView.style.background = 'red';
54
+ this.rootView.style.overflow = 'hidden';
55
+
56
+ this.contentContainer.style.width = '100%';
57
+ this.contentContainer.style.height = '100%';
58
+ this.contentContainer.style.display = 'flex';
59
+ this.contentContainer.style.flexDirection = 'column';
60
+
61
+ this.footer = new FooterView(this.emitter);
62
+ this.rootView.appendChild(this.contentContainer);
63
+
64
+ this.emitter.on('renderStart', pageIndex => {
65
+ this.footer.prevPageState(pageIndex !== 0);
66
+ this.footer.nextPageState(pageIndex !== this.images.length - 1);
67
+ });
68
+
69
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
70
+ const that = this;
71
+ Object.defineProperty(this.emitter, 'footView', {
72
+ get(): HTMLDivElement {
73
+ return that.footerContainer;
74
+ },
75
+ });
76
+ Object.defineProperty(this.emitter, 'view', {
77
+ get(): any {
78
+ return that.rootView;
79
+ },
80
+ });
81
+ Object.defineProperty(this.emitter, 'permissions', {
82
+ get(): any {
83
+ return that.permissions;
84
+ },
85
+ });
86
+ Object.defineProperty(this.emitter, 'pageIndex', {
87
+ get(): any {
88
+ return that.container.pageIndex;
89
+ },
90
+ });
91
+ Object.defineProperty(this.emitter, 'pageCount', {
92
+ get(): any {
93
+ return that.images.length;
94
+ },
95
+ });
96
+ Object.defineProperty(this.emitter, 'goto', {
97
+ get(): any {
98
+ return (index: number) => {
99
+ if (that.permissions.hasPermission(ImageryDocPermissionFlag.switchPage)) {
100
+ that.container.goto(index);
101
+ }
102
+ };
103
+ },
104
+ });
105
+ Object.defineProperty(this.emitter, 'imgContent', {
106
+ get(): any {
107
+ return (index: number) => {
108
+ return that.images[index].getImgContent();
109
+ };
110
+ },
111
+ });
112
+ Object.defineProperty(this.emitter, 'imgSize', {
113
+ get(): any {
114
+ return (index: number) => {
115
+ return {
116
+ width: that.images[index].width,
117
+ height: that.images[index].height,
118
+ };
119
+ };
120
+ },
121
+ });
122
+ }
123
+
124
+ public async initialize(option: ImageryDocOption): Promise<void> {
125
+ const whiteboardApp = new WhiteboardApplication();
126
+ // @ts-ignore
127
+ whiteboardApp.roomDoc = this.roomDoc;
128
+ // @ts-ignore
129
+ whiteboardApp.appId = `${this.appId}_wb`;
130
+ // @ts-ignore
131
+ whiteboardApp.userId = this.userId;
132
+ // @ts-ignore
133
+ whiteboardApp.userManager = this.userManager;
134
+ // @ts-ignore
135
+ whiteboardApp.applicationManager = this.applicationManager;
136
+ await whiteboardApp.initialize({
137
+ width: -1,
138
+ height: -1,
139
+ });
140
+ this.whiteboardApp = whiteboardApp;
141
+ this.whiteboard = whiteboardApp.emitter;
142
+ this.whiteboard.enableCameraByMouse = false;
143
+ this.whiteboard.enableCameraByTouch = false;
144
+ this.whiteboard.view.style.width = '100%';
145
+ this.whiteboard.view.style.height = '100%';
146
+ this.whiteboard.view.style.position = 'absolute';
147
+ this.whiteboard.view.style.top = '0';
148
+ this.whiteboard.view.style.left = '0';
149
+ this.whiteboard.setCanvasBackgroundColor('#f0f0f000');
150
+
151
+ if (option.displayMode === 'single') {
152
+ this.container = new SingleContainer(
153
+ this.getMap('single-container'),
154
+ whiteboardApp,
155
+ this.whiteboardContainer,
156
+ this.emitter,
157
+ );
158
+ } else {
159
+ this.container = new ContinuousContainer(
160
+ this.getMap('continuous-container'),
161
+ whiteboardApp,
162
+ this.whiteboardContainer,
163
+ this.emitter,
164
+ );
121
165
  }
122
166
 
123
- public async initialize(option: ImageryDocOption): Promise<void> {
124
- const whiteboardApp = new WhiteboardApplication();
125
- // @ts-ignore
126
- whiteboardApp.roomDoc = this.roomDoc;
127
- // @ts-ignore
128
- whiteboardApp.appId = `${this.appId}_wb`;
129
- // @ts-ignore
130
- whiteboardApp.userId = this.userId;
131
- // @ts-ignore
132
- whiteboardApp.userManager = this.userManager;
133
- // @ts-ignore
134
- whiteboardApp.applicationManager = this.applicationManager;
135
- await whiteboardApp.initialize({
136
- width: -1,
137
- height: -1
138
- });
139
- this.whiteboardApp = whiteboardApp;
140
- this.whiteboard = whiteboardApp.emitter;
141
- this.whiteboard.enableCameraByMouse = false;
142
- this.whiteboard.enableCameraByTouch = false;
143
- this.whiteboard.view.style.width = "100%";
144
- this.whiteboard.view.style.height = "100%";
145
- this.whiteboard.view.style.position = "absolute";
146
- this.whiteboard.view.style.top = "0";
147
- this.whiteboard.view.style.left = "0";
148
- this.whiteboard.setCanvasBackgroundColor("#f0f0f000");
149
-
150
- if (option.displayMode === "single") {
151
- this.container = new SingleContainer(
152
- this.getMap("single-container"),
153
- whiteboardApp,
154
- this.whiteboardContainer,
155
- this.emitter,
156
- );
157
- } else {
158
- this.container = new ContinuousContainer(
159
- this.getMap("continuous-container"),
160
- whiteboardApp,
161
- this.whiteboardContainer,
162
- this.emitter,
163
- );
164
- }
165
-
166
- this.whiteboardContainer.style.position = "relative";
167
- this.whiteboardContainer.style.flex = "1 1 auto";
168
- this.whiteboardContainer.style.overflow = "hidden";
169
- this.whiteboardContainer.appendChild(this.container.view);
170
- this.whiteboardContainer.appendChild(this.whiteboard.view);
171
-
172
- this.contentContainer.appendChild(this.whiteboardContainer);
173
- this.contentContainer.appendChild(this.footerContainer);
174
- this.footerContainer.appendChild(this.footer.root);
175
-
176
- this.whiteboard.setViewModeToMain();
177
-
178
- let i = 0;
179
- this.whiteboard.permissions.addPermission(WhiteboardPermissionFlag.mainView);
180
- while (i < option.images.length) {
181
- const image = option.images[i];
182
- this.images[i] = new LazyImage(image.src, image.width, image.height);
183
- this.container.append(this.images[i]);
184
- if (option.displayMode === "single") {
185
- this.whiteboard.addPage(`doc_${i}`);
186
- }
187
- i += 1;
188
- }
189
- if (option.displayMode === "continuous") {
190
- this.whiteboard.addPage("doc_continuous");
191
- this.whiteboard.gotoPage("doc_continuous");
192
- }
193
-
194
- if (option.displayMode === "single") {
195
- this.whiteboard.setViewModeToMain();
196
- } else {
197
- this.whiteboard.setViewModeToFree();
198
- }
199
-
200
- this.permissions = new ImageryDocPermissions(this.userManager, (userId: string) => {
201
- return this.userMap(userId);
202
- });
203
- this.permissions.addPermission(ImageryDocPermissionFlag.all);
204
- this.whiteboardApp.disableViewModel();
205
- this.container.init();
206
-
207
- this.whiteboard.permissions.removePermission(WhiteboardPermissionFlag.mainView);
208
- if (option.inheritWhiteboardId) {
209
- whiteboardApp.linkToWhiteboard(option.inheritWhiteboardId);
210
- }
211
-
212
- return Promise.resolve(undefined);
167
+ this.whiteboardContainer.style.position = 'relative';
168
+ this.whiteboardContainer.style.flex = '1 1 auto';
169
+ this.whiteboardContainer.style.overflow = 'hidden';
170
+ this.whiteboardContainer.appendChild(this.container.view);
171
+ this.whiteboardContainer.appendChild(this.whiteboard.view);
172
+
173
+ this.contentContainer.appendChild(this.whiteboardContainer);
174
+ this.contentContainer.appendChild(this.footerContainer);
175
+ this.footerContainer.appendChild(this.footer.root);
176
+
177
+ let i = 0;
178
+ this.whiteboard.permissions.addPermission(WhiteboardPermissionFlag.mainView);
179
+ this.whiteboard.setViewModeToMain();
180
+ while (i < option.images.length) {
181
+ const image = option.images[i];
182
+ this.images[i] = new LazyImage(image.src, image.width, image.height);
183
+ this.container.append(this.images[i]);
184
+ if (option.displayMode === 'single') {
185
+ this.whiteboard.addPage(`doc_${i}`);
186
+ }
187
+ i += 1;
213
188
  }
214
-
215
- private userMap(userId: string): Y.Map<any> {
216
- return this.getMap(`user/${userId}`);
189
+ if (option.displayMode === 'continuous') {
190
+ this.whiteboard.addPage('doc_continuous');
191
+ this.whiteboard.gotoPage('doc_continuous');
217
192
  }
218
193
 
219
- public async dispose(): Promise<void> {
220
- await this.whiteboardApp.dispose();
221
- this.rootView.parentElement?.removeChild(this.rootView);
222
- this.container.dispose();
223
- return Promise.resolve(undefined);
194
+ this.whiteboard.setViewModeToFree();
195
+
196
+ this.permissions = new ImageryDocPermissions(this.userManager, (userId: string) => {
197
+ return this.userMap(userId);
198
+ });
199
+ this.permissions.on('change', (userId: string, flags: ImageryDocPermissionFlag[], value: number) => {
200
+ this.emitter.emit('permissionChange', userId, flags, value);
201
+ });
202
+
203
+ this.permissions.addPermission(ImageryDocPermissionFlag.all);
204
+ this.whiteboardApp.disableViewModel();
205
+ this.container.init();
206
+
207
+ this.whiteboard.permissions.removePermission(WhiteboardPermissionFlag.mainView);
208
+ if (option.inheritWhiteboardId) {
209
+ whiteboardApp.linkToWhiteboard(option.inheritWhiteboardId);
224
210
  }
211
+
212
+ return Promise.resolve(undefined);
213
+ }
214
+
215
+ private userMap(userId: string): Y.Map<any> {
216
+ return this.getMap(`user/${userId}`);
217
+ }
218
+
219
+ public async dispose(): Promise<void> {
220
+ await this.whiteboardApp.dispose();
221
+ this.rootView.parentElement?.removeChild(this.rootView);
222
+ this.container.dispose();
223
+ this.permissions.dispose();
224
+ Object.defineProperty(this.emitter, 'footView', { value: null });
225
+ Object.defineProperty(this.emitter, 'view', { value: null });
226
+ Object.defineProperty(this.emitter, 'permissions', { value: null });
227
+ Object.defineProperty(this.emitter, 'pageIndex', { value: null });
228
+ Object.defineProperty(this.emitter, 'pageCount', { value: null });
229
+ Object.defineProperty(this.emitter, 'goto', { value: null });
230
+ Object.defineProperty(this.emitter, 'imgContent', { value: null });
231
+ Object.defineProperty(this.emitter, 'imgSize', { value: null });
232
+ this.emitter.removeAllListeners();
233
+ return Promise.resolve(undefined);
234
+ }
225
235
  }
236
+
237
+ // @ts-ignore
238
+ window.__ImageryDocApplication = ImageryDocApplication;
@@ -1,6 +1,6 @@
1
- import { type RoomUser, type UserManager } from "@netless/forge-room";
2
- import EventEmitter from "eventemitter3";
3
- import * as Y from "yjs";
1
+ import { type RoomUser, type UserManager } from '@netless/forge-room';
2
+ import EventEmitter from 'eventemitter3';
3
+ import * as Y from 'yjs';
4
4
 
5
5
  export enum ImageryDocPermissionFlag {
6
6
  /**
@@ -39,121 +39,131 @@ export interface ImageryDocPermissionEvents {
39
39
 
40
40
  export class ImageryDocPermissions extends EventEmitter<ImageryDocPermissionEvents> {
41
41
 
42
- private requestUserMap: (userId: string) => Y.Map<any>;
43
- private userManager: UserManager;
44
- private observers: Map<string, any> = new Map();
45
-
46
- public constructor(
47
- userManager: UserManager,
48
- requestUserMap: (userId: string) => Y.Map<any>,
49
- ) {
50
- super();
51
- this.userManager = userManager;
52
- this.requestUserMap = requestUserMap;
53
- this.createModel(this.userManager.selfId);
54
- this.userManager.userIdList().forEach((userId) => {
55
- this.addObserve(userId);
56
- });
57
-
58
- this.userManager.on("join", this.handleUserJoin);
59
- this.userManager.on("leave", this.handleUserLeave);
42
+ private requestUserMap: (userId: string) => Y.Map<any>;
43
+ private userManager: UserManager;
44
+ private observers: Map<string, any> = new Map();
45
+
46
+ public constructor(
47
+ userManager: UserManager,
48
+ requestUserMap: (userId: string) => Y.Map<any>,
49
+ ) {
50
+ super();
51
+ this.userManager = userManager;
52
+ this.requestUserMap = requestUserMap;
53
+ this.createModel(this.userManager.selfId);
54
+ this.userManager.userIdList().forEach((userId) => {
55
+ this.addObserve(userId);
56
+ });
57
+
58
+ this.userManager.on('join', this.handleUserJoin);
59
+ this.userManager.on('leave', this.handleUserLeave);
60
+ }
61
+
62
+ private handleUserLeave = (user: RoomUser) => {
63
+ const cb = this.observers.get(user.id);
64
+ if (cb) {
65
+ this.requestUserMap(user.id).unobserve(cb);
60
66
  }
67
+ };
61
68
 
62
- private handleUserLeave = (user: RoomUser) => {
63
- const cb = this.observers.get(user.id);
64
- if (cb) {
65
- this.requestUserMap(user.id).unobserve(cb);
66
- }
67
- };
69
+ private handleUserJoin = (user: RoomUser) => {
70
+ this.addObserve(user.id);
71
+ };
68
72
 
69
- private handleUserJoin = (user: RoomUser) => {
70
- this.addObserve(user.id);
73
+ private addObserve(userId: string) {
74
+ const observer = (evt: Y.YMapEvent<any>) => {
75
+ this.handleUserPermissionChange(userId, evt);
71
76
  };
72
-
73
- private addObserve(userId: string) {
74
- const observer = (evt: Y.YMapEvent<any>) => {
75
- this.handleUserPermissionChange(userId, evt);
76
- };
77
- this.observers.set(userId, observer);
78
- this.requestUserMap(userId).observe(observer)
79
- }
80
-
81
- private createModel(userId: string) {
82
- const userMap = this.requestUserMap(userId);
83
- if (!userMap.has("permission")) {
84
- userMap.set("permission", 0);
85
- }
77
+ this.observers.set(userId, observer);
78
+ this.requestUserMap(userId).observe(observer);
79
+ }
80
+
81
+ private createModel(userId: string) {
82
+ const userMap = this.requestUserMap(userId);
83
+ if (!userMap.has('permission')) {
84
+ userMap.set('permission', 0);
86
85
  }
87
-
88
- private handleUserPermissionChange(userId: string, evt: Y.YMapEvent<any>) {
89
- for (const [key, value] of evt.changes.keys.entries()) {
90
- if (key === "permission") {
91
- if (value.action === "add" || value.action === "update") {
92
- const newValue = this.requestUserMap(userId).get("permission");
93
- this.emit("change", userId, this.resolveFlags(newValue), newValue);
94
- }
95
- }
86
+ }
87
+
88
+ private handleUserPermissionChange(userId: string, evt: Y.YMapEvent<any>) {
89
+ for (const [key, value] of evt.changes.keys.entries()) {
90
+ if (key === 'permission') {
91
+ if (value.action === 'add' || value.action === 'update') {
92
+ const newValue = this.requestUserMap(userId).get('permission');
93
+ this.emit('change', userId, this.resolveFlags(newValue), newValue);
96
94
  }
95
+ }
97
96
  }
97
+ }
98
98
 
99
- /**
99
+ /**
100
100
  * 解析权限列表组合
101
101
  * @param {number} value - 权限数字值
102
102
  * @return {WhiteboardPermissionFlag[]} - 权限列表
103
103
  */
104
- public resolveFlags(value: number): ImageryDocPermissionFlag[] {
105
- return [
106
- ImageryDocPermissionFlag.switchPage,
107
- ImageryDocPermissionFlag.sideBar,
108
- ImageryDocPermissionFlag.camera
109
- ].filter(v => (v & value) !== 0)
110
- }
111
-
112
- /**
104
+ public resolveFlags(value: number): ImageryDocPermissionFlag[] {
105
+ return [
106
+ ImageryDocPermissionFlag.switchPage,
107
+ ImageryDocPermissionFlag.sideBar,
108
+ ImageryDocPermissionFlag.camera,
109
+ ].filter(v => (v & value) !== 0);
110
+ }
111
+
112
+ /**
113
113
  * 获取权限列表组合对应的数值
114
114
  * @param { string } userId 不传表示获取自己
115
115
  */
116
- public getPermissionValue(userId?: string): number {
117
- return this.requestUserMap(userId ?? this.userManager.selfId).get("permission") ?? 0;
118
- }
116
+ public getPermissionValue(userId?: string): number {
117
+ return this.requestUserMap(userId ?? this.userManager.selfId).get('permission') ?? 0;
118
+ }
119
119
 
120
- /**
120
+ /**
121
121
  * 获取权限列表
122
122
  * @param {string=} userId 可选, 不传表示获取自己
123
123
  */
124
- public getPermissionFlags(userId?: string): ImageryDocPermissionFlag[] {
125
- const value = this.requestUserMap(userId ?? this.userManager.selfId).get("permission") ?? 0;
126
- return this.resolveFlags(value);
127
- }
124
+ public getPermissionFlags(userId?: string): ImageryDocPermissionFlag[] {
125
+ const value = this.requestUserMap(userId ?? this.userManager.selfId).get('permission') ?? 0;
126
+ return this.resolveFlags(value);
127
+ }
128
128
 
129
- /**
129
+ /**
130
130
  * 返回对应 userId 是否有相应权限
131
131
  * @param {string=} userId 可选, 不传表示返回自己是否有相应权限
132
132
  * @param {WhiteboardPermissionFlag} flag
133
133
  */
134
- public hasPermission(flag: ImageryDocPermissionFlag, userId?: string): boolean {
135
- return ((this.requestUserMap(userId ?? this.userManager.selfId).get("permission") ?? 0) & flag) !== 0;
136
- }
134
+ public hasPermission(flag: ImageryDocPermissionFlag, userId?: string): boolean {
135
+ return ((this.requestUserMap(userId ?? this.userManager.selfId).get('permission') ?? 0) & flag) !== 0;
136
+ }
137
137
 
138
- /**
138
+ /**
139
139
  * 添加权限
140
140
  * @param {WhiteboardPermissionFlag} flag 权限标记
141
141
  * @param {string=} userId 可选, 为 userId 添加权限, 不传表示为自己添加权限
142
142
  */
143
- public addPermission(flag: ImageryDocPermissionFlag, userId?: string) {
144
- const userMap = this.requestUserMap(userId ?? this.userManager.selfId);
145
- const oldValue = userMap.get("permission") ?? 0;
146
- this.requestUserMap(userId ?? this.userManager.selfId).set("permission", oldValue | flag);
147
- }
143
+ public addPermission(flag: ImageryDocPermissionFlag, userId?: string) {
144
+ const userMap = this.requestUserMap(userId ?? this.userManager.selfId);
145
+ const oldValue = userMap.get('permission') ?? 0;
146
+ this.requestUserMap(userId ?? this.userManager.selfId).set('permission', oldValue | flag);
147
+ }
148
148
 
149
- /**
149
+ /**
150
150
  * 移除权限
151
151
  * @param {WhiteboardPermissionFlag} flag 权限标记
152
152
  * @param {string=} userId 可选, 为 userId 移除权限, 不传表示为自己移除权限
153
153
  */
154
- public removePermission(flag: ImageryDocPermissionFlag, userId?: string) {
155
- const userMap = this.requestUserMap(userId ?? this.userManager.selfId);
156
- const oldValue = userMap.get("permission") ?? 0;
157
- this.requestUserMap(userId ?? this.userManager.selfId).set("permission", oldValue & (~flag));
154
+ public removePermission(flag: ImageryDocPermissionFlag, userId?: string) {
155
+ const userMap = this.requestUserMap(userId ?? this.userManager.selfId);
156
+ const oldValue = userMap.get('permission') ?? 0;
157
+ this.requestUserMap(userId ?? this.userManager.selfId).set('permission', oldValue & (~flag));
158
+ }
159
+
160
+ public dispose() {
161
+ this.userManager.off('join', this.handleUserJoin);
162
+ this.userManager.off('leave', this.handleUserLeave);
163
+ for (const [userId, observer] of this.observers) {
164
+ this.requestUserMap(userId).unobserve(observer);
158
165
  }
166
+ this.observers.clear();
167
+ this.removeAllListeners();
168
+ }
159
169
  }