@netless/app-presentation 0.1.13-beta.0 → 0.1.13-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.mjs CHANGED
@@ -1147,6 +1147,9 @@ var _Preload = class _Preload {
1147
1147
  // 当前触摸的索引
1148
1148
  this.touchIndex = 0;
1149
1149
  this.preloadSize = 0;
1150
+ // 暂停后不再创建预加载链接(app 失焦降级时调用);已插入的 link 会被移除,
1151
+ // 挂起的 idle 回调重新进入 touch() 时也会被跳过
1152
+ this.paused = false;
1150
1153
  this.preloadMap = new Map(pages.map((e, index) => [index, {
1151
1154
  src: e.src,
1152
1155
  state: 0 /* unloaded */
@@ -1154,7 +1157,21 @@ var _Preload = class _Preload {
1154
1157
  this.preloadSize = this.preloadMap.size;
1155
1158
  this.touch(0, true);
1156
1159
  }
1160
+ pause() {
1161
+ if (this.paused)
1162
+ return;
1163
+ this.paused = true;
1164
+ this.destroySomeLink();
1165
+ }
1166
+ resume(index) {
1167
+ if (!this.paused)
1168
+ return;
1169
+ this.paused = false;
1170
+ this.touch(index != null ? index : this.touchIndex, true);
1171
+ }
1157
1172
  touch(index, force = false) {
1173
+ if (this.paused)
1174
+ return;
1158
1175
  if (index >= this.preloadSize) {
1159
1176
  this.touchIndex = 0;
1160
1177
  } else {
@@ -1953,6 +1970,138 @@ var ppt2page = (ppt, name, originSize) => {
1953
1970
  const size = fitPageSizeToOrigin(ppt, originSize);
1954
1971
  return __spreadProps(__spreadValues({}, size), { src: ppt.src, thumbnail: ppt.previewURL, name });
1955
1972
  };
1973
+ var findBackgroundImage = (view) => {
1974
+ const container = view.divElement;
1975
+ if (!container || typeof container.querySelector !== "function")
1976
+ return null;
1977
+ return container.querySelector('img[alt="background"]');
1978
+ };
1979
+ var isBlurDegradationAllowed = (context) => {
1980
+ const boxStatus = context.getBoxStatus();
1981
+ if (boxStatus) {
1982
+ return boxStatus !== "normal";
1983
+ }
1984
+ const boxState = context.getWindowManager().boxState;
1985
+ return boxState !== void 0 && boxState !== "normal";
1986
+ };
1987
+ var DEFAULT_SETUP_READY_TIMEOUT = 5e3;
1988
+ var waitForCurrentPageImage = (view, timeoutMs, isDisposed) => {
1989
+ return new Promise((resolve) => {
1990
+ let settled = false;
1991
+ let pollTimer;
1992
+ const settle = (loaded) => {
1993
+ if (settled)
1994
+ return;
1995
+ settled = true;
1996
+ window.clearTimeout(timeoutTimer);
1997
+ if (pollTimer !== void 0)
1998
+ window.clearInterval(pollTimer);
1999
+ resolve(loaded);
2000
+ };
2001
+ const timeoutTimer = window.setTimeout(() => settle(false), timeoutMs);
2002
+ const check = () => {
2003
+ if (isDisposed()) {
2004
+ settle(false);
2005
+ return;
2006
+ }
2007
+ const img = findBackgroundImage(view);
2008
+ if (img && img.complete && img.naturalWidth > 0) {
2009
+ settle(true);
2010
+ }
2011
+ };
2012
+ check();
2013
+ if (!settled) {
2014
+ pollTimer = window.setInterval(check, 100);
2015
+ }
2016
+ });
2017
+ };
2018
+ var resolveImageUrl = (url) => {
2019
+ try {
2020
+ return new URL(url, window.location.href).href;
2021
+ } catch (e) {
2022
+ return url;
2023
+ }
2024
+ };
2025
+ var setupBlurThumbnailDegradation = (config) => {
2026
+ const { context, view, pages, pageIndex$, app, dispose: dispose2 } = config;
2027
+ let blurEpisode = false;
2028
+ let reDegradeEnabled = false;
2029
+ const degrade = () => {
2030
+ const page = pages[pageIndex$.value];
2031
+ if (!(page == null ? void 0 : page.thumbnail))
2032
+ return;
2033
+ const img = findBackgroundImage(view);
2034
+ if (img && resolveImageUrl(img.src) !== resolveImageUrl(page.thumbnail)) {
2035
+ img.src = page.thumbnail;
2036
+ }
2037
+ };
2038
+ const restore2 = () => {
2039
+ const page = pages[pageIndex$.value];
2040
+ const img = findBackgroundImage(view);
2041
+ if (page && img && resolveImageUrl(img.src) !== resolveImageUrl(page.src)) {
2042
+ img.src = page.src;
2043
+ }
2044
+ };
2045
+ const isBackgroundImg = (target) => {
2046
+ var _a;
2047
+ const el = target;
2048
+ return Boolean(
2049
+ el && el.tagName === "IMG" && ((_a = el.matches) == null ? void 0 : _a.call(el, 'img[alt="background"]'))
2050
+ );
2051
+ };
2052
+ const onImgLoad = (ev) => {
2053
+ if (!blurEpisode || !reDegradeEnabled)
2054
+ return;
2055
+ if (!isBackgroundImg(ev.target))
2056
+ return;
2057
+ degrade();
2058
+ };
2059
+ const onImgError = (ev) => {
2060
+ if (!blurEpisode || !reDegradeEnabled)
2061
+ return;
2062
+ if (!isBackgroundImg(ev.target))
2063
+ return;
2064
+ reDegradeEnabled = false;
2065
+ };
2066
+ const offFocus = context.emitter.on("focus", (isFocused) => {
2067
+ if (isFocused) {
2068
+ if (blurEpisode) {
2069
+ blurEpisode = false;
2070
+ reDegradeEnabled = false;
2071
+ restore2();
2072
+ app.preload.resume(pageIndex$.value);
2073
+ }
2074
+ } else {
2075
+ if (!isBlurDegradationAllowed(context))
2076
+ return;
2077
+ blurEpisode = true;
2078
+ reDegradeEnabled = true;
2079
+ degrade();
2080
+ app.preload.pause();
2081
+ }
2082
+ });
2083
+ dispose2.add(offFocus);
2084
+ const viewEl = view.divElement;
2085
+ if (viewEl && typeof viewEl.addEventListener === "function") {
2086
+ viewEl.addEventListener("load", onImgLoad, true);
2087
+ viewEl.addEventListener("error", onImgError, true);
2088
+ dispose2.add(() => {
2089
+ viewEl.removeEventListener("load", onImgLoad, true);
2090
+ viewEl.removeEventListener("error", onImgError, true);
2091
+ });
2092
+ } else {
2093
+ warnOnceMissingViewContainer(view);
2094
+ }
2095
+ };
2096
+ var degradedWarnedViews = /* @__PURE__ */ new WeakSet();
2097
+ var warnOnceMissingViewContainer = (view) => {
2098
+ if (degradedWarnedViews.has(view))
2099
+ return;
2100
+ degradedWarnedViews.add(view);
2101
+ console.warn(
2102
+ "[Presentation]: blur thumbnail degradation runs without re-degrade coverage (view container unavailable)"
2103
+ );
2104
+ };
1956
2105
  var createLogger = (room) => {
1957
2106
  if (room && room.logger) {
1958
2107
  return (...args) => room.logger.info(...args);
@@ -2028,7 +2177,7 @@ var teardownByContext = /* @__PURE__ */ new WeakMap();
2028
2177
  var NetlessAppPresentation = {
2029
2178
  kind: "Presentation",
2030
2179
  setup(context) {
2031
- var _a, _b, _c;
2180
+ var _a, _b, _c, _d;
2032
2181
  const diagnosticLogger = createDiagnosticLogger(context);
2033
2182
  const view = context.getView();
2034
2183
  if (!view)
@@ -2374,10 +2523,13 @@ var NetlessAppPresentation = {
2374
2523
  options.useClipView
2375
2524
  )
2376
2525
  );
2377
- app.contentDOM.dataset.appPresentationVersion = "0.1.13-beta.0";
2526
+ app.contentDOM.dataset.appPresentationVersion = "0.1.13-beta.1";
2378
2527
  app.scaleDocsToFit = scaleDocsToFit;
2379
2528
  app.log = log;
2380
2529
  app.warn = warn;
2530
+ if (pageIndex$.value !== 0) {
2531
+ app.preload.touch(pageIndex$.value, true);
2532
+ }
2381
2533
  const getCameraDiagnosticState = (reason, requestedCamera) => {
2382
2534
  const page = app.page();
2383
2535
  const pageSize = page && isValidSize(page) ? { width: page.width, height: page.height } : void 0;
@@ -2434,8 +2586,8 @@ var NetlessAppPresentation = {
2434
2586
  app.setDocsViewReadonly(true);
2435
2587
  }
2436
2588
  const goToPageByClick = () => {
2437
- var _a2, _b2, _c2, _d;
2438
- const currentApplianceName = (_d = (_c2 = (_b2 = (_a2 = context.getRoom()) == null ? void 0 : _a2.state) == null ? void 0 : _b2.memberState) == null ? void 0 : _c2.currentApplianceName) != null ? _d : "";
2589
+ var _a2, _b2, _c2, _d2;
2590
+ const currentApplianceName = (_d2 = (_c2 = (_b2 = (_a2 = context.getRoom()) == null ? void 0 : _a2.state) == null ? void 0 : _b2.memberState) == null ? void 0 : _c2.currentApplianceName) != null ? _d2 : "";
2439
2591
  if (!app.readonly && currentApplianceName === "clicker") {
2440
2592
  nextPage();
2441
2593
  }
@@ -2482,6 +2634,9 @@ var NetlessAppPresentation = {
2482
2634
  app.setReadonly(!isWritable);
2483
2635
  })
2484
2636
  );
2637
+ if (!options.disableBlurThumbnailDegradation) {
2638
+ setupBlurThumbnailDegradation({ context, view, pages, pageIndex$, app, dispose: dispose2 });
2639
+ }
2485
2640
  const getOriginScale = () => {
2486
2641
  const page = app.page();
2487
2642
  if (!page || !isValidSize(page))
@@ -2831,9 +2986,14 @@ var NetlessAppPresentation = {
2831
2986
  }
2832
2987
  )
2833
2988
  );
2834
- return prepareScenesPromise.then(
2835
- () => controller
2836
- );
2989
+ const setupReadyTimeout = (_d = options.setupReadyTimeout) != null ? _d : DEFAULT_SETUP_READY_TIMEOUT;
2990
+ return prepareScenesPromise.then(async () => {
2991
+ const loaded = await waitForCurrentPageImage(view, setupReadyTimeout, () => disposed);
2992
+ if (!loaded) {
2993
+ warn(`[Presentation] setup ready wait timed out after ${setupReadyTimeout}ms`);
2994
+ }
2995
+ return controller;
2996
+ });
2837
2997
  },
2838
2998
  teardown(context) {
2839
2999
  var _a;
@@ -2919,7 +3079,7 @@ var install = (register, options = {}) => {
2919
3079
  };
2920
3080
 
2921
3081
  // src/index.ts
2922
- var version = "0.1.13-beta.0";
3082
+ var version = "0.1.13-beta.1";
2923
3083
 
2924
3084
  export { NetlessAppPresentation, Presentation, Scrollbar, NetlessAppPresentation as default, install, version };
2925
3085
  //# sourceMappingURL=index.mjs.map