@netless/forge-slide 0.1.1-alpha.7 → 0.1.1-alpha.9

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,13 +1,13 @@
1
- import {Whiteboard, WhiteboardApplication, WhiteboardPermissionFlag} from "@netless/forge-whiteboard";
2
- import {ISlideConfig, Slide, SLIDE_EVENTS} from "@netless/slide";
3
- import {AbstractApplication} from "@netless/forge-room";
4
- import {SlideForge} from "./Slide";
5
- import {ForgeSlidePermissionFlag, ForgeSlidePermissions} from "./ForgeSlidePermession";
6
- import {FooterView} from "./FooterView";
7
- import * as Y from "yjs";
8
- import {SideBarView} from "./SiderBarView";
9
- import {deepEqual, delay} from "./utils";
10
- import { kvStore } from "@netless/forge-room";
1
+ import { Whiteboard, WhiteboardApplication, WhiteboardPermissionFlag } from '@netless/forge-whiteboard';
2
+ import { ISlideConfig, Slide, SLIDE_EVENTS } from '@netless/slide';
3
+ import { AbstractApplication, kvStore } from '@netless/forge-room';
4
+ import { SlideForge } from './Slide';
5
+ import { ForgeSlidePermissionFlag, ForgeSlidePermissions } from './ForgeSlidePermession';
6
+ import { FooterView } from './FooterView';
7
+ import * as Y from 'yjs';
8
+ import { SideBarView } from './SiderBarView';
9
+ import { deepEqual, delay } from './utils';
10
+ // import { slidePool } from './SlidePool';
11
11
 
12
12
  export interface SlideApplicationOption {
13
13
  prefix: string;
@@ -26,447 +26,520 @@ interface PreviewImage {
26
26
  height: number;
27
27
  }
28
28
 
29
- export const Slide_APP_NAME = "forge_slide";
29
+ export const Slide_APP_NAME = 'forge_slide';
30
30
 
31
31
  export class SlideApplication extends AbstractApplication<SlideApplicationOption, SlideForge> {
32
32
 
33
- static applicationName = Slide_APP_NAME;
34
-
35
- public readonly name: string = Slide_APP_NAME;
36
- public readonly emitter: SlideForge = new SlideForge();
37
-
38
- private whiteboardApp!: WhiteboardApplication;
39
- private whiteboard!: Whiteboard;
40
- private rootView: HTMLDivElement = document.createElement("div");
41
- private contentContainer: HTMLDivElement = document.createElement("div");
42
- private whiteboardContainer: HTMLDivElement = document.createElement("div");
43
- private slideContainer: HTMLDivElement = document.createElement("div");
44
- private permissions!: ForgeSlidePermissions;
45
- private footer: FooterView;
46
- private sideBar: SideBarView;
47
- private slide!: Slide;
48
- private currentSlideIndex: number = 0;
49
- private taskId: string = "";
50
- private prefix: string = "";
51
- private slideCount: number = 0;
52
-
53
- constructor() {
54
- super();
55
- (window as any).emitter = this.emitter;
56
- this.rootView.setAttribute("data-forge-app", Slide_APP_NAME);
57
- this.rootView.style.background = "#f0f0f0f0";
58
- this.rootView.style.overflow = "hidden";
59
-
60
- this.contentContainer.style.width = "100%";
61
- this.contentContainer.style.height = "100%";
62
- this.contentContainer.style.display = "flex";
63
- this.contentContainer.style.flexDirection = "column";
64
-
65
- this.slideContainer.style.width = "100%";
66
- this.slideContainer.style.height = "100%";
67
-
68
- this.footer = new FooterView();
69
- this.sideBar = new SideBarView();
70
- this.sideBar.on("pageChange", index => {
71
- if (index > 0 && index <= this.slideCount) {
72
- this.slide.renderSlide(index);
73
- }
74
- });
75
- this.footer.on("prevStep", () => {
76
- if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changeStep)) {
77
- return;
78
- }
79
- if (this.slide.mainSeqStep > 0 || this.slide.mainSeqState !== "idle") {
80
- this.slide.prevStep();
81
- } else if (this.currentSlideIndex > 1){
82
- if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changePage)) {
83
- return;
84
- }
85
- this.slide.renderSlide(this.currentSlideIndex - 1)
86
- }
87
- });
88
- this.footer.on("nextStep", () => {
89
- if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changeStep)) {
90
- return;
91
- }
92
- if (this.slide.mainSeqStep < this.slide.mainSeqLength) {
93
- this.slide.nextStep()
94
- } else {
95
- if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changePage)) {
96
- return;
97
- }
98
- this.slide.renderSlide(this.currentSlideIndex + 1)
99
- }
100
- });
101
- this.footer.on("prevPage", () => {
102
- if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changePage)) {
103
- return;
104
- }
105
- if (this.currentSlideIndex > 1) {
106
- this.slide.renderSlide(this.currentSlideIndex - 1);
107
- }
108
- });
109
- this.footer.on("nextPage", () => {
110
- if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changePage)) {
111
- return;
112
- }
113
- if (this.currentSlideIndex < this.slideCount) {
114
- this.slide.renderSlide(this.currentSlideIndex + 1);
115
- }
116
- });
117
-
118
- this.footer.on("sideBarToggle", () => {
119
- if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changePage)) {
120
- return;
121
- }
122
- if (this.sideBar.root.style.left === "0px") {
123
- this.sideBar.root.style.left = "-240px";
124
- } else {
125
- this.sideBar.root.style.left = "0px";
126
- }
127
- })
128
-
129
- this.rootView.appendChild(this.contentContainer);
130
-
131
- this.emitter.on("renderStart", pageIndex => {
132
- this.footer.prevPageState(pageIndex !== 0);
133
- });
134
-
135
- const that = this;
136
- Object.defineProperty(this.emitter, "view", {
137
- get(): any {
138
- return that.rootView;
139
- }
140
- });
141
- Object.defineProperty(this.emitter, "permissions", {
142
- get(): any {
143
- return that.permissions;
144
- }
145
- });
146
- Object.defineProperty(this.emitter, "footView", {
147
- get(): any {
148
- return that.footer.root;
149
- }
150
- })
151
- Object.defineProperty(this.emitter, "sidebarView", {
152
- get(): any {
153
- return that.sideBar.root;
154
- }
155
- })
156
- Object.defineProperty(this.emitter, "pageIndex", {
157
- get(): any {
158
- return that.currentSlideIndex;
159
- }
160
- });
161
- Object.defineProperty(this.emitter, "pageCount", {
162
- get(): any {
163
- return that.slideCount;
164
- }
165
- });
166
- Object.defineProperty(this.emitter, "goto", {
167
- writable: false,
168
- enumerable: false,
169
- value: (pageIndex: number) => {
170
- this.sideBar.emit("pageChange", pageIndex);
171
- }
172
- });
173
- Object.defineProperty(this.emitter, "nextStep", {
174
- writable: false,
175
- enumerable: false,
176
- value: () => {
177
- this.footer.emit("nextStep");
178
- }
179
- })
180
- Object.defineProperty(this.emitter, "prevStep", {
181
- writable: false,
182
- enumerable: false,
183
- value: () => {
184
- this.footer.emit("prevStep");
185
- }
186
- })
187
- Object.defineProperty(this.emitter, "nextPage", {
188
- writable: false,
189
- enumerable: false,
190
- value: () => {
191
- this.footer.emit("nextPage");
192
- }
193
- })
194
- Object.defineProperty(this.emitter, "prevPage", {
195
- writable: false,
196
- enumerable: false,
197
- value: () => {
198
- this.footer.emit("prevPage");
199
- }
200
- })
201
- Object.defineProperty(this.emitter, "sideBarToggle", {
202
- writable: false,
203
- enumerable: false,
204
- value: () => {
205
- this.footer.emit("sideBarToggle");
206
- }
207
- })
208
- Object.defineProperty(this.emitter, "imgContent", {
209
- writable: false,
210
- enumerable: false,
211
- value: (pageIndex: number) => {
212
- return this.getImageContent(pageIndex);
213
- }
214
- })
215
-
216
- Object.defineProperty(this.emitter, "imgUrl", {
217
- writable: false,
218
- enumerable: false,
219
- value: (pageIndex: number) => {
220
- return this.getImageUrl(pageIndex);
221
- }
222
- })
223
-
224
- Object.defineProperty(this.emitter, "imgSize", {
225
- writable: false,
226
- enumerable: false,
227
- value: (pageIndex: number) => {
228
- return this.getImageSize(pageIndex);
229
- }
230
- })
231
- }
232
-
233
- private getPreviewImageUrl (pageIndex: number) {
234
- if (pageIndex < 1 || pageIndex > this.slideCount) {
235
- throw new Error("pageIndex out of range");
33
+ static applicationName = Slide_APP_NAME;
34
+
35
+ public readonly name: string = Slide_APP_NAME;
36
+ public readonly emitter: SlideForge = new SlideForge();
37
+
38
+ private whiteboardApp!: WhiteboardApplication;
39
+ private whiteboard!: Whiteboard;
40
+ private rootView: HTMLDivElement = document.createElement('div');
41
+ private contentContainer: HTMLDivElement = document.createElement('div');
42
+ private whiteboardContainer: HTMLDivElement = document.createElement('div');
43
+ private slideContainer: HTMLDivElement = document.createElement('div');
44
+ private permissions!: ForgeSlidePermissions;
45
+ private footer: FooterView;
46
+ private sideBar: SideBarView;
47
+ private slide!: Slide;
48
+ private currentSlideIndex: number = 0;
49
+ private taskId: string = '';
50
+ private prefix: string = '';
51
+ private slideCount: number = 0;
52
+
53
+ constructor() {
54
+ super();
55
+ (window as any).emitter = this.emitter;
56
+ this.rootView.setAttribute('data-forge-app', Slide_APP_NAME);
57
+ this.rootView.style.background = '#f0f0f0f0';
58
+ this.rootView.style.overflow = 'hidden';
59
+
60
+ this.contentContainer.style.width = '100%';
61
+ this.contentContainer.style.height = '100%';
62
+ this.contentContainer.style.display = 'flex';
63
+ this.contentContainer.style.flexDirection = 'column';
64
+
65
+ this.slideContainer.style.width = '100%';
66
+ this.slideContainer.style.height = '100%';
67
+
68
+ this.footer = new FooterView();
69
+ this.sideBar = new SideBarView();
70
+ this.sideBar.on('pageChange', index => {
71
+ if (index > 0 && index <= this.slideCount) {
72
+ this.slide.renderSlide(index);
73
+ }
74
+ });
75
+ this.footer.on('prevStep', () => {
76
+ if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changeStep)) {
77
+ return;
78
+ }
79
+ if (this.slide.mainSeqStep > 0 || this.slide.mainSeqState !== 'idle') {
80
+ this.slide.prevStep();
81
+ } else if (this.currentSlideIndex > 1){
82
+ if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changePage)) {
83
+ return;
236
84
  }
237
- return `${this.prefix}/${this.taskId}/preview/${pageIndex}.png`;
85
+ this.slide.renderSlide(this.currentSlideIndex - 1);
86
+ }
87
+ });
88
+ this.footer.on('nextStep', () => {
89
+ if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changeStep)) {
90
+ return;
91
+ }
92
+ if (this.slide.mainSeqStep < this.slide.mainSeqLength) {
93
+ this.slide.nextStep();
94
+ } else {
95
+ if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changePage)) {
96
+ return;
97
+ }
98
+ this.slide.renderSlide(this.currentSlideIndex + 1);
99
+ }
100
+ });
101
+ this.footer.on('prevPage', () => {
102
+ if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changePage)) {
103
+ return;
104
+ }
105
+ if (this.currentSlideIndex > 1) {
106
+ this.slide.renderSlide(this.currentSlideIndex - 1);
107
+ }
108
+ });
109
+ this.footer.on('nextPage', () => {
110
+ if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changePage)) {
111
+ return;
112
+ }
113
+ if (this.currentSlideIndex < this.slideCount) {
114
+ this.slide.renderSlide(this.currentSlideIndex + 1);
115
+ }
116
+ });
117
+
118
+ this.footer.on('sideBarToggle', () => {
119
+ if (!this.permissions.hasPermission(ForgeSlidePermissionFlag.changePage)) {
120
+ return;
121
+ }
122
+ if (this.sideBar.isShowSideBar) {
123
+ this.sideBar.hidden();
124
+ } else {
125
+ this.sideBar.show();
126
+ }
127
+ });
128
+
129
+ this.rootView.appendChild(this.contentContainer);
130
+
131
+ this.emitter.on('renderStart', pageIndex => {
132
+ this.footer.prevPageState(pageIndex !== 0);
133
+ });
134
+
135
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
136
+ const that = this;
137
+ Object.defineProperty(this.emitter, 'view', {
138
+ get(): any {
139
+ return that.rootView;
140
+ },
141
+ });
142
+ Object.defineProperty(this.emitter, 'permissions', {
143
+ get(): any {
144
+ return that.permissions;
145
+ },
146
+ });
147
+ Object.defineProperty(this.emitter, 'footView', {
148
+ get(): any {
149
+ return that.footer.root;
150
+ },
151
+ });
152
+ Object.defineProperty(this.emitter, 'sidebarView', {
153
+ get(): any {
154
+ return that.sideBar.root;
155
+ },
156
+ });
157
+ Object.defineProperty(this.emitter, 'pageIndex', {
158
+ get(): any {
159
+ return that.currentSlideIndex;
160
+ },
161
+ });
162
+ Object.defineProperty(this.emitter, 'pageCount', {
163
+ get(): any {
164
+ return that.slideCount;
165
+ },
166
+ });
167
+ Object.defineProperty(this.emitter, 'goto', {
168
+ writable: false,
169
+ enumerable: false,
170
+ value: (pageIndex: number) => {
171
+ this.sideBar.emit('pageChange', pageIndex);
172
+ },
173
+ });
174
+ Object.defineProperty(this.emitter, 'nextStep', {
175
+ writable: false,
176
+ enumerable: false,
177
+ value: () => {
178
+ this.footer.emit('nextStep');
179
+ },
180
+ });
181
+ Object.defineProperty(this.emitter, 'prevStep', {
182
+ writable: false,
183
+ enumerable: false,
184
+ value: () => {
185
+ this.footer.emit('prevStep');
186
+ },
187
+ });
188
+ Object.defineProperty(this.emitter, 'nextPage', {
189
+ writable: false,
190
+ enumerable: false,
191
+ value: () => {
192
+ this.footer.emit('nextPage');
193
+ },
194
+ });
195
+ Object.defineProperty(this.emitter, 'prevPage', {
196
+ writable: false,
197
+ enumerable: false,
198
+ value: () => {
199
+ this.footer.emit('prevPage');
200
+ },
201
+ });
202
+ Object.defineProperty(this.emitter, 'sideBarToggle', {
203
+ writable: false,
204
+ enumerable: false,
205
+ value: () => {
206
+ this.footer.emit('sideBarToggle');
207
+ },
208
+ });
209
+ Object.defineProperty(this.emitter, 'imgContent', {
210
+ writable: false,
211
+ enumerable: false,
212
+ value: (pageIndex: number) => {
213
+ return this.getImageContent(pageIndex);
214
+ },
215
+ });
216
+
217
+ Object.defineProperty(this.emitter, 'imgUrl', {
218
+ writable: false,
219
+ enumerable: false,
220
+ value: (pageIndex: number) => {
221
+ return this.getImageUrl(pageIndex);
222
+ },
223
+ });
224
+
225
+ Object.defineProperty(this.emitter, 'imgSize', {
226
+ writable: false,
227
+ enumerable: false,
228
+ value: (pageIndex: number) => {
229
+ return this.getImageSize(pageIndex);
230
+ },
231
+ });
232
+ }
233
+
234
+ private getPreviewImageUrl (pageIndex: number) {
235
+ if (pageIndex < 1 || pageIndex > this.slideCount) {
236
+ throw new Error('pageIndex out of range');
238
237
  }
239
-
240
- private async getPreviewImage(imageUrl: string) {
241
- const image = fetch(imageUrl);
242
- return await image.then(res => res.blob()).then(blob => {
243
- return new Promise<PreviewImage>(resolve => {
244
- const reader = new FileReader();
245
- reader.onloadend = () => {
246
- const base64Data = reader.result as string;
247
- const img = document.createElement("img");
248
- img.src = base64Data;
249
- img.onload = () => {
250
- resolve({
251
- url: imageUrl,
252
- src: base64Data,
253
- width: img.width,
254
- height: img.height,
255
- });
256
- }
257
- }
258
- reader.readAsDataURL(blob);
259
- })
260
- });
238
+ return `${this.prefix}/${this.taskId}/preview/${pageIndex}.png`;
239
+ }
240
+
241
+ private async getPreviewImage(imageUrl: string) {
242
+ const image = fetch(imageUrl);
243
+ return await image.then(res => res.blob()).then(blob => {
244
+ return new Promise<PreviewImage>(resolve => {
245
+ const reader = new FileReader();
246
+ reader.onloadend = () => {
247
+ const base64Data = reader.result as string;
248
+ const img = document.createElement('img');
249
+ img.src = base64Data;
250
+ img.onload = () => {
251
+ resolve({
252
+ url: imageUrl,
253
+ src: base64Data,
254
+ width: img.width,
255
+ height: img.height,
256
+ });
257
+ };
258
+ };
259
+ reader.readAsDataURL(blob);
260
+ });
261
+ });
262
+ }
263
+
264
+ private async getImageUrl(pageIndex: number) {
265
+ return this.getPreviewImageUrl(pageIndex);
266
+ }
267
+
268
+ private async getImageSize(pageIndex: number) {
269
+ const imageUrl = this.getPreviewImageUrl(pageIndex);
270
+ let preview: PreviewImage | null = null;
271
+ try {
272
+ const result = await kvStore.getItem(imageUrl);
273
+ preview = result ? JSON.parse(result) : null;
274
+ } catch (e) {
275
+ console.warn('kvStore getItem error', e);
261
276
  }
262
-
263
- private async getImageUrl(pageIndex: number) {
264
- return this.getPreviewImageUrl(pageIndex);
277
+ if (preview) {
278
+ return { width: preview.width, height: preview.height };
265
279
  }
266
-
267
- private async getImageSize(pageIndex: number) {
268
- const imageUrl = this.getPreviewImageUrl(pageIndex);
269
- let preview: PreviewImage | null = null;
270
- try {
271
- const result = await kvStore.getItem(imageUrl);
272
- preview = result ? JSON.parse(result) : null;
273
- } catch (e) {
274
- console.warn("kvStore getItem error", e);
275
- }
276
- if (preview) {
277
- return { width: preview.width, height: preview.height };
278
- }
279
- preview = await this.getPreviewImage(imageUrl);
280
- await kvStore.setItem(imageUrl, JSON.stringify(preview));
281
- return { width: preview.width, height: preview.height };
280
+ preview = await this.getPreviewImage(imageUrl);
281
+ await kvStore.setItem(imageUrl, JSON.stringify(preview));
282
+ return { width: preview.width, height: preview.height };
283
+ }
284
+
285
+ private async getImageContent(pageIndex: number) {
286
+ const imageUrl = this.getPreviewImageUrl(pageIndex);
287
+ let preview: PreviewImage | null = null;
288
+ try {
289
+ const result = await kvStore.getItem(imageUrl);
290
+ preview = result ? JSON.parse(result) : null;
291
+ } catch (e) {
292
+ console.warn('kvStore getItem error', e);
282
293
  }
283
-
284
- private async getImageContent(pageIndex: number) {
285
- const imageUrl = this.getPreviewImageUrl(pageIndex);
286
- let preview: PreviewImage | null = null;
287
- try {
288
- const result = await kvStore.getItem(imageUrl);
289
- preview = result ? JSON.parse(result) : null;
290
- } catch (e) {
291
- console.warn("kvStore getItem error", e);
292
- }
293
- if (preview) {
294
- return preview.src;
294
+ if (preview) {
295
+ return preview.src;
296
+ }
297
+ preview = await this.getPreviewImage(imageUrl);
298
+ await kvStore.setItem(imageUrl, JSON.stringify(preview));
299
+ return preview.src;
300
+ }
301
+
302
+ private applySlideState = async (slideState: any, lastDispatch: any) => {
303
+ if (this.slide.slideState.currentSlideIndex < 0) {
304
+ this.slide.emit(SLIDE_EVENTS.syncReceive, lastDispatch);
305
+ return;
306
+ }
307
+ if (this.slide.slideState.currentSlideIndex > 0 && deepEqual(this.slide.slideState, slideState)) {
308
+ this.slide.emit(SLIDE_EVENTS.syncReceive, lastDispatch);
309
+ } else {
310
+ await this.slide.setSlideState(slideState);
311
+ await delay(200);
312
+ this.slide.emit(SLIDE_EVENTS.syncReceive, lastDispatch);
313
+ }
314
+ };
315
+
316
+ private onSlideEventHandler = async (event: Y.YMapEvent<any>) => {
317
+ for (const [key, value] of event.changes.keys.entries()) {
318
+ if (key === 'syncSlide') {
319
+ if (value.action === 'add' || value.action === 'update') {
320
+ const { slideState: slideStateFromServer, dispatch: dispatchFromServer } = this.getMap(this.name).get('syncSlide');
321
+ this.applySlideState(slideStateFromServer, dispatchFromServer);
295
322
  }
296
- preview = await this.getPreviewImage(imageUrl);
297
- await kvStore.setItem(imageUrl, JSON.stringify(preview));
298
- return preview.src;
323
+ }
324
+ }
325
+ };
326
+
327
+ private keyBoardEvents = (event: KeyboardEvent) => {
328
+ if (event.key === 'ArrowLeft') {
329
+ this.footer.emit('prevStep');
330
+ } else if (event.key === 'ArrowRight') {
331
+ this.footer.emit('nextStep');
332
+ } else if (event.key === 'ArrowUp') {
333
+ this.footer.emit('prevPage');
334
+ } else if (event.key === 'ArrowDown') {
335
+ this.footer.emit('nextPage');
336
+ }
337
+ };
338
+
339
+ private bindKeyBoardEvent() {
340
+ document.addEventListener('keydown', this.keyBoardEvents);
341
+ }
342
+
343
+ private unbindKeyBoardEvent() {
344
+ document.removeEventListener('keydown', this.keyBoardEvents);
345
+ }
346
+
347
+ private async onFocusInstance() {
348
+ this.bindKeyBoardEvent();
349
+ // await slidePool.active(this.appId, this.slide);
350
+ }
351
+
352
+ private onRefocusInstance() {
353
+ this.unbindKeyBoardEvent();
354
+ }
355
+
356
+
357
+ public async initialize(option: SlideApplicationOption): Promise<void> {
358
+ this.prefix = option.prefix;
359
+ this.taskId = option.taskId;
360
+ const whiteboardApp = new WhiteboardApplication();
361
+ // @ts-ignore
362
+ whiteboardApp.roomDoc = this.roomDoc;
363
+ // @ts-ignore
364
+ whiteboardApp.appId = `${option.taskId}_${this.appId}_wb`;
365
+ // @ts-ignore
366
+ whiteboardApp.userId = this.userId;
367
+ // @ts-ignore
368
+ whiteboardApp.userManager = this.userManager;
369
+ // @ts-ignore
370
+ whiteboardApp.applicationManager = this.applicationManager;
371
+
372
+ const json = await fetch(`${option.prefix}/${option.taskId}/jsonOutput/slide-1.json`).then(res => res.json());
373
+ this.slideCount = json.slideCount;
374
+ await whiteboardApp.initialize({
375
+ width: json.width,
376
+ height: json.height,
377
+ });
378
+ this.whiteboardApp = whiteboardApp;
379
+ this.whiteboard = whiteboardApp.emitter;
380
+ this.whiteboard.enableCameraByMouse = false;
381
+ this.whiteboard.enableCameraByTouch = false;
382
+ this.whiteboard.view.style.width = '100%';
383
+ this.whiteboard.view.style.height = '100%';
384
+ this.whiteboard.view.style.position = 'absolute';
385
+ this.whiteboard.view.style.top = '0';
386
+ this.whiteboard.view.style.left = '0';
387
+ this.whiteboard.view.style.zIndex = '4';
388
+ this.whiteboard.view.classList.add('slide-whiteboard');
389
+ this.whiteboard.permissions.addPermission(WhiteboardPermissionFlag.all);
390
+ this.whiteboard.setCanvasBackgroundColor('#f0f0f000');
391
+ this.whiteboardContainer.style.position = 'relative';
392
+ this.whiteboardContainer.style.flex = '0 0 auto';
393
+ this.whiteboardContainer.style.height = 'calc(100% - 24px)';
394
+ this.whiteboardContainer.classList.add('forge-slide-whiteboard-container');
395
+ this.whiteboardContainer.appendChild(this.whiteboard.view);
396
+ this.whiteboardContainer.appendChild(this.slideContainer);
397
+
398
+ this.contentContainer.appendChild(this.whiteboardContainer);
399
+ this.contentContainer.appendChild(this.footer.root);
400
+ this.contentContainer.appendChild(this.sideBar.root);
401
+
402
+ if (option.inheritWhiteboardId) {
403
+ whiteboardApp.linkToWhiteboard(option.inheritWhiteboardId);
299
404
  }
300
405
 
301
- private applySlideState = async (slideState: any, lastDispatch: any) => {
302
- if (this.slide.slideState.currentSlideIndex < 0) {
303
- this.slide.emit(SLIDE_EVENTS.syncReceive, lastDispatch);
304
- return;
305
- }
306
- if (this.slide.slideState.currentSlideIndex > 0 && deepEqual(this.slide.slideState, slideState)) {
307
- this.slide.emit(SLIDE_EVENTS.syncReceive, lastDispatch);
406
+ this.whiteboard.setViewModeToMain();
407
+
408
+
409
+ this.slideContainer.setAttribute('builder', 'slide-builder');
410
+
411
+ // await slidePool.waitUntilReady(this.appId);
412
+ this.slide = new Slide({
413
+ ...option.options,
414
+ interactive: true,
415
+ anchor: this.slideContainer,
416
+ mode: 'interactive',
417
+ // logger: {
418
+ // info: console.log,
419
+ // warn: console.warn,
420
+ // error: console.error,
421
+ // },
422
+ });
423
+ this.slide.setResource(option.taskId, option.prefix);
424
+ this.sideBar.initialize(json.slideCount, option);
425
+
426
+ this.slide.on(SLIDE_EVENTS.syncDispatch, event => {
427
+ this.getMap(this.name).set('syncSlide', {
428
+ slideState: this.slide.slideState,
429
+ dispatch: event,
430
+ });
431
+ });
432
+
433
+ this.slide.on(SLIDE_EVENTS.mainSeqStepStart, (animateIndex: number) => {
434
+ this.emitter.emit('mainSeqStepStart', animateIndex);
435
+ });
436
+
437
+ this.slide.on(SLIDE_EVENTS.mainSeqStepEnd, (animateIndex: number) => {
438
+ this.emitter.emit('mainSeqStepEnd', animateIndex);
439
+ });
440
+
441
+ this.slide.on(SLIDE_EVENTS.animateStart, () => {
442
+ this.sideBar.hidden();
443
+ });
444
+
445
+ this.slide.on(SLIDE_EVENTS.renderError, ({ error, index }) => {
446
+ if (error.errorType === 'CANVAS_CRASH') {
447
+ this.slide.renderSlide(index);
448
+ }
449
+ });
450
+
451
+ this.slide.on(SLIDE_EVENTS.renderStart, (slideIndex) => {
452
+ this.whiteboardApp.emitter.view.style.opacity = '0';
453
+ this.whiteboardApp.emitter.addPage(`${slideIndex}`);
454
+ this.whiteboardApp.emitter.gotoPage(`${slideIndex}`);
455
+ this.sideBar.hidden();
456
+ const { slideState: slideStateFromServer, dispatch: dispatchFromServer } = this.getMap(this.name).get('syncSlide');
457
+ this.applySlideState(slideStateFromServer, dispatchFromServer);
458
+ this.emitter.emit('renderStart', slideIndex);
459
+ });
460
+
461
+ this.slide.on(SLIDE_EVENTS.renderEnd, (slideIndex) => {
462
+ this.currentSlideIndex = slideIndex;
463
+ this.whiteboardApp.emitter.view.style.opacity = '1';
464
+ // slidePool.active(this.appId, this.slide);
465
+ // slidePool.onRenderEnd(this.appId, this.window?.focused ?? false);
466
+ this.emitter.emit('renderEnd', slideIndex);
467
+ });
468
+
469
+ this.slide.on(SLIDE_EVENTS.stateChange, (state) => {
470
+ this.getMap(this.name).set('slideState', state);
471
+ });
472
+
473
+ this.getMap(this.name).observe(this.onSlideEventHandler);
474
+
475
+ (window as any).slide = this.slide;
476
+ (window as any).slideWhiteboard = this.whiteboardApp;
477
+ (window as any).forgeSlide = this;
478
+
479
+ const syncSlide = this.getMap(this.name).get('slideState');
480
+ if (syncSlide && syncSlide.taskId === option.taskId) {
481
+ this.slide.setSlideState(syncSlide);
482
+ } else {
483
+ this.slide.renderSlide(1);
484
+ }
485
+ this.permissions = new ForgeSlidePermissions(this.userManager, (userId: string) => {
486
+ return this.userMap(userId);
487
+ });
488
+ this.permissions.on('change', (userId, flags, value) => {
489
+ this.emitter.emit('permissionChange', userId, flags, value);
490
+ if (this.userId === userId) {
491
+ if (flags.includes(ForgeSlidePermissionFlag.clickAnim)) {
492
+ this.slideContainer.style.pointerEvents = 'auto';
308
493
  } else {
309
- await this.slide.setSlideState(slideState);
310
- await delay(200);
311
- this.slide.emit(SLIDE_EVENTS.syncReceive, lastDispatch);
494
+ this.slideContainer.style.pointerEvents = 'none';
312
495
  }
313
- }
314
-
315
- private onSlideEventHandler = async (event: Y.YMapEvent<any>) => {
316
- for (const [key, value] of event.changes.keys.entries()) {
317
- if (key === "syncSlide") {
318
- if (value.action === "add" || value.action === "update") {
319
- const { slideState: slideStateFromServer, dispatch: dispatchFromServer } = this.getMap(this.name).get("syncSlide");
320
- this.applySlideState(slideStateFromServer, dispatchFromServer);
321
- }
322
- }
496
+ }
497
+ });
498
+ this.permissions.setPermission(ForgeSlidePermissionFlag.all);
499
+ this.whiteboardApp.disableViewModel();
500
+ if (this.window) {
501
+ let prevStatus = 'normal';
502
+ this.window.on('statusChange', (status) => {
503
+ if (prevStatus === 'minimized') {
504
+ this.onFocusInstance();
505
+ prevStatus = status;
506
+ return;
323
507
  }
324
- }
325
-
326
- public async initialize(option: SlideApplicationOption): Promise<void> {
327
- this.prefix = option.prefix;
328
- this.taskId = option.taskId;
329
- const whiteboardApp = new WhiteboardApplication();
330
- // @ts-ignore
331
- whiteboardApp.roomDoc = this.roomDoc;
332
- // @ts-ignore
333
- whiteboardApp.appId = `${option.taskId}_wb`;
334
- // @ts-ignore
335
- whiteboardApp.userId = this.userId;
336
- // @ts-ignore
337
- whiteboardApp.userManager = this.userManager;
338
- // @ts-ignore
339
- whiteboardApp.applicationManager = this.applicationManager;
340
-
341
- const json = await fetch(`${option.prefix}/${option.taskId}/jsonOutput/slide-1.json`).then(res => res.json())
342
- this.slideCount = json.slideCount;
343
- await whiteboardApp.initialize({
344
- width: json.width,
345
- height: json.height,
346
- });
347
- this.whiteboardApp = whiteboardApp;
348
- this.whiteboard = whiteboardApp.emitter;
349
- this.whiteboard.enableCameraByMouse = false;
350
- this.whiteboard.enableCameraByTouch = false;
351
- this.whiteboard.view.style.width = "100%";
352
- this.whiteboard.view.style.height = "100%";
353
- this.whiteboard.view.style.position = "absolute";
354
- this.whiteboard.view.style.top = "0";
355
- this.whiteboard.view.style.left = "0";
356
- this.whiteboard.view.style.zIndex = "4";
357
- this.whiteboard.view.classList.add("slide-whiteboard");
358
- this.whiteboard.permissions.addPermission(WhiteboardPermissionFlag.all);
359
- this.whiteboard.setCanvasBackgroundColor("#f0f0f000");
360
- this.whiteboardContainer.style.position = "relative";
361
- this.whiteboardContainer.style.flex = "0 0 auto";
362
- this.whiteboardContainer.style.height = "calc(100% - 24px)";
363
- this.whiteboardContainer.classList.add("forge-slide-whiteboard-container");
364
- this.whiteboardContainer.appendChild(this.whiteboard.view);
365
- this.whiteboardContainer.appendChild(this.slideContainer);
366
-
367
- this.contentContainer.appendChild(this.whiteboardContainer);
368
- this.contentContainer.appendChild(this.footer.root);
369
- this.contentContainer.appendChild(this.sideBar.root);
370
-
371
- if (option.inheritWhiteboardId) {
372
- whiteboardApp.linkToWhiteboard(option.inheritWhiteboardId);
508
+ prevStatus = status;
509
+ if (status === 'normal') {
510
+ this.onFocusInstance();
511
+ } else if (status === 'minimized') {
512
+ this.onRefocusInstance();
373
513
  }
374
-
375
- this.whiteboard.setViewModeToMain();
376
-
377
-
378
- this.slideContainer.setAttribute("builder", "slide-builder")
379
- this.slide = new Slide({
380
- ...option.options,
381
- interactive: true,
382
- anchor: this.slideContainer,
383
- mode: "interactive",
384
- // logger: {
385
- // info: console.log,
386
- // warn: console.warn,
387
- // error: console.error,
388
- // },
389
- })
390
- this.slide.setResource(option.taskId, option.prefix);
391
- this.sideBar.initialize(json.slideCount, option);
392
-
393
- this.slide.on("syncDispatch", event => {
394
- this.getMap(this.name).set("syncSlide", {
395
- slideState: this.slide.slideState,
396
- dispatch: event,
397
- })
398
- })
399
-
400
- this.slide.on("mainSeqStepStart", (animateIndex: number) => {
401
- this.emitter.emit("mainSeqStepStart", animateIndex);
402
- })
403
-
404
- this.slide.on("mainSeqStepEnd", (animateIndex: number) => {
405
- this.emitter.emit("mainSeqStepEnd", animateIndex);
406
- })
407
-
408
- this.slide.on("renderStart", (slideIndex) => {
409
- this.whiteboardApp.emitter.view.style.opacity = "0";
410
- this.whiteboardApp.emitter.addPage(`${slideIndex}`);
411
- this.whiteboardApp.emitter.gotoPage(`${slideIndex}`);
412
- this.emitter.emit("renderStart", slideIndex);
413
- })
414
-
415
- this.slide.on("renderEnd", (slideIndex) => {
416
- this.currentSlideIndex = slideIndex;
417
- this.whiteboardApp.emitter.view.style.opacity = "1";
418
- this.emitter.emit("renderEnd", slideIndex);
419
- });
420
-
421
- this.slide.on("stateChange", (state) => {
422
- this.getMap(this.name).set("slideState", state)
423
- })
424
-
425
- this.getMap(this.name).observe(this.onSlideEventHandler);
426
-
427
- (window as any).slide = this.slide;
428
- (window as any).slideWhiteboard = this.whiteboardApp;
429
- (window as any).forgeSlide = this;
430
-
431
- const syncSlide = this.getMap(this.name).get("slideState");
432
- if (syncSlide && syncSlide.taskId === option.taskId) {
433
- this.slide.setSlideState(syncSlide)
514
+ });
515
+ this.window.on('focusedChange', (status) => {
516
+ if (status) {
517
+ this.onFocusInstance();
434
518
  } else {
435
- this.slide.renderSlide(1);
519
+ this.onRefocusInstance();
436
520
  }
437
- this.permissions = new ForgeSlidePermissions(this.userManager, (userId: string) => {
438
- return this.userMap(userId);
439
- });
440
- this.permissions.on("change", (userId, flags, value) => {
441
- this.emitter.emit("permissionChange", userId, flags, value);
442
- if (this.userId === userId) {
443
- if (flags.includes(ForgeSlidePermissionFlag.clickAnim)) {
444
- this.slideContainer.style.pointerEvents = "auto";
445
- } else {
446
- this.slideContainer.style.pointerEvents = "none";
447
- }
448
- }
449
- });
450
- this.permissions.addPermission(ForgeSlidePermissionFlag.all);
451
- this.whiteboardApp.disableViewModel();
452
- // @ts-ignore
453
- window.__forge_slide = this;
454
- // @ts-ignore
455
- window.slidePermissions = this.permissions;
456
- return Promise.resolve(undefined);
457
- }
458
-
459
- private userMap(userId: string): Y.Map<any> {
460
- return this.getMap(`user/${userId}`);
461
- }
462
-
463
- public async dispose(): Promise<void> {
464
- await this.whiteboardApp.dispose();
465
- this.rootView.parentElement?.removeChild(this.rootView);
466
- this.slide.destroy();
467
- this.sideBar.dispose();
468
- this.getMap(this.name).unobserve(this.onSlideEventHandler)
469
- return Promise.resolve(undefined);
521
+ });
470
522
  }
523
+ // @ts-ignore
524
+ window.__forge_slide = this;
525
+ // @ts-ignore
526
+ window.slidePermissions = this.permissions;
527
+ return Promise.resolve(undefined);
528
+ }
529
+
530
+ private userMap(userId: string): Y.Map<any> {
531
+ return this.getMap(`user/${userId}`);
532
+ }
533
+
534
+ public async dispose(): Promise<void> {
535
+ await this.whiteboardApp.dispose();
536
+ this.rootView.parentElement?.removeChild(this.rootView);
537
+ this.slide.destroy();
538
+ this.sideBar.dispose();
539
+ this.getMap(this.name).unobserve(this.onSlideEventHandler);
540
+ this.permissions.dispose();
541
+ this.footer.dispose();
542
+ // slidePool.remove(this.appId);
543
+ }
471
544
 
472
545
  }