chore: enforce lint across codebase and ban "maybe" in identifiers

Remove member-ordering and complexity eslint-disable comments by reordering
class members and applying targeted fixes. Add metoyou/no-maybe-in-naming,
type-safe WebRTC e2e harness helpers, and resolve remaining lint errors so
npm run lint exits cleanly.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-11 11:08:26 +02:00
co-authored by Cursor
parent b630bacdc6
commit 79c6f91cd6
138 changed files with 4286 additions and 2310 deletions
@@ -11,7 +11,6 @@
* This file wires them together and exposes a public API that is
* identical to the old monolithic service so consumers don't change.
*/
/* eslint-disable @typescript-eslint/member-ordering, @typescript-eslint/no-non-null-assertion */
import {
Injectable,
inject,
@@ -60,70 +59,115 @@ import { selectCurrentUser } from '../../store/users/users.selectors';
providedIn: 'root'
})
export class WebRTCService implements OnDestroy {
private readonly timeSync = inject(TimeSyncService);
private readonly debugging = inject(DebuggingService);
private readonly screenShareSourcePicker = inject(ScreenShareSourcePickerService);
private readonly iceServerSettings = inject(IceServerSettingsService);
private readonly signalServerAuth = inject(SignalServerAuthService);
private readonly store = inject(Store);
private readonly clientInstance = inject(ClientInstanceService);
private currentHomeUser: { id: string; homeSignalServerUrl?: string; displayName: string } | null = null;
private readonly logger = new WebRTCLogger(() => this.debugging.enabled());
private readonly state = new WebRtcStateController();
readonly peerId = this.state.peerId;
readonly isConnected = this.state.isConnected;
readonly hasEverConnected = this.state.hasEverConnected;
readonly isVoiceConnected = this.state.isVoiceConnected;
readonly connectedPeers = this.state.connectedPeers;
readonly isMuted = this.state.isMuted;
readonly isDeafened = this.state.isDeafened;
readonly isCameraEnabled = this.state.isCameraEnabled;
readonly isScreenSharing = this.state.isScreenSharing;
readonly isNoiseReductionEnabled = this.state.isNoiseReductionEnabled;
readonly screenStream = this.state.screenStream;
readonly isScreenShareRemotePlaybackSuppressed = this.state.isScreenShareRemotePlaybackSuppressed;
readonly forceDefaultRemotePlaybackOutput = this.state.forceDefaultRemotePlaybackOutput;
readonly hasConnectionError = this.state.hasConnectionError;
readonly connectionErrorMessage = this.state.connectionErrorMessage;
readonly shouldShowConnectionError = this.state.shouldShowConnectionError;
readonly peerLatencies = this.state.peerLatencies;
private readonly signalingMessage$ = new Subject<IncomingSignalingMessage>();
readonly onSignalingMessage = this.signalingMessage$.asObservable();
private readonly accountSyncRelay$ = new Subject<ChatEvent>();
private readonly signalingReconnectedSubject$ = new Subject<string>();
readonly signalingReconnected$ = this.signalingReconnectedSubject$.asObservable();
// Delegates to managers
get onMessageReceived(): Observable<ChatEvent> {
return merge(this.peerMediaFacade.onMessageReceived, this.accountSyncRelay$);
}
get onPeerConnected(): Observable<string> {
return this.peerMediaFacade.onPeerConnected;
}
get onPeerDisconnected(): Observable<string> {
return this.peerMediaFacade.onPeerDisconnected;
}
get onRemoteStream(): Observable<{ peerId: string; stream: MediaStream }> {
return this.peerMediaFacade.onRemoteStream;
}
get onVoiceConnected(): Observable<void> {
return this.peerMediaFacade.onVoiceConnected;
}
/** The server ID currently being viewed / active, or `null`. */
get currentServerId(): string | null {
return this.state.currentServerId;
}
private readonly timeSync = inject(TimeSyncService);
private readonly debugging = inject(DebuggingService);
private readonly screenShareSourcePicker = inject(ScreenShareSourcePickerService);
private readonly iceServerSettings = inject(IceServerSettingsService);
private readonly signalServerAuth = inject(SignalServerAuthService);
private readonly store = inject(Store);
private readonly clientInstance = inject(ClientInstanceService);
private currentHomeUser: { id: string; homeSignalServerUrl?: string; displayName: string } | null = null;
private readonly logger = new WebRTCLogger(() => this.debugging.enabled());
private readonly state = new WebRtcStateController();
private readonly signalingMessage$ = new Subject<IncomingSignalingMessage>();
private readonly accountSyncRelay$ = new Subject<ChatEvent>();
private readonly signalingReconnectedSubject$ = new Subject<string>();
private readonly peerManager: PeerConnectionManager;
private readonly mediaManager: MediaManager;
private readonly screenShareManager: ScreenShareManager;
private readonly peerMediaFacade: PeerMediaFacade;
private readonly voiceSessionController: VoiceSessionController;
private readonly signalingCoordinator: ServerSignalingCoordinator<IncomingSignalingMessage>;
private readonly signalingTransportHandler: SignalingTransportHandler<IncomingSignalingMessage>;
private readonly signalingMessageHandler: IncomingSignalingMessageHandler;
private readonly serverMembershipSignalingHandler: ServerMembershipSignalingHandler<IncomingSignalingMessage>;
private readonly remoteScreenShareRequestController: RemoteScreenShareRequestController;
constructor() {
@@ -138,11 +182,13 @@ export class WebRTCService implements OnDestroy {
});
// Create managers with null callbacks first to break circular initialization
this.peerManager = new PeerConnectionManager(this.logger, null!);
const pendingPeerMessageHandler = () => undefined;
this.mediaManager = new MediaManager(this.logger, null!);
this.peerManager = new PeerConnectionManager(this.logger, pendingPeerMessageHandler);
this.screenShareManager = new ScreenShareManager(this.logger, null!);
this.mediaManager = new MediaManager(this.logger, pendingPeerMessageHandler);
this.screenShareManager = new ScreenShareManager(this.logger, pendingPeerMessageHandler);
this.peerMediaFacade = new PeerMediaFacade({
peerManager: this.peerManager,
@@ -260,79 +306,6 @@ export class WebRTCService implements OnDestroy {
this.wireManagerEvents();
}
private wireManagerEvents(): void {
// Internal control-plane messages for on-demand screen-share delivery.
this.peerManager.messageReceived$.subscribe((event) =>
this.remoteScreenShareRequestController.handlePeerControlMessage(event)
);
// Peer manager -> connected peers signal
this.peerManager.connectedPeersChanged$.subscribe((peers: string[]) =>
this.state.setConnectedPeers(peers)
);
// If we are already sharing when a new peer connection finishes, push the
// current screen-share tracks to that peer and renegotiate.
this.peerManager.peerConnected$.subscribe((peerId) => {
if (this.peerMediaFacade.isScreenShareActive()) {
this.peerMediaFacade.syncScreenShareToPeer(peerId);
}
this.mediaManager.refreshVoiceRouting();
this.remoteScreenShareRequestController.handlePeerConnected(peerId);
});
this.peerManager.peerDisconnected$.subscribe((peerId) => {
this.remoteScreenShareRequestController.handlePeerDisconnected(peerId);
});
// Media manager -> voice connected signal
this.mediaManager.voiceConnected$.subscribe(() => {
this.voiceSessionController.handleVoiceConnected();
});
// Peer manager -> latency updates
this.peerManager.peerLatencyChanged$.subscribe(() =>
this.state.syncPeerLatencies(this.peerManager.peerLatencies)
);
}
private handleSignalingConnectionStatus(signalUrl: string, connected: boolean, errorMessage?: string): void {
this.state.updateSignalingConnectionStatus(
connected ? true : this.signalingCoordinator.isAnySignalingConnected(),
connected,
errorMessage
);
if (connected) {
this.signalingReconnectedSubject$.next(signalUrl);
}
}
private handleSignalingMessage(message: IncomingSignalingMessage, signalUrl: string): void {
if (message.type === 'auth_required' || message.type === 'auth_error') {
this.store.dispatch(UsersActions.signalServerAuthFailed({ signalUrl }));
return;
}
if (message.type === 'account_sync') {
const accountMessage = message as AccountSyncSignalingMessage;
if (shouldApplyAccountSyncPayload(
accountMessage.clientInstanceId,
this.clientInstance.getClientInstanceId()
)) {
this.accountSyncRelay$.next(unwrapAccountSyncPayload(accountMessage));
}
return;
}
this.signalingMessage$.next(message);
this.signalingMessageHandler.handleMessage(message, signalUrl);
}
// PUBLIC API - matches the old monolithic service's interface
/**
@@ -392,11 +365,6 @@ export class WebRTCService implements OnDestroy {
this.state.setCurrentServer(serverId);
}
/** The server ID currently being viewed / active, or `null`. */
get currentServerId(): string | null {
return this.state.currentServerId;
}
/** The last signaling URL used by the client, if any. */
getCurrentSignalingUrl(): string | null {
return this.signalingTransportHandler.getCurrentSignalingUrl(this.state.currentServerId);
@@ -757,6 +725,107 @@ export class WebRTCService implements OnDestroy {
this.peerMediaFacade.stopScreenShare();
}
requestVoiceClientTakeover(): void {
this.signalingTransportHandler.sendRawMessage({
type: 'voice_client_takeover',
clientInstanceId: this.clientInstance.getClientInstanceId()
});
}
getClientInstanceId(): string {
return this.clientInstance.getClientInstanceId();
}
/** Disconnect from the signaling server and clean up all state. */
disconnect(): void {
this.leaveRoom();
this.destroyAllSignalingManagers();
this.state.resetConnectionState();
}
/** Alias for {@link disconnect}. */
disconnectAll(): void {
this.disconnect();
}
ngOnDestroy(): void {
this.disconnect();
this.peerMediaFacade.destroy();
}
private wireManagerEvents(): void {
// Internal control-plane messages for on-demand screen-share delivery.
this.peerManager.messageReceived$.subscribe((event) =>
this.remoteScreenShareRequestController.handlePeerControlMessage(event)
);
// Peer manager -> connected peers signal
this.peerManager.connectedPeersChanged$.subscribe((peers: string[]) =>
this.state.setConnectedPeers(peers)
);
// If we are already sharing when a new peer connection finishes, push the
// current screen-share tracks to that peer and renegotiate.
this.peerManager.peerConnected$.subscribe((peerId) => {
if (this.peerMediaFacade.isScreenShareActive()) {
this.peerMediaFacade.syncScreenShareToPeer(peerId);
}
this.mediaManager.refreshVoiceRouting();
this.remoteScreenShareRequestController.handlePeerConnected(peerId);
});
this.peerManager.peerDisconnected$.subscribe((peerId) => {
this.remoteScreenShareRequestController.handlePeerDisconnected(peerId);
});
// Media manager -> voice connected signal
this.mediaManager.voiceConnected$.subscribe(() => {
this.voiceSessionController.handleVoiceConnected();
});
// Peer manager -> latency updates
this.peerManager.peerLatencyChanged$.subscribe(() =>
this.state.syncPeerLatencies(this.peerManager.peerLatencies)
);
}
private handleSignalingConnectionStatus(signalUrl: string, connected: boolean, errorMessage?: string): void {
this.state.updateSignalingConnectionStatus(
connected ? true : this.signalingCoordinator.isAnySignalingConnected(),
connected,
errorMessage
);
if (connected) {
this.signalingReconnectedSubject$.next(signalUrl);
}
}
private handleSignalingMessage(message: IncomingSignalingMessage, signalUrl: string): void {
if (message.type === 'auth_required' || message.type === 'auth_error') {
this.store.dispatch(UsersActions.signalServerAuthFailed({ signalUrl }));
return;
}
if (message.type === 'account_sync') {
const accountMessage = message as AccountSyncSignalingMessage;
if (shouldApplyAccountSyncPayload(
accountMessage.clientInstanceId,
this.clientInstance.getClientInstanceId()
)) {
this.accountSyncRelay$.next(unwrapAccountSyncPayload(accountMessage));
}
return;
}
this.signalingMessage$.next(message);
this.signalingMessageHandler.handleMessage(message, signalUrl);
}
private relayBroadcastEvent(event: ChatEvent): void {
const clientInstanceId = this.clientInstance.getClientInstanceId();
@@ -801,29 +870,6 @@ export class WebRTCService implements OnDestroy {
this.relayAccountSync(event);
}
requestVoiceClientTakeover(): void {
this.signalingTransportHandler.sendRawMessage({
type: 'voice_client_takeover',
clientInstanceId: this.clientInstance.getClientInstanceId()
});
}
getClientInstanceId(): string {
return this.clientInstance.getClientInstanceId();
}
/** Disconnect from the signaling server and clean up all state. */
disconnect(): void {
this.leaveRoom();
this.destroyAllSignalingManagers();
this.state.resetConnectionState();
}
/** Alias for {@link disconnect}. */
disconnectAll(): void {
this.disconnect();
}
private fullCleanup(): void {
this.signalingCoordinator.clearPeerTracking();
this.remoteScreenShareRequestController.clear();
@@ -839,8 +885,4 @@ export class WebRTCService implements OnDestroy {
this.signalingCoordinator.destroy();
}
ngOnDestroy(): void {
this.disconnect();
this.peerMediaFacade.destroy();
}
}