@stormstreaming/stormstreamer 1.0.6 → 1.0.8

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Change Log
2
2
 
3
+ ## 1.0.8
4
+
5
+ Fix frozen video preview after detach/reattach to DOM tree.
6
+
7
+ ## 1.0.7
8
+
9
+ Fixed race condition in StageController where resize methods could fire after detach, causing "Cannot read properties of null" errors.
10
+
3
11
  ## 1.0.6
4
12
 
5
13
  Fixed intervals not being properly cleaned up when player instance is removed,
package/dist/amd/index.js CHANGED
@@ -4,8 +4,8 @@
4
4
  * contact@stormstreaming.com
5
5
  * https://stormstreaming.com
6
6
  *
7
- * Version: 1.0.6
8
- * Version: 2/22/2026, 12:57:01 PM
7
+ * Version: 1.0.8
8
+ * Version: 2/24/2026, 4:44:50 PM
9
9
  *
10
10
  * LEGAL NOTICE:
11
11
  * This software is subject to the terms and conditions defined in
@@ -2774,12 +2774,12 @@
2774
2774
  */
2775
2775
  this._tempContainerHeight = 0;
2776
2776
  /**
2777
- * Video width (initally 0, after "onmetadata" event is updated to match the real one
2777
+ * Video width (initially 0, after "onmetadata" event is updated to match the real one)
2778
2778
  * @private
2779
2779
  */
2780
2780
  this._videoWidth = 0;
2781
2781
  /**
2782
- * Video width (initally 0, after "onmetadata" event is updated to match the real one
2782
+ * Video height (initially 0, after "onmetadata" event is updated to match the real one)
2783
2783
  * @private
2784
2784
  */
2785
2785
  this._videoHeight = 0;
@@ -2799,7 +2799,7 @@
2799
2799
  */
2800
2800
  this._isResizing = false;
2801
2801
  /**
2802
- * Deco
2802
+ * Auto resize flag
2803
2803
  * @private
2804
2804
  */
2805
2805
  this._autoResizeEnabled = true;
@@ -2855,16 +2855,17 @@
2855
2855
  this._screenElement = new ScreenElement(this._main);
2856
2856
  this._videoContainer.appendChild(this._screenElement.getVideoElement());
2857
2857
  const debounceValue = this._main.getConfigManager().getSettingsData().getVideoData().resizeDebounce;
2858
+ // FIX: debounce(() => ()=>{}) zwracało funkcję zamiast ją wywoływać
2858
2859
  if (debounceValue > 0) {
2859
- this._resizeObserver = new ResizeObserver(debounce$1(() => () => {
2860
- if (this._autoResizeEnabled) this.handleResize();
2860
+ this._resizeObserver = new ResizeObserver(debounce$1(() => {
2861
+ if (this._autoResizeEnabled && this._parentElement) this.handleResize();
2861
2862
  }, debounceValue, {
2862
2863
  leading: false,
2863
2864
  trailing: true
2864
2865
  }));
2865
2866
  } else {
2866
2867
  this._resizeObserver = new ResizeObserver(() => {
2867
- if (this._autoResizeEnabled) this.handleResize();
2868
+ if (this._autoResizeEnabled && this._parentElement) this.handleResize();
2868
2869
  });
2869
2870
  }
2870
2871
  this._fullscreenChangeHandler = this.onFullScreenChange;
@@ -2892,7 +2893,7 @@
2892
2893
  */
2893
2894
  attachToParent(container) {
2894
2895
  // preparing elements
2895
- let result = false; // To indicate the success of the operation
2896
+ let result = false;
2896
2897
  let tempParentElement = null;
2897
2898
  // Check if container is either an ID string or an HTMLElement instance
2898
2899
  if (typeof container === "string") {
@@ -2913,21 +2914,26 @@
2913
2914
  if (this._debug) this._logger.decoratedLog("Attach To Parent: " + container + " (success)", "dark-pink");
2914
2915
  this._parentElement = tempParentElement;
2915
2916
  this._parentElement.appendChild(this._videoContainer);
2917
+ if (this._screenElement) {
2918
+ const videoElement = this._screenElement.getVideoElement();
2919
+ if (videoElement === null || videoElement === void 0 ? void 0 : videoElement.srcObject) {
2920
+ videoElement.play().catch(() => {});
2921
+ }
2922
+ }
2916
2923
  this._resizeObserver.observe(this._parentElement);
2917
- this._parentElement.addEventListener("transitionend", () => {
2918
- this.handleResize();
2919
- });
2924
+ // FIX: użyj zapisanego handlera zamiast anonimowej funkcji
2925
+ this._parentElement.addEventListener("transitionend", this._transitionEndHandler);
2920
2926
  this._main.dispatchEvent("containerChange", {
2921
2927
  ref: this._main,
2922
2928
  container: this._parentElement
2923
2929
  });
2924
2930
  this.handleResize();
2925
- result = true; // Operation successful
2931
+ result = true;
2926
2932
  } else {
2927
2933
  if (this._debug) this._logger.decoratedLog("Attach To Parent: " + container + " (failure - container not found)", "dark-pink");
2928
2934
  this._logger.warning(this, "attachToParent :: container \"" + container + "\"+ was not found");
2929
2935
  }
2930
- return result; // Return the result of the operation
2936
+ return result;
2931
2937
  }
2932
2938
  /**
2933
2939
  * Detaches the library from a parent container
@@ -2937,7 +2943,16 @@
2937
2943
  let result = false;
2938
2944
  if (this._parentElement != null && this._videoContainer != null) {
2939
2945
  this._logger.info(this, "Detaching from parent: " + this._videoContainer);
2940
- // POPRAWKA: Usuń event listener z zapisanym handlerem
2946
+ // FIX: anuluj pending requestAnimationFrame żeby callback nie strzelił na null parent
2947
+ if (this._animationFrameId !== null) {
2948
+ cancelAnimationFrame(this._animationFrameId);
2949
+ this._animationFrameId = null;
2950
+ // przywróć overflow jeśli został zmieniony przez handleResize
2951
+ if (this._isResizing) {
2952
+ this._parentElement.style.overflow = this._parentOriginalOverflow;
2953
+ }
2954
+ this._isResizing = false;
2955
+ }
2941
2956
  if (this._transitionEndHandler) {
2942
2957
  this._parentElement.removeEventListener("transitionend", this._transitionEndHandler);
2943
2958
  }
@@ -2958,7 +2973,6 @@
2958
2973
  }
2959
2974
  handleResize() {
2960
2975
  if (!this._parentElement || this._isResizing || this._isDestroying) return;
2961
- // POPRAWKA: Anulowanie poprzedniego requestAnimationFrame
2962
2976
  if (this._animationFrameId !== null) {
2963
2977
  cancelAnimationFrame(this._animationFrameId);
2964
2978
  }
@@ -2966,7 +2980,12 @@
2966
2980
  this._parentOriginalOverflow = this._parentElement.style.overflow;
2967
2981
  this._parentElement.style.overflow = 'hidden';
2968
2982
  this._animationFrameId = requestAnimationFrame(() => {
2969
- if (this._isDestroying) return;
2983
+ // FIX: ponowny guard - parentElement mógł zostać null między kolejkowaniem a wykonaniem RAF
2984
+ if (this._isDestroying || !this._parentElement) {
2985
+ this._isResizing = false;
2986
+ this._animationFrameId = null;
2987
+ return;
2988
+ }
2970
2989
  this.calculateNewDimensions();
2971
2990
  if (this._parentElement) {
2972
2991
  this._parentElement.style.overflow = this._parentOriginalOverflow;
@@ -2983,6 +3002,7 @@
2983
3002
  });
2984
3003
  }
2985
3004
  calculateNewDimensions() {
3005
+ if (!this._parentElement) return;
2986
3006
  const calcMethod = this._main.getConfigManager().getSettingsData().getVideoData().parentSizeCalculationMethod;
2987
3007
  switch (calcMethod) {
2988
3008
  case SizeCalculationType.CLIENT_DIMENSIONS:
@@ -3080,7 +3100,6 @@
3080
3100
  //--- LETTER BOX
3081
3101
  case ScalingType.LETTER_BOX:
3082
3102
  {
3083
- // jeżeli szerokość
3084
3103
  videoWidth = this._containerWidth;
3085
3104
  videoHeight = this._videoHeight * this._containerWidth / this._videoWidth;
3086
3105
  if (videoHeight <= this._containerHeight) {
@@ -3255,42 +3274,37 @@
3255
3274
  }
3256
3275
  this._fullscreenChangeHandler = null;
3257
3276
  }
3258
- // 6. Zniszcz ScreenElement
3277
+ // 5. Zniszcz ScreenElement
3259
3278
  if (this._screenElement) {
3260
- // Wyczyść video element
3261
3279
  const videoElement = this._screenElement.getVideoElement();
3262
3280
  if (videoElement) {
3263
- // Zatrzymaj wszelkie strumienie
3264
3281
  if (videoElement.srcObject instanceof MediaStream) {
3265
3282
  videoElement.srcObject.getTracks().forEach(track => {
3266
3283
  track.enabled = false;
3267
3284
  track.stop();
3268
3285
  });
3269
3286
  }
3270
- // Wyczyść element
3271
3287
  videoElement.pause();
3272
3288
  videoElement.removeAttribute('src');
3273
3289
  videoElement.srcObject = null;
3274
3290
  videoElement.load();
3275
- // Usuń z DOM jeśli jest podłączony
3276
3291
  if (videoElement.parentNode) {
3277
3292
  videoElement.parentNode.removeChild(videoElement);
3278
3293
  }
3279
3294
  }
3280
- // Jeśli ScreenElement ma własną metodę destroy, wywołaj ją
3281
3295
  if (typeof this._screenElement.destroy === 'function') {
3282
3296
  this._screenElement.destroy();
3283
3297
  }
3284
3298
  this._screenElement = null;
3285
3299
  }
3286
- // 7. Usuń kontener video z DOM
3300
+ // 6. Usuń kontener video z DOM
3287
3301
  if (this._videoContainer) {
3288
3302
  if (this._videoContainer.parentNode) {
3289
3303
  this._videoContainer.parentNode.removeChild(this._videoContainer);
3290
3304
  }
3291
3305
  this._videoContainer = null;
3292
3306
  }
3293
- // 8. Resetuj zmienne
3307
+ // 7. Resetuj zmienne
3294
3308
  this._containerWidth = 0;
3295
3309
  this._containerHeight = 0;
3296
3310
  this._tempContainerWidth = 0;
@@ -3300,6 +3314,7 @@
3300
3314
  this.isInFullScreenMode = false;
3301
3315
  this._isResizing = false;
3302
3316
  this._autoResizeEnabled = false;
3317
+ this._transitionEndHandler = null;
3303
3318
  this._logger.success(this, "StageController successfully destroyed");
3304
3319
  } catch (error) {
3305
3320
  this._logger.error(this, "Error during destroy: " + error);
@@ -6760,8 +6775,8 @@
6760
6775
  constructor(streamConfig, autoInitialize = false) {
6761
6776
  super();
6762
6777
  this.DEV_MODE = true;
6763
- this.STREAMER_VERSION = "1.0.6";
6764
- this.COMPILE_DATE = "2/22/2026, 12:56:59 PM";
6778
+ this.STREAMER_VERSION = "1.0.8";
6779
+ this.COMPILE_DATE = "2/24/2026, 4:44:48 PM";
6765
6780
  this.STREAMER_BRANCH = "Experimental";
6766
6781
  this.STREAMER_PROTOCOL_VERSION = 1;
6767
6782
  this._initialized = false;