@netless/app-slide 0.1.1 → 0.1.4

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,4 +1,7 @@
1
1
  import type { SlideController } from "../SlideController";
2
+ declare type DebugMessage = {
3
+ slide: boolean | "__instance" | "__debug";
4
+ };
2
5
  declare class Logger {
3
6
  enable: boolean;
4
7
  apps: Record<string, {
@@ -10,9 +13,12 @@ declare class Logger {
10
13
  log(...args: Parameters<Console["log"]>): void;
11
14
  verbose(...args: Parameters<Console["log"]>): void;
12
15
  dispose(appId: string): void;
13
- _onMessage: (ev: MessageEvent<{
14
- slide: boolean | "__instance";
15
- }>) => void;
16
+ /**
17
+ * @example
18
+ * window.postMessage({ slide: '__debug' })
19
+ * window.dispatchEvent(new MessageEvent('message', { data: { slide: '__debug' } }))
20
+ */
21
+ _onMessage: (ev: MessageEvent<DebugMessage> | CustomEvent<DebugMessage>) => void;
16
22
  }
17
23
  export declare const logger: Logger;
18
24
  export declare const log: (...args: Parameters<Console["log"]>) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/app-slide",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "main": "dist/main.cjs.js",
5
5
  "module": "dist/main.es.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,7 +11,7 @@
11
11
  ],
12
12
  "devDependencies": {
13
13
  "@netless/app-shared": "^0.1.1",
14
- "@netless/slide": "^0.2.9",
14
+ "@netless/slide": "^0.2.10",
15
15
  "@types/color-string": "^1.5.2",
16
16
  "color-string": "^1.9.0",
17
17
  "side-effect-manager": "^0.1.5",
@@ -11,6 +11,7 @@
11
11
  import type { AppContext, Player, Room } from "@netless/window-manager";
12
12
  import type { SyncEvent } from "@netless/slide";
13
13
  import type { Attributes, MagixEvents, MagixPayload, SlideState } from "../typings";
14
+ import type { AppOptions } from "..";
14
15
 
15
16
  import { SideEffectManager } from "side-effect-manager";
16
17
  import { Slide, SLIDE_EVENTS } from "@netless/slide";
@@ -28,7 +29,7 @@ export const EmptyAttributes: Attributes = {
28
29
  };
29
30
 
30
31
  export interface SlideControllerOptions {
31
- context: AppContext<Attributes, MagixEvents>;
32
+ context: AppContext<Attributes, MagixEvents, AppOptions>;
32
33
  anchor: HTMLDivElement;
33
34
  onPageChanged: (page: number) => void;
34
35
  onTransitionStart: () => void;
@@ -55,6 +56,9 @@ export class SlideController {
55
56
 
56
57
  private syncStateOnceFlag: boolean;
57
58
 
59
+ private visible: boolean;
60
+ private savedIsFrozen: boolean;
61
+
58
62
  public constructor({
59
63
  context,
60
64
  anchor,
@@ -73,6 +77,8 @@ export class SlideController {
73
77
  this.slide = this.createSlide(anchor);
74
78
  // the adder does not need to sync state
75
79
  this.syncStateOnceFlag = !this.context.isAddApp;
80
+ this.visible = document.visibilityState === "visible";
81
+ this.savedIsFrozen = false;
76
82
  this.initialize();
77
83
  }
78
84
 
@@ -152,6 +158,11 @@ export class SlideController {
152
158
  slide.on(SLIDE_EVENTS.syncDispatch, this.onSyncDispatch);
153
159
 
154
160
  slide.on(SLIDE_EVENTS.renderEnd, this.resolveReady);
161
+
162
+ this.sideEffect.add(() => {
163
+ document.addEventListener("visibilitychange", this.onVisibilityChange);
164
+ return () => document.removeEventListener("visibilitychange", this.onVisibilityChange);
165
+ });
155
166
  }
156
167
 
157
168
  private onSyncDispatch = (event: SyncEvent) => {
@@ -236,10 +247,10 @@ export class SlideController {
236
247
  controller: logger.enable,
237
248
  enableGlobalClick: true,
238
249
  renderOptions: {
239
- minFPS: 25,
240
- maxFPS: 30,
250
+ minFPS: this.context.getAppOptions()?.minFPS || 25,
251
+ maxFPS: this.context.getAppOptions()?.maxFPS || 30,
241
252
  autoFPS: true,
242
- autoResolution: true,
253
+ autoResolution: this.context.getAppOptions()?.autoResolution ?? true,
243
254
  resolution: this.context.getAppOptions()?.resolution,
244
255
  transactionBgColor: this.context.getAppOptions()?.bgColor || cachedGetBgColor(anchor),
245
256
  },
@@ -308,6 +319,7 @@ export class SlideController {
308
319
  };
309
320
 
310
321
  public unfreeze = async () => {
322
+ if (!this.visible) return;
311
323
  if (this.ready) {
312
324
  log("[Slide] unfreeze", this.context.appId);
313
325
  if (this.freezePromise) {
@@ -320,4 +332,17 @@ export class SlideController {
320
332
  this._toFreeze = -1;
321
333
  }
322
334
  };
335
+
336
+ private onVisibilityChange = async () => {
337
+ if (!(this.visible = document.visibilityState === "visible")) {
338
+ this.savedIsFrozen = this.freezePromise ? this._toFreeze === 1 : this.isFrozen;
339
+ log("[Slide] freeze because tab becomes invisible");
340
+ this.freeze();
341
+ } else {
342
+ log("[Slide] unfreeze because tab becomes visible", { savedIsFrozen: this.savedIsFrozen });
343
+ if (!this.savedIsFrozen) {
344
+ this.unfreeze();
345
+ }
346
+ }
347
+ };
323
348
  }
package/src/index.ts CHANGED
@@ -27,9 +27,18 @@ export const version = __APP_VERSION__;
27
27
  export { DefaultUrl, apps, FreezerLength, addHooks };
28
28
 
29
29
  export interface AppOptions {
30
+ /** show debug controller */
30
31
  debug?: boolean;
32
+ /** scale */
31
33
  resolution?: number;
34
+ /** background color for slide animations */
32
35
  bgColor?: string;
36
+ /** minimal fps @default 25 */
37
+ minFPS?: number;
38
+ /** maximal fps @default 30 */
39
+ maxFPS?: number;
40
+ /** whether to re-scale automatically @default true */
41
+ autoResolution?: boolean;
33
42
  }
34
43
 
35
44
  export interface Controller {
@@ -1,6 +1,8 @@
1
1
  import type { SlideController } from "../SlideController";
2
2
  import { isObj } from "./helpers";
3
3
 
4
+ type DebugMessage = { slide: boolean | "__instance" | "__debug" };
5
+
4
6
  class Logger {
5
7
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
8
  public apps: Record<string, { context?: any; controller?: SlideController }> = {};
@@ -23,12 +25,28 @@ class Logger {
23
25
  delete this.apps[appId];
24
26
  window.removeEventListener("message", this._onMessage);
25
27
  }
26
- _onMessage = (ev: MessageEvent<{ slide: boolean | "__instance" }>) => {
27
- if (isObj(ev.data)) {
28
- if (typeof ev.data.slide === "boolean") {
29
- this.enable = ev.data.slide;
30
- } else if (ev.data.slide === "__instance") {
28
+ /**
29
+ * @example
30
+ * window.postMessage({ slide: '__debug' })
31
+ * window.dispatchEvent(new MessageEvent('message', { data: { slide: '__debug' } }))
32
+ */
33
+ _onMessage = (ev: MessageEvent<DebugMessage> | CustomEvent<DebugMessage>) => {
34
+ let data: DebugMessage | undefined;
35
+ if (ev instanceof CustomEvent) {
36
+ data = ev.detail;
37
+ } else if (isObj(ev.data)) {
38
+ data = ev.data;
39
+ }
40
+ if (data) {
41
+ if (typeof data.slide === "boolean") {
42
+ this.enable = data.slide;
43
+ } else if (data.slide === "__instance") {
31
44
  console.log(this);
45
+ } else if (data.slide === "__debug") {
46
+ Object.values(this.apps).forEach(app => {
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
+ (app.controller?.slide as any)?.createController();
49
+ });
32
50
  }
33
51
  }
34
52
  };