diff --git a/lib/api/api_service_connection.dart b/lib/api/api_service_connection.dart index 086916c..65d8bef 100644 --- a/lib/api/api_service_connection.dart +++ b/lib/api/api_service_connection.dart @@ -661,6 +661,18 @@ extension ApiServiceConnection on ApiService { _pingTimer?.cancel(); _reconnectTimer?.cancel(); + _streamSubscription?.cancel(); + + if (_channel != null) { + print("Закрываем старое WebSocket соединение перед переподключением..."); + try { + _channel!.sink.close(status.goingAway); + } catch (e) { + print("Ошибка при закрытии старого соединения: $e"); + } + _channel = null; + } + _isSessionOnline = false; _isSessionReady = false; _handshakeSent = false; @@ -730,10 +742,17 @@ extension ApiServiceConnection on ApiService { try { _pingTimer?.cancel(); _reconnectTimer?.cancel(); + _streamSubscription?.cancel(); + _streamSubscription = null; if (_channel != null) { - _channel!.sink.close(); + print("🔄 Закрываем старое WebSocket соединение..."); + try { + _channel!.sink.close(status.goingAway); + } catch (e) { + print("Ошибка при закрытии старого соединения: $e"); + } _channel = null; } @@ -752,23 +771,23 @@ extension ApiServiceConnection on ApiService { _lastChatsAt = null; print( - " Кэш чатов очищен: _lastChatsPayload = $_lastChatsPayload, _chatsFetchedInThisSession = $_chatsFetchedInThisSession", + "🔄 Кэш чатов очищен: _lastChatsPayload = $_lastChatsPayload, _chatsFetchedInThisSession = $_chatsFetchedInThisSession", ); _connectionStatusController.add("disconnected"); await connect(); - print(" Полное переподключение завершено"); + print("✅ Полное переподключение завершено"); await Future.delayed(const Duration(milliseconds: 1500)); if (!_reconnectionCompleteController.isClosed) { - print(" Отправляем уведомление о завершении переподключения"); + print("✅ Отправляем уведомление о завершении переподключения"); _reconnectionCompleteController.add(null); } } catch (e) { - print("Ошибка полного переподключения: $e"); + print("❌ Ошибка полного переподключения: $e"); rethrow; } } diff --git a/lib/screens/chats_screen.dart b/lib/screens/chats_screen.dart index 073a009..5b94e70 100644 --- a/lib/screens/chats_screen.dart +++ b/lib/screens/chats_screen.dart @@ -98,6 +98,7 @@ class _ChatsScreenState extends State StreamSubscription? _connectionStatusSubscription; StreamSubscription? _connectionStateSubscription; bool _isAccountsExpanded = false; + bool _isReconnecting = false; SharedPreferences? _prefs; @@ -2328,6 +2329,61 @@ class _ChatsScreenState extends State ); }, ), + ListTile( + leading: _isReconnecting + ? SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator( + strokeWidth: 2, + valueColor: AlwaysStoppedAnimation( + colors.primary, + ), + ), + ) + : const Icon(Icons.refresh), + title: const Text('Переподключиться'), + enabled: !_isReconnecting, + onTap: () async { + if (_isReconnecting) return; + + setState(() { + _isReconnecting = true; + }); + + try { + await ApiService.instance.performFullReconnection(); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text( + 'Переподключение выполнено успешно', + ), + backgroundColor: colors.primaryContainer, + duration: const Duration(seconds: 2), + ), + ); + Navigator.pop(context); + } + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Ошибка переподключения: $e'), + backgroundColor: colors.error, + duration: const Duration(seconds: 3), + ), + ); + } + } finally { + if (mounted) { + setState(() { + _isReconnecting = false; + }); + } + } + }, + ), ListTile( leading: const Icon(Icons.settings_outlined), title: const Text('Настройки'), @@ -3892,6 +3948,39 @@ class _ChatsScreenState extends State Future _logout() async { try { + ApiService.instance.disconnect(); + + final accountManager = AccountManager(); + await accountManager.initialize(); + final currentAccount = accountManager.currentAccount; + + if (currentAccount != null) { + try { + if (accountManager.accounts.length > 1) { + await accountManager.removeAccount(currentAccount.id); + } else { + final prefs = await SharedPreferences.getInstance(); + await prefs.remove('authToken'); + await prefs.remove('userId'); + await prefs.remove('multi_accounts'); + await prefs.remove('current_account_id'); + } + } catch (e) { + print('Ошибка при удалении аккаунта: $e'); + final prefs = await SharedPreferences.getInstance(); + await prefs.remove('authToken'); + await prefs.remove('userId'); + } + } else { + final prefs = await SharedPreferences.getInstance(); + await prefs.remove('authToken'); + await prefs.remove('userId'); + } + + await ApiService.instance.logout(); + + ApiService.instance.clearAllCaches(); + if (mounted) { Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (context) => const PhoneEntryScreen()),