небольшие изменения
This commit is contained in:
+21
-22
@@ -1,5 +1,7 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import '../core/utils/parse.dart';
|
||||
|
||||
enum AttachmentType {
|
||||
photo,
|
||||
video,
|
||||
@@ -13,6 +15,8 @@ enum AttachmentType {
|
||||
share,
|
||||
call,
|
||||
inlineKeyboard,
|
||||
forward,
|
||||
unknown,
|
||||
}
|
||||
|
||||
String? decodeAttachPreview(dynamic raw) {
|
||||
@@ -128,7 +132,6 @@ class VideoAttachment extends MessageAttachment {
|
||||
final int? duration;
|
||||
final int? size;
|
||||
|
||||
/// 0 — обычное видео, 1 — видеосообщение-кружок.
|
||||
final int? videoType;
|
||||
|
||||
bool get isNote => videoType == 1;
|
||||
@@ -307,7 +310,8 @@ class StickerAttachment extends MessageAttachment {
|
||||
previewData: decodeAttachPreview(map['previewData']),
|
||||
baseUrl: (map['url'] ?? map['baseUrl'])?.toString(),
|
||||
stickerId: map['stickerId']?.toString(),
|
||||
stickerPackId: map['setId']?.toString() ?? map['stickerPackId']?.toString(),
|
||||
stickerPackId:
|
||||
map['setId']?.toString() ?? map['stickerPackId']?.toString(),
|
||||
lottieUrl: map['lottieUrl']?.toString(),
|
||||
width: map['width'] as int?,
|
||||
height: map['height'] as int?,
|
||||
@@ -358,7 +362,9 @@ class ContactAttachment extends MessageAttachment {
|
||||
lastName: map['lastName']?.toString(),
|
||||
phoneNumber: map['phoneNumber']?.toString(),
|
||||
photoUrl: map['photoUrl']?.toString(),
|
||||
contactId: map['contactId'] is int ? map['contactId'] as int : int.tryParse(map['contactId']?.toString() ?? ''),
|
||||
contactId: map['contactId'] is int
|
||||
? map['contactId'] as int
|
||||
: int.tryParse(map['contactId']?.toString() ?? ''),
|
||||
name: map['name']?.toString(),
|
||||
);
|
||||
}
|
||||
@@ -448,8 +454,10 @@ class ControlAttachment extends MessageAttachment {
|
||||
baseUrl: map['baseUrl']?.toString(),
|
||||
event: map['event']?.toString(),
|
||||
title: title,
|
||||
userIds: (map['userIds'] as List?)?.map((e) => e is int ? e : int.tryParse(e?.toString() ?? '') ?? 0).toList(),
|
||||
userId: map['userId'] is int ? map['userId'] as int : int.tryParse(map['userId']?.toString() ?? ''),
|
||||
userIds: map['userIds'] is List ? parseIntList(map['userIds']) : null,
|
||||
userId: map['userId'] is int
|
||||
? map['userId'] as int
|
||||
: int.tryParse(map['userId']?.toString() ?? ''),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -469,10 +477,8 @@ class PollAttachment extends MessageAttachment {
|
||||
final int pollId;
|
||||
final String? title;
|
||||
|
||||
const PollAttachment({
|
||||
required this.pollId,
|
||||
this.title,
|
||||
}) : super(type: AttachmentType.poll);
|
||||
const PollAttachment({required this.pollId, this.title})
|
||||
: super(type: AttachmentType.poll);
|
||||
|
||||
factory PollAttachment.fromMap(Map<String, dynamic> map) {
|
||||
final id = map['pollId'] ?? map['id'];
|
||||
@@ -522,10 +528,7 @@ class CallAttachment extends MessageAttachment {
|
||||
hangupType: map['hangupType']?.toString(),
|
||||
conversationId: map['conversationId']?.toString(),
|
||||
joinLink: map['joinLink']?.toString(),
|
||||
contactIds: (map['contactIds'] as List?)
|
||||
?.map((e) => e is int ? e : int.tryParse(e?.toString() ?? '') ?? 0)
|
||||
.toList() ??
|
||||
const [],
|
||||
contactIds: parseIntList(map['contactIds']),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -631,10 +634,8 @@ class InlineKeyboardAttachment extends MessageAttachment {
|
||||
final String? callbackId;
|
||||
final List<List<InlineKeyboardButton>> rows;
|
||||
|
||||
const InlineKeyboardAttachment({
|
||||
this.callbackId,
|
||||
required this.rows,
|
||||
}) : super(type: AttachmentType.inlineKeyboard);
|
||||
const InlineKeyboardAttachment({this.callbackId, required this.rows})
|
||||
: super(type: AttachmentType.inlineKeyboard);
|
||||
|
||||
bool get isEmpty => rows.every((row) => row.isEmpty);
|
||||
|
||||
@@ -667,9 +668,7 @@ class InlineKeyboardAttachment extends MessageAttachment {
|
||||
'_type': 'INLINE_KEYBOARD',
|
||||
if (callbackId != null) 'callbackId': callbackId,
|
||||
'keyboard': {
|
||||
'buttons': rows
|
||||
.map((row) => row.map((b) => b.toMap()).toList())
|
||||
.toList(),
|
||||
'buttons': rows.map((row) => row.map((b) => b.toMap()).toList()).toList(),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -695,7 +694,7 @@ class ForwardedMessageAttachment extends MessageAttachment {
|
||||
this.originalChatId,
|
||||
this.originalAttachments,
|
||||
this.originalContact,
|
||||
}) : super(type: AttachmentType.photo);
|
||||
}) : super(type: AttachmentType.forward);
|
||||
|
||||
factory ForwardedMessageAttachment.fromMap(Map<String, dynamic> map) {
|
||||
final linkRaw = map['link'];
|
||||
@@ -764,7 +763,7 @@ class ForwardedMessageAttachment extends MessageAttachment {
|
||||
class UnknownAttachment extends MessageAttachment {
|
||||
final Map<String, dynamic> rawData;
|
||||
|
||||
const UnknownAttachment(this.rawData) : super(type: AttachmentType.photo);
|
||||
const UnknownAttachment(this.rawData) : super(type: AttachmentType.unknown);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toMap() => rawData;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
class ChatInfo {
|
||||
final Map<String, dynamic> raw;
|
||||
final List<int> participantIds;
|
||||
final Set<int> adminIds;
|
||||
final int? owner;
|
||||
|
||||
const ChatInfo({
|
||||
required this.raw,
|
||||
required this.participantIds,
|
||||
required this.adminIds,
|
||||
required this.owner,
|
||||
});
|
||||
|
||||
factory ChatInfo.fromMap(Map<String, dynamic> map) {
|
||||
return ChatInfo(
|
||||
raw: map,
|
||||
participantIds: _idKeys(map['participants']),
|
||||
adminIds: _idKeys(map['adminParticipants']).toSet(),
|
||||
owner: map['owner'] as int?,
|
||||
);
|
||||
}
|
||||
|
||||
bool isAdmin(int id) => adminIds.contains(id);
|
||||
bool isOwner(int id) => owner != null && id == owner;
|
||||
|
||||
int? get participantsCount => raw['participantsCount'] as int?;
|
||||
int? get blockedParticipantsCount => raw['blockedParticipantsCount'] as int?;
|
||||
String? get link => raw['link'] as String?;
|
||||
String? get description => raw['description'] as String?;
|
||||
|
||||
static List<int> _idKeys(Object? source) {
|
||||
if (source is! Map) return const [];
|
||||
final out = <int>[];
|
||||
for (final key in source.keys) {
|
||||
final id = key is int ? key : int.tryParse(key.toString());
|
||||
if (id != null) out.add(id);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
class ContactName {
|
||||
final String? type;
|
||||
final String? name;
|
||||
final String? firstName;
|
||||
final String? lastName;
|
||||
|
||||
const ContactName({this.type, this.name, this.firstName, this.lastName});
|
||||
|
||||
factory ContactName.fromMap(Map map) => ContactName(
|
||||
type: map['type']?.toString(),
|
||||
name: map['name']?.toString(),
|
||||
firstName: map['firstName']?.toString(),
|
||||
lastName: map['lastName']?.toString(),
|
||||
);
|
||||
|
||||
String? get label {
|
||||
final n = name;
|
||||
if (n != null && n.trim().isNotEmpty) return n.trim();
|
||||
final combined = [firstName, lastName]
|
||||
.where((s) => s != null && s.trim().isNotEmpty)
|
||||
.map((s) => s!.trim())
|
||||
.join(' ');
|
||||
return combined.isEmpty ? null : combined;
|
||||
}
|
||||
}
|
||||
|
||||
class ContactInfo {
|
||||
final Map<String, dynamic> raw;
|
||||
final List<ContactName> names;
|
||||
|
||||
const ContactInfo({required this.raw, required this.names});
|
||||
|
||||
factory ContactInfo.fromMap(Map<String, dynamic> map) {
|
||||
final rawNames = map['names'];
|
||||
final names = <ContactName>[];
|
||||
if (rawNames is List) {
|
||||
for (final n in rawNames) {
|
||||
if (n is Map) names.add(ContactName.fromMap(n));
|
||||
}
|
||||
}
|
||||
return ContactInfo(raw: map, names: names);
|
||||
}
|
||||
|
||||
String? get displayName {
|
||||
String? firstLabel;
|
||||
for (final n in names) {
|
||||
final label = n.label;
|
||||
if (label == null) continue;
|
||||
firstLabel ??= label;
|
||||
if (n.type == 'ONEME') return label;
|
||||
}
|
||||
return firstLabel;
|
||||
}
|
||||
|
||||
String? get firstName {
|
||||
for (final n in names) {
|
||||
final f = n.firstName;
|
||||
if (f != null && f.trim().isNotEmpty) return f.trim();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String? get avatarUrl => raw['baseUrl'] as String?;
|
||||
|
||||
List<String> get options {
|
||||
final o = raw['options'];
|
||||
return o is List ? o.whereType<String>().toList() : const [];
|
||||
}
|
||||
|
||||
int? get id => raw['id'] as int?;
|
||||
}
|
||||
+50
-25
@@ -56,22 +56,50 @@ class Poll {
|
||||
}
|
||||
|
||||
Poll withStateMap(Map<dynamic, dynamic> stateMap) {
|
||||
return Poll.fromServerMap({
|
||||
'pollId': pollId,
|
||||
'title': title,
|
||||
'settings': settings,
|
||||
'version': version,
|
||||
'answers': [
|
||||
for (final a in answers) {'answerId': a.answerId, 'text': a.text},
|
||||
],
|
||||
'state': stateMap,
|
||||
});
|
||||
return _buildFromState(
|
||||
pollId: pollId,
|
||||
title: title,
|
||||
settings: settings,
|
||||
version: version,
|
||||
answerIdsAndTexts: [for (final a in answers) (a.answerId, a.text)],
|
||||
stateMap: stateMap,
|
||||
);
|
||||
}
|
||||
|
||||
factory Poll.fromServerMap(Map<dynamic, dynamic> map) {
|
||||
final state = map['state'];
|
||||
final stateMap = state is Map ? state : const {};
|
||||
|
||||
final answerIdsAndTexts = <(int, String)>[];
|
||||
final rawAnswers = map['answers'];
|
||||
if (rawAnswers is List) {
|
||||
for (final a in rawAnswers) {
|
||||
if (a is! Map) continue;
|
||||
answerIdsAndTexts.add((
|
||||
a['answerId'] as int? ?? 0,
|
||||
a['text']?.toString() ?? '',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return _buildFromState(
|
||||
pollId: map['pollId'] as int? ?? 0,
|
||||
title: map['title']?.toString() ?? '',
|
||||
settings: map['settings'] as int? ?? 0,
|
||||
version: map['version'] as int? ?? 0,
|
||||
answerIdsAndTexts: answerIdsAndTexts,
|
||||
stateMap: stateMap,
|
||||
);
|
||||
}
|
||||
|
||||
static Poll _buildFromState({
|
||||
required int pollId,
|
||||
required String title,
|
||||
required int settings,
|
||||
required int version,
|
||||
required List<(int, String)> answerIdsAndTexts,
|
||||
required Map<dynamic, dynamic> stateMap,
|
||||
}) {
|
||||
final resultsById = <int, Map>{};
|
||||
final result = stateMap['result'];
|
||||
if (result is List) {
|
||||
@@ -83,33 +111,30 @@ class Poll {
|
||||
}
|
||||
|
||||
final answers = <PollAnswer>[];
|
||||
final rawAnswers = map['answers'];
|
||||
if (rawAnswers is List) {
|
||||
for (final a in rawAnswers) {
|
||||
if (a is! Map) continue;
|
||||
final id = a['answerId'] as int? ?? 0;
|
||||
final res = resultsById[id];
|
||||
answers.add(PollAnswer(
|
||||
for (final (id, text) in answerIdsAndTexts) {
|
||||
final res = resultsById[id];
|
||||
answers.add(
|
||||
PollAnswer(
|
||||
answerId: id,
|
||||
text: a['text']?.toString() ?? '',
|
||||
text: text,
|
||||
voteCount: (res?['voteCount'] as num?)?.toInt() ?? 0,
|
||||
rate: (res?['rate'] as num?)?.toDouble() ?? 0,
|
||||
votes: _parseVoterIds(res?['votes']),
|
||||
mine: ((res?['options'] as num?)?.toInt() ?? 0) & 0x1 != 0,
|
||||
));
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Poll(
|
||||
pollId: map['pollId'] as int? ?? 0,
|
||||
title: map['title']?.toString() ?? '',
|
||||
settings: map['settings'] as int? ?? 0,
|
||||
version: map['version'] as int? ?? 0,
|
||||
pollId: pollId,
|
||||
title: title,
|
||||
settings: settings,
|
||||
version: version,
|
||||
total: (stateMap['total'] as num?)?.toInt() ?? 0,
|
||||
answers: answers,
|
||||
voterPreviewIds:
|
||||
(stateMap['voterPreviewIds'] as List?)?.whereType<int>().toList() ??
|
||||
const [],
|
||||
const [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
class ReactionCounter {
|
||||
final String reaction;
|
||||
final int count;
|
||||
const ReactionCounter({required this.reaction, required this.count});
|
||||
}
|
||||
|
||||
class ReactionInfo {
|
||||
final List<ReactionCounter> counters;
|
||||
final String? yourReaction;
|
||||
final int totalCount;
|
||||
|
||||
const ReactionInfo({
|
||||
this.counters = const [],
|
||||
this.yourReaction,
|
||||
this.totalCount = 0,
|
||||
});
|
||||
|
||||
static ReactionInfo? fromMap(Map? map) {
|
||||
if (map == null) return null;
|
||||
final rawCounters = map['counters'];
|
||||
if (rawCounters is! List || rawCounters.isEmpty) return null;
|
||||
final counters = <ReactionCounter>[];
|
||||
for (final c in rawCounters) {
|
||||
if (c is! Map) continue;
|
||||
final reaction = c['reaction']?.toString();
|
||||
if (reaction == null || reaction.isEmpty) continue;
|
||||
final rawCount = c['count'];
|
||||
counters.add(
|
||||
ReactionCounter(
|
||||
reaction: reaction,
|
||||
count: rawCount is int ? rawCount : 0,
|
||||
),
|
||||
);
|
||||
}
|
||||
if (counters.isEmpty) return null;
|
||||
final total = map['totalCount'];
|
||||
return ReactionInfo(
|
||||
counters: counters,
|
||||
yourReaction: map['yourReaction']?.toString(),
|
||||
totalCount: total is int ? total : 0,
|
||||
);
|
||||
}
|
||||
|
||||
bool get isEmpty => counters.isEmpty;
|
||||
}
|
||||
Reference in New Issue
Block a user