148 lines
4.1 KiB
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;
|
|
}
|
|
}
|