Files

282 lines
7.4 KiB
Dart
Raw Permalink Normal View History

enum MessageType {
text,
file,
image,
system;
static MessageType fromString(String? value) {
switch (value?.toUpperCase()) {
case 'FILE':
return MessageType.file;
case 'IMAGE':
return MessageType.image;
case 'SYSTEM':
return MessageType.system;
default:
return MessageType.text;
}
}
String toApiString() => name.toUpperCase();
}
enum MessageStatus {
sent,
delivered,
read;
static MessageStatus fromString(String? value) {
switch (value?.toUpperCase()) {
case 'DELIVERED':
return MessageStatus.delivered;
case 'READ':
return MessageStatus.read;
default:
return MessageStatus.sent;
}
}
}
class OtherParty {
final String id;
final String? userId;
final String name;
final String? avatar;
final String? headline;
final bool isOnline;
final String? lastSeenAt;
const OtherParty({
required this.id,
this.userId,
required this.name,
this.avatar,
this.headline,
this.isOnline = false,
this.lastSeenAt,
});
factory OtherParty.fromJson(Map<String, dynamic> json) {
return OtherParty(
id: json['id'] as String,
userId: json['userId'] as String?,
name: json['name'] as String? ?? '',
avatar: json['avatar'] as String?,
headline: json['headline'] as String?,
isOnline: json['isOnline'] as bool? ?? false,
lastSeenAt: json['lastSeenAt'] as String?,
);
}
}
class Conversation {
final String id;
final String userId;
final String agentProfileId;
final String? lastMessageAt;
final String? lastMessageText;
final int userUnreadCount;
final int agentUnreadCount;
final int unreadCount;
final String createdAt;
final String updatedAt;
final OtherParty otherParty;
final List<ChatMessage>? messages;
const Conversation({
required this.id,
required this.userId,
required this.agentProfileId,
this.lastMessageAt,
this.lastMessageText,
this.userUnreadCount = 0,
this.agentUnreadCount = 0,
this.unreadCount = 0,
required this.createdAt,
required this.updatedAt,
required this.otherParty,
this.messages,
});
factory Conversation.fromJson(Map<String, dynamic> json) {
return Conversation(
id: json['id'] as String,
userId: json['userId'] as String,
agentProfileId: json['agentProfileId'] as String,
lastMessageAt: json['lastMessageAt'] as String?,
lastMessageText: json['lastMessageText'] as String?,
userUnreadCount: json['userUnreadCount'] as int? ?? 0,
agentUnreadCount: json['agentUnreadCount'] as int? ?? 0,
unreadCount: json['unreadCount'] as int? ?? 0,
createdAt: json['createdAt'] as String,
updatedAt: json['updatedAt'] as String,
otherParty:
OtherParty.fromJson(json['otherParty'] as Map<String, dynamic>),
messages: (json['messages'] as List<dynamic>?)
?.map((e) => ChatMessage.fromJson(e as Map<String, dynamic>))
.toList(),
);
}
Conversation copyWith({
int? unreadCount,
String? lastMessageAt,
String? lastMessageText,
OtherParty? otherParty,
List<ChatMessage>? messages,
}) {
return Conversation(
id: id,
userId: userId,
agentProfileId: agentProfileId,
lastMessageAt: lastMessageAt ?? this.lastMessageAt,
lastMessageText: lastMessageText ?? this.lastMessageText,
userUnreadCount: userUnreadCount,
agentUnreadCount: agentUnreadCount,
unreadCount: unreadCount ?? this.unreadCount,
createdAt: createdAt,
updatedAt: updatedAt,
otherParty: otherParty ?? this.otherParty,
messages: messages ?? this.messages,
);
}
}
class SenderProfile {
final String? firstName;
final String? lastName;
final String? avatar;
const SenderProfile({this.firstName, this.lastName, this.avatar});
factory SenderProfile.fromJson(Map<String, dynamic> json) {
return SenderProfile(
firstName: json['firstName'] as String?,
lastName: json['lastName'] as String?,
avatar: json['avatar'] as String?,
);
}
}
class MessageSender {
final String id;
final String role;
final SenderProfile? userProfile;
final SenderProfile? agentProfile;
const MessageSender({
required this.id,
required this.role,
this.userProfile,
this.agentProfile,
});
String get displayName {
final profile = userProfile ?? agentProfile;
if (profile == null) return 'Unknown';
return '${profile.firstName ?? ''} ${profile.lastName ?? ''}'.trim();
}
String? get avatar => userProfile?.avatar ?? agentProfile?.avatar;
factory MessageSender.fromJson(Map<String, dynamic> json) {
return MessageSender(
id: json['id'] as String,
role: json['role'] as String? ?? '',
userProfile: json['userProfile'] != null
? SenderProfile.fromJson(
json['userProfile'] as Map<String, dynamic>)
: null,
agentProfile: json['agentProfile'] != null
? SenderProfile.fromJson(
json['agentProfile'] as Map<String, dynamic>)
: null,
);
}
}
class ChatMessage {
final String id;
final String conversationId;
final String senderId;
final String content;
final MessageType messageType;
final String? fileUrl;
final String? fileName;
final int? fileSize;
final String? mimeType;
final MessageStatus status;
final String? deliveredAt;
final String? readAt;
final String createdAt;
final String updatedAt;
final MessageSender sender;
const ChatMessage({
required this.id,
required this.conversationId,
required this.senderId,
required this.content,
this.messageType = MessageType.text,
this.fileUrl,
this.fileName,
this.fileSize,
this.mimeType,
this.status = MessageStatus.sent,
this.deliveredAt,
this.readAt,
required this.createdAt,
required this.updatedAt,
required this.sender,
});
bool isMine(String currentUserId) => senderId == currentUserId;
factory ChatMessage.fromJson(Map<String, dynamic> json) {
return ChatMessage(
id: json['id'] as String,
conversationId: json['conversationId'] as String,
senderId: json['senderId'] as String,
content: json['content'] as String? ?? '',
messageType: MessageType.fromString(json['messageType'] as String?),
fileUrl: json['fileUrl'] as String?,
fileName: json['fileName'] as String?,
fileSize: json['fileSize'] as int?,
mimeType: json['mimeType'] as String?,
status: MessageStatus.fromString(json['status'] as String?),
deliveredAt: json['deliveredAt'] as String?,
readAt: json['readAt'] as String?,
createdAt: json['createdAt'] as String,
updatedAt: json['updatedAt'] as String,
sender: json['sender'] != null
? MessageSender.fromJson(json['sender'] as Map<String, dynamic>)
: MessageSender(id: json['senderId'] as String, role: ''),
);
}
}
class PaginationInfo {
final int page;
final int limit;
final int total;
final int pages;
const PaginationInfo({
required this.page,
required this.limit,
required this.total,
required this.pages,
});
bool get hasMore => page < pages;
factory PaginationInfo.fromJson(Map<String, dynamic> json) {
return PaginationInfo(
page: json['page'] as int? ?? 1,
limit: json['limit'] as int? ?? 50,
total: json['total'] as int? ?? 0,
pages: json['pages'] as int? ?? 1,
);
}
}