HopSpotFrontend/lib/services/sse_service.dart

148 lines
4.1 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_client_sse/constants/sse_request_type_enum.dart';
import 'package:flutter_client_sse/flutter_client_sse.dart';
import 'package:http/http.dart' as http;
class SSEService {
static final SSEService _instance = SSEService._internal();
factory SSEService() => _instance;
SSEService._internal();
StreamSubscription<SSEModel>? _subscription;
VoidCallback? onParticipantChange;
VoidCallback? onGameStart;
void Function(String data)? onChallangeSelected;
VoidCallback? onChallangeDone;
bool get isListening => _subscription != null;
String? _currentSessionId;
int _retryCount = 0;
final int _maxRetries = 5;
bool _isRetrying = false;
bool _isStopping = false;
bool _shouldReconnect = true;
void startListening(String sessionId) {
print("startListening med id: $sessionId ");
if (!_shouldReconnect) {
print("startListening avbröts, återanslutning är blockerad.");
return;
}
if (_isStopping) {
print("_isStopping i startListening är true");
return;
}
if (_currentSessionId == sessionId && isListening) {
print('[SSE] Redan ansluten till session: $sessionId');
return;
}
if (_subscription != null) return;
_currentSessionId = sessionId;
try {
_subscription = SSEClient.subscribeToSSE(
url:
'https://group-1-15.pvt.dsv.su.se/sse/stream/$sessionId', //https://group-1-15.pvt.dsv.su.se http://10.0.2.2:8080
method: SSERequestType.GET,
header: {"Accept": "text/event-stream", "Cache-Control": "no-cache"},
).listen(
(event) {
_retryCount = 0;
final data = event.data?.trim();
if (data == null) return;
if (data == "start") {
onGameStart?.call();
} else if (data == "participantChange") {
onParticipantChange?.call();
} else if (data.startsWith("challenge")) {
final challengeText = data.substring("challenge:".length).trim();
onChallangeSelected?.call(challengeText);
} else if (data.startsWith("finished")) {
onChallangeDone?.call();
}
},
onError: (err) {
print("SSE error: $err");
_handleRetry(sessionId);
},
onDone: () {
handleStopListening();
},
cancelOnError: true,
);
} catch (e) {
print("Error i startListening: $e");
}
}
void allowReconnect() {
_shouldReconnect = true;
}
void _handleRetry(String sessionId) {
if (!_shouldReconnect) {
print("startListening avbröts, återanslutning är blockerad.");
return;
}
if (_isRetrying) return;
_isRetrying = true;
if (_retryCount < _maxRetries) {
_retryCount++;
final delay = Duration(seconds: 2 * _retryCount);
print('[SSE] Försöker återansluta om ${delay.inSeconds} sekunder...');
Future.delayed(delay, () {
if (_currentSessionId == sessionId) {
startListening(sessionId); // Återanslut
}
_isRetrying = false;
});
} else {
print('[SSE] Max antal återförsök nått.');
_isRetrying = false;
handleStopListening();
}
}
void handleStopListening() async {
await stopListening();
}
Future<void> stopListening() async {
print("Kör stopListening");
_shouldReconnect = false;
if (_isStopping) {
print("_isStopping är true");
return;
}
_isStopping = true;
if (!isListening) {
print('stopListening kallades men SSE är redan stoppad.');
_isStopping = false;
return;
}
if (_currentSessionId != null) {
final url = Uri.parse(
'https://group-1-15.pvt.dsv.su.se/sse/remove/$_currentSessionId',
);
final response = await http.delete(
url,
headers: {"Content-Type": "application/json"},
body: '"disconnect"',
);
print('DELETE removeSession status: ${response.statusCode}');
}
SSEClient.unsubscribeFromSSE();
await _subscription?.cancel();
_subscription = null;
_currentSessionId = null;
_isStopping = false;
}
}