@netless/app-slide 0.2.2 → 0.3.0-canary.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.
Files changed (58) hide show
  1. package/README-zh.md +1 -4
  2. package/README.md +1 -4
  3. package/dist/Refrigerator.d.ts +13 -0
  4. package/dist/SlideViewer.d.ts +63 -0
  5. package/dist/constants.d.ts +2 -0
  6. package/dist/{DocsViewer/icons → icons}/arrow-left.d.ts +0 -0
  7. package/dist/{DocsViewer/icons → icons}/arrow-right.d.ts +0 -0
  8. package/dist/{DocsViewer/icons → icons}/pause.d.ts +0 -0
  9. package/dist/{DocsViewer/icons → icons}/play.d.ts +0 -0
  10. package/dist/{DocsViewer/icons → icons}/sidebar.d.ts +0 -0
  11. package/dist/index.d.ts +10 -35
  12. package/dist/main.cjs.js +177 -177
  13. package/dist/main.cjs.js.map +1 -1
  14. package/dist/main.es.js +1901 -2479
  15. package/dist/main.es.js.map +1 -1
  16. package/dist/main.iife.js +254 -254
  17. package/dist/main.iife.js.map +1 -1
  18. package/dist/typings.d.ts +21 -9
  19. package/dist/utils.d.ts +1 -0
  20. package/package.json +2 -2
  21. package/src/Refrigerator.ts +66 -0
  22. package/src/SlideViewer.ts +543 -0
  23. package/src/constants.ts +3 -0
  24. package/src/{DocsViewer/icons → icons}/arrow-left.ts +0 -0
  25. package/src/{DocsViewer/icons → icons}/arrow-right.ts +0 -0
  26. package/src/{DocsViewer/icons → icons}/pause.ts +0 -0
  27. package/src/{DocsViewer/icons → icons}/play.ts +0 -0
  28. package/src/{DocsViewer/icons → icons}/sidebar.ts +0 -0
  29. package/src/index.ts +210 -205
  30. package/src/style.scss +245 -5
  31. package/src/typings.ts +23 -10
  32. package/src/utils.ts +3 -0
  33. package/dist/DocsViewer/index.d.ts +0 -53
  34. package/dist/SlideController/helpers.d.ts +0 -6
  35. package/dist/SlideController/index.d.ts +0 -60
  36. package/dist/SlideDocsViewer/index.d.ts +0 -45
  37. package/dist/SlidePreviewer/index.d.ts +0 -52
  38. package/dist/utils/bgcolor.d.ts +0 -3
  39. package/dist/utils/freezer.d.ts +0 -22
  40. package/dist/utils/helpers.d.ts +0 -6
  41. package/dist/utils/logger.d.ts +0 -39
  42. package/src/DocsViewer/icons/arrow-left.svg +0 -4
  43. package/src/DocsViewer/icons/arrow-right.svg +0 -4
  44. package/src/DocsViewer/icons/pause.svg +0 -4
  45. package/src/DocsViewer/icons/play.svg +0 -4
  46. package/src/DocsViewer/icons/sidebar.svg +0 -4
  47. package/src/DocsViewer/index.ts +0 -368
  48. package/src/DocsViewer/style.scss +0 -228
  49. package/src/DocsViewer/variables.scss +0 -1
  50. package/src/SlideController/helpers.ts +0 -48
  51. package/src/SlideController/index.ts +0 -356
  52. package/src/SlideDocsViewer/index.ts +0 -210
  53. package/src/SlideDocsViewer/style.scss +0 -11
  54. package/src/SlidePreviewer/index.ts +0 -226
  55. package/src/utils/bgcolor.ts +0 -45
  56. package/src/utils/freezer.ts +0 -75
  57. package/src/utils/helpers.ts +0 -26
  58. package/src/utils/logger.ts +0 -106
package/dist/typings.d.ts CHANGED
@@ -1,19 +1,31 @@
1
1
  import type { Slide, SLIDE_EVENTS, SyncEvent } from "@netless/slide";
2
+ import type { RegisterParams } from "@netless/window-manager";
2
3
  export declare type SlideState = Slide["slideState"];
4
+ export declare type AddHooks = NonNullable<RegisterParams["addHooks"]>;
3
5
  export interface Attributes {
4
6
  /** convert task id */
5
7
  taskId: string;
6
- /** base url of converted resources */
8
+ /** base url of converted resources, default `https://convertcdn.netless.link/dynamicConvert` */
7
9
  url: string;
8
10
  /** internal state of slide, do not change */
9
11
  state: SlideState | null;
10
12
  }
11
- export declare type MagixPayload = {
12
- type: typeof SLIDE_EVENTS.syncDispatch;
13
- payload: SyncEvent;
14
- };
15
- export declare type MagixEvents = {
16
- [SLIDE_EVENTS.syncDispatch]: MagixPayload;
17
- };
18
- export interface A {
13
+ export interface MagixEvents {
14
+ [SLIDE_EVENTS.syncDispatch]: SyncEvent;
15
+ }
16
+ export interface AppOptions {
17
+ /** show debug controller */
18
+ debug?: boolean;
19
+ /** scale */
20
+ resolution?: number;
21
+ /** background color for slide animations */
22
+ bgColor?: string;
23
+ /** minimal fps (default: 25) */
24
+ minFPS?: number;
25
+ /** maximal fps (default: 30) */
26
+ maxFPS?: number;
27
+ /** automatically decrease fps (default: true) */
28
+ autoFPS?: boolean;
29
+ /** whether to re-scale automatically (default: true) */
30
+ autoResolution?: boolean;
19
31
  }
@@ -0,0 +1 @@
1
+ export declare function noop(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/app-slide",
3
- "version": "0.2.2",
3
+ "version": "0.3.0-canary.0",
4
4
  "main": "dist/main.cjs.js",
5
5
  "module": "dist/main.es.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,11 +10,11 @@
10
10
  "README-zh.md"
11
11
  ],
12
12
  "devDependencies": {
13
- "@netless/app-shared": "0.1.2",
14
13
  "@netless/slide": "^0.4.7",
15
14
  "@types/color-string": "^1.5.2",
16
15
  "color-string": "^1.9.1",
17
16
  "side-effect-manager": "^1.1.0",
17
+ "value-enhancer": "^1.3.0",
18
18
  "vanilla-lazyload": "^17.8.2"
19
19
  },
20
20
  "scripts": {
@@ -0,0 +1,66 @@
1
+ import type { SlideViewer } from "./SlideViewer";
2
+ import type { AddHooks } from "./typings";
3
+
4
+ export class Refrigerator {
5
+ threshold = 2;
6
+
7
+ private _map = new Map<string, SlideViewer>();
8
+ private _queue: string[] = [];
9
+
10
+ set(appId: string, viewer: SlideViewer) {
11
+ this._map.set(appId, viewer);
12
+ if (!this._queue.includes(appId)) {
13
+ this._queue.unshift(appId);
14
+ }
15
+ this._refresh();
16
+ return () => {
17
+ this.delete(appId);
18
+ };
19
+ }
20
+
21
+ delete(appId: string) {
22
+ this._map.delete(appId);
23
+ this._queue = this._queue.filter(id => id !== appId);
24
+ this._refresh();
25
+ }
26
+
27
+ focus(appId: string) {
28
+ const index = this._queue.indexOf(appId);
29
+ if (index >= 0) {
30
+ this._queue.splice(index, 1);
31
+ }
32
+ this._queue.unshift(appId);
33
+ this._refresh();
34
+ }
35
+
36
+ private _refresh() {
37
+ let viewer: SlideViewer | undefined;
38
+ this._queue.forEach((appId, i) => {
39
+ if (!(viewer = this._map.get(appId))) return;
40
+ if (i < this.threshold) {
41
+ viewer.unfreeze();
42
+ } else {
43
+ viewer.freeze();
44
+ }
45
+ });
46
+ if (import.meta.env.DEV) {
47
+ console.log(
48
+ "[Slide] refrigerator._refresh",
49
+ `[${this._queue.slice(0, this.threshold)}]`,
50
+ `[${this._queue.slice(this.threshold)}]`
51
+ );
52
+ }
53
+ }
54
+ }
55
+
56
+ export const refrigerator = new Refrigerator();
57
+ if (import.meta.env.DEV) {
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ (window as any).refrigerator = refrigerator;
60
+ }
61
+
62
+ export const addHooks: AddHooks = function addHooks(emitter) {
63
+ emitter.on("focus", event => {
64
+ refrigerator.focus(event.appId);
65
+ });
66
+ };
@@ -0,0 +1,543 @@
1
+ import type { ISlideConfig } from "@netless/slide";
2
+
3
+ import { Slide } from "@netless/slide";
4
+ import { SideEffectManager } from "side-effect-manager";
5
+ import LazyLoad from "vanilla-lazyload";
6
+
7
+ import { DefaultUrl, namespace } from "./constants";
8
+ import { noop } from "./utils";
9
+ import styles from "./style.scss?inline";
10
+
11
+ import { sidebarSVG } from "./icons/sidebar";
12
+ import { arrowLeftSVG } from "./icons/arrow-left";
13
+ import { playSVG } from "./icons/play";
14
+ import { pauseSVG } from "./icons/pause";
15
+ import { arrowRightSVG } from "./icons/arrow-right";
16
+
17
+ function h<K extends keyof HTMLElementTagNameMap>(tag: K) {
18
+ return document.createElement(tag);
19
+ }
20
+
21
+ function append(parent: HTMLElement, child: HTMLElement) {
22
+ return parent.appendChild(child);
23
+ }
24
+
25
+ function wrap_class(name: string) {
26
+ return `${namespace}-${name}`;
27
+ }
28
+
29
+ function set_class(el: HTMLElement, name: string) {
30
+ el.className = wrap_class(name);
31
+ }
32
+
33
+ function trim_slash(s: string) {
34
+ return s.endsWith("/") ? s.slice(0, -1) : s;
35
+ }
36
+
37
+ interface SlideAttributes {
38
+ taskId: string;
39
+ url?: string;
40
+ }
41
+
42
+ interface PreviewPage {
43
+ width: number;
44
+ height: number;
45
+ thumbnail: string;
46
+ }
47
+
48
+ async function fetch_slide_info({ taskId, url }: SlideAttributes) {
49
+ const prefix = make_prefix(taskId, url);
50
+ const imgSrc = `${prefix}/preview/1.png`;
51
+ const jsonUrl = `${prefix}/jsonOutput/slide-1.json`;
52
+
53
+ interface PreviewInfo {
54
+ width: number;
55
+ height: number;
56
+ }
57
+ const p1 = new Promise<PreviewInfo | null>(resolve => {
58
+ const image = new Image();
59
+ image.onload = () => resolve(image);
60
+ image.onerror = () => resolve(null);
61
+ image.src = imgSrc;
62
+ });
63
+
64
+ interface SlideInfo {
65
+ width: number;
66
+ height: number;
67
+ slideCount: number;
68
+ }
69
+ const p2: Promise<SlideInfo> = fetch(jsonUrl).then(r => r.json());
70
+
71
+ return { preview: await p1, slide: await p2 };
72
+ }
73
+
74
+ function make_prefix(taskId: string, url?: string) {
75
+ return `${trim_slash(url || DefaultUrl)}/${taskId}`;
76
+ }
77
+
78
+ function create_sidebar() {
79
+ type NewPageIndexCallback = (newPageIndex: number) => void;
80
+ let new_page_index_callback: NewPageIndexCallback = noop;
81
+ const on_new_page_index = (callback: NewPageIndexCallback) => {
82
+ new_page_index_callback = callback;
83
+ };
84
+
85
+ let destroyed = false;
86
+ let readonly = false;
87
+ let active = false;
88
+ let pages: PreviewPage[] = [];
89
+ let page_index = 0;
90
+
91
+ const class_readonly = wrap_class("readonly");
92
+ const class_preview_active = wrap_class("preview-active");
93
+
94
+ const $content = h("div");
95
+ set_class($content, "content");
96
+
97
+ const $previewMask = h("div");
98
+ set_class($previewMask, "preview-mask");
99
+ $previewMask.onclick = function on_click_preview_mask(ev) {
100
+ if (readonly) return;
101
+ if (ev.target !== $previewMask) return;
102
+ set_active(false);
103
+ };
104
+ append($content, $previewMask);
105
+
106
+ const $preview = h("div");
107
+ set_class($preview, "preview");
108
+ $preview.classList.add("tele-fancy-scrollbar");
109
+ $preview.onclick = function on_click_preview(ev) {
110
+ if (readonly) return;
111
+ const page_index = (ev.target as HTMLElement).dataset?.pageIndex;
112
+ if (page_index) {
113
+ ev.preventDefault();
114
+ ev.stopPropagation();
115
+ ev.stopImmediatePropagation();
116
+ new_page_index_callback(Number(page_index));
117
+ set_active(false);
118
+ }
119
+ };
120
+ append($content, $preview);
121
+
122
+ const lazyload = new LazyLoad({
123
+ container: $preview,
124
+ elements_selector: `.${wrap_class("preview-page>img")}`,
125
+ });
126
+
127
+ function set_readonly(readonly_: boolean) {
128
+ if (readonly !== readonly_) {
129
+ readonly = readonly_;
130
+ $content.classList.toggle(class_readonly, readonly);
131
+ }
132
+ }
133
+
134
+ function set_active(active_: boolean) {
135
+ if (active !== active_) {
136
+ active = active_;
137
+ $content.classList.toggle(class_preview_active, active);
138
+ }
139
+ }
140
+
141
+ function set_pages(pages_: PreviewPage[]) {
142
+ if (pages !== pages_) {
143
+ pages = pages_;
144
+
145
+ const page_class = wrap_class("preview-page");
146
+ const page_name_class = wrap_class("preview-page-name");
147
+
148
+ pages.forEach((page, i) => {
149
+ const pageIndex = String(i);
150
+
151
+ const $page = h("a");
152
+ $page.className = page_class + " " + wrap_class(`preview-page-${i}`);
153
+ $page.href = "#";
154
+ $page.dataset.pageIndex = pageIndex;
155
+
156
+ const $name = h("span");
157
+ $name.className = page_name_class;
158
+ $name.textContent = String(i + 1);
159
+ $name.dataset.pageIndex = pageIndex;
160
+
161
+ const $img = h("img");
162
+ $img.width = page.width;
163
+ $img.height = page.height;
164
+ $img.src = page.thumbnail;
165
+ $img.alt = `page-${i}`;
166
+ $img.dataset.pageIndex = pageIndex;
167
+
168
+ append($page, $img);
169
+ append($page, $name);
170
+ append($preview, $page);
171
+ });
172
+
173
+ if (!destroyed) {
174
+ lazyload.update();
175
+ }
176
+ }
177
+ }
178
+
179
+ function set_page_index(page_index_: number) {
180
+ if (page_index !== page_index_) {
181
+ page_index = page_index_;
182
+ const $page = $preview.querySelector<HTMLElement>(
183
+ `.${wrap_class(`preview-page-${page_index}`)}`
184
+ );
185
+ if ($page) {
186
+ $preview.scrollTo({ top: $page.offsetTop - 16 });
187
+ }
188
+ }
189
+ }
190
+
191
+ function destroy() {
192
+ destroyed = true;
193
+ lazyload.destroy();
194
+ }
195
+
196
+ function get_active() {
197
+ return active;
198
+ }
199
+
200
+ return {
201
+ $content,
202
+ $preview,
203
+ set_readonly,
204
+ set_active,
205
+ get_active,
206
+ set_pages,
207
+ on_new_page_index,
208
+ set_page_index,
209
+ destroy,
210
+ };
211
+ }
212
+
213
+ function create_footer() {
214
+ type NewPageIndexCallback = (newPageIndex: number) => void;
215
+ let new_page_index_callback: NewPageIndexCallback = noop;
216
+ const on_new_page_index = (callback: NewPageIndexCallback) => {
217
+ new_page_index_callback = callback;
218
+ };
219
+
220
+ let toggle_preview_callback: () => void = noop;
221
+ const on_toggle_preview = (callback: () => void) => {
222
+ toggle_preview_callback = callback;
223
+ };
224
+
225
+ let play_callback: () => void = noop;
226
+ const on_play = (callback: () => void) => {
227
+ play_callback = callback;
228
+ };
229
+
230
+ let readonly = false;
231
+ let sidebar = false;
232
+ let page_index = 0;
233
+ let page_count = 0;
234
+
235
+ const $footer = h("div");
236
+ set_class($footer, "footer");
237
+
238
+ const $btnSidebar = h("button");
239
+ set_class($btnSidebar, "btn-sidebar");
240
+ $btnSidebar.classList.add(wrap_class("footer-btn"));
241
+ $btnSidebar.appendChild(sidebarSVG(namespace));
242
+ $btnSidebar.onclick = function on_click_btn_sidebar() {
243
+ if (readonly) return;
244
+ toggle_preview_callback();
245
+ };
246
+ $btnSidebar.style.display = "none";
247
+ $footer.appendChild($btnSidebar);
248
+
249
+ const $pageJumps = h("div");
250
+ set_class($pageJumps, "page-jumps");
251
+
252
+ const $btnPageBack = h("button");
253
+ set_class($btnPageBack, "btn-page-back");
254
+ $btnPageBack.classList.add(wrap_class("footer-btn"));
255
+ $btnPageBack.appendChild(arrowLeftSVG(namespace));
256
+ $btnPageBack.onclick = function on_click_btn_page_back() {
257
+ if (readonly) return;
258
+ new_page_index_callback(page_index - 1);
259
+ };
260
+ $pageJumps.appendChild($btnPageBack);
261
+
262
+ const $btnPlay = h("button");
263
+ set_class($btnPlay, "btn-page-play");
264
+ $btnPlay.classList.add(wrap_class("footer-btn"));
265
+ $btnPlay.appendChild(playSVG(namespace));
266
+ $btnPlay.appendChild(pauseSVG(namespace));
267
+ let returnPlayTimer = 0;
268
+ $btnPlay.onclick = function on_click_btn_play() {
269
+ if (readonly) return;
270
+ $btnPlay.classList.add(wrap_class("footer-btn-playing"));
271
+ play_callback();
272
+ clearTimeout(returnPlayTimer);
273
+ returnPlayTimer = setTimeout(() => {
274
+ $btnPlay.classList.remove(wrap_class("footer-btn-playing"));
275
+ }, 500);
276
+ };
277
+ $pageJumps.appendChild($btnPlay);
278
+
279
+ const $btnPageNext = h("button");
280
+ set_class($btnPageNext, "btn-page-next");
281
+ $btnPageNext.classList.add(wrap_class("footer-btn"));
282
+ $btnPageNext.appendChild(arrowRightSVG(namespace));
283
+ $btnPageNext.onclick = function on_click_btn_page_next() {
284
+ if (readonly) return;
285
+ new_page_index_callback(page_index + 1);
286
+ };
287
+ $pageJumps.appendChild($btnPageNext);
288
+
289
+ const $pageNumber = h("div");
290
+ set_class($pageNumber, "page-number");
291
+
292
+ const $pageNumberInput = h("input");
293
+ set_class($pageNumberInput, "page-number-input");
294
+ $pageNumberInput.value = String(page_index + 1);
295
+ $pageNumberInput.onfocus = function on_focus_page_number_input() {
296
+ $pageNumberInput.select();
297
+ };
298
+ $pageNumberInput.onchange = function on_change_page_number_input() {
299
+ if (readonly) return;
300
+ if ($pageNumberInput.value) {
301
+ new_page_index_callback(Number($pageNumberInput.value) - 1);
302
+ }
303
+ };
304
+
305
+ const $totalPage = h("span");
306
+ set_class($totalPage, "total-page");
307
+ $totalPage.textContent = " / ";
308
+
309
+ $pageNumber.appendChild($pageNumberInput);
310
+ $pageNumber.appendChild($totalPage);
311
+
312
+ $footer.appendChild($pageJumps);
313
+ $footer.appendChild($pageNumber);
314
+
315
+ const class_readonly = wrap_class("readonly");
316
+
317
+ function set_readonly(readonly_: boolean) {
318
+ if (readonly !== readonly_) {
319
+ readonly = readonly_;
320
+ $footer.classList.toggle(class_readonly, readonly);
321
+ $pageNumberInput.disabled = readonly;
322
+ }
323
+ }
324
+
325
+ function set_sidebar(sidebar_: boolean) {
326
+ if (sidebar !== sidebar_) {
327
+ sidebar = sidebar_;
328
+ $btnSidebar.style.display = sidebar ? "" : "none";
329
+ }
330
+ }
331
+
332
+ function set_page_index(page_index_: number) {
333
+ if (page_index !== page_index_) {
334
+ page_index = page_index_;
335
+ $pageNumberInput.value = String(page_index + 1);
336
+ }
337
+ }
338
+
339
+ function set_page_count(page_count_: number) {
340
+ if (page_count !== page_count_) {
341
+ page_count = page_count_;
342
+ $totalPage.textContent = ` / ${page_count}`;
343
+ }
344
+ }
345
+
346
+ return {
347
+ $footer,
348
+ $pageNumberInput,
349
+ set_readonly,
350
+ set_sidebar,
351
+ set_page_index,
352
+ set_page_count,
353
+ on_new_page_index,
354
+ on_toggle_preview,
355
+ on_play,
356
+ };
357
+ }
358
+
359
+ function create_slide_wrapper() {
360
+ const $slide = h("div");
361
+ set_class($slide, "slide");
362
+ return $slide;
363
+ }
364
+
365
+ function on_visibility_change(callback: (visible: boolean) => void) {
366
+ if (typeof document !== "undefined") {
367
+ const listener = () => callback(document.visibilityState === "visible");
368
+ document.addEventListener("visibilitychange", listener);
369
+ return () => document.removeEventListener("visibilitychange", listener);
370
+ }
371
+ return noop;
372
+ }
373
+
374
+ export type SlideViewerOptions = Omit<ISlideConfig, "anchor"> & SlideAttributes;
375
+
376
+ export interface SlideViewerInfoResponse {
377
+ width: number;
378
+ height: number;
379
+ slideCount: number;
380
+ }
381
+
382
+ export class SlideViewer {
383
+ static styles = styles;
384
+
385
+ private readonly sideEffect = new SideEffectManager();
386
+
387
+ readonly $slide = create_slide_wrapper();
388
+ readonly sidebar = create_sidebar();
389
+ readonly footer = create_footer();
390
+ readonly $content: HTMLElement;
391
+ readonly $footer: HTMLElement;
392
+
393
+ readonly slide;
394
+
395
+ private readonly _readyPromise: Promise<void>;
396
+ private readonly _infoPromise: Promise<SlideViewerInfoResponse>;
397
+ private _ready = false;
398
+ private _slideCount = 0;
399
+ private _destroyed = false;
400
+
401
+ constructor(options: SlideViewerOptions) {
402
+ this.$content = this.sidebar.$content;
403
+ this.$footer = this.footer.$footer;
404
+ append(this.$content, this.$slide);
405
+ append(this.$content, this.$footer);
406
+
407
+ let resolveReady: () => void;
408
+ this._readyPromise = new Promise(resolve => {
409
+ resolveReady = resolve;
410
+ });
411
+
412
+ const on_new_page_index = (index: number) => {
413
+ if (this._ready && index >= 0 && index < this._slideCount) {
414
+ this.slide.renderSlide(index + 1);
415
+ }
416
+ };
417
+ this.sidebar.on_new_page_index(on_new_page_index);
418
+ this.footer.on_new_page_index(on_new_page_index);
419
+
420
+ this.footer.on_toggle_preview(() => {
421
+ this.sidebar.set_active(!this.sidebar.get_active());
422
+ });
423
+
424
+ this.footer.on_play(() => {
425
+ this.slide.nextStep();
426
+ });
427
+
428
+ this.sideEffect.addDisposer(this.sidebar.destroy);
429
+ this.sideEffect.addDisposer(() => this.slide.destroy());
430
+
431
+ let saved_is_frozen = false;
432
+ this.sideEffect.addDisposer(
433
+ on_visibility_change(visible => {
434
+ if (this._destroyed) return;
435
+ if (!visible) {
436
+ saved_is_frozen = this._isFrozen;
437
+ this.freeze();
438
+ } else {
439
+ if (!saved_is_frozen) this.unfreeze();
440
+ }
441
+ })
442
+ );
443
+
444
+ this.slide = new Slide({ anchor: this.$slide, ...options });
445
+ this.slide.setResource(options.taskId, options.url || DefaultUrl);
446
+
447
+ let resolveFetching: (response: SlideViewerInfoResponse) => void;
448
+ this._infoPromise = new Promise<SlideViewerInfoResponse>(resolve => {
449
+ resolveFetching = resolve;
450
+ });
451
+
452
+ this.slide.on("renderEnd", () => {
453
+ if (!this._ready)
454
+ setTimeout(() => {
455
+ this._ready = true;
456
+ resolveReady();
457
+ }, 1000);
458
+ });
459
+
460
+ const fetching = fetch_slide_info(options).then(({ preview, slide }) => {
461
+ if (this._destroyed) return;
462
+
463
+ this._slideCount = slide.slideCount;
464
+
465
+ if (preview) {
466
+ const { taskId, url } = options;
467
+ const { slideCount } = slide;
468
+ const { width, height } = preview;
469
+
470
+ const prefix = make_prefix(taskId, url);
471
+ const pages = Array.from({ length: slideCount }, (_, i) => ({
472
+ width,
473
+ height,
474
+ thumbnail: `${prefix}/preview/${i + 1}.png`,
475
+ }));
476
+
477
+ this.sidebar.set_pages(pages);
478
+ this.footer.set_sidebar(true);
479
+ }
480
+
481
+ this.footer.set_page_count(slide.slideCount);
482
+ resolveFetching(slide);
483
+ });
484
+
485
+ fetching.catch(error => {
486
+ console.log("[Slide] fetch slide info error");
487
+ console.error(error);
488
+ });
489
+
490
+ this.ready(() => {
491
+ if (this._isFrozen) {
492
+ this.freeze();
493
+ }
494
+ });
495
+ }
496
+
497
+ prepare(callback: (response: SlideViewerInfoResponse) => void) {
498
+ return this._infoPromise.then(callback);
499
+ }
500
+
501
+ ready(callback: () => void) {
502
+ return this._readyPromise.then(callback);
503
+ }
504
+
505
+ destroy() {
506
+ this._destroyed = true;
507
+ this.sideEffect.flushAll();
508
+ }
509
+
510
+ setReadonly(readonly: boolean) {
511
+ this.slide.setInteractive(!readonly);
512
+ this.sidebar.set_readonly(readonly);
513
+ this.footer.set_readonly(readonly);
514
+ }
515
+
516
+ setPage(page: number) {
517
+ this.sidebar.set_page_index(page - 1);
518
+ this.footer.set_page_index(page - 1);
519
+ }
520
+
521
+ private _isFrozen = false;
522
+ private _freezePromise: Promise<void> | null = null;
523
+
524
+ freeze() {
525
+ if (this._destroyed) return;
526
+ this._isFrozen = true;
527
+ if (!this._ready || this._freezePromise) return;
528
+ this._freezePromise = this.slide.frozen().then(() => {
529
+ this._freezePromise = null;
530
+ if (!this._isFrozen) this.unfreeze();
531
+ });
532
+ }
533
+
534
+ unfreeze() {
535
+ if (this._destroyed) return;
536
+ this._isFrozen = false;
537
+ if (!this._ready || this._freezePromise) return;
538
+ this._freezePromise = this.slide.release().then(() => {
539
+ this._freezePromise = null;
540
+ if (this._isFrozen) this.freeze();
541
+ });
542
+ }
543
+ }
@@ -0,0 +1,3 @@
1
+ export const namespace = "netless-app-slide";
2
+
3
+ export const DefaultUrl = "https://convertcdn.netless.link/dynamicConvert";
File without changes
File without changes
File without changes
File without changes
File without changes