@netless/slide 1.4.55-alpha.1 → 1.4.55-alpha.3
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/README.md +31 -0
- package/lib/FrozenMediaState.d.ts +13 -0
- package/lib/Lock.d.ts +3 -1
- package/lib/Lock.js +17 -1
- package/lib/Slide.d.ts +33 -6
- package/lib/Slide.js +28 -28
- package/lib/SyncTaskManager.d.ts +43 -3
- package/lib/SyncTaskManager.js +182 -10
- package/lib/global.js +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -2,9 +2,40 @@
|
|
|
2
2
|
|
|
3
3
|
## [示例及具体文档参考](https://github.com/netless-io/netless-slide-demo)
|
|
4
4
|
|
|
5
|
+
## interactive 客户端的同步队列追最新策略
|
|
6
|
+
|
|
7
|
+
`@netless/slide` 默认按 FIFO 顺序执行所有接收到的同步事件。对于需要在弱网积压时优先追赶最新页面的 interactive 客户端,可以显式启用 `latest-pending-render`;可写端和只读端都可以使用:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
const slide = new Slide({
|
|
11
|
+
// 其他配置
|
|
12
|
+
syncEventQueuePolicy: "latest-pending-render",
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
slide.setSyncEventQueuePolicy("fifo");
|
|
16
|
+
slide.setSyncEventQueuePolicy("latest-pending-render");
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
该策略只处理尚未开始执行的 pending 事件:
|
|
20
|
+
|
|
21
|
+
- 新的 `renderSlide` 到达时,删除同一资源段内排在它之前的 pending 翻页、`nextStep`、`prevStep`、交互动画和媒体操作。
|
|
22
|
+
- 保留最新 `renderSlide`,以及它之后到达的所有操作,并继续按 FIFO 执行。
|
|
23
|
+
- `setResource` 和未知事件是硬边界,不会被删除,也不会跨越边界压缩。
|
|
24
|
+
- 已经开始执行的事件不会被取消;该策略不保证完全不显示 running 中间页。
|
|
25
|
+
- 动态切换策略本身不会清空或重排已有队列;切换后新到达的 `renderSlide` 才会触发压缩。
|
|
26
|
+
- latest 策略下开始执行远端 `renderSlide`,或远端事件形成 pending 积压后,Slide 会暂时阻止本地 `nextStep()`、`prevStep()`、`renderSlide()`、`doRenderSlide()` 和画布交互;同步接收、状态恢复和队列执行不受影响。本机事件优先通过现有 Lock 的 UUID 回包识别,并以 `clientId` 作为补充,不会锁住正在操作的当前控制者。
|
|
27
|
+
- 临时输入锁在同步队列重新空闲后解除,并恢复调用方最近一次通过 `setInteractive()` 设置的权限;不会把原本的只读端恢复成可写。
|
|
28
|
+
|
|
29
|
+
该能力不会根据 `interactive` 自动开启。调用方应通过自己的灰度开关显式选择;关闭策略时可以恢复为 `fifo`,不会修改调用方原有的本地交互权限。
|
|
30
|
+
|
|
31
|
+
该策略只在 Slide 的 `mode: "interactive"` 下生效;`sync`、`local` 和 `addLink` mode 会强制使用 `fifo`。这项 mode 保护不能替代调用方的只读权限与 feature flag 判断。
|
|
32
|
+
|
|
33
|
+
实际发生压缩时,SDK 会通过现有 logger/tracker 记录丢弃分类、保留页码、目标事件接收时间、对应渲染完成时间和追赶输入锁状态;记录中不包含事件 UUID、资源 URL 或 token。
|
|
34
|
+
|
|
5
35
|
## changelog
|
|
6
36
|
|
|
7
37
|
### 未发布
|
|
38
|
+
* 增加 `latest-pending-render` 同步队列策略,弱网积压时丢弃最后翻页前尚未执行的中间页面操作,并在追赶期间阻止本地输入
|
|
8
39
|
* 修复 PPT 图形内阴影(`innerShadow`)被错误渲染为不透明黑边的问题
|
|
9
40
|
* 按转换数据中的颜色、模糊半径、距离和方向渲染柔化内阴影
|
|
10
41
|
* 使用 SDF 判定形状内边缘,并扩展滤镜与 SDF 边界,避免阴影被裁剪
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface FrozenMediaPlaybackState {
|
|
2
|
+
type: "pause" | "play";
|
|
3
|
+
time: number;
|
|
4
|
+
}
|
|
5
|
+
export declare type FrozenMediaTimes = {
|
|
6
|
+
[key: string]: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function captureFrozenMediaTimes(mediaState: {
|
|
9
|
+
[key: string]: FrozenMediaPlaybackState;
|
|
10
|
+
}, frozenTime: number): FrozenMediaTimes;
|
|
11
|
+
export declare function applyFrozenMediaTimes(mediaState: {
|
|
12
|
+
[key: string]: FrozenMediaPlaybackState;
|
|
13
|
+
}, frozenMediaTimes: FrozenMediaTimes, releaseTime: number): void;
|
package/lib/Lock.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export declare class Lock {
|
|
2
2
|
private autoUnlock;
|
|
3
|
+
private localKeyAutoRemove;
|
|
4
|
+
private localKeys;
|
|
3
5
|
private locks;
|
|
4
6
|
private available;
|
|
5
7
|
constructor(available: boolean);
|
|
6
8
|
addLock(type: string, key: string): void;
|
|
7
|
-
unlock(type: string, key: string | null | undefined):
|
|
9
|
+
unlock(type: string, key: string | null | undefined): boolean;
|
|
8
10
|
isLocked(type: string): boolean;
|
|
9
11
|
}
|
package/lib/Lock.js
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
var Lock = /** @class */ (function () {
|
|
5
5
|
function Lock(available) {
|
|
6
6
|
this.autoUnlock = Object.create(null);
|
|
7
|
+
this.localKeyAutoRemove = Object.create(null);
|
|
8
|
+
this.localKeys = Object.create(null);
|
|
7
9
|
this.locks = Object.create(null);
|
|
8
10
|
this.available = false;
|
|
9
11
|
this.available = available;
|
|
@@ -14,18 +16,32 @@ var Lock = /** @class */ (function () {
|
|
|
14
16
|
return;
|
|
15
17
|
}
|
|
16
18
|
this.locks[type] = key;
|
|
19
|
+
this.localKeys[key] = true;
|
|
20
|
+
this.localKeyAutoRemove[key] = window.setTimeout(function () {
|
|
21
|
+
delete _this.localKeys[key];
|
|
22
|
+
delete _this.localKeyAutoRemove[key];
|
|
23
|
+
}, 60 * 1000);
|
|
17
24
|
this.autoUnlock[type] = window.setTimeout(function () {
|
|
18
25
|
delete _this.locks[type];
|
|
26
|
+
delete _this.autoUnlock[type];
|
|
19
27
|
}, 3000);
|
|
20
28
|
};
|
|
21
29
|
Lock.prototype.unlock = function (type, key) {
|
|
22
30
|
if (!this.available) {
|
|
23
|
-
return;
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
var isLocalEvent = !!key && !!this.localKeys[key];
|
|
34
|
+
if (key && isLocalEvent) {
|
|
35
|
+
window.clearTimeout(this.localKeyAutoRemove[key]);
|
|
36
|
+
delete this.localKeys[key];
|
|
37
|
+
delete this.localKeyAutoRemove[key];
|
|
24
38
|
}
|
|
25
39
|
if (key && this.locks[type] && this.locks[type] === key) {
|
|
26
40
|
window.clearTimeout(this.autoUnlock[type]);
|
|
27
41
|
delete this.locks[type];
|
|
42
|
+
delete this.autoUnlock[type];
|
|
28
43
|
}
|
|
44
|
+
return isLocalEvent;
|
|
29
45
|
};
|
|
30
46
|
Lock.prototype.isLocked = function (type) {
|
|
31
47
|
if (!this.available) {
|
package/lib/Slide.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { SlideError, VolumeAdjuster } from "@netless/ppt-player";
|
|
2
2
|
import { IPlugin } from "@netless/plugin-system";
|
|
3
|
+
import type { SyncEventQueuePolicy } from "./SyncTaskManager";
|
|
3
4
|
import { AliTrackLogger } from "./AliTrackLogger";
|
|
4
5
|
import { preloadResource } from "./global";
|
|
5
6
|
export { ErrorType, PreloadCancelledError } from "@netless/ppt-player";
|
|
6
|
-
export
|
|
7
|
+
export type { SyncEventQueuePolicy } from "./SyncTaskManager";
|
|
7
8
|
export declare type UrlInterrupter = (url: string) => Promise<string>;
|
|
8
9
|
export interface ILoaderDelegate {
|
|
9
10
|
/**
|
|
@@ -178,10 +179,6 @@ export interface ISlideRenderOptions {
|
|
|
178
179
|
*/
|
|
179
180
|
transitionResolutionLevel?: number;
|
|
180
181
|
antialias?: boolean;
|
|
181
|
-
/** Maximum compressed bytes accepted for one client-decoded GIF. */
|
|
182
|
-
localGifMaxCompressedBytes?: number;
|
|
183
|
-
/** Maximum estimated GIF working set for one cached slide. */
|
|
184
|
-
localGifMaxWorkingSetBytes?: number;
|
|
185
182
|
}
|
|
186
183
|
export interface INavigatorDelegate {
|
|
187
184
|
gotoPage?: (index: number) => void;
|
|
@@ -213,6 +210,12 @@ export interface ISlideConfig {
|
|
|
213
210
|
* "local" Local mode, no synchronization events will be triggered
|
|
214
211
|
*/
|
|
215
212
|
mode: "interactive" | "sync" | "local" | "addLink";
|
|
213
|
+
/**
|
|
214
|
+
* Queue policy for received synchronization events.
|
|
215
|
+
* Default is "fifo". "latest-pending-render" lets interactive clients skip pending intermediate pages.
|
|
216
|
+
* Non-interactive modes always use "fifo".
|
|
217
|
+
*/
|
|
218
|
+
syncEventQueuePolicy?: SyncEventQueuePolicy;
|
|
216
219
|
/**
|
|
217
220
|
* Whether to enable global clicking, after turning on, as long as you click within the ppt viewport range,
|
|
218
221
|
* and do not trigger interactive elements inside ppt, it will trigger the next action.
|
|
@@ -281,13 +284,18 @@ export interface ISlideConfig {
|
|
|
281
284
|
skipActionWhenFrozen?: boolean;
|
|
282
285
|
enableAutoForward?: boolean;
|
|
283
286
|
customLinks?: CustomLink[];
|
|
287
|
+
/**
|
|
288
|
+
* Disable the built-in ResizeObserver and rely on external notifyFrameResize() calls.
|
|
289
|
+
* Set this to true when using window-manager's boxSizeChange event as the resize signal.
|
|
290
|
+
* @default false
|
|
291
|
+
*/
|
|
292
|
+
disableFrameResizeObserver?: boolean;
|
|
284
293
|
resourceMaxRetries?: number;
|
|
285
294
|
onResourceMaxRetries?: (url: string, error: Error) => void;
|
|
286
295
|
}
|
|
287
296
|
interface MediaState {
|
|
288
297
|
type: "pause" | "play";
|
|
289
298
|
time: number;
|
|
290
|
-
frozenTime?: number;
|
|
291
299
|
fullscreen?: boolean;
|
|
292
300
|
}
|
|
293
301
|
interface TimeNodeSeqState {
|
|
@@ -438,12 +446,14 @@ export declare class Slide extends Slide_base {
|
|
|
438
446
|
private userInputTime;
|
|
439
447
|
private isSyncingSlideState;
|
|
440
448
|
private frozenTaskManager;
|
|
449
|
+
private frozenMediaTimes;
|
|
441
450
|
private randomId;
|
|
442
451
|
private resize;
|
|
443
452
|
private isAnimating;
|
|
444
453
|
private renderingTaskManager;
|
|
445
454
|
private isLoading;
|
|
446
455
|
private interactive;
|
|
456
|
+
private syncCatchUpInputBlocked;
|
|
447
457
|
private anchor;
|
|
448
458
|
private tracker;
|
|
449
459
|
private player?;
|
|
@@ -459,6 +469,7 @@ export declare class Slide extends Slide_base {
|
|
|
459
469
|
private enableGlobalClick;
|
|
460
470
|
private lastEmitedState;
|
|
461
471
|
private syncQueue;
|
|
472
|
+
private selfSyncEvents;
|
|
462
473
|
private playerController;
|
|
463
474
|
private lock;
|
|
464
475
|
private isInitResized;
|
|
@@ -482,6 +493,10 @@ export declare class Slide extends Slide_base {
|
|
|
482
493
|
private get dispatchIncrId();
|
|
483
494
|
constructor(initConfig: ISlideConfig);
|
|
484
495
|
private _updateVolumeByStaticAdjuster;
|
|
496
|
+
private handleSyncQueueCompact;
|
|
497
|
+
private handleSyncQueueCompactRenderComplete;
|
|
498
|
+
private handleSyncQueueCatchUpStateChange;
|
|
499
|
+
private updatePlayerInteractive;
|
|
485
500
|
private recoverHandler;
|
|
486
501
|
private reportError;
|
|
487
502
|
initSlideConfig(config: ISlideConfig): ISlideConfig;
|
|
@@ -500,6 +515,12 @@ export declare class Slide extends Slide_base {
|
|
|
500
515
|
private updateStageCountLimit;
|
|
501
516
|
private setMedianControllerAttribute;
|
|
502
517
|
private frameResizeHandler;
|
|
518
|
+
/**
|
|
519
|
+
* Notify the slide that its frame container may have changed size.
|
|
520
|
+
* Call this when using an external resize signal (e.g. window-manager's boxSizeChange event)
|
|
521
|
+
* instead of the built-in ResizeObserver.
|
|
522
|
+
*/
|
|
523
|
+
notifyFrameResize(): void;
|
|
503
524
|
/**
|
|
504
525
|
* Update ppt fixed height and width, this method only takes effect when the fixedFrameSize configuration item is set.
|
|
505
526
|
* @param width Width value that needs to be updated, unit px.
|
|
@@ -622,6 +643,7 @@ export declare class Slide extends Slide_base {
|
|
|
622
643
|
* @param isForward Whether to flip forward or backward, affecting the page transition animation.
|
|
623
644
|
*/
|
|
624
645
|
doRenderSlide(index: number, isForward?: boolean): Promise<void>;
|
|
646
|
+
private enqueueRenderSlide;
|
|
625
647
|
getSnapshot(): string | null;
|
|
626
648
|
/**
|
|
627
649
|
* 执行下一个主序列动画
|
|
@@ -647,6 +669,11 @@ export declare class Slide extends Slide_base {
|
|
|
647
669
|
* @param val boolean
|
|
648
670
|
*/
|
|
649
671
|
setInteractive(val: boolean): void;
|
|
672
|
+
/**
|
|
673
|
+
* Set how received synchronization events are scheduled.
|
|
674
|
+
* Changing the policy does not reorder or clear the current pending queue by itself.
|
|
675
|
+
*/
|
|
676
|
+
setSyncEventQueuePolicy(policy: SyncEventQueuePolicy): void;
|
|
650
677
|
/**
|
|
651
678
|
* Pause playback, asynchronous operation.
|
|
652
679
|
*/
|