@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.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 {
@@ -1296,10 +1313,7 @@ var Presentation = class {
1296
1313
  if (this.initialized)
1297
1314
  return;
1298
1315
  this.initialized = true;
1299
- this.dispose.add(() => {
1300
- var _a2;
1301
- return (_a2 = this.previewLazyload) == null ? void 0 : _a2.destroy();
1302
- });
1316
+ this.dispose.add(() => this.destroyPreviewLazyload());
1303
1317
  this.contentDOM.classList.toggle(this.c("readonly"), this.readonly);
1304
1318
  this.dom.appendChild(this.contentDOM);
1305
1319
  const previewMask = this.contentDOM.appendChild(document.createElement("div"));
@@ -1452,6 +1466,17 @@ var Presentation = class {
1452
1466
  }
1453
1467
  }
1454
1468
  }
1469
+ /** Release preview images while this presentation stays in the runtime cache. */
1470
+ suspendPreviewResources() {
1471
+ this.togglePreview(false);
1472
+ this.destroyPreviewLazyload();
1473
+ this.previewDOM.querySelectorAll("img").forEach((img) => {
1474
+ img.removeAttribute("src");
1475
+ img.removeAttribute("srcset");
1476
+ img.removeAttribute("sizes");
1477
+ LazyLoad.resetStatus(img);
1478
+ });
1479
+ }
1455
1480
  // [origin] means the cause:
1456
1481
  // - navigation: user clicked on the left / right button on footer
1457
1482
  // - input: user filled the bottom-right page number input box
@@ -1486,6 +1511,11 @@ var Presentation = class {
1486
1511
  return src;
1487
1512
  }
1488
1513
  }
1514
+ destroyPreviewLazyload() {
1515
+ var _a;
1516
+ (_a = this.previewLazyload) == null ? void 0 : _a.destroy();
1517
+ this.previewLazyload = null;
1518
+ }
1489
1519
  c(className) {
1490
1520
  return `${this.namespace}-${className}`;
1491
1521
  }
@@ -1498,7 +1528,7 @@ var Presentation = class {
1498
1528
  };
1499
1529
 
1500
1530
  // src/style.scss?inline
1501
- 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}";
1531
+ 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}";
1502
1532
 
1503
1533
  // src/store.ts
1504
1534
  function noop() {
@@ -1944,6 +1974,23 @@ function cameraToSharedViewport(camera, viewSize, referenceSize) {
1944
1974
  };
1945
1975
  }
1946
1976
 
1977
+ // src/runtime-lifecycle.ts
1978
+ var createPresentationRuntimeTeardown = (box, dispose2) => {
1979
+ let tornDown = false;
1980
+ return () => {
1981
+ if (tornDown)
1982
+ return;
1983
+ tornDown = true;
1984
+ try {
1985
+ dispose2();
1986
+ } finally {
1987
+ box.unmountContent();
1988
+ box.unmountFooter();
1989
+ box.unmountStyles();
1990
+ }
1991
+ };
1992
+ };
1993
+
1947
1994
  // src/app-presentation.ts
1948
1995
  var import_debounce2 = __toESM(require_debounce());
1949
1996
  var emptySceneName = "$$empty$$";
@@ -1953,6 +2000,211 @@ var ppt2page = (ppt, name, originSize) => {
1953
2000
  const size = fitPageSizeToOrigin(ppt, originSize);
1954
2001
  return __spreadProps(__spreadValues({}, size), { src: ppt.src, thumbnail: ppt.previewURL, name });
1955
2002
  };
2003
+ var findBackgroundImage = (view) => {
2004
+ const container = view.divElement;
2005
+ if (!container || typeof container.querySelector !== "function")
2006
+ return null;
2007
+ return container.querySelector('img[alt="background"]');
2008
+ };
2009
+ var isBlurDegradationAllowed = (context) => {
2010
+ var _a;
2011
+ if (((_a = context.getWindowManager()) == null ? void 0 : _a.lazySetupInMaximizedMode) !== true) {
2012
+ return false;
2013
+ }
2014
+ const boxStatus = context.getBoxStatus();
2015
+ if (boxStatus) {
2016
+ return boxStatus !== "normal";
2017
+ }
2018
+ const boxState = context.getWindowManager().boxState;
2019
+ return boxState !== void 0 && boxState !== "normal";
2020
+ };
2021
+ var DEFAULT_SETUP_READY_TIMEOUT = 5e3;
2022
+ var waitForCurrentPageImage = (view, timeoutMs, isDisposed) => {
2023
+ return new Promise((resolve) => {
2024
+ let settled = false;
2025
+ let pollTimer;
2026
+ const settle = (loaded) => {
2027
+ if (settled)
2028
+ return;
2029
+ settled = true;
2030
+ window.clearTimeout(timeoutTimer);
2031
+ if (pollTimer !== void 0)
2032
+ window.clearInterval(pollTimer);
2033
+ resolve(loaded);
2034
+ };
2035
+ const timeoutTimer = window.setTimeout(() => settle(false), timeoutMs);
2036
+ const check = () => {
2037
+ if (isDisposed()) {
2038
+ settle(false);
2039
+ return;
2040
+ }
2041
+ const img = findBackgroundImage(view);
2042
+ if (img && img.complete && img.naturalWidth > 0) {
2043
+ settle(true);
2044
+ }
2045
+ };
2046
+ check();
2047
+ if (!settled) {
2048
+ pollTimer = window.setInterval(check, 100);
2049
+ }
2050
+ });
2051
+ };
2052
+ var resolveImageUrl = (url) => {
2053
+ try {
2054
+ return new URL(url, window.location.href).href;
2055
+ } catch (e) {
2056
+ return url;
2057
+ }
2058
+ };
2059
+ var TRANSPARENT_BACKGROUND = "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";
2060
+ var BACKGROUND_SUSPENDED_CLASS = "netless-app-presentation-background-suspended";
2061
+ var hasUsableThumbnail = (page) => {
2062
+ const thumbnailURL = page.thumbnail;
2063
+ if (!thumbnailURL)
2064
+ return false;
2065
+ try {
2066
+ const source = new URL(page.src, window.location.href);
2067
+ const thumbnail = new URL(thumbnailURL, window.location.href);
2068
+ const sameResourcePath = source.origin === thumbnail.origin && source.pathname === thumbnail.pathname;
2069
+ if (/\.gif$/i.test(source.pathname) && sameResourcePath)
2070
+ return false;
2071
+ } catch (e) {
2072
+ if (/\.gif(?:$|[?#])/i.test(page.src))
2073
+ return false;
2074
+ }
2075
+ return resolveImageUrl(thumbnailURL) !== resolveImageUrl(page.src);
2076
+ };
2077
+ var setupBlurThumbnailDegradation = (config) => {
2078
+ const { context, view, pages, pageIndex$, app, dispose: dispose2 } = config;
2079
+ const box = context.getBox();
2080
+ const boxBlurClass = box.wrapClassName("blur");
2081
+ let blurEpisode = false;
2082
+ let reDegradeEnabled = false;
2083
+ let boxBlurred = box.$box.classList.contains(boxBlurClass);
2084
+ const setBackgroundSuspended = (suspended) => {
2085
+ app.whiteboardDOM.classList.toggle(
2086
+ BACKGROUND_SUSPENDED_CLASS,
2087
+ suspended
2088
+ );
2089
+ };
2090
+ const degrade = () => {
2091
+ const page = pages[pageIndex$.value];
2092
+ if (!page)
2093
+ return;
2094
+ const thumbnailURL = page.thumbnail;
2095
+ const img = findBackgroundImage(view);
2096
+ if (!thumbnailURL || !hasUsableThumbnail(page)) {
2097
+ if (boxBlurred) {
2098
+ setBackgroundSuspended(true);
2099
+ if (img && resolveImageUrl(img.src) !== resolveImageUrl(TRANSPARENT_BACKGROUND)) {
2100
+ img.src = TRANSPARENT_BACKGROUND;
2101
+ }
2102
+ }
2103
+ return;
2104
+ }
2105
+ setBackgroundSuspended(false);
2106
+ if (img && resolveImageUrl(img.src) !== resolveImageUrl(thumbnailURL)) {
2107
+ img.src = thumbnailURL;
2108
+ }
2109
+ };
2110
+ const restore2 = () => {
2111
+ const page = pages[pageIndex$.value];
2112
+ const img = findBackgroundImage(view);
2113
+ if (page && img && resolveImageUrl(img.src) !== resolveImageUrl(page.src)) {
2114
+ img.src = page.src;
2115
+ }
2116
+ setBackgroundSuspended(false);
2117
+ };
2118
+ const suspendCachedResources = () => {
2119
+ if (!blurEpisode || !boxBlurred)
2120
+ return;
2121
+ app.suspendPreviewResources();
2122
+ const page = pages[pageIndex$.value];
2123
+ if (!page || !hasUsableThumbnail(page) || reDegradeEnabled) {
2124
+ degrade();
2125
+ }
2126
+ };
2127
+ const restoreFocusedResources = () => {
2128
+ if (!blurEpisode)
2129
+ return;
2130
+ blurEpisode = false;
2131
+ reDegradeEnabled = false;
2132
+ restore2();
2133
+ app.preload.resume(pageIndex$.value);
2134
+ };
2135
+ const isBackgroundImg = (target) => {
2136
+ var _a;
2137
+ const el = target;
2138
+ return Boolean(
2139
+ el && el.tagName === "IMG" && ((_a = el.matches) == null ? void 0 : _a.call(el, 'img[alt="background"]'))
2140
+ );
2141
+ };
2142
+ const ownsTarget = (target) => {
2143
+ if (!isBackgroundImg(target))
2144
+ return false;
2145
+ const el = view.divElement;
2146
+ return !!(el && el.contains(target));
2147
+ };
2148
+ const onImgLoad = (ev) => {
2149
+ if (!blurEpisode || !reDegradeEnabled)
2150
+ return;
2151
+ if (!ownsTarget(ev.target))
2152
+ return;
2153
+ degrade();
2154
+ };
2155
+ const onImgError = (ev) => {
2156
+ if (!blurEpisode || !reDegradeEnabled)
2157
+ return;
2158
+ if (!ownsTarget(ev.target))
2159
+ return;
2160
+ reDegradeEnabled = false;
2161
+ };
2162
+ const offFocus = context.emitter.on("focus", (isFocused) => {
2163
+ if (isFocused) {
2164
+ restoreFocusedResources();
2165
+ } else {
2166
+ if (!isBlurDegradationAllowed(context))
2167
+ return;
2168
+ blurEpisode = true;
2169
+ reDegradeEnabled = true;
2170
+ degrade();
2171
+ app.preload.pause();
2172
+ suspendCachedResources();
2173
+ }
2174
+ });
2175
+ dispose2.add(offFocus);
2176
+ const updateBoxBlurred = (blurred) => {
2177
+ if (boxBlurred === blurred)
2178
+ return;
2179
+ boxBlurred = blurred;
2180
+ if (blurred)
2181
+ suspendCachedResources();
2182
+ else
2183
+ restoreFocusedResources();
2184
+ };
2185
+ const onBoxBlur = () => updateBoxBlurred(true);
2186
+ const onBoxFocus = () => updateBoxBlurred(false);
2187
+ box.events.on("blur", onBoxBlur);
2188
+ box.events.on("focus", onBoxFocus);
2189
+ dispose2.add(() => {
2190
+ box.events.off("blur", onBoxBlur);
2191
+ box.events.off("focus", onBoxFocus);
2192
+ });
2193
+ const boxClassObserver = new MutationObserver(() => {
2194
+ updateBoxBlurred(box.$box.classList.contains(boxBlurClass));
2195
+ });
2196
+ boxClassObserver.observe(box.$box, {
2197
+ attributes: true,
2198
+ attributeFilter: ["class"]
2199
+ });
2200
+ dispose2.add(() => boxClassObserver.disconnect());
2201
+ document.addEventListener("load", onImgLoad, true);
2202
+ document.addEventListener("error", onImgError, true);
2203
+ dispose2.add(() => {
2204
+ document.removeEventListener("load", onImgLoad, true);
2205
+ document.removeEventListener("error", onImgError, true);
2206
+ });
2207
+ };
1956
2208
  var createLogger = (room) => {
1957
2209
  if (room && room.logger) {
1958
2210
  return (...args) => room.logger.info(...args);
@@ -2028,7 +2280,7 @@ var teardownByContext = /* @__PURE__ */ new WeakMap();
2028
2280
  var NetlessAppPresentation = {
2029
2281
  kind: "Presentation",
2030
2282
  setup(context) {
2031
- var _a, _b, _c;
2283
+ var _a, _b, _c, _d;
2032
2284
  const diagnosticLogger = createDiagnosticLogger(context);
2033
2285
  const view = context.getView();
2034
2286
  if (!view)
@@ -2374,10 +2626,13 @@ var NetlessAppPresentation = {
2374
2626
  options.useClipView
2375
2627
  )
2376
2628
  );
2377
- app.contentDOM.dataset.appPresentationVersion = "0.1.13-beta.0";
2629
+ app.contentDOM.dataset.appPresentationVersion = "0.1.13-beta.2";
2378
2630
  app.scaleDocsToFit = scaleDocsToFit;
2379
2631
  app.log = log;
2380
2632
  app.warn = warn;
2633
+ if (pageIndex$.value !== 0) {
2634
+ app.preload.touch(pageIndex$.value, true);
2635
+ }
2381
2636
  const getCameraDiagnosticState = (reason, requestedCamera) => {
2382
2637
  const page = app.page();
2383
2638
  const pageSize = page && isValidSize(page) ? { width: page.width, height: page.height } : void 0;
@@ -2434,8 +2689,8 @@ var NetlessAppPresentation = {
2434
2689
  app.setDocsViewReadonly(true);
2435
2690
  }
2436
2691
  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 : "";
2692
+ var _a2, _b2, _c2, _d2;
2693
+ 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
2694
  if (!app.readonly && currentApplianceName === "clicker") {
2440
2695
  nextPage();
2441
2696
  }
@@ -2482,6 +2737,9 @@ var NetlessAppPresentation = {
2482
2737
  app.setReadonly(!isWritable);
2483
2738
  })
2484
2739
  );
2740
+ if (!options.disableBlurThumbnailDegradation) {
2741
+ setupBlurThumbnailDegradation({ context, view, pages, pageIndex$, app, dispose: dispose2 });
2742
+ }
2485
2743
  const getOriginScale = () => {
2486
2744
  const page = app.page();
2487
2745
  if (!page || !isValidSize(page))
@@ -2610,6 +2868,10 @@ var NetlessAppPresentation = {
2610
2868
  };
2611
2869
  let disposed = false;
2612
2870
  let offDestroy;
2871
+ const teardownRuntime = createPresentationRuntimeTeardown(
2872
+ box,
2873
+ dispose2
2874
+ );
2613
2875
  const teardown = () => {
2614
2876
  if (disposed)
2615
2877
  return;
@@ -2617,7 +2879,7 @@ var NetlessAppPresentation = {
2617
2879
  const removeDestroy = offDestroy;
2618
2880
  offDestroy = void 0;
2619
2881
  removeDestroy == null ? void 0 : removeDestroy();
2620
- dispose2();
2882
+ teardownRuntime();
2621
2883
  };
2622
2884
  offDestroy = context.emitter.on("destroy", teardown);
2623
2885
  teardownByContext.set(context, teardown);
@@ -2831,9 +3093,14 @@ var NetlessAppPresentation = {
2831
3093
  }
2832
3094
  )
2833
3095
  );
2834
- return prepareScenesPromise.then(
2835
- () => controller
2836
- );
3096
+ const setupReadyTimeout = (_d = options.setupReadyTimeout) != null ? _d : DEFAULT_SETUP_READY_TIMEOUT;
3097
+ return prepareScenesPromise.then(async () => {
3098
+ const loaded = await waitForCurrentPageImage(view, setupReadyTimeout, () => disposed);
3099
+ if (!loaded && !disposed) {
3100
+ warn(`[Presentation] setup ready wait timed out after ${setupReadyTimeout}ms`);
3101
+ }
3102
+ return controller;
3103
+ });
2837
3104
  },
2838
3105
  teardown(context) {
2839
3106
  var _a;
@@ -2919,7 +3186,7 @@ var install = (register, options = {}) => {
2919
3186
  };
2920
3187
 
2921
3188
  // src/index.ts
2922
- var version = "0.1.13-beta.0";
3189
+ var version = "0.1.13-beta.2";
2923
3190
 
2924
- export { NetlessAppPresentation, Presentation, Scrollbar, NetlessAppPresentation as default, install, version };
3191
+ export { NetlessAppPresentation, Presentation, Scrollbar, NetlessAppPresentation as default, install, setupBlurThumbnailDegradation, version };
2925
3192
  //# sourceMappingURL=index.mjs.map