@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/dist/Slide.d.ts +35 -6
- package/dist/Slide.d.ts.map +1 -1
- package/dist/SlideApplication.d.ts +6 -0
- package/dist/SlideApplication.d.ts.map +1 -1
- package/dist/index.esm.js +116 -3
- package/dist/index.esm.js.map +2 -2
- package/dist/index.js +116 -3
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
- package/src/Slide.ts +35 -6
- package/src/SlideApplication.ts +119 -6
package/package.json
CHANGED
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) =>
|
|
57
|
+
public goto!: (index: number) => void
|
|
45
58
|
/**
|
|
46
59
|
* 下一步, 如果已经是本页的最后一步, 则切换到下一页
|
|
47
60
|
*/
|
|
48
|
-
public nextStep!: () =>
|
|
61
|
+
public nextStep!: () => void
|
|
49
62
|
/**
|
|
50
63
|
* 上一步, 如果已经是本页的第一步, 则切换到上一页
|
|
51
64
|
*/
|
|
52
|
-
public prevStep!: () =>
|
|
65
|
+
public prevStep!: () => void
|
|
53
66
|
/**
|
|
54
67
|
* 下一页, 如果是最后一页, 则不执行任何操作
|
|
55
68
|
*/
|
|
56
|
-
public nextPage!: () =>
|
|
69
|
+
public nextPage!: () => void
|
|
57
70
|
/**
|
|
58
71
|
* 上一页, 如果是第一页, 则不执行任何操作
|
|
59
72
|
*/
|
|
60
|
-
public prevPage!: () =>
|
|
73
|
+
public prevPage!: () => void
|
|
61
74
|
/**
|
|
62
75
|
* 切换侧栏显示状态
|
|
63
76
|
*/
|
|
64
|
-
public sideBarToggle!: () =>
|
|
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
|
}
|
package/src/SlideApplication.ts
CHANGED
|
@@ -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
|
-
|
|
299
|
-
|
|
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";
|