@netless/app-slide 0.2.17 → 0.2.19

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.
@@ -4,7 +4,10 @@ export interface FreezableSlide {
4
4
  unfreeze: () => void;
5
5
  }
6
6
  export declare let useFreezer: boolean;
7
- export declare const FreezerLength = 2;
7
+ export declare let FreezerLength: number;
8
+ export declare function getFreezerLength(): number;
9
+ /** @param length - must be >= 1, default is 2 */
10
+ export declare function setFreezerLength(length: number): void;
8
11
  export declare const apps: {
9
12
  map: Map<string, FreezableSlide>;
10
13
  boxes: Map<string, ReadonlyTeleBox>;
@@ -14,10 +17,12 @@ export declare const apps: {
14
17
  delete(appId: string): void;
15
18
  focus(appId: string): void;
16
19
  };
20
+ export declare function onCreated(callback: (appId: string) => void): () => boolean;
21
+ export declare function onDestroyed(callback: (appId: string) => void): () => boolean;
17
22
  export declare type AddHooks = NonNullable<RegisterParams["addHooks"]>;
18
23
  /**
19
24
  * Put this function in your register code:
20
- * `WindowManager.register({ addHooks })`
25
+ * `WindowManager.register({ kind: 'Slide', src: SlideApp, addHooks })`
21
26
  * So that it will automatically freeze the app when it is not in focus.
22
27
  */
23
28
  export declare const addHooks: AddHooks;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/app-slide",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "main": "dist/main.cjs.js",
5
5
  "module": "dist/main.es.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,7 +10,7 @@
10
10
  "README-zh.md"
11
11
  ],
12
12
  "devDependencies": {
13
- "@netless/slide": "^0.7.7",
13
+ "@netless/slide": "^0.8.0",
14
14
  "@types/color-string": "^1.5.2",
15
15
  "color-string": "^1.9.1",
16
16
  "side-effect-manager": "^1.2.1",
@@ -35,7 +35,9 @@ export interface SlideControllerOptions {
35
35
  onPageChanged: (page: number) => void;
36
36
  onTransitionStart: () => void;
37
37
  onTransitionEnd: () => void;
38
- onError: (args: { error: Error }) => void;
38
+ onError: (args: { error: Error; index: number }) => void;
39
+ onRenderError?: (error: Error, pageIndex: number) => void;
40
+ showRenderError?: boolean;
39
41
  }
40
42
 
41
43
  type MagixEventListener = Parameters<
@@ -45,6 +47,8 @@ type MagixEventListener = Parameters<
45
47
  export class SlideController {
46
48
  public readonly context: SlideControllerOptions["context"];
47
49
  public readonly slide: Slide;
50
+ public readonly showRenderError: boolean;
51
+ public readonly onRenderError?: (error: Error, pageIndex: number) => void;
48
52
 
49
53
  private readonly room?: Room;
50
54
  private readonly player?: Player;
@@ -67,11 +71,15 @@ export class SlideController {
67
71
  onTransitionStart,
68
72
  onTransitionEnd,
69
73
  onError,
74
+ onRenderError,
75
+ showRenderError,
70
76
  }: SlideControllerOptions) {
71
77
  this.onPageChanged = onPageChanged;
72
78
  this.onTransitionStart = onTransitionStart;
73
79
  this.onTransitionEnd = onTransitionEnd;
74
80
  this.onError = onError;
81
+ this.onRenderError = onRenderError;
82
+ this.showRenderError = showRenderError ?? true;
75
83
 
76
84
  this.context = context;
77
85
  this.room = context.getRoom();
@@ -263,6 +271,8 @@ export class SlideController {
263
271
  resolution: options.resolution,
264
272
  transactionBgColor: options.bgColor || cachedGetBgColor(anchor),
265
273
  maxResolutionLevel: options.maxResolutionLevel,
274
+ forceCanvas: options.forceCanvas,
275
+ enableNvidiaDetect: options.enableNvidiaDetect,
266
276
  },
267
277
  fixedFrameSize: options.fixedFrameSize,
268
278
  loaderDelegate: options.loaderDelegate,
@@ -130,10 +130,15 @@ export class SlideDocsViewer {
130
130
  return this;
131
131
  }
132
132
 
133
- protected onError = ({ error }: { error: Error }) => {
133
+ protected onError = ({ error, index }: { error: Error; index: number }) => {
134
134
  this.viewer.setPaused();
135
- this.$overlay.textContent = `Error on slide[page=${this.slideController?.page}]: ${error.message}`;
136
- this.$overlay.style.opacity = "1";
135
+ if (this.slideController?.showRenderError) {
136
+ this.$overlay.textContent = `Error on slide[page=${this.slideController.page}]: ${error.message}`;
137
+ this.$overlay.style.opacity = "1";
138
+ }
139
+ if (this.slideController?.onRenderError) {
140
+ this.slideController.onRenderError(error, index);
141
+ }
137
142
  logger.warn("[Slide] render error", error);
138
143
  };
139
144
 
@@ -20,6 +20,7 @@ $namespace: "netless-app-slide";
20
20
  left: 0;
21
21
  width: 100%;
22
22
  height: 100%;
23
+ padding: 8px;
23
24
  background: rgba(255, 0, 0, 0.25);
24
25
  transition: opacity 0.3s;
25
26
  opacity: 0;
package/src/index.ts CHANGED
@@ -30,6 +30,8 @@ export const version = __APP_VERSION__;
30
30
 
31
31
  export { DefaultUrl, apps, FreezerLength, addHooks };
32
32
 
33
+ export { setFreezerLength, getFreezerLength, onCreated, onDestroyed } from "./utils/freezer";
34
+
33
35
  export interface AppOptions
34
36
  extends Pick<
35
37
  ISlideConfig,
@@ -57,6 +59,14 @@ export interface AppOptions
57
59
  autoResolution?: boolean;
58
60
  /** 1~4, default: 3 */
59
61
  maxResolutionLevel?: number;
62
+ /** use canvas2d mode, downside: some 3d effects are lost */
63
+ forceCanvas?: boolean;
64
+ /** fix windows 11 nvidia rendering bug, downside: render next page slows down */
65
+ enableNvidiaDetect?: boolean;
66
+ /** custom error handler */
67
+ onRenderError?: (error: Error, pageIndex: number) => void;
68
+ /** whether to show an overlay of error message @default: true */
69
+ showRenderError?: boolean;
60
70
  }
61
71
 
62
72
  export interface ILogger {
@@ -65,7 +75,9 @@ export interface ILogger {
65
75
  warn?(msg: string): void;
66
76
  }
67
77
 
68
- export interface Controller {
78
+ export interface AppResult {
79
+ viewer: () => SlideDocsViewer | null;
80
+ controller: () => SlideController | null | undefined;
69
81
  slide: () => Slide | undefined;
70
82
  position: () => [page: number, pageCount: number] | undefined;
71
83
  nextStep: () => boolean;
@@ -75,7 +87,7 @@ export interface Controller {
75
87
  jumpToPage: (page: number) => boolean;
76
88
  }
77
89
 
78
- const SlideApp: NetlessApp<Attributes, MagixEvents, AppOptions, Controller> = {
90
+ const SlideApp: NetlessApp<Attributes, MagixEvents, AppOptions, AppResult> = {
79
91
  kind: "Slide",
80
92
  setup(context) {
81
93
  console.log("[Slide] setup @ " + version);
@@ -121,10 +133,14 @@ const SlideApp: NetlessApp<Attributes, MagixEvents, AppOptions, Controller> = {
121
133
  };
122
134
 
123
135
  const mountSlideController = (options: MountSlideOptions): SlideController => {
136
+ const appOptions = context.getAppOptions() || {};
137
+
124
138
  const slideController = new SlideController({
125
139
  context,
126
140
  ...options,
127
141
  onPageChanged,
142
+ onRenderError: appOptions.onRenderError,
143
+ showRenderError: appOptions.showRenderError,
128
144
  });
129
145
  if (useFreezer) apps.set(context.appId, slideController, box);
130
146
  logger.setAppController(context.appId, slideController);
@@ -194,6 +210,12 @@ const SlideApp: NetlessApp<Attributes, MagixEvents, AppOptions, Controller> = {
194
210
  docsViewer.mount();
195
211
 
196
212
  return {
213
+ viewer: () => {
214
+ return docsViewer;
215
+ },
216
+ controller: () => {
217
+ return docsViewer?.slideController;
218
+ },
197
219
  slide: () => {
198
220
  return docsViewer?.slideController?.slide;
199
221
  },
@@ -7,7 +7,16 @@ export interface FreezableSlide {
7
7
  }
8
8
 
9
9
  export let useFreezer = false;
10
- export const FreezerLength = 2;
10
+ export let FreezerLength = 2;
11
+
12
+ export function getFreezerLength() {
13
+ return FreezerLength;
14
+ }
15
+
16
+ /** @param length - must be >= 1, default is 2 */
17
+ export function setFreezerLength(length: number) {
18
+ FreezerLength = length < 1 ? Infinity : length;
19
+ }
11
20
 
12
21
  const inspect = (arr: string[]) => {
13
22
  return "[" + arr + "]";
@@ -69,16 +78,39 @@ if (import.meta.env.DEV) {
69
78
  (window as any).freezer = apps;
70
79
  }
71
80
 
81
+ const on_created_callbacks = new Set<(appId: string) => void>();
82
+
83
+ export function onCreated(callback: (appId: string) => void) {
84
+ on_created_callbacks.add(callback);
85
+ return () => on_created_callbacks.delete(callback);
86
+ }
87
+
88
+ const on_destroyed_callbacks = new Set<(appId: string) => void>();
89
+
90
+ export function onDestroyed(callback: (appId: string) => void) {
91
+ on_destroyed_callbacks.add(callback);
92
+ return () => on_destroyed_callbacks.delete(callback);
93
+ }
94
+
72
95
  export type AddHooks = NonNullable<RegisterParams["addHooks"]>;
73
96
 
74
97
  /**
75
98
  * Put this function in your register code:
76
- * `WindowManager.register({ addHooks })`
99
+ * `WindowManager.register({ kind: 'Slide', src: SlideApp, addHooks })`
77
100
  * So that it will automatically freeze the app when it is not in focus.
78
101
  */
79
102
  export const addHooks: AddHooks = emitter => {
80
103
  useFreezer = true;
104
+
81
105
  emitter.on("focus", ({ appId }) => {
82
106
  apps.focus(appId);
83
107
  });
108
+
109
+ emitter.on("created", ({ appId }) => {
110
+ on_created_callbacks.forEach(callback => callback(appId));
111
+ });
112
+
113
+ emitter.on("destroy", ({ appId }) => {
114
+ on_destroyed_callbacks.forEach(callback => callback(appId));
115
+ });
84
116
  };