@netless/app-presentation 0.1.13-beta.2 → 0.1.13-beta.4

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
@@ -1154,6 +1154,7 @@ var _Preload = class _Preload {
1154
1154
  // 暂停后不再创建预加载链接(app 失焦降级时调用);已插入的 link 会被移除,
1155
1155
  // 挂起的 idle 回调重新进入 touch() 时也会被跳过
1156
1156
  this.paused = false;
1157
+ this.disposed = false;
1157
1158
  this.preloadMap = new Map(pages.map((e, index) => [index, {
1158
1159
  src: e.src,
1159
1160
  state: 0 /* unloaded */
@@ -1168,13 +1169,13 @@ var _Preload = class _Preload {
1168
1169
  this.destroySomeLink();
1169
1170
  }
1170
1171
  resume(index) {
1171
- if (!this.paused)
1172
+ if (!this.paused || this.disposed)
1172
1173
  return;
1173
1174
  this.paused = false;
1174
1175
  this.touch(index != null ? index : this.touchIndex, true);
1175
1176
  }
1176
1177
  touch(index, force = false) {
1177
- if (this.paused)
1178
+ if (this.paused || this.disposed)
1178
1179
  return;
1179
1180
  if (index >= this.preloadSize) {
1180
1181
  this.touchIndex = 0;
@@ -1182,11 +1183,11 @@ var _Preload = class _Preload {
1182
1183
  this.touchIndex = index;
1183
1184
  }
1184
1185
  const value = this.preloadMap.get(this.touchIndex);
1185
- if (value && value.state === 0 /* unloaded */) {
1186
+ if (value && (value.state === 0 /* unloaded */ || force && value.state === 2 /* error */)) {
1186
1187
  this.createLink(this.touchIndex, force);
1187
1188
  }
1188
1189
  if (this.loadingLinks.size < _Preload.maxLinks) {
1189
- const willLoad = [...this.preloadMap.entries()].find(([i, e]) => i > this.touchIndex && e.state !== 1 /* loaded */);
1190
+ const willLoad = [...this.preloadMap.entries()].find(([i, e]) => i > this.touchIndex && e.state === 0 /* unloaded */);
1190
1191
  if (willLoad) {
1191
1192
  this.requestAsyncCallBack(() => {
1192
1193
  this.touch(willLoad[0], false);
@@ -1219,21 +1220,27 @@ var _Preload = class _Preload {
1219
1220
  linkDom.as = "image";
1220
1221
  linkDom.href = value.src;
1221
1222
  linkDom.dataset.order = index + "";
1222
- document.head.appendChild(linkDom);
1223
1223
  linkDom.onload = () => {
1224
+ var _a;
1225
+ if (((_a = this.loadingLinks.get(index)) == null ? void 0 : _a.link) !== linkDom)
1226
+ return;
1224
1227
  const value2 = this.preloadMap.get(index);
1225
1228
  if (value2) {
1226
1229
  value2.state = 1 /* loaded */;
1227
1230
  this.preloadMap.set(index, value2);
1228
- document.head.contains(linkDom) && document.head.removeChild(linkDom);
1229
- this.loadingLinks.delete(index);
1231
+ this.removeLink(index, linkDom);
1230
1232
  this.touch(this.touchIndex + 1, false);
1231
1233
  }
1232
1234
  };
1233
1235
  linkDom.onerror = () => {
1236
+ var _a;
1237
+ if (((_a = this.loadingLinks.get(index)) == null ? void 0 : _a.link) !== linkDom)
1238
+ return;
1234
1239
  const value2 = this.preloadMap.get(index);
1235
- if (value2 == null ? void 0 : value2.src) {
1236
- linkDom.href = value2.src;
1240
+ if (value2) {
1241
+ value2.state = 2 /* error */;
1242
+ this.removeLink(index, linkDom);
1243
+ this.touch(this.touchIndex + 1, false);
1237
1244
  }
1238
1245
  };
1239
1246
  this.loadingLinks.set(index, {
@@ -1242,17 +1249,23 @@ var _Preload = class _Preload {
1242
1249
  });
1243
1250
  value.state = 0 /* unloaded */;
1244
1251
  this.preloadMap.set(index, value);
1252
+ document.head.appendChild(linkDom);
1245
1253
  return 0 /* unloaded */;
1246
1254
  }
1247
1255
  return 2 /* error */;
1248
1256
  }
1257
+ removeLink(index, link) {
1258
+ link.onload = null;
1259
+ link.onerror = null;
1260
+ document.head.contains(link) && document.head.removeChild(link);
1261
+ this.loadingLinks.delete(index);
1262
+ }
1249
1263
  destroySomeLink(excludeIndex) {
1250
1264
  for (const [index, { link }] of this.loadingLinks) {
1251
1265
  if (excludeIndex !== void 0 && index === excludeIndex) {
1252
1266
  continue;
1253
1267
  }
1254
- document.head.contains(link) && document.head.removeChild(link);
1255
- this.loadingLinks.delete(index);
1268
+ this.removeLink(index, link);
1256
1269
  }
1257
1270
  }
1258
1271
  async requestAsyncCallBack(callBack, timeout) {
@@ -1270,6 +1283,7 @@ var _Preload = class _Preload {
1270
1283
  callBack();
1271
1284
  }
1272
1285
  dispose() {
1286
+ this.disposed = true;
1273
1287
  this.destroySomeLink();
1274
1288
  this.preloadMap.clear();
1275
1289
  }
@@ -1982,19 +1996,72 @@ function cameraToSharedViewport(camera, viewSize, referenceSize) {
1982
1996
  var createPresentationRuntimeTeardown = (box, dispose2) => {
1983
1997
  let tornDown = false;
1984
1998
  return () => {
1999
+ var _a, _b, _c;
1985
2000
  if (tornDown)
1986
2001
  return;
1987
2002
  tornDown = true;
1988
2003
  try {
1989
2004
  dispose2();
1990
2005
  } finally {
1991
- box.unmountContent();
1992
- box.unmountFooter();
1993
- box.unmountStyles();
2006
+ try {
2007
+ (_a = box.unmountContent) == null ? void 0 : _a.call(box);
2008
+ } finally {
2009
+ try {
2010
+ (_b = box.unmountFooter) == null ? void 0 : _b.call(box);
2011
+ } finally {
2012
+ (_c = box.unmountStyles) == null ? void 0 : _c.call(box);
2013
+ }
2014
+ }
1994
2015
  }
1995
2016
  };
1996
2017
  };
1997
2018
 
2019
+ // src/setup-ready.ts
2020
+ var waitForCurrentPageImage = (getImage, timeoutMs, isDisposed, options) => {
2021
+ return new Promise((resolve) => {
2022
+ let settled = false;
2023
+ let timedOut = false;
2024
+ let pollTimer;
2025
+ const settle = (result) => {
2026
+ if (settled)
2027
+ return;
2028
+ settled = true;
2029
+ window.clearTimeout(timeoutTimer);
2030
+ if (pollTimer !== void 0)
2031
+ window.clearInterval(pollTimer);
2032
+ resolve(result);
2033
+ };
2034
+ const timeoutTimer = window.setTimeout(() => {
2035
+ timedOut = true;
2036
+ options == null ? void 0 : options.onTimeout();
2037
+ if (!(options == null ? void 0 : options.waitForReady()))
2038
+ settle("timeout");
2039
+ }, timeoutMs);
2040
+ const check = () => {
2041
+ var _a, _b;
2042
+ if (isDisposed()) {
2043
+ settle("disposed");
2044
+ return;
2045
+ }
2046
+ if (timedOut && !(options == null ? void 0 : options.waitForReady())) {
2047
+ settle("timeout");
2048
+ return;
2049
+ }
2050
+ const img = getImage();
2051
+ if (img == null ? void 0 : img.complete) {
2052
+ if (img.naturalWidth > 0) {
2053
+ settle("loaded");
2054
+ } else if (img.currentSrc || ((_a = img.getAttribute("src")) == null ? void 0 : _a.trim()) || ((_b = img.getAttribute("srcset")) == null ? void 0 : _b.trim())) {
2055
+ settle("error");
2056
+ }
2057
+ }
2058
+ };
2059
+ check();
2060
+ if (!settled)
2061
+ pollTimer = window.setInterval(check, 100);
2062
+ });
2063
+ };
2064
+
1998
2065
  // src/app-presentation.ts
1999
2066
  var import_debounce2 = __toESM(require_debounce());
2000
2067
  var emptySceneName = "$$empty$$";
@@ -2023,36 +2090,6 @@ var isBlurDegradationAllowed = (context) => {
2023
2090
  return boxState !== void 0 && boxState !== "normal";
2024
2091
  };
2025
2092
  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
2093
  var resolveImageUrl = (url) => {
2057
2094
  try {
2058
2095
  return new URL(url, window.location.href).href;
@@ -2084,6 +2121,19 @@ var setupBlurThumbnailDegradation = (config) => {
2084
2121
  const boxBlurClass = box.wrapClassName("blur");
2085
2122
  let blurEpisode = false;
2086
2123
  let reDegradeEnabled = false;
2124
+ let previewSuspended = false;
2125
+ let appliedFocusState = true;
2126
+ let logicalFocused = true;
2127
+ const activityBlocked = () => {
2128
+ var _a, _b;
2129
+ const wm = context.getWindowManager();
2130
+ if ((wm == null ? void 0 : wm.lazySetupInMaximizedMode) !== true)
2131
+ return false;
2132
+ const host = (_a = context.getRuntimeActivity) == null ? void 0 : _a.call(context);
2133
+ if (host)
2134
+ return document.visibilityState === "hidden" || !host.active;
2135
+ return document.visibilityState === "hidden" || wm.boxState === "minimized" || ((_b = wm.attributes) == null ? void 0 : _b.minimized) === true || context.getBoxStatus() === "minimized";
2136
+ };
2087
2137
  let boxBlurred = box.$box.classList.contains(boxBlurClass);
2088
2138
  const setBackgroundSuspended = (suspended) => {
2089
2139
  app.whiteboardDOM.classList.toggle(
@@ -2098,7 +2148,7 @@ var setupBlurThumbnailDegradation = (config) => {
2098
2148
  const thumbnailURL = page.thumbnail;
2099
2149
  const img = findBackgroundImage(view);
2100
2150
  if (!thumbnailURL || !hasUsableThumbnail(page)) {
2101
- if (boxBlurred) {
2151
+ if (boxBlurred || activityBlocked()) {
2102
2152
  setBackgroundSuspended(true);
2103
2153
  if (img && resolveImageUrl(img.src) !== resolveImageUrl(TRANSPARENT_BACKGROUND)) {
2104
2154
  img.src = TRANSPARENT_BACKGROUND;
@@ -2120,9 +2170,12 @@ var setupBlurThumbnailDegradation = (config) => {
2120
2170
  setBackgroundSuspended(false);
2121
2171
  };
2122
2172
  const suspendCachedResources = () => {
2123
- if (!blurEpisode || !boxBlurred)
2173
+ if (!blurEpisode || !boxBlurred && !activityBlocked())
2124
2174
  return;
2125
- app.suspendPreviewResources();
2175
+ if (!previewSuspended) {
2176
+ previewSuspended = true;
2177
+ app.suspendPreviewResources();
2178
+ }
2126
2179
  const page = pages[pageIndex$.value];
2127
2180
  if (!page || !hasUsableThumbnail(page) || reDegradeEnabled) {
2128
2181
  degrade();
@@ -2133,6 +2186,7 @@ var setupBlurThumbnailDegradation = (config) => {
2133
2186
  return;
2134
2187
  blurEpisode = false;
2135
2188
  reDegradeEnabled = false;
2189
+ previewSuspended = false;
2136
2190
  restore2();
2137
2191
  app.preload.resume(pageIndex$.value);
2138
2192
  };
@@ -2163,27 +2217,40 @@ var setupBlurThumbnailDegradation = (config) => {
2163
2217
  return;
2164
2218
  reDegradeEnabled = false;
2165
2219
  };
2166
- const offFocus = context.emitter.on("focus", (isFocused) => {
2220
+ const applyActivity = () => {
2221
+ var _a;
2222
+ const lazy = ((_a = context.getWindowManager()) == null ? void 0 : _a.lazySetupInMaximizedMode) === true;
2223
+ const isFocused = (!lazy || logicalFocused) && !activityBlocked();
2224
+ if (appliedFocusState === isFocused)
2225
+ return;
2226
+ if (!isFocused && !isBlurDegradationAllowed(context) && !activityBlocked())
2227
+ return;
2167
2228
  if (isFocused) {
2168
2229
  restoreFocusedResources();
2169
2230
  } else {
2170
- if (!isBlurDegradationAllowed(context))
2171
- return;
2172
2231
  blurEpisode = true;
2173
2232
  reDegradeEnabled = true;
2174
2233
  degrade();
2175
2234
  app.preload.pause();
2176
2235
  suspendCachedResources();
2177
2236
  }
2237
+ appliedFocusState = isFocused;
2238
+ };
2239
+ const offFocus = context.emitter.on("focus", (isFocused) => {
2240
+ logicalFocused = isFocused;
2241
+ applyActivity();
2178
2242
  });
2179
2243
  dispose2.add(offFocus);
2244
+ dispose2.add(context.emitter.on("runtimeActivity", applyActivity));
2245
+ document.addEventListener("visibilitychange", applyActivity);
2246
+ dispose2.add(() => document.removeEventListener("visibilitychange", applyActivity));
2180
2247
  const updateBoxBlurred = (blurred) => {
2181
2248
  if (boxBlurred === blurred)
2182
2249
  return;
2183
2250
  boxBlurred = blurred;
2184
2251
  if (blurred)
2185
2252
  suspendCachedResources();
2186
- else
2253
+ else if (logicalFocused && !activityBlocked())
2187
2254
  restoreFocusedResources();
2188
2255
  };
2189
2256
  const onBoxBlur = () => updateBoxBlurred(true);
@@ -2630,7 +2697,7 @@ var NetlessAppPresentation = {
2630
2697
  options.useClipView
2631
2698
  )
2632
2699
  );
2633
- app.contentDOM.dataset.appPresentationVersion = "0.1.13-beta.2";
2700
+ app.contentDOM.dataset.appPresentationVersion = "0.1.13-beta.4";
2634
2701
  app.scaleDocsToFit = scaleDocsToFit;
2635
2702
  app.log = log;
2636
2703
  app.warn = warn;
@@ -3099,9 +3166,22 @@ var NetlessAppPresentation = {
3099
3166
  );
3100
3167
  const setupReadyTimeout = (_d = options.setupReadyTimeout) != null ? _d : DEFAULT_SETUP_READY_TIMEOUT;
3101
3168
  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`);
3169
+ const result = await waitForCurrentPageImage(
3170
+ () => findBackgroundImage(view),
3171
+ setupReadyTimeout,
3172
+ () => disposed,
3173
+ {
3174
+ waitForReady: () => Boolean(context.waitForActualSetupReady),
3175
+ onTimeout: () => warn(`[Presentation] setup page image still pending after ${setupReadyTimeout}ms`)
3176
+ }
3177
+ );
3178
+ if (disposed)
3179
+ throw new Error("[Presentation] disposed before setup ready");
3180
+ if (result === "error" && context.waitForActualSetupReady) {
3181
+ throw new Error("[Presentation] setup page image failed to load");
3182
+ }
3183
+ if (result === "error" && !disposed) {
3184
+ warn("[Presentation] setup page image failed to load; continuing setup");
3105
3185
  }
3106
3186
  return controller;
3107
3187
  });
@@ -3190,7 +3270,7 @@ var install = (register, options = {}) => {
3190
3270
  };
3191
3271
 
3192
3272
  // src/index.ts
3193
- var version = "0.1.13-beta.2";
3273
+ var version = "0.1.13-beta.4";
3194
3274
 
3195
3275
  exports.NetlessAppPresentation = NetlessAppPresentation;
3196
3276
  exports.Presentation = Presentation;