@netless/slide 1.4.55-alpha.1 → 1.4.55-alpha.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/README.md +31 -0
- package/lib/Lock.d.ts +3 -1
- package/lib/Lock.js +17 -1
- package/lib/Slide.d.ts +20 -5
- 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 +4 -3
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 边界,避免阴影被裁剪
|
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.
|
|
@@ -444,6 +447,7 @@ export declare class Slide extends Slide_base {
|
|
|
444
447
|
private renderingTaskManager;
|
|
445
448
|
private isLoading;
|
|
446
449
|
private interactive;
|
|
450
|
+
private syncCatchUpInputBlocked;
|
|
447
451
|
private anchor;
|
|
448
452
|
private tracker;
|
|
449
453
|
private player?;
|
|
@@ -459,6 +463,7 @@ export declare class Slide extends Slide_base {
|
|
|
459
463
|
private enableGlobalClick;
|
|
460
464
|
private lastEmitedState;
|
|
461
465
|
private syncQueue;
|
|
466
|
+
private selfSyncEvents;
|
|
462
467
|
private playerController;
|
|
463
468
|
private lock;
|
|
464
469
|
private isInitResized;
|
|
@@ -482,6 +487,10 @@ export declare class Slide extends Slide_base {
|
|
|
482
487
|
private get dispatchIncrId();
|
|
483
488
|
constructor(initConfig: ISlideConfig);
|
|
484
489
|
private _updateVolumeByStaticAdjuster;
|
|
490
|
+
private handleSyncQueueCompact;
|
|
491
|
+
private handleSyncQueueCompactRenderComplete;
|
|
492
|
+
private handleSyncQueueCatchUpStateChange;
|
|
493
|
+
private updatePlayerInteractive;
|
|
485
494
|
private recoverHandler;
|
|
486
495
|
private reportError;
|
|
487
496
|
initSlideConfig(config: ISlideConfig): ISlideConfig;
|
|
@@ -622,6 +631,7 @@ export declare class Slide extends Slide_base {
|
|
|
622
631
|
* @param isForward Whether to flip forward or backward, affecting the page transition animation.
|
|
623
632
|
*/
|
|
624
633
|
doRenderSlide(index: number, isForward?: boolean): Promise<void>;
|
|
634
|
+
private enqueueRenderSlide;
|
|
625
635
|
getSnapshot(): string | null;
|
|
626
636
|
/**
|
|
627
637
|
* 执行下一个主序列动画
|
|
@@ -647,6 +657,11 @@ export declare class Slide extends Slide_base {
|
|
|
647
657
|
* @param val boolean
|
|
648
658
|
*/
|
|
649
659
|
setInteractive(val: boolean): void;
|
|
660
|
+
/**
|
|
661
|
+
* Set how received synchronization events are scheduled.
|
|
662
|
+
* Changing the policy does not reorder or clear the current pending queue by itself.
|
|
663
|
+
*/
|
|
664
|
+
setSyncEventQueuePolicy(policy: SyncEventQueuePolicy): void;
|
|
650
665
|
/**
|
|
651
666
|
* Pause playback, asynchronous operation.
|
|
652
667
|
*/
|