diff --git a/client-mobile/l10n/app_en.arb b/client-mobile/l10n/app_en.arb index c467e9a..ca71290 100644 --- a/client-mobile/l10n/app_en.arb +++ b/client-mobile/l10n/app_en.arb @@ -83,6 +83,11 @@ "registrationFailed": "Registration failed", "online": "online", "lastSeen": "last seen {date} at {time}", + "lastSeenRelative": "last seen {hours}h {minutes}m ago", + "lastSeenRelativeMinutes": "last seen {minutes}m ago", + "lastSeenJustNow": "last seen just now", + "lastSeenYesterday": "last seen yesterday at {time}", + "lastSeenDayBeforeYesterday": "last seen day before yesterday at {time}", "noMessages": "No messages yet", "messageHint": "Message" } diff --git a/client-mobile/l10n/app_ru.arb b/client-mobile/l10n/app_ru.arb index 546682e..65112f9 100644 --- a/client-mobile/l10n/app_ru.arb +++ b/client-mobile/l10n/app_ru.arb @@ -83,6 +83,11 @@ "registrationFailed": "Ошибка регистрации", "online": "в сети", "lastSeen": "был(а) в сети {date} в {time}", + "lastSeenRelative": "был(а) {hours} ч. {minutes} мин. назад", + "lastSeenRelativeMinutes": "был(а) {minutes} мин. назад", + "lastSeenJustNow": "был(а) только что", + "lastSeenYesterday": "был(а) вчера в {time}", + "lastSeenDayBeforeYesterday": "был(а) позавчера в {time}", "noMessages": "Сообщений пока нет", "messageHint": "Сообщение" } diff --git a/client-mobile/lib/core/network/signalr_service.dart b/client-mobile/lib/core/network/signalr_service.dart index 4f788ad..6c102f9 100644 --- a/client-mobile/lib/core/network/signalr_service.dart +++ b/client-mobile/lib/core/network/signalr_service.dart @@ -7,8 +7,14 @@ class SignalRService { final SharedPreferences prefs; HubConnection? _hubConnection; final _messageController = StreamController.broadcast(); + final _typingController = StreamController>.broadcast(); + final _statusController = StreamController>.broadcast(); + final _readReceiptController = StreamController>.broadcast(); Stream get messages => _messageController.stream; + Stream> get typingUpdates => _typingController.stream; + Stream> get statusUpdates => _statusController.stream; + Stream> get readReceipts => _readReceiptController.stream; SignalRService(this.prefs); @@ -54,13 +60,46 @@ class SignalRService { print('[SignalR] Reconnected! ID: $connectionId'); }); - // Handle multiple possible event names to be safe - _hubConnection?.on('ReceiveMessage', _handleReceiveMessage); - _hubConnection?.on('receiveMessage', _handleReceiveMessage); - _hubConnection?.on('UserTyping', _handleUserTyping); + // Event names verified from backend source code (MessageNotifier.cs) + _hubConnection?.on('new_message', _handleReceiveMessage); + _hubConnection?.on('new_message_received', _handleReceiveMessage); // Optional fallback + _hubConnection?.on('user_typing', _handleUserTyping); - _hubConnection?.on('UserStoppedTyping', _handleUserStoppedTyping); _hubConnection?.on('user_stopped_typing', _handleUserStoppedTyping); + _hubConnection?.on('user_online', (args) { + // ignore: avoid_print + print('[SignalR] user_online: $args'); + if (args != null && args.isNotEmpty) { + final data = args[0] as Map; + _statusController.add({'userId': data['userId'] ?? data['UserId'], 'isOnline': true}); + } + }); + _hubConnection?.on('user_offline', (args) { + // ignore: avoid_print + print('[SignalR] user_offline: $args'); + if (args != null && args.isNotEmpty) { + final data = args[0] as Map; + _statusController.add({ + 'userId': data['userId'] ?? data['UserId'], + 'isOnline': false, + 'lastSeen': data['lastSeen'] ?? data['LastSeen'] + }); + } + }); + + _hubConnection?.on('messages_read', (args) { + // ignore: avoid_print + print('[SignalR] messages_read: $args'); + if (args != null && args.isNotEmpty) { + final data = args[0] as Map; + _readReceiptController.add({ + 'chatId': data['chatId'] ?? data['ChatId'], + 'userId': data['userId'] ?? data['UserId'], + 'lastReadMessageId': data['lastReadMessageId'] ?? data['LastReadMessageId'], + 'lastReadSequenceId': data['lastReadSequenceId'] ?? data['LastReadSequenceId'], + }); + } + }); try { // ignore: avoid_print @@ -74,8 +113,17 @@ class SignalRService { } } - final _typingController = StreamController>.broadcast(); - Stream> get typingUpdates => _typingController.stream; + Future markMessagesAsRead(String chatId, String lastReadMessageId, int lastReadSequenceId) async { + // ignore: avoid_print + print('[SignalR] markMessagesAsRead: chatId=$chatId, msgId=$lastReadMessageId, seqId=$lastReadSequenceId'); + await _hubConnection?.invoke('read_messages', args: [ + { + 'ChatId': chatId, + 'LastReadMessageId': lastReadMessageId, + 'LastReadSequenceId': lastReadSequenceId, + } + ]); + } void _handleUserTyping(List? arguments) { // ignore: avoid_print @@ -109,15 +157,18 @@ class SignalRService { if (arguments != null && arguments.isNotEmpty) { final data = arguments[0] as Map; final message = Message( - id: data['id'] ?? '', - chatId: data['chatId'] ?? '', - senderId: data['userId'] ?? (data['senderId'] ?? ''), - content: data['content'] ?? '', - messageType: data['type']?.toString().toLowerCase() ?? 'text', - createdAt: _parseDateTime(data['createdAt']), - updatedAt: _parseDateTime(data['updatedAt']), - isRead: data['isRead'] ?? false, - media: data['media'] is Map ? data['media'] as Map : null, + id: (data['id'] ?? data['Id'] ?? '').toString(), + chatId: (data['chatId'] ?? data['ChatId'] ?? '').toString(), + senderId: (data['senderId'] ?? data['SenderId'] ?? data['userId'] ?? data['UserId'] ?? '').toString(), + content: data['content'] ?? data['Content'] ?? '', + messageType: (data['type'] ?? data['Type'] ?? 'text').toString().toLowerCase(), + sequenceId: int.tryParse((data['sequenceId'] ?? data['SequenceId'] ?? '0').toString()) ?? 0, + createdAt: _parseDateTime(data['createdAt'] ?? data['CreatedAt']), + updatedAt: _parseDateTime(data['updatedAt'] ?? data['UpdatedAt']), + status: (data['isRead'] ?? data['IsRead'] ?? false) ? MessageStatus.read : MessageStatus.delivered, + media: (data['media'] ?? data['Media']) is Map + ? (data['media'] ?? data['Media']) as Map + : null, ); _messageController.add(message); } diff --git a/client-mobile/lib/features/chat/data/datasources/chat_remote_datasource_impl.dart b/client-mobile/lib/features/chat/data/datasources/chat_remote_datasource_impl.dart index 4b0e65f..8784f67 100644 --- a/client-mobile/lib/features/chat/data/datasources/chat_remote_datasource_impl.dart +++ b/client-mobile/lib/features/chat/data/datasources/chat_remote_datasource_impl.dart @@ -194,9 +194,10 @@ class ChatRemoteDataSourceImpl implements ChatRemoteDataSource { senderId: json['userId'] ?? (json['senderId'] ?? ''), content: json['content'] ?? '', messageType: json['type']?.toString().toLowerCase() ?? 'text', + sequenceId: int.tryParse(json['sequenceId']?.toString() ?? '0') ?? 0, createdAt: _parseDateTime(json['createdAt']), updatedAt: _parseDateTime(json['updatedAt']), - isRead: json['isRead'] ?? false, + status: (json['isRead'] ?? false) ? MessageStatus.read : MessageStatus.delivered, media: json['media'] is Map ? json['media'] as Map : null, ); } diff --git a/client-mobile/lib/features/chat/data/models/chat_model.dart b/client-mobile/lib/features/chat/data/models/chat_model.dart index 4bcac4d..a37a080 100644 --- a/client-mobile/lib/features/chat/data/models/chat_model.dart +++ b/client-mobile/lib/features/chat/data/models/chat_model.dart @@ -62,7 +62,11 @@ class LastMessageModel { late String id; late String content; late String messageType; + late int sequenceId; DateTime? createdAt; + + @Enumerated(EnumType.name) + MessageStatus status = MessageStatus.delivered; Message toEntity() { return Message( @@ -71,7 +75,9 @@ class LastMessageModel { senderId: '', content: content, messageType: messageType, + sequenceId: sequenceId, createdAt: createdAt, + status: status, ); } @@ -80,7 +86,9 @@ class LastMessageModel { ..id = message.id ..content = message.content ..messageType = message.messageType - ..createdAt = message.createdAt; + ..sequenceId = message.sequenceId + ..createdAt = message.createdAt + ..status = message.status; } } diff --git a/client-mobile/lib/features/chat/data/models/chat_model.g.dart b/client-mobile/lib/features/chat/data/models/chat_model.g.dart index 337093f..a5164bb 100644 --- a/client-mobile/lib/features/chat/data/models/chat_model.g.dart +++ b/client-mobile/lib/features/chat/data/models/chat_model.g.dart @@ -1663,6 +1663,17 @@ const LastMessageModelSchema = Schema( id: 3, name: r'messageType', type: IsarType.string, + ), + r'sequenceId': PropertySchema( + id: 4, + name: r'sequenceId', + type: IsarType.long, + ), + r'status': PropertySchema( + id: 5, + name: r'status', + type: IsarType.string, + enumMap: _LastMessageModelstatusEnumValueMap, ) }, estimateSize: _lastMessageModelEstimateSize, @@ -1680,6 +1691,7 @@ int _lastMessageModelEstimateSize( bytesCount += 3 + object.content.length * 3; bytesCount += 3 + object.id.length * 3; bytesCount += 3 + object.messageType.length * 3; + bytesCount += 3 + object.status.name.length * 3; return bytesCount; } @@ -1693,6 +1705,8 @@ void _lastMessageModelSerialize( writer.writeDateTime(offsets[1], object.createdAt); writer.writeString(offsets[2], object.id); writer.writeString(offsets[3], object.messageType); + writer.writeLong(offsets[4], object.sequenceId); + writer.writeString(offsets[5], object.status.name); } LastMessageModel _lastMessageModelDeserialize( @@ -1706,6 +1720,10 @@ LastMessageModel _lastMessageModelDeserialize( object.createdAt = reader.readDateTimeOrNull(offsets[1]); object.id = reader.readString(offsets[2]); object.messageType = reader.readString(offsets[3]); + object.sequenceId = reader.readLong(offsets[4]); + object.status = _LastMessageModelstatusValueEnumMap[ + reader.readStringOrNull(offsets[5])] ?? + MessageStatus.sending; return object; } @@ -1724,11 +1742,30 @@ P _lastMessageModelDeserializeProp

( return (reader.readString(offset)) as P; case 3: return (reader.readString(offset)) as P; + case 4: + return (reader.readLong(offset)) as P; + case 5: + return (_LastMessageModelstatusValueEnumMap[ + reader.readStringOrNull(offset)] ?? + MessageStatus.sending) as P; default: throw IsarError('Unknown property with id $propertyId'); } } +const _LastMessageModelstatusEnumValueMap = { + r'sending': r'sending', + r'delivered': r'delivered', + r'read': r'read', + r'error': r'error', +}; +const _LastMessageModelstatusValueEnumMap = { + r'sending': MessageStatus.sending, + r'delivered': MessageStatus.delivered, + r'read': MessageStatus.read, + r'error': MessageStatus.error, +}; + extension LastMessageModelQueryFilter on QueryBuilder { QueryBuilder @@ -2212,6 +2249,198 @@ extension LastMessageModelQueryFilter )); }); } + + QueryBuilder + sequenceIdEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'sequenceId', + value: value, + )); + }); + } + + QueryBuilder + sequenceIdGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'sequenceId', + value: value, + )); + }); + } + + QueryBuilder + sequenceIdLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'sequenceId', + value: value, + )); + }); + } + + QueryBuilder + sequenceIdBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'sequenceId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder + statusEqualTo( + MessageStatus value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusGreaterThan( + MessageStatus value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusLessThan( + MessageStatus value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusBetween( + MessageStatus lower, + MessageStatus upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'status', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusMatches(String pattern, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'status', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'status', + value: '', + )); + }); + } + + QueryBuilder + statusIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'status', + value: '', + )); + }); + } } extension LastMessageModelQueryObject diff --git a/client-mobile/lib/features/chat/data/models/message_model.dart b/client-mobile/lib/features/chat/data/models/message_model.dart index cb94e14..7b0181c 100644 --- a/client-mobile/lib/features/chat/data/models/message_model.dart +++ b/client-mobile/lib/features/chat/data/models/message_model.dart @@ -16,12 +16,15 @@ class MessageModel { late String senderId; late String content; late String messageType; + late int sequenceId; @Index() DateTime? createdAt; DateTime? updatedAt; - bool isRead = false; + + @Enumerated(EnumType.name) + MessageStatus status = MessageStatus.delivered; // For simplicity, store media as a JSON string or ignore for now String? mediaJson; @@ -33,9 +36,10 @@ class MessageModel { senderId: senderId, content: content, messageType: messageType, + sequenceId: sequenceId, createdAt: createdAt, updatedAt: updatedAt, - isRead: isRead, + status: status, ); } @@ -46,8 +50,9 @@ class MessageModel { ..senderId = message.senderId ..content = message.content ..messageType = message.messageType + ..sequenceId = message.sequenceId ..createdAt = message.createdAt ..updatedAt = message.updatedAt - ..isRead = message.isRead ?? false; + ..status = message.status; } } diff --git a/client-mobile/lib/features/chat/data/models/message_model.g.dart b/client-mobile/lib/features/chat/data/models/message_model.g.dart index 11738a9..495165b 100644 --- a/client-mobile/lib/features/chat/data/models/message_model.g.dart +++ b/client-mobile/lib/features/chat/data/models/message_model.g.dart @@ -37,28 +37,34 @@ const MessageModelSchema = CollectionSchema( name: r'id', type: IsarType.string, ), - r'isRead': PropertySchema( - id: 4, - name: r'isRead', - type: IsarType.bool, - ), r'mediaJson': PropertySchema( - id: 5, + id: 4, name: r'mediaJson', type: IsarType.string, ), r'messageType': PropertySchema( - id: 6, + id: 5, name: r'messageType', type: IsarType.string, ), r'senderId': PropertySchema( - id: 7, + id: 6, name: r'senderId', type: IsarType.string, ), - r'updatedAt': PropertySchema( + r'sequenceId': PropertySchema( + id: 7, + name: r'sequenceId', + type: IsarType.long, + ), + r'status': PropertySchema( id: 8, + name: r'status', + type: IsarType.string, + enumMap: _MessageModelstatusEnumValueMap, + ), + r'updatedAt': PropertySchema( + id: 9, name: r'updatedAt', type: IsarType.dateTime, ) @@ -134,6 +140,7 @@ int _messageModelEstimateSize( } bytesCount += 3 + object.messageType.length * 3; bytesCount += 3 + object.senderId.length * 3; + bytesCount += 3 + object.status.name.length * 3; return bytesCount; } @@ -147,11 +154,12 @@ void _messageModelSerialize( writer.writeString(offsets[1], object.content); writer.writeDateTime(offsets[2], object.createdAt); writer.writeString(offsets[3], object.id); - writer.writeBool(offsets[4], object.isRead); - writer.writeString(offsets[5], object.mediaJson); - writer.writeString(offsets[6], object.messageType); - writer.writeString(offsets[7], object.senderId); - writer.writeDateTime(offsets[8], object.updatedAt); + writer.writeString(offsets[4], object.mediaJson); + writer.writeString(offsets[5], object.messageType); + writer.writeString(offsets[6], object.senderId); + writer.writeLong(offsets[7], object.sequenceId); + writer.writeString(offsets[8], object.status.name); + writer.writeDateTime(offsets[9], object.updatedAt); } MessageModel _messageModelDeserialize( @@ -165,12 +173,15 @@ MessageModel _messageModelDeserialize( object.content = reader.readString(offsets[1]); object.createdAt = reader.readDateTimeOrNull(offsets[2]); object.id = reader.readString(offsets[3]); - object.isRead = reader.readBool(offsets[4]); object.isarId = id; - object.mediaJson = reader.readStringOrNull(offsets[5]); - object.messageType = reader.readString(offsets[6]); - object.senderId = reader.readString(offsets[7]); - object.updatedAt = reader.readDateTimeOrNull(offsets[8]); + object.mediaJson = reader.readStringOrNull(offsets[4]); + object.messageType = reader.readString(offsets[5]); + object.senderId = reader.readString(offsets[6]); + object.sequenceId = reader.readLong(offsets[7]); + object.status = + _MessageModelstatusValueEnumMap[reader.readStringOrNull(offsets[8])] ?? + MessageStatus.sending; + object.updatedAt = reader.readDateTimeOrNull(offsets[9]); return object; } @@ -190,20 +201,37 @@ P _messageModelDeserializeProp

( case 3: return (reader.readString(offset)) as P; case 4: - return (reader.readBool(offset)) as P; - case 5: return (reader.readStringOrNull(offset)) as P; + case 5: + return (reader.readString(offset)) as P; case 6: return (reader.readString(offset)) as P; case 7: - return (reader.readString(offset)) as P; + return (reader.readLong(offset)) as P; case 8: + return (_MessageModelstatusValueEnumMap[ + reader.readStringOrNull(offset)] ?? + MessageStatus.sending) as P; + case 9: return (reader.readDateTimeOrNull(offset)) as P; default: throw IsarError('Unknown property with id $propertyId'); } } +const _MessageModelstatusEnumValueMap = { + r'sending': r'sending', + r'delivered': r'delivered', + r'read': r'read', + r'error': r'error', +}; +const _MessageModelstatusValueEnumMap = { + r'sending': MessageStatus.sending, + r'delivered': MessageStatus.delivered, + r'read': MessageStatus.read, + r'error': MessageStatus.error, +}; + Id _messageModelGetId(MessageModel object) { return object.isarId; } @@ -1041,16 +1069,6 @@ extension MessageModelQueryFilter }); } - QueryBuilder isReadEqualTo( - bool value) { - return QueryBuilder.apply(this, (query) { - return query.addFilterCondition(FilterCondition.equalTo( - property: r'isRead', - value: value, - )); - }); - } - QueryBuilder isarIdEqualTo( Id value) { return QueryBuilder.apply(this, (query) { @@ -1532,6 +1550,197 @@ extension MessageModelQueryFilter }); } + QueryBuilder + sequenceIdEqualTo(int value) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'sequenceId', + value: value, + )); + }); + } + + QueryBuilder + sequenceIdGreaterThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'sequenceId', + value: value, + )); + }); + } + + QueryBuilder + sequenceIdLessThan( + int value, { + bool include = false, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'sequenceId', + value: value, + )); + }); + } + + QueryBuilder + sequenceIdBetween( + int lower, + int upper, { + bool includeLower = true, + bool includeUpper = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'sequenceId', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + )); + }); + } + + QueryBuilder statusEqualTo( + MessageStatus value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusGreaterThan( + MessageStatus value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + include: include, + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusLessThan( + MessageStatus value, { + bool include = false, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.lessThan( + include: include, + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder statusBetween( + MessageStatus lower, + MessageStatus upper, { + bool includeLower = true, + bool includeUpper = true, + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.between( + property: r'status', + lower: lower, + includeLower: includeLower, + upper: upper, + includeUpper: includeUpper, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusStartsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.startsWith( + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusEndsWith( + String value, { + bool caseSensitive = true, + }) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.endsWith( + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusContains(String value, {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.contains( + property: r'status', + value: value, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder statusMatches( + String pattern, + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.matches( + property: r'status', + wildcard: pattern, + caseSensitive: caseSensitive, + )); + }); + } + + QueryBuilder + statusIsEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.equalTo( + property: r'status', + value: '', + )); + }); + } + + QueryBuilder + statusIsNotEmpty() { + return QueryBuilder.apply(this, (query) { + return query.addFilterCondition(FilterCondition.greaterThan( + property: r'status', + value: '', + )); + }); + } + QueryBuilder updatedAtIsNull() { return QueryBuilder.apply(this, (query) { @@ -1663,18 +1872,6 @@ extension MessageModelQuerySortBy }); } - QueryBuilder sortByIsRead() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isRead', Sort.asc); - }); - } - - QueryBuilder sortByIsReadDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isRead', Sort.desc); - }); - } - QueryBuilder sortByMediaJson() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'mediaJson', Sort.asc); @@ -1712,6 +1909,31 @@ extension MessageModelQuerySortBy }); } + QueryBuilder sortBySequenceId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sequenceId', Sort.asc); + }); + } + + QueryBuilder + sortBySequenceIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sequenceId', Sort.desc); + }); + } + + QueryBuilder sortByStatus() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'status', Sort.asc); + }); + } + + QueryBuilder sortByStatusDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'status', Sort.desc); + }); + } + QueryBuilder sortByUpdatedAt() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'updatedAt', Sort.asc); @@ -1775,18 +1997,6 @@ extension MessageModelQuerySortThenBy }); } - QueryBuilder thenByIsRead() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isRead', Sort.asc); - }); - } - - QueryBuilder thenByIsReadDesc() { - return QueryBuilder.apply(this, (query) { - return query.addSortBy(r'isRead', Sort.desc); - }); - } - QueryBuilder thenByIsarId() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'isarId', Sort.asc); @@ -1836,6 +2046,31 @@ extension MessageModelQuerySortThenBy }); } + QueryBuilder thenBySequenceId() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sequenceId', Sort.asc); + }); + } + + QueryBuilder + thenBySequenceIdDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'sequenceId', Sort.desc); + }); + } + + QueryBuilder thenByStatus() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'status', Sort.asc); + }); + } + + QueryBuilder thenByStatusDesc() { + return QueryBuilder.apply(this, (query) { + return query.addSortBy(r'status', Sort.desc); + }); + } + QueryBuilder thenByUpdatedAt() { return QueryBuilder.apply(this, (query) { return query.addSortBy(r'updatedAt', Sort.asc); @@ -1878,12 +2113,6 @@ extension MessageModelQueryWhereDistinct }); } - QueryBuilder distinctByIsRead() { - return QueryBuilder.apply(this, (query) { - return query.addDistinctBy(r'isRead'); - }); - } - QueryBuilder distinctByMediaJson( {bool caseSensitive = true}) { return QueryBuilder.apply(this, (query) { @@ -1905,6 +2134,19 @@ extension MessageModelQueryWhereDistinct }); } + QueryBuilder distinctBySequenceId() { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'sequenceId'); + }); + } + + QueryBuilder distinctByStatus( + {bool caseSensitive = true}) { + return QueryBuilder.apply(this, (query) { + return query.addDistinctBy(r'status', caseSensitive: caseSensitive); + }); + } + QueryBuilder distinctByUpdatedAt() { return QueryBuilder.apply(this, (query) { return query.addDistinctBy(r'updatedAt'); @@ -1944,12 +2186,6 @@ extension MessageModelQueryProperty }); } - QueryBuilder isReadProperty() { - return QueryBuilder.apply(this, (query) { - return query.addPropertyName(r'isRead'); - }); - } - QueryBuilder mediaJsonProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'mediaJson'); @@ -1968,6 +2204,18 @@ extension MessageModelQueryProperty }); } + QueryBuilder sequenceIdProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'sequenceId'); + }); + } + + QueryBuilder statusProperty() { + return QueryBuilder.apply(this, (query) { + return query.addPropertyName(r'status'); + }); + } + QueryBuilder updatedAtProperty() { return QueryBuilder.apply(this, (query) { return query.addPropertyName(r'updatedAt'); diff --git a/client-mobile/lib/features/chat/data/repositories/chat_repository_impl.dart b/client-mobile/lib/features/chat/data/repositories/chat_repository_impl.dart index cd25abe..17b4439 100644 --- a/client-mobile/lib/features/chat/data/repositories/chat_repository_impl.dart +++ b/client-mobile/lib/features/chat/data/repositories/chat_repository_impl.dart @@ -24,9 +24,19 @@ class ChatRepositoryImpl implements ChatRepository { @override Stream> get typingStream => signalRService.typingUpdates; + @override + Stream> get statusStream => signalRService.statusUpdates; + + @override + Stream> get readReceiptStream => signalRService.readReceipts; + @override Future sendTypingStatus(String chatId, bool isTyping) => signalRService.sendTypingStatus(chatId, isTyping); + @override + Future markAsRead(String chatId, String lastReadMessageId, int lastReadSequenceId) => + signalRService.markMessagesAsRead(chatId, lastReadMessageId, lastReadSequenceId); + @override Future initSignalR() => signalRService.init(); diff --git a/client-mobile/lib/features/chat/domain/entities/message.dart b/client-mobile/lib/features/chat/domain/entities/message.dart index 853d41d..2eb68f7 100644 --- a/client-mobile/lib/features/chat/domain/entities/message.dart +++ b/client-mobile/lib/features/chat/domain/entities/message.dart @@ -3,6 +3,8 @@ import 'package:freezed_annotation/freezed_annotation.dart'; part 'message.freezed.dart'; // part 'message.g.dart'; +enum MessageStatus { sending, delivered, read, error } + @freezed class Message with _$Message { const factory Message({ @@ -10,12 +12,11 @@ class Message with _$Message { required String chatId, required String senderId, required String content, - required String messageType, // 'text', 'image', 'video', 'audio', 'file' + required String messageType, + required int sequenceId, DateTime? createdAt, DateTime? updatedAt, - bool? isRead, + @Default(MessageStatus.delivered) MessageStatus status, Map? media, }) = _Message; - - // factory Message.fromJson(Map json) => _$MessageFromJson(json); } diff --git a/client-mobile/lib/features/chat/domain/entities/message.freezed.dart b/client-mobile/lib/features/chat/domain/entities/message.freezed.dart index 2a0d83c..4085f6f 100644 --- a/client-mobile/lib/features/chat/domain/entities/message.freezed.dart +++ b/client-mobile/lib/features/chat/domain/entities/message.freezed.dart @@ -20,11 +20,11 @@ mixin _$Message { String get chatId => throw _privateConstructorUsedError; String get senderId => throw _privateConstructorUsedError; String get content => throw _privateConstructorUsedError; - String get messageType => - throw _privateConstructorUsedError; // 'text', 'image', 'video', 'audio', 'file' + String get messageType => throw _privateConstructorUsedError; + int get sequenceId => throw _privateConstructorUsedError; DateTime? get createdAt => throw _privateConstructorUsedError; DateTime? get updatedAt => throw _privateConstructorUsedError; - bool? get isRead => throw _privateConstructorUsedError; + MessageStatus get status => throw _privateConstructorUsedError; Map? get media => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -42,9 +42,10 @@ abstract class $MessageCopyWith<$Res> { String senderId, String content, String messageType, + int sequenceId, DateTime? createdAt, DateTime? updatedAt, - bool? isRead, + MessageStatus status, Map? media}); } @@ -66,9 +67,10 @@ class _$MessageCopyWithImpl<$Res, $Val extends Message> Object? senderId = null, Object? content = null, Object? messageType = null, + Object? sequenceId = null, Object? createdAt = freezed, Object? updatedAt = freezed, - Object? isRead = freezed, + Object? status = null, Object? media = freezed, }) { return _then(_value.copyWith( @@ -92,6 +94,10 @@ class _$MessageCopyWithImpl<$Res, $Val extends Message> ? _value.messageType : messageType // ignore: cast_nullable_to_non_nullable as String, + sequenceId: null == sequenceId + ? _value.sequenceId + : sequenceId // ignore: cast_nullable_to_non_nullable + as int, createdAt: freezed == createdAt ? _value.createdAt : createdAt // ignore: cast_nullable_to_non_nullable @@ -100,10 +106,10 @@ class _$MessageCopyWithImpl<$Res, $Val extends Message> ? _value.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable as DateTime?, - isRead: freezed == isRead - ? _value.isRead - : isRead // ignore: cast_nullable_to_non_nullable - as bool?, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as MessageStatus, media: freezed == media ? _value.media : media // ignore: cast_nullable_to_non_nullable @@ -125,9 +131,10 @@ abstract class _$$MessageImplCopyWith<$Res> implements $MessageCopyWith<$Res> { String senderId, String content, String messageType, + int sequenceId, DateTime? createdAt, DateTime? updatedAt, - bool? isRead, + MessageStatus status, Map? media}); } @@ -147,9 +154,10 @@ class __$$MessageImplCopyWithImpl<$Res> Object? senderId = null, Object? content = null, Object? messageType = null, + Object? sequenceId = null, Object? createdAt = freezed, Object? updatedAt = freezed, - Object? isRead = freezed, + Object? status = null, Object? media = freezed, }) { return _then(_$MessageImpl( @@ -173,6 +181,10 @@ class __$$MessageImplCopyWithImpl<$Res> ? _value.messageType : messageType // ignore: cast_nullable_to_non_nullable as String, + sequenceId: null == sequenceId + ? _value.sequenceId + : sequenceId // ignore: cast_nullable_to_non_nullable + as int, createdAt: freezed == createdAt ? _value.createdAt : createdAt // ignore: cast_nullable_to_non_nullable @@ -181,10 +193,10 @@ class __$$MessageImplCopyWithImpl<$Res> ? _value.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable as DateTime?, - isRead: freezed == isRead - ? _value.isRead - : isRead // ignore: cast_nullable_to_non_nullable - as bool?, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as MessageStatus, media: freezed == media ? _value._media : media // ignore: cast_nullable_to_non_nullable @@ -202,9 +214,10 @@ class _$MessageImpl implements _Message { required this.senderId, required this.content, required this.messageType, + required this.sequenceId, this.createdAt, this.updatedAt, - this.isRead, + this.status = MessageStatus.delivered, final Map? media}) : _media = media; @@ -218,13 +231,15 @@ class _$MessageImpl implements _Message { final String content; @override final String messageType; -// 'text', 'image', 'video', 'audio', 'file' + @override + final int sequenceId; @override final DateTime? createdAt; @override final DateTime? updatedAt; @override - final bool? isRead; + @JsonKey() + final MessageStatus status; final Map? _media; @override Map? get media { @@ -237,7 +252,7 @@ class _$MessageImpl implements _Message { @override String toString() { - return 'Message(id: $id, chatId: $chatId, senderId: $senderId, content: $content, messageType: $messageType, createdAt: $createdAt, updatedAt: $updatedAt, isRead: $isRead, media: $media)'; + return 'Message(id: $id, chatId: $chatId, senderId: $senderId, content: $content, messageType: $messageType, sequenceId: $sequenceId, createdAt: $createdAt, updatedAt: $updatedAt, status: $status, media: $media)'; } @override @@ -252,11 +267,13 @@ class _$MessageImpl implements _Message { (identical(other.content, content) || other.content == content) && (identical(other.messageType, messageType) || other.messageType == messageType) && + (identical(other.sequenceId, sequenceId) || + other.sequenceId == sequenceId) && (identical(other.createdAt, createdAt) || other.createdAt == createdAt) && (identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt) && - (identical(other.isRead, isRead) || other.isRead == isRead) && + (identical(other.status, status) || other.status == status) && const DeepCollectionEquality().equals(other._media, _media)); } @@ -268,9 +285,10 @@ class _$MessageImpl implements _Message { senderId, content, messageType, + sequenceId, createdAt, updatedAt, - isRead, + status, const DeepCollectionEquality().hash(_media)); @JsonKey(ignore: true) @@ -287,9 +305,10 @@ abstract class _Message implements Message { required final String senderId, required final String content, required final String messageType, + required final int sequenceId, final DateTime? createdAt, final DateTime? updatedAt, - final bool? isRead, + final MessageStatus status, final Map? media}) = _$MessageImpl; @override @@ -302,12 +321,14 @@ abstract class _Message implements Message { String get content; @override String get messageType; - @override // 'text', 'image', 'video', 'audio', 'file' + @override + int get sequenceId; + @override DateTime? get createdAt; @override DateTime? get updatedAt; @override - bool? get isRead; + MessageStatus get status; @override Map? get media; @override diff --git a/client-mobile/lib/features/chat/domain/repositories/chat_repository.dart b/client-mobile/lib/features/chat/domain/repositories/chat_repository.dart index 11c7a31..de56e1e 100644 --- a/client-mobile/lib/features/chat/domain/repositories/chat_repository.dart +++ b/client-mobile/lib/features/chat/domain/repositories/chat_repository.dart @@ -16,7 +16,10 @@ abstract class ChatRepository { Stream get messageStream; Stream> get typingStream; + Stream> get statusStream; + Stream> get readReceiptStream; Future sendTypingStatus(String chatId, bool isTyping); + Future markAsRead(String chatId, String lastReadMessageId, int lastReadSequenceId); Future initSignalR(); Future disposeSignalR(); } diff --git a/client-mobile/lib/features/chat/presentation/bloc/chat_bloc.dart b/client-mobile/lib/features/chat/presentation/bloc/chat_bloc.dart index 735967c..cd9ac87 100644 --- a/client-mobile/lib/features/chat/presentation/bloc/chat_bloc.dart +++ b/client-mobile/lib/features/chat/presentation/bloc/chat_bloc.dart @@ -10,6 +10,12 @@ class ChatBloc extends Bloc { final ChatRepository chatRepository; StreamSubscription? _messageSubscription; StreamSubscription? _typingSubscription; + StreamSubscription? _statusSubscription; + StreamSubscription? _readReceiptSubscription; + Timer? _refreshTimer; + Timer? _retryTimer; + String? _currentUserId; + final Set _sendingIds = {}; ChatBloc({required this.chatRepository}) : super(const ChatState.initial()) { on(_onStarted); @@ -20,7 +26,13 @@ class ChatBloc extends Bloc { on(_onMessageSent); on(_onFavoritesRequested); on(_onTypingUpdated); + on(_onUserStatusChanged); + on(_onRefreshPresence); on(_onSendTypingStatus); + on(_onMarkAsRead); + on(_onReadReceiptReceived); + on(_onMessageStatusUpdated); + on(_onMessageReplaced); on(_onCacheCleared); _messageSubscription = chatRepository.messageStream.listen((message) { @@ -30,9 +42,37 @@ class ChatBloc extends Bloc { _typingSubscription = chatRepository.typingStream.listen((data) { add(ChatEvent.typingUpdated(data['chatId'], data['userId'], data['isTyping'])); }); + + _statusSubscription = chatRepository.statusStream.listen((data) { + add(ChatEvent.userStatusChanged( + data['userId'], + data['isOnline'], + lastSeen: data['lastSeen'] != null ? DateTime.tryParse(data['lastSeen'].toString()) : null, + )); + }); + + _readReceiptSubscription = chatRepository.readReceiptStream.listen((data) { + add(ChatEvent.readReceiptReceived( + chatId: data['chatId'], + userId: data['userId'], + lastReadMessageId: data['lastReadMessageId'], + lastReadSequenceId: int.tryParse(data['lastReadSequenceId'].toString()) ?? 0, + )); + }); + + // Refresh presence status every minute to update "X minutes ago" + _refreshTimer = Timer.periodic(const Duration(minutes: 1), (_) { + add(const ChatEvent.refreshPresence()); + }); + + // Retry sending messages every 10 seconds + _retryTimer = Timer.periodic(const Duration(seconds: 10), (_) { + _retryPendingMessages(); + }); } Future _onStarted(ChatEventStarted event, Emitter emit) async { + _currentUserId = event.userId; // ignore: avoid_print print('[DEBUG] ChatBloc._onStarted for user: ${event.userId}'); // Start SignalR in background @@ -129,12 +169,39 @@ class ChatBloc extends Bloc { orElse: () => [], ); - // Check for duplicates - if (currentMessages.any((m) => m.id == message.id)) return; + final List mutableList = List.from(currentMessages); - final updatedMessages = List.from(currentMessages)..insert(0, message); - // Ensure sorting if needed (usually messages are already in order from stream) - + // Check if this is a message from me that should replace a temp one + if (message.senderId == _currentUserId) { + // Look for a temp message with same content and type + final tempIdx = mutableList.indexWhere((m) => + m.id.startsWith('temp_') && + m.messageType.toLowerCase() == message.messageType.toLowerCase() && + (m.content.trim() == message.content.trim() || (m.content.isEmpty && message.content.isEmpty))); + + if (tempIdx != -1) { + // Replace temp with real one + // ignore: avoid_print + print('[DEBUG] Smart replacement (SignalR): replacing ${mutableList[tempIdx].id} with ${message.id} (Type: ${message.messageType})'); + mutableList[tempIdx] = message; + emit(ChatState.messagesLoaded(currentChat, mutableList, typingUsers: state.typingUsers)); + return; + } + + // If no temp message found, check if we already have this message by ID (prevent double add) + if (mutableList.any((m) => m.id == message.id)) { + // ignore: avoid_print + print('[DEBUG] Self-message already in list, skipping: ${message.id}'); + return; + } + // ignore: avoid_print + print('[DEBUG] Self-message received but no matching temp found: ${message.id} (Content: "${message.content}", Type: ${message.messageType})'); + } else { + // From someone else, check for duplicates + if (mutableList.any((m) => m.id == message.id)) return; + } + + final updatedMessages = mutableList..insert(0, message); emit(ChatState.messagesLoaded(currentChat, updatedMessages, typingUsers: state.typingUsers)); } @@ -146,12 +213,80 @@ class ChatBloc extends Bloc { } Future _onMessageSent(ChatEventMessageSent event, Emitter emit) async { + final currentChat = state.maybeMap( + chatSelected: (s) => s.chat, + messagesLoaded: (s) => s.chat, + orElse: () => null, + ); + + if (currentChat == null) return; + final userId = _currentUserId ?? ''; + + final List currentMessages = state.maybeMap( + chatSelected: (s) => s.messages, + messagesLoaded: (s) => s.messages, + orElse: () => [], + ); + + // Create optimistic "sending" message + final tempId = 'temp_${DateTime.now().millisecondsSinceEpoch}'; + final tempMessage = Message( + id: tempId, + chatId: event.chatId, + senderId: userId, + content: event.content, + messageType: 'text', + sequenceId: -1, // Temporary + createdAt: DateTime.now(), + status: MessageStatus.sending, + ); + + final updatedMessages = List.from(currentMessages)..insert(0, tempMessage); + emit(ChatState.messagesLoaded(currentChat, updatedMessages, typingUsers: state.typingUsers)); + final result = await chatRepository.sendMessage(event.chatId, event.content); + result.fold( - (error) => emit(ChatState.error(error.message ?? 'Failed to send message', typingUsers: state.typingUsers)), - (_) { - // Optimistically or via refresh - add(ChatEvent.messagesRequested(event.chatId)); + (error) { + // ignore: avoid_print + print('[DEBUG] sendMessage failed for $tempId: ${error.toString()}'); + final isNetworkError = error.maybeMap( + network: (_) => true, + orElse: () => false, + ); + + if (isNetworkError) { + // Keep as sending, retry timer will pick it up + return; + } + + final List currentList = state.maybeMap( + messagesLoaded: (s) => s.messages, + orElse: () => updatedMessages, + ); + + final List mutableList = List.from(currentList); + final idx = mutableList.indexWhere((m) => m.id == tempId); + if (idx != -1) { + mutableList[idx] = mutableList[idx].copyWith(status: MessageStatus.error); + emit(ChatState.messagesLoaded(currentChat, mutableList, typingUsers: state.typingUsers)); + } + }, + (sentMessage) { + // Replace temp message with the actual one from server + // ignore: avoid_print + print('[DEBUG] sendMessage success for $tempId, replacing with ${sentMessage.id}'); + final List currentList = state.maybeMap( + messagesLoaded: (s) => s.messages, + orElse: () => updatedMessages, + ); + + final List mutableList = List.from(currentList); + final idx = mutableList.indexWhere((m) => m.id == tempId); + if (idx != -1) { + mutableList[idx] = sentMessage; + emit(ChatState.messagesLoaded(currentChat, mutableList, typingUsers: state.typingUsers)); + } }, ); } @@ -196,10 +331,98 @@ class ChatBloc extends Bloc { ); } + Future _onUserStatusChanged(ChatEventUserStatusChanged event, Emitter emit) async { + state.mapOrNull( + chatsLoaded: (s) { + final updatedChats = s.chats.map((chat) { + final participants = chat.participants; + if (participants != null && participants.any((p) => p.id == event.userId)) { + final updatedParticipants = participants.map((p) { + if (p.id == event.userId) { + return p.copyWith(isOnline: event.isOnline, lastSeen: event.lastSeen ?? p.lastSeen); + } + return p; + }).toList(); + return chat.copyWith(participants: updatedParticipants); + } + return chat; + }).toList(); + emit(s.copyWith(chats: updatedChats)); + }, + chatSelected: (s) { + if (s.chat.participants?.any((p) => p.id == event.userId) ?? false) { + final updatedParticipants = s.chat.participants!.map((p) { + if (p.id == event.userId) { + return p.copyWith(isOnline: event.isOnline, lastSeen: event.lastSeen ?? p.lastSeen); + } + return p; + }).toList(); + final updatedChat = s.chat.copyWith(participants: updatedParticipants); + emit(s.copyWith(chat: updatedChat)); + } + }, + messagesLoaded: (s) { + if (s.chat.participants?.any((p) => p.id == event.userId) ?? false) { + final updatedParticipants = s.chat.participants!.map((p) { + if (p.id == event.userId) { + return p.copyWith(isOnline: event.isOnline, lastSeen: event.lastSeen ?? p.lastSeen); + } + return p; + }).toList(); + final updatedChat = s.chat.copyWith(participants: updatedParticipants); + emit(s.copyWith(chat: updatedChat)); + } + }, + ); + } + + Future _onRefreshPresence(ChatEventRefreshPresence event, Emitter emit) async { + // Re-emit the current state with a new timestamp to trigger UI rebuild + state.mapOrNull( + initial: (s) => emit(s.copyWith(lastUpdate: DateTime.now())), + loading: (s) => emit(s.copyWith(lastUpdate: DateTime.now())), + chatsLoaded: (s) => emit(s.copyWith(lastUpdate: DateTime.now())), + chatSelected: (s) => emit(s.copyWith(lastUpdate: DateTime.now())), + messagesLoaded: (s) => emit(s.copyWith(lastUpdate: DateTime.now())), + error: (s) => emit(s.copyWith(lastUpdate: DateTime.now())), + ); + } + Future _onSendTypingStatus(ChatEventSendTypingStatus event, Emitter emit) async { await chatRepository.sendTypingStatus(event.chatId, event.isTyping); } + Future _onMarkAsRead(ChatEventMarkAsRead event, Emitter emit) async { + await chatRepository.markAsRead(event.chatId, event.messageId, event.sequenceId); + } + + Future _onReadReceiptReceived(ChatEventReadReceiptReceived event, Emitter emit) async { + state.mapOrNull( + messagesLoaded: (s) { + if (s.chat.id == event.chatId) { + final updatedMessages = s.messages.map((m) { + if (m.sequenceId <= event.lastReadSequenceId && m.status != MessageStatus.read) { + return m.copyWith(status: MessageStatus.read); + } + return m; + }).toList(); + emit(s.copyWith(messages: updatedMessages)); + } + }, + chatSelected: (s) { + if (s.chat.id == event.chatId) { + final updatedMessages = s.messages.map((m) { + if (m.sequenceId <= event.lastReadSequenceId && m.status != MessageStatus.read) { + return m.copyWith(status: MessageStatus.read); + } + return m; + }).toList(); + emit(s.copyWith(messages: updatedMessages)); + } + }, + ); + } + Future _onCacheCleared(ChatEventCacheCleared event, Emitter emit) async { // ignore: avoid_print print('[DEBUG] ChatBloc._onCacheCleared START'); @@ -209,10 +432,83 @@ class ChatBloc extends Bloc { emit(const ChatState.initial()); } + void _retryPendingMessages() { + state.mapOrNull( + messagesLoaded: (s) { + final pending = s.messages.where((m) => m.status == MessageStatus.sending && m.id.startsWith('temp_')).toList(); + for (final msg in pending) { + if (!_sendingIds.contains(msg.id)) { + _retrySendMessage(msg); + } + } + }, + ); + } + + Future _retrySendMessage(Message tempMessage) async { + _sendingIds.add(tempMessage.id); + final result = await chatRepository.sendMessage(tempMessage.chatId, tempMessage.content); + _sendingIds.remove(tempMessage.id); + + result.fold( + (error) { + final isNetworkError = error.maybeMap( + network: (_) => true, + orElse: () => false, + ); + + if (!isNetworkError) { + _updateMessageStatus(tempMessage.id, MessageStatus.error); + } + }, + (sentMessage) { + _replaceTempMessage(tempMessage.id, sentMessage); + }, + ); + } + + void _updateMessageStatus(String id, MessageStatus status) { + add(ChatEvent.messageStatusUpdated(id, status)); + } + + void _replaceTempMessage(String tempId, Message realMessage) { + add(ChatEvent.messageReplaced(tempId, realMessage)); + } + + Future _onMessageStatusUpdated(ChatEventMessageStatusUpdated event, Emitter emit) async { + state.mapOrNull( + messagesLoaded: (s) { + final List mutableList = List.from(s.messages); + final idx = mutableList.indexWhere((m) => m.id == event.messageId); + if (idx != -1) { + mutableList[idx] = mutableList[idx].copyWith(status: event.status); + emit(s.copyWith(messages: mutableList)); + } + }, + ); + } + + Future _onMessageReplaced(ChatEventMessageReplaced event, Emitter emit) async { + state.mapOrNull( + messagesLoaded: (s) { + final List mutableList = List.from(s.messages); + final idx = mutableList.indexWhere((m) => m.id == event.tempId); + if (idx != -1) { + mutableList[idx] = event.realMessage; + emit(s.copyWith(messages: mutableList)); + } + }, + ); + } + @override Future close() { _messageSubscription?.cancel(); _typingSubscription?.cancel(); + _statusSubscription?.cancel(); + _readReceiptSubscription?.cancel(); + _refreshTimer?.cancel(); + _retryTimer?.cancel(); chatRepository.disposeSignalR(); return super.close(); } diff --git a/client-mobile/lib/features/chat/presentation/bloc/chat_event.dart b/client-mobile/lib/features/chat/presentation/bloc/chat_event.dart index beab581..b8a99cf 100644 --- a/client-mobile/lib/features/chat/presentation/bloc/chat_event.dart +++ b/client-mobile/lib/features/chat/presentation/bloc/chat_event.dart @@ -13,6 +13,17 @@ class ChatEvent with _$ChatEvent { const factory ChatEvent.messageSent(String chatId, String content) = ChatEventMessageSent; const factory ChatEvent.favoritesRequested() = ChatEventFavoritesRequested; const factory ChatEvent.typingUpdated(String chatId, String userId, bool isTyping) = ChatEventTypingUpdated; + const factory ChatEvent.userStatusChanged(String userId, bool isOnline, {DateTime? lastSeen}) = ChatEventUserStatusChanged; + const factory ChatEvent.refreshPresence() = ChatEventRefreshPresence; const factory ChatEvent.sendTypingStatus(String chatId, bool isTyping) = ChatEventSendTypingStatus; + const factory ChatEvent.markAsRead(String chatId, String messageId, int sequenceId) = ChatEventMarkAsRead; + const factory ChatEvent.readReceiptReceived({ + required String chatId, + required String userId, + required String lastReadMessageId, + required int lastReadSequenceId, + }) = ChatEventReadReceiptReceived; + const factory ChatEvent.messageStatusUpdated(String messageId, MessageStatus status) = ChatEventMessageStatusUpdated; + const factory ChatEvent.messageReplaced(String tempId, Message realMessage) = ChatEventMessageReplaced; const factory ChatEvent.cacheCleared() = ChatEventCacheCleared; } diff --git a/client-mobile/lib/features/chat/presentation/bloc/chat_event.freezed.dart b/client-mobile/lib/features/chat/presentation/bloc/chat_event.freezed.dart index 6e61edf..3278f40 100644 --- a/client-mobile/lib/features/chat/presentation/bloc/chat_event.freezed.dart +++ b/client-mobile/lib/features/chat/presentation/bloc/chat_event.freezed.dart @@ -27,7 +27,19 @@ mixin _$ChatEvent { required TResult Function() favoritesRequested, required TResult Function(String chatId, String userId, bool isTyping) typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, required TResult Function() cacheCleared, }) => throw _privateConstructorUsedError; @@ -42,7 +54,18 @@ mixin _$ChatEvent { TResult? Function()? favoritesRequested, TResult? Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, TResult? Function()? cacheCleared, }) => throw _privateConstructorUsedError; @@ -57,7 +80,18 @@ mixin _$ChatEvent { TResult Function()? favoritesRequested, TResult Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, TResult Function()? cacheCleared, required TResult orElse(), }) => @@ -74,7 +108,16 @@ mixin _$ChatEvent { required TResult Function(ChatEventFavoritesRequested value) favoritesRequested, required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, required TResult Function(ChatEventCacheCleared value) cacheCleared, }) => throw _privateConstructorUsedError; @@ -88,7 +131,14 @@ mixin _$ChatEvent { TResult? Function(ChatEventMessageSent value)? messageSent, TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, TResult? Function(ChatEventCacheCleared value)? cacheCleared, }) => throw _privateConstructorUsedError; @@ -102,7 +152,13 @@ mixin _$ChatEvent { TResult Function(ChatEventMessageSent value)? messageSent, TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, TResult Function(ChatEventCacheCleared value)? cacheCleared, required TResult orElse(), }) => @@ -200,7 +256,19 @@ class _$ChatEventStartedImpl implements ChatEventStarted { required TResult Function() favoritesRequested, required TResult Function(String chatId, String userId, bool isTyping) typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, required TResult Function() cacheCleared, }) { return started(userId); @@ -218,7 +286,18 @@ class _$ChatEventStartedImpl implements ChatEventStarted { TResult? Function()? favoritesRequested, TResult? Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, TResult? Function()? cacheCleared, }) { return started?.call(userId); @@ -236,7 +315,18 @@ class _$ChatEventStartedImpl implements ChatEventStarted { TResult Function()? favoritesRequested, TResult Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, TResult Function()? cacheCleared, required TResult orElse(), }) { @@ -259,7 +349,16 @@ class _$ChatEventStartedImpl implements ChatEventStarted { required TResult Function(ChatEventFavoritesRequested value) favoritesRequested, required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, required TResult Function(ChatEventCacheCleared value) cacheCleared, }) { return started(this); @@ -276,7 +375,14 @@ class _$ChatEventStartedImpl implements ChatEventStarted { TResult? Function(ChatEventMessageSent value)? messageSent, TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, TResult? Function(ChatEventCacheCleared value)? cacheCleared, }) { return started?.call(this); @@ -293,7 +399,13 @@ class _$ChatEventStartedImpl implements ChatEventStarted { TResult Function(ChatEventMessageSent value)? messageSent, TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, TResult Function(ChatEventCacheCleared value)? cacheCleared, required TResult orElse(), }) { @@ -390,7 +502,19 @@ class _$ChatEventChatsLoadedImpl implements ChatEventChatsLoaded { required TResult Function() favoritesRequested, required TResult Function(String chatId, String userId, bool isTyping) typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, required TResult Function() cacheCleared, }) { return chatsLoaded(currentUserId); @@ -408,7 +532,18 @@ class _$ChatEventChatsLoadedImpl implements ChatEventChatsLoaded { TResult? Function()? favoritesRequested, TResult? Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, TResult? Function()? cacheCleared, }) { return chatsLoaded?.call(currentUserId); @@ -426,7 +561,18 @@ class _$ChatEventChatsLoadedImpl implements ChatEventChatsLoaded { TResult Function()? favoritesRequested, TResult Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, TResult Function()? cacheCleared, required TResult orElse(), }) { @@ -449,7 +595,16 @@ class _$ChatEventChatsLoadedImpl implements ChatEventChatsLoaded { required TResult Function(ChatEventFavoritesRequested value) favoritesRequested, required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, required TResult Function(ChatEventCacheCleared value) cacheCleared, }) { return chatsLoaded(this); @@ -466,7 +621,14 @@ class _$ChatEventChatsLoadedImpl implements ChatEventChatsLoaded { TResult? Function(ChatEventMessageSent value)? messageSent, TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, TResult? Function(ChatEventCacheCleared value)? cacheCleared, }) { return chatsLoaded?.call(this); @@ -483,7 +645,13 @@ class _$ChatEventChatsLoadedImpl implements ChatEventChatsLoaded { TResult Function(ChatEventMessageSent value)? messageSent, TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, TResult Function(ChatEventCacheCleared value)? cacheCleared, required TResult orElse(), }) { @@ -579,7 +747,19 @@ class _$ChatEventChatSelectedImpl implements ChatEventChatSelected { required TResult Function() favoritesRequested, required TResult Function(String chatId, String userId, bool isTyping) typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, required TResult Function() cacheCleared, }) { return chatSelected(chatId); @@ -597,7 +777,18 @@ class _$ChatEventChatSelectedImpl implements ChatEventChatSelected { TResult? Function()? favoritesRequested, TResult? Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, TResult? Function()? cacheCleared, }) { return chatSelected?.call(chatId); @@ -615,7 +806,18 @@ class _$ChatEventChatSelectedImpl implements ChatEventChatSelected { TResult Function()? favoritesRequested, TResult Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, TResult Function()? cacheCleared, required TResult orElse(), }) { @@ -638,7 +840,16 @@ class _$ChatEventChatSelectedImpl implements ChatEventChatSelected { required TResult Function(ChatEventFavoritesRequested value) favoritesRequested, required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, required TResult Function(ChatEventCacheCleared value) cacheCleared, }) { return chatSelected(this); @@ -655,7 +866,14 @@ class _$ChatEventChatSelectedImpl implements ChatEventChatSelected { TResult? Function(ChatEventMessageSent value)? messageSent, TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, TResult? Function(ChatEventCacheCleared value)? cacheCleared, }) { return chatSelected?.call(this); @@ -672,7 +890,13 @@ class _$ChatEventChatSelectedImpl implements ChatEventChatSelected { TResult Function(ChatEventMessageSent value)? messageSent, TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, TResult Function(ChatEventCacheCleared value)? cacheCleared, required TResult orElse(), }) { @@ -777,7 +1001,19 @@ class _$ChatEventMessagesRequestedImpl implements ChatEventMessagesRequested { required TResult Function() favoritesRequested, required TResult Function(String chatId, String userId, bool isTyping) typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, required TResult Function() cacheCleared, }) { return messagesRequested(chatId, cursor); @@ -795,7 +1031,18 @@ class _$ChatEventMessagesRequestedImpl implements ChatEventMessagesRequested { TResult? Function()? favoritesRequested, TResult? Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, TResult? Function()? cacheCleared, }) { return messagesRequested?.call(chatId, cursor); @@ -813,7 +1060,18 @@ class _$ChatEventMessagesRequestedImpl implements ChatEventMessagesRequested { TResult Function()? favoritesRequested, TResult Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, TResult Function()? cacheCleared, required TResult orElse(), }) { @@ -836,7 +1094,16 @@ class _$ChatEventMessagesRequestedImpl implements ChatEventMessagesRequested { required TResult Function(ChatEventFavoritesRequested value) favoritesRequested, required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, required TResult Function(ChatEventCacheCleared value) cacheCleared, }) { return messagesRequested(this); @@ -853,7 +1120,14 @@ class _$ChatEventMessagesRequestedImpl implements ChatEventMessagesRequested { TResult? Function(ChatEventMessageSent value)? messageSent, TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, TResult? Function(ChatEventCacheCleared value)? cacheCleared, }) { return messagesRequested?.call(this); @@ -870,7 +1144,13 @@ class _$ChatEventMessagesRequestedImpl implements ChatEventMessagesRequested { TResult Function(ChatEventMessageSent value)? messageSent, TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, TResult Function(ChatEventCacheCleared value)? cacheCleared, required TResult orElse(), }) { @@ -978,7 +1258,19 @@ class _$ChatEventMessageReceivedImpl implements ChatEventMessageReceived { required TResult Function() favoritesRequested, required TResult Function(String chatId, String userId, bool isTyping) typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, required TResult Function() cacheCleared, }) { return messageReceived(message); @@ -996,7 +1288,18 @@ class _$ChatEventMessageReceivedImpl implements ChatEventMessageReceived { TResult? Function()? favoritesRequested, TResult? Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, TResult? Function()? cacheCleared, }) { return messageReceived?.call(message); @@ -1014,7 +1317,18 @@ class _$ChatEventMessageReceivedImpl implements ChatEventMessageReceived { TResult Function()? favoritesRequested, TResult Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, TResult Function()? cacheCleared, required TResult orElse(), }) { @@ -1037,7 +1351,16 @@ class _$ChatEventMessageReceivedImpl implements ChatEventMessageReceived { required TResult Function(ChatEventFavoritesRequested value) favoritesRequested, required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, required TResult Function(ChatEventCacheCleared value) cacheCleared, }) { return messageReceived(this); @@ -1054,7 +1377,14 @@ class _$ChatEventMessageReceivedImpl implements ChatEventMessageReceived { TResult? Function(ChatEventMessageSent value)? messageSent, TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, TResult? Function(ChatEventCacheCleared value)? cacheCleared, }) { return messageReceived?.call(this); @@ -1071,7 +1401,13 @@ class _$ChatEventMessageReceivedImpl implements ChatEventMessageReceived { TResult Function(ChatEventMessageSent value)? messageSent, TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, TResult Function(ChatEventCacheCleared value)? cacheCleared, required TResult orElse(), }) { @@ -1175,7 +1511,19 @@ class _$ChatEventMessageSentImpl implements ChatEventMessageSent { required TResult Function() favoritesRequested, required TResult Function(String chatId, String userId, bool isTyping) typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, required TResult Function() cacheCleared, }) { return messageSent(chatId, content); @@ -1193,7 +1541,18 @@ class _$ChatEventMessageSentImpl implements ChatEventMessageSent { TResult? Function()? favoritesRequested, TResult? Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, TResult? Function()? cacheCleared, }) { return messageSent?.call(chatId, content); @@ -1211,7 +1570,18 @@ class _$ChatEventMessageSentImpl implements ChatEventMessageSent { TResult Function()? favoritesRequested, TResult Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, TResult Function()? cacheCleared, required TResult orElse(), }) { @@ -1234,7 +1604,16 @@ class _$ChatEventMessageSentImpl implements ChatEventMessageSent { required TResult Function(ChatEventFavoritesRequested value) favoritesRequested, required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, required TResult Function(ChatEventCacheCleared value) cacheCleared, }) { return messageSent(this); @@ -1251,7 +1630,14 @@ class _$ChatEventMessageSentImpl implements ChatEventMessageSent { TResult? Function(ChatEventMessageSent value)? messageSent, TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, TResult? Function(ChatEventCacheCleared value)? cacheCleared, }) { return messageSent?.call(this); @@ -1268,7 +1654,13 @@ class _$ChatEventMessageSentImpl implements ChatEventMessageSent { TResult Function(ChatEventMessageSent value)? messageSent, TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, TResult Function(ChatEventCacheCleared value)? cacheCleared, required TResult orElse(), }) { @@ -1340,7 +1732,19 @@ class _$ChatEventFavoritesRequestedImpl implements ChatEventFavoritesRequested { required TResult Function() favoritesRequested, required TResult Function(String chatId, String userId, bool isTyping) typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, required TResult Function() cacheCleared, }) { return favoritesRequested(); @@ -1358,7 +1762,18 @@ class _$ChatEventFavoritesRequestedImpl implements ChatEventFavoritesRequested { TResult? Function()? favoritesRequested, TResult? Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, TResult? Function()? cacheCleared, }) { return favoritesRequested?.call(); @@ -1376,7 +1791,18 @@ class _$ChatEventFavoritesRequestedImpl implements ChatEventFavoritesRequested { TResult Function()? favoritesRequested, TResult Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, TResult Function()? cacheCleared, required TResult orElse(), }) { @@ -1399,7 +1825,16 @@ class _$ChatEventFavoritesRequestedImpl implements ChatEventFavoritesRequested { required TResult Function(ChatEventFavoritesRequested value) favoritesRequested, required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, required TResult Function(ChatEventCacheCleared value) cacheCleared, }) { return favoritesRequested(this); @@ -1416,7 +1851,14 @@ class _$ChatEventFavoritesRequestedImpl implements ChatEventFavoritesRequested { TResult? Function(ChatEventMessageSent value)? messageSent, TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, TResult? Function(ChatEventCacheCleared value)? cacheCleared, }) { return favoritesRequested?.call(this); @@ -1433,7 +1875,13 @@ class _$ChatEventFavoritesRequestedImpl implements ChatEventFavoritesRequested { TResult Function(ChatEventMessageSent value)? messageSent, TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, TResult Function(ChatEventCacheCleared value)? cacheCleared, required TResult orElse(), }) { @@ -1542,7 +1990,19 @@ class _$ChatEventTypingUpdatedImpl implements ChatEventTypingUpdated { required TResult Function() favoritesRequested, required TResult Function(String chatId, String userId, bool isTyping) typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, required TResult Function() cacheCleared, }) { return typingUpdated(chatId, userId, isTyping); @@ -1560,7 +2020,18 @@ class _$ChatEventTypingUpdatedImpl implements ChatEventTypingUpdated { TResult? Function()? favoritesRequested, TResult? Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, TResult? Function()? cacheCleared, }) { return typingUpdated?.call(chatId, userId, isTyping); @@ -1578,7 +2049,18 @@ class _$ChatEventTypingUpdatedImpl implements ChatEventTypingUpdated { TResult Function()? favoritesRequested, TResult Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, TResult Function()? cacheCleared, required TResult orElse(), }) { @@ -1601,7 +2083,16 @@ class _$ChatEventTypingUpdatedImpl implements ChatEventTypingUpdated { required TResult Function(ChatEventFavoritesRequested value) favoritesRequested, required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, required TResult Function(ChatEventCacheCleared value) cacheCleared, }) { return typingUpdated(this); @@ -1618,7 +2109,14 @@ class _$ChatEventTypingUpdatedImpl implements ChatEventTypingUpdated { TResult? Function(ChatEventMessageSent value)? messageSent, TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, TResult? Function(ChatEventCacheCleared value)? cacheCleared, }) { return typingUpdated?.call(this); @@ -1635,7 +2133,13 @@ class _$ChatEventTypingUpdatedImpl implements ChatEventTypingUpdated { TResult Function(ChatEventMessageSent value)? messageSent, TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, TResult Function(ChatEventCacheCleared value)? cacheCleared, required TResult orElse(), }) { @@ -1659,6 +2163,488 @@ abstract class ChatEventTypingUpdated implements ChatEvent { get copyWith => throw _privateConstructorUsedError; } +/// @nodoc +abstract class _$$ChatEventUserStatusChangedImplCopyWith<$Res> { + factory _$$ChatEventUserStatusChangedImplCopyWith( + _$ChatEventUserStatusChangedImpl value, + $Res Function(_$ChatEventUserStatusChangedImpl) then) = + __$$ChatEventUserStatusChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String userId, bool isOnline, DateTime? lastSeen}); +} + +/// @nodoc +class __$$ChatEventUserStatusChangedImplCopyWithImpl<$Res> + extends _$ChatEventCopyWithImpl<$Res, _$ChatEventUserStatusChangedImpl> + implements _$$ChatEventUserStatusChangedImplCopyWith<$Res> { + __$$ChatEventUserStatusChangedImplCopyWithImpl( + _$ChatEventUserStatusChangedImpl _value, + $Res Function(_$ChatEventUserStatusChangedImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? userId = null, + Object? isOnline = null, + Object? lastSeen = freezed, + }) { + return _then(_$ChatEventUserStatusChangedImpl( + null == userId + ? _value.userId + : userId // ignore: cast_nullable_to_non_nullable + as String, + null == isOnline + ? _value.isOnline + : isOnline // ignore: cast_nullable_to_non_nullable + as bool, + lastSeen: freezed == lastSeen + ? _value.lastSeen + : lastSeen // ignore: cast_nullable_to_non_nullable + as DateTime?, + )); + } +} + +/// @nodoc + +class _$ChatEventUserStatusChangedImpl implements ChatEventUserStatusChanged { + const _$ChatEventUserStatusChangedImpl(this.userId, this.isOnline, + {this.lastSeen}); + + @override + final String userId; + @override + final bool isOnline; + @override + final DateTime? lastSeen; + + @override + String toString() { + return 'ChatEvent.userStatusChanged(userId: $userId, isOnline: $isOnline, lastSeen: $lastSeen)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChatEventUserStatusChangedImpl && + (identical(other.userId, userId) || other.userId == userId) && + (identical(other.isOnline, isOnline) || + other.isOnline == isOnline) && + (identical(other.lastSeen, lastSeen) || + other.lastSeen == lastSeen)); + } + + @override + int get hashCode => Object.hash(runtimeType, userId, isOnline, lastSeen); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ChatEventUserStatusChangedImplCopyWith<_$ChatEventUserStatusChangedImpl> + get copyWith => __$$ChatEventUserStatusChangedImplCopyWithImpl< + _$ChatEventUserStatusChangedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String? userId) started, + required TResult Function(String? currentUserId) chatsLoaded, + required TResult Function(String chatId) chatSelected, + required TResult Function(String chatId, String? cursor) messagesRequested, + required TResult Function(Message message) messageReceived, + required TResult Function(String chatId, String content) messageSent, + required TResult Function() favoritesRequested, + required TResult Function(String chatId, String userId, bool isTyping) + typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, + required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, + required TResult Function() cacheCleared, + }) { + return userStatusChanged(userId, isOnline, lastSeen); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String? userId)? started, + TResult? Function(String? currentUserId)? chatsLoaded, + TResult? Function(String chatId)? chatSelected, + TResult? Function(String chatId, String? cursor)? messagesRequested, + TResult? Function(Message message)? messageReceived, + TResult? Function(String chatId, String content)? messageSent, + TResult? Function()? favoritesRequested, + TResult? Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, + TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, + TResult? Function()? cacheCleared, + }) { + return userStatusChanged?.call(userId, isOnline, lastSeen); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String? userId)? started, + TResult Function(String? currentUserId)? chatsLoaded, + TResult Function(String chatId)? chatSelected, + TResult Function(String chatId, String? cursor)? messagesRequested, + TResult Function(Message message)? messageReceived, + TResult Function(String chatId, String content)? messageSent, + TResult Function()? favoritesRequested, + TResult Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, + TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, + TResult Function()? cacheCleared, + required TResult orElse(), + }) { + if (userStatusChanged != null) { + return userStatusChanged(userId, isOnline, lastSeen); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(ChatEventStarted value) started, + required TResult Function(ChatEventChatsLoaded value) chatsLoaded, + required TResult Function(ChatEventChatSelected value) chatSelected, + required TResult Function(ChatEventMessagesRequested value) + messagesRequested, + required TResult Function(ChatEventMessageReceived value) messageReceived, + required TResult Function(ChatEventMessageSent value) messageSent, + required TResult Function(ChatEventFavoritesRequested value) + favoritesRequested, + required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, + required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, + required TResult Function(ChatEventCacheCleared value) cacheCleared, + }) { + return userStatusChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(ChatEventStarted value)? started, + TResult? Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult? Function(ChatEventChatSelected value)? chatSelected, + TResult? Function(ChatEventMessagesRequested value)? messagesRequested, + TResult? Function(ChatEventMessageReceived value)? messageReceived, + TResult? Function(ChatEventMessageSent value)? messageSent, + TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, + TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, + TResult? Function(ChatEventCacheCleared value)? cacheCleared, + }) { + return userStatusChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(ChatEventStarted value)? started, + TResult Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult Function(ChatEventChatSelected value)? chatSelected, + TResult Function(ChatEventMessagesRequested value)? messagesRequested, + TResult Function(ChatEventMessageReceived value)? messageReceived, + TResult Function(ChatEventMessageSent value)? messageSent, + TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, + TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, + TResult Function(ChatEventCacheCleared value)? cacheCleared, + required TResult orElse(), + }) { + if (userStatusChanged != null) { + return userStatusChanged(this); + } + return orElse(); + } +} + +abstract class ChatEventUserStatusChanged implements ChatEvent { + const factory ChatEventUserStatusChanged( + final String userId, final bool isOnline, + {final DateTime? lastSeen}) = _$ChatEventUserStatusChangedImpl; + + String get userId; + bool get isOnline; + DateTime? get lastSeen; + @JsonKey(ignore: true) + _$$ChatEventUserStatusChangedImplCopyWith<_$ChatEventUserStatusChangedImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$ChatEventRefreshPresenceImplCopyWith<$Res> { + factory _$$ChatEventRefreshPresenceImplCopyWith( + _$ChatEventRefreshPresenceImpl value, + $Res Function(_$ChatEventRefreshPresenceImpl) then) = + __$$ChatEventRefreshPresenceImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$ChatEventRefreshPresenceImplCopyWithImpl<$Res> + extends _$ChatEventCopyWithImpl<$Res, _$ChatEventRefreshPresenceImpl> + implements _$$ChatEventRefreshPresenceImplCopyWith<$Res> { + __$$ChatEventRefreshPresenceImplCopyWithImpl( + _$ChatEventRefreshPresenceImpl _value, + $Res Function(_$ChatEventRefreshPresenceImpl) _then) + : super(_value, _then); +} + +/// @nodoc + +class _$ChatEventRefreshPresenceImpl implements ChatEventRefreshPresence { + const _$ChatEventRefreshPresenceImpl(); + + @override + String toString() { + return 'ChatEvent.refreshPresence()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChatEventRefreshPresenceImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String? userId) started, + required TResult Function(String? currentUserId) chatsLoaded, + required TResult Function(String chatId) chatSelected, + required TResult Function(String chatId, String? cursor) messagesRequested, + required TResult Function(Message message) messageReceived, + required TResult Function(String chatId, String content) messageSent, + required TResult Function() favoritesRequested, + required TResult Function(String chatId, String userId, bool isTyping) + typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, + required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, + required TResult Function() cacheCleared, + }) { + return refreshPresence(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String? userId)? started, + TResult? Function(String? currentUserId)? chatsLoaded, + TResult? Function(String chatId)? chatSelected, + TResult? Function(String chatId, String? cursor)? messagesRequested, + TResult? Function(Message message)? messageReceived, + TResult? Function(String chatId, String content)? messageSent, + TResult? Function()? favoritesRequested, + TResult? Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, + TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, + TResult? Function()? cacheCleared, + }) { + return refreshPresence?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String? userId)? started, + TResult Function(String? currentUserId)? chatsLoaded, + TResult Function(String chatId)? chatSelected, + TResult Function(String chatId, String? cursor)? messagesRequested, + TResult Function(Message message)? messageReceived, + TResult Function(String chatId, String content)? messageSent, + TResult Function()? favoritesRequested, + TResult Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, + TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, + TResult Function()? cacheCleared, + required TResult orElse(), + }) { + if (refreshPresence != null) { + return refreshPresence(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(ChatEventStarted value) started, + required TResult Function(ChatEventChatsLoaded value) chatsLoaded, + required TResult Function(ChatEventChatSelected value) chatSelected, + required TResult Function(ChatEventMessagesRequested value) + messagesRequested, + required TResult Function(ChatEventMessageReceived value) messageReceived, + required TResult Function(ChatEventMessageSent value) messageSent, + required TResult Function(ChatEventFavoritesRequested value) + favoritesRequested, + required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, + required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, + required TResult Function(ChatEventCacheCleared value) cacheCleared, + }) { + return refreshPresence(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(ChatEventStarted value)? started, + TResult? Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult? Function(ChatEventChatSelected value)? chatSelected, + TResult? Function(ChatEventMessagesRequested value)? messagesRequested, + TResult? Function(ChatEventMessageReceived value)? messageReceived, + TResult? Function(ChatEventMessageSent value)? messageSent, + TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, + TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, + TResult? Function(ChatEventCacheCleared value)? cacheCleared, + }) { + return refreshPresence?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(ChatEventStarted value)? started, + TResult Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult Function(ChatEventChatSelected value)? chatSelected, + TResult Function(ChatEventMessagesRequested value)? messagesRequested, + TResult Function(ChatEventMessageReceived value)? messageReceived, + TResult Function(ChatEventMessageSent value)? messageSent, + TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, + TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, + TResult Function(ChatEventCacheCleared value)? cacheCleared, + required TResult orElse(), + }) { + if (refreshPresence != null) { + return refreshPresence(this); + } + return orElse(); + } +} + +abstract class ChatEventRefreshPresence implements ChatEvent { + const factory ChatEventRefreshPresence() = _$ChatEventRefreshPresenceImpl; +} + /// @nodoc abstract class _$$ChatEventSendTypingStatusImplCopyWith<$Res> { factory _$$ChatEventSendTypingStatusImplCopyWith( @@ -1744,7 +2730,19 @@ class _$ChatEventSendTypingStatusImpl implements ChatEventSendTypingStatus { required TResult Function() favoritesRequested, required TResult Function(String chatId, String userId, bool isTyping) typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, required TResult Function() cacheCleared, }) { return sendTypingStatus(chatId, isTyping); @@ -1762,7 +2760,18 @@ class _$ChatEventSendTypingStatusImpl implements ChatEventSendTypingStatus { TResult? Function()? favoritesRequested, TResult? Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, TResult? Function()? cacheCleared, }) { return sendTypingStatus?.call(chatId, isTyping); @@ -1780,7 +2789,18 @@ class _$ChatEventSendTypingStatusImpl implements ChatEventSendTypingStatus { TResult Function()? favoritesRequested, TResult Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, TResult Function()? cacheCleared, required TResult orElse(), }) { @@ -1803,7 +2823,16 @@ class _$ChatEventSendTypingStatusImpl implements ChatEventSendTypingStatus { required TResult Function(ChatEventFavoritesRequested value) favoritesRequested, required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, required TResult Function(ChatEventCacheCleared value) cacheCleared, }) { return sendTypingStatus(this); @@ -1820,7 +2849,14 @@ class _$ChatEventSendTypingStatusImpl implements ChatEventSendTypingStatus { TResult? Function(ChatEventMessageSent value)? messageSent, TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, TResult? Function(ChatEventCacheCleared value)? cacheCleared, }) { return sendTypingStatus?.call(this); @@ -1837,7 +2873,13 @@ class _$ChatEventSendTypingStatusImpl implements ChatEventSendTypingStatus { TResult Function(ChatEventMessageSent value)? messageSent, TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, TResult Function(ChatEventCacheCleared value)? cacheCleared, required TResult orElse(), }) { @@ -1860,6 +2902,1092 @@ abstract class ChatEventSendTypingStatus implements ChatEvent { get copyWith => throw _privateConstructorUsedError; } +/// @nodoc +abstract class _$$ChatEventMarkAsReadImplCopyWith<$Res> { + factory _$$ChatEventMarkAsReadImplCopyWith(_$ChatEventMarkAsReadImpl value, + $Res Function(_$ChatEventMarkAsReadImpl) then) = + __$$ChatEventMarkAsReadImplCopyWithImpl<$Res>; + @useResult + $Res call({String chatId, String messageId, int sequenceId}); +} + +/// @nodoc +class __$$ChatEventMarkAsReadImplCopyWithImpl<$Res> + extends _$ChatEventCopyWithImpl<$Res, _$ChatEventMarkAsReadImpl> + implements _$$ChatEventMarkAsReadImplCopyWith<$Res> { + __$$ChatEventMarkAsReadImplCopyWithImpl(_$ChatEventMarkAsReadImpl _value, + $Res Function(_$ChatEventMarkAsReadImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? chatId = null, + Object? messageId = null, + Object? sequenceId = null, + }) { + return _then(_$ChatEventMarkAsReadImpl( + null == chatId + ? _value.chatId + : chatId // ignore: cast_nullable_to_non_nullable + as String, + null == messageId + ? _value.messageId + : messageId // ignore: cast_nullable_to_non_nullable + as String, + null == sequenceId + ? _value.sequenceId + : sequenceId // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class _$ChatEventMarkAsReadImpl implements ChatEventMarkAsRead { + const _$ChatEventMarkAsReadImpl(this.chatId, this.messageId, this.sequenceId); + + @override + final String chatId; + @override + final String messageId; + @override + final int sequenceId; + + @override + String toString() { + return 'ChatEvent.markAsRead(chatId: $chatId, messageId: $messageId, sequenceId: $sequenceId)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChatEventMarkAsReadImpl && + (identical(other.chatId, chatId) || other.chatId == chatId) && + (identical(other.messageId, messageId) || + other.messageId == messageId) && + (identical(other.sequenceId, sequenceId) || + other.sequenceId == sequenceId)); + } + + @override + int get hashCode => Object.hash(runtimeType, chatId, messageId, sequenceId); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ChatEventMarkAsReadImplCopyWith<_$ChatEventMarkAsReadImpl> get copyWith => + __$$ChatEventMarkAsReadImplCopyWithImpl<_$ChatEventMarkAsReadImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String? userId) started, + required TResult Function(String? currentUserId) chatsLoaded, + required TResult Function(String chatId) chatSelected, + required TResult Function(String chatId, String? cursor) messagesRequested, + required TResult Function(Message message) messageReceived, + required TResult Function(String chatId, String content) messageSent, + required TResult Function() favoritesRequested, + required TResult Function(String chatId, String userId, bool isTyping) + typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, + required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, + required TResult Function() cacheCleared, + }) { + return markAsRead(chatId, messageId, sequenceId); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String? userId)? started, + TResult? Function(String? currentUserId)? chatsLoaded, + TResult? Function(String chatId)? chatSelected, + TResult? Function(String chatId, String? cursor)? messagesRequested, + TResult? Function(Message message)? messageReceived, + TResult? Function(String chatId, String content)? messageSent, + TResult? Function()? favoritesRequested, + TResult? Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, + TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, + TResult? Function()? cacheCleared, + }) { + return markAsRead?.call(chatId, messageId, sequenceId); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String? userId)? started, + TResult Function(String? currentUserId)? chatsLoaded, + TResult Function(String chatId)? chatSelected, + TResult Function(String chatId, String? cursor)? messagesRequested, + TResult Function(Message message)? messageReceived, + TResult Function(String chatId, String content)? messageSent, + TResult Function()? favoritesRequested, + TResult Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, + TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, + TResult Function()? cacheCleared, + required TResult orElse(), + }) { + if (markAsRead != null) { + return markAsRead(chatId, messageId, sequenceId); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(ChatEventStarted value) started, + required TResult Function(ChatEventChatsLoaded value) chatsLoaded, + required TResult Function(ChatEventChatSelected value) chatSelected, + required TResult Function(ChatEventMessagesRequested value) + messagesRequested, + required TResult Function(ChatEventMessageReceived value) messageReceived, + required TResult Function(ChatEventMessageSent value) messageSent, + required TResult Function(ChatEventFavoritesRequested value) + favoritesRequested, + required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, + required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, + required TResult Function(ChatEventCacheCleared value) cacheCleared, + }) { + return markAsRead(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(ChatEventStarted value)? started, + TResult? Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult? Function(ChatEventChatSelected value)? chatSelected, + TResult? Function(ChatEventMessagesRequested value)? messagesRequested, + TResult? Function(ChatEventMessageReceived value)? messageReceived, + TResult? Function(ChatEventMessageSent value)? messageSent, + TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, + TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, + TResult? Function(ChatEventCacheCleared value)? cacheCleared, + }) { + return markAsRead?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(ChatEventStarted value)? started, + TResult Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult Function(ChatEventChatSelected value)? chatSelected, + TResult Function(ChatEventMessagesRequested value)? messagesRequested, + TResult Function(ChatEventMessageReceived value)? messageReceived, + TResult Function(ChatEventMessageSent value)? messageSent, + TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, + TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, + TResult Function(ChatEventCacheCleared value)? cacheCleared, + required TResult orElse(), + }) { + if (markAsRead != null) { + return markAsRead(this); + } + return orElse(); + } +} + +abstract class ChatEventMarkAsRead implements ChatEvent { + const factory ChatEventMarkAsRead( + final String chatId, final String messageId, final int sequenceId) = + _$ChatEventMarkAsReadImpl; + + String get chatId; + String get messageId; + int get sequenceId; + @JsonKey(ignore: true) + _$$ChatEventMarkAsReadImplCopyWith<_$ChatEventMarkAsReadImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$ChatEventReadReceiptReceivedImplCopyWith<$Res> { + factory _$$ChatEventReadReceiptReceivedImplCopyWith( + _$ChatEventReadReceiptReceivedImpl value, + $Res Function(_$ChatEventReadReceiptReceivedImpl) then) = + __$$ChatEventReadReceiptReceivedImplCopyWithImpl<$Res>; + @useResult + $Res call( + {String chatId, + String userId, + String lastReadMessageId, + int lastReadSequenceId}); +} + +/// @nodoc +class __$$ChatEventReadReceiptReceivedImplCopyWithImpl<$Res> + extends _$ChatEventCopyWithImpl<$Res, _$ChatEventReadReceiptReceivedImpl> + implements _$$ChatEventReadReceiptReceivedImplCopyWith<$Res> { + __$$ChatEventReadReceiptReceivedImplCopyWithImpl( + _$ChatEventReadReceiptReceivedImpl _value, + $Res Function(_$ChatEventReadReceiptReceivedImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? chatId = null, + Object? userId = null, + Object? lastReadMessageId = null, + Object? lastReadSequenceId = null, + }) { + return _then(_$ChatEventReadReceiptReceivedImpl( + chatId: null == chatId + ? _value.chatId + : chatId // ignore: cast_nullable_to_non_nullable + as String, + userId: null == userId + ? _value.userId + : userId // ignore: cast_nullable_to_non_nullable + as String, + lastReadMessageId: null == lastReadMessageId + ? _value.lastReadMessageId + : lastReadMessageId // ignore: cast_nullable_to_non_nullable + as String, + lastReadSequenceId: null == lastReadSequenceId + ? _value.lastReadSequenceId + : lastReadSequenceId // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class _$ChatEventReadReceiptReceivedImpl + implements ChatEventReadReceiptReceived { + const _$ChatEventReadReceiptReceivedImpl( + {required this.chatId, + required this.userId, + required this.lastReadMessageId, + required this.lastReadSequenceId}); + + @override + final String chatId; + @override + final String userId; + @override + final String lastReadMessageId; + @override + final int lastReadSequenceId; + + @override + String toString() { + return 'ChatEvent.readReceiptReceived(chatId: $chatId, userId: $userId, lastReadMessageId: $lastReadMessageId, lastReadSequenceId: $lastReadSequenceId)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChatEventReadReceiptReceivedImpl && + (identical(other.chatId, chatId) || other.chatId == chatId) && + (identical(other.userId, userId) || other.userId == userId) && + (identical(other.lastReadMessageId, lastReadMessageId) || + other.lastReadMessageId == lastReadMessageId) && + (identical(other.lastReadSequenceId, lastReadSequenceId) || + other.lastReadSequenceId == lastReadSequenceId)); + } + + @override + int get hashCode => Object.hash( + runtimeType, chatId, userId, lastReadMessageId, lastReadSequenceId); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ChatEventReadReceiptReceivedImplCopyWith< + _$ChatEventReadReceiptReceivedImpl> + get copyWith => __$$ChatEventReadReceiptReceivedImplCopyWithImpl< + _$ChatEventReadReceiptReceivedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String? userId) started, + required TResult Function(String? currentUserId) chatsLoaded, + required TResult Function(String chatId) chatSelected, + required TResult Function(String chatId, String? cursor) messagesRequested, + required TResult Function(Message message) messageReceived, + required TResult Function(String chatId, String content) messageSent, + required TResult Function() favoritesRequested, + required TResult Function(String chatId, String userId, bool isTyping) + typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, + required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, + required TResult Function() cacheCleared, + }) { + return readReceiptReceived( + chatId, userId, lastReadMessageId, lastReadSequenceId); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String? userId)? started, + TResult? Function(String? currentUserId)? chatsLoaded, + TResult? Function(String chatId)? chatSelected, + TResult? Function(String chatId, String? cursor)? messagesRequested, + TResult? Function(Message message)? messageReceived, + TResult? Function(String chatId, String content)? messageSent, + TResult? Function()? favoritesRequested, + TResult? Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, + TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, + TResult? Function()? cacheCleared, + }) { + return readReceiptReceived?.call( + chatId, userId, lastReadMessageId, lastReadSequenceId); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String? userId)? started, + TResult Function(String? currentUserId)? chatsLoaded, + TResult Function(String chatId)? chatSelected, + TResult Function(String chatId, String? cursor)? messagesRequested, + TResult Function(Message message)? messageReceived, + TResult Function(String chatId, String content)? messageSent, + TResult Function()? favoritesRequested, + TResult Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, + TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, + TResult Function()? cacheCleared, + required TResult orElse(), + }) { + if (readReceiptReceived != null) { + return readReceiptReceived( + chatId, userId, lastReadMessageId, lastReadSequenceId); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(ChatEventStarted value) started, + required TResult Function(ChatEventChatsLoaded value) chatsLoaded, + required TResult Function(ChatEventChatSelected value) chatSelected, + required TResult Function(ChatEventMessagesRequested value) + messagesRequested, + required TResult Function(ChatEventMessageReceived value) messageReceived, + required TResult Function(ChatEventMessageSent value) messageSent, + required TResult Function(ChatEventFavoritesRequested value) + favoritesRequested, + required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, + required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, + required TResult Function(ChatEventCacheCleared value) cacheCleared, + }) { + return readReceiptReceived(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(ChatEventStarted value)? started, + TResult? Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult? Function(ChatEventChatSelected value)? chatSelected, + TResult? Function(ChatEventMessagesRequested value)? messagesRequested, + TResult? Function(ChatEventMessageReceived value)? messageReceived, + TResult? Function(ChatEventMessageSent value)? messageSent, + TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, + TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, + TResult? Function(ChatEventCacheCleared value)? cacheCleared, + }) { + return readReceiptReceived?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(ChatEventStarted value)? started, + TResult Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult Function(ChatEventChatSelected value)? chatSelected, + TResult Function(ChatEventMessagesRequested value)? messagesRequested, + TResult Function(ChatEventMessageReceived value)? messageReceived, + TResult Function(ChatEventMessageSent value)? messageSent, + TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, + TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, + TResult Function(ChatEventCacheCleared value)? cacheCleared, + required TResult orElse(), + }) { + if (readReceiptReceived != null) { + return readReceiptReceived(this); + } + return orElse(); + } +} + +abstract class ChatEventReadReceiptReceived implements ChatEvent { + const factory ChatEventReadReceiptReceived( + {required final String chatId, + required final String userId, + required final String lastReadMessageId, + required final int lastReadSequenceId}) = + _$ChatEventReadReceiptReceivedImpl; + + String get chatId; + String get userId; + String get lastReadMessageId; + int get lastReadSequenceId; + @JsonKey(ignore: true) + _$$ChatEventReadReceiptReceivedImplCopyWith< + _$ChatEventReadReceiptReceivedImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$ChatEventMessageStatusUpdatedImplCopyWith<$Res> { + factory _$$ChatEventMessageStatusUpdatedImplCopyWith( + _$ChatEventMessageStatusUpdatedImpl value, + $Res Function(_$ChatEventMessageStatusUpdatedImpl) then) = + __$$ChatEventMessageStatusUpdatedImplCopyWithImpl<$Res>; + @useResult + $Res call({String messageId, MessageStatus status}); +} + +/// @nodoc +class __$$ChatEventMessageStatusUpdatedImplCopyWithImpl<$Res> + extends _$ChatEventCopyWithImpl<$Res, _$ChatEventMessageStatusUpdatedImpl> + implements _$$ChatEventMessageStatusUpdatedImplCopyWith<$Res> { + __$$ChatEventMessageStatusUpdatedImplCopyWithImpl( + _$ChatEventMessageStatusUpdatedImpl _value, + $Res Function(_$ChatEventMessageStatusUpdatedImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? messageId = null, + Object? status = null, + }) { + return _then(_$ChatEventMessageStatusUpdatedImpl( + null == messageId + ? _value.messageId + : messageId // ignore: cast_nullable_to_non_nullable + as String, + null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as MessageStatus, + )); + } +} + +/// @nodoc + +class _$ChatEventMessageStatusUpdatedImpl + implements ChatEventMessageStatusUpdated { + const _$ChatEventMessageStatusUpdatedImpl(this.messageId, this.status); + + @override + final String messageId; + @override + final MessageStatus status; + + @override + String toString() { + return 'ChatEvent.messageStatusUpdated(messageId: $messageId, status: $status)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChatEventMessageStatusUpdatedImpl && + (identical(other.messageId, messageId) || + other.messageId == messageId) && + (identical(other.status, status) || other.status == status)); + } + + @override + int get hashCode => Object.hash(runtimeType, messageId, status); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ChatEventMessageStatusUpdatedImplCopyWith< + _$ChatEventMessageStatusUpdatedImpl> + get copyWith => __$$ChatEventMessageStatusUpdatedImplCopyWithImpl< + _$ChatEventMessageStatusUpdatedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String? userId) started, + required TResult Function(String? currentUserId) chatsLoaded, + required TResult Function(String chatId) chatSelected, + required TResult Function(String chatId, String? cursor) messagesRequested, + required TResult Function(Message message) messageReceived, + required TResult Function(String chatId, String content) messageSent, + required TResult Function() favoritesRequested, + required TResult Function(String chatId, String userId, bool isTyping) + typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, + required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, + required TResult Function() cacheCleared, + }) { + return messageStatusUpdated(messageId, status); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String? userId)? started, + TResult? Function(String? currentUserId)? chatsLoaded, + TResult? Function(String chatId)? chatSelected, + TResult? Function(String chatId, String? cursor)? messagesRequested, + TResult? Function(Message message)? messageReceived, + TResult? Function(String chatId, String content)? messageSent, + TResult? Function()? favoritesRequested, + TResult? Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, + TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, + TResult? Function()? cacheCleared, + }) { + return messageStatusUpdated?.call(messageId, status); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String? userId)? started, + TResult Function(String? currentUserId)? chatsLoaded, + TResult Function(String chatId)? chatSelected, + TResult Function(String chatId, String? cursor)? messagesRequested, + TResult Function(Message message)? messageReceived, + TResult Function(String chatId, String content)? messageSent, + TResult Function()? favoritesRequested, + TResult Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, + TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, + TResult Function()? cacheCleared, + required TResult orElse(), + }) { + if (messageStatusUpdated != null) { + return messageStatusUpdated(messageId, status); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(ChatEventStarted value) started, + required TResult Function(ChatEventChatsLoaded value) chatsLoaded, + required TResult Function(ChatEventChatSelected value) chatSelected, + required TResult Function(ChatEventMessagesRequested value) + messagesRequested, + required TResult Function(ChatEventMessageReceived value) messageReceived, + required TResult Function(ChatEventMessageSent value) messageSent, + required TResult Function(ChatEventFavoritesRequested value) + favoritesRequested, + required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, + required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, + required TResult Function(ChatEventCacheCleared value) cacheCleared, + }) { + return messageStatusUpdated(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(ChatEventStarted value)? started, + TResult? Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult? Function(ChatEventChatSelected value)? chatSelected, + TResult? Function(ChatEventMessagesRequested value)? messagesRequested, + TResult? Function(ChatEventMessageReceived value)? messageReceived, + TResult? Function(ChatEventMessageSent value)? messageSent, + TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, + TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, + TResult? Function(ChatEventCacheCleared value)? cacheCleared, + }) { + return messageStatusUpdated?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(ChatEventStarted value)? started, + TResult Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult Function(ChatEventChatSelected value)? chatSelected, + TResult Function(ChatEventMessagesRequested value)? messagesRequested, + TResult Function(ChatEventMessageReceived value)? messageReceived, + TResult Function(ChatEventMessageSent value)? messageSent, + TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, + TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, + TResult Function(ChatEventCacheCleared value)? cacheCleared, + required TResult orElse(), + }) { + if (messageStatusUpdated != null) { + return messageStatusUpdated(this); + } + return orElse(); + } +} + +abstract class ChatEventMessageStatusUpdated implements ChatEvent { + const factory ChatEventMessageStatusUpdated( + final String messageId, final MessageStatus status) = + _$ChatEventMessageStatusUpdatedImpl; + + String get messageId; + MessageStatus get status; + @JsonKey(ignore: true) + _$$ChatEventMessageStatusUpdatedImplCopyWith< + _$ChatEventMessageStatusUpdatedImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$ChatEventMessageReplacedImplCopyWith<$Res> { + factory _$$ChatEventMessageReplacedImplCopyWith( + _$ChatEventMessageReplacedImpl value, + $Res Function(_$ChatEventMessageReplacedImpl) then) = + __$$ChatEventMessageReplacedImplCopyWithImpl<$Res>; + @useResult + $Res call({String tempId, Message realMessage}); + + $MessageCopyWith<$Res> get realMessage; +} + +/// @nodoc +class __$$ChatEventMessageReplacedImplCopyWithImpl<$Res> + extends _$ChatEventCopyWithImpl<$Res, _$ChatEventMessageReplacedImpl> + implements _$$ChatEventMessageReplacedImplCopyWith<$Res> { + __$$ChatEventMessageReplacedImplCopyWithImpl( + _$ChatEventMessageReplacedImpl _value, + $Res Function(_$ChatEventMessageReplacedImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? tempId = null, + Object? realMessage = null, + }) { + return _then(_$ChatEventMessageReplacedImpl( + null == tempId + ? _value.tempId + : tempId // ignore: cast_nullable_to_non_nullable + as String, + null == realMessage + ? _value.realMessage + : realMessage // ignore: cast_nullable_to_non_nullable + as Message, + )); + } + + @override + @pragma('vm:prefer-inline') + $MessageCopyWith<$Res> get realMessage { + return $MessageCopyWith<$Res>(_value.realMessage, (value) { + return _then(_value.copyWith(realMessage: value)); + }); + } +} + +/// @nodoc + +class _$ChatEventMessageReplacedImpl implements ChatEventMessageReplaced { + const _$ChatEventMessageReplacedImpl(this.tempId, this.realMessage); + + @override + final String tempId; + @override + final Message realMessage; + + @override + String toString() { + return 'ChatEvent.messageReplaced(tempId: $tempId, realMessage: $realMessage)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChatEventMessageReplacedImpl && + (identical(other.tempId, tempId) || other.tempId == tempId) && + (identical(other.realMessage, realMessage) || + other.realMessage == realMessage)); + } + + @override + int get hashCode => Object.hash(runtimeType, tempId, realMessage); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ChatEventMessageReplacedImplCopyWith<_$ChatEventMessageReplacedImpl> + get copyWith => __$$ChatEventMessageReplacedImplCopyWithImpl< + _$ChatEventMessageReplacedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String? userId) started, + required TResult Function(String? currentUserId) chatsLoaded, + required TResult Function(String chatId) chatSelected, + required TResult Function(String chatId, String? cursor) messagesRequested, + required TResult Function(Message message) messageReceived, + required TResult Function(String chatId, String content) messageSent, + required TResult Function() favoritesRequested, + required TResult Function(String chatId, String userId, bool isTyping) + typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, + required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, + required TResult Function() cacheCleared, + }) { + return messageReplaced(tempId, realMessage); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String? userId)? started, + TResult? Function(String? currentUserId)? chatsLoaded, + TResult? Function(String chatId)? chatSelected, + TResult? Function(String chatId, String? cursor)? messagesRequested, + TResult? Function(Message message)? messageReceived, + TResult? Function(String chatId, String content)? messageSent, + TResult? Function()? favoritesRequested, + TResult? Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, + TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, + TResult? Function()? cacheCleared, + }) { + return messageReplaced?.call(tempId, realMessage); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String? userId)? started, + TResult Function(String? currentUserId)? chatsLoaded, + TResult Function(String chatId)? chatSelected, + TResult Function(String chatId, String? cursor)? messagesRequested, + TResult Function(Message message)? messageReceived, + TResult Function(String chatId, String content)? messageSent, + TResult Function()? favoritesRequested, + TResult Function(String chatId, String userId, bool isTyping)? + typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, + TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, + TResult Function()? cacheCleared, + required TResult orElse(), + }) { + if (messageReplaced != null) { + return messageReplaced(tempId, realMessage); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(ChatEventStarted value) started, + required TResult Function(ChatEventChatsLoaded value) chatsLoaded, + required TResult Function(ChatEventChatSelected value) chatSelected, + required TResult Function(ChatEventMessagesRequested value) + messagesRequested, + required TResult Function(ChatEventMessageReceived value) messageReceived, + required TResult Function(ChatEventMessageSent value) messageSent, + required TResult Function(ChatEventFavoritesRequested value) + favoritesRequested, + required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, + required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, + required TResult Function(ChatEventCacheCleared value) cacheCleared, + }) { + return messageReplaced(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(ChatEventStarted value)? started, + TResult? Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult? Function(ChatEventChatSelected value)? chatSelected, + TResult? Function(ChatEventMessagesRequested value)? messagesRequested, + TResult? Function(ChatEventMessageReceived value)? messageReceived, + TResult? Function(ChatEventMessageSent value)? messageSent, + TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, + TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, + TResult? Function(ChatEventCacheCleared value)? cacheCleared, + }) { + return messageReplaced?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(ChatEventStarted value)? started, + TResult Function(ChatEventChatsLoaded value)? chatsLoaded, + TResult Function(ChatEventChatSelected value)? chatSelected, + TResult Function(ChatEventMessagesRequested value)? messagesRequested, + TResult Function(ChatEventMessageReceived value)? messageReceived, + TResult Function(ChatEventMessageSent value)? messageSent, + TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, + TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, + TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, + TResult Function(ChatEventCacheCleared value)? cacheCleared, + required TResult orElse(), + }) { + if (messageReplaced != null) { + return messageReplaced(this); + } + return orElse(); + } +} + +abstract class ChatEventMessageReplaced implements ChatEvent { + const factory ChatEventMessageReplaced( + final String tempId, final Message realMessage) = + _$ChatEventMessageReplacedImpl; + + String get tempId; + Message get realMessage; + @JsonKey(ignore: true) + _$$ChatEventMessageReplacedImplCopyWith<_$ChatEventMessageReplacedImpl> + get copyWith => throw _privateConstructorUsedError; +} + /// @nodoc abstract class _$$ChatEventCacheClearedImplCopyWith<$Res> { factory _$$ChatEventCacheClearedImplCopyWith( @@ -1909,7 +4037,19 @@ class _$ChatEventCacheClearedImpl implements ChatEventCacheCleared { required TResult Function() favoritesRequested, required TResult Function(String chatId, String userId, bool isTyping) typingUpdated, + required TResult Function(String userId, bool isOnline, DateTime? lastSeen) + userStatusChanged, + required TResult Function() refreshPresence, required TResult Function(String chatId, bool isTyping) sendTypingStatus, + required TResult Function(String chatId, String messageId, int sequenceId) + markAsRead, + required TResult Function(String chatId, String userId, + String lastReadMessageId, int lastReadSequenceId) + readReceiptReceived, + required TResult Function(String messageId, MessageStatus status) + messageStatusUpdated, + required TResult Function(String tempId, Message realMessage) + messageReplaced, required TResult Function() cacheCleared, }) { return cacheCleared(); @@ -1927,7 +4067,18 @@ class _$ChatEventCacheClearedImpl implements ChatEventCacheCleared { TResult? Function()? favoritesRequested, TResult? Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult? Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult? Function()? refreshPresence, TResult? Function(String chatId, bool isTyping)? sendTypingStatus, + TResult? Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult? Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult? Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult? Function(String tempId, Message realMessage)? messageReplaced, TResult? Function()? cacheCleared, }) { return cacheCleared?.call(); @@ -1945,7 +4096,18 @@ class _$ChatEventCacheClearedImpl implements ChatEventCacheCleared { TResult Function()? favoritesRequested, TResult Function(String chatId, String userId, bool isTyping)? typingUpdated, + TResult Function(String userId, bool isOnline, DateTime? lastSeen)? + userStatusChanged, + TResult Function()? refreshPresence, TResult Function(String chatId, bool isTyping)? sendTypingStatus, + TResult Function(String chatId, String messageId, int sequenceId)? + markAsRead, + TResult Function(String chatId, String userId, String lastReadMessageId, + int lastReadSequenceId)? + readReceiptReceived, + TResult Function(String messageId, MessageStatus status)? + messageStatusUpdated, + TResult Function(String tempId, Message realMessage)? messageReplaced, TResult Function()? cacheCleared, required TResult orElse(), }) { @@ -1968,7 +4130,16 @@ class _$ChatEventCacheClearedImpl implements ChatEventCacheCleared { required TResult Function(ChatEventFavoritesRequested value) favoritesRequested, required TResult Function(ChatEventTypingUpdated value) typingUpdated, + required TResult Function(ChatEventUserStatusChanged value) + userStatusChanged, + required TResult Function(ChatEventRefreshPresence value) refreshPresence, required TResult Function(ChatEventSendTypingStatus value) sendTypingStatus, + required TResult Function(ChatEventMarkAsRead value) markAsRead, + required TResult Function(ChatEventReadReceiptReceived value) + readReceiptReceived, + required TResult Function(ChatEventMessageStatusUpdated value) + messageStatusUpdated, + required TResult Function(ChatEventMessageReplaced value) messageReplaced, required TResult Function(ChatEventCacheCleared value) cacheCleared, }) { return cacheCleared(this); @@ -1985,7 +4156,14 @@ class _$ChatEventCacheClearedImpl implements ChatEventCacheCleared { TResult? Function(ChatEventMessageSent value)? messageSent, TResult? Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult? Function(ChatEventTypingUpdated value)? typingUpdated, + TResult? Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult? Function(ChatEventRefreshPresence value)? refreshPresence, TResult? Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult? Function(ChatEventMarkAsRead value)? markAsRead, + TResult? Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult? Function(ChatEventMessageStatusUpdated value)? + messageStatusUpdated, + TResult? Function(ChatEventMessageReplaced value)? messageReplaced, TResult? Function(ChatEventCacheCleared value)? cacheCleared, }) { return cacheCleared?.call(this); @@ -2002,7 +4180,13 @@ class _$ChatEventCacheClearedImpl implements ChatEventCacheCleared { TResult Function(ChatEventMessageSent value)? messageSent, TResult Function(ChatEventFavoritesRequested value)? favoritesRequested, TResult Function(ChatEventTypingUpdated value)? typingUpdated, + TResult Function(ChatEventUserStatusChanged value)? userStatusChanged, + TResult Function(ChatEventRefreshPresence value)? refreshPresence, TResult Function(ChatEventSendTypingStatus value)? sendTypingStatus, + TResult Function(ChatEventMarkAsRead value)? markAsRead, + TResult Function(ChatEventReadReceiptReceived value)? readReceiptReceived, + TResult Function(ChatEventMessageStatusUpdated value)? messageStatusUpdated, + TResult Function(ChatEventMessageReplaced value)? messageReplaced, TResult Function(ChatEventCacheCleared value)? cacheCleared, required TResult orElse(), }) { diff --git a/client-mobile/lib/features/chat/presentation/bloc/chat_state.dart b/client-mobile/lib/features/chat/presentation/bloc/chat_state.dart index baa0364..7535f32 100644 --- a/client-mobile/lib/features/chat/presentation/bloc/chat_state.dart +++ b/client-mobile/lib/features/chat/presentation/bloc/chat_state.dart @@ -6,10 +6,10 @@ part 'chat_state.freezed.dart'; @freezed class ChatState with _$ChatState { - const factory ChatState.initial({@Default({}) Map> typingUsers}) = ChatInitial; - const factory ChatState.loading({@Default({}) Map> typingUsers}) = ChatLoading; - const factory ChatState.chatsLoaded(List chats, {@Default({}) Map> typingUsers}) = _ChatsLoaded; - const factory ChatState.chatSelected(Chat chat, List messages, {@Default({}) Map> typingUsers}) = _ChatSelected; - const factory ChatState.messagesLoaded(Chat chat, List messages, {@Default({}) Map> typingUsers}) = _MessagesLoaded; - const factory ChatState.error(String message, {@Default({}) Map> typingUsers}) = ChatError; + const factory ChatState.initial({@Default({}) Map> typingUsers, DateTime? lastUpdate}) = ChatInitial; + const factory ChatState.loading({@Default({}) Map> typingUsers, DateTime? lastUpdate}) = ChatLoading; + const factory ChatState.chatsLoaded(List chats, {@Default({}) Map> typingUsers, DateTime? lastUpdate}) = _ChatsLoaded; + const factory ChatState.chatSelected(Chat chat, List messages, {@Default({}) Map> typingUsers, DateTime? lastUpdate}) = _ChatSelected; + const factory ChatState.messagesLoaded(Chat chat, List messages, {@Default({}) Map> typingUsers, DateTime? lastUpdate}) = _MessagesLoaded; + const factory ChatState.error(String message, {@Default({}) Map> typingUsers, DateTime? lastUpdate}) = ChatError; } diff --git a/client-mobile/lib/features/chat/presentation/bloc/chat_state.freezed.dart b/client-mobile/lib/features/chat/presentation/bloc/chat_state.freezed.dart index 43caeeb..1672de7 100644 --- a/client-mobile/lib/features/chat/presentation/bloc/chat_state.freezed.dart +++ b/client-mobile/lib/features/chat/presentation/bloc/chat_state.freezed.dart @@ -18,53 +18,70 @@ final _privateConstructorUsedError = UnsupportedError( mixin _$ChatState { Map> get typingUsers => throw _privateConstructorUsedError; + DateTime? get lastUpdate => throw _privateConstructorUsedError; @optionalTypeArgs TResult when({ - required TResult Function(Map> typingUsers) initial, - required TResult Function(Map> typingUsers) loading, required TResult Function( - List chats, Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) + initial, + required TResult Function( + Map> typingUsers, DateTime? lastUpdate) + loading, + required TResult Function(List chats, + Map> typingUsers, DateTime? lastUpdate) chatsLoaded, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) chatSelected, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) messagesLoaded, - required TResult Function( - String message, Map> typingUsers) + required TResult Function(String message, + Map> typingUsers, DateTime? lastUpdate) error, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(Map> typingUsers)? initial, - TResult? Function(Map> typingUsers)? loading, - TResult? Function(List chats, Map> typingUsers)? + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult? Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult? Function(String message, Map> typingUsers)? + TResult? Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ - TResult Function(Map> typingUsers)? initial, - TResult Function(Map> typingUsers)? loading, - TResult Function(List chats, Map> typingUsers)? + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult Function(String message, Map> typingUsers)? + TResult Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, required TResult orElse(), }) => @@ -111,7 +128,7 @@ abstract class $ChatStateCopyWith<$Res> { factory $ChatStateCopyWith(ChatState value, $Res Function(ChatState) then) = _$ChatStateCopyWithImpl<$Res, ChatState>; @useResult - $Res call({Map> typingUsers}); + $Res call({Map> typingUsers, DateTime? lastUpdate}); } /// @nodoc @@ -128,12 +145,17 @@ class _$ChatStateCopyWithImpl<$Res, $Val extends ChatState> @override $Res call({ Object? typingUsers = null, + Object? lastUpdate = freezed, }) { return _then(_value.copyWith( typingUsers: null == typingUsers ? _value.typingUsers : typingUsers // ignore: cast_nullable_to_non_nullable as Map>, + lastUpdate: freezed == lastUpdate + ? _value.lastUpdate + : lastUpdate // ignore: cast_nullable_to_non_nullable + as DateTime?, ) as $Val); } } @@ -146,7 +168,7 @@ abstract class _$$ChatInitialImplCopyWith<$Res> __$$ChatInitialImplCopyWithImpl<$Res>; @override @useResult - $Res call({Map> typingUsers}); + $Res call({Map> typingUsers, DateTime? lastUpdate}); } /// @nodoc @@ -161,12 +183,17 @@ class __$$ChatInitialImplCopyWithImpl<$Res> @override $Res call({ Object? typingUsers = null, + Object? lastUpdate = freezed, }) { return _then(_$ChatInitialImpl( typingUsers: null == typingUsers ? _value._typingUsers : typingUsers // ignore: cast_nullable_to_non_nullable as Map>, + lastUpdate: freezed == lastUpdate + ? _value.lastUpdate + : lastUpdate // ignore: cast_nullable_to_non_nullable + as DateTime?, )); } } @@ -175,7 +202,7 @@ class __$$ChatInitialImplCopyWithImpl<$Res> class _$ChatInitialImpl implements ChatInitial { const _$ChatInitialImpl( - {final Map> typingUsers = const {}}) + {final Map> typingUsers = const {}, this.lastUpdate}) : _typingUsers = typingUsers; final Map> _typingUsers; @@ -187,9 +214,12 @@ class _$ChatInitialImpl implements ChatInitial { return EqualUnmodifiableMapView(_typingUsers); } + @override + final DateTime? lastUpdate; + @override String toString() { - return 'ChatState.initial(typingUsers: $typingUsers)'; + return 'ChatState.initial(typingUsers: $typingUsers, lastUpdate: $lastUpdate)'; } @override @@ -198,12 +228,14 @@ class _$ChatInitialImpl implements ChatInitial { (other.runtimeType == runtimeType && other is _$ChatInitialImpl && const DeepCollectionEquality() - .equals(other._typingUsers, _typingUsers)); + .equals(other._typingUsers, _typingUsers) && + (identical(other.lastUpdate, lastUpdate) || + other.lastUpdate == lastUpdate)); } @override - int get hashCode => Object.hash( - runtimeType, const DeepCollectionEquality().hash(_typingUsers)); + int get hashCode => Object.hash(runtimeType, + const DeepCollectionEquality().hash(_typingUsers), lastUpdate); @JsonKey(ignore: true) @override @@ -214,62 +246,78 @@ class _$ChatInitialImpl implements ChatInitial { @override @optionalTypeArgs TResult when({ - required TResult Function(Map> typingUsers) initial, - required TResult Function(Map> typingUsers) loading, required TResult Function( - List chats, Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) + initial, + required TResult Function( + Map> typingUsers, DateTime? lastUpdate) + loading, + required TResult Function(List chats, + Map> typingUsers, DateTime? lastUpdate) chatsLoaded, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) chatSelected, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) messagesLoaded, - required TResult Function( - String message, Map> typingUsers) + required TResult Function(String message, + Map> typingUsers, DateTime? lastUpdate) error, }) { - return initial(typingUsers); + return initial(typingUsers, lastUpdate); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(Map> typingUsers)? initial, - TResult? Function(Map> typingUsers)? loading, - TResult? Function(List chats, Map> typingUsers)? + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult? Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult? Function(String message, Map> typingUsers)? + TResult? Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, }) { - return initial?.call(typingUsers); + return initial?.call(typingUsers, lastUpdate); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(Map> typingUsers)? initial, - TResult Function(Map> typingUsers)? loading, - TResult Function(List chats, Map> typingUsers)? + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult Function(String message, Map> typingUsers)? + TResult Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, required TResult orElse(), }) { if (initial != null) { - return initial(typingUsers); + return initial(typingUsers, lastUpdate); } return orElse(); } @@ -319,12 +367,15 @@ class _$ChatInitialImpl implements ChatInitial { } abstract class ChatInitial implements ChatState { - const factory ChatInitial({final Map> typingUsers}) = - _$ChatInitialImpl; + const factory ChatInitial( + {final Map> typingUsers, + final DateTime? lastUpdate}) = _$ChatInitialImpl; @override Map> get typingUsers; @override + DateTime? get lastUpdate; + @override @JsonKey(ignore: true) _$$ChatInitialImplCopyWith<_$ChatInitialImpl> get copyWith => throw _privateConstructorUsedError; @@ -338,7 +389,7 @@ abstract class _$$ChatLoadingImplCopyWith<$Res> __$$ChatLoadingImplCopyWithImpl<$Res>; @override @useResult - $Res call({Map> typingUsers}); + $Res call({Map> typingUsers, DateTime? lastUpdate}); } /// @nodoc @@ -353,12 +404,17 @@ class __$$ChatLoadingImplCopyWithImpl<$Res> @override $Res call({ Object? typingUsers = null, + Object? lastUpdate = freezed, }) { return _then(_$ChatLoadingImpl( typingUsers: null == typingUsers ? _value._typingUsers : typingUsers // ignore: cast_nullable_to_non_nullable as Map>, + lastUpdate: freezed == lastUpdate + ? _value.lastUpdate + : lastUpdate // ignore: cast_nullable_to_non_nullable + as DateTime?, )); } } @@ -367,7 +423,7 @@ class __$$ChatLoadingImplCopyWithImpl<$Res> class _$ChatLoadingImpl implements ChatLoading { const _$ChatLoadingImpl( - {final Map> typingUsers = const {}}) + {final Map> typingUsers = const {}, this.lastUpdate}) : _typingUsers = typingUsers; final Map> _typingUsers; @@ -379,9 +435,12 @@ class _$ChatLoadingImpl implements ChatLoading { return EqualUnmodifiableMapView(_typingUsers); } + @override + final DateTime? lastUpdate; + @override String toString() { - return 'ChatState.loading(typingUsers: $typingUsers)'; + return 'ChatState.loading(typingUsers: $typingUsers, lastUpdate: $lastUpdate)'; } @override @@ -390,12 +449,14 @@ class _$ChatLoadingImpl implements ChatLoading { (other.runtimeType == runtimeType && other is _$ChatLoadingImpl && const DeepCollectionEquality() - .equals(other._typingUsers, _typingUsers)); + .equals(other._typingUsers, _typingUsers) && + (identical(other.lastUpdate, lastUpdate) || + other.lastUpdate == lastUpdate)); } @override - int get hashCode => Object.hash( - runtimeType, const DeepCollectionEquality().hash(_typingUsers)); + int get hashCode => Object.hash(runtimeType, + const DeepCollectionEquality().hash(_typingUsers), lastUpdate); @JsonKey(ignore: true) @override @@ -406,62 +467,78 @@ class _$ChatLoadingImpl implements ChatLoading { @override @optionalTypeArgs TResult when({ - required TResult Function(Map> typingUsers) initial, - required TResult Function(Map> typingUsers) loading, required TResult Function( - List chats, Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) + initial, + required TResult Function( + Map> typingUsers, DateTime? lastUpdate) + loading, + required TResult Function(List chats, + Map> typingUsers, DateTime? lastUpdate) chatsLoaded, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) chatSelected, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) messagesLoaded, - required TResult Function( - String message, Map> typingUsers) + required TResult Function(String message, + Map> typingUsers, DateTime? lastUpdate) error, }) { - return loading(typingUsers); + return loading(typingUsers, lastUpdate); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(Map> typingUsers)? initial, - TResult? Function(Map> typingUsers)? loading, - TResult? Function(List chats, Map> typingUsers)? + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult? Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult? Function(String message, Map> typingUsers)? + TResult? Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, }) { - return loading?.call(typingUsers); + return loading?.call(typingUsers, lastUpdate); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(Map> typingUsers)? initial, - TResult Function(Map> typingUsers)? loading, - TResult Function(List chats, Map> typingUsers)? + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult Function(String message, Map> typingUsers)? + TResult Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, required TResult orElse(), }) { if (loading != null) { - return loading(typingUsers); + return loading(typingUsers, lastUpdate); } return orElse(); } @@ -511,12 +588,15 @@ class _$ChatLoadingImpl implements ChatLoading { } abstract class ChatLoading implements ChatState { - const factory ChatLoading({final Map> typingUsers}) = - _$ChatLoadingImpl; + const factory ChatLoading( + {final Map> typingUsers, + final DateTime? lastUpdate}) = _$ChatLoadingImpl; @override Map> get typingUsers; @override + DateTime? get lastUpdate; + @override @JsonKey(ignore: true) _$$ChatLoadingImplCopyWith<_$ChatLoadingImpl> get copyWith => throw _privateConstructorUsedError; @@ -530,7 +610,10 @@ abstract class _$$ChatsLoadedImplCopyWith<$Res> __$$ChatsLoadedImplCopyWithImpl<$Res>; @override @useResult - $Res call({List chats, Map> typingUsers}); + $Res call( + {List chats, + Map> typingUsers, + DateTime? lastUpdate}); } /// @nodoc @@ -546,6 +629,7 @@ class __$$ChatsLoadedImplCopyWithImpl<$Res> $Res call({ Object? chats = null, Object? typingUsers = null, + Object? lastUpdate = freezed, }) { return _then(_$ChatsLoadedImpl( null == chats @@ -556,6 +640,10 @@ class __$$ChatsLoadedImplCopyWithImpl<$Res> ? _value._typingUsers : typingUsers // ignore: cast_nullable_to_non_nullable as Map>, + lastUpdate: freezed == lastUpdate + ? _value.lastUpdate + : lastUpdate // ignore: cast_nullable_to_non_nullable + as DateTime?, )); } } @@ -564,7 +652,7 @@ class __$$ChatsLoadedImplCopyWithImpl<$Res> class _$ChatsLoadedImpl implements _ChatsLoaded { const _$ChatsLoadedImpl(final List chats, - {final Map> typingUsers = const {}}) + {final Map> typingUsers = const {}, this.lastUpdate}) : _chats = chats, _typingUsers = typingUsers; @@ -585,9 +673,12 @@ class _$ChatsLoadedImpl implements _ChatsLoaded { return EqualUnmodifiableMapView(_typingUsers); } + @override + final DateTime? lastUpdate; + @override String toString() { - return 'ChatState.chatsLoaded(chats: $chats, typingUsers: $typingUsers)'; + return 'ChatState.chatsLoaded(chats: $chats, typingUsers: $typingUsers, lastUpdate: $lastUpdate)'; } @override @@ -597,14 +688,17 @@ class _$ChatsLoadedImpl implements _ChatsLoaded { other is _$ChatsLoadedImpl && const DeepCollectionEquality().equals(other._chats, _chats) && const DeepCollectionEquality() - .equals(other._typingUsers, _typingUsers)); + .equals(other._typingUsers, _typingUsers) && + (identical(other.lastUpdate, lastUpdate) || + other.lastUpdate == lastUpdate)); } @override int get hashCode => Object.hash( runtimeType, const DeepCollectionEquality().hash(_chats), - const DeepCollectionEquality().hash(_typingUsers)); + const DeepCollectionEquality().hash(_typingUsers), + lastUpdate); @JsonKey(ignore: true) @override @@ -615,62 +709,78 @@ class _$ChatsLoadedImpl implements _ChatsLoaded { @override @optionalTypeArgs TResult when({ - required TResult Function(Map> typingUsers) initial, - required TResult Function(Map> typingUsers) loading, required TResult Function( - List chats, Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) + initial, + required TResult Function( + Map> typingUsers, DateTime? lastUpdate) + loading, + required TResult Function(List chats, + Map> typingUsers, DateTime? lastUpdate) chatsLoaded, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) chatSelected, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) messagesLoaded, - required TResult Function( - String message, Map> typingUsers) + required TResult Function(String message, + Map> typingUsers, DateTime? lastUpdate) error, }) { - return chatsLoaded(chats, typingUsers); + return chatsLoaded(chats, typingUsers, lastUpdate); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(Map> typingUsers)? initial, - TResult? Function(Map> typingUsers)? loading, - TResult? Function(List chats, Map> typingUsers)? + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult? Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult? Function(String message, Map> typingUsers)? + TResult? Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, }) { - return chatsLoaded?.call(chats, typingUsers); + return chatsLoaded?.call(chats, typingUsers, lastUpdate); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(Map> typingUsers)? initial, - TResult Function(Map> typingUsers)? loading, - TResult Function(List chats, Map> typingUsers)? + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult Function(String message, Map> typingUsers)? + TResult Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, required TResult orElse(), }) { if (chatsLoaded != null) { - return chatsLoaded(chats, typingUsers); + return chatsLoaded(chats, typingUsers, lastUpdate); } return orElse(); } @@ -721,12 +831,15 @@ class _$ChatsLoadedImpl implements _ChatsLoaded { abstract class _ChatsLoaded implements ChatState { const factory _ChatsLoaded(final List chats, - {final Map> typingUsers}) = _$ChatsLoadedImpl; + {final Map> typingUsers, + final DateTime? lastUpdate}) = _$ChatsLoadedImpl; List get chats; @override Map> get typingUsers; @override + DateTime? get lastUpdate; + @override @JsonKey(ignore: true) _$$ChatsLoadedImplCopyWith<_$ChatsLoadedImpl> get copyWith => throw _privateConstructorUsedError; @@ -743,7 +856,8 @@ abstract class _$$ChatSelectedImplCopyWith<$Res> $Res call( {Chat chat, List messages, - Map> typingUsers}); + Map> typingUsers, + DateTime? lastUpdate}); $ChatCopyWith<$Res> get chat; } @@ -762,6 +876,7 @@ class __$$ChatSelectedImplCopyWithImpl<$Res> Object? chat = null, Object? messages = null, Object? typingUsers = null, + Object? lastUpdate = freezed, }) { return _then(_$ChatSelectedImpl( null == chat @@ -776,6 +891,10 @@ class __$$ChatSelectedImplCopyWithImpl<$Res> ? _value._typingUsers : typingUsers // ignore: cast_nullable_to_non_nullable as Map>, + lastUpdate: freezed == lastUpdate + ? _value.lastUpdate + : lastUpdate // ignore: cast_nullable_to_non_nullable + as DateTime?, )); } @@ -792,7 +911,7 @@ class __$$ChatSelectedImplCopyWithImpl<$Res> class _$ChatSelectedImpl implements _ChatSelected { const _$ChatSelectedImpl(this.chat, final List messages, - {final Map> typingUsers = const {}}) + {final Map> typingUsers = const {}, this.lastUpdate}) : _messages = messages, _typingUsers = typingUsers; @@ -815,9 +934,12 @@ class _$ChatSelectedImpl implements _ChatSelected { return EqualUnmodifiableMapView(_typingUsers); } + @override + final DateTime? lastUpdate; + @override String toString() { - return 'ChatState.chatSelected(chat: $chat, messages: $messages, typingUsers: $typingUsers)'; + return 'ChatState.chatSelected(chat: $chat, messages: $messages, typingUsers: $typingUsers, lastUpdate: $lastUpdate)'; } @override @@ -828,7 +950,9 @@ class _$ChatSelectedImpl implements _ChatSelected { (identical(other.chat, chat) || other.chat == chat) && const DeepCollectionEquality().equals(other._messages, _messages) && const DeepCollectionEquality() - .equals(other._typingUsers, _typingUsers)); + .equals(other._typingUsers, _typingUsers) && + (identical(other.lastUpdate, lastUpdate) || + other.lastUpdate == lastUpdate)); } @override @@ -836,7 +960,8 @@ class _$ChatSelectedImpl implements _ChatSelected { runtimeType, chat, const DeepCollectionEquality().hash(_messages), - const DeepCollectionEquality().hash(_typingUsers)); + const DeepCollectionEquality().hash(_typingUsers), + lastUpdate); @JsonKey(ignore: true) @override @@ -847,62 +972,78 @@ class _$ChatSelectedImpl implements _ChatSelected { @override @optionalTypeArgs TResult when({ - required TResult Function(Map> typingUsers) initial, - required TResult Function(Map> typingUsers) loading, required TResult Function( - List chats, Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) + initial, + required TResult Function( + Map> typingUsers, DateTime? lastUpdate) + loading, + required TResult Function(List chats, + Map> typingUsers, DateTime? lastUpdate) chatsLoaded, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) chatSelected, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) messagesLoaded, - required TResult Function( - String message, Map> typingUsers) + required TResult Function(String message, + Map> typingUsers, DateTime? lastUpdate) error, }) { - return chatSelected(chat, messages, typingUsers); + return chatSelected(chat, messages, typingUsers, lastUpdate); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(Map> typingUsers)? initial, - TResult? Function(Map> typingUsers)? loading, - TResult? Function(List chats, Map> typingUsers)? + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult? Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult? Function(String message, Map> typingUsers)? + TResult? Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, }) { - return chatSelected?.call(chat, messages, typingUsers); + return chatSelected?.call(chat, messages, typingUsers, lastUpdate); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(Map> typingUsers)? initial, - TResult Function(Map> typingUsers)? loading, - TResult Function(List chats, Map> typingUsers)? + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult Function(String message, Map> typingUsers)? + TResult Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, required TResult orElse(), }) { if (chatSelected != null) { - return chatSelected(chat, messages, typingUsers); + return chatSelected(chat, messages, typingUsers, lastUpdate); } return orElse(); } @@ -953,13 +1094,16 @@ class _$ChatSelectedImpl implements _ChatSelected { abstract class _ChatSelected implements ChatState { const factory _ChatSelected(final Chat chat, final List messages, - {final Map> typingUsers}) = _$ChatSelectedImpl; + {final Map> typingUsers, + final DateTime? lastUpdate}) = _$ChatSelectedImpl; Chat get chat; List get messages; @override Map> get typingUsers; @override + DateTime? get lastUpdate; + @override @JsonKey(ignore: true) _$$ChatSelectedImplCopyWith<_$ChatSelectedImpl> get copyWith => throw _privateConstructorUsedError; @@ -976,7 +1120,8 @@ abstract class _$$MessagesLoadedImplCopyWith<$Res> $Res call( {Chat chat, List messages, - Map> typingUsers}); + Map> typingUsers, + DateTime? lastUpdate}); $ChatCopyWith<$Res> get chat; } @@ -995,6 +1140,7 @@ class __$$MessagesLoadedImplCopyWithImpl<$Res> Object? chat = null, Object? messages = null, Object? typingUsers = null, + Object? lastUpdate = freezed, }) { return _then(_$MessagesLoadedImpl( null == chat @@ -1009,6 +1155,10 @@ class __$$MessagesLoadedImplCopyWithImpl<$Res> ? _value._typingUsers : typingUsers // ignore: cast_nullable_to_non_nullable as Map>, + lastUpdate: freezed == lastUpdate + ? _value.lastUpdate + : lastUpdate // ignore: cast_nullable_to_non_nullable + as DateTime?, )); } @@ -1025,7 +1175,7 @@ class __$$MessagesLoadedImplCopyWithImpl<$Res> class _$MessagesLoadedImpl implements _MessagesLoaded { const _$MessagesLoadedImpl(this.chat, final List messages, - {final Map> typingUsers = const {}}) + {final Map> typingUsers = const {}, this.lastUpdate}) : _messages = messages, _typingUsers = typingUsers; @@ -1048,9 +1198,12 @@ class _$MessagesLoadedImpl implements _MessagesLoaded { return EqualUnmodifiableMapView(_typingUsers); } + @override + final DateTime? lastUpdate; + @override String toString() { - return 'ChatState.messagesLoaded(chat: $chat, messages: $messages, typingUsers: $typingUsers)'; + return 'ChatState.messagesLoaded(chat: $chat, messages: $messages, typingUsers: $typingUsers, lastUpdate: $lastUpdate)'; } @override @@ -1061,7 +1214,9 @@ class _$MessagesLoadedImpl implements _MessagesLoaded { (identical(other.chat, chat) || other.chat == chat) && const DeepCollectionEquality().equals(other._messages, _messages) && const DeepCollectionEquality() - .equals(other._typingUsers, _typingUsers)); + .equals(other._typingUsers, _typingUsers) && + (identical(other.lastUpdate, lastUpdate) || + other.lastUpdate == lastUpdate)); } @override @@ -1069,7 +1224,8 @@ class _$MessagesLoadedImpl implements _MessagesLoaded { runtimeType, chat, const DeepCollectionEquality().hash(_messages), - const DeepCollectionEquality().hash(_typingUsers)); + const DeepCollectionEquality().hash(_typingUsers), + lastUpdate); @JsonKey(ignore: true) @override @@ -1081,62 +1237,78 @@ class _$MessagesLoadedImpl implements _MessagesLoaded { @override @optionalTypeArgs TResult when({ - required TResult Function(Map> typingUsers) initial, - required TResult Function(Map> typingUsers) loading, required TResult Function( - List chats, Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) + initial, + required TResult Function( + Map> typingUsers, DateTime? lastUpdate) + loading, + required TResult Function(List chats, + Map> typingUsers, DateTime? lastUpdate) chatsLoaded, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) chatSelected, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) messagesLoaded, - required TResult Function( - String message, Map> typingUsers) + required TResult Function(String message, + Map> typingUsers, DateTime? lastUpdate) error, }) { - return messagesLoaded(chat, messages, typingUsers); + return messagesLoaded(chat, messages, typingUsers, lastUpdate); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(Map> typingUsers)? initial, - TResult? Function(Map> typingUsers)? loading, - TResult? Function(List chats, Map> typingUsers)? + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult? Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult? Function(String message, Map> typingUsers)? + TResult? Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, }) { - return messagesLoaded?.call(chat, messages, typingUsers); + return messagesLoaded?.call(chat, messages, typingUsers, lastUpdate); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(Map> typingUsers)? initial, - TResult Function(Map> typingUsers)? loading, - TResult Function(List chats, Map> typingUsers)? + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult Function(String message, Map> typingUsers)? + TResult Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, required TResult orElse(), }) { if (messagesLoaded != null) { - return messagesLoaded(chat, messages, typingUsers); + return messagesLoaded(chat, messages, typingUsers, lastUpdate); } return orElse(); } @@ -1187,13 +1359,16 @@ class _$MessagesLoadedImpl implements _MessagesLoaded { abstract class _MessagesLoaded implements ChatState { const factory _MessagesLoaded(final Chat chat, final List messages, - {final Map> typingUsers}) = _$MessagesLoadedImpl; + {final Map> typingUsers, + final DateTime? lastUpdate}) = _$MessagesLoadedImpl; Chat get chat; List get messages; @override Map> get typingUsers; @override + DateTime? get lastUpdate; + @override @JsonKey(ignore: true) _$$MessagesLoadedImplCopyWith<_$MessagesLoadedImpl> get copyWith => throw _privateConstructorUsedError; @@ -1207,7 +1382,10 @@ abstract class _$$ChatErrorImplCopyWith<$Res> __$$ChatErrorImplCopyWithImpl<$Res>; @override @useResult - $Res call({String message, Map> typingUsers}); + $Res call( + {String message, + Map> typingUsers, + DateTime? lastUpdate}); } /// @nodoc @@ -1223,6 +1401,7 @@ class __$$ChatErrorImplCopyWithImpl<$Res> $Res call({ Object? message = null, Object? typingUsers = null, + Object? lastUpdate = freezed, }) { return _then(_$ChatErrorImpl( null == message @@ -1233,6 +1412,10 @@ class __$$ChatErrorImplCopyWithImpl<$Res> ? _value._typingUsers : typingUsers // ignore: cast_nullable_to_non_nullable as Map>, + lastUpdate: freezed == lastUpdate + ? _value.lastUpdate + : lastUpdate // ignore: cast_nullable_to_non_nullable + as DateTime?, )); } } @@ -1241,7 +1424,7 @@ class __$$ChatErrorImplCopyWithImpl<$Res> class _$ChatErrorImpl implements ChatError { const _$ChatErrorImpl(this.message, - {final Map> typingUsers = const {}}) + {final Map> typingUsers = const {}, this.lastUpdate}) : _typingUsers = typingUsers; @override @@ -1255,9 +1438,12 @@ class _$ChatErrorImpl implements ChatError { return EqualUnmodifiableMapView(_typingUsers); } + @override + final DateTime? lastUpdate; + @override String toString() { - return 'ChatState.error(message: $message, typingUsers: $typingUsers)'; + return 'ChatState.error(message: $message, typingUsers: $typingUsers, lastUpdate: $lastUpdate)'; } @override @@ -1267,12 +1453,14 @@ class _$ChatErrorImpl implements ChatError { other is _$ChatErrorImpl && (identical(other.message, message) || other.message == message) && const DeepCollectionEquality() - .equals(other._typingUsers, _typingUsers)); + .equals(other._typingUsers, _typingUsers) && + (identical(other.lastUpdate, lastUpdate) || + other.lastUpdate == lastUpdate)); } @override - int get hashCode => Object.hash( - runtimeType, message, const DeepCollectionEquality().hash(_typingUsers)); + int get hashCode => Object.hash(runtimeType, message, + const DeepCollectionEquality().hash(_typingUsers), lastUpdate); @JsonKey(ignore: true) @override @@ -1283,62 +1471,78 @@ class _$ChatErrorImpl implements ChatError { @override @optionalTypeArgs TResult when({ - required TResult Function(Map> typingUsers) initial, - required TResult Function(Map> typingUsers) loading, required TResult Function( - List chats, Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) + initial, + required TResult Function( + Map> typingUsers, DateTime? lastUpdate) + loading, + required TResult Function(List chats, + Map> typingUsers, DateTime? lastUpdate) chatsLoaded, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) chatSelected, required TResult Function(Chat chat, List messages, - Map> typingUsers) + Map> typingUsers, DateTime? lastUpdate) messagesLoaded, - required TResult Function( - String message, Map> typingUsers) + required TResult Function(String message, + Map> typingUsers, DateTime? lastUpdate) error, }) { - return error(message, typingUsers); + return error(message, typingUsers, lastUpdate); } @override @optionalTypeArgs TResult? whenOrNull({ - TResult? Function(Map> typingUsers)? initial, - TResult? Function(Map> typingUsers)? loading, - TResult? Function(List chats, Map> typingUsers)? + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult? Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult? Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult? Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult? Function(String message, Map> typingUsers)? + TResult? Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, }) { - return error?.call(message, typingUsers); + return error?.call(message, typingUsers, lastUpdate); } @override @optionalTypeArgs TResult maybeWhen({ - TResult Function(Map> typingUsers)? initial, - TResult Function(Map> typingUsers)? loading, - TResult Function(List chats, Map> typingUsers)? + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + initial, + TResult Function( + Map> typingUsers, DateTime? lastUpdate)? + loading, + TResult Function(List chats, Map> typingUsers, + DateTime? lastUpdate)? chatsLoaded, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? chatSelected, TResult Function(Chat chat, List messages, - Map> typingUsers)? + Map> typingUsers, DateTime? lastUpdate)? messagesLoaded, - TResult Function(String message, Map> typingUsers)? + TResult Function(String message, Map> typingUsers, + DateTime? lastUpdate)? error, required TResult orElse(), }) { if (error != null) { - return error(message, typingUsers); + return error(message, typingUsers, lastUpdate); } return orElse(); } @@ -1389,12 +1593,15 @@ class _$ChatErrorImpl implements ChatError { abstract class ChatError implements ChatState { const factory ChatError(final String message, - {final Map> typingUsers}) = _$ChatErrorImpl; + {final Map> typingUsers, + final DateTime? lastUpdate}) = _$ChatErrorImpl; String get message; @override Map> get typingUsers; @override + DateTime? get lastUpdate; + @override @JsonKey(ignore: true) _$$ChatErrorImplCopyWith<_$ChatErrorImpl> get copyWith => throw _privateConstructorUsedError; diff --git a/client-mobile/lib/features/chat/presentation/pages/chat_detail_page.dart b/client-mobile/lib/features/chat/presentation/pages/chat_detail_page.dart index dcac956..f7eb7cb 100644 --- a/client-mobile/lib/features/chat/presentation/pages/chat_detail_page.dart +++ b/client-mobile/lib/features/chat/presentation/pages/chat_detail_page.dart @@ -41,8 +41,8 @@ class _ChatDetailPageState extends State { title: BlocBuilder( builder: (context, state) { final currentChat = state.maybeWhen( - chatSelected: (chat, _, __) => chat, - messagesLoaded: (chat, _, __) => chat, + chatSelected: (chat, messages, typingUsers, lastUpdate) => chat, + messagesLoaded: (chat, messages, typingUsers, lastUpdate) => chat, orElse: () => widget.chat, ); return Column( @@ -65,10 +65,10 @@ class _ChatDetailPageState extends State { child: BlocBuilder( builder: (context, state) { return state.maybeWhen( - chatSelected: (_, messages, __) => _buildMessageList(messages), - messagesLoaded: (_, messages, __) => _buildMessageList(messages), - loading: (_) => const Center(child: CircularProgressIndicator()), - error: (msg, _) => Center(child: Text('Ошибка: $msg')), + chatSelected: (chat, messages, typingUsers, lastUpdate) => _buildMessageList(messages), + messagesLoaded: (chat, messages, typingUsers, lastUpdate) => _buildMessageList(messages), + loading: (typingUsers, lastUpdate) => const Center(child: CircularProgressIndicator()), + error: (msg, typingUsers, lastUpdate) => Center(child: Text('Ошибка: $msg')), orElse: () => const Center(child: Text('Начните общение')), ); }, @@ -124,17 +124,46 @@ class _ChatDetailPageState extends State { ], ); } else if (otherMember.lastSeen != null) { - final lastSeen = otherMember.lastSeen!.toLocal(); - final timeStr = DateFormat.Hm(locale).format(lastSeen); - final dateStr = _formatDate(lastSeen, locale); return Text( - l10n.lastSeen(dateStr, timeStr), + _formatLastSeen(otherMember.lastSeen!, l10n, locale), style: const TextStyle(fontSize: 12, color: Colors.white70, fontWeight: FontWeight.normal), ); } return const SizedBox.shrink(); } + String _formatLastSeen(DateTime utcDate, AppLocalizations l10n, String locale) { + final lastSeen = utcDate.toLocal(); + final now = DateTime.now(); + final difference = now.difference(lastSeen); + final timeStr = DateFormat.Hm(locale).format(lastSeen); + + // Case 1: Same day (within 24h of NOW, but specifically checking calendar day is better for "yesterday") + // Let's use difference for "relative" and calendar days for "yesterday/day before" + + final today = DateTime(now.year, now.month, now.day); + final seenDay = DateTime(lastSeen.year, lastSeen.month, lastSeen.day); + final dayDiff = today.difference(seenDay).inDays; + + if (dayDiff == 0) { + // Same calendar day + if (difference.inHours > 0) { + return l10n.lastSeenRelative(difference.inHours, difference.inMinutes % 60); + } else if (difference.inMinutes > 0) { + return l10n.lastSeenRelativeMinutes(difference.inMinutes); + } else { + return l10n.lastSeenJustNow; + } + } else if (dayDiff == 1) { + return l10n.lastSeenYesterday(timeStr); + } else if (dayDiff == 2) { + return l10n.lastSeenDayBeforeYesterday(timeStr); + } else { + final dateStr = DateFormat.MMMMd(locale).format(lastSeen); + return l10n.lastSeen(dateStr, timeStr); + } + } + String _formatDate(DateTime date, String locale) { final now = DateTime.now(); final localDate = date.toLocal(); @@ -152,6 +181,20 @@ class _ChatDetailPageState extends State { return Center(child: Text(l10n.noMessages)); } + // Mark as read logic + WidgetsBinding.instance.addPostFrameCallback((_) { + final unreadFromOthers = messages.where((m) => + m.senderId != widget.currentUserId && + m.status != MessageStatus.read + ).toList(); + + if (unreadFromOthers.isNotEmpty) { + // Find the message with the highest sequenceId to mark everything up to it as read + final latest = unreadFromOthers.reduce((a, b) => a.sequenceId > b.sequenceId ? a : b); + context.read().add(ChatEvent.markAsRead(latest.chatId, latest.id, latest.sequenceId)); + } + }); + final List items = []; for (int i = 0; i < messages.length; i++) { final message = messages[i]; @@ -233,14 +276,23 @@ class _ChatDetailPageState extends State { style: const TextStyle(color: Colors.black87, fontSize: 16), ), const SizedBox(height: 2), - if (message.createdAt != null) - Text( - DateFormat.Hm(locale).format(message.createdAt!.toLocal()), - style: const TextStyle( - fontSize: 10, - color: Colors.black45, - ), - ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (message.createdAt != null) + Text( + DateFormat.Hm(locale).format(message.createdAt!.toLocal()), + style: const TextStyle( + fontSize: 10, + color: Colors.black45, + ), + ), + if (isMe) ...[ + const SizedBox(width: 4), + _buildStatusIcon(message), + ], + ], + ), ], ), ), @@ -249,6 +301,19 @@ class _ChatDetailPageState extends State { ); } + Widget _buildStatusIcon(Message message) { + switch (message.status) { + case MessageStatus.sending: + return const Icon(Icons.access_time, size: 12, color: Colors.black45); + case MessageStatus.delivered: + return const Icon(Icons.check, size: 12, color: Colors.black45); + case MessageStatus.read: + return const Icon(Icons.done_all, size: 12, color: Colors.blue); + case MessageStatus.error: + return const Icon(Icons.error_outline, size: 12, color: Colors.red); + } + } + Widget _buildMessageInput(Chat chat) { return Container( padding: const EdgeInsets.all(8), diff --git a/client-mobile/lib/features/chat/presentation/pages/chats_page.dart b/client-mobile/lib/features/chat/presentation/pages/chats_page.dart index 4fadf69..82bfd07 100644 --- a/client-mobile/lib/features/chat/presentation/pages/chats_page.dart +++ b/client-mobile/lib/features/chat/presentation/pages/chats_page.dart @@ -49,20 +49,13 @@ class _ChatsPageState extends State { body: BlocConsumer( listener: (context, state) { state.whenOrNull( - chatSelected: (chat, _, __) { + chatSelected: (chat, messages, typingUsers, lastUpdate) { if (_isNavigating) return; - // Extra safety: check if we are already on chat_detail - bool isAlreadyOnDetail = false; - Navigator.popUntil(context, (route) { - if (route.settings.name == 'chat_detail') { - isAlreadyOnDetail = true; - } - return true; - }); - - if (isAlreadyOnDetail) return; - + // Only navigate if we are currently on the ChatsPage + final isCurrent = ModalRoute.of(context)?.isCurrent ?? false; + if (!isCurrent) return; + _isNavigating = true; final authState = context.read().state; @@ -91,9 +84,9 @@ class _ChatsPageState extends State { }, builder: (context, state) { return state.maybeWhen( - loading: (_) => const Center(child: CircularProgressIndicator()), - chatsLoaded: (chats, _) => _buildChatList(chats, l10n), - error: (message, _) => Center(child: Text('${l10n.error}: $message')), + loading: (typingUsers, lastUpdate) => const Center(child: CircularProgressIndicator()), + chatsLoaded: (chats, typingUsers, lastUpdate) => _buildChatList(chats, l10n), + error: (message, typingUsers, lastUpdate) => Center(child: Text('${l10n.error}: $message')), orElse: () => const Center(child: CircularProgressIndicator()), ); }, diff --git a/client-mobile/lib/l10n/app_localizations.dart b/client-mobile/lib/l10n/app_localizations.dart index d4b21b4..acc7c78 100644 --- a/client-mobile/lib/l10n/app_localizations.dart +++ b/client-mobile/lib/l10n/app_localizations.dart @@ -596,6 +596,36 @@ abstract class AppLocalizations { /// **'был(а) в сети {date} в {time}'** String lastSeen(Object date, Object time); + /// No description provided for @lastSeenRelative. + /// + /// In ru, this message translates to: + /// **'был(а) {hours} ч. {minutes} мин. назад'** + String lastSeenRelative(Object hours, Object minutes); + + /// No description provided for @lastSeenRelativeMinutes. + /// + /// In ru, this message translates to: + /// **'был(а) {minutes} мин. назад'** + String lastSeenRelativeMinutes(Object minutes); + + /// No description provided for @lastSeenJustNow. + /// + /// In ru, this message translates to: + /// **'был(а) только что'** + String get lastSeenJustNow; + + /// No description provided for @lastSeenYesterday. + /// + /// In ru, this message translates to: + /// **'был(а) вчера в {time}'** + String lastSeenYesterday(Object time); + + /// No description provided for @lastSeenDayBeforeYesterday. + /// + /// In ru, this message translates to: + /// **'был(а) позавчера в {time}'** + String lastSeenDayBeforeYesterday(Object time); + /// No description provided for @noMessages. /// /// In ru, this message translates to: diff --git a/client-mobile/lib/l10n/app_localizations_en.dart b/client-mobile/lib/l10n/app_localizations_en.dart index 7d50365..2eb6e2e 100644 --- a/client-mobile/lib/l10n/app_localizations_en.dart +++ b/client-mobile/lib/l10n/app_localizations_en.dart @@ -260,6 +260,29 @@ class AppLocalizationsEn extends AppLocalizations { return 'last seen $date at $time'; } + @override + String lastSeenRelative(Object hours, Object minutes) { + return 'last seen ${hours}h ${minutes}m ago'; + } + + @override + String lastSeenRelativeMinutes(Object minutes) { + return 'last seen ${minutes}m ago'; + } + + @override + String get lastSeenJustNow => 'last seen just now'; + + @override + String lastSeenYesterday(Object time) { + return 'last seen yesterday at $time'; + } + + @override + String lastSeenDayBeforeYesterday(Object time) { + return 'last seen day before yesterday at $time'; + } + @override String get noMessages => 'No messages yet'; diff --git a/client-mobile/lib/l10n/app_localizations_ru.dart b/client-mobile/lib/l10n/app_localizations_ru.dart index d9f7905..8e9379c 100644 --- a/client-mobile/lib/l10n/app_localizations_ru.dart +++ b/client-mobile/lib/l10n/app_localizations_ru.dart @@ -260,6 +260,29 @@ class AppLocalizationsRu extends AppLocalizations { return 'был(а) в сети $date в $time'; } + @override + String lastSeenRelative(Object hours, Object minutes) { + return 'был(а) $hours ч. $minutes мин. назад'; + } + + @override + String lastSeenRelativeMinutes(Object minutes) { + return 'был(а) $minutes мин. назад'; + } + + @override + String get lastSeenJustNow => 'был(а) только что'; + + @override + String lastSeenYesterday(Object time) { + return 'был(а) вчера в $time'; + } + + @override + String lastSeenDayBeforeYesterday(Object time) { + return 'был(а) позавчера в $time'; + } + @override String get noMessages => 'Сообщений пока нет';