@netless/app-presentation 0.1.7 → 0.1.8-beta.1

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/index.d.ts CHANGED
@@ -197,9 +197,8 @@ interface ILazyLoadInstance {
197
197
 
198
198
  declare enum ELoadState {
199
199
  unloaded = 0,
200
- loading = 1,
201
- loaded = 2,
202
- error = 3
200
+ loaded = 1,
201
+ error = 2
203
202
  }
204
203
  interface IPreloadMapValue {
205
204
  src: string;
@@ -208,19 +207,18 @@ interface IPreloadMapValue {
208
207
  declare class Preload implements IDisposable {
209
208
  readonly pages: PresentationPage[];
210
209
  static maxLinks: number;
211
- readonly loadingLinks: Map<number, HTMLLinkElement>;
210
+ readonly loadingLinks: Map<number, {
211
+ link: HTMLLinkElement;
212
+ isForce: boolean;
213
+ }>;
212
214
  readonly preloadMap: Map<number, IPreloadMapValue>;
213
- readonly waitingLoadSet: Set<number>;
214
- readonly waitinglinks: number[];
215
215
  touchIndex: number;
216
216
  preloadSize: number;
217
217
  constructor(pages: PresentationPage[]);
218
- touch(index: number): Promise<ELoadState>;
219
- private autoTouch;
218
+ touch(index: number, force?: boolean): void;
220
219
  private createLink;
221
- private handler;
220
+ private destroySomeLink;
222
221
  private requestAsyncCallBack;
223
- private destroyLink;
224
222
  dispose(): void;
225
223
  }
226
224
 
@@ -229,7 +227,7 @@ interface PresentationPage {
229
227
  width: number;
230
228
  height: number;
231
229
  thumbnail?: string | undefined;
232
- name?: string | undefined;
230
+ name?: string;
233
231
  }
234
232
  interface PresentationConfig {
235
233
  readonly pages: PresentationPage[];
@@ -793,127 +793,98 @@ var NetlessAppPresentation = (function (exports) {
793
793
  var _Preload = class _Preload {
794
794
  constructor(pages) {
795
795
  this.pages = pages;
796
+ // 正在加载的链接
796
797
  this.loadingLinks = /* @__PURE__ */ new Map();
798
+ // 需要预加载的链接集合
797
799
  this.preloadMap = /* @__PURE__ */ new Map();
798
- this.waitingLoadSet = /* @__PURE__ */ new Set();
799
- this.waitinglinks = [];
800
+ // 当前触摸的索引
800
801
  this.touchIndex = 0;
801
802
  this.preloadSize = 0;
802
803
  this.preloadMap = new Map(pages.map((e, index) => [index, {
803
804
  src: e.src,
804
805
  state: 0 /* unloaded */
805
806
  }]));
806
- this.waitingLoadSet = new Set(pages.map((e, index) => index));
807
807
  this.preloadSize = this.preloadMap.size;
808
- this.touch(0);
808
+ this.touch(0, true);
809
809
  }
810
- async touch(index) {
811
- this.touchIndex = index;
812
- const value = this.preloadMap.get(index);
813
- let state = 0 /* unloaded */;
814
- if (value) {
815
- state = value.state;
816
- if (value.state === 0 /* unloaded */) {
817
- if (this.loadingLinks.size) {
818
- for (const [i, link] of this.loadingLinks) {
819
- this.destroyLink(i, link);
820
- this.waitingLoadSet.add(i);
821
- const v = this.preloadMap.get(i);
822
- if (v) {
823
- v.state = 0 /* unloaded */;
824
- this.preloadMap.set(i, v);
825
- }
826
- }
827
- for (const i of this.waitinglinks) {
828
- this.waitingLoadSet.add(i);
829
- }
830
- this.waitinglinks.length = 0;
831
- }
832
- if (this.waitinglinks.includes(index)) {
833
- this.waitinglinks.splice(this.waitinglinks.indexOf(index), 1);
834
- }
835
- state = await new Promise((resolve) => {
836
- this.waitingLoadSet.delete(index);
837
- this.createLink(index, resolve);
838
- });
839
- }
840
- }
841
- if (this.waitingLoadSet.size) {
842
- this.requestAsyncCallBack(() => {
843
- this.autoTouch();
844
- }, 1e3);
845
- }
846
- return state;
847
- }
848
- autoTouch() {
849
- this.handler();
850
- if (this.waitingLoadSet.size === 0) {
851
- return;
810
+ touch(index, force = false) {
811
+ if (index >= this.preloadSize) {
812
+ this.touchIndex = 0;
813
+ } else {
814
+ this.touchIndex = index;
852
815
  }
853
- let nextTouchDelay = 1e3;
854
- this.touchIndex = (this.touchIndex + 1) % this.preloadSize;
855
816
  const value = this.preloadMap.get(this.touchIndex);
856
- if (value) {
857
- switch (value.state) {
858
- case 0 /* unloaded */:
859
- case 3 /* error */:
860
- if (!this.waitinglinks.includes(this.touchIndex)) {
861
- this.waitinglinks.push(this.touchIndex);
862
- this.waitingLoadSet.delete(this.touchIndex);
863
- }
864
- nextTouchDelay = 0;
865
- break;
817
+ if (value && value.state === 0 /* unloaded */) {
818
+ this.createLink(this.touchIndex, force);
819
+ }
820
+ if (this.loadingLinks.size < _Preload.maxLinks) {
821
+ const willLoad = [...this.preloadMap.entries()].find(([i, e]) => i > this.touchIndex && e.state !== 1 /* loaded */);
822
+ if (willLoad) {
823
+ this.requestAsyncCallBack(() => {
824
+ this.touch(willLoad[0], false);
825
+ }, 100);
866
826
  }
867
827
  }
868
- this.requestAsyncCallBack(() => {
869
- this.autoTouch();
870
- }, nextTouchDelay);
871
828
  }
872
- createLink(index, resolve) {
829
+ createLink(index, force = false) {
873
830
  const value = this.preloadMap.get(index);
831
+ if (force) {
832
+ this.destroySomeLink(index);
833
+ }
874
834
  if (value) {
875
- const link = document.createElement("link");
876
- link.rel = "preload";
877
- link.as = "image";
878
- link.href = value.src;
879
- link.dataset.order = index + "";
880
- document.head.appendChild(link);
881
- link.onload = () => {
882
- value.state = 2 /* loaded */;
883
- this.preloadMap.set(index, value);
884
- document.head.contains(link) && document.head.removeChild(link);
885
- this.loadingLinks.delete(index);
886
- resolve && resolve(2 /* loaded */);
887
- this.autoTouch();
835
+ if (value.state === 1 /* loaded */) {
836
+ return 1 /* loaded */;
837
+ }
838
+ const curlink = this.loadingLinks.get(index);
839
+ if (curlink) {
840
+ if (curlink.isForce !== force) {
841
+ curlink.isForce = force;
842
+ this.loadingLinks.set(index, curlink);
843
+ }
844
+ return 0 /* unloaded */;
845
+ }
846
+ if (this.loadingLinks.size > _Preload.maxLinks) {
847
+ return 0 /* unloaded */;
848
+ }
849
+ const linkDom = document.createElement("link");
850
+ linkDom.rel = "preload";
851
+ linkDom.as = "image";
852
+ linkDom.href = value.src;
853
+ linkDom.dataset.order = index + "";
854
+ document.head.appendChild(linkDom);
855
+ linkDom.onload = () => {
856
+ const value2 = this.preloadMap.get(index);
857
+ if (value2) {
858
+ value2.state = 1 /* loaded */;
859
+ this.preloadMap.set(index, value2);
860
+ document.head.contains(linkDom) && document.head.removeChild(linkDom);
861
+ this.loadingLinks.delete(index);
862
+ this.touch(this.touchIndex + 1, false);
863
+ }
888
864
  };
889
- link.onerror = () => {
890
- value.state = 3 /* error */;
891
- this.preloadMap.set(index, value);
892
- if (!this.waitinglinks.includes(index)) {
893
- this.waitinglinks.push(index);
894
- this.waitingLoadSet.delete(this.touchIndex);
865
+ linkDom.onerror = () => {
866
+ const value2 = this.preloadMap.get(index);
867
+ if (value2 == null ? void 0 : value2.src) {
868
+ linkDom.href = value2.src;
895
869
  }
896
- document.head.contains(link) && document.head.removeChild(link);
897
- this.loadingLinks.delete(index);
898
- resolve && resolve(3 /* error */);
899
- this.autoTouch();
900
870
  };
901
- this.loadingLinks.set(index, link);
902
- value.state = 1 /* loading */;
871
+ this.loadingLinks.set(index, {
872
+ link: linkDom,
873
+ isForce: force
874
+ });
875
+ value.state = 0 /* unloaded */;
903
876
  this.preloadMap.set(index, value);
877
+ return 0 /* unloaded */;
904
878
  }
879
+ return 2 /* error */;
905
880
  }
906
- handler() {
907
- if (!this.waitinglinks.length) {
908
- return;
909
- }
910
- let i = this.loadingLinks.size;
911
- while (i < _Preload.maxLinks) {
912
- const index = this.waitinglinks.shift();
913
- if (index !== void 0) {
914
- this.createLink(index);
881
+ destroySomeLink(excludeIndex) {
882
+ for (const [index, { link }] of this.loadingLinks) {
883
+ if (excludeIndex !== void 0 && index === excludeIndex) {
884
+ continue;
915
885
  }
916
- i++;
886
+ document.head.contains(link) && document.head.removeChild(link);
887
+ this.loadingLinks.delete(index);
917
888
  }
918
889
  }
919
890
  async requestAsyncCallBack(callBack, timeout) {
@@ -930,17 +901,9 @@ var NetlessAppPresentation = (function (exports) {
930
901
  });
931
902
  callBack();
932
903
  }
933
- destroyLink(index, link) {
934
- document.head.contains(link) && document.head.removeChild(link);
935
- this.loadingLinks.delete(index);
936
- }
937
904
  dispose() {
938
- for (const [index, link] of this.loadingLinks) {
939
- this.destroyLink(index, link);
940
- }
905
+ this.destroySomeLink();
941
906
  this.preloadMap.clear();
942
- this.waitingLoadSet.clear();
943
- this.waitinglinks.length = 0;
944
907
  }
945
908
  };
946
909
  _Preload.maxLinks = 5;
@@ -1167,16 +1130,7 @@ var NetlessAppPresentation = (function (exports) {
1167
1130
  }
1168
1131
  this.timer = setTimeout(() => {
1169
1132
  this.timer = null;
1170
- this.preload.touch(this.pageIndex).then(() => {
1171
- const page = this.page();
1172
- if (!page) {
1173
- this.image.src = "";
1174
- return;
1175
- }
1176
- this.image.width = page.width;
1177
- this.image.height = page.height;
1178
- this.image.src = page.src;
1179
- });
1133
+ this.preload.touch(this.pageIndex, true);
1180
1134
  }, 200);
1181
1135
  }
1182
1136
  /** Returns a modified URL that points to the thumbnail image. */
@@ -1204,7 +1158,77 @@ var NetlessAppPresentation = (function (exports) {
1204
1158
  // src/style.scss?inline
1205
1159
  var style_default = ".netless-app-presentation{height:100%;display:flex;flex-flow:column nowrap}.netless-app-presentation-content{position:relative;height:100%;overflow:hidden}.netless-app-presentation-preview-mask{display:none;position:absolute;z-index:200;top:0;left:0;width:100%;height:100%}.netless-app-presentation-preview{display:flex;flex-direction:column;align-items:center;position:absolute;z-index:300;top:0;left:0;width:33%;max-width:200px;height:100%;padding-top:10px;transform:translate(-100%);background:#ededf0e6;box-shadow:inset -1px 0 #0000001c;transition:transform .4s;overflow:auto;overflow-y:scroll}.netless-app-presentation-preview-active .netless-app-presentation-preview-mask{display:block}.netless-app-presentation-preview-active .netless-app-presentation-preview{transform:translate(0)}.netless-app-presentation-preview-page{position:relative;display:block;width:55%;margin-bottom:10px;font-size:0;color:#0000;outline:none;border:7px solid rgba(0,0,0,0);border-radius:4px;transition:border-color .3s;user-select:none}.netless-app-presentation-preview-page:hover,.netless-app-presentation-preview-page.netless-app-presentation-preview-page-active{border-color:#444e601a}.netless-app-presentation-preview-page>img{width:100%;height:auto;box-sizing:border-box;border:1px solid rgba(0,0,0,.5);border-radius:1px;background-color:#fff;box-shadow:0 2px 8px #0000004d}.netless-app-presentation-preview-page-name{position:absolute;top:1px;left:-10px;transform:translate(-100%);text-align:right;font-size:12px;color:#5f5f5f;user-select:none}.netless-app-presentation-footer{box-sizing:border-box;height:26px;display:flex;align-items:center;padding:0 16px;border-top:1px solid #eeeef7;color:#191919}.netless-app-presentation-float-footer{width:100%;min-height:26px;position:absolute;left:0;bottom:0;z-index:2000;background:#f9f9fce6;transition:opacity .4s}.netless-app-presentation-footer-btn{box-sizing:border-box;width:26px;height:26px;font-size:0;margin:0;padding:3px;border:none;border-radius:1px;outline:none;color:currentColor;background:#0000;transition:background .4s;cursor:pointer;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.netless-app-presentation-footer-btn:hover{background:#ededf0e6}@media (hover: none){.netless-app-presentation-footer-btn:hover{background:#0000!important}}.netless-app-presentation-footer-btn>svg{width:100%;height:100%}.netless-app-presentation-footer-btn>svg:nth-of-type(2){display:none}.netless-app-presentation-footer-btn.netless-app-presentation-footer-btn-playing>svg:nth-of-type(1){display:none}.netless-app-presentation-footer-btn.netless-app-presentation-footer-btn-playing>svg:nth-of-type(2){display:initial}.netless-app-presentation-footer-btn~.netless-app-presentation-footer-btn{margin-left:15px}.netless-app-presentation-page-jumps{flex:1;display:flex;justify-content:center;align-items:center}.netless-app-presentation-page-number{margin-left:auto;font-size:13px;user-select:none;white-space:nowrap;word-break:keep-all}.netless-app-presentation-page-number-input{border:none;outline:none;width:3em;margin:0;padding:0 2px;text-align:right;font-size:13px;line-height:1;font-weight:400;font-family:inherit;border-radius:2px;color:currentColor;background:#0000;transition:background .4s;user-select:text;-webkit-tap-highlight-color:rgba(0,0,0,0)}.netless-app-presentation-page-number-input:hover,.netless-app-presentation-page-number-input:focus,.netless-app-presentation-page-number-input:active{background:#fff;box-shadow:#63636333 0 2px 8px}.netless-app-presentation-readonly.netless-app-presentation-footer{display:none}.netless-app-presentation-wb-view{position:absolute;top:0;left:0;width:100%;height:100%;z-index:100;overflow:hidden;transition:opacity .2s}.netless-app-presentation-image{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.netless-app-presentation-image>img{max-width:100%;max-height:100%;object-fit:contain}.telebox-color-scheme-dark .netless-app-presentation-page-number-input{color:#a6a6a8}.telebox-color-scheme-dark .netless-app-presentation-page-number-input:active,.telebox-color-scheme-dark .netless-app-presentation-page-number-input:focus,.telebox-color-scheme-dark .netless-app-presentation-page-number-input:hover{color:#222}.telebox-color-scheme-dark .netless-app-presentation-footer{color:#a6a6a8;background:#2d2d33;border-top:none}.telebox-color-scheme-dark .netless-app-presentation-footer-btn:hover{background:#212126}.telebox-color-scheme-dark .netless-app-presentation-preview{background:#323232e6}";
1206
1160
 
1161
+ // src/store.ts
1162
+ function noop() {
1163
+ }
1164
+ function safe_not_equal(a, b) {
1165
+ return a != a ? b == b : a !== b || a && typeof a === "object" || typeof a === "function";
1166
+ }
1167
+ function readable(value, start = noop) {
1168
+ let stop;
1169
+ const subscribers = /* @__PURE__ */ new Set();
1170
+ function set(new_value) {
1171
+ if (safe_not_equal(value, new_value)) {
1172
+ value = new_value;
1173
+ if (stop) {
1174
+ for (const run of subscribers) {
1175
+ run(value);
1176
+ }
1177
+ }
1178
+ }
1179
+ }
1180
+ function subscribe(run) {
1181
+ subscribers.add(run);
1182
+ if (subscribers.size === 1) {
1183
+ stop = start(set) || noop;
1184
+ }
1185
+ run(value);
1186
+ return () => {
1187
+ subscribers.delete(run);
1188
+ if (subscribers.size === 0) {
1189
+ stop && stop();
1190
+ stop = void 0;
1191
+ }
1192
+ };
1193
+ }
1194
+ function reaction(run) {
1195
+ subscribers.add(run);
1196
+ if (subscribers.size === 1) {
1197
+ stop = start(set) || noop;
1198
+ }
1199
+ return () => {
1200
+ subscribers.delete(run);
1201
+ if (subscribers.size === 0) {
1202
+ stop && stop();
1203
+ stop = void 0;
1204
+ }
1205
+ };
1206
+ }
1207
+ function dispose2(new_value) {
1208
+ if (new_value !== void 0) {
1209
+ set(new_value);
1210
+ }
1211
+ subscribers.clear();
1212
+ stop && stop();
1213
+ stop = void 0;
1214
+ }
1215
+ return {
1216
+ get value() {
1217
+ if (subscribers.size === 0) {
1218
+ stop = start(set) || noop;
1219
+ stop();
1220
+ stop = void 0;
1221
+ }
1222
+ return value;
1223
+ },
1224
+ subscribe,
1225
+ reaction,
1226
+ dispose: dispose2
1227
+ };
1228
+ }
1229
+
1207
1230
  // src/app-presentation.ts
1231
+ var emptySceneName = "$$empty$$";
1208
1232
  var ppt2page = (ppt, name) => ppt ? { width: ppt.width, height: ppt.height, src: ppt.src, thumbnail: ppt.previewURL, name } : null;
1209
1233
  var createLogger = (room) => {
1210
1234
  if (room && room.logger) {
@@ -1213,10 +1237,22 @@ var NetlessAppPresentation = (function (exports) {
1213
1237
  return (...args) => console.log(...args);
1214
1238
  }
1215
1239
  };
1240
+ var scenesEqual = (scenes1, scenes2) => {
1241
+ if (!scenes1 || !scenes2) {
1242
+ return false;
1243
+ }
1244
+ if (scenes1.length !== scenes2.length)
1245
+ return false;
1246
+ return scenes1.every((scene, index) => {
1247
+ var _a, _b, _c, _d, _e, _f;
1248
+ const scene2 = scenes2[index];
1249
+ return scene.name === scene2.name && ((_a = scene.ppt) == null ? void 0 : _a.width) === ((_b = scene2.ppt) == null ? void 0 : _b.width) && ((_c = scene.ppt) == null ? void 0 : _c.height) === ((_d = scene2.ppt) == null ? void 0 : _d.height) && ((_e = scene.ppt) == null ? void 0 : _e.src) === ((_f = scene2.ppt) == null ? void 0 : _f.src);
1250
+ });
1251
+ };
1216
1252
  var NetlessAppPresentation = {
1217
1253
  kind: "Presentation",
1218
1254
  setup(context) {
1219
- var _a, _b, _c, _d, _e;
1255
+ var _a, _b, _c;
1220
1256
  const view = context.getView();
1221
1257
  if (!view)
1222
1258
  throw new Error("[Presentation]: no whiteboard view, make sure you have added options.scenePath in addApp()");
@@ -1234,43 +1270,88 @@ var NetlessAppPresentation = (function (exports) {
1234
1270
  }
1235
1271
  const log = options.log || createLogger(context.getRoom());
1236
1272
  log(`[Presentation] new ${context.appId}`);
1273
+ const dispose2 = disposableStore();
1274
+ dispose2.add(() => log(`[Presentation] dispose ${context.appId}`));
1275
+ const view$$ = context.createStorage("view", { uid: "", originX: 0, originY: 0, width: 0, height: 0 });
1276
+ const _addScenePathListener = (name, listener) => {
1277
+ const windowManger = context.manager.windowManger;
1278
+ windowManger.emitter.on(name, listener);
1279
+ return () => windowManger == null ? void 0 : windowManger.emitter.off(name, listener);
1280
+ };
1281
+ const getPageIndex = (view2) => {
1282
+ const focusScenePath = view2.focusScenePath;
1283
+ const name = focusScenePath == null ? void 0 : focusScenePath.split("/").pop();
1284
+ let _pageIndex = pages.findIndex((page, index) => {
1285
+ var _a2;
1286
+ const n = (_a2 = page.name) != null ? _a2 : String(index + 1);
1287
+ return n === name;
1288
+ });
1289
+ if (_pageIndex === -1) {
1290
+ _pageIndex = 0;
1291
+ }
1292
+ return _pageIndex;
1293
+ };
1294
+ let pageIndex = getPageIndex(view);
1295
+ const pageIndex$ = readable(pageIndex, (set) => {
1296
+ set(pageIndex);
1297
+ return _addScenePathListener("onAppScenePathChange", (payload) => {
1298
+ const { appId } = payload;
1299
+ if (appId === context.appId) {
1300
+ const _pageIndex = getPageIndex(payload.view);
1301
+ set(_pageIndex);
1302
+ }
1303
+ });
1304
+ });
1305
+ dispose2.add(() => {
1306
+ pageIndex$.dispose();
1307
+ });
1237
1308
  if (context.isAddApp) {
1238
1309
  if (pages.length > 100)
1239
1310
  console.warn(`[Presentation]: too many pages (${pages.length}), may cause performance issues`);
1311
+ let redirectResolve = void 0;
1240
1312
  const room = context.getRoom();
1241
1313
  if (room && room.isWritable) {
1242
1314
  const scenes = room.entireScenes()[scenePath];
1243
- for (let i = 0; i < pages.length; i++) {
1244
- const p = pages[i];
1245
- const name = (_c = p.name) != null ? _c : String(i + 1);
1246
- const scene = scenes.find((scene2) => scene2.name == name && scene2.ppt);
1247
- if (scene) {
1248
- if (scene.ppt && ((_d = scene.ppt) == null ? void 0 : _d.src) === p.src) {
1249
- continue;
1250
- }
1251
- room.removeScenes(`${scenePath}/${name}`);
1252
- }
1253
- room.putScenes(scenePath, pages.map((p2, index) => {
1315
+ if (pageIndex$.value < 0 || pageIndex$.value >= pages.length) {
1316
+ throw new Error(`[Presentation] Invalid page index: ${pageIndex$.value}, scenes length: ${pages.length}`);
1317
+ }
1318
+ new Promise((resolve) => {
1319
+ const { name, ppt } = scenes[pageIndex$.value];
1320
+ redirectResolve = resolve;
1321
+ const _scenes = pages.map((p, index) => {
1254
1322
  var _a2;
1255
1323
  return {
1256
- name: (_a2 = p2.name) != null ? _a2 : String(index + 1),
1257
- ppt: { width: p2.width, height: p2.height, src: p2.src }
1324
+ name: (_a2 = p.name) != null ? _a2 : String(index + 1),
1325
+ ppt: { width: p.width, height: p.height, src: p.src }
1258
1326
  };
1259
- }));
1260
- }
1327
+ });
1328
+ if (!scenesEqual(scenes, _scenes)) {
1329
+ room.removeScenes(scenePath);
1330
+ room.putScenes(scenePath, _scenes);
1331
+ }
1332
+ if (name === _scenes[pageIndex$.value].name && !ppt) {
1333
+ context.addPage({ scene: { name: emptySceneName } }).then(() => {
1334
+ log(`[Presentation] setup setScenePath ${scenePath}/${emptySceneName}`);
1335
+ context.setScenePath(`${scenePath}/${emptySceneName}`).then(() => {
1336
+ redirectResolve && redirectResolve(true);
1337
+ });
1338
+ });
1339
+ } else {
1340
+ redirectResolve && redirectResolve(false);
1341
+ }
1342
+ }).then(async (bol) => {
1343
+ await syncPage(pageIndex$.value, room.logger);
1344
+ if (bol) {
1345
+ log(`[Presentation] setup removeScenes ${scenePath}/${emptySceneName}`);
1346
+ room.removeScenes(`${scenePath}/${emptySceneName}`);
1347
+ }
1348
+ });
1261
1349
  }
1262
1350
  }
1263
- const dispose2 = disposableStore();
1264
- dispose2.add(() => log(`[Presentation] dispose ${context.appId}`));
1265
- const page$$ = context.createStorage("page", { index: 0 });
1266
- const view$$ = context.createStorage("view", { uid: "", originX: 0, originY: 0, width: 0, height: 0 });
1267
- let lastIndex = -1;
1268
- const syncPage = async (index) => {
1351
+ const me = ((_c = context.getRoom()) == null ? void 0 : _c.uid) || context.getDisplayer().observerId + "";
1352
+ let throttleSyncView = 0;
1353
+ const syncPage = async (index, logger) => {
1269
1354
  var _a2;
1270
- if (lastIndex !== index) {
1271
- lastIndex = index;
1272
- context.dispatchAppEvent("pageStateChange", { index, length: pages.length });
1273
- }
1274
1355
  if (!context.getIsWritable())
1275
1356
  return;
1276
1357
  const scenes = context.getDisplayer().entireScenes()[scenePath];
@@ -1281,6 +1362,9 @@ var NetlessAppPresentation = (function (exports) {
1281
1362
  if (!scenes.some((scene) => scene.name === name)) {
1282
1363
  await context.addPage({ scene: { name, ppt: { width: p.width, height: p.height, src: p.src } } });
1283
1364
  }
1365
+ if (logger) {
1366
+ logger.info(`[Presentation] syncPage ${scenePath}/${name}`);
1367
+ }
1284
1368
  await context.setScenePath(`${scenePath}/${name}`);
1285
1369
  };
1286
1370
  const jumpPage = (index) => {
@@ -1301,14 +1385,14 @@ var NetlessAppPresentation = (function (exports) {
1301
1385
  const p = pages[index];
1302
1386
  const name = (_a2 = p.name) != null ? _a2 : String(index + 1);
1303
1387
  if (!scenes.some((scene) => scene.name === name)) {
1304
- context.addPage({ scene: { name } });
1388
+ context.addPage({ scene: { name, ppt: { width: p.width, height: p.height, src: p.src } } });
1305
1389
  }
1306
- page$$.setState({ index });
1390
+ syncPage(index);
1307
1391
  return true;
1308
1392
  };
1309
- const prevPage = () => jumpPage(page$$.state.index - 1);
1310
- const nextPage = () => jumpPage(page$$.state.index + 1);
1311
- const pageState = () => ({ index: page$$.state.index, length: pages.length });
1393
+ const prevPage = () => jumpPage(pageIndex$.value - 1);
1394
+ const nextPage = () => jumpPage(pageIndex$.value + 1);
1395
+ const pageState = () => ({ index: pageIndex$.value, length: pages.length });
1312
1396
  const scaleDocsToFit = () => {
1313
1397
  const { width, height } = app.page() || {};
1314
1398
  if (width && height) {
@@ -1333,8 +1417,6 @@ var NetlessAppPresentation = (function (exports) {
1333
1417
  syncViewFromRemote(true);
1334
1418
  }
1335
1419
  };
1336
- const me = ((_e = context.getRoom()) == null ? void 0 : _e.uid) || context.getDisplayer().observerId + "";
1337
- let throttleSyncView = 0;
1338
1420
  const syncView = () => {
1339
1421
  if (throttleSyncView > 0)
1340
1422
  return;
@@ -1369,12 +1451,10 @@ var NetlessAppPresentation = (function (exports) {
1369
1451
  });
1370
1452
  }
1371
1453
  };
1372
- syncPage(page$$.state.index);
1373
- dispose2.add(page$$.addStateChangedListener(() => syncPage(page$$.state.index)));
1374
1454
  dispose2.add(view$$.addStateChangedListener(() => syncViewFromRemote(false, true)));
1375
1455
  const box = context.getBox();
1376
- const app = dispose2.add(createPresentation(box, pages, jumpPage, page$$, options.thumbnail));
1377
- app.contentDOM.dataset.appPresentationVersion = "0.1.7";
1456
+ const app = dispose2.add(createPresentation(box, pages, jumpPage, pageIndex$, options.thumbnail));
1457
+ app.contentDOM.dataset.appPresentationVersion = "0.1.8-beta.1";
1378
1458
  app.scaleDocsToFit = scaleDocsToFit;
1379
1459
  app.log = log;
1380
1460
  if (options.justDocsViewReadonly) {
@@ -1548,6 +1628,7 @@ var NetlessAppPresentation = (function (exports) {
1548
1628
  this.image.style.display = "none";
1549
1629
  }
1550
1630
  updateImage() {
1631
+ super.updateImage();
1551
1632
  }
1552
1633
  onNewPageIndex(index, origin) {
1553
1634
  if (origin === "keydown" && this.box && !this.box.focus)
@@ -1561,15 +1642,14 @@ var NetlessAppPresentation = (function (exports) {
1561
1642
  }
1562
1643
  }
1563
1644
  };
1564
- function createPresentation(box, pages, jumpPage, page$$, thumbnail) {
1645
+ function createPresentation(box, pages, jumpPage, pageIndex$, thumbnail) {
1565
1646
  box.mountStyles(style_default);
1566
1647
  const app = new AppPresentation({ pages, readonly: box.readonly, jumpPage, thumbnail });
1567
1648
  app.box = box;
1568
1649
  box.mountContent(app.contentDOM);
1569
1650
  box.mountFooter(app.footerDOM);
1570
- app.setPageIndex(page$$.state.index);
1571
- app.dispose.add(page$$.addStateChangedListener(() => {
1572
- app.setPageIndex(page$$.state.index);
1651
+ app.dispose.add(pageIndex$.subscribe((pageIndex) => {
1652
+ app.setPageIndex(pageIndex);
1573
1653
  }));
1574
1654
  return app;
1575
1655
  }
@@ -1582,7 +1662,7 @@ var NetlessAppPresentation = (function (exports) {
1582
1662
  };
1583
1663
 
1584
1664
  // src/index.ts
1585
- var version = "0.1.7";
1665
+ var version = "0.1.8-beta.1";
1586
1666
 
1587
1667
  exports.NetlessAppPresentation = NetlessAppPresentation;
1588
1668
  exports.Presentation = Presentation;