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
@@ -27,8 +27,6 @@ import {
import { Subscription } from 'rxjs';
import { VoiceConnectionFacade } from '../facades/voice-connection.facade';
import { DebuggingService } from '../../../../core/services/debugging.service';
/* eslint-disable @typescript-eslint/member-ordering, @typescript-eslint/prefer-for-of, max-statements-per-line */
const SPEAKING_THRESHOLD = 0.015;
const SILENT_FRAME_GRACE = 8;
const FFT_SIZE = 256;
@@ -46,15 +44,20 @@ interface TrackedStream {
@Injectable({ providedIn: 'root' })
export class VoiceActivityService implements OnDestroy {
readonly speakingMap: Signal<ReadonlyMap<string, boolean>> = this._speakingMap;
private readonly voiceConnection = inject(VoiceConnectionFacade);
private readonly debugging = inject(DebuggingService);
private readonly tracked = new Map<string, TrackedStream>();
private animFrameId: number | null = null;
private readonly subs: Subscription[] = [];
private readonly _speakingMap = signal<ReadonlyMap<string, boolean>>(new Map());
readonly speakingMap: Signal<ReadonlyMap<string, boolean>> = this._speakingMap;
private animFrameId: number | null = null;
private readonly subs: Subscription[] = [];
private readonly _speakingMap = signal<ReadonlyMap<string, boolean>>(new Map());
constructor() {
this.subs.push(
@@ -176,30 +179,11 @@ export class VoiceActivityService implements OnDestroy {
this.stopPolling();
}
private ensureAllRemoteStreamsTracked(): void {
const peers = this.voiceConnection.getConnectedPeers();
for (const peerId of peers) {
const stream = this.voiceConnection.getRemoteVoiceStream(peerId);
if (stream) {
this.trackStream(peerId, stream);
}
}
}
private ensurePolling(): void {
if (this.animFrameId !== null)
return;
this.poll();
}
private stopPolling(): void {
if (this.animFrameId !== null) {
cancelAnimationFrame(this.animFrameId);
this.animFrameId = null;
}
ngOnDestroy(): void {
this.stopPolling();
this.tracked.forEach((entry) => this.disposeEntry(entry));
this.tracked.clear();
this.subs.forEach((subscription) => subscription.unsubscribe());
}
private poll = (): void => {
@@ -212,8 +196,8 @@ export class VoiceActivityService implements OnDestroy {
let sumSquares = 0;
for (let sampleIndex = 0; sampleIndex < dataArray.length; sampleIndex++) {
const normalised = (dataArray[sampleIndex] - 128) / 128;
for (const sample of dataArray) {
const normalised = (sample - 128) / 128;
sumSquares += normalised * normalised;
}
@@ -249,6 +233,32 @@ export class VoiceActivityService implements OnDestroy {
this.animFrameId = requestAnimationFrame(this.poll);
};
private ensureAllRemoteStreamsTracked(): void {
const peers = this.voiceConnection.getConnectedPeers();
for (const peerId of peers) {
const stream = this.voiceConnection.getRemoteVoiceStream(peerId);
if (stream) {
this.trackStream(peerId, stream);
}
}
}
private ensurePolling(): void {
if (this.animFrameId !== null)
return;
this.poll();
}
private stopPolling(): void {
if (this.animFrameId !== null) {
cancelAnimationFrame(this.animFrameId);
this.animFrameId = null;
}
}
private publishSpeakingMap(): void {
const map = new Map<string, boolean>();
@@ -269,16 +279,18 @@ export class VoiceActivityService implements OnDestroy {
private disposeEntry(entry: TrackedStream): void {
entry.sources.forEach((source) => {
try { source.disconnect(); } catch { /* already disconnected */ }
try {
source.disconnect();
} catch {
/* already disconnected */
}
});
try { entry.ctx.close(); } catch { /* already closed */ }
try {
entry.ctx.close();
} catch {
/* already closed */
}
}
ngOnDestroy(): void {
this.stopPolling();
this.tracked.forEach((entry) => this.disposeEntry(entry));
this.tracked.clear();
this.subs.forEach((subscription) => subscription.unsubscribe());
}
}