Stabilizza live YouTube/RTMP e fix crash rotazione mobile.

Pipeline YouTube con relay, overlay e publisher sync lato backend; fix GL pauseGlDuringRotation su Android per evitare crash in rotazione durante lo streaming Flutter.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-06 15:30:55 +02:00
parent 1058c644bd
commit 854738b46d
65 changed files with 2606 additions and 579 deletions

View File

@@ -21,8 +21,8 @@ class ApiClient {
_dio = Dio(
BaseOptions(
baseUrl: AppConfig.apiV1,
connectTimeout: const Duration(seconds: 15),
receiveTimeout: const Duration(seconds: 15),
connectTimeout: const Duration(seconds: 30),
receiveTimeout: const Duration(seconds: 30),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
@@ -62,12 +62,18 @@ class ApiClient {
);
}
Future<AuthTokens> refresh(String refreshToken) async {
Future<({User user, AuthTokens tokens})> refreshSession(
String refreshToken,
) async {
final response = await _dio.post<Map<String, dynamic>>(
'/auth/refresh',
data: {'refresh_token': refreshToken},
);
return AuthTokens.fromJson(response.data!);
final data = response.data!;
return (
user: User.fromJson(data['user'] as Map<String, dynamic>),
tokens: AuthTokens.fromJson(data),
);
}
Future<User> me() async {

View File

@@ -26,6 +26,7 @@ class WebsocketService {
ActionCable? _cable;
ActionChannel? _channel;
String? _sessionId;
Future<void>? _connectOp;
bool get isConnected => _cable != null && _channel != null;
@@ -35,6 +36,24 @@ class WebsocketService {
}) async {
if (_sessionId == sessionId && isConnected) return;
final prev = _connectOp;
if (prev != null) await prev.catchError((_) {});
_connectOp = _connect(sessionId: sessionId, deviceRole: deviceRole);
final op = _connectOp!;
try {
await op;
} finally {
if (identical(_connectOp, op)) {
_connectOp = null;
}
}
}
Future<void> _connect({
required String sessionId,
required String deviceRole,
}) async {
await disconnect();
final token = _ref.read(authProvider).accessToken;
@@ -161,11 +180,20 @@ class WebsocketService {
}
Future<void> disconnect() async {
_channel?.unsubscribe();
final channel = _channel;
final cable = _cable;
_channel = null;
_cable?.disconnect();
_cable = null;
_sessionId = null;
try {
channel?.unsubscribe();
} catch (_) {}
try {
cable?.disconnect();
} catch (_) {}
await Future<void>.delayed(const Duration(milliseconds: 150));
_ref.read(sessionProvider.notifier).setConnected(false);
}