hotfix handshake issue
All checks were successful
Queue Release Build / prepare (push) Successful in 16s
Deploy Web Apps / deploy (push) Successful in 10m15s
Queue Release Build / build-linux (push) Successful in 26m14s
Queue Release Build / build-windows (push) Successful in 25m41s
Queue Release Build / finalize (push) Successful in 1m51s

This commit is contained in:
2026-03-19 03:34:26 +01:00
parent c3ef8e8800
commit cb2c0495b9
3 changed files with 28 additions and 24 deletions

View File

@@ -464,23 +464,37 @@ export class WebRTCService implements OnDestroy {
} }
const existing = this.peerManager.activePeerConnections.get(user.oderId); const existing = this.peerManager.activePeerConnections.get(user.oderId);
const healthy = this.isPeerHealthy(existing);
if (existing && !healthy) { if (this.canReusePeerConnection(existing)) {
this.logger.info('Removing stale peer before recreate', { oderId: user.oderId }); this.logger.info('Reusing active peer connection', {
connectionState: existing?.connection.connectionState ?? 'unknown',
dataChannelState: existing?.dataChannel?.readyState ?? 'missing',
oderId: user.oderId,
serverId: message.serverId,
signalUrl
});
continue;
}
if (existing) {
this.logger.info('Removing failed peer before recreate', {
connectionState: existing.connection.connectionState,
dataChannelState: existing.dataChannel?.readyState ?? 'missing',
oderId: user.oderId,
serverId: message.serverId,
signalUrl
});
this.peerManager.removePeer(user.oderId); this.peerManager.removePeer(user.oderId);
} }
if (healthy)
continue;
this.logger.info('Create peer connection to existing user', { this.logger.info('Create peer connection to existing user', {
oderId: user.oderId, oderId: user.oderId,
serverId: message.serverId serverId: message.serverId,
signalUrl
}); });
this.peerManager.createPeerConnection(user.oderId, true); this.peerManager.createPeerConnection(user.oderId, true);
this.peerManager.createAndSendOffer(user.oderId); void this.peerManager.createAndSendOffer(user.oderId);
} }
} }
@@ -1282,15 +1296,14 @@ export class WebRTCService implements OnDestroy {
this._isDeafened.set(this.mediaManager.getIsSelfDeafened()); this._isDeafened.set(this.mediaManager.getIsSelfDeafened());
} }
/** Returns true if a peer connection exists and its data channel is open. */ /** Returns true if a peer connection is still alive enough to finish negotiating. */
private isPeerHealthy(peer: import('./webrtc').PeerData | undefined): boolean { private canReusePeerConnection(peer: import('./webrtc').PeerData | undefined): boolean {
if (!peer) if (!peer)
return false; return false;
const connState = peer.connection?.connectionState; const connState = peer.connection?.connectionState;
const dcState = peer.dataChannel?.readyState;
return connState === 'connected' && dcState === 'open'; return connState !== 'closed' && connState !== 'failed';
} }
private handlePeerControlMessage(event: ChatEvent): void { private handlePeerControlMessage(event: ChatEvent): void {

View File

@@ -69,18 +69,17 @@ export class FloatingVoiceControlsComponent implements OnInit {
isConnected = computed(() => this.webrtcService.isVoiceConnected()); isConnected = computed(() => this.webrtcService.isVoiceConnected());
isMuted = signal(false); isMuted = signal(false);
isDeafened = signal(false); isDeafened = signal(false);
isScreenSharing = signal(false); isScreenSharing = this.webrtcService.isScreenSharing;
includeSystemAudio = signal(false); includeSystemAudio = signal(false);
screenShareQuality = signal<ScreenShareQuality>('balanced'); screenShareQuality = signal<ScreenShareQuality>('balanced');
askScreenShareQuality = signal(true); askScreenShareQuality = signal(true);
showScreenShareQualityDialog = signal(false); showScreenShareQualityDialog = signal(false);
/** Sync local mute/deafen/screen-share state from the WebRTC service on init. */ /** Sync local mute/deafen state from the WebRTC service on init. */
ngOnInit(): void { ngOnInit(): void {
// Sync mute/deafen state from webrtc service // Sync mute/deafen state from webrtc service
this.isMuted.set(this.webrtcService.isMuted()); this.isMuted.set(this.webrtcService.isMuted());
this.isDeafened.set(this.webrtcService.isDeafened()); this.isDeafened.set(this.webrtcService.isDeafened());
this.isScreenSharing.set(this.webrtcService.isScreenSharing());
this.syncScreenShareSettings(); this.syncScreenShareSettings();
const settings = loadVoiceSettingsFromStorage(); const settings = loadVoiceSettingsFromStorage();
@@ -145,7 +144,6 @@ export class FloatingVoiceControlsComponent implements OnInit {
async toggleScreenShare(): Promise<void> { async toggleScreenShare(): Promise<void> {
if (this.isScreenSharing()) { if (this.isScreenSharing()) {
this.webrtcService.stopScreenShare(); this.webrtcService.stopScreenShare();
this.isScreenSharing.set(false);
} else { } else {
this.syncScreenShareSettings(); this.syncScreenShareSettings();
@@ -214,7 +212,6 @@ export class FloatingVoiceControlsComponent implements OnInit {
this.voiceSessionService.endSession(); this.voiceSessionService.endSession();
// Reset local state // Reset local state
this.isScreenSharing.set(false);
this.isMuted.set(false); this.isMuted.set(false);
this.isDeafened.set(false); this.isDeafened.set(false);
} }
@@ -288,8 +285,6 @@ export class FloatingVoiceControlsComponent implements OnInit {
includeSystemAudio: this.includeSystemAudio(), includeSystemAudio: this.includeSystemAudio(),
quality quality
}); });
this.isScreenSharing.set(true);
} catch (_error) { } catch (_error) {
// Screen share request was denied or failed // Screen share request was denied or failed
} }

View File

@@ -84,7 +84,7 @@ export class VoiceControlsComponent implements OnInit, OnDestroy {
connectionErrorMessage = computed(() => this.webrtcService.connectionErrorMessage()); connectionErrorMessage = computed(() => this.webrtcService.connectionErrorMessage());
isMuted = signal(false); isMuted = signal(false);
isDeafened = signal(false); isDeafened = signal(false);
isScreenSharing = signal(false); isScreenSharing = this.webrtcService.isScreenSharing;
showSettings = signal(false); showSettings = signal(false);
inputDevices = signal<AudioDevice[]>([]); inputDevices = signal<AudioDevice[]>([]);
@@ -286,7 +286,6 @@ export class VoiceControlsComponent implements OnInit, OnDestroy {
// End voice session for floating controls // End voice session for floating controls
this.voiceSessionService.endSession(); this.voiceSessionService.endSession();
this.isScreenSharing.set(false);
this.isMuted.set(false); this.isMuted.set(false);
this.isDeafened.set(false); this.isDeafened.set(false);
} }
@@ -368,7 +367,6 @@ export class VoiceControlsComponent implements OnInit, OnDestroy {
async toggleScreenShare(): Promise<void> { async toggleScreenShare(): Promise<void> {
if (this.isScreenSharing()) { if (this.isScreenSharing()) {
this.webrtcService.stopScreenShare(); this.webrtcService.stopScreenShare();
this.isScreenSharing.set(false);
} else { } else {
this.syncScreenShareSettings(); this.syncScreenShareSettings();
@@ -539,8 +537,6 @@ export class VoiceControlsComponent implements OnInit, OnDestroy {
includeSystemAudio: this.includeSystemAudio(), includeSystemAudio: this.includeSystemAudio(),
quality quality
}); });
this.isScreenSharing.set(true);
} catch (_error) {} } catch (_error) {}
} }