@netless/app-slide 0.2.2 → 0.3.0-canary.2
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/README-zh.md +1 -4
- package/README.md +1 -4
- package/dist/Refrigerator.d.ts +13 -0
- package/dist/SlideViewer.d.ts +66 -0
- package/dist/constants.d.ts +2 -0
- package/dist/{DocsViewer/icons → icons}/arrow-left.d.ts +0 -0
- package/dist/{DocsViewer/icons → icons}/arrow-right.d.ts +0 -0
- package/dist/{DocsViewer/icons → icons}/pause.d.ts +0 -0
- package/dist/{DocsViewer/icons → icons}/play.d.ts +0 -0
- package/dist/{DocsViewer/icons → icons}/sidebar.d.ts +0 -0
- package/dist/index.d.ts +10 -35
- package/dist/main.cjs.js +177 -177
- package/dist/main.cjs.js.map +1 -1
- package/dist/main.es.js +1918 -2478
- package/dist/main.es.js.map +1 -1
- package/dist/main.iife.js +254 -254
- package/dist/main.iife.js.map +1 -1
- package/dist/typings.d.ts +21 -9
- package/dist/utils.d.ts +1 -0
- package/package.json +2 -2
- package/src/Refrigerator.ts +66 -0
- package/src/SlideViewer.ts +557 -0
- package/src/constants.ts +3 -0
- package/src/fancy-scrollbar.scss +57 -0
- package/src/{DocsViewer/icons → icons}/arrow-left.ts +0 -0
- package/src/{DocsViewer/icons → icons}/arrow-right.ts +0 -0
- package/src/{DocsViewer/icons → icons}/pause.ts +0 -0
- package/src/{DocsViewer/icons → icons}/play.ts +0 -0
- package/src/{DocsViewer/icons → icons}/sidebar.ts +0 -0
- package/src/index.ts +216 -205
- package/src/style.scss +247 -5
- package/src/typings.ts +23 -10
- package/src/utils.ts +3 -0
- package/dist/DocsViewer/index.d.ts +0 -53
- package/dist/SlideController/helpers.d.ts +0 -6
- package/dist/SlideController/index.d.ts +0 -60
- package/dist/SlideDocsViewer/index.d.ts +0 -45
- package/dist/SlidePreviewer/index.d.ts +0 -52
- package/dist/utils/bgcolor.d.ts +0 -3
- package/dist/utils/freezer.d.ts +0 -22
- package/dist/utils/helpers.d.ts +0 -6
- package/dist/utils/logger.d.ts +0 -39
- package/src/DocsViewer/icons/arrow-left.svg +0 -4
- package/src/DocsViewer/icons/arrow-right.svg +0 -4
- package/src/DocsViewer/icons/pause.svg +0 -4
- package/src/DocsViewer/icons/play.svg +0 -4
- package/src/DocsViewer/icons/sidebar.svg +0 -4
- package/src/DocsViewer/index.ts +0 -368
- package/src/DocsViewer/style.scss +0 -228
- package/src/DocsViewer/variables.scss +0 -1
- package/src/SlideController/helpers.ts +0 -48
- package/src/SlideController/index.ts +0 -356
- package/src/SlideDocsViewer/index.ts +0 -210
- package/src/SlideDocsViewer/style.scss +0 -11
- package/src/SlidePreviewer/index.ts +0 -226
- package/src/utils/bgcolor.ts +0 -45
- package/src/utils/freezer.ts +0 -75
- package/src/utils/helpers.ts +0 -26
- package/src/utils/logger.ts +0 -106
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
$namespace: "netless-app-slide";
|
|
2
|
+
|
|
3
|
+
$scrollbar-size: 8px;
|
|
4
|
+
$scrollbar-ff-width: auto; // FF-only accepts auto, thin, none
|
|
5
|
+
$scrollbar-minlength: 50px; // Minimum length of scrollbar thumb
|
|
6
|
+
$scrollbar-track-color: transparent;
|
|
7
|
+
$scrollbar-color: rgba(68, 78, 96, 0.1);
|
|
8
|
+
$scrollbar-color-hover: rgba(68, 78, 96, 0.2);
|
|
9
|
+
$scrollbar-color-active: rgba(68, 78, 96, 0.2);
|
|
10
|
+
|
|
11
|
+
.#{$namespace}-tele-fancy-scrollbar {
|
|
12
|
+
overscroll-behavior: contain;
|
|
13
|
+
overflow: auto;
|
|
14
|
+
overflow-y: scroll;
|
|
15
|
+
overflow-y: overlay; // for webkit
|
|
16
|
+
-webkit-overflow-scrolling: touch;
|
|
17
|
+
-ms-overflow-style: -ms-autohiding-scrollbar;
|
|
18
|
+
scrollbar-width: $scrollbar-ff-width;
|
|
19
|
+
// Firefox has incorrect track color
|
|
20
|
+
// scrollbar-color: $scrollbar-color $scrollbar-track-color;
|
|
21
|
+
|
|
22
|
+
&::-webkit-scrollbar {
|
|
23
|
+
height: $scrollbar-size;
|
|
24
|
+
width: $scrollbar-size;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&::-webkit-scrollbar-track {
|
|
28
|
+
background-color: $scrollbar-track-color;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&::-webkit-scrollbar-thumb {
|
|
32
|
+
background-color: $scrollbar-color;
|
|
33
|
+
background-color: $scrollbar-track-color;
|
|
34
|
+
border-radius: $scrollbar-size * 0.5;
|
|
35
|
+
transition: background-color 0.4s;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&:hover::-webkit-scrollbar-thumb {
|
|
39
|
+
background-color: $scrollbar-color;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&::-webkit-scrollbar-thumb:hover {
|
|
43
|
+
background-color: $scrollbar-color-hover;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&::-webkit-scrollbar-thumb:active {
|
|
47
|
+
background-color: $scrollbar-color-active;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&::-webkit-scrollbar-thumb:vertical {
|
|
51
|
+
min-height: $scrollbar-minlength;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&::-webkit-scrollbar-thumb:horizontal {
|
|
55
|
+
min-width: $scrollbar-minlength;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/index.ts
CHANGED
|
@@ -1,234 +1,245 @@
|
|
|
1
|
-
import type { NetlessApp } from "@netless/window-manager";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type { MountSlideOptions } from "./SlideDocsViewer";
|
|
5
|
-
import type { Attributes, MagixEvents } from "./typings";
|
|
6
|
-
import type { AddHooks, FreezableSlide } from "./utils/freezer";
|
|
1
|
+
import type { AppContext, NetlessApp, Player, WhiteBoardView } from "@netless/window-manager";
|
|
2
|
+
import type { AddHooks, AppOptions, Attributes, MagixEvents, SlideState } from "./typings";
|
|
3
|
+
import type { SlideViewerOptions } from "./SlideViewer";
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
DefaultUrl,
|
|
11
|
-
EmptyAttributes,
|
|
12
|
-
syncSceneWithSlide,
|
|
13
|
-
SlideController,
|
|
14
|
-
} from "./SlideController";
|
|
15
|
-
import { SlideDocsViewer } from "./SlideDocsViewer";
|
|
16
|
-
import { apps, FreezerLength, addHooks, useFreezer } from "./utils/freezer";
|
|
17
|
-
import { log, logger } from "./utils/logger";
|
|
18
|
-
import styles from "./style.scss?inline";
|
|
19
|
-
|
|
20
|
-
export type { PreviewParams } from "./SlidePreviewer";
|
|
21
|
-
export { SlidePreviewer, default as previewSlide } from "./SlidePreviewer";
|
|
22
|
-
|
|
23
|
-
export type { Attributes, AddHooks, FreezableSlide };
|
|
5
|
+
export type { SlideState, AddHooks, AppOptions, Attributes, MagixEvents, SlideViewerOptions };
|
|
24
6
|
|
|
25
|
-
|
|
7
|
+
import ColorString from "color-string";
|
|
8
|
+
import { SideEffectManager } from "side-effect-manager";
|
|
9
|
+
import { SlideViewer } from "./SlideViewer";
|
|
10
|
+
import { refrigerator, addHooks } from "./Refrigerator";
|
|
26
11
|
|
|
27
|
-
export {
|
|
28
|
-
|
|
29
|
-
export interface AppOptions {
|
|
30
|
-
/** show debug controller */
|
|
31
|
-
debug?: boolean;
|
|
32
|
-
/** scale */
|
|
33
|
-
resolution?: number;
|
|
34
|
-
/** background color for slide animations */
|
|
35
|
-
bgColor?: string;
|
|
36
|
-
/** minimal fps @default 25 */
|
|
37
|
-
minFPS?: number;
|
|
38
|
-
/** maximal fps @default 30 */
|
|
39
|
-
maxFPS?: number;
|
|
40
|
-
/** automatically decrease fps @default true */
|
|
41
|
-
autoFPS?: boolean;
|
|
42
|
-
/** whether to re-scale automatically @default true */
|
|
43
|
-
autoResolution?: boolean;
|
|
44
|
-
}
|
|
12
|
+
export { SlideViewer, refrigerator, addHooks };
|
|
45
13
|
|
|
46
|
-
export
|
|
47
|
-
slide: () => Slide | undefined;
|
|
48
|
-
position: () => [page: number, pageCount: number] | undefined;
|
|
49
|
-
nextStep: () => boolean;
|
|
50
|
-
prevStep: () => boolean;
|
|
51
|
-
nextPage: () => boolean;
|
|
52
|
-
prevPage: () => boolean;
|
|
53
|
-
jumpToPage: (page: number) => boolean;
|
|
54
|
-
}
|
|
14
|
+
export const version = __APP_VERSION__;
|
|
55
15
|
|
|
56
|
-
const SlideApp: NetlessApp<Attributes, MagixEvents, AppOptions,
|
|
16
|
+
const SlideApp: NetlessApp<Attributes, MagixEvents, AppOptions, void> = {
|
|
57
17
|
kind: "Slide",
|
|
58
18
|
setup(context) {
|
|
59
|
-
console.log("[Slide] setup @ " +
|
|
60
|
-
|
|
61
|
-
if (context.getIsWritable()) {
|
|
62
|
-
context.storage.ensureState(EmptyAttributes);
|
|
63
|
-
}
|
|
19
|
+
console.log("[Slide] setup @ " + __APP_VERSION__);
|
|
64
20
|
|
|
65
21
|
if (!context.storage.state.taskId) {
|
|
66
22
|
throw new Error("[Slide] no taskId");
|
|
67
23
|
}
|
|
68
24
|
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
view.disableCameraTransform = true;
|
|
74
|
-
|
|
75
|
-
const box = context.getBox();
|
|
76
|
-
box.mountStyles(styles);
|
|
77
|
-
try {
|
|
78
|
-
box.$content.dataset.appSlideVersion = version;
|
|
79
|
-
} catch {
|
|
80
|
-
// ignore
|
|
81
|
-
}
|
|
25
|
+
const options = context.getAppOptions() || {};
|
|
26
|
+
const debug = Boolean(options.debug);
|
|
27
|
+
const logger = make_logger(context);
|
|
28
|
+
logger.info("[Slide] setup @ " + __APP_VERSION__);
|
|
82
29
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
onPageChanged,
|
|
106
|
-
});
|
|
107
|
-
if (useFreezer) apps.set(context.appId, slideController);
|
|
108
|
-
logger.setAppController(context.appId, slideController);
|
|
109
|
-
if (import.meta.env.DEV) {
|
|
110
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
111
|
-
(window as any).slideController = slideController;
|
|
112
|
-
}
|
|
113
|
-
slideController.readyPromise.then(options.onReady).then(() => {
|
|
114
|
-
const room = context.getRoom();
|
|
115
|
-
let synced = false;
|
|
116
|
-
if (room && context.getIsWritable()) {
|
|
117
|
-
syncSceneWithSlide(room, context, slideController.slide, baseScenePath);
|
|
118
|
-
synced = true;
|
|
119
|
-
}
|
|
120
|
-
const page = slideController.slide.slideState.currentSlideIndex;
|
|
121
|
-
log("[Slide] page to", page, synced ? "(synced)" : "", "(on ready)");
|
|
122
|
-
});
|
|
123
|
-
return slideController;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
docsViewer = new SlideDocsViewer({
|
|
127
|
-
box,
|
|
128
|
-
view,
|
|
129
|
-
mountSlideController,
|
|
130
|
-
mountWhiteboard: context.mountView.bind(context),
|
|
30
|
+
const sideEffect = new SideEffectManager();
|
|
31
|
+
|
|
32
|
+
// Create UI
|
|
33
|
+
const viewer = new SlideViewer({
|
|
34
|
+
interactive: true,
|
|
35
|
+
mode: "interactive",
|
|
36
|
+
resize: true,
|
|
37
|
+
enableGlobalClick: true,
|
|
38
|
+
controller: debug,
|
|
39
|
+
timestamp: make_timestamp(context),
|
|
40
|
+
logger,
|
|
41
|
+
renderOptions: {
|
|
42
|
+
minFPS: options.minFPS || 25,
|
|
43
|
+
maxFPS: options.maxFPS || 30,
|
|
44
|
+
autoFPS: options.autoFPS ?? true,
|
|
45
|
+
autoResolution: options.autoResolution ?? true,
|
|
46
|
+
resolution: options.resolution,
|
|
47
|
+
transactionBgColor: options.bgColor || make_bg_color(context.box.$content),
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
taskId: context.storage.state.taskId,
|
|
51
|
+
url: context.storage.state.url,
|
|
131
52
|
});
|
|
132
53
|
|
|
54
|
+
// For debugging.
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
56
|
+
(viewer as any).context = context;
|
|
57
|
+
|
|
58
|
+
sideEffect.addDisposer(refrigerator.set(context.appId, viewer));
|
|
59
|
+
|
|
133
60
|
if (import.meta.env.DEV) {
|
|
134
61
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
135
|
-
(window as any).
|
|
62
|
+
(window as any).slideViewer = viewer;
|
|
136
63
|
}
|
|
137
64
|
|
|
138
|
-
|
|
139
|
-
|
|
65
|
+
// Mount UI
|
|
66
|
+
context.box.mountStyles(SlideViewer.styles);
|
|
67
|
+
context.box.mountStage(viewer.$slide);
|
|
68
|
+
context.box.mountFooter(viewer.$footer);
|
|
69
|
+
context.box.mountContent(viewer.$content);
|
|
70
|
+
sideEffect.addDisposer(() => viewer.destroy());
|
|
140
71
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
72
|
+
// Connect UI with Netless App
|
|
73
|
+
connect({ context, viewer, sideEffect, logger });
|
|
74
|
+
|
|
75
|
+
onUnmount(context, () => {
|
|
76
|
+
logger.info("[Slide] destroy");
|
|
77
|
+
sideEffect.flushAll();
|
|
146
78
|
});
|
|
79
|
+
},
|
|
80
|
+
};
|
|
147
81
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
82
|
+
export default SlideApp;
|
|
83
|
+
|
|
84
|
+
export function previewSlide(options: SlideViewerOptions & { container: HTMLElement }) {
|
|
85
|
+
const { container } = options;
|
|
86
|
+
container.style.cssText = "display:flex;flex-direction:column";
|
|
87
|
+
const viewer = new SlideViewer(options);
|
|
88
|
+
container.appendChild(document.createElement("style")).textContent = SlideViewer.styles;
|
|
89
|
+
container.appendChild(viewer.$content);
|
|
90
|
+
container.appendChild(viewer.$footer);
|
|
91
|
+
viewer.prepare(() => viewer.slide.renderSlide(1));
|
|
92
|
+
return viewer;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function make_timestamp(context: AppContext): () => number {
|
|
96
|
+
const room = context.room;
|
|
97
|
+
const player = context.displayer as Player;
|
|
98
|
+
if (room) {
|
|
99
|
+
return () => room.calibrationTimestamp;
|
|
100
|
+
} else if (player) {
|
|
101
|
+
return () => player.beginTimestamp + player.progressTime;
|
|
102
|
+
} else {
|
|
103
|
+
return () => Date.now();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function make_logger(context: AppContext): { info: (msg: string) => void } {
|
|
108
|
+
if (import.meta.env.DEV) {
|
|
109
|
+
return { info: console.debug.bind(console) };
|
|
110
|
+
}
|
|
111
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
112
|
+
return (context.displayer as any).logger;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function make_bg_color(el: HTMLElement): string {
|
|
116
|
+
try {
|
|
117
|
+
let bg = window.getComputedStyle(el).backgroundColor;
|
|
118
|
+
if (bg !== "rgba(0, 0, 0, 0)" && bg !== "transparent") {
|
|
119
|
+
bg = hex(bg);
|
|
120
|
+
console.log("[Slide] guess bg color:", bg);
|
|
121
|
+
return bg;
|
|
122
|
+
}
|
|
123
|
+
if (el.parentElement) {
|
|
124
|
+
return make_bg_color(el.parentElement);
|
|
159
125
|
}
|
|
126
|
+
} catch {
|
|
127
|
+
// ignored
|
|
128
|
+
}
|
|
129
|
+
return "#ffffff";
|
|
130
|
+
}
|
|
160
131
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
132
|
+
// https://github.com/Qix-/color-convert/blob/8dfdbbc6b46fa6a305bf394d942cc1b08e23fca5/conversions.js#L616
|
|
133
|
+
function hex(color: string): string {
|
|
134
|
+
const result = ColorString.get(color);
|
|
135
|
+
if (result && result.model === "rgb") {
|
|
136
|
+
const args = result.value;
|
|
137
|
+
|
|
138
|
+
const integer =
|
|
139
|
+
((Math.round(args[0]) & 0xff) << 16) +
|
|
140
|
+
((Math.round(args[1]) & 0xff) << 8) +
|
|
141
|
+
(Math.round(args[2]) & 0xff);
|
|
142
|
+
|
|
143
|
+
const string = integer.toString(16);
|
|
144
|
+
return "#" + "000000".substring(string.length) + string;
|
|
145
|
+
} else {
|
|
146
|
+
return color;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
170
149
|
|
|
171
|
-
|
|
150
|
+
function onUnmount(context: AppContext, callback: () => void) {
|
|
151
|
+
context.emitter.on("destroy", callback);
|
|
152
|
+
}
|
|
172
153
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
prevPage: () => {
|
|
209
|
-
const controller = docsViewer?.slideController;
|
|
210
|
-
if (controller) {
|
|
211
|
-
const { page, pageCount } = controller;
|
|
212
|
-
if (pageCount > 0 && page > 1) {
|
|
213
|
-
controller.jumpToPage(page - 1);
|
|
214
|
-
return true;
|
|
154
|
+
interface ConnectParams {
|
|
155
|
+
context: AppContext;
|
|
156
|
+
viewer: SlideViewer;
|
|
157
|
+
sideEffect: SideEffectManager;
|
|
158
|
+
logger: { info: (msg: string) => void };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function connect({ context, viewer, sideEffect, logger }: ConnectParams) {
|
|
162
|
+
const log = import.meta.env.DEV ? console.log.bind(console) : logger.info.bind(logger);
|
|
163
|
+
|
|
164
|
+
let whiteboard: WhiteBoardView | null = null;
|
|
165
|
+
|
|
166
|
+
viewer.prepare(({ width, height, slideCount }) => {
|
|
167
|
+
if (context.destroyed) return;
|
|
168
|
+
width && context.box.setStageRatio(height / width);
|
|
169
|
+
whiteboard = context.createWhiteBoardView(slideCount);
|
|
170
|
+
kick_start();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const { slide } = viewer;
|
|
174
|
+
|
|
175
|
+
function kick_start() {
|
|
176
|
+
if (context.storage.state.state) {
|
|
177
|
+
log("[Slide] restore", { ...context.storage.state.state });
|
|
178
|
+
slide.setSlideState(context.storage.state.state);
|
|
179
|
+
} else if (context.isAddApp) {
|
|
180
|
+
log("[Slide] kick start");
|
|
181
|
+
slide.renderSlide(1);
|
|
182
|
+
} else {
|
|
183
|
+
log("[Slide] wait for restore");
|
|
184
|
+
const timeoutID = sideEffect.add(() => {
|
|
185
|
+
const timer = setInterval(() => {
|
|
186
|
+
if (!context.storage.state.state) {
|
|
187
|
+
log("[Slide] timeout");
|
|
188
|
+
slide.renderSlide(1);
|
|
215
189
|
}
|
|
216
|
-
}
|
|
217
|
-
return
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
190
|
+
}, 15 * 1000);
|
|
191
|
+
return () => clearInterval(timer);
|
|
192
|
+
});
|
|
193
|
+
const disposerID = sideEffect.addDisposer(
|
|
194
|
+
context.storage.addStateChangedListener(() => {
|
|
195
|
+
if (context.storage.state.state) {
|
|
196
|
+
log("[Slide] restore", { ...context.storage.state.state });
|
|
197
|
+
slide.setSlideState(context.storage.state.state);
|
|
198
|
+
sideEffect.flush(disposerID);
|
|
199
|
+
sideEffect.flush(timeoutID);
|
|
226
200
|
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
},
|
|
232
|
-
};
|
|
201
|
+
})
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
233
205
|
|
|
234
|
-
|
|
206
|
+
// setup sync event
|
|
207
|
+
slide.on("stateChange", () => {
|
|
208
|
+
if (context.isWritable) {
|
|
209
|
+
log("[Slide] save state", { ...slide.slideState });
|
|
210
|
+
context.storage.setState({ state: slide.slideState });
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
slide.on("syncDispatch", payload => {
|
|
214
|
+
if (context.isWritable) {
|
|
215
|
+
log("[Slide] dispatch", { ...payload });
|
|
216
|
+
context.dispatchMagixEvent("syncDispatch", payload);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
sideEffect.addDisposer(
|
|
220
|
+
context.addMagixEventListener(
|
|
221
|
+
"syncDispatch",
|
|
222
|
+
({ payload }) => {
|
|
223
|
+
log("[Slide] receive", { ...payload });
|
|
224
|
+
slide.emit("syncReceive", payload);
|
|
225
|
+
},
|
|
226
|
+
{ fireSelfEventAfterCommit: true }
|
|
227
|
+
)
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
// save state
|
|
231
|
+
slide.on("slideChange", page => {
|
|
232
|
+
if (context.isWritable && whiteboard) {
|
|
233
|
+
log("[Slide] page to", page);
|
|
234
|
+
whiteboard.jumpPage(page - 1);
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// handle ui events
|
|
239
|
+
viewer.setReadonly(!context.isWritable);
|
|
240
|
+
sideEffect.addDisposer(
|
|
241
|
+
context.emitter.on("writableChange", w => {
|
|
242
|
+
viewer.setReadonly(!w);
|
|
243
|
+
})
|
|
244
|
+
);
|
|
245
|
+
}
|