@netless/slide 1.4.61-beta.0 → 1.4.62-alpha.0

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 CHANGED
@@ -4,6 +4,12 @@
4
4
 
5
5
  ## changelog
6
6
 
7
+ ### 1.4.61 (2026-09-23)
8
+ * 修复部分 PPT 中点击元素无法触发动画的问题
9
+ * 修复重复触发条件导致动画重复推进的问题
10
+ * 修复 PPT 冻结、恢复和销毁并发执行时的时序问题
11
+ * `frozen()`、`release()`、`destroy()` 支持返回 Promise,便于等待操作完成
12
+
7
13
  ### 1.4.60 (2026-09-21)
8
14
  * 新增 PPT 媒体权限回调和点击恢复接口:`onPptMediaPermissionRequest(callback)`、`playPptMedia()`
9
15
  * 修复部分移动浏览器中 PPT 音视频无法自动播放或恢复的问题
@@ -11,7 +11,6 @@ export declare class FrozenTaskManager {
11
11
  private isDestroy;
12
12
  private runningTask?;
13
13
  private schedule;
14
- private getRunningTask;
15
14
  addTask(type: "frozen" | "release", fn: () => Promise<void>): Promise<void>;
16
15
  destroy(): Promise<void>;
17
16
  }
@@ -3,70 +3,56 @@ var FrozenTaskManager = /** @class */ (function () {
3
3
  var _this = this;
4
4
  this.tasks = [];
5
5
  this.isDestroy = false;
6
+ this.isScheduling = false;
6
7
  this.schedule = function () {
7
- if (_this.runningTask || _this.isDestroy) {
8
- return;
9
- }
8
+ _this.isScheduling = true;
10
9
  var task = _this.tasks.shift();
11
- if (!task) {
12
- return;
10
+ if (task && !_this.isDestroy) {
11
+ task.status = "running";
12
+ task.fn.apply(null).then(function () {
13
+ if (_this.tasks.length > 0) {
14
+ setTimeout(_this.schedule);
15
+ }
16
+ else {
17
+ _this.isScheduling = false;
18
+ }
19
+ }).catch(function () {
20
+ if (_this.tasks.length > 0) {
21
+ setTimeout(_this.schedule);
22
+ }
23
+ else {
24
+ _this.isScheduling = false;
25
+ }
26
+ });
13
27
  }
14
- task.status = "running";
15
- _this.runningTask = task;
16
- void task.fn.apply(null).then(task.resolve, task.reject).finally(function () {
17
- if (_this.runningTask === task) {
18
- _this.runningTask = undefined;
19
- }
20
- if (!_this.isDestroy && _this.tasks.length > 0) {
21
- setTimeout(_this.schedule);
22
- }
23
- });
24
28
  };
25
29
  }
26
30
  FrozenTaskManager.prototype.getRunningTask = function () {
27
- var _a;
28
- return (_a = this.runningTask) !== null && _a !== void 0 ? _a : null;
31
+ if (this.tasks[0] && this.tasks[0].status === "running") {
32
+ return this.tasks[0];
33
+ }
34
+ return null;
29
35
  };
30
36
  FrozenTaskManager.prototype.addTask = function (type, fn) {
31
- if (this.isDestroy) {
32
- return Promise.resolve();
33
- }
34
- var runningTask = this.getRunningTask();
35
- if (runningTask && type === runningTask.type) {
36
- return runningTask.promise;
37
- }
38
- var queuedTask = this.tasks.find(function (task) { return task.type === type; });
39
- if (queuedTask) {
40
- return queuedTask.promise;
41
- }
42
- var resolveTask;
43
- var rejectTask;
44
- var promise = new Promise(function (resolve, reject) {
45
- resolveTask = resolve;
46
- rejectTask = reject;
47
- });
48
- // Existing callers are allowed to ignore frozen()/release(). Keep the
49
- // original promise observable to awaiters without creating an
50
- // unhandled rejection for legacy fire-and-forget calls.
51
- promise.catch(function () { return undefined; });
52
37
  var task = {
53
38
  type: type,
54
39
  status: "wait",
55
40
  fn: fn,
56
- promise: promise,
57
- resolve: resolveTask,
58
- reject: rejectTask,
59
41
  };
60
- this.tasks.push(task);
61
- this.schedule();
62
- return promise;
42
+ var runningTask = this.getRunningTask();
43
+ if (runningTask && type === runningTask.type) {
44
+ return;
45
+ }
46
+ else {
47
+ this.tasks = this.tasks.filter(function (v) { return v.type !== type; });
48
+ this.tasks.push(task);
49
+ if (!this.isScheduling) {
50
+ this.schedule();
51
+ }
52
+ }
63
53
  };
64
54
  FrozenTaskManager.prototype.destroy = function () {
65
- var _a, _b;
66
55
  this.isDestroy = true;
67
- var pending = this.tasks.splice(0, this.tasks.length);
68
- pending.forEach(function (task) { return task.resolve(); });
69
- return (_b = (_a = this.runningTask) === null || _a === void 0 ? void 0 : _a.promise.catch(function () { return undefined; })) !== null && _b !== void 0 ? _b : Promise.resolve();
70
56
  };
71
57
  return FrozenTaskManager;
72
58
  }());
package/lib/Slide.d.ts CHANGED
@@ -327,6 +327,12 @@ export interface BasicSyncEvent {
327
327
  uuid?: string;
328
328
  incrId?: number;
329
329
  clientId?: string;
330
+ /** Transport author ID attached when the dispatched event is received. */
331
+ authorId?: number;
332
+ }
333
+ export interface SyncEventOrigin {
334
+ clientId?: string;
335
+ authorId?: number;
330
336
  }
331
337
  export interface SyncMediaPlayEvent extends BasicSyncEvent {
332
338
  type: "mediaPlay";
@@ -377,8 +383,8 @@ export interface SlideEventEmitter {
377
383
  removeListener(event: keyof typeof SLIDE_EVENTS, fn?: any): this;
378
384
  emit(event: typeof SLIDE_EVENTS.renderStart, index: number): boolean;
379
385
  on(event: typeof SLIDE_EVENTS.renderStart, listener: (index: number) => void): this;
380
- emit(event: typeof SLIDE_EVENTS.renderEnd, index: number): boolean;
381
- on(event: typeof SLIDE_EVENTS.renderEnd, listener: (index: number) => void): this;
386
+ emit(event: typeof SLIDE_EVENTS.renderEnd, index: number, origin?: SyncEventOrigin): boolean;
387
+ on(event: typeof SLIDE_EVENTS.renderEnd, listener: (index: number, origin?: SyncEventOrigin) => void): this;
382
388
  emit(event: typeof SLIDE_EVENTS.slideChange, nextSlideIndex: number): boolean;
383
389
  on(event: typeof SLIDE_EVENTS.slideChange, listener: (nextSlideIndex: number) => void): this;
384
390
  emit(event: typeof SLIDE_EVENTS.syncDispatch, args: SyncEvent): boolean;
@@ -401,8 +407,8 @@ export interface SlideEventEmitter {
401
407
  on(event: typeof SLIDE_EVENTS.mainSeqStepStart, listener: (index: number) => void): this;
402
408
  emit(event: typeof SLIDE_EVENTS.mainSeqStepEnd, index: number): boolean;
403
409
  on(event: typeof SLIDE_EVENTS.mainSeqStepEnd, listener: (index: number) => void): this;
404
- emit(event: typeof SLIDE_EVENTS.stateChange, state: ISlideState): boolean;
405
- on(event: typeof SLIDE_EVENTS.stateChange, listener: (state: ISlideState) => void): this;
410
+ emit(event: typeof SLIDE_EVENTS.stateChange, state: ISlideState, origin?: SyncEventOrigin): boolean;
411
+ on(event: typeof SLIDE_EVENTS.stateChange, listener: (state: ISlideState, origin?: SyncEventOrigin) => void): this;
406
412
  emit(event: typeof SLIDE_EVENTS.syncEventLag): boolean;
407
413
  on(event: typeof SLIDE_EVENTS.syncEventLag, listener: () => void): this;
408
414
  emit(event: typeof SLIDE_EVENTS.slideStepEnd): boolean;
@@ -476,6 +482,15 @@ export declare class Slide extends Slide_base {
476
482
  private pptMediaPermissionNotified;
477
483
  private pptMediaPermissionRenotifyPending;
478
484
  private pendingPptMediaState?;
485
+ private currentRenderEventOrigin?;
486
+ private currentRenderSlideIndex?;
487
+ private currentRenderEventSource?;
488
+ private isRenderEventOriginActive;
489
+ private mainSeqEventOwner?;
490
+ private interactiveSeqEventOwners;
491
+ private mediaEventOwners;
492
+ private applyingMediaEvents;
493
+ private applyingMediaEventNonce;
479
494
  private renderingIndex;
480
495
  private frameWidth;
481
496
  private frameHeight;
@@ -487,6 +502,7 @@ export declare class Slide extends Slide_base {
487
502
  private mode;
488
503
  private enableGlobalClick;
489
504
  private lastEmitedState;
505
+ private lastEmitedStateOrigin?;
490
506
  private syncQueue;
491
507
  private selfSyncEvents;
492
508
  private playerController;
@@ -558,6 +574,20 @@ export declare class Slide extends Slide_base {
558
574
  updateFixedFrameSize(width: number, height: number, callback?: () => void): void;
559
575
  private _resizeView;
560
576
  private receiveSyncHandler;
577
+ private applySyncEvent;
578
+ private handleSyncEvent;
579
+ private getSyncEventOrigin;
580
+ private getStateEventOrigin;
581
+ private isSamePlayerEventSource;
582
+ private createStateEventOwner;
583
+ private findSequenceEventOwner;
584
+ private getMediaEventOrigin;
585
+ private setInteractiveSeqEventOwner;
586
+ private setMediaEventOwner;
587
+ private beginApplyingMediaEvent;
588
+ private finishApplyingMediaEvent;
589
+ private invalidateApplyingMediaEvent;
590
+ private emitRenderEnd;
561
591
  /**
562
592
  * Set the state of the entire slide, the slide will update the screen with the incoming state.
563
593
  * It is called when synchronizing the whole.
@@ -677,6 +707,7 @@ export declare class Slide extends Slide_base {
677
707
  */
678
708
  doRenderSlide(index: number, isForward?: boolean): Promise<void>;
679
709
  private enqueueRenderSlide;
710
+ private withRenderEventOrigin;
680
711
  getSnapshot(): string | null;
681
712
  /**
682
713
  * 执行下一个主序列动画