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