@inappstory/slide-api 0.1.8 → 0.1.9

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.cjs CHANGED
@@ -2280,12 +2280,13 @@ class Video {
2280
2280
  // clean up memory and cpu processes
2281
2281
  // @ts-ignore
2282
2282
  // _log("onBeforeUnmount", true)
2283
+ // console.log("onBeforeUnmount")
2283
2284
  this._destroyVODPlayer();
2284
2285
  }
2285
2286
  _initVOD(vodData) {
2286
2287
  const onWaiting = () => {
2287
2288
  /**
2288
- * When screen on pause - ignore onWaiting
2289
+ * When screen on pause - ignore onWaiting (or when SlideApi is destroyed)
2289
2290
  * (triggered when video paused, not only when canplay = false)
2290
2291
  */
2291
2292
  if (this._isScreenOnPause) {
@@ -2828,14 +2829,14 @@ class SlideTimeline {
2828
2829
  slideDuration;
2829
2830
  slideDisabledTimer;
2830
2831
  slideReady;
2831
- _afterResumeQueuePush;
2832
+ _afterAppResumeQueuePush;
2832
2833
  sdkApi;
2833
- constructor(slideIndex, slideDuration, slideDisabledTimer, slideReady, _afterResumeQueuePush, sdkApi) {
2834
+ constructor(slideIndex, slideDuration, slideDisabledTimer, slideReady, _afterAppResumeQueuePush, sdkApi) {
2834
2835
  this.slideIndex = slideIndex;
2835
2836
  this.slideDuration = slideDuration;
2836
2837
  this.slideDisabledTimer = slideDisabledTimer;
2837
2838
  this.slideReady = slideReady;
2838
- this._afterResumeQueuePush = _afterResumeQueuePush;
2839
+ this._afterAppResumeQueuePush = _afterAppResumeQueuePush;
2839
2840
  this.sdkApi = sdkApi;
2840
2841
  this.timelineDisabledState = this.slideDisabledTimer ? TimelineDisabledState.disabled : TimelineDisabledState.enabled;
2841
2842
  }
@@ -2992,7 +2993,7 @@ class SlideTimeline {
2992
2993
  // if app is paused (in background) - don't call start timeline (Android issues)
2993
2994
  // @ts-ignore
2994
2995
  // window._log(`Push startDisabledTimeline to queue at state: ${window.slideApi.state}, time: ${new Date().getTime()}`, true);
2995
- this._afterResumeQueuePush(() => {
2996
+ this._afterAppResumeQueuePush(() => {
2996
2997
  // @ts-ignore
2997
2998
  // window._log(`Call startDisabledTimeline at state: ${window.slideApi.state}, time: ${new Date().getTime()}`, true);
2998
2999
  if (this.isSDKSupportUpdateTimeline) {
@@ -3039,7 +3040,7 @@ class Layer {
3039
3040
  _nodeRef;
3040
3041
  _slide;
3041
3042
  _slideReadyPromise;
3042
- _afterResumeQueuePush;
3043
+ _afterAppResumeQueuePush;
3043
3044
  _afterStartInitQueuePush;
3044
3045
  _showNextSlide;
3045
3046
  sdkApi;
@@ -3052,11 +3053,11 @@ class Layer {
3052
3053
  _disabledNavigation;
3053
3054
  _elements = [];
3054
3055
  _timeline;
3055
- constructor(_nodeRef, _slide, _slideReadyPromise, _afterResumeQueuePush, _afterStartInitQueuePush, _showNextSlide, sdkApi) {
3056
+ constructor(_nodeRef, _slide, _slideReadyPromise, _afterAppResumeQueuePush, _afterStartInitQueuePush, _showNextSlide, sdkApi) {
3056
3057
  this._nodeRef = _nodeRef;
3057
3058
  this._slide = _slide;
3058
3059
  this._slideReadyPromise = _slideReadyPromise;
3059
- this._afterResumeQueuePush = _afterResumeQueuePush;
3060
+ this._afterAppResumeQueuePush = _afterAppResumeQueuePush;
3060
3061
  this._afterStartInitQueuePush = _afterStartInitQueuePush;
3061
3062
  this._showNextSlide = _showNextSlide;
3062
3063
  this.sdkApi = sdkApi;
@@ -3067,7 +3068,7 @@ class Layer {
3067
3068
  this._duration = parseInt(this._nodeRef.getAttribute("data-duration") ?? "") || DEFAULT_SLIDE_DURATION;
3068
3069
  this._disabledTimer = this._nodeRef.getAttribute("data-disable-timer") === "1";
3069
3070
  this._disabledNavigation = this._nodeRef.getAttribute("data-disable-navigation") === "1";
3070
- this._timeline = new SlideTimeline(this._slideIndex, this._duration, this._disabledTimer, this._slideReadyPromise, this._afterResumeQueuePush, this.sdkApi);
3071
+ this._timeline = new SlideTimeline(this._slideIndex, this._duration, this._disabledTimer, this._slideReadyPromise, this._afterAppResumeQueuePush, this.sdkApi);
3071
3072
  const onWidgetComplete = (cardId, slideIndex) => {
3072
3073
  // todo if nothing more widgets with disabled timers - we can start layer timeline
3073
3074
  const fallback = () => this._showNextSlide(DEFAULT_SLIDE_DURATION);
@@ -3319,7 +3320,7 @@ class Layer {
3319
3320
  element.onStop();
3320
3321
  }
3321
3322
  }
3322
- async pause(resetVideoTime = false, stopAnimation = false) {
3323
+ async pause(resetVideoTime = false, stopAnimation = false, updateTimeline = true) {
3323
3324
  return new Promise(resolve => {
3324
3325
  const cb = () => {
3325
3326
  let currentTime = this.videoElement?.pause(resetVideoTime) ?? null;
@@ -3337,7 +3338,9 @@ class Layer {
3337
3338
  for (const element of this._elements) {
3338
3339
  element.onPause();
3339
3340
  }
3340
- this.timeline.slidePaused(currentTime);
3341
+ if (updateTimeline) {
3342
+ this.timeline.slidePaused(currentTime);
3343
+ }
3341
3344
  resolve({ currentTime });
3342
3345
  };
3343
3346
  const videoStartedPromise = this.videoElement?.videoStartedPromise;
@@ -3561,16 +3564,16 @@ class TextElementAutoWidthCorrection {
3561
3564
  class Slide {
3562
3565
  _slidesNodesRefs;
3563
3566
  _slideReadyPromise;
3564
- _afterResumeQueuePush;
3567
+ _afterAppResumeQueuePush;
3565
3568
  _afterStartInitQueuePush;
3566
3569
  _showNextSlide;
3567
3570
  sdkApi;
3568
3571
  _layers;
3569
3572
  _start;
3570
- constructor(_slidesNodesRefs, _slideReadyPromise, _afterResumeQueuePush, _afterStartInitQueuePush, _showNextSlide, sdkApi) {
3573
+ constructor(_slidesNodesRefs, _slideReadyPromise, _afterAppResumeQueuePush, _afterStartInitQueuePush, _showNextSlide, sdkApi) {
3571
3574
  this._slidesNodesRefs = _slidesNodesRefs;
3572
3575
  this._slideReadyPromise = _slideReadyPromise;
3573
- this._afterResumeQueuePush = _afterResumeQueuePush;
3576
+ this._afterAppResumeQueuePush = _afterAppResumeQueuePush;
3574
3577
  this._afterStartInitQueuePush = _afterStartInitQueuePush;
3575
3578
  this._showNextSlide = _showNextSlide;
3576
3579
  this.sdkApi = sdkApi;
@@ -3578,7 +3581,7 @@ class Slide {
3578
3581
  if (!this._slidesNodesRefs.length) {
3579
3582
  throw new Error("No slides found.");
3580
3583
  }
3581
- this._layers = this._slidesNodesRefs.map(item => new Layer(item, this, this._slideReadyPromise, this._afterResumeQueuePush, this._afterStartInitQueuePush, this._showNextSlide, this.sdkApi));
3584
+ this._layers = this._slidesNodesRefs.map(item => new Layer(item, this, this._slideReadyPromise, this._afterAppResumeQueuePush, this._afterStartInitQueuePush, this._showNextSlide, this.sdkApi));
3582
3585
  this._activeLayer = this._layers[0];
3583
3586
  }
3584
3587
  _activeLayer;
@@ -3685,6 +3688,7 @@ let SlideApi$1 = class SlideApi {
3685
3688
  _getViewportWidth;
3686
3689
  _getViewportHeight;
3687
3690
  _overlappingActionBarHeight;
3691
+ _separateUserAndAppPause;
3688
3692
  sdkApi;
3689
3693
  constructor(config) {
3690
3694
  this.config = config;
@@ -3694,6 +3698,7 @@ let SlideApi$1 = class SlideApi {
3694
3698
  this._getViewportWidth = config.getViewportWidth;
3695
3699
  this._getViewportHeight = config.getViewportHeight;
3696
3700
  this._overlappingActionBarHeight = config.overlappingActionBarHeight ?? 0;
3701
+ this._separateUserAndAppPause = config.separateUserAndAppPause;
3697
3702
  this.refreshSizes = proxy(this.refreshSizes, this);
3698
3703
  this.initListeners();
3699
3704
  this.refreshSizes();
@@ -3702,10 +3707,10 @@ let SlideApi$1 = class SlideApi {
3702
3707
  if (slideBox && slideBox.innerText.trim() !== "{%content}".replace("{", "{{").replace("}", "}}")) {
3703
3708
  this._slideInInit = null;
3704
3709
  this._slideInRender = true;
3705
- this._init(() => this._slideBoxRenderComplete(null), () => this._slideBoxRenderError(null)).then(({ slide, result, reason }) => {
3710
+ this._init(() => this._slideBoxRenderComplete(null)).then(({ slide, result, reason }) => {
3706
3711
  this._slide = slide;
3707
3712
  if (config.slideLoadedCb != null) {
3708
- config.slideLoadedCb({ slide, result, reason });
3713
+ config.slideLoadedCb({ cardId: slide.cardId, slideIndex: slide.slideIndex, result, reason });
3709
3714
  }
3710
3715
  });
3711
3716
  }
@@ -3715,6 +3720,7 @@ let SlideApi$1 = class SlideApi {
3715
3720
  this.slide.onBeforeUnmount();
3716
3721
  }
3717
3722
  this.destroyListeners();
3723
+ this._state = 13 /* STATE.DESTROYED */;
3718
3724
  }
3719
3725
  initListeners() {
3720
3726
  this._viewport.addEventListener("resize", this.refreshSizes);
@@ -3795,7 +3801,7 @@ let SlideApi$1 = class SlideApi {
3795
3801
  async showSlide(html) {
3796
3802
  const slideBox = this._slideWrapper.querySelector(`.${SlideApi.renderedBoxClassName}`);
3797
3803
  const slideBoxPrerender = this._slideWrapper.querySelector(`.${SlideApi.prerenderBoxClassName}`);
3798
- const _result = { slide: this.slide, result: false, reason: "" };
3804
+ const _result = { cardId: this.slide?.cardId ?? 0, slideIndex: this.slide?.slideIndex ?? 0, result: false, reason: "" };
3799
3805
  if (slideBox && slideBoxPrerender) {
3800
3806
  if (this._slideInRender) {
3801
3807
  this._slideInRender = false;
@@ -3805,12 +3811,17 @@ let SlideApi$1 = class SlideApi {
3805
3811
  this._slideInRender = true;
3806
3812
  slideBoxPrerender.innerHTML = html;
3807
3813
  const prevSlide = this.slide ? Object.assign(Object.create(Object.getPrototypeOf(this.slide)), this.slide) : null;
3808
- const { slide, result, reason } = await this._init(() => this._slideBoxRenderComplete(prevSlide), () => this._slideBoxRenderError(prevSlide));
3814
+ const { slide, result, reason } = await this._init(() => this._slideBoxRenderComplete(prevSlide));
3809
3815
  this._slide = slide;
3810
3816
  _result.result = result;
3811
3817
  _result.reason = reason;
3812
3818
  }
3813
- _result.slide = this.slide;
3819
+ else {
3820
+ _result.result = false;
3821
+ _result.reason = `Element .${SlideApi.renderedBoxClassName} or .${SlideApi.prerenderBoxClassName} does not found in DOM`;
3822
+ }
3823
+ _result.cardId = this.slide.cardId;
3824
+ _result.slideIndex = this.slide.slideIndex;
3814
3825
  return _result;
3815
3826
  }
3816
3827
  handleBackpress() {
@@ -3864,44 +3875,50 @@ let SlideApi$1 = class SlideApi {
3864
3875
  }
3865
3876
  });
3866
3877
  }
3878
+ // todo nullable
3867
3879
  _slide;
3868
3880
  _slideInInit;
3869
3881
  _state;
3870
3882
  _afterStartInitQueue = [];
3871
- _afterResumeQueue = [];
3883
+ _afterAppResumeQueue = [];
3872
3884
  get state() {
3873
3885
  return this._state;
3874
3886
  }
3875
3887
  async _onAllMediaLoaded(slide) {
3876
- return new Promise((resolve, reject) => {
3877
- const promises = slide.layers.flatMap(layer => layer.elements.flatMap(element => element.mediaElementsLoadingPromises));
3878
- // console.log({ promises });
3879
- let checkerTimerId = undefined;
3880
- let timeOutFired = false;
3881
- if (promises.length > 0) {
3882
- checkerTimerId = this.layoutService.env.setTimeout(() => {
3883
- timeOutFired = true;
3884
- reject("onAllMediaLoaded timeout");
3885
- }, 3000);
3886
- }
3887
- else {
3888
- resolve();
3889
- return;
3890
- }
3891
- Promise.all(promises).then(_ => {
3892
- checkerTimerId && this.layoutService.env.clearTimeout(checkerTimerId);
3893
- if (!timeOutFired) {
3894
- resolve();
3895
- }
3896
- }, reason => {
3897
- checkerTimerId && this.layoutService.env.clearTimeout(checkerTimerId);
3898
- if (!timeOutFired) {
3899
- reject(reason);
3900
- }
3901
- });
3902
- });
3903
- }
3904
- async _init(slideBoxCb, slideBoxFailedCb) {
3888
+ return Promise.all(slide.layers.flatMap(layer => layer.elements.flatMap(element => element.mediaElementsLoadingPromises))).then(_ => { });
3889
+ // return new Promise((resolve, reject) => {
3890
+ // const promises = slide.layers.flatMap(layer => layer.elements.flatMap(element => element.mediaElementsLoadingPromises));
3891
+ //
3892
+ // // console.log({ promises });
3893
+ //
3894
+ // let checkerTimerId: number | undefined = undefined;
3895
+ // let timeOutFired = false;
3896
+ // if (promises.length > 0) {
3897
+ // checkerTimerId = this.layoutService.env.setTimeout(() => {
3898
+ // timeOutFired = true;
3899
+ // reject("onAllMediaLoaded timeout");
3900
+ // }, 3000);
3901
+ // } else {
3902
+ // resolve();
3903
+ // return;
3904
+ // }
3905
+ // Promise.all(promises).then(
3906
+ // _ => {
3907
+ // checkerTimerId && this.layoutService.env.clearTimeout(checkerTimerId);
3908
+ // if (!timeOutFired) {
3909
+ // resolve();
3910
+ // }
3911
+ // },
3912
+ // reason => {
3913
+ // checkerTimerId && this.layoutService.env.clearTimeout(checkerTimerId);
3914
+ // if (!timeOutFired) {
3915
+ // reject(reason);
3916
+ // }
3917
+ // },
3918
+ // );
3919
+ // });
3920
+ }
3921
+ async _init(slideBoxCb) {
3905
3922
  this._state = 0 /* STATE.INIT */;
3906
3923
  const slideNodeRef = this._slideWrapper.querySelector(`.${SlideApi.prerenderBoxClassName} .narrative-slide`);
3907
3924
  const slidesNodesRefs = Array.prototype.slice.call(this._slideWrapper.querySelectorAll(`.${SlideApi.prerenderBoxClassName} .narrative-slide.narrative-multi-slide`));
@@ -3912,53 +3929,59 @@ let SlideApi$1 = class SlideApi {
3912
3929
  throw new Error("No slides found.");
3913
3930
  }
3914
3931
  let slideReadyResolve = null;
3915
- let slideReadyReject = null;
3916
- const slideReadyPromise = new Promise((resolve, reject) => {
3932
+ const slideReadyPromise = new Promise(resolve => {
3917
3933
  slideReadyResolve = resolve;
3918
- slideReadyReject = reject;
3919
3934
  });
3920
- const slide = new Slide(slidesNodesRefs, slideReadyPromise, this.afterResumeQueuePush.bind(this), this.afterStartInitQueuePush.bind(this), this.sdkApi.showNextSlide.bind(this), this.sdkApi);
3935
+ const slide = new Slide(slidesNodesRefs, slideReadyPromise, this.afterAppResumeQueuePush.bind(this), this.afterStartInitQueuePush.bind(this), this.sdkApi.showNextSlide.bind(this), this.sdkApi);
3921
3936
  this._slideInInit = slide;
3922
3937
  slide.activeLayer.timeline.triggerSlideLoadState();
3923
- const onAllMediaLoaded = this._onAllMediaLoaded(slide);
3924
3938
  if (this.sdkApi.isAndroid) {
3925
3939
  this._afterStartInitQueue = [];
3926
3940
  }
3927
- this._afterResumeQueue = [];
3941
+ this._afterAppResumeQueue = [];
3928
3942
  const result = { slide, result: false, reason: "" };
3929
- await this._initAndLoadFonts(this.sdkApi.getCardFonts());
3930
- const localData = await this.getLocalData();
3931
- const finishRender = await slide.init(localData);
3932
- /**
3933
- * если есть виджеты, которых надо ждать - то не завершаем рендеринг текущего слайда
3934
- * пример - квест, если зашли в сторис а виджету нужно показать другой слайд вместо первого
3935
- */
3936
- if (finishRender) {
3937
- this._state = 1 /* STATE.INITED */;
3938
- try {
3939
- await onAllMediaLoaded;
3943
+ try {
3944
+ const onAllMediaLoaded = this._onAllMediaLoaded(slide);
3945
+ const fontsPromise = this._initAndLoadFonts(this.sdkApi.getCardFonts());
3946
+ const mediaAndFontsPromise = Promise.all([onAllMediaLoaded, fontsPromise]).then(() => {
3947
+ this.layoutService.env.clearTimeout(mediaResourcesTimeoutId);
3948
+ });
3949
+ let mediaResourcesTimeoutId = null;
3950
+ const mediaResourcesTimeoutPromise = new Promise((resolve, reject) => {
3951
+ mediaResourcesTimeoutId = this.layoutService.env.setTimeout(() => {
3952
+ // todo add detailed info about pending media resources
3953
+ reject("MediaResources loading timed out (5 sec).");
3954
+ }, 5000);
3955
+ });
3956
+ const mediaResourcesWithTimeoutPromise = Promise.race([mediaAndFontsPromise, mediaResourcesTimeoutPromise]);
3957
+ const elementsPromise = slide.init(await this.getLocalData());
3958
+ const finishRender = await elementsPromise;
3959
+ /**
3960
+ * если есть виджеты, которых надо ждать - то не завершаем рендеринг текущего слайда
3961
+ * пример - квест, если зашли в сторис а виджету нужно показать другой слайд вместо первого
3962
+ */
3963
+ if (finishRender) {
3964
+ this._state = 1 /* STATE.INITED */;
3965
+ await mediaResourcesWithTimeoutPromise;
3940
3966
  result.result = true;
3941
3967
  slideBoxCb();
3942
- this.layoutService.env.setTimeout(() => {
3943
- slideReadyResolve();
3944
- });
3945
3968
  }
3946
- catch (reason) {
3947
- console.log("SlideInit, onAllMediaLoaded reject", reason);
3948
- slideBoxFailedCb();
3949
- this.layoutService.env.setTimeout(() => {
3950
- slideReadyReject();
3951
- });
3952
- result.result = false;
3953
- result.reason = String(reason);
3969
+ else {
3970
+ this._state = 12 /* STATE.STOPPED */;
3971
+ result.result = true;
3954
3972
  }
3973
+ this.layoutService.env.setTimeout(() => {
3974
+ slideReadyResolve();
3975
+ });
3955
3976
  }
3956
- else {
3957
- this._state = 10 /* STATE.STOPPED */;
3977
+ catch (reason) {
3978
+ console.log("SlideInit, onAllMediaLoaded reject", reason);
3979
+ slideBoxCb();
3958
3980
  this.layoutService.env.setTimeout(() => {
3959
3981
  slideReadyResolve();
3960
3982
  });
3961
- result.result = true;
3983
+ result.result = false;
3984
+ result.reason = String(reason);
3962
3985
  }
3963
3986
  return result;
3964
3987
  }
@@ -3974,6 +3997,8 @@ let SlideApi$1 = class SlideApi {
3974
3997
  slideBoxPrerender.classList.remove(SlideApi.prerenderBoxClassName);
3975
3998
  slideBox.classList.remove(SlideApi.renderedBoxClassName);
3976
3999
  slideBox.classList.add(SlideApi.prerenderBoxClassName);
4000
+ // pause Video - prevent triggering onDataWaiting from VODPlayer
4001
+ prevSlide?.activeLayer.pause(false, true, false);
3977
4002
  // 2 RAF - wait for browser render complete (CSS changes, etc.)
3978
4003
  this.layoutService.env.requestAnimationFrame(() => {
3979
4004
  this.layoutService.env.requestAnimationFrame(() => {
@@ -3987,34 +4012,10 @@ let SlideApi$1 = class SlideApi {
3987
4012
  }
3988
4013
  this._slideInRender = false;
3989
4014
  }
3990
- _slideBoxRenderError(prevSlide) {
3991
- // if (!slideInRender) {
3992
- // slideInRender = true;
3993
- // return;
3994
- // }
3995
- const slideBox = this._slideWrapper.querySelector(`.${SlideApi.renderedBoxClassName}`);
3996
- const slideBoxPrerender = this._slideWrapper.querySelector(`.${SlideApi.prerenderBoxClassName}`);
3997
- if (slideBox && slideBoxPrerender) {
3998
- const slides = Array.prototype.slice.call(slideBoxPrerender.querySelectorAll(".narrative-slide"));
3999
- for (let i = 0; i < slides.length; ++i) {
4000
- const slide = slides[i];
4001
- if (slide) {
4002
- slide.innerHTML = "";
4003
- }
4004
- }
4005
- slideBoxPrerender.classList.remove(SlideApi.prerenderBoxClassName);
4006
- slideBox.classList.remove(SlideApi.renderedBoxClassName);
4007
- slideBox.classList.add(SlideApi.prerenderBoxClassName);
4008
- prevSlide?.onBeforeUnmount();
4009
- slideBox.innerHTML = "";
4010
- slideBoxPrerender.classList.add(SlideApi.renderedBoxClassName);
4011
- }
4012
- // slideInRender = false;
4013
- }
4014
4015
  _slideConfig = {};
4015
4016
  async slideStart(config) {
4016
4017
  // console.log(`slideStart slideIdx: ${this.activeLayer.slideIndex} state: ${this._state}`);
4017
- if (!(this._state === 10 /* STATE.STOPPED */ || this._state === 1 /* STATE.INITED */)) {
4018
+ if (!(this._state === 12 /* STATE.STOPPED */ || this._state === 1 /* STATE.INITED */)) {
4018
4019
  return { currentTime: 0 };
4019
4020
  }
4020
4021
  this._state = 2 /* STATE.START */;
@@ -4029,30 +4030,32 @@ let SlideApi$1 = class SlideApi {
4029
4030
  }
4030
4031
  this._afterStartInitQueue = [];
4031
4032
  }
4032
- if (this._afterResumeQueue && Array.isArray(this._afterResumeQueue)) {
4033
- for (const job of this._afterResumeQueue) {
4033
+ if (this._afterAppResumeQueue && Array.isArray(this._afterAppResumeQueue)) {
4034
+ for (const job of this._afterAppResumeQueue) {
4034
4035
  if (isFunction(job)) {
4035
4036
  job();
4036
4037
  }
4037
4038
  }
4038
- this._afterResumeQueue = [];
4039
+ this._afterAppResumeQueue = [];
4039
4040
  }
4040
4041
  const { currentTime } = await this.slide.activeLayer.start(this._slideConfig.muted);
4041
4042
  this._state = 3 /* STATE.STARTED */;
4042
4043
  if (this.slide.activeLayer.isLayerForcePaused) {
4043
- this._state = 7 /* STATE.PAUSED */;
4044
+ this._state = 9 /* STATE.USER_PAUSED */;
4044
4045
  }
4045
4046
  return { currentTime };
4046
4047
  }
4047
4048
  async slideRestart(config) {
4048
- this._state = 10 /* STATE.STOPPED */;
4049
+ this._state = 12 /* STATE.STOPPED */;
4049
4050
  return this.slideStart(config);
4050
4051
  }
4051
4052
  _pauseCbTimer = null;
4052
- async slidePause() {
4053
+ async slideUserPause() {
4054
+ // apply user pause only if state is started or resumed
4053
4055
  if (!(this._state === 3 /* STATE.STARTED */ || this._state === 5 /* STATE.RESUMED */)) {
4054
4056
  return;
4055
4057
  }
4058
+ // TODO - move to Android SlideApi adapter
4056
4059
  // обход бага на андроиде (вызывает pause/resume при любом нажатии на экран, даже если это клик - для перехода по слайдам)
4057
4060
  // поэтому делаем отложенный вызов (300мс) а если следом приходит stop - то отменяем таймер
4058
4061
  const pauseCb = () => {
@@ -4063,15 +4066,16 @@ let SlideApi$1 = class SlideApi {
4063
4066
  // stop pause event (from sdk) if _narrative_range_slider is active
4064
4067
  return;
4065
4068
  }
4066
- this._state = 6 /* STATE.PAUSE */;
4069
+ this._state = 8 /* STATE.USER_PAUSE */;
4067
4070
  // _log("pause: " + (performance.now() - window.start));
4068
4071
  this.slide.activeLayer.pause(false, false);
4069
4072
  // clean up
4070
4073
  if (this._pauseCbTimer != null) {
4071
4074
  clearTimeout(this._pauseCbTimer);
4072
4075
  }
4073
- this._state = 7 /* STATE.PAUSED */;
4076
+ this._state = 9 /* STATE.USER_PAUSED */;
4074
4077
  };
4078
+ // todo move to Android adapter
4075
4079
  if (this.sdkApi.isAndroid) {
4076
4080
  this._pauseCbTimer = this.layoutService.env.setTimeout(pauseCb, 300);
4077
4081
  }
@@ -4079,38 +4083,68 @@ let SlideApi$1 = class SlideApi {
4079
4083
  pauseCb();
4080
4084
  }
4081
4085
  }
4082
- async slideResume() {
4086
+ async slideUserResume() {
4083
4087
  if (this._pauseCbTimer != null) {
4084
4088
  // отменяем pause если есть (баг андроида - шлет pause/resume на простой клик)
4085
4089
  clearTimeout(this._pauseCbTimer);
4086
4090
  }
4087
- if (this._state !== 7 /* STATE.PAUSED */) {
4091
+ if (this._state !== 9 /* STATE.USER_PAUSED */) {
4088
4092
  return;
4089
4093
  }
4090
4094
  this._state = 4 /* STATE.RESUME */;
4091
4095
  // _log("resume: " + (performance.now() - window.start));
4092
- if (this._afterResumeQueue && Array.isArray(this._afterResumeQueue)) {
4093
- for (const job of this._afterResumeQueue) {
4096
+ // fallback for native sdk without user and app pause event
4097
+ if (!this._separateUserAndAppPause) {
4098
+ if (this._afterAppResumeQueue && Array.isArray(this._afterAppResumeQueue)) {
4099
+ for (const job of this._afterAppResumeQueue) {
4100
+ if (isFunction(job)) {
4101
+ job();
4102
+ }
4103
+ }
4104
+ this._afterAppResumeQueue = [];
4105
+ }
4106
+ }
4107
+ this.slide.activeLayer.resume();
4108
+ this._state = 5 /* STATE.RESUMED */;
4109
+ }
4110
+ /**
4111
+ * Call on app gone background
4112
+ */
4113
+ async slideAppPause() {
4114
+ this._state = 6 /* STATE.APP_PAUSE */;
4115
+ this.slide.activeLayer.pause(false, false);
4116
+ this._state = 7 /* STATE.APP_PAUSED */;
4117
+ }
4118
+ /**
4119
+ * Call on app gone foreground after a background
4120
+ */
4121
+ async slideAppResume() {
4122
+ if (this._state !== 7 /* STATE.APP_PAUSED */) {
4123
+ return;
4124
+ }
4125
+ this._state = 4 /* STATE.RESUME */;
4126
+ if (this._afterAppResumeQueue && Array.isArray(this._afterAppResumeQueue)) {
4127
+ for (const job of this._afterAppResumeQueue) {
4094
4128
  if (isFunction(job)) {
4095
4129
  job();
4096
4130
  }
4097
4131
  }
4098
- this._afterResumeQueue = [];
4132
+ this._afterAppResumeQueue = [];
4099
4133
  }
4100
4134
  this.slide.activeLayer.resume();
4101
4135
  this._state = 5 /* STATE.RESUMED */;
4102
4136
  }
4103
4137
  async slideStop(options) {
4104
- if (!(this._state === 3 /* STATE.STARTED */ || this._state === 5 /* STATE.RESUMED */ || this._state === 7 /* STATE.PAUSED */)) {
4138
+ if (!(this._state === 3 /* STATE.STARTED */ || this._state === 5 /* STATE.RESUMED */ || this._state === 9 /* STATE.USER_PAUSED */)) {
4105
4139
  return;
4106
4140
  }
4107
- this._state = 9 /* STATE.STOP */;
4141
+ this._state = 11 /* STATE.STOP */;
4108
4142
  if (this._pauseCbTimer != null) {
4109
4143
  // отменяем pause если есть (баг андроида - шлет pause/resume на простой клик)
4110
4144
  clearTimeout(this._pauseCbTimer);
4111
4145
  }
4112
4146
  await this.slide.activeLayer.stop(options);
4113
- this._state = 10 /* STATE.STOPPED */;
4147
+ this._state = 12 /* STATE.STOPPED */;
4114
4148
  }
4115
4149
  slideTimerEnd() {
4116
4150
  const defaultAction = () => {
@@ -4143,7 +4177,7 @@ let SlideApi$1 = class SlideApi {
4143
4177
  // skip state checking and sdk issues
4144
4178
  async slidePauseUI() {
4145
4179
  await this.slide.activeLayer.pause(false, false);
4146
- this._state = 8 /* STATE.FORCE_PAUSED */;
4180
+ this._state = 10 /* STATE.FORCE_PAUSED */;
4147
4181
  }
4148
4182
  // for call from SlideApi internals (from widgets)
4149
4183
  // skip state checking and sdk issues
@@ -4160,7 +4194,7 @@ let SlideApi$1 = class SlideApi {
4160
4194
  this._slideConfig.muted = true;
4161
4195
  }
4162
4196
  get isStopped() {
4163
- return this._state === 10 /* STATE.STOPPED */;
4197
+ return this._state === 12 /* STATE.STOPPED */;
4164
4198
  }
4165
4199
  afterStartInitQueuePush(cb) {
4166
4200
  if (!isFunction(cb)) {
@@ -4173,15 +4207,20 @@ let SlideApi$1 = class SlideApi {
4173
4207
  cb();
4174
4208
  }
4175
4209
  }
4176
- afterResumeQueuePush(cb) {
4210
+ afterAppResumeQueuePush(cb) {
4177
4211
  if (!isFunction(cb)) {
4178
4212
  return false;
4179
4213
  }
4180
- if ([4 /* STATE.RESUME */, 5 /* STATE.RESUMED */, 1 /* STATE.INITED */, 2 /* STATE.START */, 3 /* STATE.STARTED */].includes(this._state)) {
4214
+ let states = [4 /* STATE.RESUME */, 5 /* STATE.RESUMED */, 1 /* STATE.INITED */, 2 /* STATE.START */, 3 /* STATE.STARTED */, 8 /* STATE.USER_PAUSE */, 9 /* STATE.USER_PAUSED */];
4215
+ // fallback for native sdk without user and app pause event
4216
+ if (!this._separateUserAndAppPause) {
4217
+ states = [4 /* STATE.RESUME */, 5 /* STATE.RESUMED */, 1 /* STATE.INITED */, 2 /* STATE.START */, 3 /* STATE.STARTED */];
4218
+ }
4219
+ if (states.includes(this._state)) {
4181
4220
  cb();
4182
4221
  }
4183
4222
  else {
4184
- this._afterResumeQueue.push(cb);
4223
+ this._afterAppResumeQueue.push(cb);
4185
4224
  }
4186
4225
  }
4187
4226
  get activeLayer() {
@@ -4760,7 +4799,7 @@ let SlideApi$1 = class SlideApi {
4760
4799
  }
4761
4800
  }
4762
4801
  }
4763
- static get [Symbol.for("___CTOR_ARGS___")]() { return [`{\n sdkApi: SDKApi;\n slideWrapper: HTMLElement;\n viewport: Window;\n userResizeHandler?: (data: { viewportWidth: number; viewportHeight: number; fontSize: number }) => void;\n slideRatio: number;\n isFullscreen: boolean;\n slideLoadedCb?: (data: { slide: Slide; result: boolean; reason?: string }) => void;\n getViewportWidth: () => number;\n getViewportHeight: () => number;\n overlappingActionBarHeight?: number;\n }`]; }
4802
+ static get [Symbol.for("___CTOR_ARGS___")]() { return [`{\n sdkApi: SDKApi;\n slideWrapper: HTMLElement;\n viewport: Window;\n userResizeHandler?: (data: { viewportWidth: number; viewportHeight: number; fontSize: number }) => void;\n slideRatio: number;\n isFullscreen: boolean;\n slideLoadedCb?: (data: { cardId: number; slideIndex: number; result: boolean; reason?: string }) => void;\n getViewportWidth: () => number;\n getViewportHeight: () => number;\n overlappingActionBarHeight?: number;\n separateUserAndAppPause: boolean;\n }`]; }
4764
4803
  };
4765
4804
 
4766
4805
  const slideApiPeerDeps = {};
@@ -4809,6 +4848,7 @@ class SlideApi extends SlideApi$1 {
4809
4848
  getViewportWidth: () => slideWrapper.clientWidth,
4810
4849
  getViewportHeight: () => slideWrapper.clientHeight,
4811
4850
  overlappingActionBarHeight: config.overlappingActionBarHeight,
4851
+ separateUserAndAppPause: true,
4812
4852
  });
4813
4853
  }
4814
4854
  static get [Symbol.for("___CTOR_ARGS___")]() { return [`SDKInterface`, `{\n root: HTMLElement;\n slideRatio: number;\n isFullscreen: boolean;\n nonce?: string;\n viewport: Window;\n userResizeHandler?: (data: { viewportWidth: number; viewportHeight: number; fontSize: number }) => void;\n VODPlayer?: typeof VODPlayer;\n overlappingActionBarHeight?: number;\n }`]; }