import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class E2eeDiagEntry { final DateTime timestamp; final String roomId; final String eventId; final String sessionId; final String error; const E2eeDiagEntry({ required this.timestamp, required this.roomId, required this.eventId, required this.sessionId, required this.error, }); Map toJson() => { 'ts': timestamp.toIso8601String(), 'room': roomId, 'event': eventId, 'session': sessionId, 'error': error, }; } class E2eeDiagnosticsNotifier extends Notifier> { static const int _maxEntries = 500; @override List build() => []; void add(E2eeDiagEntry entry) { final next = [...state, entry]; state = next.length > _maxEntries ? next.sublist(next.length - _maxEntries) : next; } void clear() => state = []; Future upload({required String serverUrl, required String token}) async { if (state.isEmpty) return 'Keine Diagnosedaten vorhanden.'; final payload = utf8.encode(jsonEncode({ 'client': 'Pyramid', 'uploaded_at': DateTime.now().toIso8601String(), 'entry_count': state.length, 'entries': state.map((e) => e.toJson()).toList(), })); final client = HttpClient(); try { final uri = Uri.parse('$serverUrl/api/e2ee-diagnostics'); final request = await client.postUrl(uri); request.headers.set('Content-Type', 'application/json; charset=utf-8'); request.headers.set('Authorization', 'Bearer $token'); request.headers.contentLength = payload.length; request.add(payload); final response = await request.close(); await response.drain(); if (response.statusCode == 200) { final count = state.length; clear(); return '$count Einträge hochgeladen und lokal gelöscht.'; } return 'Server-Fehler: HTTP ${response.statusCode}'; } on SocketException catch (e) { return 'Netzwerkfehler: ${e.message}'; } catch (e) { return 'Fehler: $e'; } finally { client.close(); } } } final e2eeDiagnosticsProvider = NotifierProvider>( E2eeDiagnosticsNotifier.new, );