Ответ на файлы отображается не как фото а как файл, список чатов теперь не дохлая хуйня, динамично изменяется. Написал левый хуй? Появляется чат сразу, создал группу? Создалось, вышел? Вышел.(+ баг что на desktop режимах отображения при выходах чернеет экран)
This commit is contained in:
@@ -332,7 +332,10 @@ class _ChatsScreenState extends State<ChatsScreen>
|
||||
final chatIdValue = payload['chatId'];
|
||||
final int? chatId = chatIdValue != null ? chatIdValue as int? : null;
|
||||
|
||||
if (opcode == 272 || opcode == 274) {
|
||||
// Для части опкодов (48, 55, 135, 272, 274) нам не нужен явный chatId в корне
|
||||
// payload, поэтому не отбрасываем их, даже если chatId == null.
|
||||
if (opcode == 272 || opcode == 274 || opcode == 48 || opcode == 55 || opcode == 135) {
|
||||
// продолжаем обработку ниже
|
||||
} else if (chatId == null) {
|
||||
return;
|
||||
}
|
||||
@@ -341,11 +344,44 @@ class _ChatsScreenState extends State<ChatsScreen>
|
||||
_setTypingForChat(chatId);
|
||||
}
|
||||
|
||||
// Ответ на отправку сообщения (opcode 64).
|
||||
// Если сервер прислал в payload полный объект chat (как при создании группы
|
||||
// через CONTROL new), добавляем/обновляем чат локально.
|
||||
if (opcode == 64 && cmd == 1 && payload['chat'] is Map<String, dynamic>) {
|
||||
final chatJson = payload['chat'] as Map<String, dynamic>;
|
||||
final newChat = Chat.fromJson(chatJson);
|
||||
|
||||
// Обновляем также глобальный кэш ApiService, чтобы настройки группы и
|
||||
// другие экраны сразу видели корректные права/админов/опции.
|
||||
ApiService.instance.updateChatInCacheFromJson(chatJson);
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
final existingIndex =
|
||||
_allChats.indexWhere((chat) => chat.id == newChat.id);
|
||||
|
||||
if (existingIndex != -1) {
|
||||
_allChats[existingIndex] = newChat;
|
||||
} else {
|
||||
final savedIndex = _allChats.indexWhere(_isSavedMessages);
|
||||
final insertIndex = savedIndex >= 0 ? savedIndex + 1 : 0;
|
||||
_allChats.insert(insertIndex, newChat);
|
||||
}
|
||||
|
||||
_filterChats();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Новый входящий месседж (opcode 128) — обновляем последний месседж и
|
||||
// двигаем чат вверх БЕЗ полного рефреша с сервера. Если такого чата ещё нет
|
||||
// (нам написал новый пользователь), создаём его на основе payload.chat.
|
||||
if (opcode == 128 && chatId != null) {
|
||||
final newMessage = Message.fromJson(payload['message']);
|
||||
ApiService.instance.clearCacheForChat(chatId);
|
||||
|
||||
final int chatIndex = _allChats.indexWhere((chat) => chat.id == chatId);
|
||||
|
||||
if (chatIndex != -1) {
|
||||
final oldChat = _allChats[chatIndex];
|
||||
final updatedChat = oldChat.copyWith(
|
||||
@@ -377,6 +413,21 @@ class _ChatsScreenState extends State<ChatsScreen>
|
||||
}
|
||||
_filterChats();
|
||||
});
|
||||
} else if (payload['chat'] is Map<String, dynamic>) {
|
||||
// Чат ещё не известен клиенту — создаём его на основе payload.chat.
|
||||
final chatJson = payload['chat'] as Map<String, dynamic>;
|
||||
final newChat = Chat.fromJson(chatJson);
|
||||
|
||||
// Обновляем глобальный кэш ApiService, чтобы дальше во всех экранах
|
||||
// был один и тот же объект чата.
|
||||
ApiService.instance.updateChatInCacheFromJson(chatJson);
|
||||
|
||||
setState(() {
|
||||
final savedIndex = _allChats.indexWhere(_isSavedMessages);
|
||||
final insertIndex = savedIndex >= 0 ? savedIndex + 1 : 0;
|
||||
_allChats.insert(insertIndex, newChat);
|
||||
_filterChats();
|
||||
});
|
||||
}
|
||||
} else if (opcode == 67 && chatId != null) {
|
||||
final editedMessage = Message.fromJson(payload['message']);
|
||||
@@ -446,10 +497,6 @@ class _ChatsScreenState extends State<ChatsScreen>
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode == 129 && chatId != null) {
|
||||
_setTypingForChat(chatId);
|
||||
}
|
||||
|
||||
if (opcode == 132) {
|
||||
final bool isOnline = payload['online'] == true;
|
||||
|
||||
@@ -536,10 +583,96 @@ class _ChatsScreenState extends State<ChatsScreen>
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
||||
// Создание/обновление группы (opcode 48) — стараемся обновить список чатов
|
||||
// локально по объекту chat из payload, без повторного getChatsAndContacts.
|
||||
if (opcode == 48) {
|
||||
print('Получен ответ на создание группы: $payload');
|
||||
print('Получен ответ на создание/обновление группы: $payload');
|
||||
|
||||
_refreshChats();
|
||||
final chatJson = payload['chat'] as Map<String, dynamic>?;
|
||||
final chatsJson = payload['chats'] as List<dynamic>?;
|
||||
|
||||
// Приоритет: одиночный chat, дальше — первый из списка chats.
|
||||
Map<String, dynamic>? effectiveChatJson = chatJson;
|
||||
if (effectiveChatJson == null && chatsJson != null && chatsJson.isNotEmpty) {
|
||||
final first = chatsJson.first;
|
||||
if (first is Map<String, dynamic>) {
|
||||
effectiveChatJson = first;
|
||||
}
|
||||
}
|
||||
|
||||
if (effectiveChatJson != null) {
|
||||
final newChat = Chat.fromJson(effectiveChatJson);
|
||||
|
||||
// Синхронизируем объект чата и в глобальном кэше ApiService.
|
||||
ApiService.instance.updateChatInCacheFromJson(effectiveChatJson);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
final existingIndex =
|
||||
_allChats.indexWhere((chat) => chat.id == newChat.id);
|
||||
|
||||
if (existingIndex != -1) {
|
||||
_allChats[existingIndex] = newChat;
|
||||
} else {
|
||||
// Вставляем новый чат сразу после "Избранного", если оно есть.
|
||||
final savedIndex = _allChats.indexWhere(_isSavedMessages);
|
||||
final insertIndex = savedIndex >= 0 ? savedIndex + 1 : 0;
|
||||
_allChats.insert(insertIndex, newChat);
|
||||
}
|
||||
|
||||
_filterChats();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Fallback: если сервер не прислал chat, обновляемся старым способом.
|
||||
_refreshChats();
|
||||
}
|
||||
}
|
||||
|
||||
// Изменение параметров чата (rename, invite‑link и т.п.) приходит с opcode 55.
|
||||
// В payload обычно лежит обновленный объект chat.
|
||||
if (opcode == 55 && cmd == 1) {
|
||||
final chatJson = payload['chat'] as Map<String, dynamic>?;
|
||||
if (chatJson != null) {
|
||||
final updatedChat = Chat.fromJson(chatJson);
|
||||
|
||||
// Обновляем глобальный кэш ApiService, чтобы настройки группы и др.
|
||||
// сразу видели новые права/линки/название.
|
||||
ApiService.instance.updateChatInCacheFromJson(chatJson);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
final existingIndex =
|
||||
_allChats.indexWhere((chat) => chat.id == updatedChat.id);
|
||||
|
||||
if (existingIndex != -1) {
|
||||
_allChats[existingIndex] = updatedChat;
|
||||
} else {
|
||||
final savedIndex = _allChats.indexWhere(_isSavedMessages);
|
||||
final insertIndex = savedIndex >= 0 ? savedIndex + 1 : 0;
|
||||
_allChats.insert(insertIndex, updatedChat);
|
||||
}
|
||||
|
||||
_filterChats();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Выход из группы: сервер сначала шлёт opcode 135 с chat.status = REMOVED,
|
||||
// а уже потом opcode 58 с CONTROL-сообщением "leave". Для обновления списка
|
||||
// чатов нам важен именно 135.
|
||||
if (opcode == 135 && payload['chat'] is Map<String, dynamic>) {
|
||||
final removedChat = payload['chat'] as Map<String, dynamic>;
|
||||
final int? removedChatId = removedChat['id'] as int?;
|
||||
final String? status = removedChat['status'] as String?;
|
||||
|
||||
if (removedChatId != null && status == 'REMOVED') {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_allChats.removeWhere((chat) => chat.id == removedChatId);
|
||||
_filteredChats.removeWhere((chat) => chat.id == removedChatId);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode == 272) {
|
||||
@@ -672,6 +805,14 @@ class _ChatsScreenState extends State<ChatsScreen>
|
||||
});
|
||||
}
|
||||
|
||||
void _removeChatLocally(int chatId) {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_allChats.removeWhere((c) => c.id == chatId);
|
||||
_filteredChats.removeWhere((c) => c.id == chatId);
|
||||
});
|
||||
}
|
||||
|
||||
final Map<int, Timer> _typingDecayTimers = {};
|
||||
final Set<int> _typingChats = {};
|
||||
final Set<int> _onlineChats = {};
|
||||
@@ -2367,7 +2508,7 @@ class _ChatsScreenState extends State<ChatsScreen>
|
||||
isChannel: isChannel,
|
||||
participantCount: participantCount,
|
||||
onChatUpdated: () {
|
||||
print('Chat updated, но не обновляем список чатов...');
|
||||
_removeChatLocally(chat.id);
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -2513,7 +2654,9 @@ class _ChatsScreenState extends State<ChatsScreen>
|
||||
} else if (chat.title?.isNotEmpty == true) {
|
||||
title = chat.title!;
|
||||
} else {
|
||||
title = "ID ${otherParticipantId ?? 0}";
|
||||
// Контакт ещё не загружен — показываем плейсхолдер и
|
||||
// параллельно запускаем загрузку.
|
||||
title = "Данные загружаются...";
|
||||
if (otherParticipantId != null && otherParticipantId != 0) {
|
||||
_loadMissingContact(otherParticipantId);
|
||||
}
|
||||
@@ -4001,7 +4144,8 @@ class _ChatsScreenState extends State<ChatsScreen>
|
||||
} else if (chat.title?.isNotEmpty == true) {
|
||||
title = chat.title!;
|
||||
} else {
|
||||
title = "ID $otherParticipantId";
|
||||
// Контакт ещё не загружен — плейсхолдер и асинхронная подзагрузка.
|
||||
title = "Данные загружаются...";
|
||||
_loadMissingContact(otherParticipantId);
|
||||
}
|
||||
avatarUrl = contact?.photoBaseUrl;
|
||||
@@ -4075,7 +4219,7 @@ class _ChatsScreenState extends State<ChatsScreen>
|
||||
isChannel: isChannel,
|
||||
participantCount: participantCount,
|
||||
onChatUpdated: () {
|
||||
print('Chat updated, но не обновляем список чатов...');
|
||||
_removeChatLocally(chat.id);
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -4751,7 +4895,15 @@ class _AddChatsToFolderDialogState extends State<_AddChatsToFolderDialog> {
|
||||
),
|
||||
],
|
||||
),
|
||||
title: Text(title, style: const TextStyle(fontSize: 16)),
|
||||
title: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontStyle: title == 'Данные загружаются...'
|
||||
? FontStyle.italic
|
||||
: FontStyle.normal,
|
||||
),
|
||||
),
|
||||
subtitle: isGroupChat && chat.participantIds.length > 2
|
||||
? Text(
|
||||
'${chat.participantIds.length} участников',
|
||||
|
||||
Reference in New Issue
Block a user