From 94ca2016ba9f856cf1713e3a54a10f2fe6b6b678 Mon Sep 17 00:00:00 2001 From: klockky Date: Thu, 9 Jul 2026 20:29:05 +0300 Subject: [PATCH] =?UTF-8?q?feat(chats):=20=D0=BF=D0=BE=D0=BB=D0=BD=D0=B0?= =?UTF-8?q?=D1=8F=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B0=20?= =?UTF-8?q?=D1=81=D0=BF=D0=B8=D1=81=D0=BA=D0=B0=20=D1=87=D0=B0=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20=D0=BF=D0=B0=D0=B3?= =?UTF-8?q?=D0=B8=D0=BD=D0=B0=D1=86=D0=B8=D1=8E=20(opcode=2053)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/backend/modules/account.dart | 1 + lib/backend/modules/chats.dart | 120 +++++++++++++++++++++++-------- 2 files changed, 91 insertions(+), 30 deletions(-) diff --git a/lib/backend/modules/account.dart b/lib/backend/modules/account.dart index 96da788..a322a93 100644 --- a/lib/backend/modules/account.dart +++ b/lib/backend/modules/account.dart @@ -586,6 +586,7 @@ class AccountModule { await _saveSyncState(data, serverTime, profile.id); await ContactsModule.syncFromLoginPayload(data, profile.id); await chats.syncFromLoginPayload(data, profile.id, profile.id); + unawaited(chats.paginateChats(_api, profile.id, profile.id, data)); try { await ContactsModule.syncFromServer(_api, profile.id); diff --git a/lib/backend/modules/chats.dart b/lib/backend/modules/chats.dart index 13f3c01..d071013 100644 --- a/lib/backend/modules/chats.dart +++ b/lib/backend/modules/chats.dart @@ -372,6 +372,8 @@ class ChatsModule { final _messageEventsController = StreamController.broadcast(); Stream get messageEvents => _messageEventsController.stream; + int? _paginatedAccountId; + void emitMessageSent(int chatId, String tempId, CachedMessage message) { _messageEventsController.add(MessageSentEvent(chatId, tempId, message)); } @@ -1136,42 +1138,100 @@ class ChatsModule { ? data['presence'] as Map : {}; PresenceFetch.primeAll(presenceMap); - final cachedAt = DateTime.now().millisecondsSinceEpoch; - final existingRows = await AppDatabase.loadChats(accountId); - final existing = { - for (final row in existingRows) - row['id'] as int: CachedChat.fromDbRow(row), - }; - - final rows = >[]; - for (final c in chats.whereType()) { - final map = c.cast(); - final parsed = parseChatRow( - map, - accountId, - currentUserId, - contactsMap, - chatsConfig, - presenceMap, - existing, - cachedAt, - ); - if (parsed == null) continue; - final row = parsed.toDbRow(); - row['in_list'] = map['status'] == 'HIDDEN' ? 2 : 1; - rows.add(row); - } - - if (rows.isNotEmpty) { - await AppDatabase.saveChats(rows); - _bump(); - } + await _persistChatMaps( + chats, + accountId, + currentUserId, + contactsMap: contactsMap, + chatsConfig: chatsConfig, + presenceMap: presenceMap, + ); } catch (e) { logger.e("Ошибка при синке: $e"); } } + Future _persistChatMaps( + List chats, + int accountId, + int currentUserId, { + Map> contactsMap = const {}, + Map chatsConfig = const {}, + Map presenceMap = const {}, + }) async { + final cachedAt = DateTime.now().millisecondsSinceEpoch; + final existingRows = await AppDatabase.loadChats( + accountId, + includeHidden: true, + ); + final existing = { + for (final row in existingRows) + row['id'] as int: CachedChat.fromDbRow(row), + }; + + final rows = >[]; + for (final c in chats.whereType()) { + final map = c.cast(); + final parsed = parseChatRow( + map, + accountId, + currentUserId, + contactsMap, + chatsConfig, + presenceMap, + existing, + cachedAt, + ); + if (parsed == null) continue; + final row = parsed.toDbRow(); + row['in_list'] = map['status'] == 'HIDDEN' ? 2 : 1; + rows.add(row); + } + + if (rows.isNotEmpty) { + await AppDatabase.saveChats(rows); + _bump(); + } + return rows.length; + } + + Future paginateChats( + Api api, + int accountId, + int currentUserId, + Map loginData, + ) async { + if (_paginatedAccountId == accountId) return; + _paginatedAccountId = accountId; + try { + var marker = loginData['chatMarker']; + if (marker is! int || marker <= 0) return; + + const count = 50; + var page = 0; + while (page < 200) { + page++; + final resp = await api.sendRequestMap(Opcode.chatsList, { + 'marker': marker, + 'count': count, + }); + if (resp == null) break; + final chats = resp['chats']; + if (chats is! List || chats.isEmpty) break; + + await _persistChatMaps(chats, accountId, currentUserId); + + final next = resp['marker']; + if (next is! int || next == marker || chats.length < count) break; + marker = next; + } + } catch (e) { + _paginatedAccountId = null; + logger.w('Пагинация чатов: $e'); + } + } + Future> getChats( int accountId, { bool includeHidden = false,