@netless/app-slide 0.0.56 → 0.1.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/typings.d.ts CHANGED
@@ -12,3 +12,8 @@ export declare type MagixPayload = {
12
12
  type: typeof SLIDE_EVENTS.syncDispatch;
13
13
  payload: SyncEvent;
14
14
  };
15
+ export declare type MagixEvents = {
16
+ [SLIDE_EVENTS.syncDispatch]: MagixPayload;
17
+ };
18
+ export interface A {
19
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netless/app-slide",
3
- "version": "0.0.56",
3
+ "version": "0.1.0",
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.3",
14
+ "@netless/slide": "^0.2.7",
15
15
  "@types/color-string": "^1.5.2",
16
16
  "color-string": "^1.9.0",
17
17
  "side-effect-manager": "^0.1.5",
@@ -8,14 +8,13 @@
8
8
  // 4. automatically re-create scenes to sync strokes, a view must be existing
9
9
  // 5. pages information are loaded dynamically by the slide package
10
10
 
11
- import type { Event as MagixEvent } from "white-web-sdk";
12
11
  import type { AppContext, Player, Room } from "@netless/window-manager";
13
12
  import type { SyncEvent } from "@netless/slide";
14
- import type { Attributes, MagixPayload, SlideState } from "../typings";
13
+ import type { Attributes, MagixEvents, MagixPayload, SlideState } from "../typings";
15
14
 
16
15
  import { SideEffectManager } from "side-effect-manager";
17
16
  import { Slide, SLIDE_EVENTS } from "@netless/slide";
18
- import { clamp, deepClone, isObj } from "../utils/helpers";
17
+ import { clamp, deepClone } from "../utils/helpers";
19
18
  import { cachedGetBgColor } from "../utils/bgcolor";
20
19
  import { logger, log, verbose } from "../utils/logger";
21
20
  export { syncSceneWithSlide, createDocsViewerPages } from "./helpers";
@@ -29,7 +28,7 @@ export const EmptyAttributes: Attributes = {
29
28
  };
30
29
 
31
30
  export interface SlideControllerOptions {
32
- context: AppContext<Attributes>;
31
+ context: AppContext<Attributes, MagixEvents>;
33
32
  anchor: HTMLDivElement;
34
33
  onPageChanged: (page: number) => void;
35
34
  onTransitionStart: () => void;
@@ -37,11 +36,14 @@ export interface SlideControllerOptions {
37
36
  onError: (args: { error: Error }) => void;
38
37
  }
39
38
 
39
+ type MagixEventListener = Parameters<
40
+ AppContext<Attributes, MagixEvents>["addMagixEventListener"]
41
+ >[1];
42
+
40
43
  export class SlideController {
41
44
  public readonly context: SlideControllerOptions["context"];
42
45
  public readonly slide: Slide;
43
46
 
44
- private readonly channel: string;
45
47
  private readonly room?: Room;
46
48
  private readonly player?: Player;
47
49
  private readonly sideEffect = new SideEffectManager();
@@ -66,7 +68,6 @@ export class SlideController {
66
68
  this.onTransitionEnd = onTransitionEnd;
67
69
  this.onError = onError;
68
70
  this.context = context;
69
- this.channel = `channel-${context.appId}`;
70
71
  this.room = context.getRoom();
71
72
  this.player = this.room ? undefined : (context.getDisplayer() as Player);
72
73
  this.slide = this.createSlide(anchor);
@@ -137,20 +138,11 @@ export class SlideController {
137
138
  return disposer;
138
139
  });
139
140
 
140
- this.sideEffect.add(() => {
141
- context.emitter.on("seek", this.onSeeked);
142
- return () => context.emitter.off("seek", this.onSeeked);
143
- });
144
-
145
- this.sideEffect.add(() => {
146
- const displayer = context.getDisplayer();
147
- displayer.addMagixEventListener(this.channel, this.magixEventListener, {
141
+ this.sideEffect.add(() =>
142
+ context.addMagixEventListener(SLIDE_EVENTS.syncDispatch, this.magixEventListener, {
148
143
  fireSelfEventAfterCommit: true,
149
- });
150
- // here we do not pass second param -- the listener
151
- // because channel name is already unique, just make it simpler
152
- return () => displayer.removeMagixEventListener(this.channel);
153
- });
144
+ })
145
+ );
154
146
 
155
147
  slide.on(SLIDE_EVENTS.slideChange, this.onPageChanged);
156
148
  slide.on(SLIDE_EVENTS.renderStart, this.onTransitionStart);
@@ -171,25 +163,23 @@ export class SlideController {
171
163
  payload: event,
172
164
  };
173
165
  log("[Slide] dispatch", event);
174
- this.room.dispatchMagixEvent(this.channel, payload);
166
+ this.context.dispatchMagixEvent(SLIDE_EVENTS.syncDispatch, payload);
175
167
  }
176
168
  };
177
169
 
178
- private magixEventListener = (ev: MagixEvent) => {
179
- if (ev.event === this.channel && isObj(ev.payload)) {
180
- const { type, payload } = ev.payload as MagixPayload;
181
- if (type === SLIDE_EVENTS.syncDispatch) {
182
- this.syncStateOnce();
183
- log("[Slide] receive", payload);
184
- this.slide.emit(SLIDE_EVENTS.syncReceive, payload);
185
- }
170
+ private magixEventListener: MagixEventListener = ev => {
171
+ const { type, payload } = ev.payload;
172
+ if (type === SLIDE_EVENTS.syncDispatch) {
173
+ this.syncStateOnce();
174
+ log("[Slide] receive", payload);
175
+ this.slide.emit(SLIDE_EVENTS.syncReceive, payload);
186
176
  }
187
177
  };
188
178
 
189
179
  private syncStateOnce() {
190
180
  // sync state before the first event, so that they can be in the correct order
191
181
  if (this.syncStateOnceFlag) {
192
- const { state } = { ...EmptyAttributes, ...this.context.getAttributes() };
182
+ const { state } = { ...EmptyAttributes, ...this.context.storage.state };
193
183
  if (state) {
194
184
  log("[Slide] sync with state (once)", deepClone(state));
195
185
  this.slide.setSlideState(deepClone(state));
@@ -201,15 +191,7 @@ export class SlideController {
201
191
  private onStateChange = (state: SlideState) => {
202
192
  if (this.context.getIsWritable()) {
203
193
  verbose("[Slide] state change", JSON.stringify(state, null, 2));
204
- this.context.updateAttributes(["state"], state);
205
- }
206
- };
207
-
208
- private onSeeked = () => {
209
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
210
- const state = this.context.getAttributes()!.state;
211
- if (state) {
212
- this.slide.setSlideState(deepClone(state));
194
+ this.context.storage.setState({ state });
213
195
  }
214
196
  };
215
197
 
package/src/index.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  import type { NetlessApp } from "@netless/window-manager";
2
2
  import type { RoomState } from "white-web-sdk";
3
+ import type { Slide } from "@netless/slide";
3
4
  import type { MountSlideOptions } from "./SlideDocsViewer";
4
- import type { Attributes } from "./typings";
5
+ import type { Attributes, MagixEvents } from "./typings";
5
6
  import type { AddHooks, FreezableSlide } from "./utils/freezer";
6
- import { useFreezer } from "./utils/freezer";
7
7
 
8
8
  import { SideEffectManager } from "side-effect-manager";
9
- import { ensureAttributes } from "@netless/app-shared";
10
9
  import {
11
10
  DefaultUrl,
12
11
  EmptyAttributes,
@@ -14,7 +13,7 @@ import {
14
13
  SlideController,
15
14
  } from "./SlideController";
16
15
  import { SlideDocsViewer } from "./SlideDocsViewer";
17
- import { apps, FreezerLength, addHooks } from "./utils/freezer";
16
+ import { apps, FreezerLength, addHooks, useFreezer } from "./utils/freezer";
18
17
  import { log, logger } from "./utils/logger";
19
18
  import styles from "./style.scss?inline";
20
19
 
@@ -27,17 +26,31 @@ export const version = __APP_VERSION__;
27
26
 
28
27
  export { DefaultUrl, apps, FreezerLength, addHooks };
29
28
 
30
- const SlideApp: NetlessApp<Attributes> = {
29
+ export interface AppOptions {
30
+ debug?: boolean;
31
+ resolution?: number;
32
+ bgColor?: string;
33
+ }
34
+
35
+ export interface Controller {
36
+ slide: () => Slide | undefined;
37
+ position: () => [page: number, pageCount: number] | undefined;
38
+ nextStep: () => boolean;
39
+ prevStep: () => boolean;
40
+ nextPage: () => boolean;
41
+ prevPage: () => boolean;
42
+ }
43
+
44
+ const SlideApp: NetlessApp<Attributes, MagixEvents, AppOptions, Controller> = {
31
45
  kind: "Slide",
32
46
  setup(context) {
33
47
  console.log("[Slide] setup @ " + version);
34
48
 
35
49
  if (context.getIsWritable()) {
36
- ensureAttributes(context, EmptyAttributes);
50
+ context.storage.ensureState(EmptyAttributes);
37
51
  }
38
52
 
39
- const attributes = context.getAttributes();
40
- if (!attributes?.taskId) {
53
+ if (!context.storage.state.taskId) {
41
54
  throw new Error("[Slide] no taskId");
42
55
  }
43
56
 
@@ -143,6 +156,54 @@ const SlideApp: NetlessApp<Attributes> = {
143
156
  });
144
157
 
145
158
  docsViewer.mount();
159
+
160
+ return {
161
+ slide: () => {
162
+ return docsViewer?.slideController?.slide;
163
+ },
164
+ nextStep: () => {
165
+ if (docsViewer && docsViewer.slideController) {
166
+ docsViewer?.slideController?.slide.nextStep();
167
+ return true;
168
+ }
169
+ return false;
170
+ },
171
+ prevStep: () => {
172
+ if (docsViewer && docsViewer.slideController) {
173
+ docsViewer?.slideController?.slide.prevStep();
174
+ return true;
175
+ }
176
+ return false;
177
+ },
178
+ position: () => {
179
+ const controller = docsViewer?.slideController;
180
+ if (controller) {
181
+ return [controller.page, controller.pageCount] as [page: number, pageCount: number];
182
+ }
183
+ },
184
+ nextPage: () => {
185
+ const controller = docsViewer?.slideController;
186
+ if (controller) {
187
+ const { page, pageCount } = controller;
188
+ if (pageCount > 0 && page < pageCount) {
189
+ controller.jumpToPage(page + 1);
190
+ return true;
191
+ }
192
+ }
193
+ return false;
194
+ },
195
+ prevPage: () => {
196
+ const controller = docsViewer?.slideController;
197
+ if (controller) {
198
+ const { page, pageCount } = controller;
199
+ if (pageCount > 0 && page > 1) {
200
+ controller.jumpToPage(page - 1);
201
+ return true;
202
+ }
203
+ }
204
+ return false;
205
+ },
206
+ };
146
207
  },
147
208
  };
148
209
 
package/src/typings.ts CHANGED
@@ -15,3 +15,9 @@ export type MagixPayload = {
15
15
  type: typeof SLIDE_EVENTS.syncDispatch;
16
16
  payload: SyncEvent;
17
17
  };
18
+
19
+ export type MagixEvents = {
20
+ [SLIDE_EVENTS.syncDispatch]: MagixPayload;
21
+ };
22
+
23
+ export interface A {}