@netless/app-presentation 0.1.12 → 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.d.ts +18 -2
- package/dist/index.global.js +445 -99
- package/dist/index.js +445 -99
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +445 -99
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/app-presentation.ts +1041 -499
- package/src/preload.ts +14 -0
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 {
|
|
@@ -1957,6 +1974,138 @@ var ppt2page = (ppt, name, originSize) => {
|
|
|
1957
1974
|
const size = fitPageSizeToOrigin(ppt, originSize);
|
|
1958
1975
|
return __spreadProps(__spreadValues({}, size), { src: ppt.src, thumbnail: ppt.previewURL, name });
|
|
1959
1976
|
};
|
|
1977
|
+
var findBackgroundImage = (view) => {
|
|
1978
|
+
const container = view.divElement;
|
|
1979
|
+
if (!container || typeof container.querySelector !== "function")
|
|
1980
|
+
return null;
|
|
1981
|
+
return container.querySelector('img[alt="background"]');
|
|
1982
|
+
};
|
|
1983
|
+
var isBlurDegradationAllowed = (context) => {
|
|
1984
|
+
const boxStatus = context.getBoxStatus();
|
|
1985
|
+
if (boxStatus) {
|
|
1986
|
+
return boxStatus !== "normal";
|
|
1987
|
+
}
|
|
1988
|
+
const boxState = context.getWindowManager().boxState;
|
|
1989
|
+
return boxState !== void 0 && boxState !== "normal";
|
|
1990
|
+
};
|
|
1991
|
+
var DEFAULT_SETUP_READY_TIMEOUT = 5e3;
|
|
1992
|
+
var waitForCurrentPageImage = (view, timeoutMs, isDisposed) => {
|
|
1993
|
+
return new Promise((resolve) => {
|
|
1994
|
+
let settled = false;
|
|
1995
|
+
let pollTimer;
|
|
1996
|
+
const settle = (loaded) => {
|
|
1997
|
+
if (settled)
|
|
1998
|
+
return;
|
|
1999
|
+
settled = true;
|
|
2000
|
+
window.clearTimeout(timeoutTimer);
|
|
2001
|
+
if (pollTimer !== void 0)
|
|
2002
|
+
window.clearInterval(pollTimer);
|
|
2003
|
+
resolve(loaded);
|
|
2004
|
+
};
|
|
2005
|
+
const timeoutTimer = window.setTimeout(() => settle(false), timeoutMs);
|
|
2006
|
+
const check = () => {
|
|
2007
|
+
if (isDisposed()) {
|
|
2008
|
+
settle(false);
|
|
2009
|
+
return;
|
|
2010
|
+
}
|
|
2011
|
+
const img = findBackgroundImage(view);
|
|
2012
|
+
if (img && img.complete && img.naturalWidth > 0) {
|
|
2013
|
+
settle(true);
|
|
2014
|
+
}
|
|
2015
|
+
};
|
|
2016
|
+
check();
|
|
2017
|
+
if (!settled) {
|
|
2018
|
+
pollTimer = window.setInterval(check, 100);
|
|
2019
|
+
}
|
|
2020
|
+
});
|
|
2021
|
+
};
|
|
2022
|
+
var resolveImageUrl = (url) => {
|
|
2023
|
+
try {
|
|
2024
|
+
return new URL(url, window.location.href).href;
|
|
2025
|
+
} catch (e) {
|
|
2026
|
+
return url;
|
|
2027
|
+
}
|
|
2028
|
+
};
|
|
2029
|
+
var setupBlurThumbnailDegradation = (config) => {
|
|
2030
|
+
const { context, view, pages, pageIndex$, app, dispose: dispose2 } = config;
|
|
2031
|
+
let blurEpisode = false;
|
|
2032
|
+
let reDegradeEnabled = false;
|
|
2033
|
+
const degrade = () => {
|
|
2034
|
+
const page = pages[pageIndex$.value];
|
|
2035
|
+
if (!(page == null ? void 0 : page.thumbnail))
|
|
2036
|
+
return;
|
|
2037
|
+
const img = findBackgroundImage(view);
|
|
2038
|
+
if (img && resolveImageUrl(img.src) !== resolveImageUrl(page.thumbnail)) {
|
|
2039
|
+
img.src = page.thumbnail;
|
|
2040
|
+
}
|
|
2041
|
+
};
|
|
2042
|
+
const restore2 = () => {
|
|
2043
|
+
const page = pages[pageIndex$.value];
|
|
2044
|
+
const img = findBackgroundImage(view);
|
|
2045
|
+
if (page && img && resolveImageUrl(img.src) !== resolveImageUrl(page.src)) {
|
|
2046
|
+
img.src = page.src;
|
|
2047
|
+
}
|
|
2048
|
+
};
|
|
2049
|
+
const isBackgroundImg = (target) => {
|
|
2050
|
+
var _a;
|
|
2051
|
+
const el = target;
|
|
2052
|
+
return Boolean(
|
|
2053
|
+
el && el.tagName === "IMG" && ((_a = el.matches) == null ? void 0 : _a.call(el, 'img[alt="background"]'))
|
|
2054
|
+
);
|
|
2055
|
+
};
|
|
2056
|
+
const onImgLoad = (ev) => {
|
|
2057
|
+
if (!blurEpisode || !reDegradeEnabled)
|
|
2058
|
+
return;
|
|
2059
|
+
if (!isBackgroundImg(ev.target))
|
|
2060
|
+
return;
|
|
2061
|
+
degrade();
|
|
2062
|
+
};
|
|
2063
|
+
const onImgError = (ev) => {
|
|
2064
|
+
if (!blurEpisode || !reDegradeEnabled)
|
|
2065
|
+
return;
|
|
2066
|
+
if (!isBackgroundImg(ev.target))
|
|
2067
|
+
return;
|
|
2068
|
+
reDegradeEnabled = false;
|
|
2069
|
+
};
|
|
2070
|
+
const offFocus = context.emitter.on("focus", (isFocused) => {
|
|
2071
|
+
if (isFocused) {
|
|
2072
|
+
if (blurEpisode) {
|
|
2073
|
+
blurEpisode = false;
|
|
2074
|
+
reDegradeEnabled = false;
|
|
2075
|
+
restore2();
|
|
2076
|
+
app.preload.resume(pageIndex$.value);
|
|
2077
|
+
}
|
|
2078
|
+
} else {
|
|
2079
|
+
if (!isBlurDegradationAllowed(context))
|
|
2080
|
+
return;
|
|
2081
|
+
blurEpisode = true;
|
|
2082
|
+
reDegradeEnabled = true;
|
|
2083
|
+
degrade();
|
|
2084
|
+
app.preload.pause();
|
|
2085
|
+
}
|
|
2086
|
+
});
|
|
2087
|
+
dispose2.add(offFocus);
|
|
2088
|
+
const viewEl = view.divElement;
|
|
2089
|
+
if (viewEl && typeof viewEl.addEventListener === "function") {
|
|
2090
|
+
viewEl.addEventListener("load", onImgLoad, true);
|
|
2091
|
+
viewEl.addEventListener("error", onImgError, true);
|
|
2092
|
+
dispose2.add(() => {
|
|
2093
|
+
viewEl.removeEventListener("load", onImgLoad, true);
|
|
2094
|
+
viewEl.removeEventListener("error", onImgError, true);
|
|
2095
|
+
});
|
|
2096
|
+
} else {
|
|
2097
|
+
warnOnceMissingViewContainer(view);
|
|
2098
|
+
}
|
|
2099
|
+
};
|
|
2100
|
+
var degradedWarnedViews = /* @__PURE__ */ new WeakSet();
|
|
2101
|
+
var warnOnceMissingViewContainer = (view) => {
|
|
2102
|
+
if (degradedWarnedViews.has(view))
|
|
2103
|
+
return;
|
|
2104
|
+
degradedWarnedViews.add(view);
|
|
2105
|
+
console.warn(
|
|
2106
|
+
"[Presentation]: blur thumbnail degradation runs without re-degrade coverage (view container unavailable)"
|
|
2107
|
+
);
|
|
2108
|
+
};
|
|
1960
2109
|
var createLogger = (room) => {
|
|
1961
2110
|
if (room && room.logger) {
|
|
1962
2111
|
return (...args) => room.logger.info(...args);
|
|
@@ -1968,7 +2117,10 @@ var createDiagnosticLogger = (context) => {
|
|
|
1968
2117
|
var _a;
|
|
1969
2118
|
const createAppLogger = context.createLogger;
|
|
1970
2119
|
if (typeof createAppLogger === "function") {
|
|
1971
|
-
return createAppLogger.call(context, "camera", {
|
|
2120
|
+
return createAppLogger.call(context, "camera", {
|
|
2121
|
+
debounceTime: 300,
|
|
2122
|
+
maxWaitTime: 2e3
|
|
2123
|
+
});
|
|
1972
2124
|
}
|
|
1973
2125
|
const roomLogger = (_a = context.getRoom()) == null ? void 0 : _a.logger;
|
|
1974
2126
|
const prefix = `[Presentation][${context.appId}][camera]`;
|
|
@@ -2025,40 +2177,60 @@ var scenesEqual = (scenes1, scenes2) => {
|
|
|
2025
2177
|
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);
|
|
2026
2178
|
});
|
|
2027
2179
|
};
|
|
2180
|
+
var teardownByContext = /* @__PURE__ */ new WeakMap();
|
|
2028
2181
|
var NetlessAppPresentation = {
|
|
2029
2182
|
kind: "Presentation",
|
|
2030
2183
|
setup(context) {
|
|
2031
|
-
var _a, _b, _c;
|
|
2184
|
+
var _a, _b, _c, _d;
|
|
2032
2185
|
const diagnosticLogger = createDiagnosticLogger(context);
|
|
2033
2186
|
const view = context.getView();
|
|
2034
2187
|
if (!view)
|
|
2035
|
-
throw new Error(
|
|
2188
|
+
throw new Error(
|
|
2189
|
+
"[Presentation]: no whiteboard view, make sure you have added options.scenePath in addApp()"
|
|
2190
|
+
);
|
|
2036
2191
|
const options = context.getAppOptions() || {};
|
|
2037
2192
|
const room = context.getRoom();
|
|
2038
2193
|
const log = options.log || createLogger(room);
|
|
2039
2194
|
const roomLogger = room == null ? void 0 : room.logger;
|
|
2040
2195
|
const warn = (...data) => (roomLogger == null ? void 0 : roomLogger.warn) ? roomLogger.warn(...data) : log(...data);
|
|
2041
2196
|
const configuredOriginSize = context.storage.state.originSize;
|
|
2042
|
-
const originSize = isValidSize(configuredOriginSize) ? {
|
|
2197
|
+
const originSize = isValidSize(configuredOriginSize) ? {
|
|
2198
|
+
width: configuredOriginSize.width,
|
|
2199
|
+
height: configuredOriginSize.height
|
|
2200
|
+
} : void 0;
|
|
2043
2201
|
if (configuredOriginSize != null && !originSize) {
|
|
2044
|
-
warn(
|
|
2202
|
+
warn(
|
|
2203
|
+
`[Presentation] originSize should contain finite positive width and height, got ${JSON.stringify(configuredOriginSize)}`
|
|
2204
|
+
);
|
|
2045
2205
|
}
|
|
2046
2206
|
const pages = (_a = context.getScenes()) == null ? void 0 : _a.map(({ ppt, name }) => ppt2page(ppt, name, originSize)).filter(Boolean);
|
|
2047
2207
|
if (!pages || pages.length === 0)
|
|
2048
|
-
throw new Error(
|
|
2208
|
+
throw new Error(
|
|
2209
|
+
"[Presentation]: empty scenes, make sure you have added options.scenes in addApp()"
|
|
2210
|
+
);
|
|
2049
2211
|
if (pages[0].src.startsWith("ppt"))
|
|
2050
|
-
throw new Error(
|
|
2212
|
+
throw new Error(
|
|
2213
|
+
"[Presentation]: legacy dynamic PPT is unsupported, please use the projector converter and @netless/slide to render it"
|
|
2214
|
+
);
|
|
2051
2215
|
const scenePath = context.getInitScenePath();
|
|
2052
2216
|
let maxCameraScale = (_b = options.maxCameraScale) != null ? _b : 3;
|
|
2053
2217
|
if (!(Number.isFinite(maxCameraScale) && maxCameraScale > 0)) {
|
|
2054
|
-
warn(
|
|
2218
|
+
warn(
|
|
2219
|
+
`[Presentation] maxCameraScale should be a positive number, got ${options.maxCameraScale}`
|
|
2220
|
+
);
|
|
2055
2221
|
maxCameraScale = 3;
|
|
2056
2222
|
}
|
|
2057
2223
|
log(`[Presentation] new ${context.appId}`);
|
|
2058
2224
|
const dispose2 = disposableStore();
|
|
2059
2225
|
dispose2.add(() => log(`[Presentation] dispose ${context.appId}`));
|
|
2060
2226
|
dispose2.add(() => diagnosticLogger.flush());
|
|
2061
|
-
const view$$ = context.createStorage("view", {
|
|
2227
|
+
const view$$ = context.createStorage("view", {
|
|
2228
|
+
uid: "",
|
|
2229
|
+
originX: 0,
|
|
2230
|
+
originY: 0,
|
|
2231
|
+
width: 0,
|
|
2232
|
+
height: 0
|
|
2233
|
+
});
|
|
2062
2234
|
const _addScenePathListener = (name, listener) => {
|
|
2063
2235
|
const windowManger = context.manager.windowManger;
|
|
2064
2236
|
windowManger.emitter.on(name, listener);
|
|
@@ -2080,13 +2252,16 @@ var NetlessAppPresentation = {
|
|
|
2080
2252
|
let pageIndex = getPageIndex(view);
|
|
2081
2253
|
const pageIndex$ = readable(pageIndex, (set) => {
|
|
2082
2254
|
set(pageIndex);
|
|
2083
|
-
return _addScenePathListener(
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
const
|
|
2087
|
-
|
|
2255
|
+
return _addScenePathListener(
|
|
2256
|
+
"onAppScenePathChange",
|
|
2257
|
+
(payload) => {
|
|
2258
|
+
const { appId } = payload;
|
|
2259
|
+
if (appId === context.appId) {
|
|
2260
|
+
const _pageIndex = getPageIndex(payload.view);
|
|
2261
|
+
set(_pageIndex);
|
|
2262
|
+
}
|
|
2088
2263
|
}
|
|
2089
|
-
|
|
2264
|
+
);
|
|
2090
2265
|
});
|
|
2091
2266
|
dispose2.add(() => {
|
|
2092
2267
|
pageIndex$.dispose();
|
|
@@ -2103,7 +2278,12 @@ var NetlessAppPresentation = {
|
|
|
2103
2278
|
const p = pages[index];
|
|
2104
2279
|
const name = (_a2 = p.name) != null ? _a2 : String(index + 1);
|
|
2105
2280
|
if (!scenes.some((scene) => scene.name === name)) {
|
|
2106
|
-
await context.addPage({
|
|
2281
|
+
await context.addPage({
|
|
2282
|
+
scene: {
|
|
2283
|
+
name,
|
|
2284
|
+
ppt: { width: p.width, height: p.height, src: p.src }
|
|
2285
|
+
}
|
|
2286
|
+
});
|
|
2107
2287
|
}
|
|
2108
2288
|
if (logger) {
|
|
2109
2289
|
logger.info(`[Presentation] syncPage ${scenePath}/${name}`);
|
|
@@ -2115,15 +2295,21 @@ var NetlessAppPresentation = {
|
|
|
2115
2295
|
if (!context.isAddApp)
|
|
2116
2296
|
return;
|
|
2117
2297
|
if (pages.length > 100)
|
|
2118
|
-
warn(
|
|
2298
|
+
warn(
|
|
2299
|
+
`[Presentation]: too many pages (${pages.length}), may cause performance issues`
|
|
2300
|
+
);
|
|
2119
2301
|
if (!room || !room.isWritable)
|
|
2120
2302
|
return;
|
|
2121
2303
|
if (pageIndex$.value < 0 || pageIndex$.value >= pages.length) {
|
|
2122
|
-
throw new Error(
|
|
2304
|
+
throw new Error(
|
|
2305
|
+
`[Presentation] Invalid page index: ${pageIndex$.value}, scenes length: ${pages.length}`
|
|
2306
|
+
);
|
|
2123
2307
|
}
|
|
2124
2308
|
const scenes = room.entireScenes()[scenePath];
|
|
2125
2309
|
if (!scenes || !scenes[pageIndex$.value]) {
|
|
2126
|
-
throw new Error(
|
|
2310
|
+
throw new Error(
|
|
2311
|
+
`[Presentation]: no initial scene found at ${scenePath}, page index: ${pageIndex$.value}`
|
|
2312
|
+
);
|
|
2127
2313
|
}
|
|
2128
2314
|
const { name, ppt } = scenes[pageIndex$.value];
|
|
2129
2315
|
const nextScenes = pages.map((page, index) => {
|
|
@@ -2152,16 +2338,22 @@ var NetlessAppPresentation = {
|
|
|
2152
2338
|
const prepareScenesPromise = prepareScenes();
|
|
2153
2339
|
const canJumpPage = (index) => {
|
|
2154
2340
|
if (!context.getIsWritable()) {
|
|
2155
|
-
warn(
|
|
2341
|
+
warn(
|
|
2342
|
+
"[Presentation]: no permission, make sure you have test room.isWritable"
|
|
2343
|
+
);
|
|
2156
2344
|
return false;
|
|
2157
2345
|
}
|
|
2158
2346
|
if (!(0 <= index && index < pages.length)) {
|
|
2159
|
-
warn(
|
|
2347
|
+
warn(
|
|
2348
|
+
`[Presentation]: page ${index + 1} out of bounds [1, ${pages.length}]`
|
|
2349
|
+
);
|
|
2160
2350
|
return false;
|
|
2161
2351
|
}
|
|
2162
2352
|
const scenes = context.getDisplayer().entireScenes()[scenePath];
|
|
2163
2353
|
if (!scenes) {
|
|
2164
|
-
warn(
|
|
2354
|
+
warn(
|
|
2355
|
+
`[Presentation]: no scenes found at ${scenePath}, make sure you have added options.scenePath in addApp()`
|
|
2356
|
+
);
|
|
2165
2357
|
return false;
|
|
2166
2358
|
}
|
|
2167
2359
|
return true;
|
|
@@ -2267,13 +2459,20 @@ var NetlessAppPresentation = {
|
|
|
2267
2459
|
try {
|
|
2268
2460
|
const { camera, size } = view;
|
|
2269
2461
|
const referenceSize = getCameraReferenceSize(originSize, page);
|
|
2270
|
-
const viewport = cameraToSharedViewport(
|
|
2462
|
+
const viewport = cameraToSharedViewport(
|
|
2463
|
+
camera,
|
|
2464
|
+
size,
|
|
2465
|
+
referenceSize
|
|
2466
|
+
);
|
|
2271
2467
|
if (viewport)
|
|
2272
2468
|
view$$.setState(__spreadValues({ uid: me }, viewport));
|
|
2273
2469
|
if (pendingMoveCameraRequest) {
|
|
2274
2470
|
diagnosticLogger.debouncedInfo(
|
|
2275
2471
|
"moveCamera",
|
|
2276
|
-
getCameraDiagnosticState(
|
|
2472
|
+
getCameraDiagnosticState(
|
|
2473
|
+
"moveCamera",
|
|
2474
|
+
pendingMoveCameraRequest
|
|
2475
|
+
)
|
|
2277
2476
|
);
|
|
2278
2477
|
pendingMoveCameraRequest = void 0;
|
|
2279
2478
|
}
|
|
@@ -2281,7 +2480,10 @@ var NetlessAppPresentation = {
|
|
|
2281
2480
|
diagnosticLogger.error(
|
|
2282
2481
|
"syncView.failed",
|
|
2283
2482
|
error,
|
|
2284
|
-
getCameraDiagnosticState(
|
|
2483
|
+
getCameraDiagnosticState(
|
|
2484
|
+
"moveCamera",
|
|
2485
|
+
pendingMoveCameraRequest
|
|
2486
|
+
)
|
|
2285
2487
|
);
|
|
2286
2488
|
pendingMoveCameraRequest = void 0;
|
|
2287
2489
|
}
|
|
@@ -2306,17 +2508,32 @@ var NetlessAppPresentation = {
|
|
|
2306
2508
|
});
|
|
2307
2509
|
}
|
|
2308
2510
|
};
|
|
2309
|
-
dispose2.add(
|
|
2511
|
+
dispose2.add(
|
|
2512
|
+
view$$.addStateChangedListener(() => syncViewFromRemote(false, true))
|
|
2513
|
+
);
|
|
2310
2514
|
const getPageSize = () => {
|
|
2311
2515
|
const { width, height } = app.page() || {};
|
|
2312
2516
|
return { width: width || 0, height: height || 0 };
|
|
2313
2517
|
};
|
|
2314
2518
|
const box = context.getBox();
|
|
2315
|
-
const app = dispose2.add(
|
|
2316
|
-
|
|
2519
|
+
const app = dispose2.add(
|
|
2520
|
+
createPresentation(
|
|
2521
|
+
box,
|
|
2522
|
+
pages,
|
|
2523
|
+
jumpPage,
|
|
2524
|
+
pageIndex$,
|
|
2525
|
+
view,
|
|
2526
|
+
options.thumbnail,
|
|
2527
|
+
options.useClipView
|
|
2528
|
+
)
|
|
2529
|
+
);
|
|
2530
|
+
app.contentDOM.dataset.appPresentationVersion = "0.1.13-beta.1";
|
|
2317
2531
|
app.scaleDocsToFit = scaleDocsToFit;
|
|
2318
2532
|
app.log = log;
|
|
2319
2533
|
app.warn = warn;
|
|
2534
|
+
if (pageIndex$.value !== 0) {
|
|
2535
|
+
app.preload.touch(pageIndex$.value, true);
|
|
2536
|
+
}
|
|
2320
2537
|
const getCameraDiagnosticState = (reason, requestedCamera) => {
|
|
2321
2538
|
const page = app.page();
|
|
2322
2539
|
const pageSize = page && isValidSize(page) ? { width: page.width, height: page.height } : void 0;
|
|
@@ -2360,19 +2577,21 @@ var NetlessAppPresentation = {
|
|
|
2360
2577
|
};
|
|
2361
2578
|
if (originSize) {
|
|
2362
2579
|
let previousPageIndex = pageIndex$.value;
|
|
2363
|
-
dispose2.add(
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2580
|
+
dispose2.add(
|
|
2581
|
+
pageIndex$.subscribe((nextPageIndex) => {
|
|
2582
|
+
if (nextPageIndex === previousPageIndex)
|
|
2583
|
+
return;
|
|
2584
|
+
previousPageIndex = nextPageIndex;
|
|
2585
|
+
scaleDocsToFit();
|
|
2586
|
+
})
|
|
2587
|
+
);
|
|
2369
2588
|
}
|
|
2370
2589
|
if (options.justDocsViewReadonly) {
|
|
2371
2590
|
app.setDocsViewReadonly(true);
|
|
2372
2591
|
}
|
|
2373
2592
|
const goToPageByClick = () => {
|
|
2374
|
-
var _a2, _b2, _c2,
|
|
2375
|
-
const currentApplianceName = (
|
|
2593
|
+
var _a2, _b2, _c2, _d2;
|
|
2594
|
+
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 : "";
|
|
2376
2595
|
if (!app.readonly && currentApplianceName === "clicker") {
|
|
2377
2596
|
nextPage();
|
|
2378
2597
|
}
|
|
@@ -2414,9 +2633,14 @@ var NetlessAppPresentation = {
|
|
|
2414
2633
|
});
|
|
2415
2634
|
syncViewFromRemote(true);
|
|
2416
2635
|
reportInitializedCamera("setup");
|
|
2417
|
-
dispose2.add(
|
|
2418
|
-
|
|
2419
|
-
|
|
2636
|
+
dispose2.add(
|
|
2637
|
+
context.emitter.on("writableChange", (isWritable) => {
|
|
2638
|
+
app.setReadonly(!isWritable);
|
|
2639
|
+
})
|
|
2640
|
+
);
|
|
2641
|
+
if (!options.disableBlurThumbnailDegradation) {
|
|
2642
|
+
setupBlurThumbnailDegradation({ context, view, pages, pageIndex$, app, dispose: dispose2 });
|
|
2643
|
+
}
|
|
2420
2644
|
const getOriginScale = () => {
|
|
2421
2645
|
const page = app.page();
|
|
2422
2646
|
if (!page || !isValidSize(page))
|
|
@@ -2438,29 +2662,53 @@ var NetlessAppPresentation = {
|
|
|
2438
2662
|
img.crossOrigin = "Anonymous";
|
|
2439
2663
|
await new Promise((resolve, reject) => {
|
|
2440
2664
|
img.onload = () => resolve();
|
|
2441
|
-
img.onerror = () => reject(
|
|
2442
|
-
|
|
2443
|
-
|
|
2665
|
+
img.onerror = () => reject(
|
|
2666
|
+
new Error(
|
|
2667
|
+
`[Presentation]: failed to load screenshot page image: ${safeResourceLocation(src)}`
|
|
2668
|
+
)
|
|
2669
|
+
);
|
|
2444
2670
|
img.src = src;
|
|
2445
2671
|
});
|
|
2446
|
-
_context.drawImage(
|
|
2672
|
+
_context.drawImage(
|
|
2673
|
+
img,
|
|
2674
|
+
0,
|
|
2675
|
+
0,
|
|
2676
|
+
width,
|
|
2677
|
+
height,
|
|
2678
|
+
0,
|
|
2679
|
+
0,
|
|
2680
|
+
_width || width,
|
|
2681
|
+
_height || height
|
|
2682
|
+
);
|
|
2447
2683
|
const currentScenePath = view.focusScenePath;
|
|
2448
2684
|
if (!currentScenePath) {
|
|
2449
2685
|
throw new Error("[Presentation]: current scene path not found");
|
|
2450
2686
|
}
|
|
2451
2687
|
const windowManger = context.getWindowManager();
|
|
2452
2688
|
if (windowManger._appliancePlugin) {
|
|
2453
|
-
await windowManger._appliancePlugin.screenshotToCanvasAsync(
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2689
|
+
await windowManger._appliancePlugin.screenshotToCanvasAsync(
|
|
2690
|
+
_context,
|
|
2691
|
+
currentScenePath,
|
|
2692
|
+
_width || width,
|
|
2693
|
+
_height || height,
|
|
2694
|
+
{
|
|
2695
|
+
centerX: 0,
|
|
2696
|
+
centerY: 0,
|
|
2697
|
+
scale: _width && _height ? Math.min(_width / width, _height / height) : 1
|
|
2698
|
+
}
|
|
2699
|
+
);
|
|
2458
2700
|
} else {
|
|
2459
|
-
await view.screenshotToCanvasAsync(
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2701
|
+
await view.screenshotToCanvasAsync(
|
|
2702
|
+
_context,
|
|
2703
|
+
currentScenePath,
|
|
2704
|
+
_width || width,
|
|
2705
|
+
_height || height,
|
|
2706
|
+
{
|
|
2707
|
+
centerX: 0,
|
|
2708
|
+
centerY: 0,
|
|
2709
|
+
scale: _width && _height ? Math.min(_width / width, _height / height) : 1
|
|
2710
|
+
}
|
|
2711
|
+
);
|
|
2464
2712
|
}
|
|
2465
2713
|
};
|
|
2466
2714
|
const screenshotCurrentPageAsync = async (_context, _width, _height) => {
|
|
@@ -2478,21 +2726,27 @@ var NetlessAppPresentation = {
|
|
|
2478
2726
|
let scrollbar;
|
|
2479
2727
|
if (options.useScrollbar) {
|
|
2480
2728
|
dispose2.make(() => {
|
|
2481
|
-
scrollbar = new Scrollbar(
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2729
|
+
scrollbar = new Scrollbar(
|
|
2730
|
+
app.contentDOM,
|
|
2731
|
+
{
|
|
2732
|
+
appId: context.appId,
|
|
2733
|
+
getPageSize,
|
|
2734
|
+
getOriginScale,
|
|
2735
|
+
syncView,
|
|
2736
|
+
getWritable: () => context.getIsWritable(),
|
|
2737
|
+
scrollbarEventCallback: options.scrollbarEventCallback
|
|
2738
|
+
},
|
|
2739
|
+
view
|
|
2740
|
+
);
|
|
2489
2741
|
return () => scrollbar == null ? void 0 : scrollbar.destroy();
|
|
2490
2742
|
});
|
|
2491
2743
|
}
|
|
2492
2744
|
const moveCamera = (camera) => {
|
|
2493
2745
|
try {
|
|
2494
2746
|
if (!context.getIsWritable()) {
|
|
2495
|
-
throw new Error(
|
|
2747
|
+
throw new Error(
|
|
2748
|
+
"[Presentation]: moveCamera must be called in writable room"
|
|
2749
|
+
);
|
|
2496
2750
|
}
|
|
2497
2751
|
pendingMoveCameraRequest = __spreadValues({}, camera);
|
|
2498
2752
|
if (scrollbar) {
|
|
@@ -2513,9 +2767,29 @@ var NetlessAppPresentation = {
|
|
|
2513
2767
|
throw error;
|
|
2514
2768
|
}
|
|
2515
2769
|
};
|
|
2516
|
-
|
|
2770
|
+
let disposed = false;
|
|
2771
|
+
let offDestroy;
|
|
2772
|
+
const teardown = () => {
|
|
2773
|
+
if (disposed)
|
|
2774
|
+
return;
|
|
2775
|
+
disposed = true;
|
|
2776
|
+
const removeDestroy = offDestroy;
|
|
2777
|
+
offDestroy = void 0;
|
|
2778
|
+
removeDestroy == null ? void 0 : removeDestroy();
|
|
2779
|
+
dispose2();
|
|
2780
|
+
};
|
|
2781
|
+
offDestroy = context.emitter.on("destroy", teardown);
|
|
2782
|
+
teardownByContext.set(context, teardown);
|
|
2517
2783
|
const reportProgress = (progress, result) => {
|
|
2518
|
-
window.postMessage(
|
|
2784
|
+
window.postMessage(
|
|
2785
|
+
{
|
|
2786
|
+
type: "@netless/_result_save_pdf_",
|
|
2787
|
+
appId: context.appId,
|
|
2788
|
+
progress,
|
|
2789
|
+
result
|
|
2790
|
+
},
|
|
2791
|
+
"*"
|
|
2792
|
+
);
|
|
2519
2793
|
return result;
|
|
2520
2794
|
};
|
|
2521
2795
|
const base64url = async (url) => {
|
|
@@ -2555,7 +2829,9 @@ var NetlessAppPresentation = {
|
|
|
2555
2829
|
}
|
|
2556
2830
|
const scenes = context.getDisplayer().entireScenes()[scenePath];
|
|
2557
2831
|
if (!scenes) {
|
|
2558
|
-
throw new Error(
|
|
2832
|
+
throw new Error(
|
|
2833
|
+
`[Presentation]: no scenes found while exporting PDF: ${scenePath}`
|
|
2834
|
+
);
|
|
2559
2835
|
}
|
|
2560
2836
|
const stage_canvas = document.createElement("canvas");
|
|
2561
2837
|
stage_canvas.width = pdfWidth;
|
|
@@ -2580,20 +2856,32 @@ var NetlessAppPresentation = {
|
|
|
2580
2856
|
const img = document.createElement("img");
|
|
2581
2857
|
await new Promise((resolve, reject) => {
|
|
2582
2858
|
img.onload = () => resolve();
|
|
2583
|
-
img.onerror = () => reject(
|
|
2584
|
-
|
|
2585
|
-
|
|
2859
|
+
img.onerror = () => reject(
|
|
2860
|
+
new Error(
|
|
2861
|
+
`[Presentation]: failed to load PDF page image, page index: ${index}`
|
|
2862
|
+
)
|
|
2863
|
+
);
|
|
2586
2864
|
img.src = url;
|
|
2587
2865
|
});
|
|
2588
2866
|
stage.drawImage(img, 0, 0, width2, height2);
|
|
2589
2867
|
wb.clearRect(0, 0, pdfWidth, pdfHeight);
|
|
2590
2868
|
const name = (_a2 = p.name) != null ? _a2 : String(index + 1);
|
|
2591
2869
|
if (scenes.some((scene) => scene.name == name)) {
|
|
2592
|
-
const camera = {
|
|
2870
|
+
const camera = {
|
|
2871
|
+
centerX: 0,
|
|
2872
|
+
centerY: 0,
|
|
2873
|
+
scale: Math.min(wb_canvas.width / width2, wb_canvas.height / height2)
|
|
2874
|
+
};
|
|
2593
2875
|
const sPath = `${scenePath}/${name}`;
|
|
2594
2876
|
const windowManger = context.getWindowManager();
|
|
2595
2877
|
if (windowManger._appliancePlugin) {
|
|
2596
|
-
await windowManger._appliancePlugin.screenshotToCanvasAsync(
|
|
2878
|
+
await windowManger._appliancePlugin.screenshotToCanvasAsync(
|
|
2879
|
+
wb,
|
|
2880
|
+
sPath,
|
|
2881
|
+
wb_canvas.width,
|
|
2882
|
+
wb_canvas.height,
|
|
2883
|
+
camera
|
|
2884
|
+
);
|
|
2597
2885
|
} else {
|
|
2598
2886
|
await view.screenshotToCanvasAsync(
|
|
2599
2887
|
wb,
|
|
@@ -2640,14 +2928,20 @@ var NetlessAppPresentation = {
|
|
|
2640
2928
|
throw error;
|
|
2641
2929
|
}
|
|
2642
2930
|
};
|
|
2643
|
-
dispose2.add(
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2931
|
+
dispose2.add(
|
|
2932
|
+
listen(
|
|
2933
|
+
window,
|
|
2934
|
+
"message",
|
|
2935
|
+
(ev) => {
|
|
2936
|
+
if (ev.data && ev.data.type == "@netless/_request_save_pdf_" && ev.data.appId == context.appId) {
|
|
2937
|
+
toPdf().catch((err) => {
|
|
2938
|
+
warn(err);
|
|
2939
|
+
reportProgress(100, null);
|
|
2940
|
+
});
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2943
|
+
)
|
|
2944
|
+
);
|
|
2651
2945
|
const setDocsViewReadonly = (bol) => {
|
|
2652
2946
|
app.setDocsViewReadonly(bol);
|
|
2653
2947
|
};
|
|
@@ -2658,19 +2952,57 @@ var NetlessAppPresentation = {
|
|
|
2658
2952
|
scrollbar.setReadonly(bol);
|
|
2659
2953
|
}
|
|
2660
2954
|
};
|
|
2661
|
-
const controller = {
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2955
|
+
const controller = {
|
|
2956
|
+
app,
|
|
2957
|
+
view,
|
|
2958
|
+
context,
|
|
2959
|
+
jumpPage,
|
|
2960
|
+
prevPage,
|
|
2961
|
+
nextPage,
|
|
2962
|
+
jumpPageAsync,
|
|
2963
|
+
prevPageAsync,
|
|
2964
|
+
nextPageAsync,
|
|
2965
|
+
pageState,
|
|
2966
|
+
toPdf,
|
|
2967
|
+
log,
|
|
2968
|
+
setDocsViewReadonly,
|
|
2969
|
+
setReadonly,
|
|
2970
|
+
moveCamera,
|
|
2971
|
+
getOriginScale,
|
|
2972
|
+
getScale,
|
|
2973
|
+
getPageSize,
|
|
2974
|
+
screenshotCurrentPageAsync
|
|
2975
|
+
};
|
|
2976
|
+
dispose2.add(
|
|
2977
|
+
listen(
|
|
2978
|
+
window,
|
|
2979
|
+
"message",
|
|
2980
|
+
(ev) => {
|
|
2981
|
+
if (ev.data === "@netless/_presentation_") {
|
|
2982
|
+
if (typeof window !== "undefined")
|
|
2983
|
+
dispose2.make(() => {
|
|
2984
|
+
const debug = window._presentation_ || (window._presentation_ = /* @__PURE__ */ new Set());
|
|
2985
|
+
debug.add(controller);
|
|
2986
|
+
return () => debug.delete(controller);
|
|
2987
|
+
});
|
|
2988
|
+
console.log(controller);
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
)
|
|
2992
|
+
);
|
|
2993
|
+
const setupReadyTimeout = (_d = options.setupReadyTimeout) != null ? _d : DEFAULT_SETUP_READY_TIMEOUT;
|
|
2994
|
+
return prepareScenesPromise.then(async () => {
|
|
2995
|
+
const loaded = await waitForCurrentPageImage(view, setupReadyTimeout, () => disposed);
|
|
2996
|
+
if (!loaded) {
|
|
2997
|
+
warn(`[Presentation] setup ready wait timed out after ${setupReadyTimeout}ms`);
|
|
2998
|
+
}
|
|
2999
|
+
return controller;
|
|
3000
|
+
});
|
|
3001
|
+
},
|
|
3002
|
+
teardown(context) {
|
|
3003
|
+
var _a;
|
|
3004
|
+
(_a = teardownByContext.get(context)) == null ? void 0 : _a();
|
|
3005
|
+
teardownByContext.delete(context);
|
|
2674
3006
|
}
|
|
2675
3007
|
};
|
|
2676
3008
|
var AppPresentation = class extends Presentation {
|
|
@@ -2690,19 +3022,29 @@ var AppPresentation = class extends Presentation {
|
|
|
2690
3022
|
if (0 <= index && index < this.pages.length) {
|
|
2691
3023
|
this.jumpPage(index);
|
|
2692
3024
|
} else {
|
|
2693
|
-
(_a = this.warn) == null ? void 0 : _a.call(
|
|
3025
|
+
(_a = this.warn) == null ? void 0 : _a.call(
|
|
3026
|
+
this,
|
|
3027
|
+
`[Presentation]: page index ${index} out of bounds [0, ${this.pages.length - 1}]`
|
|
3028
|
+
);
|
|
2694
3029
|
}
|
|
2695
3030
|
}
|
|
2696
3031
|
};
|
|
2697
3032
|
function createPresentation(box, pages, jumpPage, pageIndex$, view, thumbnail, useClipView) {
|
|
2698
3033
|
box.mountStyles(style_default);
|
|
2699
|
-
const app = new AppPresentation({
|
|
3034
|
+
const app = new AppPresentation({
|
|
3035
|
+
pages,
|
|
3036
|
+
readonly: box.readonly,
|
|
3037
|
+
jumpPage,
|
|
3038
|
+
thumbnail
|
|
3039
|
+
});
|
|
2700
3040
|
app.box = box;
|
|
2701
3041
|
box.mountContent(app.contentDOM);
|
|
2702
3042
|
box.mountFooter(app.footerDOM);
|
|
2703
|
-
app.dispose.add(
|
|
2704
|
-
|
|
2705
|
-
|
|
3043
|
+
app.dispose.add(
|
|
3044
|
+
pageIndex$.subscribe((pageIndex) => {
|
|
3045
|
+
app.setPageIndex(pageIndex);
|
|
3046
|
+
})
|
|
3047
|
+
);
|
|
2706
3048
|
if (useClipView && view) {
|
|
2707
3049
|
const onCameraUpdatedEffectForMaskView = (0, import_debounce2.default)(() => {
|
|
2708
3050
|
const { width: pageWidth, height: pageHeight } = app.page() || {};
|
|
@@ -2711,8 +3053,12 @@ function createPresentation(box, pages, jumpPage, pageIndex$, view, thumbnail, u
|
|
|
2711
3053
|
}
|
|
2712
3054
|
const { scale } = view.camera;
|
|
2713
3055
|
const { width, height } = view.size;
|
|
2714
|
-
const pageRatioX = Math.round(
|
|
2715
|
-
|
|
3056
|
+
const pageRatioX = Math.round(
|
|
3057
|
+
(1 - pageWidth * scale / width) / 2 * 100
|
|
3058
|
+
);
|
|
3059
|
+
const pageRatioY = Math.round(
|
|
3060
|
+
(1 - pageHeight * scale / height) / 2 * 100
|
|
3061
|
+
);
|
|
2716
3062
|
app.whiteboardDOM.style.clipPath = `inset(${pageRatioY}% ${pageRatioX}%)`;
|
|
2717
3063
|
}, 50);
|
|
2718
3064
|
onCameraUpdatedEffectForMaskView();
|
|
@@ -2737,7 +3083,7 @@ var install = (register, options = {}) => {
|
|
|
2737
3083
|
};
|
|
2738
3084
|
|
|
2739
3085
|
// src/index.ts
|
|
2740
|
-
var version = "0.1.
|
|
3086
|
+
var version = "0.1.13-beta.1";
|
|
2741
3087
|
|
|
2742
3088
|
exports.NetlessAppPresentation = NetlessAppPresentation;
|
|
2743
3089
|
exports.Presentation = Presentation;
|