feat: нормальная работа с группами

This commit is contained in:
Jganenokk
2026-07-25 15:30:07 +07:00
parent 8e55675c5e
commit 20503c9b1a
12 changed files with 1157 additions and 88 deletions
+141
View File
@@ -13,6 +13,7 @@ import '../../core/storage/app_database.dart';
import '../../core/storage/token_storage.dart';
import '../../core/utils/logger.dart';
import '../../core/utils/text_format.dart';
import '../../models/contact_info.dart';
import '../api.dart';
import 'chat_parsing.dart';
import 'chat_preview.dart';
@@ -303,6 +304,33 @@ class ChatSearchHit {
});
}
class ChatMemberEntry {
final int id;
final String? name;
final String? avatarUrl;
final int? seenTime;
final int presenceStatus;
final bool blocked;
const ChatMemberEntry({
required this.id,
this.name,
this.avatarUrl,
this.seenTime,
required this.presenceStatus,
this.blocked = false,
});
bool get isOnline => presenceStatus == 1;
}
class ChatMembersPage {
final List<ChatMemberEntry> members;
final int marker;
const ChatMembersPage({required this.members, required this.marker});
}
class MessageSearchHit {
final int chatId;
final String? messageId;
@@ -1686,6 +1714,119 @@ class ChatsModule {
}
}
Future<bool> addMembers(
Api api, {
required int chatId,
required List<int> userIds,
bool showHistory = true,
}) async {
if (userIds.isEmpty) return false;
try {
final packet = await api.sendRequest(Opcode.chatMembersUpdate, {
'chatId': chatId,
'userIds': userIds,
'showHistory': showHistory,
'operation': 'add',
});
if (!packet.isOk) {
logger.w('addMembers $chatId: ${messageFromErrorPayload(packet.payload)}');
return false;
}
final data = packet.payload;
final chat = data is Map ? data['chat'] : null;
if (chat is Map) {
final accountId = await TokenStorage.getActiveAccountId();
if (accountId != null) {
await cacheServerChat(chat.cast<dynamic, dynamic>(), accountId);
}
}
return true;
} on PacketError catch (e) {
logger.w('addMembers $chatId: ${e.message}');
return false;
} catch (e) {
logger.w('addMembers $chatId: $e');
return false;
}
}
Future<ChatMembersPage?> getChatMembers(
Api api,
int chatId, {
int marker = 0,
int count = 50,
}) async {
try {
final packet = await api.sendRequest(Opcode.chatMembers, {
'type': 'MEMBER',
'marker': marker,
'chatId': chatId,
'count': count,
});
if (!packet.isOk) return null;
final payload = packet.payload;
if (payload is! Map) return null;
final entries = <ChatMemberEntry>[];
final presenceById = <int, Map<String, dynamic>>{};
final rawMembers = payload['members'];
if (rawMembers is List) {
for (final m in rawMembers.whereType<Map>()) {
final contact = m['contact'];
if (contact is! Map) continue;
final id = contact['id'];
if (id is! int) continue;
final info = ContactInfo.fromMap(Map<String, dynamic>.from(contact));
final name = info.displayName;
if (name != null && name.isNotEmpty) ContactCache.put(id, name);
final avatar = info.avatarUrl;
if (avatar != null && avatar.isNotEmpty) {
ContactCache.putAvatar(id, avatar);
}
final phone = contact['phone'];
if (phone is int && phone > 0) ContactCache.putPhone(id, phone);
ContactInfoFetch.putContact(id, contact.cast<dynamic, dynamic>());
final presence = m['presence'];
var status = 0;
int? seen;
if (presence is Map) {
final p = Map<String, dynamic>.from(presence);
presenceById[id] = p;
status = (p['status'] as int?) ?? 0;
final s = p['seen'];
seen = s is int ? s : null;
}
entries.add(
ChatMemberEntry(
id: id,
name: name,
avatarUrl: avatar,
seenTime: seen,
presenceStatus: status,
blocked: info.isDeleted,
),
);
}
}
if (presenceById.isNotEmpty) PresenceFetch.primeAll(presenceById);
final next = payload['marker'];
return ChatMembersPage(
members: entries,
marker: next is int ? next : marker,
);
} on PacketError catch (e) {
logger.w('getChatMembers $chatId: ${e.message}');
return null;
} catch (e) {
logger.w('getChatMembers $chatId: $e');
return null;
}
}
Future<List<CachedChat>> refreshChats(Api api, List<int> chatIds) async {
if (chatIds.isEmpty) return const [];
try {