feat(chats): полная загрузка списка чатов через пагинацию (opcode 53)

This commit is contained in:
klockky
2026-07-09 20:29:05 +03:00
parent cc5eb6299e
commit 94ca2016ba
2 changed files with 91 additions and 30 deletions
+1
View File
@@ -586,6 +586,7 @@ class AccountModule {
await _saveSyncState(data, serverTime, profile.id); await _saveSyncState(data, serverTime, profile.id);
await ContactsModule.syncFromLoginPayload(data, profile.id); await ContactsModule.syncFromLoginPayload(data, profile.id);
await chats.syncFromLoginPayload(data, profile.id, profile.id); await chats.syncFromLoginPayload(data, profile.id, profile.id);
unawaited(chats.paginateChats(_api, profile.id, profile.id, data));
try { try {
await ContactsModule.syncFromServer(_api, profile.id); await ContactsModule.syncFromServer(_api, profile.id);
+90 -30
View File
@@ -372,6 +372,8 @@ class ChatsModule {
final _messageEventsController = StreamController<MessageEvent>.broadcast(); final _messageEventsController = StreamController<MessageEvent>.broadcast();
Stream<MessageEvent> get messageEvents => _messageEventsController.stream; Stream<MessageEvent> get messageEvents => _messageEventsController.stream;
int? _paginatedAccountId;
void emitMessageSent(int chatId, String tempId, CachedMessage message) { void emitMessageSent(int chatId, String tempId, CachedMessage message) {
_messageEventsController.add(MessageSentEvent(chatId, tempId, message)); _messageEventsController.add(MessageSentEvent(chatId, tempId, message));
} }
@@ -1136,42 +1138,100 @@ class ChatsModule {
? data['presence'] as Map ? data['presence'] as Map
: {}; : {};
PresenceFetch.primeAll(presenceMap); PresenceFetch.primeAll(presenceMap);
final cachedAt = DateTime.now().millisecondsSinceEpoch;
final existingRows = await AppDatabase.loadChats(accountId); await _persistChatMaps(
final existing = { chats,
for (final row in existingRows) accountId,
row['id'] as int: CachedChat.fromDbRow(row), currentUserId,
}; contactsMap: contactsMap,
chatsConfig: chatsConfig,
final rows = <Map<String, dynamic>>[]; presenceMap: presenceMap,
for (final c in chats.whereType<Map>()) { );
final map = c.cast<dynamic, dynamic>();
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();
}
} catch (e) { } catch (e) {
logger.e("Ошибка при синке: $e"); logger.e("Ошибка при синке: $e");
} }
} }
Future<int> _persistChatMaps(
List<dynamic> chats,
int accountId,
int currentUserId, {
Map<int, Map<dynamic, dynamic>> contactsMap = const {},
Map<dynamic, dynamic> chatsConfig = const {},
Map<dynamic, dynamic> 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 = <Map<String, dynamic>>[];
for (final c in chats.whereType<Map>()) {
final map = c.cast<dynamic, dynamic>();
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<void> paginateChats(
Api api,
int accountId,
int currentUserId,
Map<dynamic, dynamic> 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<List<CachedChat>> getChats( Future<List<CachedChat>> getChats(
int accountId, { int accountId, {
bool includeHidden = false, bool includeHidden = false,