bad7366bdb
- create challange window - challanges view page - decline and accept - notif tab (wip) - active game window (wip) --------- Co-authored-by: shahdlala66 <shahd.lala66@gmail.com> Co-authored-by: Lala, Shahd <Shahd.Lala@sybit.de> Reviewed-on: #3
136 lines
4.1 KiB
TypeScript
136 lines
4.1 KiB
TypeScript
import { Injectable, inject } from '@angular/core';
|
|
import { Subject } from 'rxjs';
|
|
import { ChallengeEventService } from './challenge-event.service';
|
|
import { Challenge } from '../models/challenge.models';
|
|
|
|
/**
|
|
* Service to handle WebSocket connections for challenge events
|
|
* Listens for incoming challenge notifications and emits them to ChallengeEventService
|
|
*/
|
|
@Injectable({ providedIn: 'root' })
|
|
export class ChallengeWebSocketService {
|
|
private readonly challengeEventService = inject(ChallengeEventService);
|
|
private ws: WebSocket | null = null;
|
|
private reconnectAttempts = 0;
|
|
private readonly maxReconnectAttempts = 5;
|
|
private readonly reconnectDelay = 3000;
|
|
|
|
/**
|
|
* Initialize WebSocket connection for challenge events
|
|
*/
|
|
connect(): void {
|
|
if (this.ws) {
|
|
return; // Already connected
|
|
}
|
|
|
|
const wsProtocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
|
|
const wsUrl = `${wsProtocol}://${window.location.host}/ws/challenges`;
|
|
|
|
try {
|
|
this.ws = new WebSocket(wsUrl);
|
|
|
|
this.ws.onopen = () => {
|
|
console.log('Challenge WebSocket connected');
|
|
this.reconnectAttempts = 0;
|
|
};
|
|
|
|
this.ws.onmessage = (event) => {
|
|
this.handleMessage(event.data);
|
|
};
|
|
|
|
this.ws.onerror = (error) => {
|
|
console.error('Challenge WebSocket error:', error);
|
|
};
|
|
|
|
this.ws.onclose = () => {
|
|
console.log('Challenge WebSocket disconnected');
|
|
this.ws = null;
|
|
this.attemptReconnect();
|
|
};
|
|
} catch (error) {
|
|
console.error('Failed to create WebSocket:', error);
|
|
this.attemptReconnect();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Close the WebSocket connection
|
|
*/
|
|
disconnect(): void {
|
|
if (this.ws) {
|
|
this.ws.close();
|
|
this.ws = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send a message through WebSocket
|
|
*/
|
|
send(message: any): void {
|
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
this.ws.send(JSON.stringify(message));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle incoming WebSocket messages
|
|
*/
|
|
private handleMessage(data: string): void {
|
|
try {
|
|
const message = JSON.parse(data);
|
|
|
|
if (!message.type) {
|
|
return;
|
|
}
|
|
|
|
switch (message.type) {
|
|
case 'challenge.received':
|
|
if (message.challenge) {
|
|
this.challengeEventService.onChallengeReceived(message.challenge as Challenge);
|
|
}
|
|
break;
|
|
|
|
case 'challenge.accepted':
|
|
if (message.challenge) {
|
|
this.challengeEventService.onChallengeAccepted(message.challenge as Challenge);
|
|
}
|
|
break;
|
|
|
|
case 'challenge.declined':
|
|
if (message.challengeId) {
|
|
this.challengeEventService.removeChallenge(message.challengeId);
|
|
}
|
|
break;
|
|
|
|
case 'challenge.expired':
|
|
if (message.challengeId) {
|
|
this.challengeEventService.removeChallenge(message.challengeId);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
console.debug('Unknown challenge message type:', message.type);
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to parse WebSocket message:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attempt to reconnect to WebSocket
|
|
*/
|
|
private attemptReconnect(): void {
|
|
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
console.error('Max WebSocket reconnection attempts reached');
|
|
return;
|
|
}
|
|
|
|
this.reconnectAttempts++;
|
|
console.log(`Attempting WebSocket reconnect (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
|
|
|
|
setTimeout(() => {
|
|
this.connect();
|
|
}, this.reconnectDelay);
|
|
}
|
|
}
|