mirror of
https://github.com/xtr-dev/rondevu-client.git
synced 2025-12-10 02:43:25 +00:00
Extract duplicate ICE candidate handler code to base PeerState class
Refactored common ICE candidate handling logic to reduce code duplication: - Added setupIceCandidateHandler() method to base PeerState class - Moved iceCandidateHandler property to base class - Updated cleanup() in base class to remove ICE candidate handler - Removed duplicate handler code from CreatingOfferState and AnsweringState - Both states now call this.setupIceCandidateHandler(offerId) This eliminates ~15 lines of duplicated code per state and ensures consistent ICE candidate handling across all states that need it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -6,8 +6,6 @@ import type RondevuPeer from './index.js';
|
|||||||
* Answering an offer and sending to server
|
* Answering an offer and sending to server
|
||||||
*/
|
*/
|
||||||
export class AnsweringState extends PeerState {
|
export class AnsweringState extends PeerState {
|
||||||
private iceCandidateHandler?: (event: RTCPeerConnectionIceEvent) => void;
|
|
||||||
|
|
||||||
constructor(peer: RondevuPeer) {
|
constructor(peer: RondevuPeer) {
|
||||||
super(peer);
|
super(peer);
|
||||||
}
|
}
|
||||||
@@ -33,19 +31,7 @@ export class AnsweringState extends PeerState {
|
|||||||
await this.peer.offersApi.answer(offerId, answer.sdp!);
|
await this.peer.offersApi.answer(offerId, answer.sdp!);
|
||||||
|
|
||||||
// Enable trickle ICE - send candidates as they arrive
|
// Enable trickle ICE - send candidates as they arrive
|
||||||
this.iceCandidateHandler = async (event: RTCPeerConnectionIceEvent) => {
|
this.setupIceCandidateHandler(offerId);
|
||||||
if (event.candidate && offerId) {
|
|
||||||
const candidateData = event.candidate.toJSON();
|
|
||||||
if (candidateData.candidate && candidateData.candidate !== '') {
|
|
||||||
try {
|
|
||||||
await this.peer.offersApi.addIceCandidates(offerId, [candidateData]);
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error sending ICE candidate:', err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.peer.pc.addEventListener('icecandidate', this.iceCandidateHandler);
|
|
||||||
|
|
||||||
// Transition to exchanging ICE
|
// Transition to exchanging ICE
|
||||||
const { ExchangingIceState } = await import('./exchanging-ice-state.js');
|
const { ExchangingIceState } = await import('./exchanging-ice-state.js');
|
||||||
@@ -56,10 +42,4 @@ export class AnsweringState extends PeerState {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup(): void {
|
|
||||||
if (this.iceCandidateHandler) {
|
|
||||||
this.peer.pc.removeEventListener('icecandidate', this.iceCandidateHandler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import type RondevuPeer from './index.js';
|
|||||||
* Creating offer and sending to server
|
* Creating offer and sending to server
|
||||||
*/
|
*/
|
||||||
export class CreatingOfferState extends PeerState {
|
export class CreatingOfferState extends PeerState {
|
||||||
private iceCandidateHandler?: (event: RTCPeerConnectionIceEvent) => void;
|
|
||||||
|
|
||||||
constructor(peer: RondevuPeer, private options: PeerOptions) {
|
constructor(peer: RondevuPeer, private options: PeerOptions) {
|
||||||
super(peer);
|
super(peer);
|
||||||
}
|
}
|
||||||
@@ -41,19 +39,7 @@ export class CreatingOfferState extends PeerState {
|
|||||||
this.peer.offerId = offerId;
|
this.peer.offerId = offerId;
|
||||||
|
|
||||||
// Enable trickle ICE - send candidates as they arrive
|
// Enable trickle ICE - send candidates as they arrive
|
||||||
this.iceCandidateHandler = async (event: RTCPeerConnectionIceEvent) => {
|
this.setupIceCandidateHandler(offerId);
|
||||||
if (event.candidate && offerId) {
|
|
||||||
const candidateData = event.candidate.toJSON();
|
|
||||||
if (candidateData.candidate && candidateData.candidate !== '') {
|
|
||||||
try {
|
|
||||||
await this.peer.offersApi.addIceCandidates(offerId, [candidateData]);
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error sending ICE candidate:', err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.peer.pc.addEventListener('icecandidate', this.iceCandidateHandler);
|
|
||||||
|
|
||||||
// Transition to waiting for answer
|
// Transition to waiting for answer
|
||||||
const { WaitingForAnswerState } = await import('./waiting-for-answer-state.js');
|
const { WaitingForAnswerState } = await import('./waiting-for-answer-state.js');
|
||||||
@@ -66,10 +52,4 @@ export class CreatingOfferState extends PeerState {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup(): void {
|
|
||||||
if (this.iceCandidateHandler) {
|
|
||||||
this.peer.pc.removeEventListener('icecandidate', this.iceCandidateHandler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import type RondevuPeer from './index.js';
|
|||||||
* Implements the State pattern for managing WebRTC connection lifecycle
|
* Implements the State pattern for managing WebRTC connection lifecycle
|
||||||
*/
|
*/
|
||||||
export abstract class PeerState {
|
export abstract class PeerState {
|
||||||
|
protected iceCandidateHandler?: (event: RTCPeerConnectionIceEvent) => void;
|
||||||
|
|
||||||
constructor(protected peer: RondevuPeer) {}
|
constructor(protected peer: RondevuPeer) {}
|
||||||
|
|
||||||
abstract get name(): string;
|
abstract get name(): string;
|
||||||
@@ -29,8 +31,31 @@ export abstract class PeerState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup trickle ICE candidate handler
|
||||||
|
* Sends local ICE candidates to server as they are discovered
|
||||||
|
*/
|
||||||
|
protected setupIceCandidateHandler(offerId: string): void {
|
||||||
|
this.iceCandidateHandler = async (event: RTCPeerConnectionIceEvent) => {
|
||||||
|
if (event.candidate && offerId) {
|
||||||
|
const candidateData = event.candidate.toJSON();
|
||||||
|
if (candidateData.candidate && candidateData.candidate !== '') {
|
||||||
|
try {
|
||||||
|
await this.peer.offersApi.addIceCandidates(offerId, [candidateData]);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error sending ICE candidate:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.peer.pc.addEventListener('icecandidate', this.iceCandidateHandler);
|
||||||
|
}
|
||||||
|
|
||||||
cleanup(): void {
|
cleanup(): void {
|
||||||
// Override in states that need cleanup
|
// Clean up ICE candidate handler if it exists
|
||||||
|
if (this.iceCandidateHandler) {
|
||||||
|
this.peer.pc.removeEventListener('icecandidate', this.iceCandidateHandler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async close(): Promise<void> {
|
async close(): Promise<void> {
|
||||||
|
|||||||
Reference in New Issue
Block a user