@3dsource/angular-unreal-module 0.0.144 → 0.0.145

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.
@@ -3249,6 +3249,20 @@ class WebRtcPlayerService extends SubService {
3249
3249
  this.remoteDescriptionSet = false;
3250
3250
  this.iceCandidateBuffer.length = 0;
3251
3251
  }
3252
+ /**
3253
+ * Single source of truth for tearing down the remote connection: closes the
3254
+ * signaling WebSocket and then the PeerConnection/DataChannel.
3255
+ *
3256
+ * Called by the `destroyRemoteConnections$` effect and, as a
3257
+ * lifecycle-independent safeguard, by `UnrealSceneComponent.onDestroy` (the
3258
+ * route-scoped effects may already be torn down on navigation). Both close
3259
+ * steps are idempotent, so invoking this twice in one teardown is a harmless
3260
+ * no-op.
3261
+ */
3262
+ releaseRemoteConnections(reason) {
3263
+ this.signallingSrv.close({ code: WSCloseCode_FORCE_CIRRUS_CLOSE, reason });
3264
+ this.closePC();
3265
+ }
3252
3266
  canSend() {
3253
3267
  return this.dcClient && this.dcClient.readyState === 'open';
3254
3268
  }
@@ -3816,11 +3830,7 @@ class UnrealEffects {
3816
3830
  });
3817
3831
  this.destroyRemoteConnections$ = createEffect(() => {
3818
3832
  return this.actions$.pipe(ofType(destroyRemoteConnections), tap(({ reason }) => {
3819
- this.signallingService.close({
3820
- code: WSCloseCode_FORCE_CIRRUS_CLOSE,
3821
- reason,
3822
- });
3823
- this.webRtcPlayerService.closePC();
3833
+ this.webRtcPlayerService.releaseRemoteConnections(reason);
3824
3834
  }), filter(({ reason }) => reason === DisconnectReason.DropConnection), map(() => dropConnection()));
3825
3835
  });
3826
3836
  this.destroyConnectionAndRestart$ = createEffect(() => {
@@ -7171,26 +7181,19 @@ class UnrealSceneComponent {
7171
7181
  this.commandsSender = inject(UnrealCommunicatorService);
7172
7182
  this.videoService = inject(VideoService);
7173
7183
  this.webRtcPlayerService = inject(WebRtcPlayerService);
7174
- this.signallingService = inject(SignallingService);
7175
7184
  this.destroyRef = inject(DestroyRef);
7176
7185
  this.unrealConfig = inject(UNREAL_CONFIG);
7177
7186
  this.autoHighResolution = false;
7178
7187
  this.destroyRef.onDestroy(() => {
7179
- // Mirror of the `destroyRemoteConnections$` effect's teardown tap, run
7180
- // directly here as a safeguard. provideUnrealModule (effects) is
7181
- // registered per 3D route, so on navigation the route's environment
7182
- // injector — and its UnrealEffects — may be torn down before the
7188
+ // Release the remote connection synchronously, independent of the
7189
+ // route-scoped UnrealEffects. provideUnrealModule (effects) is registered
7190
+ // per 3D route, so on navigation the route's environment injector — and
7191
+ // its UnrealEffects — may be torn down before the
7183
7192
  // `destroyUnrealScene → destroyRemoteConnections` effect chain closes the
7184
- // WebSocket/PeerConnection, which would leak the stream session. The
7185
- // engine services are providedIn:'root' singletons, so we close them
7186
- // directly. Keep the SAME calls, args and order as the effect's tap
7187
- // (close → closePC); both are idempotent, so whichever runs second is a
7188
- // harmless no-op.
7189
- this.signallingService.close({
7190
- code: WSCloseCode_FORCE_CIRRUS_CLOSE,
7191
- reason: DisconnectReason.Destroy,
7192
- });
7193
- this.webRtcPlayerService.closePC();
7193
+ // WebSocket/PeerConnection, which would leak the stream session. We call
7194
+ // the same root-singleton method the effect uses, so the two can never
7195
+ // drift; it's idempotent, so whichever runs second is a harmless no-op.
7196
+ this.webRtcPlayerService.releaseRemoteConnections(DisconnectReason.Destroy);
7194
7197
  // State cleanup is reducer-driven, not effect-driven: the
7195
7198
  // `destroyUnrealScene` reducer resets the whole UnrealState to
7196
7199
  // initialState (cirrusConnected/viewportReady/… → false). Reducers run in