@netless/forge-slide 0.1.0-alpha.0 → 0.1.1-alpha.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/forge-slide",
3
- "version": "0.1.0-alpha.0",
3
+ "version": "0.1.1-alpha.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
package/src/Slide.ts CHANGED
@@ -22,6 +22,18 @@ export interface SlideEvents {
22
22
  * @param {number} pageIndex 页面索引
23
23
  */
24
24
  renderEnd: (pageIndex: number) => void;
25
+
26
+ /**
27
+ * 主序列动画完成时触发
28
+ * @param {number} animateIndex 主动画索引
29
+ */
30
+ mainSeqStepEnd: (animateIndex: number) => void;
31
+
32
+ /**
33
+ * 主序列动画开始时触发
34
+ * @param {number} animateIndex 主动画索引
35
+ */
36
+ mainSeqStepStart: (animateIndex: number) => void;
25
37
  }
26
38
 
27
39
 
@@ -29,6 +41,7 @@ export class SlideForge extends EventEmitter<SlideEvents> implements Application
29
41
 
30
42
  public readonly view!: HTMLDivElement;
31
43
  public readonly permissions!: ForgeSlidePermissions;
44
+ public readonly footView!: HTMLDivElement;
32
45
  /**
33
46
  * 当前页面索引, 从 0 开始
34
47
  */
@@ -41,25 +54,41 @@ export class SlideForge extends EventEmitter<SlideEvents> implements Application
41
54
  * 切换到参数指定页面, index 从 0 开始
42
55
  * @param {number} index 页面索引
43
56
  */
44
- public goto!: (index: number) => Promise<void>
57
+ public goto!: (index: number) => void
45
58
  /**
46
59
  * 下一步, 如果已经是本页的最后一步, 则切换到下一页
47
60
  */
48
- public nextStep!: () => Promise<void>
61
+ public nextStep!: () => void
49
62
  /**
50
63
  * 上一步, 如果已经是本页的第一步, 则切换到上一页
51
64
  */
52
- public prevStep!: () => Promise<void>
65
+ public prevStep!: () => void
53
66
  /**
54
67
  * 下一页, 如果是最后一页, 则不执行任何操作
55
68
  */
56
- public nextPage!: () => Promise<void>
69
+ public nextPage!: () => void
57
70
  /**
58
71
  * 上一页, 如果是第一页, 则不执行任何操作
59
72
  */
60
- public prevPage!: () => Promise<void>
73
+ public prevPage!: () => void
61
74
  /**
62
75
  * 切换侧栏显示状态
63
76
  */
64
- public sideBarToggle!: () => Promise<void>
77
+ public sideBarToggle!: () => void
78
+
79
+ /**
80
+ * 获取预览图图片内容, base64 编码
81
+ * @param {number} index 页面索引
82
+ */
83
+ public imgContent!: (index: number) => Promise<string>;
84
+ /**
85
+ * 获取预览图图片链接
86
+ * @param {number} index 页面索引
87
+ */
88
+ public imgUrl!: (index: number) => Promise<string>;
89
+ /**
90
+ * 获取预览图图片尺寸
91
+ * @param {number} index 页面索引
92
+ */
93
+ public imgSize!: (index: number) => Promise<{width: number, height: number}>;
65
94
  }
@@ -7,6 +7,7 @@ import {FooterView} from "./FoorerView";
7
7
  import * as Y from "yjs";
8
8
  import {SideBarView} from "./SiderBarView";
9
9
  import {deepEqual, delay} from "./utils";
10
+ import { kvStore } from "@netless/forge-room";
10
11
 
11
12
  export interface SlideApplicationOption {
12
13
  prefix: string;
@@ -18,6 +19,13 @@ export interface SlideApplicationOption {
18
19
  inheritWhiteboardId?: string;
19
20
  }
20
21
 
22
+ interface PreviewImage {
23
+ url: string;
24
+ src: string;
25
+ width: number;
26
+ height: number;
27
+ }
28
+
21
29
  export const Slide_APP_NAME = "forge_slide";
22
30
 
23
31
  export class SlideApplication extends AbstractApplication<SlideApplicationOption, SlideForge> {
@@ -38,6 +46,8 @@ export class SlideApplication extends AbstractApplication<SlideApplicationOption
38
46
  private sideBar: SideBarView;
39
47
  private slide!: Slide;
40
48
  private currentSlideIndex: number = 0;
49
+ private taskId: string = "";
50
+ private prefix: string = "";
41
51
 
42
52
  constructor() {
43
53
  super();
@@ -118,6 +128,10 @@ export class SlideApplication extends AbstractApplication<SlideApplicationOption
118
128
 
119
129
  this.rootView.appendChild(this.contentContainer);
120
130
 
131
+ this.permissions.on("change", (userId, flags, value) => {
132
+ this.emitter.emit("permissionChange", userId, flags, value);
133
+ })
134
+
121
135
  this.emitter.on("renderStart", pageIndex => {
122
136
  this.footer.prevPageState(pageIndex !== 0);
123
137
  });
@@ -133,6 +147,11 @@ export class SlideApplication extends AbstractApplication<SlideApplicationOption
133
147
  return that.permissions;
134
148
  }
135
149
  });
150
+ Object.defineProperty(this.emitter, "footView", {
151
+ get(): any {
152
+ return that.footer.root;
153
+ }
154
+ })
136
155
  Object.defineProperty(this.emitter, "pageIndex", {
137
156
  get(): any {
138
157
  return that.currentSlideIndex;
@@ -185,6 +204,90 @@ export class SlideApplication extends AbstractApplication<SlideApplicationOption
185
204
  this.footer.emit("sideBarToggle");
186
205
  }
187
206
  })
207
+ Object.defineProperty(this.emitter, "imgContent", {
208
+ writable: false,
209
+ enumerable: false,
210
+ value: (pageIndex: number) => {
211
+ return this.getImageContent(pageIndex);
212
+ }
213
+ })
214
+
215
+ Object.defineProperty(this.emitter, "imgUrl", {
216
+ writable: false,
217
+ enumerable: false,
218
+ value: (pageIndex: number) => {
219
+ return this.getImageUrl(pageIndex);
220
+ }
221
+ })
222
+
223
+ Object.defineProperty(this.emitter, "imgSize", {
224
+ writable: false,
225
+ enumerable: false,
226
+ value: (pageIndex: number) => {
227
+ return this.getImageSize(pageIndex);
228
+ }
229
+ })
230
+ }
231
+
232
+ private async getPreviewImage(imageUrl: string) {
233
+ const image = fetch(imageUrl);
234
+ return await image.then(res => res.blob()).then(blob => {
235
+ return new Promise<PreviewImage>(resolve => {
236
+ const reader = new FileReader();
237
+ reader.onloadend = () => {
238
+ const base64Data = reader.result as string;
239
+ const img = document.createElement("img");
240
+ img.src = base64Data;
241
+ img.onload = () => {
242
+ resolve({
243
+ url: imageUrl,
244
+ src: base64Data,
245
+ width: img.width,
246
+ height: img.height,
247
+ });
248
+ }
249
+ }
250
+ reader.readAsDataURL(blob);
251
+ })
252
+ });
253
+ }
254
+
255
+ private async getImageUrl(pageIndex: number) {
256
+ return `${this.prefix}/${this.taskId}/preview/${pageIndex + 1}.png`;
257
+ }
258
+
259
+ private async getImageSize(pageIndex: number) {
260
+ const imageUrl = `${this.prefix}/${this.taskId}/preview/${pageIndex + 1}.png`;
261
+ let preview: PreviewImage | null = null;
262
+ try {
263
+ const result = await kvStore.getItem(imageUrl);
264
+ preview = result ? JSON.parse(result) : null;
265
+ } catch (e) {
266
+ console.warn("kvStore getItem error", e);
267
+ }
268
+ if (preview) {
269
+ return { width: preview.width, height: preview.height };
270
+ }
271
+ preview = await this.getPreviewImage(imageUrl);
272
+ await kvStore.setItem(imageUrl, JSON.stringify(preview));
273
+ return { width: preview.width, height: preview.height };
274
+ }
275
+
276
+ private async getImageContent(pageIndex: number) {
277
+ const imageUrl = `${this.prefix}/${this.taskId}/preview/${pageIndex + 1}.png`;
278
+ let preview: PreviewImage | null = null;
279
+ try {
280
+ const result = await kvStore.getItem(imageUrl);
281
+ preview = result ? JSON.parse(result) : null;
282
+ } catch (e) {
283
+ console.warn("kvStore getItem error", e);
284
+ }
285
+ if (preview) {
286
+ return preview.src;
287
+ }
288
+ preview = await this.getPreviewImage(imageUrl);
289
+ await kvStore.setItem(imageUrl, JSON.stringify(preview));
290
+ return preview.src;
188
291
  }
189
292
 
190
293
  private applySlideState = async (slideState: any, lastDispatch: any) => {
@@ -192,7 +295,6 @@ export class SlideApplication extends AbstractApplication<SlideApplicationOption
192
295
  this.slide.emit(SLIDE_EVENTS.syncReceive, lastDispatch);
193
296
  return;
194
297
  }
195
- console.log('%cisEqual', 'color: blue; font-size: 20px;', deepEqual(this.slide.slideState, slideState));
196
298
  if (this.slide.slideState.currentSlideIndex > 0 && deepEqual(this.slide.slideState, slideState)) {
197
299
  this.slide.emit(SLIDE_EVENTS.syncReceive, lastDispatch);
198
300
  } else {
@@ -214,6 +316,8 @@ export class SlideApplication extends AbstractApplication<SlideApplicationOption
214
316
  }
215
317
 
216
318
  public async initialize(option: SlideApplicationOption): Promise<void> {
319
+ this.prefix = option.prefix;
320
+ this.taskId = option.taskId;
217
321
  const whiteboardApp = new WhiteboardApplication();
218
322
  // @ts-ignore
219
323
  whiteboardApp.roomDoc = this.roomDoc;
@@ -256,7 +360,6 @@ export class SlideApplication extends AbstractApplication<SlideApplicationOption
256
360
 
257
361
  if (option.inheritWhiteboardId) {
258
362
  whiteboardApp.linkToWhiteboard(option.inheritWhiteboardId);
259
- console.log("inheritWhiteboardId", option.inheritWhiteboardId);
260
363
  }
261
364
 
262
365
  this.whiteboard.setViewModeToMain();
@@ -284,25 +387,36 @@ export class SlideApplication extends AbstractApplication<SlideApplicationOption
284
387
  })
285
388
  })
286
389
 
390
+ this.slide.on("mainSeqStepStart", (animateIndex: number) => {
391
+ this.emitter.emit("mainSeqStepStart", animateIndex);
392
+ })
393
+
394
+ this.slide.on("mainSeqStepEnd", (animateIndex: number) => {
395
+ this.emitter.emit("mainSeqStepEnd", animateIndex);
396
+ })
397
+
287
398
  this.slide.on("renderStart", (slideIndex) => {
288
399
  this.whiteboardApp.emitter.view.style.opacity = "0";
289
400
  this.whiteboardApp.emitter.addPage(`${slideIndex}`);
290
401
  this.whiteboardApp.emitter.gotoPage(`${slideIndex}`);
402
+ this.emitter.emit("renderStart", slideIndex);
291
403
  })
292
404
 
293
405
  this.slide.on("renderEnd", (slideIndex) => {
294
406
  this.currentSlideIndex = slideIndex;
295
407
  this.whiteboardApp.emitter.view.style.opacity = "1";
408
+ this.emitter.emit("renderEnd", slideIndex);
296
409
  });
297
410
 
298
- this.slide.on("stateChange", (state) => {
299
- this.getMap(this.name).set("slideState", state)
300
- })
411
+ this.slide.on("stateChange", (state) => {
412
+ this.getMap(this.name).set("slideState", state)
413
+ })
301
414
 
302
415
  this.getMap(this.name).observe(this.onSlideEventHandler);
303
416
 
304
417
  (window as any).slide = this.slide;
305
418
  (window as any).slideWhiteboard = this.whiteboardApp;
419
+ (window as any).forgeSlide = this;
306
420
 
307
421
  const syncSlide = this.getMap(this.name).get("slideState");
308
422
  if (syncSlide && syncSlide.taskId === option.taskId) {
@@ -315,7 +429,6 @@ export class SlideApplication extends AbstractApplication<SlideApplicationOption
315
429
  return this.userMap(userId);
316
430
  });
317
431
  this.permissions.on("change", (userId, flags, value) => {
318
- console.log(userId, flags, value);
319
432
  if (this.userId === userId) {
320
433
  if (flags.includes(ForgeSlidePermissionFlag.clickAnim)) {
321
434
  this.slideContainer.style.pointerEvents = "auto";