@netless/app-presentation 0.1.13-beta.0 → 0.1.13-beta.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/dist/index.js CHANGED
@@ -1151,6 +1151,9 @@ var _Preload = class _Preload {
1151
1151
  // 当前触摸的索引
1152
1152
  this.touchIndex = 0;
1153
1153
  this.preloadSize = 0;
1154
+ // 暂停后不再创建预加载链接(app 失焦降级时调用);已插入的 link 会被移除,
1155
+ // 挂起的 idle 回调重新进入 touch() 时也会被跳过
1156
+ this.paused = false;
1154
1157
  this.preloadMap = new Map(pages.map((e, index) => [index, {
1155
1158
  src: e.src,
1156
1159
  state: 0 /* unloaded */
@@ -1158,7 +1161,21 @@ var _Preload = class _Preload {
1158
1161
  this.preloadSize = this.preloadMap.size;
1159
1162
  this.touch(0, true);
1160
1163
  }
1164
+ pause() {
1165
+ if (this.paused)
1166
+ return;
1167
+ this.paused = true;
1168
+ this.destroySomeLink();
1169
+ }
1170
+ resume(index) {
1171
+ if (!this.paused)
1172
+ return;
1173
+ this.paused = false;
1174
+ this.touch(index != null ? index : this.touchIndex, true);
1175
+ }
1161
1176
  touch(index, force = false) {
1177
+ if (this.paused)
1178
+ return;
1162
1179
  if (index >= this.preloadSize) {
1163
1180
  this.touchIndex = 0;
1164
1181
  } else {
@@ -1300,10 +1317,7 @@ var Presentation = class {
1300
1317
  if (this.initialized)
1301
1318
  return;
1302
1319
  this.initialized = true;
1303
- this.dispose.add(() => {
1304
- var _a2;
1305
- return (_a2 = this.previewLazyload) == null ? void 0 : _a2.destroy();
1306
- });
1320
+ this.dispose.add(() => this.destroyPreviewLazyload());
1307
1321
  this.contentDOM.classList.toggle(this.c("readonly"), this.readonly);
1308
1322
  this.dom.appendChild(this.contentDOM);
1309
1323
  const previewMask = this.contentDOM.appendChild(document.createElement("div"));
@@ -1456,6 +1470,17 @@ var Presentation = class {
1456
1470
  }
1457
1471
  }
1458
1472
  }
1473
+ /** Release preview images while this presentation stays in the runtime cache. */
1474
+ suspendPreviewResources() {
1475
+ this.togglePreview(false);
1476
+ this.destroyPreviewLazyload();
1477
+ this.previewDOM.querySelectorAll("img").forEach((img) => {
1478
+ img.removeAttribute("src");
1479
+ img.removeAttribute("srcset");
1480
+ img.removeAttribute("sizes");
1481
+ LazyLoad.resetStatus(img);
1482
+ });
1483
+ }
1459
1484
  // [origin] means the cause:
1460
1485
  // - navigation: user clicked on the left / right button on footer
1461
1486
  // - input: user filled the bottom-right page number input box
@@ -1490,6 +1515,11 @@ var Presentation = class {
1490
1515
  return src;
1491
1516
  }
1492
1517
  }
1518
+ destroyPreviewLazyload() {
1519
+ var _a;
1520
+ (_a = this.previewLazyload) == null ? void 0 : _a.destroy();
1521
+ this.previewLazyload = null;
1522
+ }
1493
1523
  c(className) {
1494
1524
  return `${this.namespace}-${className}`;
1495
1525
  }
@@ -1502,7 +1532,7 @@ var Presentation = class {
1502
1532
  };
1503
1533
 
1504
1534
  // src/style.scss?inline
1505
- 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}.netless-app-presentation-scrollbar-container{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:101}.netless-app-presentation-scrollbar-container-x,.netless-app-presentation-scrollbar-container-y{position:absolute;pointer-events:none;display:flex;justify-content:center;box-sizing:border-box;padding:0}.netless-app-presentation-scrollbar-container-x{bottom:0;left:0;height:6px;width:100%;padding-right:6px}.netless-app-presentation-scrollbar-container-y{top:0;right:0;width:6px;height:100%;flex-direction:column;padding-bottom:6px}.netless-app-presentation-scrollbar-x,.netless-app-presentation-scrollbar-y{border-radius:2px;background-color:#1b1f4d4d;pointer-events:auto;cursor:default}.netless-app-presentation-scrollbar-x{height:6px}.netless-app-presentation-scrollbar-y{width:6px}";
1535
+ 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-background-suspended .background{display:none!important}.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}.netless-app-presentation-scrollbar-container{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:101}.netless-app-presentation-scrollbar-container-x,.netless-app-presentation-scrollbar-container-y{position:absolute;pointer-events:none;display:flex;justify-content:center;box-sizing:border-box;padding:0}.netless-app-presentation-scrollbar-container-x{bottom:0;left:0;height:6px;width:100%;padding-right:6px}.netless-app-presentation-scrollbar-container-y{top:0;right:0;width:6px;height:100%;flex-direction:column;padding-bottom:6px}.netless-app-presentation-scrollbar-x,.netless-app-presentation-scrollbar-y{border-radius:2px;background-color:#1b1f4d4d;pointer-events:auto;cursor:default}.netless-app-presentation-scrollbar-x{height:6px}.netless-app-presentation-scrollbar-y{width:6px}";
1506
1536
 
1507
1537
  // src/store.ts
1508
1538
  function noop() {
@@ -1948,6 +1978,23 @@ function cameraToSharedViewport(camera, viewSize, referenceSize) {
1948
1978
  };
1949
1979
  }
1950
1980
 
1981
+ // src/runtime-lifecycle.ts
1982
+ var createPresentationRuntimeTeardown = (box, dispose2) => {
1983
+ let tornDown = false;
1984
+ return () => {
1985
+ if (tornDown)
1986
+ return;
1987
+ tornDown = true;
1988
+ try {
1989
+ dispose2();
1990
+ } finally {
1991
+ box.unmountContent();
1992
+ box.unmountFooter();
1993
+ box.unmountStyles();
1994
+ }
1995
+ };
1996
+ };
1997
+
1951
1998
  // src/app-presentation.ts
1952
1999
  var import_debounce2 = __toESM(require_debounce());
1953
2000
  var emptySceneName = "$$empty$$";
@@ -1957,6 +2004,211 @@ var ppt2page = (ppt, name, originSize) => {
1957
2004
  const size = fitPageSizeToOrigin(ppt, originSize);
1958
2005
  return __spreadProps(__spreadValues({}, size), { src: ppt.src, thumbnail: ppt.previewURL, name });
1959
2006
  };
2007
+ var findBackgroundImage = (view) => {
2008
+ const container = view.divElement;
2009
+ if (!container || typeof container.querySelector !== "function")
2010
+ return null;
2011
+ return container.querySelector('img[alt="background"]');
2012
+ };
2013
+ var isBlurDegradationAllowed = (context) => {
2014
+ var _a;
2015
+ if (((_a = context.getWindowManager()) == null ? void 0 : _a.lazySetupInMaximizedMode) !== true) {
2016
+ return false;
2017
+ }
2018
+ const boxStatus = context.getBoxStatus();
2019
+ if (boxStatus) {
2020
+ return boxStatus !== "normal";
2021
+ }
2022
+ const boxState = context.getWindowManager().boxState;
2023
+ return boxState !== void 0 && boxState !== "normal";
2024
+ };
2025
+ var DEFAULT_SETUP_READY_TIMEOUT = 5e3;
2026
+ var waitForCurrentPageImage = (view, timeoutMs, isDisposed) => {
2027
+ return new Promise((resolve) => {
2028
+ let settled = false;
2029
+ let pollTimer;
2030
+ const settle = (loaded) => {
2031
+ if (settled)
2032
+ return;
2033
+ settled = true;
2034
+ window.clearTimeout(timeoutTimer);
2035
+ if (pollTimer !== void 0)
2036
+ window.clearInterval(pollTimer);
2037
+ resolve(loaded);
2038
+ };
2039
+ const timeoutTimer = window.setTimeout(() => settle(false), timeoutMs);
2040
+ const check = () => {
2041
+ if (isDisposed()) {
2042
+ settle(false);
2043
+ return;
2044
+ }
2045
+ const img = findBackgroundImage(view);
2046
+ if (img && img.complete && img.naturalWidth > 0) {
2047
+ settle(true);
2048
+ }
2049
+ };
2050
+ check();
2051
+ if (!settled) {
2052
+ pollTimer = window.setInterval(check, 100);
2053
+ }
2054
+ });
2055
+ };
2056
+ var resolveImageUrl = (url) => {
2057
+ try {
2058
+ return new URL(url, window.location.href).href;
2059
+ } catch (e) {
2060
+ return url;
2061
+ }
2062
+ };
2063
+ var TRANSPARENT_BACKGROUND = "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";
2064
+ var BACKGROUND_SUSPENDED_CLASS = "netless-app-presentation-background-suspended";
2065
+ var hasUsableThumbnail = (page) => {
2066
+ const thumbnailURL = page.thumbnail;
2067
+ if (!thumbnailURL)
2068
+ return false;
2069
+ try {
2070
+ const source = new URL(page.src, window.location.href);
2071
+ const thumbnail = new URL(thumbnailURL, window.location.href);
2072
+ const sameResourcePath = source.origin === thumbnail.origin && source.pathname === thumbnail.pathname;
2073
+ if (/\.gif$/i.test(source.pathname) && sameResourcePath)
2074
+ return false;
2075
+ } catch (e) {
2076
+ if (/\.gif(?:$|[?#])/i.test(page.src))
2077
+ return false;
2078
+ }
2079
+ return resolveImageUrl(thumbnailURL) !== resolveImageUrl(page.src);
2080
+ };
2081
+ var setupBlurThumbnailDegradation = (config) => {
2082
+ const { context, view, pages, pageIndex$, app, dispose: dispose2 } = config;
2083
+ const box = context.getBox();
2084
+ const boxBlurClass = box.wrapClassName("blur");
2085
+ let blurEpisode = false;
2086
+ let reDegradeEnabled = false;
2087
+ let boxBlurred = box.$box.classList.contains(boxBlurClass);
2088
+ const setBackgroundSuspended = (suspended) => {
2089
+ app.whiteboardDOM.classList.toggle(
2090
+ BACKGROUND_SUSPENDED_CLASS,
2091
+ suspended
2092
+ );
2093
+ };
2094
+ const degrade = () => {
2095
+ const page = pages[pageIndex$.value];
2096
+ if (!page)
2097
+ return;
2098
+ const thumbnailURL = page.thumbnail;
2099
+ const img = findBackgroundImage(view);
2100
+ if (!thumbnailURL || !hasUsableThumbnail(page)) {
2101
+ if (boxBlurred) {
2102
+ setBackgroundSuspended(true);
2103
+ if (img && resolveImageUrl(img.src) !== resolveImageUrl(TRANSPARENT_BACKGROUND)) {
2104
+ img.src = TRANSPARENT_BACKGROUND;
2105
+ }
2106
+ }
2107
+ return;
2108
+ }
2109
+ setBackgroundSuspended(false);
2110
+ if (img && resolveImageUrl(img.src) !== resolveImageUrl(thumbnailURL)) {
2111
+ img.src = thumbnailURL;
2112
+ }
2113
+ };
2114
+ const restore2 = () => {
2115
+ const page = pages[pageIndex$.value];
2116
+ const img = findBackgroundImage(view);
2117
+ if (page && img && resolveImageUrl(img.src) !== resolveImageUrl(page.src)) {
2118
+ img.src = page.src;
2119
+ }
2120
+ setBackgroundSuspended(false);
2121
+ };
2122
+ const suspendCachedResources = () => {
2123
+ if (!blurEpisode || !boxBlurred)
2124
+ return;
2125
+ app.suspendPreviewResources();
2126
+ const page = pages[pageIndex$.value];
2127
+ if (!page || !hasUsableThumbnail(page) || reDegradeEnabled) {
2128
+ degrade();
2129
+ }
2130
+ };
2131
+ const restoreFocusedResources = () => {
2132
+ if (!blurEpisode)
2133
+ return;
2134
+ blurEpisode = false;
2135
+ reDegradeEnabled = false;
2136
+ restore2();
2137
+ app.preload.resume(pageIndex$.value);
2138
+ };
2139
+ const isBackgroundImg = (target) => {
2140
+ var _a;
2141
+ const el = target;
2142
+ return Boolean(
2143
+ el && el.tagName === "IMG" && ((_a = el.matches) == null ? void 0 : _a.call(el, 'img[alt="background"]'))
2144
+ );
2145
+ };
2146
+ const ownsTarget = (target) => {
2147
+ if (!isBackgroundImg(target))
2148
+ return false;
2149
+ const el = view.divElement;
2150
+ return !!(el && el.contains(target));
2151
+ };
2152
+ const onImgLoad = (ev) => {
2153
+ if (!blurEpisode || !reDegradeEnabled)
2154
+ return;
2155
+ if (!ownsTarget(ev.target))
2156
+ return;
2157
+ degrade();
2158
+ };
2159
+ const onImgError = (ev) => {
2160
+ if (!blurEpisode || !reDegradeEnabled)
2161
+ return;
2162
+ if (!ownsTarget(ev.target))
2163
+ return;
2164
+ reDegradeEnabled = false;
2165
+ };
2166
+ const offFocus = context.emitter.on("focus", (isFocused) => {
2167
+ if (isFocused) {
2168
+ restoreFocusedResources();
2169
+ } else {
2170
+ if (!isBlurDegradationAllowed(context))
2171
+ return;
2172
+ blurEpisode = true;
2173
+ reDegradeEnabled = true;
2174
+ degrade();
2175
+ app.preload.pause();
2176
+ suspendCachedResources();
2177
+ }
2178
+ });
2179
+ dispose2.add(offFocus);
2180
+ const updateBoxBlurred = (blurred) => {
2181
+ if (boxBlurred === blurred)
2182
+ return;
2183
+ boxBlurred = blurred;
2184
+ if (blurred)
2185
+ suspendCachedResources();
2186
+ else
2187
+ restoreFocusedResources();
2188
+ };
2189
+ const onBoxBlur = () => updateBoxBlurred(true);
2190
+ const onBoxFocus = () => updateBoxBlurred(false);
2191
+ box.events.on("blur", onBoxBlur);
2192
+ box.events.on("focus", onBoxFocus);
2193
+ dispose2.add(() => {
2194
+ box.events.off("blur", onBoxBlur);
2195
+ box.events.off("focus", onBoxFocus);
2196
+ });
2197
+ const boxClassObserver = new MutationObserver(() => {
2198
+ updateBoxBlurred(box.$box.classList.contains(boxBlurClass));
2199
+ });
2200
+ boxClassObserver.observe(box.$box, {
2201
+ attributes: true,
2202
+ attributeFilter: ["class"]
2203
+ });
2204
+ dispose2.add(() => boxClassObserver.disconnect());
2205
+ document.addEventListener("load", onImgLoad, true);
2206
+ document.addEventListener("error", onImgError, true);
2207
+ dispose2.add(() => {
2208
+ document.removeEventListener("load", onImgLoad, true);
2209
+ document.removeEventListener("error", onImgError, true);
2210
+ });
2211
+ };
1960
2212
  var createLogger = (room) => {
1961
2213
  if (room && room.logger) {
1962
2214
  return (...args) => room.logger.info(...args);
@@ -2032,7 +2284,7 @@ var teardownByContext = /* @__PURE__ */ new WeakMap();
2032
2284
  var NetlessAppPresentation = {
2033
2285
  kind: "Presentation",
2034
2286
  setup(context) {
2035
- var _a, _b, _c;
2287
+ var _a, _b, _c, _d;
2036
2288
  const diagnosticLogger = createDiagnosticLogger(context);
2037
2289
  const view = context.getView();
2038
2290
  if (!view)
@@ -2378,10 +2630,13 @@ var NetlessAppPresentation = {
2378
2630
  options.useClipView
2379
2631
  )
2380
2632
  );
2381
- app.contentDOM.dataset.appPresentationVersion = "0.1.13-beta.0";
2633
+ app.contentDOM.dataset.appPresentationVersion = "0.1.13-beta.2";
2382
2634
  app.scaleDocsToFit = scaleDocsToFit;
2383
2635
  app.log = log;
2384
2636
  app.warn = warn;
2637
+ if (pageIndex$.value !== 0) {
2638
+ app.preload.touch(pageIndex$.value, true);
2639
+ }
2385
2640
  const getCameraDiagnosticState = (reason, requestedCamera) => {
2386
2641
  const page = app.page();
2387
2642
  const pageSize = page && isValidSize(page) ? { width: page.width, height: page.height } : void 0;
@@ -2438,8 +2693,8 @@ var NetlessAppPresentation = {
2438
2693
  app.setDocsViewReadonly(true);
2439
2694
  }
2440
2695
  const goToPageByClick = () => {
2441
- var _a2, _b2, _c2, _d;
2442
- 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 : "";
2696
+ var _a2, _b2, _c2, _d2;
2697
+ 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 : "";
2443
2698
  if (!app.readonly && currentApplianceName === "clicker") {
2444
2699
  nextPage();
2445
2700
  }
@@ -2486,6 +2741,9 @@ var NetlessAppPresentation = {
2486
2741
  app.setReadonly(!isWritable);
2487
2742
  })
2488
2743
  );
2744
+ if (!options.disableBlurThumbnailDegradation) {
2745
+ setupBlurThumbnailDegradation({ context, view, pages, pageIndex$, app, dispose: dispose2 });
2746
+ }
2489
2747
  const getOriginScale = () => {
2490
2748
  const page = app.page();
2491
2749
  if (!page || !isValidSize(page))
@@ -2614,6 +2872,10 @@ var NetlessAppPresentation = {
2614
2872
  };
2615
2873
  let disposed = false;
2616
2874
  let offDestroy;
2875
+ const teardownRuntime = createPresentationRuntimeTeardown(
2876
+ box,
2877
+ dispose2
2878
+ );
2617
2879
  const teardown = () => {
2618
2880
  if (disposed)
2619
2881
  return;
@@ -2621,7 +2883,7 @@ var NetlessAppPresentation = {
2621
2883
  const removeDestroy = offDestroy;
2622
2884
  offDestroy = void 0;
2623
2885
  removeDestroy == null ? void 0 : removeDestroy();
2624
- dispose2();
2886
+ teardownRuntime();
2625
2887
  };
2626
2888
  offDestroy = context.emitter.on("destroy", teardown);
2627
2889
  teardownByContext.set(context, teardown);
@@ -2835,9 +3097,14 @@ var NetlessAppPresentation = {
2835
3097
  }
2836
3098
  )
2837
3099
  );
2838
- return prepareScenesPromise.then(
2839
- () => controller
2840
- );
3100
+ const setupReadyTimeout = (_d = options.setupReadyTimeout) != null ? _d : DEFAULT_SETUP_READY_TIMEOUT;
3101
+ return prepareScenesPromise.then(async () => {
3102
+ const loaded = await waitForCurrentPageImage(view, setupReadyTimeout, () => disposed);
3103
+ if (!loaded && !disposed) {
3104
+ warn(`[Presentation] setup ready wait timed out after ${setupReadyTimeout}ms`);
3105
+ }
3106
+ return controller;
3107
+ });
2841
3108
  },
2842
3109
  teardown(context) {
2843
3110
  var _a;
@@ -2923,12 +3190,13 @@ var install = (register, options = {}) => {
2923
3190
  };
2924
3191
 
2925
3192
  // src/index.ts
2926
- var version = "0.1.13-beta.0";
3193
+ var version = "0.1.13-beta.2";
2927
3194
 
2928
3195
  exports.NetlessAppPresentation = NetlessAppPresentation;
2929
3196
  exports.Presentation = Presentation;
2930
3197
  exports.Scrollbar = Scrollbar;
2931
3198
  exports.default = NetlessAppPresentation;
2932
3199
  exports.install = install;
3200
+ exports.setupBlurThumbnailDegradation = setupBlurThumbnailDegradation;
2933
3201
  exports.version = version;
2934
3202
  //# sourceMappingURL=index.js.map