переподключение, рабочий логаут

This commit is contained in:
needle10
2025-12-01 20:47:54 +03:00
parent b277da140a
commit ee60cd41d9
2 changed files with 113 additions and 5 deletions

View File

@@ -661,6 +661,18 @@ extension ApiServiceConnection on ApiService {
_pingTimer?.cancel(); _pingTimer?.cancel();
_reconnectTimer?.cancel(); _reconnectTimer?.cancel();
_streamSubscription?.cancel();
if (_channel != null) {
print("Закрываем старое WebSocket соединение перед переподключением...");
try {
_channel!.sink.close(status.goingAway);
} catch (e) {
print("Ошибка при закрытии старого соединения: $e");
}
_channel = null;
}
_isSessionOnline = false; _isSessionOnline = false;
_isSessionReady = false; _isSessionReady = false;
_handshakeSent = false; _handshakeSent = false;
@@ -730,10 +742,17 @@ extension ApiServiceConnection on ApiService {
try { try {
_pingTimer?.cancel(); _pingTimer?.cancel();
_reconnectTimer?.cancel(); _reconnectTimer?.cancel();
_streamSubscription?.cancel(); _streamSubscription?.cancel();
_streamSubscription = null;
if (_channel != null) { if (_channel != null) {
_channel!.sink.close(); print("🔄 Закрываем старое WebSocket соединение...");
try {
_channel!.sink.close(status.goingAway);
} catch (e) {
print("Ошибка при закрытии старого соединения: $e");
}
_channel = null; _channel = null;
} }
@@ -752,23 +771,23 @@ extension ApiServiceConnection on ApiService {
_lastChatsAt = null; _lastChatsAt = null;
print( print(
" Кэш чатов очищен: _lastChatsPayload = $_lastChatsPayload, _chatsFetchedInThisSession = $_chatsFetchedInThisSession", "🔄 Кэш чатов очищен: _lastChatsPayload = $_lastChatsPayload, _chatsFetchedInThisSession = $_chatsFetchedInThisSession",
); );
_connectionStatusController.add("disconnected"); _connectionStatusController.add("disconnected");
await connect(); await connect();
print(" Полное переподключение завершено"); print(" Полное переподключение завершено");
await Future.delayed(const Duration(milliseconds: 1500)); await Future.delayed(const Duration(milliseconds: 1500));
if (!_reconnectionCompleteController.isClosed) { if (!_reconnectionCompleteController.isClosed) {
print(" Отправляем уведомление о завершении переподключения"); print(" Отправляем уведомление о завершении переподключения");
_reconnectionCompleteController.add(null); _reconnectionCompleteController.add(null);
} }
} catch (e) { } catch (e) {
print("Ошибка полного переподключения: $e"); print("Ошибка полного переподключения: $e");
rethrow; rethrow;
} }
} }

View File

@@ -98,6 +98,7 @@ class _ChatsScreenState extends State<ChatsScreen>
StreamSubscription<void>? _connectionStatusSubscription; StreamSubscription<void>? _connectionStatusSubscription;
StreamSubscription<String>? _connectionStateSubscription; StreamSubscription<String>? _connectionStateSubscription;
bool _isAccountsExpanded = false; bool _isAccountsExpanded = false;
bool _isReconnecting = false;
SharedPreferences? _prefs; SharedPreferences? _prefs;
@@ -2328,6 +2329,61 @@ class _ChatsScreenState extends State<ChatsScreen>
); );
}, },
), ),
ListTile(
leading: _isReconnecting
? SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
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( ListTile(
leading: const Icon(Icons.settings_outlined), leading: const Icon(Icons.settings_outlined),
title: const Text('Настройки'), title: const Text('Настройки'),
@@ -3892,6 +3948,39 @@ class _ChatsScreenState extends State<ChatsScreen>
Future<void> _logout() async { Future<void> _logout() async {
try { 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) { if (mounted) {
Navigator.of(context).pushAndRemoveUntil( Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => const PhoneEntryScreen()), MaterialPageRoute(builder: (context) => const PhoneEntryScreen()),