forked from eatvio/eatvio_app
added unread messages and unread chats counters
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'chat_message_model.freezed.dart';
|
||||
@@ -10,7 +11,10 @@ class ChatMessageModel with _$ChatMessageModel {
|
||||
required String data,
|
||||
@JsonKey(name: 'media_data') required List<dynamic>? mediaData,
|
||||
@JsonKey(name: 'author_id') required int authorId,
|
||||
@JsonKey(name: 'updated_at') required String updatedAt,
|
||||
@JsonKey(name: 'updated_at', fromJson: parseDate) required DateTime updatedAt,
|
||||
@JsonKey(name: 'read_by_to_user', defaultValue: false) required bool isRead,
|
||||
@JsonKey(name: 'is_author_message_auth_user') required bool? isCurrentUserAuthor,
|
||||
@JsonKey(name: 'room_id') required String? roomId,
|
||||
}) = _ChatMessageModel;
|
||||
|
||||
factory ChatMessageModel.fromJson(Map<String, Object?> json) => _$ChatMessageModelFromJson(json);
|
||||
|
||||
@@ -26,8 +26,14 @@ mixin _$ChatMessageModel {
|
||||
List<dynamic>? get mediaData => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'author_id')
|
||||
int get authorId => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'updated_at')
|
||||
String get updatedAt => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'updated_at', fromJson: parseDate)
|
||||
DateTime get updatedAt => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'read_by_to_user', defaultValue: false)
|
||||
bool get isRead => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'is_author_message_auth_user')
|
||||
bool? get isCurrentUserAuthor => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'room_id')
|
||||
String? get roomId => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this ChatMessageModel to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@@ -50,7 +56,10 @@ abstract class $ChatMessageModelCopyWith<$Res> {
|
||||
String data,
|
||||
@JsonKey(name: 'media_data') List<dynamic>? mediaData,
|
||||
@JsonKey(name: 'author_id') int authorId,
|
||||
@JsonKey(name: 'updated_at') String updatedAt});
|
||||
@JsonKey(name: 'updated_at', fromJson: parseDate) DateTime updatedAt,
|
||||
@JsonKey(name: 'read_by_to_user', defaultValue: false) bool isRead,
|
||||
@JsonKey(name: 'is_author_message_auth_user') bool? isCurrentUserAuthor,
|
||||
@JsonKey(name: 'room_id') String? roomId});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -73,6 +82,9 @@ class _$ChatMessageModelCopyWithImpl<$Res, $Val extends ChatMessageModel>
|
||||
Object? mediaData = freezed,
|
||||
Object? authorId = null,
|
||||
Object? updatedAt = null,
|
||||
Object? isRead = null,
|
||||
Object? isCurrentUserAuthor = freezed,
|
||||
Object? roomId = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
id: null == id
|
||||
@@ -94,7 +106,19 @@ class _$ChatMessageModelCopyWithImpl<$Res, $Val extends ChatMessageModel>
|
||||
updatedAt: null == updatedAt
|
||||
? _value.updatedAt
|
||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
as DateTime,
|
||||
isRead: null == isRead
|
||||
? _value.isRead
|
||||
: isRead // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
isCurrentUserAuthor: freezed == isCurrentUserAuthor
|
||||
? _value.isCurrentUserAuthor
|
||||
: isCurrentUserAuthor // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
roomId: freezed == roomId
|
||||
? _value.roomId
|
||||
: roomId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
@@ -112,7 +136,10 @@ abstract class _$$ChatMessageModelImplCopyWith<$Res>
|
||||
String data,
|
||||
@JsonKey(name: 'media_data') List<dynamic>? mediaData,
|
||||
@JsonKey(name: 'author_id') int authorId,
|
||||
@JsonKey(name: 'updated_at') String updatedAt});
|
||||
@JsonKey(name: 'updated_at', fromJson: parseDate) DateTime updatedAt,
|
||||
@JsonKey(name: 'read_by_to_user', defaultValue: false) bool isRead,
|
||||
@JsonKey(name: 'is_author_message_auth_user') bool? isCurrentUserAuthor,
|
||||
@JsonKey(name: 'room_id') String? roomId});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -133,6 +160,9 @@ class __$$ChatMessageModelImplCopyWithImpl<$Res>
|
||||
Object? mediaData = freezed,
|
||||
Object? authorId = null,
|
||||
Object? updatedAt = null,
|
||||
Object? isRead = null,
|
||||
Object? isCurrentUserAuthor = freezed,
|
||||
Object? roomId = freezed,
|
||||
}) {
|
||||
return _then(_$ChatMessageModelImpl(
|
||||
id: null == id
|
||||
@@ -154,7 +184,19 @@ class __$$ChatMessageModelImplCopyWithImpl<$Res>
|
||||
updatedAt: null == updatedAt
|
||||
? _value.updatedAt
|
||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
as DateTime,
|
||||
isRead: null == isRead
|
||||
? _value.isRead
|
||||
: isRead // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
isCurrentUserAuthor: freezed == isCurrentUserAuthor
|
||||
? _value.isCurrentUserAuthor
|
||||
: isCurrentUserAuthor // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
roomId: freezed == roomId
|
||||
? _value.roomId
|
||||
: roomId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -167,7 +209,12 @@ class _$ChatMessageModelImpl implements _ChatMessageModel {
|
||||
required this.data,
|
||||
@JsonKey(name: 'media_data') required final List<dynamic>? mediaData,
|
||||
@JsonKey(name: 'author_id') required this.authorId,
|
||||
@JsonKey(name: 'updated_at') required this.updatedAt})
|
||||
@JsonKey(name: 'updated_at', fromJson: parseDate) required this.updatedAt,
|
||||
@JsonKey(name: 'read_by_to_user', defaultValue: false)
|
||||
required this.isRead,
|
||||
@JsonKey(name: 'is_author_message_auth_user')
|
||||
required this.isCurrentUserAuthor,
|
||||
@JsonKey(name: 'room_id') required this.roomId})
|
||||
: _mediaData = mediaData;
|
||||
|
||||
factory _$ChatMessageModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -192,12 +239,21 @@ class _$ChatMessageModelImpl implements _ChatMessageModel {
|
||||
@JsonKey(name: 'author_id')
|
||||
final int authorId;
|
||||
@override
|
||||
@JsonKey(name: 'updated_at')
|
||||
final String updatedAt;
|
||||
@JsonKey(name: 'updated_at', fromJson: parseDate)
|
||||
final DateTime updatedAt;
|
||||
@override
|
||||
@JsonKey(name: 'read_by_to_user', defaultValue: false)
|
||||
final bool isRead;
|
||||
@override
|
||||
@JsonKey(name: 'is_author_message_auth_user')
|
||||
final bool? isCurrentUserAuthor;
|
||||
@override
|
||||
@JsonKey(name: 'room_id')
|
||||
final String? roomId;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChatMessageModel(id: $id, data: $data, mediaData: $mediaData, authorId: $authorId, updatedAt: $updatedAt)';
|
||||
return 'ChatMessageModel(id: $id, data: $data, mediaData: $mediaData, authorId: $authorId, updatedAt: $updatedAt, isRead: $isRead, isCurrentUserAuthor: $isCurrentUserAuthor, roomId: $roomId)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -212,13 +268,25 @@ class _$ChatMessageModelImpl implements _ChatMessageModel {
|
||||
(identical(other.authorId, authorId) ||
|
||||
other.authorId == authorId) &&
|
||||
(identical(other.updatedAt, updatedAt) ||
|
||||
other.updatedAt == updatedAt));
|
||||
other.updatedAt == updatedAt) &&
|
||||
(identical(other.isRead, isRead) || other.isRead == isRead) &&
|
||||
(identical(other.isCurrentUserAuthor, isCurrentUserAuthor) ||
|
||||
other.isCurrentUserAuthor == isCurrentUserAuthor) &&
|
||||
(identical(other.roomId, roomId) || other.roomId == roomId));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, id, data,
|
||||
const DeepCollectionEquality().hash(_mediaData), authorId, updatedAt);
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
id,
|
||||
data,
|
||||
const DeepCollectionEquality().hash(_mediaData),
|
||||
authorId,
|
||||
updatedAt,
|
||||
isRead,
|
||||
isCurrentUserAuthor,
|
||||
roomId);
|
||||
|
||||
/// Create a copy of ChatMessageModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -243,7 +311,13 @@ abstract class _ChatMessageModel implements ChatMessageModel {
|
||||
required final String data,
|
||||
@JsonKey(name: 'media_data') required final List<dynamic>? mediaData,
|
||||
@JsonKey(name: 'author_id') required final int authorId,
|
||||
@JsonKey(name: 'updated_at') required final String updatedAt}) =
|
||||
@JsonKey(name: 'updated_at', fromJson: parseDate)
|
||||
required final DateTime updatedAt,
|
||||
@JsonKey(name: 'read_by_to_user', defaultValue: false)
|
||||
required final bool isRead,
|
||||
@JsonKey(name: 'is_author_message_auth_user')
|
||||
required final bool? isCurrentUserAuthor,
|
||||
@JsonKey(name: 'room_id') required final String? roomId}) =
|
||||
_$ChatMessageModelImpl;
|
||||
|
||||
factory _ChatMessageModel.fromJson(Map<String, dynamic> json) =
|
||||
@@ -260,8 +334,17 @@ abstract class _ChatMessageModel implements ChatMessageModel {
|
||||
@JsonKey(name: 'author_id')
|
||||
int get authorId;
|
||||
@override
|
||||
@JsonKey(name: 'updated_at')
|
||||
String get updatedAt;
|
||||
@JsonKey(name: 'updated_at', fromJson: parseDate)
|
||||
DateTime get updatedAt;
|
||||
@override
|
||||
@JsonKey(name: 'read_by_to_user', defaultValue: false)
|
||||
bool get isRead;
|
||||
@override
|
||||
@JsonKey(name: 'is_author_message_auth_user')
|
||||
bool? get isCurrentUserAuthor;
|
||||
@override
|
||||
@JsonKey(name: 'room_id')
|
||||
String? get roomId;
|
||||
|
||||
/// Create a copy of ChatMessageModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
|
||||
@@ -13,7 +13,10 @@ _$ChatMessageModelImpl _$$ChatMessageModelImplFromJson(
|
||||
data: json['data'] as String,
|
||||
mediaData: json['media_data'] as List<dynamic>?,
|
||||
authorId: (json['author_id'] as num).toInt(),
|
||||
updatedAt: json['updated_at'] as String,
|
||||
updatedAt: parseDate(json['updated_at'] as String),
|
||||
isRead: json['read_by_to_user'] as bool? ?? false,
|
||||
isCurrentUserAuthor: json['is_author_message_auth_user'] as bool?,
|
||||
roomId: json['room_id'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ChatMessageModelImplToJson(
|
||||
@@ -23,5 +26,8 @@ Map<String, dynamic> _$$ChatMessageModelImplToJson(
|
||||
'data': instance.data,
|
||||
'media_data': instance.mediaData,
|
||||
'author_id': instance.authorId,
|
||||
'updated_at': instance.updatedAt,
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'read_by_to_user': instance.isRead,
|
||||
'is_author_message_auth_user': instance.isCurrentUserAuthor,
|
||||
'room_id': instance.roomId,
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'chat_room_preview_model.freezed.dart';
|
||||
@@ -17,26 +18,19 @@ class ChatRoom with _$ChatRoom {
|
||||
const factory ChatRoom({
|
||||
@JsonKey(name: "id") required String id,
|
||||
@JsonKey(name: "room_name") required String roomName,
|
||||
@JsonKey(name: "last_message") required dynamic lastMessage,
|
||||
@JsonKey(name: "last_message", fromJson: parseLastMessage) required ChatMessageModel? lastMessage,
|
||||
@JsonKey(name: "users") required Users users,
|
||||
@JsonKey(name: "unread_messages_count") required int unreadMessagesCount,
|
||||
}) = _ChatRoom;
|
||||
|
||||
factory ChatRoom.fromJson(Map<String, dynamic> json) => _$ChatRoomFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class LastMessageClass with _$LastMessageClass {
|
||||
const factory LastMessageClass({
|
||||
@JsonKey(name: "id") required int id,
|
||||
@JsonKey(name: "data") required String data,
|
||||
@JsonKey(name: "media_data") required List<dynamic> mediaData,
|
||||
@JsonKey(name: "author_id") required int authorId,
|
||||
@JsonKey(name: "is_author_message_auth_user") required bool isAuthorMessageAuthUser,
|
||||
@JsonKey(name: "read_by_to_user") required bool readByToUser,
|
||||
@JsonKey(name: "updated_at") required DateTime updatedAt,
|
||||
}) = _LastMessageClass;
|
||||
|
||||
factory LastMessageClass.fromJson(Map<String, dynamic> json) => _$LastMessageClassFromJson(json);
|
||||
ChatMessageModel? parseLastMessage(dynamic json) {
|
||||
if (json is List) {
|
||||
return null;
|
||||
}
|
||||
return ChatMessageModel.fromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
|
||||
@@ -190,10 +190,12 @@ mixin _$ChatRoom {
|
||||
String get id => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "room_name")
|
||||
String get roomName => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "last_message")
|
||||
dynamic get lastMessage => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "last_message", fromJson: parseLastMessage)
|
||||
ChatMessageModel? get lastMessage => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "users")
|
||||
Users get users => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "unread_messages_count")
|
||||
int get unreadMessagesCount => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this ChatRoom to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@@ -213,9 +215,12 @@ abstract class $ChatRoomCopyWith<$Res> {
|
||||
$Res call(
|
||||
{@JsonKey(name: "id") String id,
|
||||
@JsonKey(name: "room_name") String roomName,
|
||||
@JsonKey(name: "last_message") dynamic lastMessage,
|
||||
@JsonKey(name: "users") Users users});
|
||||
@JsonKey(name: "last_message", fromJson: parseLastMessage)
|
||||
ChatMessageModel? lastMessage,
|
||||
@JsonKey(name: "users") Users users,
|
||||
@JsonKey(name: "unread_messages_count") int unreadMessagesCount});
|
||||
|
||||
$ChatMessageModelCopyWith<$Res>? get lastMessage;
|
||||
$UsersCopyWith<$Res> get users;
|
||||
}
|
||||
|
||||
@@ -238,6 +243,7 @@ class _$ChatRoomCopyWithImpl<$Res, $Val extends ChatRoom>
|
||||
Object? roomName = null,
|
||||
Object? lastMessage = freezed,
|
||||
Object? users = null,
|
||||
Object? unreadMessagesCount = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
id: null == id
|
||||
@@ -251,14 +257,32 @@ class _$ChatRoomCopyWithImpl<$Res, $Val extends ChatRoom>
|
||||
lastMessage: freezed == lastMessage
|
||||
? _value.lastMessage
|
||||
: lastMessage // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,
|
||||
as ChatMessageModel?,
|
||||
users: null == users
|
||||
? _value.users
|
||||
: users // ignore: cast_nullable_to_non_nullable
|
||||
as Users,
|
||||
unreadMessagesCount: null == unreadMessagesCount
|
||||
? _value.unreadMessagesCount
|
||||
: unreadMessagesCount // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
/// Create a copy of ChatRoom
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ChatMessageModelCopyWith<$Res>? get lastMessage {
|
||||
if (_value.lastMessage == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $ChatMessageModelCopyWith<$Res>(_value.lastMessage!, (value) {
|
||||
return _then(_value.copyWith(lastMessage: value) as $Val);
|
||||
});
|
||||
}
|
||||
|
||||
/// Create a copy of ChatRoom
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@@ -281,9 +305,13 @@ abstract class _$$ChatRoomImplCopyWith<$Res>
|
||||
$Res call(
|
||||
{@JsonKey(name: "id") String id,
|
||||
@JsonKey(name: "room_name") String roomName,
|
||||
@JsonKey(name: "last_message") dynamic lastMessage,
|
||||
@JsonKey(name: "users") Users users});
|
||||
@JsonKey(name: "last_message", fromJson: parseLastMessage)
|
||||
ChatMessageModel? lastMessage,
|
||||
@JsonKey(name: "users") Users users,
|
||||
@JsonKey(name: "unread_messages_count") int unreadMessagesCount});
|
||||
|
||||
@override
|
||||
$ChatMessageModelCopyWith<$Res>? get lastMessage;
|
||||
@override
|
||||
$UsersCopyWith<$Res> get users;
|
||||
}
|
||||
@@ -305,6 +333,7 @@ class __$$ChatRoomImplCopyWithImpl<$Res>
|
||||
Object? roomName = null,
|
||||
Object? lastMessage = freezed,
|
||||
Object? users = null,
|
||||
Object? unreadMessagesCount = null,
|
||||
}) {
|
||||
return _then(_$ChatRoomImpl(
|
||||
id: null == id
|
||||
@@ -318,11 +347,15 @@ class __$$ChatRoomImplCopyWithImpl<$Res>
|
||||
lastMessage: freezed == lastMessage
|
||||
? _value.lastMessage
|
||||
: lastMessage // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,
|
||||
as ChatMessageModel?,
|
||||
users: null == users
|
||||
? _value.users
|
||||
: users // ignore: cast_nullable_to_non_nullable
|
||||
as Users,
|
||||
unreadMessagesCount: null == unreadMessagesCount
|
||||
? _value.unreadMessagesCount
|
||||
: unreadMessagesCount // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -333,8 +366,11 @@ class _$ChatRoomImpl implements _ChatRoom {
|
||||
const _$ChatRoomImpl(
|
||||
{@JsonKey(name: "id") required this.id,
|
||||
@JsonKey(name: "room_name") required this.roomName,
|
||||
@JsonKey(name: "last_message") required this.lastMessage,
|
||||
@JsonKey(name: "users") required this.users});
|
||||
@JsonKey(name: "last_message", fromJson: parseLastMessage)
|
||||
required this.lastMessage,
|
||||
@JsonKey(name: "users") required this.users,
|
||||
@JsonKey(name: "unread_messages_count")
|
||||
required this.unreadMessagesCount});
|
||||
|
||||
factory _$ChatRoomImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$ChatRoomImplFromJson(json);
|
||||
@@ -346,15 +382,18 @@ class _$ChatRoomImpl implements _ChatRoom {
|
||||
@JsonKey(name: "room_name")
|
||||
final String roomName;
|
||||
@override
|
||||
@JsonKey(name: "last_message")
|
||||
final dynamic lastMessage;
|
||||
@JsonKey(name: "last_message", fromJson: parseLastMessage)
|
||||
final ChatMessageModel? lastMessage;
|
||||
@override
|
||||
@JsonKey(name: "users")
|
||||
final Users users;
|
||||
@override
|
||||
@JsonKey(name: "unread_messages_count")
|
||||
final int unreadMessagesCount;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChatRoom(id: $id, roomName: $roomName, lastMessage: $lastMessage, users: $users)';
|
||||
return 'ChatRoom(id: $id, roomName: $roomName, lastMessage: $lastMessage, users: $users, unreadMessagesCount: $unreadMessagesCount)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -365,15 +404,17 @@ class _$ChatRoomImpl implements _ChatRoom {
|
||||
(identical(other.id, id) || other.id == id) &&
|
||||
(identical(other.roomName, roomName) ||
|
||||
other.roomName == roomName) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.lastMessage, lastMessage) &&
|
||||
(identical(other.users, users) || other.users == users));
|
||||
(identical(other.lastMessage, lastMessage) ||
|
||||
other.lastMessage == lastMessage) &&
|
||||
(identical(other.users, users) || other.users == users) &&
|
||||
(identical(other.unreadMessagesCount, unreadMessagesCount) ||
|
||||
other.unreadMessagesCount == unreadMessagesCount));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, id, roomName,
|
||||
const DeepCollectionEquality().hash(lastMessage), users);
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, id, roomName, lastMessage, users, unreadMessagesCount);
|
||||
|
||||
/// Create a copy of ChatRoom
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -395,8 +436,11 @@ abstract class _ChatRoom implements ChatRoom {
|
||||
const factory _ChatRoom(
|
||||
{@JsonKey(name: "id") required final String id,
|
||||
@JsonKey(name: "room_name") required final String roomName,
|
||||
@JsonKey(name: "last_message") required final dynamic lastMessage,
|
||||
@JsonKey(name: "users") required final Users users}) = _$ChatRoomImpl;
|
||||
@JsonKey(name: "last_message", fromJson: parseLastMessage)
|
||||
required final ChatMessageModel? lastMessage,
|
||||
@JsonKey(name: "users") required final Users users,
|
||||
@JsonKey(name: "unread_messages_count")
|
||||
required final int unreadMessagesCount}) = _$ChatRoomImpl;
|
||||
|
||||
factory _ChatRoom.fromJson(Map<String, dynamic> json) =
|
||||
_$ChatRoomImpl.fromJson;
|
||||
@@ -408,11 +452,14 @@ abstract class _ChatRoom implements ChatRoom {
|
||||
@JsonKey(name: "room_name")
|
||||
String get roomName;
|
||||
@override
|
||||
@JsonKey(name: "last_message")
|
||||
dynamic get lastMessage;
|
||||
@JsonKey(name: "last_message", fromJson: parseLastMessage)
|
||||
ChatMessageModel? get lastMessage;
|
||||
@override
|
||||
@JsonKey(name: "users")
|
||||
Users get users;
|
||||
@override
|
||||
@JsonKey(name: "unread_messages_count")
|
||||
int get unreadMessagesCount;
|
||||
|
||||
/// Create a copy of ChatRoom
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -422,327 +469,6 @@ abstract class _ChatRoom implements ChatRoom {
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
LastMessageClass _$LastMessageClassFromJson(Map<String, dynamic> json) {
|
||||
return _LastMessageClass.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$LastMessageClass {
|
||||
@JsonKey(name: "id")
|
||||
int get id => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "data")
|
||||
String get data => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "media_data")
|
||||
List<dynamic> get mediaData => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "author_id")
|
||||
int get authorId => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "is_author_message_auth_user")
|
||||
bool get isAuthorMessageAuthUser => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "read_by_to_user")
|
||||
bool get readByToUser => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "updated_at")
|
||||
DateTime get updatedAt => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this LastMessageClass to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of LastMessageClass
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$LastMessageClassCopyWith<LastMessageClass> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $LastMessageClassCopyWith<$Res> {
|
||||
factory $LastMessageClassCopyWith(
|
||||
LastMessageClass value, $Res Function(LastMessageClass) then) =
|
||||
_$LastMessageClassCopyWithImpl<$Res, LastMessageClass>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{@JsonKey(name: "id") int id,
|
||||
@JsonKey(name: "data") String data,
|
||||
@JsonKey(name: "media_data") List<dynamic> mediaData,
|
||||
@JsonKey(name: "author_id") int authorId,
|
||||
@JsonKey(name: "is_author_message_auth_user")
|
||||
bool isAuthorMessageAuthUser,
|
||||
@JsonKey(name: "read_by_to_user") bool readByToUser,
|
||||
@JsonKey(name: "updated_at") DateTime updatedAt});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$LastMessageClassCopyWithImpl<$Res, $Val extends LastMessageClass>
|
||||
implements $LastMessageClassCopyWith<$Res> {
|
||||
_$LastMessageClassCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of LastMessageClass
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? id = null,
|
||||
Object? data = null,
|
||||
Object? mediaData = null,
|
||||
Object? authorId = null,
|
||||
Object? isAuthorMessageAuthUser = null,
|
||||
Object? readByToUser = null,
|
||||
Object? updatedAt = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
id: null == id
|
||||
? _value.id
|
||||
: id // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
data: null == data
|
||||
? _value.data
|
||||
: data // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
mediaData: null == mediaData
|
||||
? _value.mediaData
|
||||
: mediaData // ignore: cast_nullable_to_non_nullable
|
||||
as List<dynamic>,
|
||||
authorId: null == authorId
|
||||
? _value.authorId
|
||||
: authorId // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
isAuthorMessageAuthUser: null == isAuthorMessageAuthUser
|
||||
? _value.isAuthorMessageAuthUser
|
||||
: isAuthorMessageAuthUser // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
readByToUser: null == readByToUser
|
||||
? _value.readByToUser
|
||||
: readByToUser // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
updatedAt: null == updatedAt
|
||||
? _value.updatedAt
|
||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$LastMessageClassImplCopyWith<$Res>
|
||||
implements $LastMessageClassCopyWith<$Res> {
|
||||
factory _$$LastMessageClassImplCopyWith(_$LastMessageClassImpl value,
|
||||
$Res Function(_$LastMessageClassImpl) then) =
|
||||
__$$LastMessageClassImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{@JsonKey(name: "id") int id,
|
||||
@JsonKey(name: "data") String data,
|
||||
@JsonKey(name: "media_data") List<dynamic> mediaData,
|
||||
@JsonKey(name: "author_id") int authorId,
|
||||
@JsonKey(name: "is_author_message_auth_user")
|
||||
bool isAuthorMessageAuthUser,
|
||||
@JsonKey(name: "read_by_to_user") bool readByToUser,
|
||||
@JsonKey(name: "updated_at") DateTime updatedAt});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$LastMessageClassImplCopyWithImpl<$Res>
|
||||
extends _$LastMessageClassCopyWithImpl<$Res, _$LastMessageClassImpl>
|
||||
implements _$$LastMessageClassImplCopyWith<$Res> {
|
||||
__$$LastMessageClassImplCopyWithImpl(_$LastMessageClassImpl _value,
|
||||
$Res Function(_$LastMessageClassImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of LastMessageClass
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? id = null,
|
||||
Object? data = null,
|
||||
Object? mediaData = null,
|
||||
Object? authorId = null,
|
||||
Object? isAuthorMessageAuthUser = null,
|
||||
Object? readByToUser = null,
|
||||
Object? updatedAt = null,
|
||||
}) {
|
||||
return _then(_$LastMessageClassImpl(
|
||||
id: null == id
|
||||
? _value.id
|
||||
: id // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
data: null == data
|
||||
? _value.data
|
||||
: data // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
mediaData: null == mediaData
|
||||
? _value._mediaData
|
||||
: mediaData // ignore: cast_nullable_to_non_nullable
|
||||
as List<dynamic>,
|
||||
authorId: null == authorId
|
||||
? _value.authorId
|
||||
: authorId // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
isAuthorMessageAuthUser: null == isAuthorMessageAuthUser
|
||||
? _value.isAuthorMessageAuthUser
|
||||
: isAuthorMessageAuthUser // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
readByToUser: null == readByToUser
|
||||
? _value.readByToUser
|
||||
: readByToUser // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
updatedAt: null == updatedAt
|
||||
? _value.updatedAt
|
||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$LastMessageClassImpl implements _LastMessageClass {
|
||||
const _$LastMessageClassImpl(
|
||||
{@JsonKey(name: "id") required this.id,
|
||||
@JsonKey(name: "data") required this.data,
|
||||
@JsonKey(name: "media_data") required final List<dynamic> mediaData,
|
||||
@JsonKey(name: "author_id") required this.authorId,
|
||||
@JsonKey(name: "is_author_message_auth_user")
|
||||
required this.isAuthorMessageAuthUser,
|
||||
@JsonKey(name: "read_by_to_user") required this.readByToUser,
|
||||
@JsonKey(name: "updated_at") required this.updatedAt})
|
||||
: _mediaData = mediaData;
|
||||
|
||||
factory _$LastMessageClassImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$LastMessageClassImplFromJson(json);
|
||||
|
||||
@override
|
||||
@JsonKey(name: "id")
|
||||
final int id;
|
||||
@override
|
||||
@JsonKey(name: "data")
|
||||
final String data;
|
||||
final List<dynamic> _mediaData;
|
||||
@override
|
||||
@JsonKey(name: "media_data")
|
||||
List<dynamic> get mediaData {
|
||||
if (_mediaData is EqualUnmodifiableListView) return _mediaData;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_mediaData);
|
||||
}
|
||||
|
||||
@override
|
||||
@JsonKey(name: "author_id")
|
||||
final int authorId;
|
||||
@override
|
||||
@JsonKey(name: "is_author_message_auth_user")
|
||||
final bool isAuthorMessageAuthUser;
|
||||
@override
|
||||
@JsonKey(name: "read_by_to_user")
|
||||
final bool readByToUser;
|
||||
@override
|
||||
@JsonKey(name: "updated_at")
|
||||
final DateTime updatedAt;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LastMessageClass(id: $id, data: $data, mediaData: $mediaData, authorId: $authorId, isAuthorMessageAuthUser: $isAuthorMessageAuthUser, readByToUser: $readByToUser, updatedAt: $updatedAt)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$LastMessageClassImpl &&
|
||||
(identical(other.id, id) || other.id == id) &&
|
||||
(identical(other.data, data) || other.data == data) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._mediaData, _mediaData) &&
|
||||
(identical(other.authorId, authorId) ||
|
||||
other.authorId == authorId) &&
|
||||
(identical(
|
||||
other.isAuthorMessageAuthUser, isAuthorMessageAuthUser) ||
|
||||
other.isAuthorMessageAuthUser == isAuthorMessageAuthUser) &&
|
||||
(identical(other.readByToUser, readByToUser) ||
|
||||
other.readByToUser == readByToUser) &&
|
||||
(identical(other.updatedAt, updatedAt) ||
|
||||
other.updatedAt == updatedAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
id,
|
||||
data,
|
||||
const DeepCollectionEquality().hash(_mediaData),
|
||||
authorId,
|
||||
isAuthorMessageAuthUser,
|
||||
readByToUser,
|
||||
updatedAt);
|
||||
|
||||
/// Create a copy of LastMessageClass
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$LastMessageClassImplCopyWith<_$LastMessageClassImpl> get copyWith =>
|
||||
__$$LastMessageClassImplCopyWithImpl<_$LastMessageClassImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$LastMessageClassImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _LastMessageClass implements LastMessageClass {
|
||||
const factory _LastMessageClass(
|
||||
{@JsonKey(name: "id") required final int id,
|
||||
@JsonKey(name: "data") required final String data,
|
||||
@JsonKey(name: "media_data") required final List<dynamic> mediaData,
|
||||
@JsonKey(name: "author_id") required final int authorId,
|
||||
@JsonKey(name: "is_author_message_auth_user")
|
||||
required final bool isAuthorMessageAuthUser,
|
||||
@JsonKey(name: "read_by_to_user") required final bool readByToUser,
|
||||
@JsonKey(name: "updated_at") required final DateTime updatedAt}) =
|
||||
_$LastMessageClassImpl;
|
||||
|
||||
factory _LastMessageClass.fromJson(Map<String, dynamic> json) =
|
||||
_$LastMessageClassImpl.fromJson;
|
||||
|
||||
@override
|
||||
@JsonKey(name: "id")
|
||||
int get id;
|
||||
@override
|
||||
@JsonKey(name: "data")
|
||||
String get data;
|
||||
@override
|
||||
@JsonKey(name: "media_data")
|
||||
List<dynamic> get mediaData;
|
||||
@override
|
||||
@JsonKey(name: "author_id")
|
||||
int get authorId;
|
||||
@override
|
||||
@JsonKey(name: "is_author_message_auth_user")
|
||||
bool get isAuthorMessageAuthUser;
|
||||
@override
|
||||
@JsonKey(name: "read_by_to_user")
|
||||
bool get readByToUser;
|
||||
@override
|
||||
@JsonKey(name: "updated_at")
|
||||
DateTime get updatedAt;
|
||||
|
||||
/// Create a copy of LastMessageClass
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$LastMessageClassImplCopyWith<_$LastMessageClassImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
Users _$UsersFromJson(Map<String, dynamic> json) {
|
||||
return _Users.fromJson(json);
|
||||
}
|
||||
|
||||
@@ -24,8 +24,9 @@ _$ChatRoomImpl _$$ChatRoomImplFromJson(Map<String, dynamic> json) =>
|
||||
_$ChatRoomImpl(
|
||||
id: json['id'] as String,
|
||||
roomName: json['room_name'] as String,
|
||||
lastMessage: json['last_message'],
|
||||
lastMessage: parseLastMessage(json['last_message']),
|
||||
users: Users.fromJson(json['users'] as Map<String, dynamic>),
|
||||
unreadMessagesCount: (json['unread_messages_count'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ChatRoomImplToJson(_$ChatRoomImpl instance) =>
|
||||
@@ -34,30 +35,7 @@ Map<String, dynamic> _$$ChatRoomImplToJson(_$ChatRoomImpl instance) =>
|
||||
'room_name': instance.roomName,
|
||||
'last_message': instance.lastMessage,
|
||||
'users': instance.users,
|
||||
};
|
||||
|
||||
_$LastMessageClassImpl _$$LastMessageClassImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$LastMessageClassImpl(
|
||||
id: (json['id'] as num).toInt(),
|
||||
data: json['data'] as String,
|
||||
mediaData: json['media_data'] as List<dynamic>,
|
||||
authorId: (json['author_id'] as num).toInt(),
|
||||
isAuthorMessageAuthUser: json['is_author_message_auth_user'] as bool,
|
||||
readByToUser: json['read_by_to_user'] as bool,
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$LastMessageClassImplToJson(
|
||||
_$LastMessageClassImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'data': instance.data,
|
||||
'media_data': instance.mediaData,
|
||||
'author_id': instance.authorId,
|
||||
'is_author_message_auth_user': instance.isAuthorMessageAuthUser,
|
||||
'read_by_to_user': instance.readByToUser,
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'unread_messages_count': instance.unreadMessagesCount,
|
||||
};
|
||||
|
||||
_$UsersImpl _$$UsersImplFromJson(Map<String, dynamic> json) => _$UsersImpl(
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
|
||||
import 'package:eatvio_app/core/initialization_cubit/ws_manager.dart';
|
||||
import 'package:eatvio_app/core/websockets/ws_manager.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart';
|
||||
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
|
||||
@@ -87,10 +88,12 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
|
||||
wsManager.subscribeDirectChatChannel();
|
||||
wsManager.directChatStream?.listen((event) {
|
||||
AudioPlayer().play((AssetSource('audio/recive_message.wav')));
|
||||
final message = ChatMessageModel.fromJson(jsonDecode(event.data)['message']);
|
||||
List<ChatMessageModel> messagesList = [
|
||||
ChatMessageModel.fromJson(jsonDecode(event.data)['message']),
|
||||
message,
|
||||
...(state as ChatRoomStateLoaded).chatMessages,
|
||||
];
|
||||
chatRepository.emitNewMessageToChats(message);
|
||||
emit(
|
||||
ChatRoomState.loaded(
|
||||
chatRoom: (state as ChatRoomStateLoaded).chatRoom,
|
||||
@@ -125,17 +128,46 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
|
||||
});
|
||||
}
|
||||
|
||||
sendMessage({
|
||||
Future<bool> sendMessage({
|
||||
required String chatId,
|
||||
String? data,
|
||||
List<File>? files,
|
||||
}) async {
|
||||
await chatRepository.sendMessage(
|
||||
chatId: chatId,
|
||||
data: data,
|
||||
files: files != null ? await ImageCompressUtility.compressFilesList(files) : null,
|
||||
);
|
||||
AudioPlayer().play((AssetSource('audio/send_message.wav')));
|
||||
try {
|
||||
await chatRepository.sendMessage(
|
||||
chatId: chatId,
|
||||
data: data,
|
||||
files: files != null ? await ImageCompressUtility.compressFilesList(files) : null,
|
||||
);
|
||||
AudioPlayer().play((AssetSource('audio/send_message.wav')));
|
||||
return true;
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> markMessagesAsRead(String chatId, List<({int id, int index})> messagesIds) async {
|
||||
try {
|
||||
if (state is ChatRoomStateLoaded) {
|
||||
final ids = messagesIds.map((e) => e.id).toList();
|
||||
await chatRepository.markMessagesAsRead(chatId, ids);
|
||||
final currentMessages = [...(state as ChatRoomStateLoaded).chatMessages];
|
||||
messagesIds.forEach((elem) {
|
||||
currentMessages[elem.index] = currentMessages[elem.index].copyWith(isRead: true);
|
||||
});
|
||||
if (!isClosed) {
|
||||
emit(
|
||||
(state as ChatRoomStateLoaded).copyWith(chatMessages: currentMessages),
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_select_cubit/chat_select_state.dart';
|
||||
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class ChatSelectCubit extends Cubit<ChatSelectState> {
|
||||
final ChatRepository chatRepository;
|
||||
|
||||
ChatSelectCubit({
|
||||
required this.chatRepository,
|
||||
}) : super(ChatSelectState());
|
||||
|
||||
getChatRooms({String? query}) async {
|
||||
emit(ChatSelectState.loading());
|
||||
try {
|
||||
final chatRooms = await chatRepository.getChatRoomPreviews(query: query);
|
||||
emit(
|
||||
ChatSelectState.loaded(
|
||||
chatRooms: chatRooms,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(
|
||||
ChatSelectState.error(errorMessage: e.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import 'package:eatvio_app/features/chat/models/chat_room_preview_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'chat_select_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class ChatSelectState with _$ChatSelectState {
|
||||
const factory ChatSelectState() = _ChatSelectState;
|
||||
|
||||
const factory ChatSelectState.loading() = ChatSelectStateLoading;
|
||||
|
||||
const factory ChatSelectState.error({
|
||||
required String errorMessage,
|
||||
}) = ChatSelectStateError;
|
||||
|
||||
const factory ChatSelectState.loaded({
|
||||
required List<ChatRoom> chatRooms,
|
||||
}) = ChatSelectStateLoaded;
|
||||
}
|
||||
@@ -1,646 +0,0 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'chat_select_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ChatSelectState {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(String errorMessage) error,
|
||||
required TResult Function(List<ChatRoom> chatRooms) loaded,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
TResult? Function(List<ChatRoom> chatRooms)? loaded,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(String errorMessage)? error,
|
||||
TResult Function(List<ChatRoom> chatRooms)? loaded,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_ChatSelectState value) $default, {
|
||||
required TResult Function(ChatSelectStateLoading value) loading,
|
||||
required TResult Function(ChatSelectStateError value) error,
|
||||
required TResult Function(ChatSelectStateLoaded value) loaded,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_ChatSelectState value)? $default, {
|
||||
TResult? Function(ChatSelectStateLoading value)? loading,
|
||||
TResult? Function(ChatSelectStateError value)? error,
|
||||
TResult? Function(ChatSelectStateLoaded value)? loaded,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_ChatSelectState value)? $default, {
|
||||
TResult Function(ChatSelectStateLoading value)? loading,
|
||||
TResult Function(ChatSelectStateError value)? error,
|
||||
TResult Function(ChatSelectStateLoaded value)? loaded,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ChatSelectStateCopyWith<$Res> {
|
||||
factory $ChatSelectStateCopyWith(
|
||||
ChatSelectState value, $Res Function(ChatSelectState) then) =
|
||||
_$ChatSelectStateCopyWithImpl<$Res, ChatSelectState>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ChatSelectStateCopyWithImpl<$Res, $Val extends ChatSelectState>
|
||||
implements $ChatSelectStateCopyWith<$Res> {
|
||||
_$ChatSelectStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of ChatSelectState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ChatSelectStateImplCopyWith<$Res> {
|
||||
factory _$$ChatSelectStateImplCopyWith(_$ChatSelectStateImpl value,
|
||||
$Res Function(_$ChatSelectStateImpl) then) =
|
||||
__$$ChatSelectStateImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ChatSelectStateImplCopyWithImpl<$Res>
|
||||
extends _$ChatSelectStateCopyWithImpl<$Res, _$ChatSelectStateImpl>
|
||||
implements _$$ChatSelectStateImplCopyWith<$Res> {
|
||||
__$$ChatSelectStateImplCopyWithImpl(
|
||||
_$ChatSelectStateImpl _value, $Res Function(_$ChatSelectStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of ChatSelectState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$ChatSelectStateImpl implements _ChatSelectState {
|
||||
const _$ChatSelectStateImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChatSelectState()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType && other is _$ChatSelectStateImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(String errorMessage) error,
|
||||
required TResult Function(List<ChatRoom> chatRooms) loaded,
|
||||
}) {
|
||||
return $default();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
TResult? Function(List<ChatRoom> chatRooms)? loaded,
|
||||
}) {
|
||||
return $default?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(String errorMessage)? error,
|
||||
TResult Function(List<ChatRoom> chatRooms)? loaded,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if ($default != null) {
|
||||
return $default();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_ChatSelectState value) $default, {
|
||||
required TResult Function(ChatSelectStateLoading value) loading,
|
||||
required TResult Function(ChatSelectStateError value) error,
|
||||
required TResult Function(ChatSelectStateLoaded value) loaded,
|
||||
}) {
|
||||
return $default(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_ChatSelectState value)? $default, {
|
||||
TResult? Function(ChatSelectStateLoading value)? loading,
|
||||
TResult? Function(ChatSelectStateError value)? error,
|
||||
TResult? Function(ChatSelectStateLoaded value)? loaded,
|
||||
}) {
|
||||
return $default?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_ChatSelectState value)? $default, {
|
||||
TResult Function(ChatSelectStateLoading value)? loading,
|
||||
TResult Function(ChatSelectStateError value)? error,
|
||||
TResult Function(ChatSelectStateLoaded value)? loaded,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if ($default != null) {
|
||||
return $default(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _ChatSelectState implements ChatSelectState {
|
||||
const factory _ChatSelectState() = _$ChatSelectStateImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ChatSelectStateLoadingImplCopyWith<$Res> {
|
||||
factory _$$ChatSelectStateLoadingImplCopyWith(
|
||||
_$ChatSelectStateLoadingImpl value,
|
||||
$Res Function(_$ChatSelectStateLoadingImpl) then) =
|
||||
__$$ChatSelectStateLoadingImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ChatSelectStateLoadingImplCopyWithImpl<$Res>
|
||||
extends _$ChatSelectStateCopyWithImpl<$Res, _$ChatSelectStateLoadingImpl>
|
||||
implements _$$ChatSelectStateLoadingImplCopyWith<$Res> {
|
||||
__$$ChatSelectStateLoadingImplCopyWithImpl(
|
||||
_$ChatSelectStateLoadingImpl _value,
|
||||
$Res Function(_$ChatSelectStateLoadingImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of ChatSelectState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$ChatSelectStateLoadingImpl implements ChatSelectStateLoading {
|
||||
const _$ChatSelectStateLoadingImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChatSelectState.loading()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ChatSelectStateLoadingImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(String errorMessage) error,
|
||||
required TResult Function(List<ChatRoom> chatRooms) loaded,
|
||||
}) {
|
||||
return loading();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
TResult? Function(List<ChatRoom> chatRooms)? loaded,
|
||||
}) {
|
||||
return loading?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(String errorMessage)? error,
|
||||
TResult Function(List<ChatRoom> chatRooms)? loaded,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_ChatSelectState value) $default, {
|
||||
required TResult Function(ChatSelectStateLoading value) loading,
|
||||
required TResult Function(ChatSelectStateError value) error,
|
||||
required TResult Function(ChatSelectStateLoaded value) loaded,
|
||||
}) {
|
||||
return loading(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_ChatSelectState value)? $default, {
|
||||
TResult? Function(ChatSelectStateLoading value)? loading,
|
||||
TResult? Function(ChatSelectStateError value)? error,
|
||||
TResult? Function(ChatSelectStateLoaded value)? loaded,
|
||||
}) {
|
||||
return loading?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_ChatSelectState value)? $default, {
|
||||
TResult Function(ChatSelectStateLoading value)? loading,
|
||||
TResult Function(ChatSelectStateError value)? error,
|
||||
TResult Function(ChatSelectStateLoaded value)? loaded,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ChatSelectStateLoading implements ChatSelectState {
|
||||
const factory ChatSelectStateLoading() = _$ChatSelectStateLoadingImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ChatSelectStateErrorImplCopyWith<$Res> {
|
||||
factory _$$ChatSelectStateErrorImplCopyWith(_$ChatSelectStateErrorImpl value,
|
||||
$Res Function(_$ChatSelectStateErrorImpl) then) =
|
||||
__$$ChatSelectStateErrorImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({String errorMessage});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ChatSelectStateErrorImplCopyWithImpl<$Res>
|
||||
extends _$ChatSelectStateCopyWithImpl<$Res, _$ChatSelectStateErrorImpl>
|
||||
implements _$$ChatSelectStateErrorImplCopyWith<$Res> {
|
||||
__$$ChatSelectStateErrorImplCopyWithImpl(_$ChatSelectStateErrorImpl _value,
|
||||
$Res Function(_$ChatSelectStateErrorImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of ChatSelectState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? errorMessage = null,
|
||||
}) {
|
||||
return _then(_$ChatSelectStateErrorImpl(
|
||||
errorMessage: null == errorMessage
|
||||
? _value.errorMessage
|
||||
: errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$ChatSelectStateErrorImpl implements ChatSelectStateError {
|
||||
const _$ChatSelectStateErrorImpl({required this.errorMessage});
|
||||
|
||||
@override
|
||||
final String errorMessage;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChatSelectState.error(errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ChatSelectStateErrorImpl &&
|
||||
(identical(other.errorMessage, errorMessage) ||
|
||||
other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, errorMessage);
|
||||
|
||||
/// Create a copy of ChatSelectState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ChatSelectStateErrorImplCopyWith<_$ChatSelectStateErrorImpl>
|
||||
get copyWith =>
|
||||
__$$ChatSelectStateErrorImplCopyWithImpl<_$ChatSelectStateErrorImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(String errorMessage) error,
|
||||
required TResult Function(List<ChatRoom> chatRooms) loaded,
|
||||
}) {
|
||||
return error(errorMessage);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
TResult? Function(List<ChatRoom> chatRooms)? loaded,
|
||||
}) {
|
||||
return error?.call(errorMessage);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(String errorMessage)? error,
|
||||
TResult Function(List<ChatRoom> chatRooms)? loaded,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (error != null) {
|
||||
return error(errorMessage);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_ChatSelectState value) $default, {
|
||||
required TResult Function(ChatSelectStateLoading value) loading,
|
||||
required TResult Function(ChatSelectStateError value) error,
|
||||
required TResult Function(ChatSelectStateLoaded value) loaded,
|
||||
}) {
|
||||
return error(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_ChatSelectState value)? $default, {
|
||||
TResult? Function(ChatSelectStateLoading value)? loading,
|
||||
TResult? Function(ChatSelectStateError value)? error,
|
||||
TResult? Function(ChatSelectStateLoaded value)? loaded,
|
||||
}) {
|
||||
return error?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_ChatSelectState value)? $default, {
|
||||
TResult Function(ChatSelectStateLoading value)? loading,
|
||||
TResult Function(ChatSelectStateError value)? error,
|
||||
TResult Function(ChatSelectStateLoaded value)? loaded,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (error != null) {
|
||||
return error(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ChatSelectStateError implements ChatSelectState {
|
||||
const factory ChatSelectStateError({required final String errorMessage}) =
|
||||
_$ChatSelectStateErrorImpl;
|
||||
|
||||
String get errorMessage;
|
||||
|
||||
/// Create a copy of ChatSelectState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$ChatSelectStateErrorImplCopyWith<_$ChatSelectStateErrorImpl>
|
||||
get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ChatSelectStateLoadedImplCopyWith<$Res> {
|
||||
factory _$$ChatSelectStateLoadedImplCopyWith(
|
||||
_$ChatSelectStateLoadedImpl value,
|
||||
$Res Function(_$ChatSelectStateLoadedImpl) then) =
|
||||
__$$ChatSelectStateLoadedImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({List<ChatRoom> chatRooms});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ChatSelectStateLoadedImplCopyWithImpl<$Res>
|
||||
extends _$ChatSelectStateCopyWithImpl<$Res, _$ChatSelectStateLoadedImpl>
|
||||
implements _$$ChatSelectStateLoadedImplCopyWith<$Res> {
|
||||
__$$ChatSelectStateLoadedImplCopyWithImpl(_$ChatSelectStateLoadedImpl _value,
|
||||
$Res Function(_$ChatSelectStateLoadedImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of ChatSelectState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? chatRooms = null,
|
||||
}) {
|
||||
return _then(_$ChatSelectStateLoadedImpl(
|
||||
chatRooms: null == chatRooms
|
||||
? _value._chatRooms
|
||||
: chatRooms // ignore: cast_nullable_to_non_nullable
|
||||
as List<ChatRoom>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$ChatSelectStateLoadedImpl implements ChatSelectStateLoaded {
|
||||
const _$ChatSelectStateLoadedImpl({required final List<ChatRoom> chatRooms})
|
||||
: _chatRooms = chatRooms;
|
||||
|
||||
final List<ChatRoom> _chatRooms;
|
||||
@override
|
||||
List<ChatRoom> get chatRooms {
|
||||
if (_chatRooms is EqualUnmodifiableListView) return _chatRooms;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_chatRooms);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChatSelectState.loaded(chatRooms: $chatRooms)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ChatSelectStateLoadedImpl &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._chatRooms, _chatRooms));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, const DeepCollectionEquality().hash(_chatRooms));
|
||||
|
||||
/// Create a copy of ChatSelectState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ChatSelectStateLoadedImplCopyWith<_$ChatSelectStateLoadedImpl>
|
||||
get copyWith => __$$ChatSelectStateLoadedImplCopyWithImpl<
|
||||
_$ChatSelectStateLoadedImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(String errorMessage) error,
|
||||
required TResult Function(List<ChatRoom> chatRooms) loaded,
|
||||
}) {
|
||||
return loaded(chatRooms);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
TResult? Function(List<ChatRoom> chatRooms)? loaded,
|
||||
}) {
|
||||
return loaded?.call(chatRooms);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(String errorMessage)? error,
|
||||
TResult Function(List<ChatRoom> chatRooms)? loaded,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loaded != null) {
|
||||
return loaded(chatRooms);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_ChatSelectState value) $default, {
|
||||
required TResult Function(ChatSelectStateLoading value) loading,
|
||||
required TResult Function(ChatSelectStateError value) error,
|
||||
required TResult Function(ChatSelectStateLoaded value) loaded,
|
||||
}) {
|
||||
return loaded(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_ChatSelectState value)? $default, {
|
||||
TResult? Function(ChatSelectStateLoading value)? loading,
|
||||
TResult? Function(ChatSelectStateError value)? error,
|
||||
TResult? Function(ChatSelectStateLoaded value)? loaded,
|
||||
}) {
|
||||
return loaded?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_ChatSelectState value)? $default, {
|
||||
TResult Function(ChatSelectStateLoading value)? loading,
|
||||
TResult Function(ChatSelectStateError value)? error,
|
||||
TResult Function(ChatSelectStateLoaded value)? loaded,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loaded != null) {
|
||||
return loaded(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ChatSelectStateLoaded implements ChatSelectState {
|
||||
const factory ChatSelectStateLoaded(
|
||||
{required final List<ChatRoom> chatRooms}) = _$ChatSelectStateLoadedImpl;
|
||||
|
||||
List<ChatRoom> get chatRooms;
|
||||
|
||||
/// Create a copy of ChatSelectState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$ChatSelectStateLoadedImplCopyWith<_$ChatSelectStateLoadedImpl>
|
||||
get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
144
lib/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart
Normal file
144
lib/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart
Normal file
@@ -0,0 +1,144 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/websockets/ws_manager.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_state.dart';
|
||||
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
|
||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class ChatsCubit extends Cubit<ChatsState> {
|
||||
final ChatRepository chatRepository;
|
||||
final ProfileRepository profileRepository;
|
||||
final WsManager wsManager;
|
||||
late StreamSubscription? newIncomingMessagesSubscription;
|
||||
late StreamSubscription? newLastMessageSubscription;
|
||||
|
||||
ChatsCubit({
|
||||
required this.chatRepository,
|
||||
required this.wsManager,
|
||||
required this.profileRepository,
|
||||
}) : super(ChatsState()) {
|
||||
newIncomingMessagesSubscription = wsManager.newMessagesStream?.listen((event) {
|
||||
_handleNewMessageViaSocket(event.data);
|
||||
});
|
||||
|
||||
newLastMessageSubscription = chatRepository.newUserMessagesStream.listen((message) {
|
||||
_setNewLastMessage(message);
|
||||
});
|
||||
}
|
||||
String? _query;
|
||||
Future<void> getChatRoomsWithLoading({String? query}) async {
|
||||
_query = query;
|
||||
emit(state.copyWith(state: BaseState.loading));
|
||||
try {
|
||||
final chatRooms = await chatRepository.getChatRoomPreviews(query: query);
|
||||
final unreadChats = chatRooms.where(
|
||||
(element) => element.unreadMessagesCount > 0,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
chatRooms: chatRooms,
|
||||
chatsWithUnreadMessagesCount: unreadChats.length,
|
||||
state: BaseState.success,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(errorMessage: e.toString(), state: BaseState.error),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getChatRooms({String? query}) async {
|
||||
_query = query;
|
||||
try {
|
||||
final chatRooms = await chatRepository.getChatRoomPreviews(query: query);
|
||||
final unreadChats = chatRooms.where(
|
||||
(element) => element.unreadMessagesCount > 0,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
chatRooms: chatRooms,
|
||||
chatsWithUnreadMessagesCount: unreadChats.length,
|
||||
state: BaseState.success,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(errorMessage: e.toString(), state: BaseState.error),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void reduceUnreadMessagesCount({required String chatId, required int count}) {
|
||||
bool isChatRead = false;
|
||||
final updatedChatRooms = state.chatRooms.map((room) {
|
||||
if (room.id == chatId) {
|
||||
int unreadMessagesCount = room.unreadMessagesCount - count;
|
||||
if (unreadMessagesCount <= 0) {
|
||||
unreadMessagesCount = 0;
|
||||
isChatRead = true;
|
||||
}
|
||||
return room.copyWith(unreadMessagesCount: unreadMessagesCount);
|
||||
}
|
||||
return room;
|
||||
}).toList();
|
||||
emit(
|
||||
state.copyWith(
|
||||
chatRooms: updatedChatRooms,
|
||||
chatsWithUnreadMessagesCount: isChatRead ? state.chatsWithUnreadMessagesCount - 1 : state.chatsWithUnreadMessagesCount,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _handleNewMessageViaSocket(dynamic data) async {
|
||||
final json = jsonDecode(data);
|
||||
final message = ChatMessageModel.fromJson(json['message']);
|
||||
|
||||
final currentChatRooms = [...state.chatRooms];
|
||||
|
||||
bool wasChanged = false;
|
||||
bool willIncrementUnreadChats = false;
|
||||
final updatedChatRooms = currentChatRooms.map((chatRoom) {
|
||||
if (chatRoom.id == message.roomId) {
|
||||
wasChanged = true;
|
||||
if (chatRoom.unreadMessagesCount == 0) {
|
||||
willIncrementUnreadChats = true;
|
||||
}
|
||||
return chatRoom.copyWith(lastMessage: message, unreadMessagesCount: chatRoom.unreadMessagesCount + 1);
|
||||
}
|
||||
return chatRoom;
|
||||
}).toList();
|
||||
|
||||
if (!wasChanged && _query == null) {
|
||||
getChatRooms();
|
||||
} else {
|
||||
emit(
|
||||
state.copyWith(
|
||||
chatRooms: updatedChatRooms,
|
||||
chatsWithUnreadMessagesCount: willIncrementUnreadChats ? state.chatsWithUnreadMessagesCount + 1 : state.chatsWithUnreadMessagesCount,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _setNewLastMessage(ChatMessageModel message) {
|
||||
final chats = state.chatRooms.map((chat) {
|
||||
if (chat.id == message.roomId) {
|
||||
return chat.copyWith(lastMessage: message);
|
||||
}
|
||||
return chat;
|
||||
}).toList();
|
||||
|
||||
emit(state.copyWith(chatRooms: chats));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
newIncomingMessagesSubscription?.cancel();
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_room_preview_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'chats_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class ChatsState with _$ChatsState {
|
||||
|
||||
factory ChatsState({
|
||||
@Default(BaseState.initial) BaseState state,
|
||||
@Default(0) int chatsWithUnreadMessagesCount,
|
||||
@Default([]) List<ChatRoom> chatRooms,
|
||||
@Default(null) String? errorMessage,
|
||||
}) = _ChatsState;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'chats_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ChatsState {
|
||||
BaseState get state => throw _privateConstructorUsedError;
|
||||
int get chatsWithUnreadMessagesCount => throw _privateConstructorUsedError;
|
||||
List<ChatRoom> get chatRooms => throw _privateConstructorUsedError;
|
||||
String? get errorMessage => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of ChatsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$ChatsStateCopyWith<ChatsState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ChatsStateCopyWith<$Res> {
|
||||
factory $ChatsStateCopyWith(
|
||||
ChatsState value, $Res Function(ChatsState) then) =
|
||||
_$ChatsStateCopyWithImpl<$Res, ChatsState>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{BaseState state,
|
||||
int chatsWithUnreadMessagesCount,
|
||||
List<ChatRoom> chatRooms,
|
||||
String? errorMessage});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ChatsStateCopyWithImpl<$Res, $Val extends ChatsState>
|
||||
implements $ChatsStateCopyWith<$Res> {
|
||||
_$ChatsStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of ChatsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? state = null,
|
||||
Object? chatsWithUnreadMessagesCount = null,
|
||||
Object? chatRooms = null,
|
||||
Object? errorMessage = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
state: null == state
|
||||
? _value.state
|
||||
: state // ignore: cast_nullable_to_non_nullable
|
||||
as BaseState,
|
||||
chatsWithUnreadMessagesCount: null == chatsWithUnreadMessagesCount
|
||||
? _value.chatsWithUnreadMessagesCount
|
||||
: chatsWithUnreadMessagesCount // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
chatRooms: null == chatRooms
|
||||
? _value.chatRooms
|
||||
: chatRooms // ignore: cast_nullable_to_non_nullable
|
||||
as List<ChatRoom>,
|
||||
errorMessage: freezed == errorMessage
|
||||
? _value.errorMessage
|
||||
: errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ChatsStateImplCopyWith<$Res>
|
||||
implements $ChatsStateCopyWith<$Res> {
|
||||
factory _$$ChatsStateImplCopyWith(
|
||||
_$ChatsStateImpl value, $Res Function(_$ChatsStateImpl) then) =
|
||||
__$$ChatsStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{BaseState state,
|
||||
int chatsWithUnreadMessagesCount,
|
||||
List<ChatRoom> chatRooms,
|
||||
String? errorMessage});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ChatsStateImplCopyWithImpl<$Res>
|
||||
extends _$ChatsStateCopyWithImpl<$Res, _$ChatsStateImpl>
|
||||
implements _$$ChatsStateImplCopyWith<$Res> {
|
||||
__$$ChatsStateImplCopyWithImpl(
|
||||
_$ChatsStateImpl _value, $Res Function(_$ChatsStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of ChatsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? state = null,
|
||||
Object? chatsWithUnreadMessagesCount = null,
|
||||
Object? chatRooms = null,
|
||||
Object? errorMessage = freezed,
|
||||
}) {
|
||||
return _then(_$ChatsStateImpl(
|
||||
state: null == state
|
||||
? _value.state
|
||||
: state // ignore: cast_nullable_to_non_nullable
|
||||
as BaseState,
|
||||
chatsWithUnreadMessagesCount: null == chatsWithUnreadMessagesCount
|
||||
? _value.chatsWithUnreadMessagesCount
|
||||
: chatsWithUnreadMessagesCount // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
chatRooms: null == chatRooms
|
||||
? _value._chatRooms
|
||||
: chatRooms // ignore: cast_nullable_to_non_nullable
|
||||
as List<ChatRoom>,
|
||||
errorMessage: freezed == errorMessage
|
||||
? _value.errorMessage
|
||||
: errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$ChatsStateImpl implements _ChatsState {
|
||||
_$ChatsStateImpl(
|
||||
{this.state = BaseState.initial,
|
||||
this.chatsWithUnreadMessagesCount = 0,
|
||||
final List<ChatRoom> chatRooms = const [],
|
||||
this.errorMessage = null})
|
||||
: _chatRooms = chatRooms;
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final BaseState state;
|
||||
@override
|
||||
@JsonKey()
|
||||
final int chatsWithUnreadMessagesCount;
|
||||
final List<ChatRoom> _chatRooms;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<ChatRoom> get chatRooms {
|
||||
if (_chatRooms is EqualUnmodifiableListView) return _chatRooms;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_chatRooms);
|
||||
}
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final String? errorMessage;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChatsState(state: $state, chatsWithUnreadMessagesCount: $chatsWithUnreadMessagesCount, chatRooms: $chatRooms, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ChatsStateImpl &&
|
||||
(identical(other.state, state) || other.state == state) &&
|
||||
(identical(other.chatsWithUnreadMessagesCount,
|
||||
chatsWithUnreadMessagesCount) ||
|
||||
other.chatsWithUnreadMessagesCount ==
|
||||
chatsWithUnreadMessagesCount) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._chatRooms, _chatRooms) &&
|
||||
(identical(other.errorMessage, errorMessage) ||
|
||||
other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
state,
|
||||
chatsWithUnreadMessagesCount,
|
||||
const DeepCollectionEquality().hash(_chatRooms),
|
||||
errorMessage);
|
||||
|
||||
/// Create a copy of ChatsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ChatsStateImplCopyWith<_$ChatsStateImpl> get copyWith =>
|
||||
__$$ChatsStateImplCopyWithImpl<_$ChatsStateImpl>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _ChatsState implements ChatsState {
|
||||
factory _ChatsState(
|
||||
{final BaseState state,
|
||||
final int chatsWithUnreadMessagesCount,
|
||||
final List<ChatRoom> chatRooms,
|
||||
final String? errorMessage}) = _$ChatsStateImpl;
|
||||
|
||||
@override
|
||||
BaseState get state;
|
||||
@override
|
||||
int get chatsWithUnreadMessagesCount;
|
||||
@override
|
||||
List<ChatRoom> get chatRooms;
|
||||
@override
|
||||
String? get errorMessage;
|
||||
|
||||
/// Create a copy of ChatsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$ChatsStateImplCopyWith<_$ChatsStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/widgets/chat_bubble_widget.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
@@ -12,12 +15,14 @@ import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:visibility_detector/visibility_detector.dart';
|
||||
|
||||
class ChatScreen extends StatefulWidget {
|
||||
final String chatId;
|
||||
|
||||
final ChatsCubit chatsCubit;
|
||||
const ChatScreen({
|
||||
required this.chatId,
|
||||
required this.chatsCubit,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@@ -29,6 +34,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
final scrollController = ScrollController();
|
||||
final TextEditingController textEditingController = TextEditingController();
|
||||
final ChatRoomCubit chatRoomCubit = sl<ChatRoomCubit>();
|
||||
final List<({int id, int index})> unreadMessagesIds = [];
|
||||
final List<({int id, int index})> unreadMessagesIdsCopy = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -152,25 +159,65 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
(context, index) {
|
||||
if (index < state.chatMessages.length) {
|
||||
if ((index + 1 != state.chatMessages.length &&
|
||||
DateTime.parse(state.chatMessages[index].updatedAt).day != DateTime.parse(state.chatMessages[index + 1].updatedAt).day) ||
|
||||
state.chatMessages[index].updatedAt.day != state.chatMessages[index + 1].updatedAt.day) ||
|
||||
index + 1 == state.chatMessages.length) {
|
||||
final isCurrentUserAuthor = state.chatRoom.users['to_chat_user']!.id != state.chatMessages[index].authorId;
|
||||
return Column(
|
||||
children: [
|
||||
_messageDate(state.chatMessages[index].updatedAt),
|
||||
ChatBubbleWidget(
|
||||
sendTime: state.chatMessages[index].updatedAt,
|
||||
text: state.chatMessages[index].data.trim(),
|
||||
isCurrentUser: state.chatRoom.users['to_chat_user']!.id != state.chatMessages[index].authorId,
|
||||
mediaData: state.chatMessages[index].mediaData ?? [],
|
||||
VisibilityDetector(
|
||||
key: Key(state.chatMessages[index].id.toString()),
|
||||
onVisibilityChanged: (VisibilityInfo info) {
|
||||
if (!state.chatMessages[index].isRead && !isCurrentUserAuthor && info.visibleFraction > 0) {
|
||||
unreadMessagesIdsCopy.add((id: state.chatMessages[index].id, index: index));
|
||||
EasyDebounce.debounce(
|
||||
'mark_as_read',
|
||||
Duration(milliseconds: 500),
|
||||
() async {
|
||||
final result = await context.read<ChatRoomCubit>().markMessagesAsRead(state.chatRoom.id, unreadMessagesIdsCopy);
|
||||
if (!result) return;
|
||||
widget.chatsCubit.reduceUnreadMessagesCount(chatId: state.chatRoom.id, count: unreadMessagesIdsCopy.length);
|
||||
unreadMessagesIdsCopy.clear();
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
child: ChatBubbleWidget(
|
||||
isRead: state.chatMessages[index].isRead,
|
||||
sendTime: state.chatMessages[index].updatedAt,
|
||||
text: state.chatMessages[index].data.trim(),
|
||||
isCurrentUser: isCurrentUserAuthor,
|
||||
mediaData: state.chatMessages[index].mediaData ?? [],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return ChatBubbleWidget(
|
||||
sendTime: state.chatMessages[index].updatedAt,
|
||||
text: state.chatMessages[index].data.trim(),
|
||||
isCurrentUser: state.chatRoom.users['to_chat_user']!.id != state.chatMessages[index].authorId,
|
||||
mediaData: state.chatMessages[index].mediaData ?? [],
|
||||
final isCurrentUserAuthor = state.chatRoom.users['to_chat_user']!.id != state.chatMessages[index].authorId;
|
||||
return VisibilityDetector(
|
||||
key: Key(state.chatMessages[index].id.toString()),
|
||||
onVisibilityChanged: (VisibilityInfo info) {
|
||||
if (!state.chatMessages[index].isRead && !isCurrentUserAuthor && info.visibleFraction > 0) {
|
||||
unreadMessagesIds.add((id: state.chatMessages[index].id, index: index));
|
||||
EasyDebounce.debounce(
|
||||
'mark_as_read',
|
||||
Duration(milliseconds: 500),
|
||||
() async {
|
||||
final result = await context.read<ChatRoomCubit>().markMessagesAsRead(state.chatRoom.id, unreadMessagesIds);
|
||||
if (!result) return;
|
||||
widget.chatsCubit.reduceUnreadMessagesCount(chatId: state.chatRoom.id, count: unreadMessagesIds.length);
|
||||
unreadMessagesIds.clear();
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
child: ChatBubbleWidget(
|
||||
isRead: state.chatMessages[index].isRead,
|
||||
sendTime: state.chatMessages[index].updatedAt,
|
||||
text: state.chatMessages[index].data.trim(),
|
||||
isCurrentUser: isCurrentUserAuthor,
|
||||
mediaData: state.chatMessages[index].mediaData ?? [],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Padding(
|
||||
@@ -222,7 +269,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
|
||||
if (result != null) {
|
||||
List<File> files = result.paths.map((path) => File(path!)).toList();
|
||||
chatRoomCubit.sendMessage(
|
||||
await chatRoomCubit.sendMessage(
|
||||
chatId: widget.chatId,
|
||||
files: files,
|
||||
);
|
||||
@@ -329,13 +376,13 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
_messageDate(String date) {
|
||||
_messageDate(DateTime date) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
padding: const EdgeInsets.only(top: 32),
|
||||
child: Text(
|
||||
DateFormat.yMMMMd('RU').format(
|
||||
DateTime.parse(date),
|
||||
date,
|
||||
),
|
||||
style: const TextStyle(
|
||||
height: 1,
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_select_cubit/chat_select_cubit.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_select_cubit/chat_select_state.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/widgets/chat_entry_widget.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/widgets/chat_search_bar_widget.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class ChatSelectScreen extends StatefulWidget {
|
||||
const ChatSelectScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<ChatSelectScreen> createState() => _ChatSelectScreenState();
|
||||
}
|
||||
|
||||
class _ChatSelectScreenState extends State<ChatSelectScreen> {
|
||||
final ChatSelectCubit chatSelectCubit = sl<ChatSelectCubit>();
|
||||
final searchController = TextEditingController();
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider<ChatSelectCubit>(
|
||||
create: (context) => chatSelectCubit..getChatRooms(),
|
||||
child: BlocBuilder<ChatSelectCubit, ChatSelectState>(
|
||||
builder: (context, state) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
toolbarHeight: 0,
|
||||
),
|
||||
body: NestedScrollView(
|
||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||
return [
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
sliver: SliverAppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
stretchTriggerOffset: 1,
|
||||
scrolledUnderElevation: 0,
|
||||
floating: true,
|
||||
snap: true,
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: ChatSearchBarWidget(
|
||||
onSuffixIconTap: () => context.read<ChatSelectCubit>().getChatRooms(),
|
||||
onChanged: (query) {
|
||||
if (query.length > 2) {
|
||||
EasyDebounce.debounce(
|
||||
'searchChatRoom',
|
||||
Duration(milliseconds: 300),
|
||||
() => context.read<ChatSelectCubit>().getChatRooms(query: query),
|
||||
);
|
||||
} else {
|
||||
context.read<ChatSelectCubit>().getChatRooms();
|
||||
}
|
||||
},
|
||||
controller: searchController,
|
||||
fillColor: Color(0xFFF0F2F5),
|
||||
hintText: "Поиск",
|
||||
hintStyle: TextStyle(
|
||||
color: Color(0xFF7B8794),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
body: stateBuilder(state),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
stateBuilder(state) {
|
||||
if (state is ChatSelectStateLoading) {
|
||||
return Scaffold(
|
||||
body: const Loader(),
|
||||
);
|
||||
} else if (state is ChatSelectStateLoaded) {
|
||||
return _buildChatList(context, state);
|
||||
} else if (state is ChatSelectStateError) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(child: Text(state.errorMessage)),
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
body: const Loader(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_buildChatList(BuildContext context, ChatSelectStateLoaded state) {
|
||||
return ListView.separated(
|
||||
padding: EdgeInsets.all(16),
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
separatorBuilder: (context, index) {
|
||||
return SizedBox(
|
||||
height: 8,
|
||||
);
|
||||
},
|
||||
itemCount: state.chatRooms.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ChatEntryWidget(chatRoom: state.chatRooms[index]);
|
||||
},
|
||||
);
|
||||
}
|
||||
109
lib/features/chat/presentation/pages/chats_screen.dart
Normal file
109
lib/features/chat/presentation/pages/chats_screen.dart
Normal file
@@ -0,0 +1,109 @@
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_state.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/widgets/chat_entry_widget.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/widgets/chat_search_bar_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class ChatsScreen extends StatefulWidget {
|
||||
const ChatsScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<ChatsScreen> createState() => _ChatsScreenState();
|
||||
}
|
||||
|
||||
class _ChatsScreenState extends State<ChatsScreen> {
|
||||
final searchController = TextEditingController();
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<ChatsCubit, ChatsState>(
|
||||
builder: (context, state) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
toolbarHeight: 0,
|
||||
),
|
||||
body: NestedScrollView(
|
||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||
return [
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
sliver: SliverAppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
stretchTriggerOffset: 1,
|
||||
scrolledUnderElevation: 0,
|
||||
floating: true,
|
||||
snap: true,
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: ChatSearchBarWidget(
|
||||
onSuffixIconTap: () => context.read<ChatsCubit>().getChatRooms(),
|
||||
onChanged: (query) {
|
||||
if (query.length > 2) {
|
||||
EasyDebounce.debounce(
|
||||
'searchChatRoom',
|
||||
Duration(milliseconds: 300),
|
||||
() => context.read<ChatsCubit>().getChatRooms(query: query),
|
||||
);
|
||||
} else {
|
||||
context.read<ChatsCubit>().getChatRooms();
|
||||
}
|
||||
},
|
||||
controller: searchController,
|
||||
fillColor: Color(0xFFF0F2F5),
|
||||
hintText: "Поиск",
|
||||
hintStyle: TextStyle(
|
||||
color: Color(0xFF7B8794),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
body: stateBuilder(state),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
stateBuilder(ChatsState state) {
|
||||
if (state.state == BaseState.loading) {
|
||||
return Scaffold(
|
||||
body: const Loader(),
|
||||
);
|
||||
} else if (state.state == BaseState.success) {
|
||||
return _buildChatList(context, state);
|
||||
} else if (state.state == BaseState.error) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(child: Text(state.errorMessage ?? '')),
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
body: const Loader(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_buildChatList(BuildContext context, ChatsState state) {
|
||||
return ListView.separated(
|
||||
padding: EdgeInsets.all(16),
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
separatorBuilder: (context, index) {
|
||||
return SizedBox(
|
||||
height: 8,
|
||||
);
|
||||
},
|
||||
itemCount: state.chatRooms.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ChatEntryWidget(chatRoom: state.chatRooms[index]);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -15,118 +15,146 @@ class ChatBubbleWidget extends StatelessWidget {
|
||||
required this.text,
|
||||
required this.isCurrentUser,
|
||||
required this.mediaData,
|
||||
required this.isRead,
|
||||
});
|
||||
|
||||
final String sendTime;
|
||||
final DateTime sendTime;
|
||||
final String text;
|
||||
final bool isCurrentUser;
|
||||
final bool isRead;
|
||||
final List<dynamic> mediaData;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.fromLTRB(isCurrentUser ? 64 : 16, 4, isCurrentUser ? 16 : 64, 4),
|
||||
child: Align(
|
||||
alignment: isCurrentUser ? Alignment.centerRight : Alignment.centerLeft,
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: isCurrentUser ? appTheme.gray50 : appTheme.gray60004,
|
||||
borderRadius: mediaData.length > 0
|
||||
? BorderRadius.circular(24)
|
||||
: BorderRadius.horizontal(
|
||||
left: isCurrentUser ? Radius.circular(32) : Radius.circular(16),
|
||||
right: isCurrentUser ? Radius.circular(16) : Radius.circular(24),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: mediaData.length > 0 ? EdgeInsets.all(8) : EdgeInsets.only(top: 8, bottom: 8, left: isCurrentUser ? 16 : 8, right: isCurrentUser ? 8 : 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: isCurrentUser ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (mediaData.isNotEmpty)
|
||||
CustomScrollView(
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
SliverList.separated(
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
if (!mediaData[index].toString().contains('.png') &&
|
||||
!mediaData[index].toString().contains('.jpg') &&
|
||||
!mediaData[index].toString().contains('.jpeg')) {
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.all(4),
|
||||
horizontalTitleGap: 8,
|
||||
onTap: () async {
|
||||
if (!await launchUrl(Uri.parse(baseUrl + '/storage/' + mediaData[index].toString()))) {
|
||||
throw Exception('Could not launch ${mediaData[index].toString()}');
|
||||
}
|
||||
},
|
||||
leading: Icon(
|
||||
Icons.file_copy_outlined,
|
||||
color: Colors.white,
|
||||
),
|
||||
trailing: Icon(
|
||||
Icons.download_outlined,
|
||||
color: Colors.white,
|
||||
),
|
||||
title: Text(
|
||||
mediaData[index].toString().replaceAll('chat_files/', ''),
|
||||
maxLines: 2,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
context.pushTransparentRoute(
|
||||
PhotoViewScreen(
|
||||
imageUrls: mediaData.map((e) => baseUrl + '/storage/' + e.toString()).toList(),
|
||||
index: index,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Hero(
|
||||
tag: baseUrl + '/storage/' + '${mediaData[index]}',
|
||||
transitionOnUserGestures: true,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: baseUrl + '/storage/' + '${mediaData[index]}',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) => const SizedBox(height: 8),
|
||||
itemCount: mediaData.length,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (mediaData.length > 0 && text.isNotEmpty) SizedBox(height: 8),
|
||||
if (text.isNotEmpty)
|
||||
Text(
|
||||
text,
|
||||
style: TextStyles.textFS13FW400.copyWith(color: appTheme.black, fontSize: 16),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: mediaData.length > 0 ? const EdgeInsets.only(right: 8, top: 4, left: 8) : EdgeInsets.zero,
|
||||
child: Text(
|
||||
DateTime.parse(sendTime).format('hh:mm'),
|
||||
style: TextStyle(
|
||||
color: Color(0xFF7B8794),
|
||||
height: 1,
|
||||
fontSize: 10,
|
||||
),
|
||||
final size = MediaQuery.sizeOf(context);
|
||||
return Container(
|
||||
width: size.width,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(isCurrentUser ? 64 : 16, 10, isCurrentUser ? 16 : 64, 4),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: isCurrentUser ? MainAxisAlignment.end : MainAxisAlignment.start,
|
||||
children: [
|
||||
if (isCurrentUser)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 4, bottom: 4),
|
||||
child: Text(
|
||||
sendTime.format('hh:mm'),
|
||||
style: TextStyle(
|
||||
color: Color(0xFF7B8794),
|
||||
height: 1,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
constraints: BoxConstraints(maxWidth: size.width * 0.7),
|
||||
decoration: BoxDecoration(
|
||||
color: isCurrentUser ? appTheme.gray50 : appTheme.gray60004,
|
||||
borderRadius: mediaData.length > 0
|
||||
? BorderRadius.circular(24)
|
||||
: BorderRadius.horizontal(
|
||||
left: isCurrentUser ? Radius.circular(32) : Radius.circular(16),
|
||||
right: isCurrentUser ? Radius.circular(16) : Radius.circular(24),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding:
|
||||
mediaData.isNotEmpty ? EdgeInsets.all(8) : EdgeInsets.only(top: 8, bottom: 8, left: isCurrentUser ? 16 : 8, right: isCurrentUser ? 8 : 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: isCurrentUser ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (mediaData.isNotEmpty)
|
||||
SizedBox(
|
||||
width: size.width * 0.7,
|
||||
child: CustomScrollView(
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
SliverList.separated(
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
if (!mediaData[index].toString().contains('.png') &&
|
||||
!mediaData[index].toString().contains('.jpg') &&
|
||||
!mediaData[index].toString().contains('.jpeg')) {
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.all(4),
|
||||
horizontalTitleGap: 8,
|
||||
onTap: () async {
|
||||
if (!await launchUrl(Uri.parse(baseUrl + '/storage/' + mediaData[index].toString()))) {
|
||||
throw Exception('Could not launch ${mediaData[index].toString()}');
|
||||
}
|
||||
},
|
||||
leading: Icon(
|
||||
Icons.file_copy_outlined,
|
||||
color: Colors.white,
|
||||
),
|
||||
trailing: Icon(
|
||||
Icons.download_outlined,
|
||||
color: Colors.white,
|
||||
),
|
||||
title: Text(
|
||||
mediaData[index].toString().replaceAll('chat_files/', ''),
|
||||
maxLines: 2,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
context.pushTransparentRoute(
|
||||
PhotoViewScreen(
|
||||
imageUrls: mediaData.map((e) => baseUrl + '/storage/' + e.toString()).toList(),
|
||||
index: index,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Hero(
|
||||
tag: baseUrl + '/storage/' + '${mediaData[index]}',
|
||||
transitionOnUserGestures: true,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: baseUrl + '/storage/' + '${mediaData[index]}',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) => const SizedBox(height: 8),
|
||||
itemCount: mediaData.length,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (mediaData.isNotEmpty && text.isNotEmpty) SizedBox(height: 8),
|
||||
if (text.isNotEmpty)
|
||||
Text(
|
||||
text,
|
||||
style: TextStyles.textFS13FW400.copyWith(color: appTheme.black, fontSize: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!isCurrentUser)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 4, bottom: 4),
|
||||
child: Text(
|
||||
sendTime.format('hh:mm'),
|
||||
style: TextStyle(
|
||||
color: Color(0xFF7B8794),
|
||||
height: 1,
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -2,7 +2,9 @@ import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_room_preview_model.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class ChatEntryWidget extends StatefulWidget {
|
||||
@@ -18,15 +20,6 @@ class ChatEntryWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ChatEntryWidgetState extends State<ChatEntryWidget> {
|
||||
LastMessageClass? lastMessage;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.chatRoom.lastMessage is Map<String, dynamic>) {
|
||||
lastMessage = LastMessageClass.fromJson(widget.chatRoom.lastMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -34,10 +27,13 @@ class _ChatEntryWidgetState extends State<ChatEntryWidget> {
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'chatScreen',
|
||||
extra: widget.chatRoom.id.toString(),
|
||||
extra: {
|
||||
'chatId': widget.chatRoom.id.toString(),
|
||||
'chatsCubit': context.read<ChatsCubit>(),
|
||||
},
|
||||
),
|
||||
child: Ink(
|
||||
padding: EdgeInsets.all(16),
|
||||
padding: EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
color: Color(0xFFF6FAFF),
|
||||
@@ -54,39 +50,51 @@ class _ChatEntryWidgetState extends State<ChatEntryWidget> {
|
||||
backgroundColor: Colors.white,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
widget.chatRoom.users.toChatUser.name.length <= 20
|
||||
? widget.chatRoom.users.toChatUser.name
|
||||
: widget.chatRoom.users.toChatUser.name.substring(0, 20) + '...',
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
Spacer(),
|
||||
if (lastMessage != null)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 8),
|
||||
child: Text(
|
||||
lastMessage!.updatedAt.format('dd MMM', 'ru'),
|
||||
style: theme.textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
],
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.chatRoom.users.toChatUser.name.length <= 20
|
||||
? widget.chatRoom.users.toChatUser.name
|
||||
: widget.chatRoom.users.toChatUser.name.substring(0, 20) + '...',
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
if (widget.chatRoom.lastMessage != null)
|
||||
Text(
|
||||
widget.chatRoom.lastMessage!.data.toString().trim(),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: CustomTextStyles.bodyMediumBluegray800,
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
if (lastMessage != null)
|
||||
Text(
|
||||
lastMessage!.data.toString().trim(),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: CustomTextStyles.bodyMediumBluegray800,
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
if (widget.chatRoom.lastMessage != null)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 8),
|
||||
child: Text(
|
||||
widget.chatRoom.lastMessage!.updatedAt.format('dd MMM', 'ru'),
|
||||
style: theme.textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
if (widget.chatRoom.unreadMessagesCount > 0)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: appTheme.blueA400,
|
||||
),
|
||||
child: Text(
|
||||
widget.chatRoom.unreadMessagesCount.toString(),
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.whiteA700),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_messages_model.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_room_model.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_room_preview_model.dart';
|
||||
@@ -10,10 +12,18 @@ import 'package:http_parser/http_parser.dart';
|
||||
class ChatRepository {
|
||||
final ChatService chatService;
|
||||
|
||||
final _newUserMessagesController = StreamController<ChatMessageModel>();
|
||||
|
||||
Stream<ChatMessageModel> get newUserMessagesStream => _newUserMessagesController.stream;
|
||||
|
||||
ChatRepository({
|
||||
required this.chatService,
|
||||
});
|
||||
|
||||
void emitNewMessageToChats(ChatMessageModel message) {
|
||||
_newUserMessagesController.add(message);
|
||||
}
|
||||
|
||||
Future<void> sendMessage({
|
||||
required String chatId,
|
||||
String? data,
|
||||
@@ -66,7 +76,7 @@ class ChatRepository {
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<ChatRoomModel> getChatRoomIdByUserSlug({required String slug}) async {
|
||||
try {
|
||||
@@ -75,4 +85,12 @@ class ChatRepository {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> markMessagesAsRead(String chatId, List<int> messageIds) async {
|
||||
try {
|
||||
await chatService.markMessagesAsRead(id: chatId, body: {'messages_ids': messageIds});
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,4 +38,7 @@ abstract class ChatService {
|
||||
Future<ChatRoomModel> getChatRoomIdByUserSlug({
|
||||
@Path() required String user,
|
||||
});
|
||||
|
||||
@POST('/api/chat/{id}/messages/markAsRead')
|
||||
Future<void> markMessagesAsRead({@Path() required String id, @Body() required Map<String, List<int>> body});
|
||||
}
|
||||
|
||||
@@ -167,6 +167,29 @@ class _ChatService implements ChatService {
|
||||
return _value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> markMessagesAsRead({
|
||||
required String id,
|
||||
required Map<String, List<int>> body,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = <String, dynamic>{};
|
||||
_data.addAll(body);
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/chat/${id}/messages/markAsRead',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
|
||||
if (T != dynamic &&
|
||||
!(requestOptions.responseType == ResponseType.bytes ||
|
||||
|
||||
Reference in New Issue
Block a user