@@ -4,5 +4,4 @@ targets:
|
||||
json_serializable:
|
||||
options:
|
||||
explicit_to_json: true
|
||||
field_rename: snake
|
||||
any_map: true
|
||||
field_rename: snake
|
||||
@@ -44,9 +44,9 @@ class StreamExample extends StatelessWidget {
|
||||
/// To initialize this example, an instance of
|
||||
/// [client] and [channel] is required.
|
||||
const StreamExample({
|
||||
Key key,
|
||||
@required this.client,
|
||||
@required this.channel,
|
||||
Key? key,
|
||||
required this.client,
|
||||
required this.channel,
|
||||
}) : super(key: key);
|
||||
|
||||
/// Instance of [StreamChatClient] we created earlier.
|
||||
@@ -69,28 +69,31 @@ class StreamExample extends StatelessWidget {
|
||||
/// containing the channel name and a [MessageView] displaying recent messages.
|
||||
class HomeScreen extends StatelessWidget {
|
||||
/// [HomeScreen] is constructed using the [Channel] we defined earlier.
|
||||
const HomeScreen({Key key, @required this.channel}) : super(key: key);
|
||||
const HomeScreen({
|
||||
Key? key,
|
||||
required this.channel,
|
||||
}) : super(key: key);
|
||||
|
||||
/// Channel object containing the [Channel.id] we'd like to observe.
|
||||
final Channel channel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final messages = channel.state.channelStateStream;
|
||||
final messages = channel.state!.channelStateStream;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Channel: ${channel.id}'),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: StreamBuilder<ChannelState>(
|
||||
child: StreamBuilder<ChannelState?>(
|
||||
stream: messages,
|
||||
builder: (
|
||||
BuildContext context,
|
||||
AsyncSnapshot<ChannelState> snapshot,
|
||||
AsyncSnapshot<ChannelState?> snapshot,
|
||||
) {
|
||||
if (snapshot.hasData && snapshot.data != null) {
|
||||
return MessageView(
|
||||
messages: snapshot.data.messages.reversed.toList(),
|
||||
messages: snapshot.data!.messages.reversed.toList(),
|
||||
channel: channel,
|
||||
);
|
||||
} else if (snapshot.hasError) {
|
||||
@@ -119,9 +122,9 @@ class HomeScreen extends StatelessWidget {
|
||||
class MessageView extends StatefulWidget {
|
||||
/// Message takes the latest list of messages and the current channel.
|
||||
const MessageView({
|
||||
Key key,
|
||||
@required this.messages,
|
||||
@required this.channel,
|
||||
Key? key,
|
||||
required this.messages,
|
||||
required this.channel,
|
||||
}) : super(key: key);
|
||||
|
||||
/// List of messages sent in the given channel.
|
||||
@@ -135,8 +138,8 @@ class MessageView extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MessageViewState extends State<MessageView> {
|
||||
TextEditingController _controller;
|
||||
ScrollController _scrollController;
|
||||
late final TextEditingController _controller;
|
||||
late final ScrollController _scrollController;
|
||||
|
||||
List<Message> get _messages => widget.messages;
|
||||
|
||||
@@ -174,12 +177,12 @@ class _MessageViewState extends State<MessageView> {
|
||||
reverse: true,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final item = _messages[index];
|
||||
if (item.user.id == widget.channel.client.uid) {
|
||||
if (item.user?.id == widget.channel.client.uid) {
|
||||
return Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Text(item.text),
|
||||
child: Text(item.text ?? ''),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@@ -187,7 +190,7 @@ class _MessageViewState extends State<MessageView> {
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Text(item.text),
|
||||
child: Text(item.text ?? ''),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -246,5 +249,5 @@ class _MessageViewState extends State<MessageView> {
|
||||
/// Helper extension for quickly retrieving
|
||||
/// the current user id from a [StreamChatClient].
|
||||
extension on StreamChatClient {
|
||||
String get uid => state.user.id;
|
||||
String get uid => state.user!.id;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ publish_to: "none"
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
cupertino_icons: ^1.0.0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,7 @@ class SortOption<T> {
|
||||
|
||||
/// Sorting field Comparator required for offline sorting
|
||||
@JsonKey(ignore: true)
|
||||
final Comparator<T> comparator;
|
||||
final Comparator<T>? comparator;
|
||||
|
||||
/// Serialize model to json
|
||||
Map<String, dynamic> toJson() => _$SortOptionToJson(this);
|
||||
@@ -70,31 +70,31 @@ class PaginationParams {
|
||||
|
||||
/// Filter on ids greater than the given value.
|
||||
@JsonKey(name: 'id_gt')
|
||||
final String greaterThan;
|
||||
final String? greaterThan;
|
||||
|
||||
/// Filter on ids greater than or equal to the given value.
|
||||
@JsonKey(name: 'id_gte')
|
||||
final String greaterThanOrEqual;
|
||||
final String? greaterThanOrEqual;
|
||||
|
||||
/// Filter on ids smaller than the given value.
|
||||
@JsonKey(name: 'id_lt')
|
||||
final String lessThan;
|
||||
final String? lessThan;
|
||||
|
||||
/// Filter on ids smaller than or equal to the given value.
|
||||
@JsonKey(name: 'id_lte')
|
||||
final String lessThanOrEqual;
|
||||
final String? lessThanOrEqual;
|
||||
|
||||
/// Serialize model to json
|
||||
Map<String, dynamic> toJson() => _$PaginationParamsToJson(this);
|
||||
|
||||
/// Creates a copy of [PaginationParams] with specified attributes overridden.
|
||||
PaginationParams copyWith({
|
||||
int limit,
|
||||
int offset,
|
||||
String greaterThan,
|
||||
String greaterThanOrEqual,
|
||||
String lessThan,
|
||||
String lessThanOrEqual,
|
||||
int? limit,
|
||||
int? offset,
|
||||
String? greaterThan,
|
||||
String? greaterThanOrEqual,
|
||||
String? lessThan,
|
||||
String? lessThanOrEqual,
|
||||
}) =>
|
||||
PaginationParams(
|
||||
limit: limit ?? this.limit,
|
||||
@@ -106,6 +106,7 @@ class PaginationParams {
|
||||
);
|
||||
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^
|
||||
limit.hashCode ^
|
||||
|
||||
@@ -13,7 +13,10 @@ Map<String, dynamic> _$SortOptionToJson<T>(SortOption<T> instance) =>
|
||||
};
|
||||
|
||||
Map<String, dynamic> _$PaginationParamsToJson(PaginationParams instance) {
|
||||
final val = <String, dynamic>{};
|
||||
final val = <String, dynamic>{
|
||||
'limit': instance.limit,
|
||||
'offset': instance.offset,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
@@ -21,8 +24,6 @@ Map<String, dynamic> _$PaginationParamsToJson(PaginationParams instance) {
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('limit', instance.limit);
|
||||
writeNotNull('offset', instance.offset);
|
||||
writeNotNull('id_gt', instance.greaterThan);
|
||||
writeNotNull('id_gte', instance.greaterThanOrEqual);
|
||||
writeNotNull('id_lt', instance.lessThan);
|
||||
|
||||
@@ -13,14 +13,15 @@ import 'package:stream_chat/src/models/user.dart';
|
||||
part 'responses.g.dart';
|
||||
|
||||
class _BaseResponse {
|
||||
String duration;
|
||||
String? duration;
|
||||
}
|
||||
|
||||
/// Model response for [StreamChatClient.resync] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SyncResponse extends _BaseResponse {
|
||||
/// The list of events
|
||||
List<Event> events;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Event> events;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SyncResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -31,7 +32,8 @@ class SyncResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryChannelsResponse extends _BaseResponse {
|
||||
/// List of channels state returned by the query
|
||||
List<ChannelState> channels;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<ChannelState> channels;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryChannelsResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -41,8 +43,8 @@ class QueryChannelsResponse extends _BaseResponse {
|
||||
/// Model response for [StreamChatClient.queryChannels] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class TranslateMessageResponse extends _BaseResponse {
|
||||
/// List of channels state returned by the query
|
||||
TranslatedMessage message;
|
||||
/// Translated message
|
||||
late TranslatedMessage message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static TranslateMessageResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -53,7 +55,8 @@ class TranslateMessageResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryMembersResponse extends _BaseResponse {
|
||||
/// List of channels state returned by the query
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -64,7 +67,8 @@ class QueryMembersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryUsersResponse extends _BaseResponse {
|
||||
/// List of users returned by the query
|
||||
List<User> users;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<User> users;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryUsersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -75,7 +79,8 @@ class QueryUsersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryReactionsResponse extends _BaseResponse {
|
||||
/// List of reactions returned by the query
|
||||
List<Reaction> reactions;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Reaction> reactions;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryReactionsResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -86,7 +91,8 @@ class QueryReactionsResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryRepliesResponse extends _BaseResponse {
|
||||
/// List of messages returned by the api call
|
||||
List<Message> messages;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Message> messages;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryRepliesResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -97,7 +103,8 @@ class QueryRepliesResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class ListDevicesResponse extends _BaseResponse {
|
||||
/// List of user devices
|
||||
List<Device> devices;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Device> devices;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static ListDevicesResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -108,7 +115,7 @@ class ListDevicesResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendFileResponse extends _BaseResponse {
|
||||
/// The url of the uploaded file
|
||||
String file;
|
||||
late String file;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendFileResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -119,7 +126,7 @@ class SendFileResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendImageResponse extends _BaseResponse {
|
||||
/// The url of the uploaded file
|
||||
String file;
|
||||
late String file;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendImageResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -130,10 +137,10 @@ class SendImageResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendReactionResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
late Message message;
|
||||
|
||||
/// The reaction created by the api call
|
||||
Reaction reaction;
|
||||
late Reaction reaction;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendReactionResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -144,10 +151,10 @@ class SendReactionResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class ConnectGuestUserResponse extends _BaseResponse {
|
||||
/// Guest user access token
|
||||
String accessToken;
|
||||
late String accessToken;
|
||||
|
||||
/// Guest user
|
||||
User user;
|
||||
late User user;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static ConnectGuestUserResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -158,7 +165,8 @@ class ConnectGuestUserResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class UpdateUsersResponse extends _BaseResponse {
|
||||
/// Updated users
|
||||
Map<String, User> users;
|
||||
@JsonKey(defaultValue: {})
|
||||
late Map<String, User> users;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static UpdateUsersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -169,7 +177,7 @@ class UpdateUsersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class UpdateMessageResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
late Message message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static UpdateMessageResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -180,7 +188,7 @@ class UpdateMessageResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendMessageResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
late Message message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendMessageResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -191,15 +199,15 @@ class SendMessageResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class GetMessageResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
late Message message;
|
||||
|
||||
/// Channel of the message
|
||||
ChannelModel channel;
|
||||
ChannelModel? channel;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static GetMessageResponse fromJson(Map<String, dynamic> json) {
|
||||
final res = _$GetMessageResponseFromJson(json);
|
||||
final jsonChannel = res.message?.extraData?.remove('channel');
|
||||
final jsonChannel = res.message.extraData.remove('channel');
|
||||
if (jsonChannel != null) {
|
||||
res.channel = ChannelModel.fromJson(jsonChannel);
|
||||
}
|
||||
@@ -211,7 +219,8 @@ class GetMessageResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SearchMessagesResponse extends _BaseResponse {
|
||||
/// List of messages returned by the api call
|
||||
List<GetMessageResponse> results;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<GetMessageResponse> results;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SearchMessagesResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -222,7 +231,8 @@ class SearchMessagesResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class GetMessagesByIdResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
List<Message> messages;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Message> messages;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static GetMessagesByIdResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -233,13 +243,13 @@ class GetMessagesByIdResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class UpdateChannelResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
List<Member>? members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static UpdateChannelResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -250,10 +260,10 @@ class UpdateChannelResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class PartialUpdateChannelResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
List<Member>? members;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static PartialUpdateChannelResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -264,13 +274,14 @@ class PartialUpdateChannelResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class InviteMembersResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static InviteMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -281,13 +292,14 @@ class InviteMembersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class RemoveMembersResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static RemoveMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -298,7 +310,7 @@ class RemoveMembersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendActionResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendActionResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -309,13 +321,14 @@ class SendActionResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class AddMembersResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static AddMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -326,13 +339,14 @@ class AddMembersResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class AcceptInviteResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static AcceptInviteResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -343,13 +357,14 @@ class AcceptInviteResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class RejectInviteResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static RejectInviteResponse fromJson(Map<String, dynamic> json) =>
|
||||
@@ -368,19 +383,23 @@ class EmptyResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class ChannelStateResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
late ChannelModel channel;
|
||||
|
||||
/// List of messages returned by the api call
|
||||
List<Message> messages;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Message> messages;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Member> members;
|
||||
|
||||
/// Number of users watching the channel
|
||||
int watcherCount;
|
||||
@JsonKey(defaultValue: 0)
|
||||
late int watcherCount;
|
||||
|
||||
/// List of read states
|
||||
List<Read> read;
|
||||
@JsonKey(defaultValue: [])
|
||||
late List<Read> read;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static ChannelStateResponse fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -6,394 +6,274 @@ part of 'responses.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
SyncResponse _$SyncResponseFromJson(Map json) {
|
||||
SyncResponse _$SyncResponseFromJson(Map<String, dynamic> json) {
|
||||
return SyncResponse()
|
||||
..duration = json['duration'] as String
|
||||
..events = (json['events'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Event.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..events = (json['events'] as List<dynamic>?)
|
||||
?.map((e) => Event.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
QueryChannelsResponse _$QueryChannelsResponseFromJson(Map json) {
|
||||
QueryChannelsResponse _$QueryChannelsResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return QueryChannelsResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channels = (json['channels'] as List)
|
||||
?.map((e) => e == null ? null : ChannelState.fromJson(e as Map))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..channels = (json['channels'] as List<dynamic>?)
|
||||
?.map((e) => ChannelState.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
TranslateMessageResponse _$TranslateMessageResponseFromJson(Map json) {
|
||||
TranslateMessageResponse _$TranslateMessageResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return TranslateMessageResponse()
|
||||
..duration = json['duration'] as String
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: TranslatedMessage.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
..duration = json['duration'] as String?
|
||||
..message =
|
||||
TranslatedMessage.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
QueryMembersResponse _$QueryMembersResponseFromJson(Map json) {
|
||||
QueryMembersResponse _$QueryMembersResponseFromJson(Map<String, dynamic> json) {
|
||||
return QueryMembersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
QueryUsersResponse _$QueryUsersResponseFromJson(Map json) {
|
||||
QueryUsersResponse _$QueryUsersResponseFromJson(Map<String, dynamic> json) {
|
||||
return QueryUsersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..users = (json['users'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: User.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..users = (json['users'] as List<dynamic>?)
|
||||
?.map((e) => User.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
QueryReactionsResponse _$QueryReactionsResponseFromJson(Map json) {
|
||||
QueryReactionsResponse _$QueryReactionsResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return QueryReactionsResponse()
|
||||
..duration = json['duration'] as String
|
||||
..reactions = (json['reactions'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Reaction.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..reactions = (json['reactions'] as List<dynamic>?)
|
||||
?.map((e) => Reaction.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
QueryRepliesResponse _$QueryRepliesResponseFromJson(Map json) {
|
||||
QueryRepliesResponse _$QueryRepliesResponseFromJson(Map<String, dynamic> json) {
|
||||
return QueryRepliesResponse()
|
||||
..duration = json['duration'] as String
|
||||
..messages = (json['messages'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Message.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..messages = (json['messages'] as List<dynamic>?)
|
||||
?.map((e) => Message.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
ListDevicesResponse _$ListDevicesResponseFromJson(Map json) {
|
||||
ListDevicesResponse _$ListDevicesResponseFromJson(Map<String, dynamic> json) {
|
||||
return ListDevicesResponse()
|
||||
..duration = json['duration'] as String
|
||||
..devices = (json['devices'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Device.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..devices = (json['devices'] as List<dynamic>?)
|
||||
?.map((e) => Device.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
SendFileResponse _$SendFileResponseFromJson(Map json) {
|
||||
SendFileResponse _$SendFileResponseFromJson(Map<String, dynamic> json) {
|
||||
return SendFileResponse()
|
||||
..duration = json['duration'] as String
|
||||
..duration = json['duration'] as String?
|
||||
..file = json['file'] as String;
|
||||
}
|
||||
|
||||
SendImageResponse _$SendImageResponseFromJson(Map json) {
|
||||
SendImageResponse _$SendImageResponseFromJson(Map<String, dynamic> json) {
|
||||
return SendImageResponse()
|
||||
..duration = json['duration'] as String
|
||||
..duration = json['duration'] as String?
|
||||
..file = json['file'] as String;
|
||||
}
|
||||
|
||||
SendReactionResponse _$SendReactionResponseFromJson(Map json) {
|
||||
SendReactionResponse _$SendReactionResponseFromJson(Map<String, dynamic> json) {
|
||||
return SendReactionResponse()
|
||||
..duration = json['duration'] as String
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..reaction = json['reaction'] == null
|
||||
? null
|
||||
: Reaction.fromJson((json['reaction'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
..duration = json['duration'] as String?
|
||||
..message = Message.fromJson(json['message'] as Map<String, dynamic>)
|
||||
..reaction = Reaction.fromJson(json['reaction'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
ConnectGuestUserResponse _$ConnectGuestUserResponseFromJson(Map json) {
|
||||
ConnectGuestUserResponse _$ConnectGuestUserResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return ConnectGuestUserResponse()
|
||||
..duration = json['duration'] as String
|
||||
..duration = json['duration'] as String?
|
||||
..accessToken = json['access_token'] as String
|
||||
..user = json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
..user = User.fromJson(json['user'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
UpdateUsersResponse _$UpdateUsersResponseFromJson(Map json) {
|
||||
UpdateUsersResponse _$UpdateUsersResponseFromJson(Map<String, dynamic> json) {
|
||||
return UpdateUsersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..users = (json['users'] as Map)?.map(
|
||||
(k, e) => MapEntry(
|
||||
k as String,
|
||||
e == null
|
||||
? null
|
||||
: User.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))),
|
||||
);
|
||||
..duration = json['duration'] as String?
|
||||
..users = (json['users'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, User.fromJson(e as Map<String, dynamic>)),
|
||||
) ??
|
||||
{};
|
||||
}
|
||||
|
||||
UpdateMessageResponse _$UpdateMessageResponseFromJson(Map json) {
|
||||
UpdateMessageResponse _$UpdateMessageResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return UpdateMessageResponse()
|
||||
..duration = json['duration'] as String
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
..duration = json['duration'] as String?
|
||||
..message = Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
SendMessageResponse _$SendMessageResponseFromJson(Map json) {
|
||||
SendMessageResponse _$SendMessageResponseFromJson(Map<String, dynamic> json) {
|
||||
return SendMessageResponse()
|
||||
..duration = json['duration'] as String
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
..duration = json['duration'] as String?
|
||||
..message = Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
GetMessageResponse _$GetMessageResponseFromJson(Map json) {
|
||||
GetMessageResponse _$GetMessageResponseFromJson(Map<String, dynamic> json) {
|
||||
return GetMessageResponse()
|
||||
..duration = json['duration'] as String
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..duration = json['duration'] as String?
|
||||
..message = Message.fromJson(json['message'] as Map<String, dynamic>)
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: ChannelModel.fromJson(json['channel'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
SearchMessagesResponse _$SearchMessagesResponseFromJson(Map json) {
|
||||
SearchMessagesResponse _$SearchMessagesResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return SearchMessagesResponse()
|
||||
..duration = json['duration'] as String
|
||||
..results = (json['results'] as List)
|
||||
?.map((e) => e == null ? null : GetMessageResponse.fromJson(e as Map))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..results = (json['results'] as List<dynamic>?)
|
||||
?.map((e) => GetMessageResponse.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
GetMessagesByIdResponse _$GetMessagesByIdResponseFromJson(Map json) {
|
||||
GetMessagesByIdResponse _$GetMessagesByIdResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return GetMessagesByIdResponse()
|
||||
..duration = json['duration'] as String
|
||||
..messages = (json['messages'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Message.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..messages = (json['messages'] as List<dynamic>?)
|
||||
?.map((e) => Message.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
UpdateChannelResponse _$UpdateChannelResponseFromJson(Map json) {
|
||||
UpdateChannelResponse _$UpdateChannelResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return UpdateChannelResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList()
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
PartialUpdateChannelResponse _$PartialUpdateChannelResponseFromJson(Map json) {
|
||||
PartialUpdateChannelResponse _$PartialUpdateChannelResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return PartialUpdateChannelResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
|
||||
InviteMembersResponse _$InviteMembersResponseFromJson(Map json) {
|
||||
InviteMembersResponse _$InviteMembersResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return InviteMembersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
RemoveMembersResponse _$RemoveMembersResponseFromJson(Map json) {
|
||||
RemoveMembersResponse _$RemoveMembersResponseFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return RemoveMembersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
SendActionResponse _$SendActionResponseFromJson(Map json) {
|
||||
SendActionResponse _$SendActionResponseFromJson(Map<String, dynamic> json) {
|
||||
return SendActionResponse()
|
||||
..duration = json['duration'] as String
|
||||
..duration = json['duration'] as String?
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
AddMembersResponse _$AddMembersResponseFromJson(Map json) {
|
||||
AddMembersResponse _$AddMembersResponseFromJson(Map<String, dynamic> json) {
|
||||
return AddMembersResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
AcceptInviteResponse _$AcceptInviteResponseFromJson(Map json) {
|
||||
AcceptInviteResponse _$AcceptInviteResponseFromJson(Map<String, dynamic> json) {
|
||||
return AcceptInviteResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
RejectInviteResponse _$RejectInviteResponseFromJson(Map json) {
|
||||
RejectInviteResponse _$RejectInviteResponseFromJson(Map<String, dynamic> json) {
|
||||
return RejectInviteResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..message = json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
));
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
EmptyResponse _$EmptyResponseFromJson(Map json) {
|
||||
return EmptyResponse()..duration = json['duration'] as String;
|
||||
EmptyResponse _$EmptyResponseFromJson(Map<String, dynamic> json) {
|
||||
return EmptyResponse()..duration = json['duration'] as String?;
|
||||
}
|
||||
|
||||
ChannelStateResponse _$ChannelStateResponseFromJson(Map json) {
|
||||
ChannelStateResponse _$ChannelStateResponseFromJson(Map<String, dynamic> json) {
|
||||
return ChannelStateResponse()
|
||||
..duration = json['duration'] as String
|
||||
..channel = json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
))
|
||||
..messages = (json['messages'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Message.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..members = (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList()
|
||||
..watcherCount = json['watcher_count'] as int
|
||||
..read = (json['read'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Read.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList();
|
||||
..duration = json['duration'] as String?
|
||||
..channel = ChannelModel.fromJson(json['channel'] as Map<String, dynamic>)
|
||||
..messages = (json['messages'] as List<dynamic>?)
|
||||
?.map((e) => Message.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..members = (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[]
|
||||
..watcherCount = json['watcher_count'] as int? ?? 0
|
||||
..read = (json['read'] as List<dynamic>?)
|
||||
?.map((e) => Read.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:stream_chat/src/client.dart';
|
||||
import 'package:stream_chat/src/exceptions.dart';
|
||||
|
||||
@@ -6,30 +5,30 @@ import 'package:stream_chat/src/exceptions.dart';
|
||||
class RetryPolicy {
|
||||
/// Instantiate a new RetryPolicy
|
||||
RetryPolicy({
|
||||
@required this.shouldRetry,
|
||||
@required this.retryTimeout,
|
||||
this.attempt,
|
||||
required this.shouldRetry,
|
||||
required this.retryTimeout,
|
||||
this.attempt = 0,
|
||||
});
|
||||
|
||||
/// The number of attempts tried so far
|
||||
int attempt = 0;
|
||||
|
||||
/// This function evaluates if we should retry the failure
|
||||
final bool Function(StreamChatClient client, int attempt, ApiError apiError)
|
||||
final bool Function(StreamChatClient client, int attempt, ApiError? apiError)
|
||||
shouldRetry;
|
||||
|
||||
/// In the case that we want to retry a failed request the retryTimeout
|
||||
/// method is called to determine the timeout
|
||||
final Duration Function(
|
||||
StreamChatClient client, int attempt, ApiError apiError) retryTimeout;
|
||||
StreamChatClient client, int attempt, ApiError? apiError) retryTimeout;
|
||||
|
||||
/// Creates a copy of [RetryPolicy] with specified attributes overridden.
|
||||
RetryPolicy copyWith({
|
||||
bool Function(StreamChatClient client, int attempt, ApiError apiError)
|
||||
bool Function(StreamChatClient client, int attempt, ApiError? apiError)?
|
||||
shouldRetry,
|
||||
Duration Function(StreamChatClient client, int attempt, ApiError apiError)
|
||||
Duration Function(StreamChatClient client, int attempt, ApiError? apiError)?
|
||||
retryTimeout,
|
||||
int attempt,
|
||||
int? attempt,
|
||||
}) =>
|
||||
RetryPolicy(
|
||||
retryTimeout: retryTimeout ?? this.retryTimeout,
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:stream_chat/src/api/channel.dart';
|
||||
import 'package:stream_chat/src/api/retry_policy.dart';
|
||||
import 'package:stream_chat/src/event_type.dart';
|
||||
@@ -14,7 +13,7 @@ import 'package:stream_chat/stream_chat.dart';
|
||||
class RetryQueue {
|
||||
/// Instantiate a new RetryQueue object
|
||||
RetryQueue({
|
||||
@required this.channel,
|
||||
required this.channel,
|
||||
this.logger,
|
||||
}) {
|
||||
_retryPolicy = channel.client.retryPolicy;
|
||||
@@ -28,14 +27,14 @@ class RetryQueue {
|
||||
final Channel channel;
|
||||
|
||||
/// The logger associated to this queue
|
||||
final Logger logger;
|
||||
final Logger? logger;
|
||||
|
||||
final _subscriptions = <StreamSubscription>[];
|
||||
|
||||
void _listenConnectionRecovered() {
|
||||
_subscriptions
|
||||
.add(channel.client.on(EventType.connectionRecovered).listen((event) {
|
||||
if (!_isRetrying && event.online) {
|
||||
if (!_isRetrying && event.online!) {
|
||||
_startRetrying();
|
||||
}
|
||||
}));
|
||||
@@ -43,12 +42,13 @@ class RetryQueue {
|
||||
|
||||
final HeapPriorityQueue<Message> _messageQueue = HeapPriorityQueue(_byDate);
|
||||
bool _isRetrying = false;
|
||||
RetryPolicy _retryPolicy;
|
||||
RetryPolicy? _retryPolicy;
|
||||
|
||||
/// Add a list of messages
|
||||
void add(List<Message> messages) {
|
||||
logger?.info('added ${messages.length} messages');
|
||||
final messageList = _messageQueue.toList();
|
||||
|
||||
_messageQueue.addAll(messages
|
||||
.where((element) => !messageList.any((m) => m.id == element.id)));
|
||||
|
||||
@@ -60,7 +60,7 @@ class RetryQueue {
|
||||
Future<void> _startRetrying() async {
|
||||
logger?.info('start retrying');
|
||||
_isRetrying = true;
|
||||
final retryPolicy = _retryPolicy.copyWith(attempt: 0);
|
||||
final retryPolicy = _retryPolicy!.copyWith(attempt: 0);
|
||||
|
||||
while (_messageQueue.isNotEmpty) {
|
||||
final message = _messageQueue.first;
|
||||
@@ -72,7 +72,7 @@ class RetryQueue {
|
||||
logger?.info('now ${_messageQueue.length} messages in the queue');
|
||||
retryPolicy.attempt = 0;
|
||||
} catch (error) {
|
||||
ApiError apiError;
|
||||
ApiError? apiError;
|
||||
if (error is DioError) {
|
||||
if (error.type == DioErrorType.response) {
|
||||
_messageQueue.remove(message);
|
||||
@@ -84,7 +84,7 @@ class RetryQueue {
|
||||
);
|
||||
} else if (error is ApiError) {
|
||||
apiError = error;
|
||||
if (apiError.status?.toString()?.startsWith('4') == true) {
|
||||
if (apiError.status?.toString().startsWith('4') == true) {
|
||||
_messageQueue.remove(message);
|
||||
return;
|
||||
}
|
||||
@@ -101,6 +101,7 @@ class RetryQueue {
|
||||
}
|
||||
|
||||
retryPolicy.attempt++;
|
||||
|
||||
final timeout = retryPolicy.retryTimeout(
|
||||
channel.client,
|
||||
retryPolicy.attempt,
|
||||
@@ -112,13 +113,13 @@ class RetryQueue {
|
||||
_isRetrying = false;
|
||||
}
|
||||
|
||||
void _sendFailedEvent(Message message) {
|
||||
final newStatus = message.status == MessageSendingStatus.sending
|
||||
void _sendFailedEvent(Message? message) {
|
||||
final newStatus = message!.status == MessageSendingStatus.sending
|
||||
? MessageSendingStatus.failed
|
||||
: (message.status == MessageSendingStatus.updating
|
||||
? MessageSendingStatus.failed_update
|
||||
: MessageSendingStatus.failed_delete);
|
||||
channel.state.addMessage(message.copyWith(
|
||||
channel.state!.addMessage(message.copyWith(
|
||||
status: newStatus,
|
||||
));
|
||||
}
|
||||
@@ -141,20 +142,24 @@ class RetryQueue {
|
||||
final messageList = _messageQueue.toList();
|
||||
if (event.message != null) {
|
||||
final messageIndex =
|
||||
messageList.indexWhere((m) => m.id == event.message.id);
|
||||
messageList.indexWhere((m) => m.id == event.message!.id);
|
||||
if (messageIndex == -1 &&
|
||||
[
|
||||
MessageSendingStatus.failed_update,
|
||||
MessageSendingStatus.failed,
|
||||
MessageSendingStatus.failed_delete,
|
||||
].contains(event.message.status)) {
|
||||
].contains(event.message!.status)) {
|
||||
logger?.info('add message from events');
|
||||
add([event.message]);
|
||||
final m = event.message;
|
||||
|
||||
if (m != null) {
|
||||
add([m]);
|
||||
}
|
||||
} else if (messageIndex != -1 &&
|
||||
[
|
||||
MessageSendingStatus.sent,
|
||||
null,
|
||||
].contains(event.message.status)) {
|
||||
].contains(event.message!.status)) {
|
||||
_messageQueue.remove(messageList[messageIndex]);
|
||||
}
|
||||
}
|
||||
@@ -171,10 +176,14 @@ class RetryQueue {
|
||||
final date1 = _getMessageDate(m1);
|
||||
final date2 = _getMessageDate(m2);
|
||||
|
||||
if (date1 == null || date2 == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return date1.compareTo(date2);
|
||||
}
|
||||
|
||||
static DateTime _getMessageDate(Message m1) {
|
||||
static DateTime? _getMessageDate(Message m1) {
|
||||
switch (m1.status) {
|
||||
case MessageSendingStatus.failed_delete:
|
||||
case MessageSendingStatus.deleting:
|
||||
|
||||
@@ -3,5 +3,5 @@ import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
|
||||
/// Html version of websocket implementation
|
||||
/// Used in Flutter web version
|
||||
WebSocketChannel connectWebSocket(String url, {Iterable<String> protocols}) =>
|
||||
WebSocketChannel connectWebSocket(String url, {Iterable<String>? protocols}) =>
|
||||
HtmlWebSocketChannel.connect(url, protocols: protocols);
|
||||
|
||||
@@ -3,5 +3,5 @@ import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
|
||||
/// IO version of websocket implementation
|
||||
/// Used in Flutter mobile version
|
||||
WebSocketChannel connectWebSocket(String url, {Iterable<String> protocols}) =>
|
||||
WebSocketChannel connectWebSocket(String url, {Iterable<String>? protocols}) =>
|
||||
IOWebSocketChannel.connect(url, protocols: protocols);
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
/// Stub version of websocket implementation
|
||||
/// Used just for conditional library import
|
||||
WebSocketChannel connectWebSocket(String url,
|
||||
{Iterable<String> protocols,
|
||||
Map<String, dynamic> headers,
|
||||
Duration pingInterval}) =>
|
||||
{Iterable<String>? protocols,
|
||||
Map<String, dynamic>? headers,
|
||||
Duration? pingInterval}) =>
|
||||
throw UnimplementedError();
|
||||
|
||||
@@ -16,8 +16,8 @@ typedef EventHandler = void Function(Event);
|
||||
/// Typedef used for connecting to a websocket. Method returns a
|
||||
/// [WebSocketChannel] and accepts a connection [url] and an optional
|
||||
/// [Iterable] of `protocols`.
|
||||
typedef ConnectWebSocket = WebSocketChannel Function(String url,
|
||||
{Iterable<String> protocols});
|
||||
typedef ConnectWebSocket = WebSocketChannel Function(String? url,
|
||||
{Iterable<String>? protocols});
|
||||
|
||||
// TODO: parse error even
|
||||
// TODO: if parsing an error into an event fails we should not hide the
|
||||
@@ -27,11 +27,11 @@ class WebSocket {
|
||||
/// Creates a new websocket
|
||||
/// To connect the WS call [connect]
|
||||
WebSocket({
|
||||
@required this.baseUrl,
|
||||
this.user,
|
||||
this.connectParams,
|
||||
this.connectPayload,
|
||||
this.handler,
|
||||
required this.baseUrl,
|
||||
required this.user,
|
||||
required this.handler,
|
||||
this.connectParams = const {},
|
||||
this.connectPayload = const {},
|
||||
this.logger,
|
||||
this.connectFunc,
|
||||
this.reconnectionMonitorInterval = 1,
|
||||
@@ -78,12 +78,12 @@ class WebSocket {
|
||||
final EventHandler handler;
|
||||
|
||||
/// A WS specific logger instance
|
||||
final Logger logger;
|
||||
final Logger? logger;
|
||||
|
||||
/// Connection function
|
||||
/// Used only for testing purpose
|
||||
@visibleForTesting
|
||||
final ConnectWebSocket connectFunc;
|
||||
final ConnectWebSocket? connectFunc;
|
||||
|
||||
/// Interval of the reconnection monitor timer
|
||||
/// This checks that it received a new event in the last
|
||||
@@ -107,43 +107,43 @@ class WebSocket {
|
||||
_connectionStatusController.add(status);
|
||||
|
||||
/// The current connection status value
|
||||
ConnectionStatus get connectionStatus => _connectionStatusController.value;
|
||||
ConnectionStatus? get connectionStatus => _connectionStatusController.value;
|
||||
|
||||
/// This notifies of connection status changes
|
||||
Stream<ConnectionStatus> get connectionStatusStream =>
|
||||
_connectionStatusController.stream;
|
||||
|
||||
String _path;
|
||||
late final String _path;
|
||||
int _retryAttempt = 1;
|
||||
WebSocketChannel _channel;
|
||||
Timer _healthCheck, _reconnectionMonitor;
|
||||
DateTime _lastEventAt;
|
||||
late WebSocketChannel _channel;
|
||||
Timer? _healthCheck, _reconnectionMonitor;
|
||||
DateTime? _lastEventAt;
|
||||
bool _manuallyDisconnected = false;
|
||||
bool _connecting = false;
|
||||
bool _reconnecting = false;
|
||||
|
||||
Event _decodeEvent(String source) => Event.fromJson(json.decode(source));
|
||||
|
||||
Completer<Event> _connectionCompleter = Completer<Event>();
|
||||
Completer<Event?> _connectionCompleter = Completer<Event?>();
|
||||
|
||||
/// Connect the WS using the parameters passed in the constructor
|
||||
Future<Event> connect() {
|
||||
Future<Event?> connect() async {
|
||||
_manuallyDisconnected = false;
|
||||
|
||||
if (_connecting) {
|
||||
logger.severe('already connecting');
|
||||
logger?.severe('already connecting');
|
||||
return null;
|
||||
}
|
||||
|
||||
_connecting = true;
|
||||
_connectionStatus = ConnectionStatus.connecting;
|
||||
|
||||
logger.info('connecting to $_path');
|
||||
logger?.info('connecting to $_path');
|
||||
|
||||
_channel =
|
||||
connectFunc?.call(_path) ?? WebSocketChannel.connect(Uri.parse(_path));
|
||||
_channel.stream.listen(
|
||||
(data) {
|
||||
(data) async {
|
||||
final jsonData = json.decode(data);
|
||||
if (jsonData['error'] != null) {
|
||||
return _onConnectionError(jsonData['error']);
|
||||
@@ -153,9 +153,7 @@ class WebSocket {
|
||||
onError: (error, stacktrace) {
|
||||
_onConnectionError(error, stacktrace);
|
||||
},
|
||||
onDone: () {
|
||||
_onDone();
|
||||
},
|
||||
onDone: _onDone,
|
||||
);
|
||||
return _connectionCompleter.future;
|
||||
}
|
||||
@@ -166,7 +164,7 @@ class WebSocket {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('connection closed | closeCode: ${_channel.closeCode} | '
|
||||
logger?.info('connection closed | closeCode: ${_channel.closeCode} | '
|
||||
'closedReason: ${_channel.closeReason}');
|
||||
|
||||
if (!_reconnecting) {
|
||||
@@ -180,10 +178,10 @@ class WebSocket {
|
||||
}
|
||||
|
||||
final event = _decodeEvent(data);
|
||||
logger.info('received new event: $data');
|
||||
logger?.info('received new event: $data');
|
||||
|
||||
if (_lastEventAt == null) {
|
||||
logger.info('connection estabilished');
|
||||
logger?.info('connection estabilished');
|
||||
_connecting = false;
|
||||
_reconnecting = false;
|
||||
_lastEventAt = DateTime.now();
|
||||
@@ -204,9 +202,9 @@ class WebSocket {
|
||||
}
|
||||
|
||||
Future<void> _onConnectionError(error, [stacktrace]) async {
|
||||
logger..severe('error connecting')..severe(error);
|
||||
logger?..severe('error connecting')..severe(error);
|
||||
if (stacktrace != null) {
|
||||
logger.severe(stacktrace);
|
||||
logger?.severe(stacktrace);
|
||||
}
|
||||
_connecting = false;
|
||||
|
||||
@@ -225,7 +223,7 @@ class WebSocket {
|
||||
void _reconnectionTimer(_) {
|
||||
final now = DateTime.now();
|
||||
if (_lastEventAt != null &&
|
||||
now.difference(_lastEventAt).inSeconds > reconnectionMonitorTimeout) {
|
||||
now.difference(_lastEventAt!).inSeconds > reconnectionMonitorTimeout) {
|
||||
_channel.sink.close();
|
||||
}
|
||||
}
|
||||
@@ -244,18 +242,18 @@ class WebSocket {
|
||||
return;
|
||||
}
|
||||
if (_connecting) {
|
||||
logger.info('already connecting');
|
||||
logger?.info('already connecting');
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('reconnecting..');
|
||||
logger?.info('reconnecting..');
|
||||
|
||||
_cancelTimers();
|
||||
|
||||
try {
|
||||
await connect();
|
||||
} catch (e) {
|
||||
logger.log(Level.SEVERE, e.toString());
|
||||
logger?.log(Level.SEVERE, e.toString());
|
||||
}
|
||||
await Future.delayed(
|
||||
Duration(seconds: min(_retryAttempt * 5, 25)),
|
||||
@@ -267,7 +265,7 @@ class WebSocket {
|
||||
}
|
||||
|
||||
Future<void> _reconnect() async {
|
||||
logger.info('reconnect');
|
||||
logger?.info('reconnect');
|
||||
if (!_reconnecting) {
|
||||
_reconnecting = true;
|
||||
_connectionStatus = ConnectionStatus.connecting;
|
||||
@@ -279,20 +277,20 @@ class WebSocket {
|
||||
void _cancelTimers() {
|
||||
_lastEventAt = null;
|
||||
if (_healthCheck != null) {
|
||||
_healthCheck.cancel();
|
||||
_healthCheck!.cancel();
|
||||
}
|
||||
if (_reconnectionMonitor != null) {
|
||||
_reconnectionMonitor.cancel();
|
||||
_reconnectionMonitor!.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void _healthCheckTimer(_) {
|
||||
logger.info('sending health.check');
|
||||
logger?.info('sending health.check');
|
||||
_channel.sink.add("{'type': 'health.check'}");
|
||||
}
|
||||
|
||||
void _startHealthCheck() {
|
||||
logger.info('start health check monitor');
|
||||
logger?.info('start health check monitor');
|
||||
|
||||
_healthCheck = Timer.periodic(
|
||||
Duration(seconds: healthCheckInterval),
|
||||
@@ -311,13 +309,13 @@ class WebSocket {
|
||||
if (_manuallyDisconnected) {
|
||||
return;
|
||||
}
|
||||
logger.info('disconnecting');
|
||||
logger?.info('disconnecting');
|
||||
_connectionCompleter = Completer();
|
||||
_cancelTimers();
|
||||
_reconnecting = false;
|
||||
_manuallyDisconnected = true;
|
||||
_connectionStatus = ConnectionStatus.disconnected;
|
||||
await _connectionStatusController.close();
|
||||
return _channel.sink.close();
|
||||
await _channel.sink.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:stream_chat/src/api/responses.dart';
|
||||
import 'package:stream_chat/src/client.dart';
|
||||
import 'package:stream_chat/src/models/attachment_file.dart';
|
||||
import 'package:stream_chat/src/extensions/string_extension.dart';
|
||||
import 'package:stream_chat/src/models/attachment_file.dart';
|
||||
|
||||
/// Class responsible for uploading images and files to a given channel
|
||||
abstract class AttachmentFileUploader {
|
||||
@@ -15,8 +15,8 @@ abstract class AttachmentFileUploader {
|
||||
AttachmentFile image,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
/// Uploads a [file] to the given channel.
|
||||
@@ -28,8 +28,8 @@ abstract class AttachmentFileUploader {
|
||||
AttachmentFile file,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
/// Deletes a image using its [url] from the given channel.
|
||||
@@ -40,7 +40,7 @@ abstract class AttachmentFileUploader {
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
/// Deletes a file using its [url] from the given channel.
|
||||
@@ -51,7 +51,7 @@ abstract class AttachmentFileUploader {
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -67,22 +67,22 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
AttachmentFile file,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final filename = file.path?.split('/')?.last ?? file.name;
|
||||
final mimeType = filename.mimeType;
|
||||
final filename = file.path?.split('/').last ?? file.name;
|
||||
final mimeType = filename?.mimeType;
|
||||
|
||||
MultipartFile multiPartFile;
|
||||
MultipartFile? multiPartFile;
|
||||
if (file.path != null) {
|
||||
multiPartFile = await MultipartFile.fromFile(
|
||||
file.path,
|
||||
file.path!,
|
||||
filename: filename,
|
||||
contentType: mimeType,
|
||||
);
|
||||
} else if (file.bytes != null) {
|
||||
multiPartFile = MultipartFile.fromBytes(
|
||||
file.bytes,
|
||||
file.bytes!,
|
||||
filename: filename,
|
||||
contentType: mimeType,
|
||||
);
|
||||
@@ -104,22 +104,22 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
AttachmentFile file,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final filename = file.path?.split('/')?.last ?? file.name;
|
||||
final mimeType = filename.mimeType;
|
||||
final filename = file.path?.split('/').last ?? file.name;
|
||||
final mimeType = filename?.mimeType;
|
||||
|
||||
MultipartFile multiPartFile;
|
||||
MultipartFile? multiPartFile;
|
||||
if (file.path != null) {
|
||||
multiPartFile = await MultipartFile.fromFile(
|
||||
file.path,
|
||||
file.path!,
|
||||
filename: filename,
|
||||
contentType: mimeType,
|
||||
);
|
||||
} else if (file.bytes != null) {
|
||||
multiPartFile = MultipartFile.fromBytes(
|
||||
file.bytes,
|
||||
file.bytes!,
|
||||
filename: filename,
|
||||
contentType: mimeType,
|
||||
);
|
||||
@@ -141,7 +141,7 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final response = await _client.delete(
|
||||
'/channels/$channelType/$channelId/image',
|
||||
@@ -156,7 +156,7 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final response = await _client.delete(
|
||||
'/channels/$channelType/$channelId/file',
|
||||
|
||||
@@ -38,7 +38,7 @@ typedef DecoderFunction<T> = T Function(Map<String, dynamic>);
|
||||
|
||||
/// A function which can be used to request a Stream Chat API token from your
|
||||
/// own backend server. Function requires a single [userId].
|
||||
typedef TokenProvider = Future<String> Function(String userId);
|
||||
typedef TokenProvider = Future<String> Function(String? userId);
|
||||
|
||||
/// Provider used to send push notifications.
|
||||
enum PushProvider {
|
||||
@@ -82,58 +82,59 @@ class StreamChatClient {
|
||||
this.tokenProvider,
|
||||
this.baseURL = _defaultBaseURL,
|
||||
this.logLevel = Level.WARNING,
|
||||
this.logHandlerFunction,
|
||||
LogHandlerFunction? logHandlerFunction,
|
||||
Duration connectTimeout = const Duration(seconds: 6),
|
||||
Duration receiveTimeout = const Duration(seconds: 6),
|
||||
Dio httpClient,
|
||||
RetryPolicy retryPolicy,
|
||||
Dio? httpClient,
|
||||
RetryPolicy? retryPolicy,
|
||||
this.attachmentFileUploader,
|
||||
}) {
|
||||
_retryPolicy = retryPolicy ??
|
||||
RetryPolicy(
|
||||
retryTimeout:
|
||||
(StreamChatClient client, int attempt, ApiError error) =>
|
||||
(StreamChatClient client, int attempt, ApiError? error) =>
|
||||
Duration(seconds: 1 * attempt),
|
||||
shouldRetry: (StreamChatClient client, int attempt, ApiError error) =>
|
||||
attempt < 5,
|
||||
shouldRetry:
|
||||
(StreamChatClient client, int attempt, ApiError? error) =>
|
||||
attempt < 5,
|
||||
);
|
||||
|
||||
attachmentFileUploader ??= StreamAttachmentFileUploader(this);
|
||||
|
||||
state = ClientState(this);
|
||||
|
||||
_setupLogger();
|
||||
_setupLogger(logHandlerFunction);
|
||||
_setupDio(httpClient, receiveTimeout, connectTimeout);
|
||||
|
||||
logger.info('instantiating new client');
|
||||
}
|
||||
|
||||
set chatPersistenceClient(ChatPersistenceClient value) {
|
||||
set chatPersistenceClient(ChatPersistenceClient? value) {
|
||||
_originalChatPersistenceClient = value;
|
||||
}
|
||||
|
||||
ChatPersistenceClient _originalChatPersistenceClient;
|
||||
ChatPersistenceClient? _originalChatPersistenceClient;
|
||||
|
||||
/// Chat persistence client
|
||||
ChatPersistenceClient get chatPersistenceClient => _chatPersistenceClient;
|
||||
ChatPersistenceClient? get chatPersistenceClient => _chatPersistenceClient;
|
||||
|
||||
ChatPersistenceClient _chatPersistenceClient;
|
||||
ChatPersistenceClient? _chatPersistenceClient;
|
||||
|
||||
/// Attachment uploader
|
||||
AttachmentFileUploader attachmentFileUploader;
|
||||
AttachmentFileUploader? attachmentFileUploader;
|
||||
|
||||
/// Whether the chat persistence is available or not
|
||||
bool get persistenceEnabled => _chatPersistenceClient != null;
|
||||
|
||||
RetryPolicy _retryPolicy;
|
||||
RetryPolicy? _retryPolicy;
|
||||
|
||||
bool _synced = false;
|
||||
|
||||
/// The retry policy options getter
|
||||
RetryPolicy get retryPolicy => _retryPolicy;
|
||||
RetryPolicy? get retryPolicy => _retryPolicy;
|
||||
|
||||
/// This client state
|
||||
ClientState state;
|
||||
late ClientState state;
|
||||
|
||||
/// By default the Chat client will write all messages with level Warn or
|
||||
/// Error to stdout.
|
||||
@@ -169,7 +170,7 @@ class StreamChatClient {
|
||||
/// final client = StreamChatClient("stream-chat-api-key",
|
||||
/// logHandlerFunction: myLogHandlerFunction);
|
||||
///```
|
||||
LogHandlerFunction logHandlerFunction;
|
||||
late LogHandlerFunction logHandlerFunction;
|
||||
|
||||
/// Your project Stream Chat api key.
|
||||
/// Find your API keys here https://getstream.io/dashboard/
|
||||
@@ -184,7 +185,7 @@ class StreamChatClient {
|
||||
/// The token will be the return value of the function.
|
||||
/// It's used by the client to refresh the token once expired or to connect
|
||||
/// the user without a predefined token using [connectUserWithProvider].
|
||||
final TokenProvider tokenProvider;
|
||||
final TokenProvider? tokenProvider;
|
||||
|
||||
/// [Dio] httpClient
|
||||
/// It's be chosen because it's easy to use and supports interesting features
|
||||
@@ -195,8 +196,8 @@ class StreamChatClient {
|
||||
|
||||
static const _defaultBaseURL = 'chat-us-east-1.stream-io-api.com';
|
||||
static const _tokenExpiredErrorCode = 40;
|
||||
StreamSubscription<ConnectionStatus> _connectionStatusSubscription;
|
||||
Future<void> Function(ConnectionStatus) _connectionStatusHandler;
|
||||
StreamSubscription<ConnectionStatus>? _connectionStatusSubscription;
|
||||
Future<void> Function(ConnectionStatus)? _connectionStatusHandler;
|
||||
|
||||
final BehaviorSubject<Event> _controller = BehaviorSubject<Event>();
|
||||
|
||||
@@ -211,7 +212,7 @@ class StreamChatClient {
|
||||
_wsConnectionStatusController.add(status);
|
||||
|
||||
/// The current status value of the websocket connection
|
||||
ConnectionStatus get wsConnectionStatus =>
|
||||
ConnectionStatus? get wsConnectionStatus =>
|
||||
_wsConnectionStatusController.value;
|
||||
|
||||
/// This notifies the connection status of the websocket connection.
|
||||
@@ -220,19 +221,19 @@ class StreamChatClient {
|
||||
_wsConnectionStatusController.stream;
|
||||
|
||||
/// The current user token
|
||||
String token;
|
||||
String? token;
|
||||
|
||||
/// The id of the current websocket connection
|
||||
String get connectionId => _connectionId;
|
||||
String? get connectionId => _connectionId;
|
||||
|
||||
bool _anonymous = false;
|
||||
String _connectionId;
|
||||
WebSocket _ws;
|
||||
String? _connectionId;
|
||||
late WebSocket _ws;
|
||||
|
||||
bool get _hasConnectionId => _connectionId != null;
|
||||
|
||||
void _setupDio(
|
||||
Dio httpClient,
|
||||
Dio? httpClient,
|
||||
Duration receiveTimeout,
|
||||
Duration connectTimeout,
|
||||
) {
|
||||
@@ -267,9 +268,8 @@ class StreamChatClient {
|
||||
var stringData = options.data.toString();
|
||||
|
||||
if (options.data is FormData) {
|
||||
final multiPart = (options.data as FormData).files[0]?.value;
|
||||
stringData =
|
||||
'${multiPart?.filename} - ${multiPart?.contentType}';
|
||||
final multiPart = (options.data as FormData).files[0].value;
|
||||
stringData = '${multiPart.filename} - ${multiPart.contentType}';
|
||||
}
|
||||
|
||||
logger.info('''
|
||||
@@ -301,11 +301,11 @@ class StreamChatClient {
|
||||
|
||||
if (tokenProvider != null) {
|
||||
httpClient.lock();
|
||||
final userId = state.user.id;
|
||||
final userId = state.user!.id;
|
||||
|
||||
await _disconnect();
|
||||
|
||||
final newToken = await tokenProvider(userId);
|
||||
final newToken = await tokenProvider!(userId);
|
||||
await Future.delayed(const Duration(seconds: 4));
|
||||
token = newToken;
|
||||
|
||||
@@ -341,13 +341,11 @@ class StreamChatClient {
|
||||
),
|
||||
),
|
||||
);
|
||||
} catch (err) {
|
||||
} on DioError {
|
||||
handler.reject(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
LogHandlerFunction _getDefaultLogHandler() {
|
||||
@@ -373,14 +371,14 @@ class StreamChatClient {
|
||||
) =>
|
||||
Logger.detached(name)
|
||||
..level = logLevel
|
||||
..onRecord.listen(logHandlerFunction ?? _getDefaultLogHandler());
|
||||
..onRecord.listen(logHandlerFunction);
|
||||
|
||||
void _setupLogger() {
|
||||
void _setupLogger(LogHandlerFunction? logHandlerFunction) {
|
||||
logger.level = logLevel;
|
||||
|
||||
logHandlerFunction ??= _getDefaultLogHandler();
|
||||
this.logHandlerFunction = logHandlerFunction ?? _getDefaultLogHandler();
|
||||
|
||||
logger.onRecord.listen(logHandlerFunction);
|
||||
logger.onRecord.listen(this.logHandlerFunction);
|
||||
|
||||
logger.info('logger setup');
|
||||
}
|
||||
@@ -395,7 +393,7 @@ class StreamChatClient {
|
||||
await _wsConnectionStatusController.close();
|
||||
}
|
||||
|
||||
Map<String, String> get _httpHeaders => {
|
||||
Map<String, String?> get _httpHeaders => {
|
||||
'Authorization': token,
|
||||
'stream-auth-type': _authType,
|
||||
'X-Stream-Client': _userAgent,
|
||||
@@ -405,12 +403,12 @@ class StreamChatClient {
|
||||
/// Set the current user, this triggers a connection to the API.
|
||||
/// It returns a [Future] that resolves when the connection is setup.
|
||||
@Deprecated('Use `connectUser` instead. Will be removed in Future releases')
|
||||
Future<Event> setUser(User user, String token) => connectUser(user, token);
|
||||
Future<Event?> setUser(User user, String token) => connectUser(user, token);
|
||||
|
||||
/// Connects the current user, this triggers a connection to the API.
|
||||
/// It returns a [Future] that resolves when the connection is setup.
|
||||
Future<Event> connectUser(User user, String token) async {
|
||||
if (_connectCompleter != null && !_connectCompleter.isCompleted) {
|
||||
Future<Event?> connectUser(User? user, String? token) async {
|
||||
if (_connectCompleter != null && !_connectCompleter!.isCompleted) {
|
||||
logger.warning('Already connecting');
|
||||
throw Exception('Already connecting');
|
||||
}
|
||||
@@ -418,15 +416,23 @@ class StreamChatClient {
|
||||
_connectCompleter = Completer();
|
||||
|
||||
logger.info('connect user');
|
||||
|
||||
if (user == null) {
|
||||
final e = Error();
|
||||
_connectCompleter!
|
||||
.completeError(e, StackTrace.fromString('No user provided.'));
|
||||
throw e;
|
||||
}
|
||||
|
||||
state.user = OwnUser.fromJson(user.toJson());
|
||||
this.token = token;
|
||||
_anonymous = false;
|
||||
|
||||
return connect().then((event) {
|
||||
_connectCompleter.complete(event);
|
||||
_connectCompleter!.complete(event);
|
||||
return event;
|
||||
}).catchError((e, s) {
|
||||
_connectCompleter.completeError(e, s);
|
||||
_connectCompleter!.completeError(e, s);
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
@@ -436,28 +442,29 @@ class StreamChatClient {
|
||||
@Deprecated(
|
||||
'Use `connectUserWithProvider` instead. Will be removed in Future releases',
|
||||
)
|
||||
Future<Event> setUserWithProvider(User user) => connectUserWithProvider(user);
|
||||
Future<Event?> setUserWithProvider(User user) =>
|
||||
connectUserWithProvider(user);
|
||||
|
||||
/// Connects the current user using the [tokenProvider] to fetch the token.
|
||||
/// It returns a [Future] that resolves when the connection is setup.
|
||||
Future<Event> connectUserWithProvider(User user) async {
|
||||
Future<Event?> connectUserWithProvider(User user) async {
|
||||
if (tokenProvider == null) {
|
||||
throw Exception('''
|
||||
TokenProvider must be provided in the constructor in order to use `connectUserWithProvider` method.
|
||||
Use `connectUser` providing a token.
|
||||
''');
|
||||
}
|
||||
final token = await tokenProvider(user.id);
|
||||
final token = await tokenProvider!(user.id);
|
||||
return connectUser(user, token);
|
||||
}
|
||||
|
||||
/// Stream of [Event] coming from websocket connection
|
||||
/// Pass an eventType as parameter in order to filter just a type of event
|
||||
Stream<Event> on([
|
||||
String eventType,
|
||||
String eventType2,
|
||||
String eventType3,
|
||||
String eventType4,
|
||||
String? eventType,
|
||||
String? eventType2,
|
||||
String? eventType3,
|
||||
String? eventType4,
|
||||
]) =>
|
||||
stream.where((event) =>
|
||||
eventType == null ||
|
||||
@@ -475,9 +482,10 @@ class StreamChatClient {
|
||||
}
|
||||
|
||||
if (!event.isLocal) {
|
||||
if (_synced && event.createdAt != null) {
|
||||
final createdAt = event.createdAt;
|
||||
if (_synced && createdAt != null) {
|
||||
await _chatPersistenceClient?.updateConnectionInfo(event);
|
||||
await _chatPersistenceClient?.updateLastSyncAt(event.createdAt);
|
||||
await _chatPersistenceClient?.updateLastSyncAt(createdAt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,10 +499,10 @@ class StreamChatClient {
|
||||
_controller.add(event);
|
||||
}
|
||||
|
||||
Completer<Event> _connectCompleter;
|
||||
Completer<Event>? _connectCompleter;
|
||||
|
||||
/// Connect the client websocket
|
||||
Future<Event> connect() async {
|
||||
Future<Event?> connect() async {
|
||||
logger.info('connecting');
|
||||
if (wsConnectionStatus == ConnectionStatus.connecting) {
|
||||
logger.warning('Already connecting');
|
||||
@@ -510,20 +518,20 @@ class StreamChatClient {
|
||||
|
||||
if (_originalChatPersistenceClient != null) {
|
||||
_chatPersistenceClient = _originalChatPersistenceClient;
|
||||
await _chatPersistenceClient.connect(state.user.id);
|
||||
await _chatPersistenceClient!.connect(state.user!.id);
|
||||
}
|
||||
|
||||
_ws = WebSocket(
|
||||
baseUrl: baseURL,
|
||||
user: state.user,
|
||||
user: state.user!,
|
||||
connectParams: {
|
||||
'api_key': apiKey,
|
||||
'authorization': token,
|
||||
'authorization': token!,
|
||||
'stream-auth-type': _authType,
|
||||
'X-Stream-Client': _userAgent,
|
||||
},
|
||||
connectPayload: {
|
||||
'user_id': state.user.id,
|
||||
'user_id': state.user!.id,
|
||||
'server_determines_connection_id': true,
|
||||
},
|
||||
handler: handleEvent,
|
||||
@@ -540,7 +548,7 @@ class StreamChatClient {
|
||||
);
|
||||
|
||||
if (status == ConnectionStatus.connected) {
|
||||
handleEvent(Event(
|
||||
handleEvent(const Event(
|
||||
type: EventType.connectionRecovered,
|
||||
online: true,
|
||||
));
|
||||
@@ -548,7 +556,7 @@ class StreamChatClient {
|
||||
// ignore: unawaited_futures
|
||||
queryChannelsOnline(filter: {
|
||||
'cid': {
|
||||
'\$in': state.channels.keys.toList(),
|
||||
'\$in': state.channels!.keys.toList(),
|
||||
},
|
||||
}).then(
|
||||
(_) async {
|
||||
@@ -567,8 +575,10 @@ class StreamChatClient {
|
||||
var event = await _chatPersistenceClient?.getConnectionInfo();
|
||||
|
||||
await _ws.connect().then((e) async {
|
||||
await _chatPersistenceClient?.updateConnectionInfo(e);
|
||||
event = e;
|
||||
if (e != null) {
|
||||
await _chatPersistenceClient?.updateConnectionInfo(e);
|
||||
event = e;
|
||||
}
|
||||
await resync();
|
||||
}).catchError((err, stacktrace) {
|
||||
logger.severe('error connecting ws', err, stacktrace);
|
||||
@@ -582,7 +592,7 @@ class StreamChatClient {
|
||||
}
|
||||
|
||||
/// Get the events missed while offline to sync the offline storage
|
||||
Future<void> resync([List<String> cids]) async {
|
||||
Future<void> resync([List<String>? cids]) async {
|
||||
final lastSyncAt = await _chatPersistenceClient?.getLastSyncAt();
|
||||
|
||||
if (lastSyncAt == null) {
|
||||
@@ -608,7 +618,7 @@ class StreamChatClient {
|
||||
SyncResponse.fromJson,
|
||||
);
|
||||
|
||||
res.events.sort((a, b) => a.createdAt.compareTo(b.createdAt));
|
||||
res.events.sort((a, b) => a.createdAt!.compareTo(b.createdAt!));
|
||||
|
||||
res.events.forEach((element) {
|
||||
logger
|
||||
@@ -625,26 +635,26 @@ class StreamChatClient {
|
||||
}
|
||||
}
|
||||
|
||||
String _asMap(sort) => sort?.map((s) => s.toJson().toString())?.join('');
|
||||
String? _asMap(sort) => sort?.map((s) => s.toJson().toString())?.join('');
|
||||
|
||||
final _queryChannelsStreams = <String, Future<List<Channel>>>{};
|
||||
|
||||
/// Requests channels with a given query.
|
||||
Stream<List<Channel>> queryChannels({
|
||||
Map<String, dynamic> filter,
|
||||
List<SortOption<ChannelModel>> sort,
|
||||
Map<String, dynamic> options,
|
||||
Map<String, dynamic>? filter,
|
||||
List<SortOption<ChannelModel>>? sort,
|
||||
Map<String, dynamic>? options,
|
||||
PaginationParams paginationParams = const PaginationParams(),
|
||||
int messageLimit,
|
||||
int? messageLimit,
|
||||
bool waitForConnect = true,
|
||||
}) async* {
|
||||
final hash = base64.encode(utf8.encode(
|
||||
'$filter${_asMap(sort)}$options${paginationParams?.toJson()}'
|
||||
'$filter${_asMap(sort)}$options${paginationParams.toJson()}'
|
||||
'$messageLimit',
|
||||
));
|
||||
|
||||
if (_queryChannelsStreams.containsKey(hash)) {
|
||||
yield await _queryChannelsStreams[hash];
|
||||
yield await _queryChannelsStreams[hash]!;
|
||||
} else {
|
||||
final channels = await queryChannelsOffline(
|
||||
filter: filter,
|
||||
@@ -674,17 +684,17 @@ class StreamChatClient {
|
||||
|
||||
/// Requests channels with a given query from the API.
|
||||
Future<List<Channel>> queryChannelsOnline({
|
||||
@required Map<String, dynamic> filter,
|
||||
List<SortOption<ChannelModel>> sort,
|
||||
Map<String, dynamic> options,
|
||||
int messageLimit,
|
||||
required Map<String, dynamic>? filter,
|
||||
List<SortOption<ChannelModel>>? sort,
|
||||
Map<String, dynamic>? options,
|
||||
int? messageLimit,
|
||||
PaginationParams paginationParams = const PaginationParams(),
|
||||
bool waitForConnect = true,
|
||||
}) async {
|
||||
if (waitForConnect) {
|
||||
if (_connectCompleter != null && !_connectCompleter.isCompleted) {
|
||||
if (_connectCompleter != null && !_connectCompleter!.isCompleted) {
|
||||
logger.info('awaiting connection completer');
|
||||
await _connectCompleter.future;
|
||||
await _connectCompleter!.future;
|
||||
}
|
||||
if (wsConnectionStatus != ConnectionStatus.connected) {
|
||||
throw Exception(
|
||||
@@ -716,9 +726,7 @@ class StreamChatClient {
|
||||
payload.addAll(options);
|
||||
}
|
||||
|
||||
if (paginationParams != null) {
|
||||
payload.addAll(paginationParams.toJson());
|
||||
}
|
||||
payload.addAll(paginationParams.toJson());
|
||||
|
||||
final response = await get(
|
||||
'/channels',
|
||||
@@ -732,7 +740,7 @@ class StreamChatClient {
|
||||
QueryChannelsResponse.fromJson,
|
||||
);
|
||||
|
||||
if ((res.channels ?? []).isEmpty && (paginationParams?.offset ?? 0) == 0) {
|
||||
if (res.channels.isEmpty && paginationParams.offset == 0) {
|
||||
logger.warning(
|
||||
'''
|
||||
We could not find any channel for this query.
|
||||
@@ -751,15 +759,14 @@ class StreamChatClient {
|
||||
|
||||
state._updateUsers(users);
|
||||
|
||||
logger.info('Got ${res.channels?.length} channels from api');
|
||||
logger.info('Got ${res.channels.length} channels from api');
|
||||
|
||||
final updateData = _mapChannelStateToChannel(channels);
|
||||
|
||||
await _chatPersistenceClient?.updateChannelQueries(
|
||||
filter,
|
||||
channels.map((c) => c.channel.cid).toList(),
|
||||
clearQueryCache:
|
||||
paginationParams?.offset == null || paginationParams.offset == 0,
|
||||
filter ?? {},
|
||||
channels.map((c) => c.channel!.cid).toList(),
|
||||
clearQueryCache: paginationParams.offset == 0,
|
||||
);
|
||||
|
||||
state.channels = updateData.key;
|
||||
@@ -768,36 +775,34 @@ class StreamChatClient {
|
||||
|
||||
/// Requests channels with a given query from the Persistence client.
|
||||
Future<List<Channel>> queryChannelsOffline({
|
||||
@required Map<String, dynamic> filter,
|
||||
@required List<SortOption<ChannelModel>> sort,
|
||||
required Map<String, dynamic>? filter,
|
||||
required List<SortOption<ChannelModel>>? sort,
|
||||
PaginationParams paginationParams = const PaginationParams(),
|
||||
}) async {
|
||||
final offlineChannels = await _chatPersistenceClient?.getChannelStates(
|
||||
final offlineChannels = (await _chatPersistenceClient?.getChannelStates(
|
||||
filter: filter,
|
||||
sort: sort,
|
||||
paginationParams: paginationParams,
|
||||
);
|
||||
))!;
|
||||
final updatedData = _mapChannelStateToChannel(offlineChannels);
|
||||
state.channels = updatedData.key;
|
||||
return updatedData.value;
|
||||
}
|
||||
|
||||
MapEntry<Map<String, Channel>, List<Channel>> _mapChannelStateToChannel(
|
||||
MapEntry<Map<String?, Channel>, List<Channel>> _mapChannelStateToChannel(
|
||||
List<ChannelState> channelStates,
|
||||
) {
|
||||
final channels = {...state.channels ?? {}};
|
||||
final newChannels = <Channel>[];
|
||||
if (channelStates != null) {
|
||||
for (final channelState in channelStates) {
|
||||
final channel = channels[channelState.channel.cid];
|
||||
if (channel != null) {
|
||||
channel.state?.updateChannelState(channelState);
|
||||
newChannels.add(channel);
|
||||
} else {
|
||||
final newChannel = Channel.fromState(this, channelState);
|
||||
channels[newChannel.cid] = newChannel;
|
||||
newChannels.add(newChannel);
|
||||
}
|
||||
for (final channelState in channelStates) {
|
||||
final channel = channels[channelState.channel!.cid];
|
||||
if (channel != null) {
|
||||
channel.state!.updateChannelState(channelState);
|
||||
newChannels.add(channel);
|
||||
} else {
|
||||
final newChannel = Channel.fromState(this, channelState);
|
||||
channels[newChannel.cid] = newChannel;
|
||||
newChannels.add(newChannel);
|
||||
}
|
||||
}
|
||||
return MapEntry(channels, newChannels);
|
||||
@@ -817,7 +822,7 @@ class StreamChatClient {
|
||||
/// Handy method to make http GET request with error parsing.
|
||||
Future<Response<String>> get(
|
||||
String path, {
|
||||
Map<String, dynamic> queryParameters,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
try {
|
||||
final response = await httpClient.get<String>(
|
||||
@@ -835,8 +840,8 @@ class StreamChatClient {
|
||||
Future<Response<String>> post(
|
||||
String path, {
|
||||
dynamic data,
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
try {
|
||||
final response = await httpClient.post<String>(
|
||||
@@ -855,8 +860,8 @@ class StreamChatClient {
|
||||
/// Handy method to make http DELETE request with error parsing.
|
||||
Future<Response<String>> delete(
|
||||
String path, {
|
||||
Map<String, dynamic> queryParameters,
|
||||
CancelToken cancelToken,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
try {
|
||||
final response = await httpClient.delete<String>(
|
||||
@@ -874,7 +879,7 @@ class StreamChatClient {
|
||||
/// Handy method to make http PATCH request with error parsing.
|
||||
Future<Response<String>> patch(
|
||||
String path, {
|
||||
Map<String, dynamic> queryParameters,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
dynamic data,
|
||||
}) async {
|
||||
try {
|
||||
@@ -893,7 +898,7 @@ class StreamChatClient {
|
||||
/// Handy method to make http PUT request with error parsing.
|
||||
Future<Response<String>> put(
|
||||
String path, {
|
||||
Map<String, dynamic> queryParameters,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
dynamic data,
|
||||
}) async {
|
||||
try {
|
||||
@@ -910,12 +915,10 @@ class StreamChatClient {
|
||||
}
|
||||
|
||||
/// Used to log errors and stacktrace in case of bad json deserialization
|
||||
T decode<T>(String j, DecoderFunction<T> decoderFunction) {
|
||||
T decode<T>(String? j, DecoderFunction<T> decoderFunction) {
|
||||
try {
|
||||
if (j == null) {
|
||||
return null;
|
||||
}
|
||||
return decoderFunction(json.decode(j));
|
||||
final data = j ?? '{}';
|
||||
return decoderFunction(json.decode(data));
|
||||
} catch (error, stacktrace) {
|
||||
logger.severe('Error decoding response', error, stacktrace);
|
||||
rethrow;
|
||||
@@ -927,7 +930,7 @@ class StreamChatClient {
|
||||
String get _userAgent => 'stream-chat-dart-client-${CurrentPlatform.name}-'
|
||||
'${PACKAGE_VERSION.split('+')[0]}';
|
||||
|
||||
Map<String, String> get _commonQueryParams => {
|
||||
Map<String, String?> get _commonQueryParams => {
|
||||
'user_id': state.user?.id,
|
||||
'api_key': apiKey,
|
||||
'connection_id': _connectionId,
|
||||
@@ -937,13 +940,13 @@ class StreamChatClient {
|
||||
/// the API. It returns a [Future] that resolves when the connection is setup.
|
||||
@Deprecated(
|
||||
'Use `connectAnonymousUser` instead. Will be removed in Future releases')
|
||||
Future<Event> setAnonymousUser() => connectAnonymousUser();
|
||||
Future<Event?> setAnonymousUser() => connectAnonymousUser();
|
||||
|
||||
/// Connects the current user with an anonymous id, this triggers a connection
|
||||
/// to the API. It returns a [Future] that resolves when the connection is
|
||||
/// setup.
|
||||
Future<Event> connectAnonymousUser() async {
|
||||
if (_connectCompleter != null && !_connectCompleter.isCompleted) {
|
||||
Future<Event?> connectAnonymousUser() async {
|
||||
if (_connectCompleter != null && !_connectCompleter!.isCompleted) {
|
||||
logger.warning('Already connecting');
|
||||
throw Exception('Already connecting');
|
||||
}
|
||||
@@ -955,10 +958,10 @@ class StreamChatClient {
|
||||
state.user = OwnUser(id: uuid.v4());
|
||||
|
||||
return connect().then((event) {
|
||||
_connectCompleter.complete(event);
|
||||
_connectCompleter!.complete(event);
|
||||
return event;
|
||||
}).catchError((e, s) {
|
||||
_connectCompleter.completeError(e, s);
|
||||
_connectCompleter!.completeError(e, s);
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
@@ -967,16 +970,17 @@ class StreamChatClient {
|
||||
/// It returns a [Future] that resolves when the connection is setup.
|
||||
@Deprecated(
|
||||
'Use `connectGuestUser` instead. Will be removed in Future releases')
|
||||
Future<Event> setGuestUser(User user) => connectGuestUser(user);
|
||||
Future<Event?> setGuestUser(User user) => connectGuestUser(user);
|
||||
|
||||
/// Connects the current user as guest, this triggers a connection to the API.
|
||||
/// It returns a [Future] that resolves when the connection is setup.
|
||||
Future<Event> connectGuestUser(User user) async {
|
||||
Future<Event?> connectGuestUser(User user) async {
|
||||
_anonymous = true;
|
||||
final response = await post('/guest', data: {'user': user.toJson()})
|
||||
.then((res) => decode<ConnectGuestUserResponse>(
|
||||
res.data, ConnectGuestUserResponse.fromJson))
|
||||
.whenComplete(() => _anonymous = false);
|
||||
|
||||
return connectUser(
|
||||
response.user,
|
||||
response.accessToken,
|
||||
@@ -1009,16 +1013,16 @@ class StreamChatClient {
|
||||
Future<void> _disconnect() async {
|
||||
logger.info('Client disconnecting');
|
||||
|
||||
await _ws?.disconnect();
|
||||
await _ws.disconnect();
|
||||
await _connectionStatusSubscription?.cancel();
|
||||
}
|
||||
|
||||
/// Requests users with a given query.
|
||||
Future<QueryUsersResponse> queryUsers({
|
||||
Map<String, dynamic> filter,
|
||||
List<SortOption> sort,
|
||||
Map<String, dynamic> options,
|
||||
PaginationParams pagination,
|
||||
Map<String, dynamic>? filter,
|
||||
List<SortOption>? sort,
|
||||
Map<String, dynamic>? options,
|
||||
PaginationParams? pagination,
|
||||
}) async {
|
||||
final defaultOptions = {
|
||||
'presence': _hasConnectionId,
|
||||
@@ -1049,7 +1053,7 @@ class StreamChatClient {
|
||||
QueryUsersResponse.fromJson,
|
||||
);
|
||||
|
||||
state?._updateUsers(response.users);
|
||||
state._updateUsers(response.users);
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -1057,13 +1061,13 @@ class StreamChatClient {
|
||||
/// A message search.
|
||||
Future<SearchMessagesResponse> search(
|
||||
Map<String, dynamic> filters, {
|
||||
String query,
|
||||
List<SortOption> sort,
|
||||
PaginationParams paginationParams,
|
||||
Map<String, dynamic> messageFilters,
|
||||
String? query,
|
||||
List<SortOption>? sort,
|
||||
PaginationParams? paginationParams,
|
||||
Map<String, dynamic>? messageFilters,
|
||||
}) async {
|
||||
assert(() {
|
||||
if (filters == null || filters.isEmpty) {
|
||||
if (filters.isEmpty) {
|
||||
throw ArgumentError('`filters` cannot be set as null or empty');
|
||||
}
|
||||
if (query == null && messageFilters == null) {
|
||||
@@ -1098,10 +1102,10 @@ class StreamChatClient {
|
||||
AttachmentFile file,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
}) =>
|
||||
attachmentFileUploader.sendFile(
|
||||
attachmentFileUploader!.sendFile(
|
||||
file,
|
||||
channelId,
|
||||
channelType,
|
||||
@@ -1114,10 +1118,10 @@ class StreamChatClient {
|
||||
AttachmentFile image,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
}) =>
|
||||
attachmentFileUploader.sendImage(
|
||||
attachmentFileUploader!.sendImage(
|
||||
image,
|
||||
channelId,
|
||||
channelType,
|
||||
@@ -1130,9 +1134,9 @@ class StreamChatClient {
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
CancelToken? cancelToken,
|
||||
}) =>
|
||||
attachmentFileUploader.deleteFile(
|
||||
attachmentFileUploader!.deleteFile(
|
||||
url,
|
||||
channelId,
|
||||
channelType,
|
||||
@@ -1144,9 +1148,9 @@ class StreamChatClient {
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
CancelToken? cancelToken,
|
||||
}) =>
|
||||
attachmentFileUploader.deleteImage(
|
||||
attachmentFileUploader!.deleteImage(
|
||||
url,
|
||||
channelId,
|
||||
channelType,
|
||||
@@ -1188,13 +1192,13 @@ class StreamChatClient {
|
||||
/// Returns a channel client with the given type, id and custom data.
|
||||
Channel channel(
|
||||
String type, {
|
||||
String id,
|
||||
Map<String, dynamic> extraData,
|
||||
String? id,
|
||||
Map<String, dynamic>? extraData,
|
||||
}) {
|
||||
if (type != null &&
|
||||
id != null &&
|
||||
state.channels?.containsKey('$type:$id') == true) {
|
||||
return state.channels['$type:$id'];
|
||||
if (id != null && state.channels?.containsKey('$type:$id') == true) {
|
||||
if (state.channels!['$type:$id'] != null) {
|
||||
return state.channels!['$type:$id'] as Channel;
|
||||
}
|
||||
}
|
||||
|
||||
return Channel(this, type, id, extraData);
|
||||
@@ -1323,7 +1327,10 @@ class StreamChatClient {
|
||||
|
||||
/// Sends the message to the given channel
|
||||
Future<SendMessageResponse> sendMessage(
|
||||
Message message, String channelId, String channelType) async {
|
||||
Message message,
|
||||
String channelId,
|
||||
String channelType,
|
||||
) async {
|
||||
final response = await post(
|
||||
'/channels/$channelType/$channelId/message',
|
||||
data: {'message': message.toJson()},
|
||||
@@ -1359,14 +1366,13 @@ class StreamChatClient {
|
||||
) {
|
||||
assert(() {
|
||||
if (timeoutOrExpirationDate is! DateTime &&
|
||||
timeoutOrExpirationDate is! num &&
|
||||
timeoutOrExpirationDate != null) {
|
||||
timeoutOrExpirationDate is! num) {
|
||||
throw ArgumentError('Invalid timeout or Expiration date');
|
||||
}
|
||||
return true;
|
||||
}(), 'Check whether time out is valid');
|
||||
|
||||
DateTime pinExpires;
|
||||
DateTime? pinExpires;
|
||||
if (timeoutOrExpirationDate is DateTime) {
|
||||
pinExpires = timeoutOrExpirationDate.toUtc();
|
||||
} else if (timeoutOrExpirationDate is num) {
|
||||
@@ -1395,12 +1401,12 @@ class ClientState {
|
||||
.map((e) => e.me)
|
||||
.listen((user) {
|
||||
_userController.add(user);
|
||||
if (user.totalUnreadCount != null) {
|
||||
_totalUnreadCountController.add(user.totalUnreadCount);
|
||||
if (user?.totalUnreadCount != null) {
|
||||
_totalUnreadCountController.add(user?.totalUnreadCount);
|
||||
}
|
||||
|
||||
if (user.unreadChannels != null) {
|
||||
_unreadChannelsController.add(user.unreadChannels);
|
||||
if (user?.unreadChannels != null) {
|
||||
_unreadChannelsController.add(user?.unreadChannels);
|
||||
}
|
||||
}),
|
||||
_client
|
||||
@@ -1425,23 +1431,27 @@ class ClientState {
|
||||
final _subscriptions = <StreamSubscription>[];
|
||||
|
||||
/// Used internally for optimistic update of unread count
|
||||
set totalUnreadCount(int unreadCount) {
|
||||
_totalUnreadCountController?.add(unreadCount ?? 0);
|
||||
set totalUnreadCount(int? unreadCount) {
|
||||
_totalUnreadCountController.add(unreadCount ?? 0);
|
||||
}
|
||||
|
||||
void _listenChannelHidden() {
|
||||
_subscriptions.add(_client.on(EventType.channelHidden).listen((event) {
|
||||
_client.chatPersistenceClient?.deleteChannels([event.cid]);
|
||||
final cid = event.cid;
|
||||
|
||||
if (cid != null) {
|
||||
_client.chatPersistenceClient?.deleteChannels([cid]);
|
||||
}
|
||||
if (channels != null) {
|
||||
channels = channels..removeWhere((cid, ch) => cid == event.cid);
|
||||
channels = channels?..removeWhere((cid, ch) => cid == event.cid);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
void _listenUserUpdated() {
|
||||
_subscriptions.add(_client.on(EventType.userUpdated).listen((event) {
|
||||
if (event.user.id == user.id) {
|
||||
user = OwnUser.fromJson(event.user.toJson());
|
||||
if (event.user!.id == user!.id) {
|
||||
user = OwnUser.fromJson(event.user!.toJson());
|
||||
}
|
||||
_updateUser(event.user);
|
||||
}));
|
||||
@@ -1455,10 +1465,10 @@ class ClientState {
|
||||
EventType.notificationChannelDeleted,
|
||||
)
|
||||
.listen((Event event) async {
|
||||
final eventChannel = event.channel;
|
||||
final eventChannel = event.channel!;
|
||||
await _client.chatPersistenceClient?.deleteChannels([eventChannel.cid]);
|
||||
if (channels != null) {
|
||||
channels = channels..remove(eventChannel.cid);
|
||||
channels = channels?..remove(eventChannel.cid);
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -1466,61 +1476,63 @@ class ClientState {
|
||||
final StreamChatClient _client;
|
||||
|
||||
/// Update user information
|
||||
set user(OwnUser user) {
|
||||
set user(OwnUser? user) {
|
||||
_userController.add(user);
|
||||
}
|
||||
|
||||
void _updateUsers(List<User> userList) {
|
||||
void _updateUsers(List<User?> userList) {
|
||||
final newUsers = {
|
||||
...users ?? {},
|
||||
for (var user in userList) user.id: user,
|
||||
...users,
|
||||
for (var user in userList) user!.id: user,
|
||||
};
|
||||
_usersController.add(newUsers);
|
||||
}
|
||||
|
||||
void _updateUser(User user) => _updateUsers([user]);
|
||||
void _updateUser(User? user) => _updateUsers([user]);
|
||||
|
||||
/// The current user
|
||||
OwnUser get user => _userController.value;
|
||||
OwnUser? get user => _userController.value;
|
||||
|
||||
/// The current user as a stream
|
||||
Stream<OwnUser> get userStream => _userController.stream;
|
||||
Stream<OwnUser?> get userStream => _userController.stream;
|
||||
|
||||
/// The current user
|
||||
Map<String, User> get users => _usersController.value;
|
||||
Map<String?, User?> get users =>
|
||||
_usersController.value as Map<String?, User?>;
|
||||
|
||||
/// The current user as a stream
|
||||
Stream<Map<String, User>> get usersStream => _usersController.stream;
|
||||
Stream<Map<String?, User?>> get usersStream => _usersController.stream;
|
||||
|
||||
/// The current unread channels count
|
||||
int get unreadChannels => _unreadChannelsController.value;
|
||||
int? get unreadChannels => _unreadChannelsController.value;
|
||||
|
||||
/// The current unread channels count as a stream
|
||||
Stream<int> get unreadChannelsStream => _unreadChannelsController.stream;
|
||||
Stream<int?> get unreadChannelsStream => _unreadChannelsController.stream;
|
||||
|
||||
/// The current total unread messages count
|
||||
int get totalUnreadCount => _totalUnreadCountController.value;
|
||||
int? get totalUnreadCount => _totalUnreadCountController.value;
|
||||
|
||||
/// The current total unread messages count as a stream
|
||||
Stream<int> get totalUnreadCountStream => _totalUnreadCountController.stream;
|
||||
Stream<int?> get totalUnreadCountStream => _totalUnreadCountController.stream;
|
||||
|
||||
/// The current list of channels in memory as a stream
|
||||
Stream<Map<String, Channel>> get channelsStream => _channelsController.stream;
|
||||
Stream<Map<String?, Channel>?> get channelsStream =>
|
||||
_channelsController.stream;
|
||||
|
||||
/// The current list of channels in memory
|
||||
Map<String, Channel> get channels => _channelsController.value;
|
||||
Map<String?, Channel>? get channels => _channelsController.value;
|
||||
|
||||
set channels(Map<String, Channel> v) {
|
||||
set channels(Map<String?, Channel>? v) {
|
||||
_channelsController.add(v);
|
||||
}
|
||||
|
||||
final BehaviorSubject<Map<String, Channel>> _channelsController =
|
||||
final BehaviorSubject<Map<String?, Channel>?> _channelsController =
|
||||
BehaviorSubject.seeded({});
|
||||
final BehaviorSubject<OwnUser> _userController = BehaviorSubject();
|
||||
final BehaviorSubject<Map<String, User>> _usersController =
|
||||
final BehaviorSubject<OwnUser?> _userController = BehaviorSubject();
|
||||
final BehaviorSubject<Map<String?, User?>> _usersController =
|
||||
BehaviorSubject.seeded({});
|
||||
final BehaviorSubject<int> _unreadChannelsController = BehaviorSubject();
|
||||
final BehaviorSubject<int> _totalUnreadCountController = BehaviorSubject();
|
||||
final BehaviorSubject<int?> _unreadChannelsController = BehaviorSubject();
|
||||
final BehaviorSubject<int?> _totalUnreadCountController = BehaviorSubject();
|
||||
|
||||
/// Call this method to dispose this object
|
||||
void dispose() {
|
||||
@@ -1528,7 +1540,7 @@ class ClientState {
|
||||
_userController.close();
|
||||
_unreadChannelsController.close();
|
||||
_totalUnreadCountController.close();
|
||||
channels.values.forEach((c) => c.dispose());
|
||||
channels!.values.forEach((c) => c.dispose());
|
||||
_channelsController.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ abstract class ChatPersistenceClient {
|
||||
/// Get stored replies by messageId
|
||||
Future<List<Message>> getReplies(
|
||||
String parentId, {
|
||||
PaginationParams options,
|
||||
PaginationParams? options,
|
||||
});
|
||||
|
||||
/// Get stored connection event
|
||||
@@ -53,20 +53,20 @@ abstract class ChatPersistenceClient {
|
||||
/// for filtering out messages
|
||||
Future<List<Message>> getMessagesByCid(
|
||||
String cid, {
|
||||
PaginationParams messagePagination,
|
||||
PaginationParams? messagePagination,
|
||||
});
|
||||
|
||||
/// Get stored pinned [Message]s by providing channel [cid]
|
||||
Future<List<Message>> getPinnedMessagesByCid(
|
||||
String cid, {
|
||||
PaginationParams messagePagination,
|
||||
PaginationParams? messagePagination,
|
||||
});
|
||||
|
||||
/// Get [ChannelState] data by providing channel [cid]
|
||||
Future<ChannelState> getChannelStateByCid(
|
||||
String cid, {
|
||||
PaginationParams messagePagination,
|
||||
PaginationParams pinnedMessagePagination,
|
||||
PaginationParams? messagePagination,
|
||||
PaginationParams? pinnedMessagePagination,
|
||||
}) async {
|
||||
final data = await Future.wait([
|
||||
getMembersByCid(cid),
|
||||
@@ -76,11 +76,11 @@ abstract class ChatPersistenceClient {
|
||||
getPinnedMessagesByCid(cid, messagePagination: pinnedMessagePagination),
|
||||
]);
|
||||
return ChannelState(
|
||||
members: data[0],
|
||||
read: data[1],
|
||||
channel: data[2],
|
||||
messages: data[3],
|
||||
pinnedMessages: data[4],
|
||||
members: data[0] as List<Member>,
|
||||
read: data[1] as List<Read>,
|
||||
channel: data[2] as ChannelModel,
|
||||
messages: data[3] as List<Message>,
|
||||
pinnedMessages: data[4] as List<Message>,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -89,9 +89,9 @@ abstract class ChatPersistenceClient {
|
||||
/// Optionally, pass [filter], [sort], [paginationParams]
|
||||
/// for filtering out states.
|
||||
Future<List<ChannelState>> getChannelStates({
|
||||
Map<String, dynamic> filter,
|
||||
List<SortOption<ChannelModel>> sort = const [],
|
||||
PaginationParams paginationParams,
|
||||
Map<String, dynamic>? filter,
|
||||
List<SortOption<ChannelModel>>? sort = const [],
|
||||
PaginationParams? paginationParams,
|
||||
});
|
||||
|
||||
/// Update list of channel queries.
|
||||
@@ -180,8 +180,11 @@ abstract class ChatPersistenceClient {
|
||||
.map((m) => m.id)
|
||||
.toList(growable: false));
|
||||
|
||||
final cleanedChannelStates =
|
||||
channelStates.where((it) => it.channel != null);
|
||||
|
||||
final deleteMembers = deleteMembersByCids(
|
||||
channelStates.map((it) => it.channel.cid).toList(growable: false),
|
||||
cleanedChannelStates.map((it) => it.channel!.cid).toList(growable: false),
|
||||
);
|
||||
|
||||
await Future.wait([
|
||||
@@ -189,58 +192,57 @@ abstract class ChatPersistenceClient {
|
||||
deleteMembers,
|
||||
]);
|
||||
|
||||
final channels =
|
||||
channelStates.map((it) => it.channel).where((it) => it != null);
|
||||
final channels = cleanedChannelStates
|
||||
.map((it) => it.channel)
|
||||
.where((it) => it != null) as Iterable<ChannelModel>;
|
||||
|
||||
final reactions = channelStates
|
||||
.expand((it) => it.messages)
|
||||
.expand((it) => [
|
||||
final reactions =
|
||||
cleanedChannelStates.expand((it) => it.messages).expand((it) => [
|
||||
if (it.ownReactions != null)
|
||||
...it.ownReactions.where((r) => r.userId != null),
|
||||
...it.ownReactions!.where((r) => r.userId != null),
|
||||
if (it.latestReactions != null)
|
||||
...it.latestReactions.where((r) => r.userId != null)
|
||||
])
|
||||
.where((it) => it != null);
|
||||
...it.latestReactions!.where((r) => r.userId != null),
|
||||
]);
|
||||
|
||||
final users = channelStates
|
||||
final users = cleanedChannelStates
|
||||
.map((cs) => [
|
||||
cs.channel?.createdBy,
|
||||
...cs.messages
|
||||
?.map((m) => [
|
||||
.map((m) => [
|
||||
m.user,
|
||||
if (m.latestReactions != null)
|
||||
...m.latestReactions.map((r) => r.user),
|
||||
...m.latestReactions!.map((r) => r.user),
|
||||
if (m.ownReactions != null)
|
||||
...m.ownReactions.map((r) => r.user),
|
||||
...m.ownReactions!.map((r) => r.user),
|
||||
])
|
||||
?.expand((v) => v),
|
||||
if (cs.read != null) ...cs.read.map((r) => r.user),
|
||||
if (cs.members != null) ...cs.members.map((m) => m.user),
|
||||
.expand((v) => v),
|
||||
...cs.read.map((r) => r.user),
|
||||
...cs.members.map((m) => m.user),
|
||||
])
|
||||
.expand((it) => it)
|
||||
.where((it) => it != null);
|
||||
.where((it) => it != null) as Iterable<User>;
|
||||
|
||||
final updateMessagesFuture = channelStates.map((it) {
|
||||
final cid = it.channel.cid;
|
||||
final messages = it.messages.where((it) => it != null);
|
||||
final updateMessagesFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final messages = it.messages;
|
||||
return updateMessages(cid, messages.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
final updatePinnedMessagesFuture = channelStates.map((it) {
|
||||
final cid = it.channel.cid;
|
||||
final messages = it.pinnedMessages.where((it) => it != null);
|
||||
final updatePinnedMessagesFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final messages = it.pinnedMessages;
|
||||
return updatePinnedMessages(cid, messages.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
final updateReadsFuture = channelStates.map((it) {
|
||||
final cid = it.channel.cid;
|
||||
final reads = it.read?.where((it) => it != null) ?? [];
|
||||
final updateReadsFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final reads = it.read;
|
||||
return updateReads(cid, reads.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
final updateMembersFuture = channelStates.map((it) {
|
||||
final cid = it.channel.cid;
|
||||
final members = it.members.where((it) => it != null);
|
||||
final updateMembersFuture = cleanedChannelStates.map((it) {
|
||||
final cid = it.channel!.cid;
|
||||
final members = it.members;
|
||||
return updateMembers(cid, members.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
|
||||
@@ -4,25 +4,25 @@ import 'dart:convert';
|
||||
class ApiError extends Error {
|
||||
/// Creates a new ApiError instance using the response body and status code
|
||||
ApiError(this.body, this.status) : jsonData = _decode(body) {
|
||||
if (jsonData != null && jsonData.containsKey('code')) {
|
||||
_code = jsonData['code'];
|
||||
if (jsonData != null && jsonData!.containsKey('code')) {
|
||||
_code = jsonData!['code'];
|
||||
}
|
||||
}
|
||||
|
||||
/// Raw body of the response
|
||||
final String body;
|
||||
final String? body;
|
||||
|
||||
/// Json parsed body
|
||||
final Map<String, dynamic> jsonData;
|
||||
final Map<String, dynamic>? jsonData;
|
||||
|
||||
/// Http status code of the response
|
||||
final int status;
|
||||
final int? status;
|
||||
|
||||
/// Stream specific error code
|
||||
int get code => _code;
|
||||
int _code;
|
||||
int? get code => _code;
|
||||
int? _code;
|
||||
|
||||
static Map<String, dynamic> _decode(String body) {
|
||||
static Map<String, dynamic>? _decode(String? body) {
|
||||
try {
|
||||
if (body == null) {
|
||||
return null;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// Useful extension functions for [Map]
|
||||
extension MapX on Map {
|
||||
extension MapX<K, V> on Map<K, V> {
|
||||
/// Returns a new map with null keys or values removed
|
||||
Map<String, dynamic> get nullProtected =>
|
||||
{...this}..removeWhere((key, value) => key == null || value == null);
|
||||
Map<K, V> get nullProtected =>
|
||||
Map.from(this)..removeWhere((key, value) => key == null || value == null);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ extension RateLimit on Function {
|
||||
Duration wait, {
|
||||
bool leading = false,
|
||||
bool trailing = true,
|
||||
Duration maxWait,
|
||||
Duration? maxWait,
|
||||
}) =>
|
||||
Debounce(
|
||||
this,
|
||||
@@ -40,7 +40,7 @@ Debounce debounce(
|
||||
Duration wait, {
|
||||
bool leading = false,
|
||||
bool trailing = true,
|
||||
Duration maxWait,
|
||||
Duration? maxWait,
|
||||
}) =>
|
||||
Debounce(
|
||||
func,
|
||||
@@ -121,13 +121,13 @@ class Debounce {
|
||||
Duration wait, {
|
||||
bool leading = false,
|
||||
bool trailing = true,
|
||||
Duration maxWait,
|
||||
Duration? maxWait,
|
||||
}) : _leading = leading,
|
||||
_trailing = trailing,
|
||||
_wait = wait?.inMilliseconds ?? 0,
|
||||
_wait = wait.inMilliseconds,
|
||||
_maxing = maxWait != null {
|
||||
if (_maxing) {
|
||||
_maxWait = math.max(maxWait.inMilliseconds, _wait);
|
||||
_maxWait = math.max(maxWait!.inMilliseconds, _wait);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,15 +137,15 @@ class Debounce {
|
||||
final int _wait;
|
||||
final bool _maxing;
|
||||
|
||||
int _maxWait;
|
||||
List<Object> _lastArgs;
|
||||
Map<Symbol, Object> _lastNamedArgs;
|
||||
Timer _timer;
|
||||
int _lastCallTime;
|
||||
Object _result;
|
||||
int _lastInvokeTime = 0;
|
||||
late int _maxWait;
|
||||
List<Object?>? _lastArgs;
|
||||
Map<Symbol, Object>? _lastNamedArgs;
|
||||
Timer? _timer;
|
||||
int? _lastCallTime;
|
||||
Object? _result;
|
||||
int? _lastInvokeTime = 0;
|
||||
|
||||
Object _invokeFunc(int time) {
|
||||
Object? _invokeFunc(int? time) {
|
||||
final args = _lastArgs;
|
||||
final namedArgs = _lastNamedArgs;
|
||||
_lastArgs = _lastNamedArgs = null;
|
||||
@@ -154,11 +154,11 @@ class Debounce {
|
||||
}
|
||||
|
||||
Timer _startTimer(Function pendingFunc, int wait) =>
|
||||
Timer(Duration(milliseconds: wait), pendingFunc);
|
||||
Timer(Duration(milliseconds: wait), pendingFunc as void Function());
|
||||
|
||||
bool _shouldInvoke(int time) {
|
||||
final timeSinceLastCall = time - (_lastCallTime ?? double.nan);
|
||||
final timeSinceLastInvoke = time - _lastInvokeTime;
|
||||
final timeSinceLastInvoke = time - _lastInvokeTime!;
|
||||
|
||||
// Either this is the first call, activity has stopped and we're at the
|
||||
// trailing edge, the system time has gone backwards and we're treating
|
||||
@@ -169,7 +169,7 @@ class Debounce {
|
||||
(_maxing && timeSinceLastInvoke >= _maxWait);
|
||||
}
|
||||
|
||||
Object _trailingEdge(int time) {
|
||||
Object? _trailingEdge(int time) {
|
||||
_timer = null;
|
||||
|
||||
// Only invoke if we have `lastArgs` which means `func` has been
|
||||
@@ -182,8 +182,8 @@ class Debounce {
|
||||
}
|
||||
|
||||
int _remainingWait(int time) {
|
||||
final timeSinceLastCall = time - _lastCallTime;
|
||||
final timeSinceLastInvoke = time - _lastInvokeTime;
|
||||
final timeSinceLastCall = time - _lastCallTime!;
|
||||
final timeSinceLastInvoke = time - _lastInvokeTime!;
|
||||
final timeWaiting = _wait - timeSinceLastCall;
|
||||
|
||||
return _maxing
|
||||
@@ -201,7 +201,7 @@ class Debounce {
|
||||
}
|
||||
}
|
||||
|
||||
Object _leadingEdge(int time) {
|
||||
Object? _leadingEdge(int? time) {
|
||||
// Reset any `maxWait` timer.
|
||||
_lastInvokeTime = time;
|
||||
// Start the timer for the trailing edge.
|
||||
@@ -218,7 +218,7 @@ class Debounce {
|
||||
}
|
||||
|
||||
/// Immediately invokes all the remaining delayed functions.
|
||||
Object flush() {
|
||||
Object? flush() {
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
return _timer == null ? _result : _trailingEdge(now);
|
||||
}
|
||||
@@ -228,15 +228,15 @@ class Debounce {
|
||||
|
||||
/// Calls/invokes this class like a function.
|
||||
/// Pass [args] and [namedArgs] to be used while invoking [_func].
|
||||
Object call(
|
||||
Object? call(
|
||||
List<dynamic> args, {
|
||||
Map<Symbol, dynamic> namedArgs,
|
||||
Map<Symbol, dynamic>? namedArgs,
|
||||
}) {
|
||||
final time = DateTime.now().millisecondsSinceEpoch;
|
||||
final isInvoking = _shouldInvoke(time);
|
||||
|
||||
_lastArgs = args;
|
||||
_lastNamedArgs = namedArgs;
|
||||
_lastNamedArgs = namedArgs as Map<Symbol, Object>?;
|
||||
_lastCallTime = time;
|
||||
|
||||
if (isInvoking) {
|
||||
@@ -323,13 +323,13 @@ class Throttle {
|
||||
void cancel() => _debounce.cancel();
|
||||
|
||||
/// Immediately invokes all the remaining delayed functions.
|
||||
Object flush() => _debounce.flush();
|
||||
Object? flush() => _debounce.flush();
|
||||
|
||||
/// True if there are functions remaining to get invoked.
|
||||
bool get isPending => _debounce.isPending;
|
||||
|
||||
/// Calls/invokes this class like a function.
|
||||
/// Pass [args] and [namedArgs] to be used while invoking `func`.
|
||||
Object call(List<dynamic> args, {Map<Symbol, dynamic> namedArgs}) =>
|
||||
Object? call(List<dynamic> args, {Map<Symbol, dynamic>? namedArgs}) =>
|
||||
_debounce.call(args, namedArgs: namedArgs);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,15 @@ import 'package:mime/mime.dart';
|
||||
/// Useful extension functions for [String]
|
||||
extension StringX on String {
|
||||
/// Returns the mime type from the passed file name.
|
||||
http_parser.MediaType get mimeType {
|
||||
if (this == null) return null;
|
||||
http_parser.MediaType? get mimeType {
|
||||
if (toLowerCase().endsWith('heic')) {
|
||||
return http_parser.MediaType.parse('image/heic');
|
||||
} else {
|
||||
return http_parser.MediaType.parse(lookupMimeType(this));
|
||||
final mimeType = lookupMimeType(this);
|
||||
if (mimeType == null) {
|
||||
return null;
|
||||
}
|
||||
return http_parser.MediaType.parse(mimeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,13 @@ part 'action.g.dart';
|
||||
@JsonSerializable()
|
||||
class Action {
|
||||
/// Constructor used for json serialization
|
||||
Action({this.name, this.style, this.text, this.type, this.value});
|
||||
Action({
|
||||
required this.name,
|
||||
this.style = 'default',
|
||||
required this.text,
|
||||
required this.type,
|
||||
this.value,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Action.fromJson(Map<String, dynamic> json) => _$ActionFromJson(json);
|
||||
@@ -15,6 +21,7 @@ class Action {
|
||||
final String name;
|
||||
|
||||
/// The style of the action
|
||||
@JsonKey(defaultValue: 'default')
|
||||
final String style;
|
||||
|
||||
/// The test of the action
|
||||
@@ -24,7 +31,7 @@ class Action {
|
||||
final String type;
|
||||
|
||||
/// The value of the action
|
||||
final String value;
|
||||
final String? value;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => _$ActionToJson(this);
|
||||
|
||||
@@ -6,13 +6,13 @@ part of 'action.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Action _$ActionFromJson(Map json) {
|
||||
Action _$ActionFromJson(Map<String, dynamic> json) {
|
||||
return Action(
|
||||
name: json['name'] as String,
|
||||
style: json['style'] as String,
|
||||
style: json['style'] as String? ?? 'default',
|
||||
text: json['text'] as String,
|
||||
type: json['type'] as String,
|
||||
value: json['value'] as String,
|
||||
value: json['value'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,10 @@ part 'attachment.g.dart';
|
||||
class Attachment extends Equatable {
|
||||
/// Constructor used for json serialization
|
||||
Attachment({
|
||||
String id,
|
||||
String? id,
|
||||
this.type,
|
||||
this.titleLink,
|
||||
String title,
|
||||
String? title,
|
||||
this.thumbUrl,
|
||||
this.text,
|
||||
this.pretext,
|
||||
@@ -32,17 +32,19 @@ class Attachment extends Equatable {
|
||||
this.authorLink,
|
||||
this.authorIcon,
|
||||
this.assetUrl,
|
||||
this.actions,
|
||||
List<Action>? actions,
|
||||
this.extraData,
|
||||
this.file,
|
||||
UploadState uploadState,
|
||||
UploadState? uploadState,
|
||||
}) : id = id ?? const Uuid().v4(),
|
||||
title = title ?? file?.name,
|
||||
localUri = file?.path != null ? Uri.parse(file.path) : null,
|
||||
uploadState = uploadState ??
|
||||
((assetUrl != null || imageUrl != null)
|
||||
? const UploadState.success()
|
||||
: const UploadState.preparing());
|
||||
localUri = file?.path != null ? Uri.parse(file!.path!) : null,
|
||||
actions = actions ?? [] {
|
||||
this.uploadState = uploadState ??
|
||||
((assetUrl != null || imageUrl != null)
|
||||
? const UploadState.success()
|
||||
: const UploadState.preparing());
|
||||
}
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Attachment.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -56,59 +58,60 @@ class Attachment extends Equatable {
|
||||
|
||||
///The attachment type based on the URL resource. This can be: audio,
|
||||
///image or video
|
||||
final String type;
|
||||
final String? type;
|
||||
|
||||
///The link to which the attachment message points to.
|
||||
final String titleLink;
|
||||
final String? titleLink;
|
||||
|
||||
/// The attachment title
|
||||
final String title;
|
||||
final String? title;
|
||||
|
||||
/// The URL to the attached file thumbnail. You can use this to represent the
|
||||
/// attached link.
|
||||
final String thumbUrl;
|
||||
final String? thumbUrl;
|
||||
|
||||
/// The attachment text. It will be displayed in the channel next to the
|
||||
/// original message.
|
||||
final String text;
|
||||
final String? text;
|
||||
|
||||
/// Optional text that appears above the attachment block
|
||||
final String pretext;
|
||||
final String? pretext;
|
||||
|
||||
/// The original URL that was used to scrape this attachment.
|
||||
final String ogScrapeUrl;
|
||||
final String? ogScrapeUrl;
|
||||
|
||||
/// The URL to the attached image. This is present for URL pointing to an
|
||||
/// image article (eg. Unsplash)
|
||||
final String imageUrl;
|
||||
final String footerIcon;
|
||||
final String footer;
|
||||
final String? imageUrl;
|
||||
final String? footerIcon;
|
||||
final String? footer;
|
||||
final dynamic fields;
|
||||
final String fallback;
|
||||
final String color;
|
||||
final String? fallback;
|
||||
final String? color;
|
||||
|
||||
/// The name of the author.
|
||||
final String authorName;
|
||||
final String authorLink;
|
||||
final String authorIcon;
|
||||
final String? authorName;
|
||||
final String? authorLink;
|
||||
final String? authorIcon;
|
||||
|
||||
/// The URL to the audio, video or image related to the URL.
|
||||
final String assetUrl;
|
||||
final String? assetUrl;
|
||||
|
||||
/// Actions from a command
|
||||
@JsonKey(defaultValue: [])
|
||||
final List<Action> actions;
|
||||
|
||||
final Uri localUri;
|
||||
final Uri? localUri;
|
||||
|
||||
/// The file present inside this attachment.
|
||||
final AttachmentFile file;
|
||||
final AttachmentFile? file;
|
||||
|
||||
/// The current upload state of the attachment
|
||||
final UploadState uploadState;
|
||||
late final UploadState uploadState;
|
||||
|
||||
/// Map of custom channel extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
final Map<String, dynamic>? extraData;
|
||||
|
||||
/// The attachment ID.
|
||||
///
|
||||
@@ -147,37 +150,37 @@ class Attachment extends Equatable {
|
||||
];
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$AttachmentToJson(this), topLevelFields)
|
||||
..removeWhere((key, value) => dbSpecificTopLevelFields.contains(key));
|
||||
Map<String, dynamic> toJson() =>
|
||||
Serialization.moveFromExtraDataToRoot(_$AttachmentToJson(this))
|
||||
..removeWhere((key, value) => dbSpecificTopLevelFields.contains(key));
|
||||
|
||||
/// Serialize to db data
|
||||
Map<String, dynamic> toData() => Serialization.moveFromExtraDataToRoot(
|
||||
_$AttachmentToJson(this), topLevelFields + dbSpecificTopLevelFields);
|
||||
Map<String, dynamic> toData() =>
|
||||
Serialization.moveFromExtraDataToRoot(_$AttachmentToJson(this));
|
||||
|
||||
Attachment copyWith({
|
||||
String id,
|
||||
String type,
|
||||
String titleLink,
|
||||
String title,
|
||||
String thumbUrl,
|
||||
String text,
|
||||
String pretext,
|
||||
String ogScrapeUrl,
|
||||
String imageUrl,
|
||||
String footerIcon,
|
||||
String footer,
|
||||
String? id,
|
||||
String? type,
|
||||
String? titleLink,
|
||||
String? title,
|
||||
String? thumbUrl,
|
||||
String? text,
|
||||
String? pretext,
|
||||
String? ogScrapeUrl,
|
||||
String? imageUrl,
|
||||
String? footerIcon,
|
||||
String? footer,
|
||||
dynamic fields,
|
||||
String fallback,
|
||||
String color,
|
||||
String authorName,
|
||||
String authorLink,
|
||||
String authorIcon,
|
||||
String assetUrl,
|
||||
List<Action> actions,
|
||||
AttachmentFile file,
|
||||
UploadState uploadState,
|
||||
Map<String, dynamic> extraData,
|
||||
String? fallback,
|
||||
String? color,
|
||||
String? authorName,
|
||||
String? authorLink,
|
||||
String? authorIcon,
|
||||
String? assetUrl,
|
||||
List<Action>? actions,
|
||||
AttachmentFile? file,
|
||||
UploadState? uploadState,
|
||||
Map<String, dynamic>? extraData,
|
||||
}) =>
|
||||
Attachment(
|
||||
id: id ?? this.id,
|
||||
@@ -205,7 +208,7 @@ class Attachment extends Equatable {
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
type,
|
||||
titleLink,
|
||||
|
||||
@@ -6,46 +6,37 @@ part of 'attachment.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Attachment _$AttachmentFromJson(Map json) {
|
||||
Attachment _$AttachmentFromJson(Map<String, dynamic> json) {
|
||||
return Attachment(
|
||||
id: json['id'] as String,
|
||||
type: json['type'] as String,
|
||||
titleLink: json['title_link'] as String,
|
||||
title: json['title'] as String,
|
||||
thumbUrl: json['thumb_url'] as String,
|
||||
text: json['text'] as String,
|
||||
pretext: json['pretext'] as String,
|
||||
ogScrapeUrl: json['og_scrape_url'] as String,
|
||||
imageUrl: json['image_url'] as String,
|
||||
footerIcon: json['footer_icon'] as String,
|
||||
footer: json['footer'] as String,
|
||||
id: json['id'] as String?,
|
||||
type: json['type'] as String?,
|
||||
titleLink: json['title_link'] as String?,
|
||||
title: json['title'] as String?,
|
||||
thumbUrl: json['thumb_url'] as String?,
|
||||
text: json['text'] as String?,
|
||||
pretext: json['pretext'] as String?,
|
||||
ogScrapeUrl: json['og_scrape_url'] as String?,
|
||||
imageUrl: json['image_url'] as String?,
|
||||
footerIcon: json['footer_icon'] as String?,
|
||||
footer: json['footer'] as String?,
|
||||
fields: json['fields'],
|
||||
fallback: json['fallback'] as String,
|
||||
color: json['color'] as String,
|
||||
authorName: json['author_name'] as String,
|
||||
authorLink: json['author_link'] as String,
|
||||
authorIcon: json['author_icon'] as String,
|
||||
assetUrl: json['asset_url'] as String,
|
||||
actions: (json['actions'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Action.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
fallback: json['fallback'] as String?,
|
||||
color: json['color'] as String?,
|
||||
authorName: json['author_name'] as String?,
|
||||
authorLink: json['author_link'] as String?,
|
||||
authorIcon: json['author_icon'] as String?,
|
||||
assetUrl: json['asset_url'] as String?,
|
||||
actions: (json['actions'] as List<dynamic>?)
|
||||
?.map((e) => Action.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
extraData: json['extra_data'] as Map<String, dynamic>?,
|
||||
file: json['file'] == null
|
||||
? null
|
||||
: AttachmentFile.fromJson((json['file'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: AttachmentFile.fromJson(json['file'] as Map<String, dynamic>),
|
||||
uploadState: json['upload_state'] == null
|
||||
? null
|
||||
: UploadState.fromJson((json['upload_state'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: UploadState.fromJson(json['upload_state'] as Map<String, dynamic>),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,10 +66,10 @@ Map<String, dynamic> _$AttachmentToJson(Attachment instance) {
|
||||
writeNotNull('author_link', instance.authorLink);
|
||||
writeNotNull('author_icon', instance.authorIcon);
|
||||
writeNotNull('asset_url', instance.assetUrl);
|
||||
writeNotNull('actions', instance.actions?.map((e) => e?.toJson())?.toList());
|
||||
val['actions'] = instance.actions.map((e) => e.toJson()).toList();
|
||||
writeNotNull('file', instance.file?.toJson());
|
||||
writeNotNull('upload_state', instance.uploadState?.toJson());
|
||||
val['upload_state'] = instance.uploadState.toJson();
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
writeNotNull('id', instance.id);
|
||||
val['id'] = instance.id;
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -8,18 +8,21 @@ part 'attachment_file.g.dart';
|
||||
|
||||
/// Union class to hold various [UploadState] of a attachment.
|
||||
@freezed
|
||||
abstract class UploadState with _$UploadState {
|
||||
class UploadState with _$UploadState {
|
||||
/// Preparing state of the union
|
||||
const factory UploadState.preparing() = Preparing;
|
||||
|
||||
/// InProgress state of the union
|
||||
const factory UploadState.inProgress({int uploaded, int total}) = InProgress;
|
||||
const factory UploadState.inProgress({
|
||||
required int uploaded,
|
||||
required int total,
|
||||
}) = InProgress;
|
||||
|
||||
/// Success state of the union
|
||||
const factory UploadState.success() = Success;
|
||||
|
||||
/// Failed state of the union
|
||||
const factory UploadState.failed({@required String error}) = Failed;
|
||||
const factory UploadState.failed({required String error}) = Failed;
|
||||
|
||||
/// Creates a new instance from a json
|
||||
factory UploadState.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -27,7 +30,7 @@ abstract class UploadState with _$UploadState {
|
||||
}
|
||||
|
||||
/// Helper extension for UploadState
|
||||
extension UploadStateX on UploadState {
|
||||
extension UploadStateX on UploadState? {
|
||||
/// Returns true if state is [Preparing]
|
||||
bool get isPreparing => this is Preparing;
|
||||
|
||||
@@ -41,9 +44,15 @@ extension UploadStateX on UploadState {
|
||||
bool get isFailed => this is Failed;
|
||||
}
|
||||
|
||||
Uint8List _fromString(String bytes) => Uint8List.fromList(bytes.codeUnits);
|
||||
Uint8List? _fromString(String? bytes) {
|
||||
if (bytes == null) return null;
|
||||
return Uint8List.fromList(bytes.codeUnits);
|
||||
}
|
||||
|
||||
String _toString(Uint8List bytes) => String.fromCharCodes(bytes);
|
||||
String? _toString(Uint8List? bytes) {
|
||||
if (bytes == null) return null;
|
||||
return String.fromCharCodes(bytes);
|
||||
}
|
||||
|
||||
/// The class that contains the information about an attachment file
|
||||
@JsonSerializable()
|
||||
@@ -54,7 +63,10 @@ class AttachmentFile {
|
||||
this.name,
|
||||
this.bytes,
|
||||
this.size,
|
||||
});
|
||||
}) : assert(
|
||||
path != null || bytes != null,
|
||||
'Either path or bytes should be != null',
|
||||
);
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory AttachmentFile.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -65,21 +77,21 @@ class AttachmentFile {
|
||||
/// ```
|
||||
/// final File myFile = File(platformFile.path);
|
||||
/// ```
|
||||
final String path;
|
||||
final String? path;
|
||||
|
||||
/// File name including its extension.
|
||||
final String name;
|
||||
final String? name;
|
||||
|
||||
/// Byte data for this file. Particularly useful if you want to manipulate
|
||||
/// its data or easily upload to somewhere else.
|
||||
@JsonKey(toJson: _toString, fromJson: _fromString)
|
||||
final Uint8List bytes;
|
||||
final Uint8List? bytes;
|
||||
|
||||
/// The file size in bytes.
|
||||
final int size;
|
||||
final int? size;
|
||||
|
||||
/// File extension for this file.
|
||||
String get extension => name?.split('.')?.last;
|
||||
String? get extension => name?.split('.').last;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => _$AttachmentFileToJson(this);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: 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
|
||||
// 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
|
||||
|
||||
part of 'attachment_file.dart';
|
||||
|
||||
@@ -8,6 +8,10 @@ part of 'attachment_file.dart';
|
||||
// **************************************************************************
|
||||
|
||||
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 informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||
|
||||
UploadState _$UploadStateFromJson(Map<String, dynamic> json) {
|
||||
switch (json['runtimeType'] as String) {
|
||||
case 'preparing':
|
||||
@@ -28,74 +32,72 @@ UploadState _$UploadStateFromJson(Map<String, dynamic> json) {
|
||||
class _$UploadStateTearOff {
|
||||
const _$UploadStateTearOff();
|
||||
|
||||
// ignore: unused_element
|
||||
Preparing preparing() {
|
||||
return const Preparing();
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
InProgress inProgress({int uploaded, int total}) {
|
||||
InProgress inProgress({required int uploaded, required int total}) {
|
||||
return InProgress(
|
||||
uploaded: uploaded,
|
||||
total: total,
|
||||
);
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
Success success() {
|
||||
return const Success();
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
Failed failed({@required String error}) {
|
||||
Failed failed({required String error}) {
|
||||
return Failed(
|
||||
error: error,
|
||||
);
|
||||
}
|
||||
|
||||
// ignore: unused_element
|
||||
UploadState fromJson(Map<String, Object> json) {
|
||||
return UploadState.fromJson(json);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
// ignore: unused_element
|
||||
const $UploadState = _$UploadStateTearOff();
|
||||
|
||||
/// @nodoc
|
||||
mixin _$UploadState {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object>({
|
||||
@required TResult preparing(),
|
||||
@required TResult inProgress(int uploaded, int total),
|
||||
@required TResult success(),
|
||||
@required TResult failed(String error),
|
||||
});
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() preparing,
|
||||
required TResult Function(int uploaded, int total) inProgress,
|
||||
required TResult Function() success,
|
||||
required TResult Function(String error) failed,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object>({
|
||||
TResult preparing(),
|
||||
TResult inProgress(int uploaded, int total),
|
||||
TResult success(),
|
||||
TResult failed(String error),
|
||||
@required TResult orElse(),
|
||||
});
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object>({
|
||||
@required TResult preparing(Preparing value),
|
||||
@required TResult inProgress(InProgress value),
|
||||
@required TResult success(Success value),
|
||||
@required TResult failed(Failed value),
|
||||
});
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Preparing value) preparing,
|
||||
required TResult Function(InProgress value) inProgress,
|
||||
required TResult Function(Success value) success,
|
||||
required TResult Function(Failed value) failed,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object>({
|
||||
TResult preparing(Preparing value),
|
||||
TResult inProgress(InProgress value),
|
||||
TResult success(Success value),
|
||||
TResult failed(Failed value),
|
||||
@required TResult orElse(),
|
||||
});
|
||||
Map<String, dynamic> toJson();
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -154,29 +156,24 @@ class _$Preparing implements Preparing {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object>({
|
||||
@required TResult preparing(),
|
||||
@required TResult inProgress(int uploaded, int total),
|
||||
@required TResult success(),
|
||||
@required TResult failed(String error),
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() preparing,
|
||||
required TResult Function(int uploaded, int total) inProgress,
|
||||
required TResult Function() success,
|
||||
required TResult Function(String error) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return preparing();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object>({
|
||||
TResult preparing(),
|
||||
TResult inProgress(int uploaded, int total),
|
||||
TResult success(),
|
||||
TResult failed(String error),
|
||||
@required TResult orElse(),
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (preparing != null) {
|
||||
return preparing();
|
||||
}
|
||||
@@ -185,29 +182,24 @@ class _$Preparing implements Preparing {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object>({
|
||||
@required TResult preparing(Preparing value),
|
||||
@required TResult inProgress(InProgress value),
|
||||
@required TResult success(Success value),
|
||||
@required TResult failed(Failed value),
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Preparing value) preparing,
|
||||
required TResult Function(InProgress value) inProgress,
|
||||
required TResult Function(Success value) success,
|
||||
required TResult Function(Failed value) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return preparing(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object>({
|
||||
TResult preparing(Preparing value),
|
||||
TResult inProgress(InProgress value),
|
||||
TResult success(Success value),
|
||||
TResult failed(Failed value),
|
||||
@required TResult orElse(),
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (preparing != null) {
|
||||
return preparing(this);
|
||||
}
|
||||
@@ -245,12 +237,18 @@ class _$InProgressCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object uploaded = freezed,
|
||||
Object total = freezed,
|
||||
Object? uploaded = freezed,
|
||||
Object? total = freezed,
|
||||
}) {
|
||||
return _then(InProgress(
|
||||
uploaded: uploaded == freezed ? _value.uploaded : uploaded as int,
|
||||
total: total == freezed ? _value.total : total as int,
|
||||
uploaded: uploaded == freezed
|
||||
? _value.uploaded
|
||||
: uploaded // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
total: total == freezed
|
||||
? _value.total
|
||||
: total // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -259,7 +257,7 @@ class _$InProgressCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
|
||||
/// @nodoc
|
||||
class _$InProgress implements InProgress {
|
||||
const _$InProgress({this.uploaded, this.total});
|
||||
const _$InProgress({required this.uploaded, required this.total});
|
||||
|
||||
factory _$InProgress.fromJson(Map<String, dynamic> json) =>
|
||||
_$_$InProgressFromJson(json);
|
||||
@@ -298,29 +296,24 @@ class _$InProgress implements InProgress {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object>({
|
||||
@required TResult preparing(),
|
||||
@required TResult inProgress(int uploaded, int total),
|
||||
@required TResult success(),
|
||||
@required TResult failed(String error),
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() preparing,
|
||||
required TResult Function(int uploaded, int total) inProgress,
|
||||
required TResult Function() success,
|
||||
required TResult Function(String error) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return inProgress(uploaded, total);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object>({
|
||||
TResult preparing(),
|
||||
TResult inProgress(int uploaded, int total),
|
||||
TResult success(),
|
||||
TResult failed(String error),
|
||||
@required TResult orElse(),
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (inProgress != null) {
|
||||
return inProgress(uploaded, total);
|
||||
}
|
||||
@@ -329,29 +322,24 @@ class _$InProgress implements InProgress {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object>({
|
||||
@required TResult preparing(Preparing value),
|
||||
@required TResult inProgress(InProgress value),
|
||||
@required TResult success(Success value),
|
||||
@required TResult failed(Failed value),
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Preparing value) preparing,
|
||||
required TResult Function(InProgress value) inProgress,
|
||||
required TResult Function(Success value) success,
|
||||
required TResult Function(Failed value) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return inProgress(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object>({
|
||||
TResult preparing(Preparing value),
|
||||
TResult inProgress(InProgress value),
|
||||
TResult success(Success value),
|
||||
TResult failed(Failed value),
|
||||
@required TResult orElse(),
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (inProgress != null) {
|
||||
return inProgress(this);
|
||||
}
|
||||
@@ -365,15 +353,17 @@ class _$InProgress implements InProgress {
|
||||
}
|
||||
|
||||
abstract class InProgress implements UploadState {
|
||||
const factory InProgress({int uploaded, int total}) = _$InProgress;
|
||||
const factory InProgress({required int uploaded, required int total}) =
|
||||
_$InProgress;
|
||||
|
||||
factory InProgress.fromJson(Map<String, dynamic> json) =
|
||||
_$InProgress.fromJson;
|
||||
|
||||
int get uploaded;
|
||||
int get total;
|
||||
int get uploaded => throw _privateConstructorUsedError;
|
||||
int get total => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$InProgressCopyWith<InProgress> get copyWith;
|
||||
$InProgressCopyWith<InProgress> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -416,29 +406,24 @@ class _$Success implements Success {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object>({
|
||||
@required TResult preparing(),
|
||||
@required TResult inProgress(int uploaded, int total),
|
||||
@required TResult success(),
|
||||
@required TResult failed(String error),
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() preparing,
|
||||
required TResult Function(int uploaded, int total) inProgress,
|
||||
required TResult Function() success,
|
||||
required TResult Function(String error) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return success();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object>({
|
||||
TResult preparing(),
|
||||
TResult inProgress(int uploaded, int total),
|
||||
TResult success(),
|
||||
TResult failed(String error),
|
||||
@required TResult orElse(),
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (success != null) {
|
||||
return success();
|
||||
}
|
||||
@@ -447,29 +432,24 @@ class _$Success implements Success {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object>({
|
||||
@required TResult preparing(Preparing value),
|
||||
@required TResult inProgress(InProgress value),
|
||||
@required TResult success(Success value),
|
||||
@required TResult failed(Failed value),
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Preparing value) preparing,
|
||||
required TResult Function(InProgress value) inProgress,
|
||||
required TResult Function(Success value) success,
|
||||
required TResult Function(Failed value) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return success(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object>({
|
||||
TResult preparing(Preparing value),
|
||||
TResult inProgress(InProgress value),
|
||||
TResult success(Success value),
|
||||
TResult failed(Failed value),
|
||||
@required TResult orElse(),
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (success != null) {
|
||||
return success(this);
|
||||
}
|
||||
@@ -506,10 +486,13 @@ class _$FailedCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object error = freezed,
|
||||
Object? error = freezed,
|
||||
}) {
|
||||
return _then(Failed(
|
||||
error: error == freezed ? _value.error : error as String,
|
||||
error: error == freezed
|
||||
? _value.error
|
||||
: error // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -518,7 +501,7 @@ class _$FailedCopyWithImpl<$Res> extends _$UploadStateCopyWithImpl<$Res>
|
||||
|
||||
/// @nodoc
|
||||
class _$Failed implements Failed {
|
||||
const _$Failed({@required this.error}) : assert(error != null);
|
||||
const _$Failed({required this.error});
|
||||
|
||||
factory _$Failed.fromJson(Map<String, dynamic> json) =>
|
||||
_$_$FailedFromJson(json);
|
||||
@@ -550,29 +533,24 @@ class _$Failed implements Failed {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object>({
|
||||
@required TResult preparing(),
|
||||
@required TResult inProgress(int uploaded, int total),
|
||||
@required TResult success(),
|
||||
@required TResult failed(String error),
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() preparing,
|
||||
required TResult Function(int uploaded, int total) inProgress,
|
||||
required TResult Function() success,
|
||||
required TResult Function(String error) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return failed(error);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object>({
|
||||
TResult preparing(),
|
||||
TResult inProgress(int uploaded, int total),
|
||||
TResult success(),
|
||||
TResult failed(String error),
|
||||
@required TResult orElse(),
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? preparing,
|
||||
TResult Function(int uploaded, int total)? inProgress,
|
||||
TResult Function()? success,
|
||||
TResult Function(String error)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (failed != null) {
|
||||
return failed(error);
|
||||
}
|
||||
@@ -581,29 +559,24 @@ class _$Failed implements Failed {
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object>({
|
||||
@required TResult preparing(Preparing value),
|
||||
@required TResult inProgress(InProgress value),
|
||||
@required TResult success(Success value),
|
||||
@required TResult failed(Failed value),
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Preparing value) preparing,
|
||||
required TResult Function(InProgress value) inProgress,
|
||||
required TResult Function(Success value) success,
|
||||
required TResult Function(Failed value) failed,
|
||||
}) {
|
||||
assert(preparing != null);
|
||||
assert(inProgress != null);
|
||||
assert(success != null);
|
||||
assert(failed != null);
|
||||
return failed(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object>({
|
||||
TResult preparing(Preparing value),
|
||||
TResult inProgress(InProgress value),
|
||||
TResult success(Success value),
|
||||
TResult failed(Failed value),
|
||||
@required TResult orElse(),
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Preparing value)? preparing,
|
||||
TResult Function(InProgress value)? inProgress,
|
||||
TResult Function(Success value)? success,
|
||||
TResult Function(Failed value)? failed,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
assert(orElse != null);
|
||||
if (failed != null) {
|
||||
return failed(this);
|
||||
}
|
||||
@@ -617,11 +590,11 @@ class _$Failed implements Failed {
|
||||
}
|
||||
|
||||
abstract class Failed implements UploadState {
|
||||
const factory Failed({@required String error}) = _$Failed;
|
||||
const factory Failed({required String error}) = _$Failed;
|
||||
|
||||
factory Failed.fromJson(Map<String, dynamic> json) = _$Failed.fromJson;
|
||||
|
||||
String get error;
|
||||
String get error => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$FailedCopyWith<Failed> get copyWith;
|
||||
$FailedCopyWith<Failed> get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ part of 'attachment_file.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
AttachmentFile _$AttachmentFileFromJson(Map json) {
|
||||
AttachmentFile _$AttachmentFileFromJson(Map<String, dynamic> json) {
|
||||
return AttachmentFile(
|
||||
path: json['path'] as String,
|
||||
name: json['name'] as String,
|
||||
bytes: _fromString(json['bytes'] as String),
|
||||
size: json['size'] as int,
|
||||
path: json['path'] as String?,
|
||||
name: json['name'] as String?,
|
||||
bytes: _fromString(json['bytes'] as String?),
|
||||
size: json['size'] as int?,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ Map<String, dynamic> _$AttachmentFileToJson(AttachmentFile instance) =>
|
||||
'size': instance.size,
|
||||
};
|
||||
|
||||
_$Preparing _$_$PreparingFromJson(Map json) {
|
||||
_$Preparing _$_$PreparingFromJson(Map<String, dynamic> json) {
|
||||
return _$Preparing();
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$_$PreparingToJson(_$Preparing instance) =>
|
||||
<String, dynamic>{};
|
||||
|
||||
_$InProgress _$_$InProgressFromJson(Map json) {
|
||||
_$InProgress _$_$InProgressFromJson(Map<String, dynamic> json) {
|
||||
return _$InProgress(
|
||||
uploaded: json['uploaded'] as int,
|
||||
total: json['total'] as int,
|
||||
@@ -43,14 +43,14 @@ Map<String, dynamic> _$_$InProgressToJson(_$InProgress instance) =>
|
||||
'total': instance.total,
|
||||
};
|
||||
|
||||
_$Success _$_$SuccessFromJson(Map json) {
|
||||
_$Success _$_$SuccessFromJson(Map<String, dynamic> json) {
|
||||
return _$Success();
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$_$SuccessToJson(_$Success instance) =>
|
||||
<String, dynamic>{};
|
||||
|
||||
_$Failed _$_$FailedFromJson(Map json) {
|
||||
_$Failed _$_$FailedFromJson(Map<String, dynamic> json) {
|
||||
return _$Failed(
|
||||
error: json['error'] as String,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:stream_chat/src/models/command.dart';
|
||||
|
||||
part 'channel_config.g.dart';
|
||||
|
||||
/// The class that contains the information about the configuration of a channel
|
||||
@@ -7,35 +8,38 @@ part 'channel_config.g.dart';
|
||||
class ChannelConfig {
|
||||
/// Constructor used for json serialization
|
||||
ChannelConfig({
|
||||
this.automod,
|
||||
this.commands,
|
||||
this.connectEvents,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.maxMessageLength,
|
||||
this.messageRetention,
|
||||
this.mutes,
|
||||
this.name,
|
||||
this.reactions,
|
||||
this.readEvents,
|
||||
this.replies,
|
||||
this.search,
|
||||
this.typingEvents,
|
||||
this.uploads,
|
||||
this.urlEnrichment,
|
||||
});
|
||||
this.automod = 'flag',
|
||||
this.commands = const [],
|
||||
this.connectEvents = false,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
this.maxMessageLength = 0,
|
||||
this.messageRetention = '',
|
||||
this.mutes = false,
|
||||
this.reactions = false,
|
||||
this.readEvents = false,
|
||||
this.replies = false,
|
||||
this.search = false,
|
||||
this.typingEvents = false,
|
||||
this.uploads = false,
|
||||
this.urlEnrichment = false,
|
||||
}) : createdAt = createdAt ?? DateTime.now(),
|
||||
updatedAt = updatedAt ?? DateTime.now();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory ChannelConfig.fromJson(Map<String, dynamic> json) =>
|
||||
_$ChannelConfigFromJson(json);
|
||||
|
||||
/// Moderation configuration
|
||||
@JsonKey(defaultValue: 'flag')
|
||||
final String automod;
|
||||
|
||||
/// List of available commands
|
||||
@JsonKey(defaultValue: [])
|
||||
final List<Command> commands;
|
||||
|
||||
/// True if the channel should send connect events
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool connectEvents;
|
||||
|
||||
/// Date of channel creation
|
||||
@@ -45,36 +49,43 @@ class ChannelConfig {
|
||||
final DateTime updatedAt;
|
||||
|
||||
/// Max channel message length
|
||||
@JsonKey(defaultValue: 0)
|
||||
final int maxMessageLength;
|
||||
|
||||
/// Duration of message retention
|
||||
@JsonKey(defaultValue: '')
|
||||
final String messageRetention;
|
||||
|
||||
/// True if users can be muted
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool mutes;
|
||||
|
||||
/// Name of the channel
|
||||
final String name;
|
||||
|
||||
/// True if reaction are active for this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool reactions;
|
||||
|
||||
/// True if readEvents are active for this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool readEvents;
|
||||
|
||||
/// True if reply message are active for this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool replies;
|
||||
|
||||
/// True if it's possible to perform a search in this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool search;
|
||||
|
||||
/// True if typing events should be sent for this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool typingEvents;
|
||||
|
||||
/// True if it's possible to upload files to this channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool uploads;
|
||||
|
||||
/// True if urls appears as attachments
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool urlEnrichment;
|
||||
|
||||
/// Serialize to json
|
||||
|
||||
@@ -6,48 +6,43 @@ part of 'channel_config.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ChannelConfig _$ChannelConfigFromJson(Map json) {
|
||||
ChannelConfig _$ChannelConfigFromJson(Map<String, dynamic> json) {
|
||||
return ChannelConfig(
|
||||
automod: json['automod'] as String,
|
||||
commands: (json['commands'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Command.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
connectEvents: json['connect_events'] as bool,
|
||||
automod: json['automod'] as String? ?? 'flag',
|
||||
commands: (json['commands'] as List<dynamic>?)
|
||||
?.map((e) => Command.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
connectEvents: json['connect_events'] as bool? ?? false,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: json['updated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
maxMessageLength: json['max_message_length'] as int,
|
||||
messageRetention: json['message_retention'] as String,
|
||||
mutes: json['mutes'] as bool,
|
||||
name: json['name'] as String,
|
||||
reactions: json['reactions'] as bool,
|
||||
readEvents: json['read_events'] as bool,
|
||||
replies: json['replies'] as bool,
|
||||
search: json['search'] as bool,
|
||||
typingEvents: json['typing_events'] as bool,
|
||||
uploads: json['uploads'] as bool,
|
||||
urlEnrichment: json['url_enrichment'] as bool,
|
||||
maxMessageLength: json['max_message_length'] as int? ?? 0,
|
||||
messageRetention: json['message_retention'] as String? ?? '',
|
||||
mutes: json['mutes'] as bool? ?? false,
|
||||
reactions: json['reactions'] as bool? ?? false,
|
||||
readEvents: json['read_events'] as bool? ?? false,
|
||||
replies: json['replies'] as bool? ?? false,
|
||||
search: json['search'] as bool? ?? false,
|
||||
typingEvents: json['typing_events'] as bool? ?? false,
|
||||
uploads: json['uploads'] as bool? ?? false,
|
||||
urlEnrichment: json['url_enrichment'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$ChannelConfigToJson(ChannelConfig instance) =>
|
||||
<String, dynamic>{
|
||||
'automod': instance.automod,
|
||||
'commands': instance.commands?.map((e) => e?.toJson())?.toList(),
|
||||
'commands': instance.commands.map((e) => e.toJson()).toList(),
|
||||
'connect_events': instance.connectEvents,
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'updated_at': instance.updatedAt?.toIso8601String(),
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'max_message_length': instance.maxMessageLength,
|
||||
'message_retention': instance.messageRetention,
|
||||
'mutes': instance.mutes,
|
||||
'name': instance.name,
|
||||
'reactions': instance.reactions,
|
||||
'read_events': instance.readEvents,
|
||||
'replies': instance.replies,
|
||||
|
||||
@@ -10,20 +10,29 @@ part 'channel_model.g.dart';
|
||||
class ChannelModel {
|
||||
/// Constructor used for json serialization
|
||||
ChannelModel({
|
||||
this.id,
|
||||
this.type,
|
||||
this.cid,
|
||||
this.config,
|
||||
String? id,
|
||||
String? type,
|
||||
String? cid,
|
||||
ChannelConfig? config,
|
||||
this.createdBy,
|
||||
this.frozen,
|
||||
this.frozen = false,
|
||||
this.lastMessageAt,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
this.deletedAt,
|
||||
this.memberCount,
|
||||
this.memberCount = 0,
|
||||
this.extraData,
|
||||
this.team,
|
||||
});
|
||||
}) : config = config ?? ChannelConfig(),
|
||||
createdAt = createdAt ?? DateTime.now(),
|
||||
updatedAt = updatedAt ?? DateTime.now(),
|
||||
assert(
|
||||
cid != null || (id != null && type != null),
|
||||
'provide either a cid or an id and type',
|
||||
),
|
||||
id = id ?? cid!.split(':')[1],
|
||||
type = type ?? cid!.split(':')[0],
|
||||
cid = cid ?? '$type:$id';
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory ChannelModel.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -46,15 +55,15 @@ class ChannelModel {
|
||||
|
||||
/// The user that created this channel
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final User createdBy;
|
||||
final User? createdBy;
|
||||
|
||||
/// True if this channel is frozen
|
||||
@JsonKey(includeIfNull: false)
|
||||
@JsonKey(includeIfNull: false, defaultValue: false)
|
||||
final bool frozen;
|
||||
|
||||
/// The date of the last message
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime lastMessageAt;
|
||||
final DateTime? lastMessageAt;
|
||||
|
||||
/// The date of channel creation
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@@ -66,19 +75,20 @@ class ChannelModel {
|
||||
|
||||
/// The date of channel deletion
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime deletedAt;
|
||||
final DateTime? deletedAt;
|
||||
|
||||
/// The count of this channel members
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false, toJson: Serialization.readOnly, defaultValue: 0)
|
||||
final int memberCount;
|
||||
|
||||
/// Map of custom channel extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
final Map<String, dynamic>? extraData;
|
||||
|
||||
/// The team the channel belongs to
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final String team;
|
||||
final String? team;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -98,30 +108,29 @@ class ChannelModel {
|
||||
];
|
||||
|
||||
/// Shortcut for channel name
|
||||
String get name =>
|
||||
extraData?.containsKey('name') == true ? extraData['name'] : cid;
|
||||
String? get name =>
|
||||
extraData?.containsKey('name') == true ? extraData!['name'] : cid;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$ChannelModelToJson(this),
|
||||
topLevelFields,
|
||||
);
|
||||
|
||||
/// Creates a copy of [ChannelModel] with specified attributes overridden.
|
||||
ChannelModel copyWith({
|
||||
String id,
|
||||
String type,
|
||||
String cid,
|
||||
ChannelConfig config,
|
||||
User createdBy,
|
||||
bool frozen,
|
||||
DateTime lastMessageAt,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime deletedAt,
|
||||
int memberCount,
|
||||
Map<String, dynamic> extraData,
|
||||
String team,
|
||||
String? id,
|
||||
String? type,
|
||||
String? cid,
|
||||
ChannelConfig? config,
|
||||
User? createdBy,
|
||||
bool? frozen,
|
||||
DateTime? lastMessageAt,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? deletedAt,
|
||||
int? memberCount,
|
||||
Map<String, dynamic>? extraData,
|
||||
String? team,
|
||||
}) =>
|
||||
ChannelModel(
|
||||
id: id ?? this.id,
|
||||
@@ -141,7 +150,7 @@ class ChannelModel {
|
||||
|
||||
/// Returns a new [ChannelModel] that is a combination of this channelModel
|
||||
/// and the given [other] channelModel.
|
||||
ChannelModel merge(ChannelModel other) {
|
||||
ChannelModel merge(ChannelModel? other) {
|
||||
if (other == null) return this;
|
||||
return copyWith(
|
||||
id: other.id,
|
||||
|
||||
@@ -6,22 +6,18 @@ part of 'channel_model.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ChannelModel _$ChannelModelFromJson(Map json) {
|
||||
ChannelModel _$ChannelModelFromJson(Map<String, dynamic> json) {
|
||||
return ChannelModel(
|
||||
id: json['id'] as String,
|
||||
type: json['type'] as String,
|
||||
cid: json['cid'] as String,
|
||||
id: json['id'] as String?,
|
||||
type: json['type'] as String?,
|
||||
cid: json['cid'] as String?,
|
||||
config: json['config'] == null
|
||||
? null
|
||||
: ChannelConfig.fromJson((json['config'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: ChannelConfig.fromJson(json['config'] as Map<String, dynamic>),
|
||||
createdBy: json['created_by'] == null
|
||||
? null
|
||||
: User.fromJson((json['created_by'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
frozen: json['frozen'] as bool,
|
||||
: User.fromJson(json['created_by'] as Map<String, dynamic>),
|
||||
frozen: json['frozen'] as bool? ?? false,
|
||||
lastMessageAt: json['last_message_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_message_at'] as String),
|
||||
@@ -34,11 +30,9 @@ ChannelModel _$ChannelModelFromJson(Map json) {
|
||||
deletedAt: json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
memberCount: json['member_count'] as int,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
team: json['team'] as String,
|
||||
memberCount: json['member_count'] as int? ?? 0,
|
||||
extraData: json['extra_data'] as Map<String, dynamic>?,
|
||||
team: json['team'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -57,7 +51,7 @@ Map<String, dynamic> _$ChannelModelToJson(ChannelModel instance) {
|
||||
writeNotNull('cid', readonly(instance.cid));
|
||||
writeNotNull('config', readonly(instance.config));
|
||||
writeNotNull('created_by', readonly(instance.createdBy));
|
||||
writeNotNull('frozen', instance.frozen);
|
||||
val['frozen'] = instance.frozen;
|
||||
writeNotNull('last_message_at', readonly(instance.lastMessageAt));
|
||||
writeNotNull('created_at', readonly(instance.createdAt));
|
||||
writeNotNull('updated_at', readonly(instance.updatedAt));
|
||||
|
||||
@@ -22,24 +22,29 @@ class ChannelState {
|
||||
});
|
||||
|
||||
/// The channel to which this state belongs
|
||||
final ChannelModel channel;
|
||||
final ChannelModel? channel;
|
||||
|
||||
/// A paginated list of channel messages
|
||||
@JsonKey(defaultValue: <Message>[])
|
||||
final List<Message> messages;
|
||||
|
||||
/// A paginated list of channel members
|
||||
@JsonKey(defaultValue: <Member>[])
|
||||
final List<Member> members;
|
||||
|
||||
/// A paginated list of pinned messages
|
||||
@JsonKey(defaultValue: <Message>[])
|
||||
final List<Message> pinnedMessages;
|
||||
|
||||
/// The count of users watching the channel
|
||||
final int watcherCount;
|
||||
final int? watcherCount;
|
||||
|
||||
/// A paginated list of users watching the channel
|
||||
@JsonKey(defaultValue: <User>[])
|
||||
final List<User> watchers;
|
||||
|
||||
/// The list of channel reads
|
||||
@JsonKey(defaultValue: <Read>[])
|
||||
final List<Read> read;
|
||||
|
||||
/// Create a new instance from a json
|
||||
@@ -51,13 +56,13 @@ class ChannelState {
|
||||
|
||||
/// Creates a copy of [ChannelState] with specified attributes overridden.
|
||||
ChannelState copyWith({
|
||||
ChannelModel channel,
|
||||
List<Message> messages,
|
||||
List<Member> members,
|
||||
List<Message> pinnedMessages,
|
||||
int watcherCount,
|
||||
List<User> watchers,
|
||||
List<Read> read,
|
||||
ChannelModel? channel,
|
||||
List<Message>? messages,
|
||||
List<Member>? members,
|
||||
List<Message>? pinnedMessages,
|
||||
int? watcherCount,
|
||||
List<User>? watchers,
|
||||
List<Read>? read,
|
||||
}) =>
|
||||
ChannelState(
|
||||
channel: channel ?? this.channel,
|
||||
|
||||
@@ -6,60 +6,43 @@ part of 'channel_state.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ChannelState _$ChannelStateFromJson(Map json) {
|
||||
ChannelState _$ChannelStateFromJson(Map<String, dynamic> json) {
|
||||
return ChannelState(
|
||||
channel: json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
messages: (json['messages'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Message.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
members: (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
pinnedMessages: (json['pinned_messages'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Message.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
watcherCount: json['watcher_count'] as int,
|
||||
watchers: (json['watchers'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: User.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
read: (json['read'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Read.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
: ChannelModel.fromJson(json['channel'] as Map<String, dynamic>),
|
||||
messages: (json['messages'] as List<dynamic>?)
|
||||
?.map((e) => Message.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
members: (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
pinnedMessages: (json['pinned_messages'] as List<dynamic>?)
|
||||
?.map((e) => Message.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
watcherCount: json['watcher_count'] as int?,
|
||||
watchers: (json['watchers'] as List<dynamic>?)
|
||||
?.map((e) => User.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
read: (json['read'] as List<dynamic>?)
|
||||
?.map((e) => Read.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$ChannelStateToJson(ChannelState instance) =>
|
||||
<String, dynamic>{
|
||||
'channel': instance.channel?.toJson(),
|
||||
'messages': instance.messages?.map((e) => e?.toJson())?.toList(),
|
||||
'members': instance.members?.map((e) => e?.toJson())?.toList(),
|
||||
'messages': instance.messages.map((e) => e.toJson()).toList(),
|
||||
'members': instance.members.map((e) => e.toJson()).toList(),
|
||||
'pinned_messages':
|
||||
instance.pinnedMessages?.map((e) => e?.toJson())?.toList(),
|
||||
instance.pinnedMessages.map((e) => e.toJson()).toList(),
|
||||
'watcher_count': instance.watcherCount,
|
||||
'watchers': instance.watchers?.map((e) => e?.toJson())?.toList(),
|
||||
'read': instance.read?.map((e) => e?.toJson())?.toList(),
|
||||
'watchers': instance.watchers.map((e) => e.toJson()).toList(),
|
||||
'read': instance.read.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
|
||||
@@ -7,9 +7,9 @@ part 'command.g.dart';
|
||||
class Command {
|
||||
/// Constructor used for json serialization
|
||||
Command({
|
||||
this.name,
|
||||
this.description,
|
||||
this.args,
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.args,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'command.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Command _$CommandFromJson(Map json) {
|
||||
Command _$CommandFromJson(Map<String, dynamic> json) {
|
||||
return Command(
|
||||
name: json['name'] as String,
|
||||
description: json['description'] as String,
|
||||
|
||||
@@ -7,8 +7,8 @@ part 'device.g.dart';
|
||||
class Device {
|
||||
/// Constructor used for json serialization
|
||||
Device({
|
||||
this.id,
|
||||
this.pushProvider,
|
||||
required this.id,
|
||||
required this.pushProvider,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'device.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Device _$DeviceFromJson(Map json) {
|
||||
Device _$DeviceFromJson(Map<String, dynamic> json) {
|
||||
return Device(
|
||||
id: json['id'] as String,
|
||||
pushProvider: json['push_provider'] as String,
|
||||
|
||||
@@ -10,7 +10,7 @@ part 'event.g.dart';
|
||||
@JsonSerializable()
|
||||
class Event {
|
||||
/// Constructor used for json serialization
|
||||
Event({
|
||||
const Event({
|
||||
this.type,
|
||||
this.cid,
|
||||
this.connectionId,
|
||||
@@ -27,71 +27,72 @@ class Event {
|
||||
this.channelId,
|
||||
this.channelType,
|
||||
this.parentId,
|
||||
this.extraData,
|
||||
}) : isLocal = true;
|
||||
this.extraData = const {},
|
||||
this.isLocal = true,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Event.fromJson(Map<String, dynamic> json) =>
|
||||
_$EventFromJson(Serialization.moveToExtraDataFromRoot(
|
||||
json,
|
||||
topLevelFields,
|
||||
))
|
||||
..isLocal = false;
|
||||
));
|
||||
|
||||
/// The type of the event
|
||||
/// [EventType] contains some predefined constant types
|
||||
final String type;
|
||||
final String? type;
|
||||
|
||||
/// The channel cid to which the event belongs
|
||||
final String cid;
|
||||
final String? cid;
|
||||
|
||||
/// The channel id to which the event belongs
|
||||
final String channelId;
|
||||
final String? channelId;
|
||||
|
||||
/// The channel type to which the event belongs
|
||||
final String channelType;
|
||||
final String? channelType;
|
||||
|
||||
/// The connection id in which the event has been sent
|
||||
final String connectionId;
|
||||
final String? connectionId;
|
||||
|
||||
/// The date of creation of the event
|
||||
final DateTime createdAt;
|
||||
final DateTime? createdAt;
|
||||
|
||||
/// User object of the health check user
|
||||
final OwnUser me;
|
||||
final OwnUser? me;
|
||||
|
||||
/// User object of the current user
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// The message sent with the event
|
||||
final Message message;
|
||||
final Message? message;
|
||||
|
||||
/// The channel sent with the event
|
||||
final EventChannel channel;
|
||||
final EventChannel? channel;
|
||||
|
||||
/// The member sent with the event
|
||||
final Member member;
|
||||
final Member? member;
|
||||
|
||||
/// The reaction sent with the event
|
||||
final Reaction reaction;
|
||||
final Reaction? reaction;
|
||||
|
||||
/// The number of unread messages for current user
|
||||
final int totalUnreadCount;
|
||||
final int? totalUnreadCount;
|
||||
|
||||
/// User total unread channels
|
||||
final int unreadChannels;
|
||||
final int? unreadChannels;
|
||||
|
||||
/// Online status
|
||||
final bool online;
|
||||
final bool? online;
|
||||
|
||||
/// The id of the parent message of a thread
|
||||
final String parentId;
|
||||
final String? parentId;
|
||||
|
||||
/// True if the event is generated by this client
|
||||
bool isLocal;
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool isLocal;
|
||||
|
||||
/// Map of custom channel extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
@JsonKey(defaultValue: {})
|
||||
final Map<String, dynamic> extraData;
|
||||
|
||||
/// Known top level fields.
|
||||
@@ -119,28 +120,27 @@ class Event {
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$EventToJson(this),
|
||||
topLevelFields,
|
||||
);
|
||||
|
||||
/// Creates a copy of [Event] with specified attributes overridden.
|
||||
Event copyWith({
|
||||
String type,
|
||||
String cid,
|
||||
String channelId,
|
||||
String channelType,
|
||||
String connectionId,
|
||||
DateTime createdAt,
|
||||
OwnUser me,
|
||||
User user,
|
||||
Message message,
|
||||
EventChannel channel,
|
||||
Member member,
|
||||
Reaction reaction,
|
||||
int totalUnreadCount,
|
||||
int unreadChannels,
|
||||
bool online,
|
||||
String parentId,
|
||||
Map<String, dynamic> extraData,
|
||||
String? type,
|
||||
String? cid,
|
||||
String? channelId,
|
||||
String? channelType,
|
||||
String? connectionId,
|
||||
DateTime? createdAt,
|
||||
OwnUser? me,
|
||||
User? user,
|
||||
Message? message,
|
||||
EventChannel? channel,
|
||||
Member? member,
|
||||
Reaction? reaction,
|
||||
int? totalUnreadCount,
|
||||
int? unreadChannels,
|
||||
bool? online,
|
||||
String? parentId,
|
||||
Map<String, dynamic>? extraData,
|
||||
}) =>
|
||||
Event(
|
||||
type: type ?? this.type,
|
||||
@@ -169,18 +169,18 @@ class EventChannel extends ChannelModel {
|
||||
/// Constructor used for json serialization
|
||||
EventChannel({
|
||||
this.members,
|
||||
String id,
|
||||
String type,
|
||||
String cid,
|
||||
ChannelConfig config,
|
||||
User createdBy,
|
||||
bool frozen,
|
||||
DateTime lastMessageAt,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime deletedAt,
|
||||
int memberCount,
|
||||
Map<String, dynamic> extraData,
|
||||
String? id,
|
||||
String? type,
|
||||
required String cid,
|
||||
required ChannelConfig config,
|
||||
User? createdBy,
|
||||
bool frozen = false,
|
||||
DateTime? lastMessageAt,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
DateTime? deletedAt,
|
||||
required int memberCount,
|
||||
Map<String, dynamic>? extraData,
|
||||
}) : super(
|
||||
id: id,
|
||||
type: type,
|
||||
@@ -204,7 +204,7 @@ class EventChannel extends ChannelModel {
|
||||
));
|
||||
|
||||
/// A paginated list of channel members
|
||||
final List<Member> members;
|
||||
final List<Member>? members;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -217,6 +217,5 @@ class EventChannel extends ChannelModel {
|
||||
@override
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$EventChannelToJson(this),
|
||||
topLevelFields,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,126 +6,87 @@ part of 'event.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Event _$EventFromJson(Map json) {
|
||||
Event _$EventFromJson(Map<String, dynamic> json) {
|
||||
return Event(
|
||||
type: json['type'] as String,
|
||||
cid: json['cid'] as String,
|
||||
connectionId: json['connection_id'] as String,
|
||||
type: json['type'] as String?,
|
||||
cid: json['cid'] as String?,
|
||||
connectionId: json['connection_id'] as String?,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
me: json['me'] == null
|
||||
? null
|
||||
: OwnUser.fromJson((json['me'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: OwnUser.fromJson(json['me'] as Map<String, dynamic>),
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
message: json['message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
totalUnreadCount: json['total_unread_count'] as int,
|
||||
unreadChannels: json['unread_channels'] as int,
|
||||
: Message.fromJson(json['message'] as Map<String, dynamic>),
|
||||
totalUnreadCount: json['total_unread_count'] as int?,
|
||||
unreadChannels: json['unread_channels'] as int?,
|
||||
reaction: json['reaction'] == null
|
||||
? null
|
||||
: Reaction.fromJson((json['reaction'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
online: json['online'] as bool,
|
||||
: Reaction.fromJson(json['reaction'] as Map<String, dynamic>),
|
||||
online: json['online'] as bool?,
|
||||
channel: json['channel'] == null
|
||||
? null
|
||||
: EventChannel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: EventChannel.fromJson(json['channel'] as Map<String, dynamic>),
|
||||
member: json['member'] == null
|
||||
? null
|
||||
: Member.fromJson((json['member'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
channelId: json['channel_id'] as String,
|
||||
channelType: json['channel_type'] as String,
|
||||
parentId: json['parent_id'] as String,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
)..isLocal = json['is_local'] as bool;
|
||||
: Member.fromJson(json['member'] as Map<String, dynamic>),
|
||||
channelId: json['channel_id'] as String?,
|
||||
channelType: json['channel_type'] as String?,
|
||||
parentId: json['parent_id'] as String?,
|
||||
extraData: json['extra_data'] as Map<String, dynamic>? ?? {},
|
||||
isLocal: json['is_local'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$EventToJson(Event instance) {
|
||||
final val = <String, dynamic>{
|
||||
'type': instance.type,
|
||||
'cid': instance.cid,
|
||||
'channel_id': instance.channelId,
|
||||
'channel_type': instance.channelType,
|
||||
'connection_id': instance.connectionId,
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'me': instance.me?.toJson(),
|
||||
'user': instance.user?.toJson(),
|
||||
'message': instance.message?.toJson(),
|
||||
'channel': instance.channel?.toJson(),
|
||||
'member': instance.member?.toJson(),
|
||||
'reaction': instance.reaction?.toJson(),
|
||||
'total_unread_count': instance.totalUnreadCount,
|
||||
'unread_channels': instance.unreadChannels,
|
||||
'online': instance.online,
|
||||
'parent_id': instance.parentId,
|
||||
'is_local': instance.isLocal,
|
||||
};
|
||||
Map<String, dynamic> _$EventToJson(Event instance) => <String, dynamic>{
|
||||
'type': instance.type,
|
||||
'cid': instance.cid,
|
||||
'channel_id': instance.channelId,
|
||||
'channel_type': instance.channelType,
|
||||
'connection_id': instance.connectionId,
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'me': instance.me?.toJson(),
|
||||
'user': instance.user?.toJson(),
|
||||
'message': instance.message?.toJson(),
|
||||
'channel': instance.channel?.toJson(),
|
||||
'member': instance.member?.toJson(),
|
||||
'reaction': instance.reaction?.toJson(),
|
||||
'total_unread_count': instance.totalUnreadCount,
|
||||
'unread_channels': instance.unreadChannels,
|
||||
'online': instance.online,
|
||||
'parent_id': instance.parentId,
|
||||
'is_local': instance.isLocal,
|
||||
'extra_data': instance.extraData,
|
||||
};
|
||||
|
||||
void writeNotNull(String key, dynamic value) {
|
||||
if (value != null) {
|
||||
val[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
return val;
|
||||
}
|
||||
|
||||
EventChannel _$EventChannelFromJson(Map json) {
|
||||
EventChannel _$EventChannelFromJson(Map<String, dynamic> json) {
|
||||
return EventChannel(
|
||||
members: (json['members'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Member.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
id: json['id'] as String,
|
||||
type: json['type'] as String,
|
||||
members: (json['members'] as List<dynamic>?)
|
||||
?.map((e) => Member.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
id: json['id'] as String?,
|
||||
type: json['type'] as String?,
|
||||
cid: json['cid'] as String,
|
||||
config: json['config'] == null
|
||||
? null
|
||||
: ChannelConfig.fromJson((json['config'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
config: ChannelConfig.fromJson(json['config'] as Map<String, dynamic>),
|
||||
createdBy: json['created_by'] == null
|
||||
? null
|
||||
: User.fromJson((json['created_by'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
frozen: json['frozen'] as bool,
|
||||
: User.fromJson(json['created_by'] as Map<String, dynamic>),
|
||||
frozen: json['frozen'] as bool? ?? false,
|
||||
lastMessageAt: json['last_message_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_message_at'] as String),
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: json['updated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt: json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
memberCount: json['member_count'] as int,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
memberCount: json['member_count'] as int? ?? 0,
|
||||
extraData: json['extra_data'] as Map<String, dynamic>?,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -144,13 +105,13 @@ Map<String, dynamic> _$EventChannelToJson(EventChannel instance) {
|
||||
writeNotNull('cid', readonly(instance.cid));
|
||||
writeNotNull('config', readonly(instance.config));
|
||||
writeNotNull('created_by', readonly(instance.createdBy));
|
||||
writeNotNull('frozen', instance.frozen);
|
||||
val['frozen'] = instance.frozen;
|
||||
writeNotNull('last_message_at', readonly(instance.lastMessageAt));
|
||||
writeNotNull('created_at', readonly(instance.createdAt));
|
||||
writeNotNull('updated_at', readonly(instance.updatedAt));
|
||||
writeNotNull('deleted_at', readonly(instance.deletedAt));
|
||||
writeNotNull('member_count', readonly(instance.memberCount));
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
val['members'] = instance.members?.map((e) => e?.toJson())?.toList();
|
||||
val['members'] = instance.members?.map((e) => e.toJson()).toList();
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -12,15 +12,16 @@ class Member {
|
||||
this.user,
|
||||
this.inviteAcceptedAt,
|
||||
this.inviteRejectedAt,
|
||||
this.invited,
|
||||
this.invited = false,
|
||||
this.role,
|
||||
this.userId,
|
||||
this.isModerator,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.banned,
|
||||
this.shadowBanned,
|
||||
});
|
||||
this.isModerator = false,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
this.banned = false,
|
||||
this.shadowBanned = false,
|
||||
}) : createdAt = createdAt ?? DateTime.now(),
|
||||
updatedAt = updatedAt ?? DateTime.now();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Member.fromJson(Map<String, dynamic> json) {
|
||||
@@ -31,30 +32,34 @@ class Member {
|
||||
}
|
||||
|
||||
/// The interested user
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// The date in which the user accepted the invite to the channel
|
||||
final DateTime inviteAcceptedAt;
|
||||
final DateTime? inviteAcceptedAt;
|
||||
|
||||
/// The date in which the user rejected the invite to the channel
|
||||
final DateTime inviteRejectedAt;
|
||||
final DateTime? inviteRejectedAt;
|
||||
|
||||
/// True if the user has been invited to the channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool invited;
|
||||
|
||||
/// The role of the user in the channel
|
||||
final String role;
|
||||
final String? role;
|
||||
|
||||
/// The id of the interested user
|
||||
final String userId;
|
||||
final String? userId;
|
||||
|
||||
/// True if the user is a moderator of the channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool isModerator;
|
||||
|
||||
/// True if the member is banned from the channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool banned;
|
||||
|
||||
/// True if the member is shadow banned from the channel
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool shadowBanned;
|
||||
|
||||
/// The date of creation
|
||||
@@ -65,17 +70,17 @@ class Member {
|
||||
|
||||
/// Creates a copy of [Member] with specified attributes overridden.
|
||||
Member copyWith({
|
||||
User user,
|
||||
DateTime inviteAcceptedAt,
|
||||
DateTime inviteRejectedAt,
|
||||
bool invited,
|
||||
String role,
|
||||
String userId,
|
||||
bool isModerator,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
bool banned,
|
||||
bool shadowBanned,
|
||||
User? user,
|
||||
DateTime? inviteAcceptedAt,
|
||||
DateTime? inviteRejectedAt,
|
||||
bool? invited,
|
||||
String? role,
|
||||
String? userId,
|
||||
bool? isModerator,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
bool? banned,
|
||||
bool? shadowBanned,
|
||||
}) =>
|
||||
Member(
|
||||
user: user ?? this.user,
|
||||
|
||||
@@ -6,31 +6,29 @@ part of 'member.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Member _$MemberFromJson(Map json) {
|
||||
Member _$MemberFromJson(Map<String, dynamic> json) {
|
||||
return Member(
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
inviteAcceptedAt: json['invite_accepted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['invite_accepted_at'] as String),
|
||||
inviteRejectedAt: json['invite_rejected_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['invite_rejected_at'] as String),
|
||||
invited: json['invited'] as bool,
|
||||
role: json['role'] as String,
|
||||
userId: json['user_id'] as String,
|
||||
isModerator: json['is_moderator'] as bool,
|
||||
invited: json['invited'] as bool? ?? false,
|
||||
role: json['role'] as String?,
|
||||
userId: json['user_id'] as String?,
|
||||
isModerator: json['is_moderator'] as bool? ?? false,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: json['updated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
banned: json['banned'] as bool,
|
||||
shadowBanned: json['shadow_banned'] as bool,
|
||||
banned: json['banned'] as bool? ?? false,
|
||||
shadowBanned: json['shadow_banned'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -44,6 +42,6 @@ Map<String, dynamic> _$MemberToJson(Member instance) => <String, dynamic>{
|
||||
'is_moderator': instance.isModerator,
|
||||
'banned': instance.banned,
|
||||
'shadow_banned': instance.shadowBanned,
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'updated_at': instance.updatedAt?.toIso8601String(),
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
};
|
||||
|
||||
@@ -45,13 +45,13 @@ enum MessageSendingStatus {
|
||||
class Message extends Equatable {
|
||||
/// Constructor used for json serialization
|
||||
Message({
|
||||
String id,
|
||||
String? id,
|
||||
this.text,
|
||||
this.type,
|
||||
this.attachments,
|
||||
this.mentionedUsers,
|
||||
this.silent,
|
||||
this.shadowed,
|
||||
this.type = 'regular',
|
||||
this.attachments = const [],
|
||||
this.mentionedUsers = const [],
|
||||
this.silent = false,
|
||||
this.shadowed = false,
|
||||
this.reactionCounts,
|
||||
this.reactionScores,
|
||||
this.latestReactions,
|
||||
@@ -63,19 +63,21 @@ class Message extends Equatable {
|
||||
this.threadParticipants,
|
||||
this.showInChannel,
|
||||
this.command,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
this.user,
|
||||
this.pinned = false,
|
||||
this.pinnedAt,
|
||||
DateTime pinExpires,
|
||||
DateTime? pinExpires,
|
||||
this.pinnedBy,
|
||||
this.extraData,
|
||||
this.extraData = const {},
|
||||
this.deletedAt,
|
||||
this.status = MessageSendingStatus.sent,
|
||||
this.skipPush,
|
||||
this.skipPush = false,
|
||||
}) : id = id ?? const Uuid().v4(),
|
||||
pinExpires = pinExpires?.toUtc();
|
||||
pinExpires = pinExpires?.toUtc(),
|
||||
createdAt = createdAt ?? DateTime.now(),
|
||||
updatedAt = updatedAt ?? DateTime.now();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Message.fromJson(Map<String, dynamic> json) => _$MessageFromJson(
|
||||
@@ -86,75 +88,91 @@ class Message extends Equatable {
|
||||
final String id;
|
||||
|
||||
/// The text of this message
|
||||
final String text;
|
||||
final String? text;
|
||||
|
||||
/// The status of a sending message
|
||||
@JsonKey(ignore: true)
|
||||
final MessageSendingStatus status;
|
||||
|
||||
/// The message type
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: 'regular',
|
||||
)
|
||||
final String type;
|
||||
|
||||
/// The list of attachments, either provided by the user or generated from a
|
||||
/// command or as a result of URL scraping.
|
||||
@JsonKey(includeIfNull: false)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
defaultValue: [],
|
||||
)
|
||||
final List<Attachment> attachments;
|
||||
|
||||
/// The list of user mentioned in the message
|
||||
@JsonKey(toJson: Serialization.userIds)
|
||||
@JsonKey(
|
||||
toJson: Serialization.userIds,
|
||||
defaultValue: [],
|
||||
)
|
||||
final List<User> mentionedUsers;
|
||||
|
||||
/// A map describing the count of number of every reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final Map<String, int> reactionCounts;
|
||||
final Map<String, int>? reactionCounts;
|
||||
|
||||
/// A map describing the count of score of every reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final Map<String, int> reactionScores;
|
||||
final Map<String, int>? reactionScores;
|
||||
|
||||
/// The latest reactions to the message created by any user.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final List<Reaction> latestReactions;
|
||||
final List<Reaction>? latestReactions;
|
||||
|
||||
/// The reactions added to the message by the current user.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final List<Reaction> ownReactions;
|
||||
final List<Reaction>? ownReactions;
|
||||
|
||||
/// The ID of the parent message, if the message is a thread reply.
|
||||
final String parentId;
|
||||
final String? parentId;
|
||||
|
||||
/// A quoted reply message
|
||||
@JsonKey(toJson: Serialization.readOnly)
|
||||
final Message quotedMessage;
|
||||
final Message? quotedMessage;
|
||||
|
||||
/// The ID of the quoted message, if the message is a quoted reply.
|
||||
final String quotedMessageId;
|
||||
final String? quotedMessageId;
|
||||
|
||||
/// Reserved field indicating the number of replies for this message.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final int replyCount;
|
||||
final int? replyCount;
|
||||
|
||||
/// Reserved field indicating the thread participants for this message.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final List<User> threadParticipants;
|
||||
final List<User>? threadParticipants;
|
||||
|
||||
/// Check if this message needs to show in the channel.
|
||||
final bool showInChannel;
|
||||
final bool? showInChannel;
|
||||
|
||||
/// If true the message is silent
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool silent;
|
||||
|
||||
/// If true the message will not send a push notification
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool skipPush;
|
||||
|
||||
/// If true the message is shadowed
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: false,
|
||||
)
|
||||
final bool shadowed;
|
||||
|
||||
/// A used command name.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final String command;
|
||||
final String? command;
|
||||
|
||||
/// Reserved field indicating when the message was created.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@@ -166,26 +184,30 @@ class Message extends Equatable {
|
||||
|
||||
/// User who sent the message
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// If true the message is pinned
|
||||
@JsonKey(defaultValue: false)
|
||||
final bool pinned;
|
||||
|
||||
/// Reserved field indicating when the message was pinned
|
||||
@JsonKey(toJson: Serialization.readOnly)
|
||||
final DateTime pinnedAt;
|
||||
final DateTime? pinnedAt;
|
||||
|
||||
/// Reserved field indicating when the message will expire
|
||||
///
|
||||
/// if `null` message has no expiry
|
||||
final DateTime pinExpires;
|
||||
final DateTime? pinExpires;
|
||||
|
||||
/// Reserved field indicating who pinned the message
|
||||
@JsonKey(toJson: Serialization.readOnly)
|
||||
final User pinnedBy;
|
||||
final User? pinnedBy;
|
||||
|
||||
/// Message custom extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
defaultValue: {},
|
||||
)
|
||||
final Map<String, dynamic> extraData;
|
||||
|
||||
/// True if the message is a system info
|
||||
@@ -199,7 +221,7 @@ class Message extends Equatable {
|
||||
|
||||
/// Reserved field indicating when the message was deleted.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime deletedAt;
|
||||
final DateTime? deletedAt;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -236,39 +258,40 @@ class Message extends Equatable {
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$MessageToJson(this), topLevelFields);
|
||||
_$MessageToJson(this),
|
||||
);
|
||||
|
||||
/// Creates a copy of [Message] with specified attributes overridden.
|
||||
Message copyWith({
|
||||
String id,
|
||||
String text,
|
||||
String type,
|
||||
List<Attachment> attachments,
|
||||
List<User> mentionedUsers,
|
||||
Map<String, int> reactionCounts,
|
||||
Map<String, int> reactionScores,
|
||||
List<Reaction> latestReactions,
|
||||
List<Reaction> ownReactions,
|
||||
String parentId,
|
||||
Message quotedMessage,
|
||||
String quotedMessageId,
|
||||
int replyCount,
|
||||
List<User> threadParticipants,
|
||||
bool showInChannel,
|
||||
bool shadowed,
|
||||
bool silent,
|
||||
String command,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime deletedAt,
|
||||
User user,
|
||||
bool pinned,
|
||||
DateTime pinnedAt,
|
||||
Object pinExpires = _pinExpires,
|
||||
User pinnedBy,
|
||||
Map<String, dynamic> extraData,
|
||||
MessageSendingStatus status,
|
||||
bool skipPush,
|
||||
String? id,
|
||||
String? text,
|
||||
String? type,
|
||||
List<Attachment>? attachments,
|
||||
List<User>? mentionedUsers,
|
||||
Map<String, int>? reactionCounts,
|
||||
Map<String, int>? reactionScores,
|
||||
List<Reaction>? latestReactions,
|
||||
List<Reaction>? ownReactions,
|
||||
String? parentId,
|
||||
Message? quotedMessage,
|
||||
String? quotedMessageId,
|
||||
int? replyCount,
|
||||
List<User>? threadParticipants,
|
||||
bool? showInChannel,
|
||||
bool? shadowed,
|
||||
bool? silent,
|
||||
String? command,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? deletedAt,
|
||||
User? user,
|
||||
bool? pinned,
|
||||
DateTime? pinnedAt,
|
||||
Object? pinExpires = _pinExpires,
|
||||
User? pinnedBy,
|
||||
Map<String, dynamic>? extraData,
|
||||
MessageSendingStatus? status,
|
||||
bool? skipPush,
|
||||
}) {
|
||||
assert(() {
|
||||
if (pinExpires is! DateTime &&
|
||||
@@ -306,49 +329,47 @@ class Message extends Equatable {
|
||||
pinned: pinned ?? this.pinned,
|
||||
pinnedAt: pinnedAt ?? this.pinnedAt,
|
||||
pinnedBy: pinnedBy ?? this.pinnedBy,
|
||||
pinExpires: pinExpires == _pinExpires ? this.pinExpires : pinExpires,
|
||||
pinExpires:
|
||||
pinExpires == _pinExpires ? this.pinExpires : pinExpires as DateTime?,
|
||||
skipPush: skipPush ?? this.skipPush,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns a new [Message] that is a combination of this message and the
|
||||
/// given [other] message.
|
||||
Message merge(Message other) {
|
||||
if (other == null) return this;
|
||||
return copyWith(
|
||||
id: other.id,
|
||||
text: other.text,
|
||||
type: other.type,
|
||||
attachments: other.attachments,
|
||||
mentionedUsers: other.mentionedUsers,
|
||||
reactionCounts: other.reactionCounts,
|
||||
reactionScores: other.reactionScores,
|
||||
latestReactions: other.latestReactions,
|
||||
ownReactions: other.ownReactions,
|
||||
parentId: other.parentId,
|
||||
quotedMessage: other.quotedMessage,
|
||||
quotedMessageId: other.quotedMessageId,
|
||||
replyCount: other.replyCount,
|
||||
threadParticipants: other.threadParticipants,
|
||||
showInChannel: other.showInChannel,
|
||||
command: other.command,
|
||||
createdAt: other.createdAt,
|
||||
silent: other.silent,
|
||||
extraData: other.extraData,
|
||||
user: other.user,
|
||||
shadowed: other.shadowed,
|
||||
updatedAt: other.updatedAt,
|
||||
deletedAt: other.deletedAt,
|
||||
status: other.status,
|
||||
pinned: other.pinned,
|
||||
pinnedAt: other.pinnedAt,
|
||||
pinExpires: other.pinExpires,
|
||||
pinnedBy: other.pinnedBy,
|
||||
);
|
||||
}
|
||||
Message merge(Message other) => copyWith(
|
||||
id: other.id,
|
||||
text: other.text,
|
||||
type: other.type,
|
||||
attachments: other.attachments,
|
||||
mentionedUsers: other.mentionedUsers,
|
||||
reactionCounts: other.reactionCounts,
|
||||
reactionScores: other.reactionScores,
|
||||
latestReactions: other.latestReactions,
|
||||
ownReactions: other.ownReactions,
|
||||
parentId: other.parentId,
|
||||
quotedMessage: other.quotedMessage,
|
||||
quotedMessageId: other.quotedMessageId,
|
||||
replyCount: other.replyCount,
|
||||
threadParticipants: other.threadParticipants,
|
||||
showInChannel: other.showInChannel,
|
||||
command: other.command,
|
||||
createdAt: other.createdAt,
|
||||
silent: other.silent,
|
||||
extraData: other.extraData,
|
||||
user: other.user,
|
||||
shadowed: other.shadowed,
|
||||
updatedAt: other.updatedAt,
|
||||
deletedAt: other.deletedAt,
|
||||
status: other.status,
|
||||
pinned: other.pinned,
|
||||
pinnedAt: other.pinnedAt,
|
||||
pinExpires: other.pinExpires,
|
||||
pinnedBy: other.pinnedBy,
|
||||
);
|
||||
|
||||
@override
|
||||
List<Object> get props => [
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
text,
|
||||
type,
|
||||
@@ -386,7 +407,7 @@ class Message extends Equatable {
|
||||
@JsonSerializable()
|
||||
class TranslatedMessage extends Message {
|
||||
/// Constructor used for json serialization
|
||||
TranslatedMessage(this.i18n);
|
||||
TranslatedMessage(this.i18n) : super();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory TranslatedMessage.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -395,7 +416,7 @@ class TranslatedMessage extends Message {
|
||||
);
|
||||
|
||||
/// A Map of
|
||||
final Map<String, String> i18n;
|
||||
final Map<String, String>? i18n;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -408,6 +429,5 @@ class TranslatedMessage extends Message {
|
||||
@override
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$TranslatedMessageToJson(this),
|
||||
topLevelFields,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,64 +6,44 @@ part of 'message.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Message _$MessageFromJson(Map json) {
|
||||
Message _$MessageFromJson(Map<String, dynamic> json) {
|
||||
return Message(
|
||||
id: json['id'] as String,
|
||||
text: json['text'] as String,
|
||||
type: json['type'] as String,
|
||||
attachments: (json['attachments'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Attachment.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
mentionedUsers: (json['mentioned_users'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: User.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
silent: json['silent'] as bool,
|
||||
shadowed: json['shadowed'] as bool,
|
||||
reactionCounts: (json['reaction_counts'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e as int),
|
||||
id: json['id'] as String?,
|
||||
text: json['text'] as String?,
|
||||
type: json['type'] as String? ?? 'regular',
|
||||
attachments: (json['attachments'] as List<dynamic>?)
|
||||
?.map((e) => Attachment.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
mentionedUsers: (json['mentioned_users'] as List<dynamic>?)
|
||||
?.map((e) => User.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
silent: json['silent'] as bool? ?? false,
|
||||
shadowed: json['shadowed'] as bool? ?? false,
|
||||
reactionCounts: (json['reaction_counts'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as int),
|
||||
),
|
||||
reactionScores: (json['reaction_scores'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e as int),
|
||||
reactionScores: (json['reaction_scores'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as int),
|
||||
),
|
||||
latestReactions: (json['latest_reactions'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Reaction.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
ownReactions: (json['own_reactions'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Reaction.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
parentId: json['parent_id'] as String,
|
||||
latestReactions: (json['latest_reactions'] as List<dynamic>?)
|
||||
?.map((e) => Reaction.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
ownReactions: (json['own_reactions'] as List<dynamic>?)
|
||||
?.map((e) => Reaction.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
parentId: json['parent_id'] as String?,
|
||||
quotedMessage: json['quoted_message'] == null
|
||||
? null
|
||||
: Message.fromJson((json['quoted_message'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
quotedMessageId: json['quoted_message_id'] as String,
|
||||
replyCount: json['reply_count'] as int,
|
||||
threadParticipants: (json['thread_participants'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: User.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
showInChannel: json['show_in_channel'] as bool,
|
||||
command: json['command'] as String,
|
||||
: Message.fromJson(json['quoted_message'] as Map<String, dynamic>),
|
||||
quotedMessageId: json['quoted_message_id'] as String?,
|
||||
replyCount: json['reply_count'] as int?,
|
||||
threadParticipants: (json['thread_participants'] as List<dynamic>?)
|
||||
?.map((e) => User.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
showInChannel: json['show_in_channel'] as bool?,
|
||||
command: json['command'] as String?,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
@@ -72,10 +52,8 @@ Message _$MessageFromJson(Map json) {
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
pinned: json['pinned'] as bool,
|
||||
: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
pinned: json['pinned'] as bool? ?? false,
|
||||
pinnedAt: json['pinned_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['pinned_at'] as String),
|
||||
@@ -84,16 +62,12 @@ Message _$MessageFromJson(Map json) {
|
||||
: DateTime.parse(json['pin_expires'] as String),
|
||||
pinnedBy: json['pinned_by'] == null
|
||||
? null
|
||||
: User.fromJson((json['pinned_by'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
: User.fromJson(json['pinned_by'] as Map<String, dynamic>),
|
||||
extraData: json['extra_data'] as Map<String, dynamic>? ?? {},
|
||||
deletedAt: json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
skipPush: json['skip_push'] as bool,
|
||||
skipPush: json['skip_push'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,8 +84,7 @@ Map<String, dynamic> _$MessageToJson(Message instance) {
|
||||
}
|
||||
|
||||
writeNotNull('type', readonly(instance.type));
|
||||
writeNotNull(
|
||||
'attachments', instance.attachments?.map((e) => e?.toJson())?.toList());
|
||||
val['attachments'] = instance.attachments.map((e) => e.toJson()).toList();
|
||||
val['mentioned_users'] = Serialization.userIds(instance.mentionedUsers);
|
||||
writeNotNull('reaction_counts', readonly(instance.reactionCounts));
|
||||
writeNotNull('reaction_scores', readonly(instance.reactionScores));
|
||||
@@ -134,15 +107,15 @@ Map<String, dynamic> _$MessageToJson(Message instance) {
|
||||
val['pinned_at'] = readonly(instance.pinnedAt);
|
||||
val['pin_expires'] = instance.pinExpires?.toIso8601String();
|
||||
val['pinned_by'] = readonly(instance.pinnedBy);
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
val['extra_data'] = instance.extraData;
|
||||
writeNotNull('deleted_at', readonly(instance.deletedAt));
|
||||
return val;
|
||||
}
|
||||
|
||||
TranslatedMessage _$TranslatedMessageFromJson(Map json) {
|
||||
TranslatedMessage _$TranslatedMessageFromJson(Map<String, dynamic> json) {
|
||||
return TranslatedMessage(
|
||||
(json['i18n'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e as String),
|
||||
(json['i18n'] as Map<String, dynamic>?)?.map(
|
||||
(k, e) => MapEntry(k, e as String),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,12 @@ part 'mute.g.dart';
|
||||
@JsonSerializable()
|
||||
class Mute {
|
||||
/// Constructor used for json serialization
|
||||
Mute({this.user, this.channel, this.createdAt, this.updatedAt});
|
||||
Mute({
|
||||
required this.user,
|
||||
required this.channel,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Mute.fromJson(Map<String, dynamic> json) => _$MuteFromJson(json);
|
||||
|
||||
@@ -6,24 +6,12 @@ part of 'mute.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Mute _$MuteFromJson(Map json) {
|
||||
Mute _$MuteFromJson(Map<String, dynamic> json) {
|
||||
return Mute(
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
channel: json['channel'] == null
|
||||
? null
|
||||
: ChannelModel.fromJson((json['channel'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: json['updated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
user: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
channel: ChannelModel.fromJson(json['channel'] as Map<String, dynamic>),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,19 +12,19 @@ part 'own_user.g.dart';
|
||||
class OwnUser extends User {
|
||||
/// Constructor used for json serialization
|
||||
OwnUser({
|
||||
this.devices,
|
||||
this.mutes,
|
||||
this.totalUnreadCount,
|
||||
this.devices = const [],
|
||||
this.mutes = const [],
|
||||
this.totalUnreadCount = 0,
|
||||
this.unreadChannels,
|
||||
this.channelMutes,
|
||||
String id,
|
||||
String role,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime lastActive,
|
||||
bool online,
|
||||
Map<String, dynamic> extraData,
|
||||
bool banned,
|
||||
this.channelMutes = const [],
|
||||
String id = '',
|
||||
String role = '',
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? lastActive,
|
||||
bool online = false,
|
||||
Map<String, dynamic> extraData = const {},
|
||||
bool banned = false,
|
||||
}) : super(
|
||||
id: id,
|
||||
role: role,
|
||||
@@ -41,24 +41,34 @@ class OwnUser extends User {
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields));
|
||||
|
||||
/// List of user devices
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: <Device>[])
|
||||
final List<Device> devices;
|
||||
|
||||
/// List of users muted by the user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: <Mute>[])
|
||||
final List<Mute> mutes;
|
||||
|
||||
/// List of users muted by the user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: <Mute>[])
|
||||
final List<Mute> channelMutes;
|
||||
|
||||
/// Total unread messages by the user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false, toJson: Serialization.readOnly, defaultValue: 0)
|
||||
final int totalUnreadCount;
|
||||
|
||||
/// Total unread channels by the user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final int unreadChannels;
|
||||
final int? unreadChannels;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -74,5 +84,6 @@ class OwnUser extends User {
|
||||
/// Serialize to json
|
||||
@override
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$OwnUserToJson(this), topLevelFields);
|
||||
_$OwnUserToJson(this),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,33 +6,24 @@ part of 'own_user.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
OwnUser _$OwnUserFromJson(Map json) {
|
||||
OwnUser _$OwnUserFromJson(Map<String, dynamic> json) {
|
||||
return OwnUser(
|
||||
devices: (json['devices'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Device.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
mutes: (json['mutes'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Mute.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
totalUnreadCount: json['total_unread_count'] as int,
|
||||
unreadChannels: json['unread_channels'] as int,
|
||||
channelMutes: (json['channel_mutes'] as List)
|
||||
?.map((e) => e == null
|
||||
? null
|
||||
: Mute.fromJson((e as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)))
|
||||
?.toList(),
|
||||
devices: (json['devices'] as List<dynamic>?)
|
||||
?.map((e) => Device.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
mutes: (json['mutes'] as List<dynamic>?)
|
||||
?.map((e) => Mute.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
totalUnreadCount: json['total_unread_count'] as int? ?? 0,
|
||||
unreadChannels: json['unread_channels'] as int?,
|
||||
channelMutes: (json['channel_mutes'] as List<dynamic>?)
|
||||
?.map((e) => Mute.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
id: json['id'] as String,
|
||||
role: json['role'] as String,
|
||||
role: json['role'] as String? ?? '',
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
@@ -42,11 +33,9 @@ OwnUser _$OwnUserFromJson(Map json) {
|
||||
lastActive: json['last_active'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_active'] as String),
|
||||
online: json['online'] as bool,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
banned: json['banned'] as bool,
|
||||
online: json['online'] as bool? ?? false,
|
||||
extraData: json['extra_data'] as Map<String, dynamic>,
|
||||
banned: json['banned'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,7 +56,7 @@ Map<String, dynamic> _$OwnUserToJson(OwnUser instance) {
|
||||
writeNotNull('last_active', readonly(instance.lastActive));
|
||||
writeNotNull('online', readonly(instance.online));
|
||||
writeNotNull('banned', readonly(instance.banned));
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
val['extra_data'] = instance.extraData;
|
||||
writeNotNull('devices', readonly(instance.devices));
|
||||
writeNotNull('mutes', readonly(instance.mutes));
|
||||
writeNotNull('channel_mutes', readonly(instance.channelMutes));
|
||||
|
||||
@@ -10,20 +10,24 @@ class Reaction {
|
||||
/// Constructor used for json serialization
|
||||
Reaction({
|
||||
this.messageId,
|
||||
this.createdAt,
|
||||
this.type,
|
||||
DateTime? createdAt,
|
||||
required this.type,
|
||||
this.user,
|
||||
String userId,
|
||||
this.score,
|
||||
String? userId,
|
||||
this.score = 0,
|
||||
this.extraData,
|
||||
}) : userId = userId ?? user?.id;
|
||||
}) : userId = userId ?? user?.id,
|
||||
createdAt = createdAt ?? DateTime.now();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Reaction.fromJson(Map<String, dynamic> json) => _$ReactionFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields));
|
||||
factory Reaction.fromJson(Map<String, dynamic> json) =>
|
||||
_$ReactionFromJson(Serialization.moveToExtraDataFromRoot(
|
||||
json,
|
||||
topLevelFields,
|
||||
));
|
||||
|
||||
/// The messageId to which the reaction belongs
|
||||
final String messageId;
|
||||
final String? messageId;
|
||||
|
||||
/// The type of the reaction
|
||||
final String type;
|
||||
@@ -34,18 +38,19 @@ class Reaction {
|
||||
|
||||
/// The user that sent the reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// The score of the reaction (ie. number of reactions sent)
|
||||
@JsonKey(defaultValue: 0)
|
||||
final int score;
|
||||
|
||||
/// The userId that sent the reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final String userId;
|
||||
final String? userId;
|
||||
|
||||
/// Reaction custom extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
final Map<String, dynamic>? extraData;
|
||||
|
||||
/// Map of custom user extraData
|
||||
static const topLevelFields = [
|
||||
@@ -59,17 +64,18 @@ class Reaction {
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$ReactionToJson(this), topLevelFields);
|
||||
_$ReactionToJson(this),
|
||||
);
|
||||
|
||||
/// Creates a copy of [Reaction] with specified attributes overridden.
|
||||
Reaction copyWith({
|
||||
String messageId,
|
||||
DateTime createdAt,
|
||||
String type,
|
||||
User user,
|
||||
String userId,
|
||||
int score,
|
||||
Map<String, dynamic> extraData,
|
||||
String? messageId,
|
||||
DateTime? createdAt,
|
||||
String? type,
|
||||
User? user,
|
||||
String? userId,
|
||||
int? score,
|
||||
Map<String, dynamic>? extraData,
|
||||
}) =>
|
||||
Reaction(
|
||||
messageId: messageId ?? this.messageId,
|
||||
@@ -83,16 +89,13 @@ class Reaction {
|
||||
|
||||
/// Returns a new [Reaction] that is a combination of this reaction and the
|
||||
/// given [other] reaction.
|
||||
Reaction merge(Reaction other) {
|
||||
if (other == null) return this;
|
||||
return copyWith(
|
||||
messageId: other.messageId,
|
||||
createdAt: other.createdAt,
|
||||
type: other.type,
|
||||
user: other.user,
|
||||
userId: other.userId,
|
||||
score: other.score,
|
||||
extraData: other.extraData,
|
||||
);
|
||||
}
|
||||
Reaction merge(Reaction other) => copyWith(
|
||||
messageId: other.messageId,
|
||||
createdAt: other.createdAt,
|
||||
type: other.type,
|
||||
user: other.user,
|
||||
userId: other.userId,
|
||||
score: other.score,
|
||||
extraData: other.extraData,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,23 +6,19 @@ part of 'reaction.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Reaction _$ReactionFromJson(Map json) {
|
||||
Reaction _$ReactionFromJson(Map<String, dynamic> json) {
|
||||
return Reaction(
|
||||
messageId: json['message_id'] as String,
|
||||
messageId: json['message_id'] as String?,
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
type: json['type'] as String,
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
userId: json['user_id'] as String,
|
||||
score: json['score'] as int,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
userId: json['user_id'] as String?,
|
||||
score: json['score'] as int? ?? 0,
|
||||
extraData: json['extra_data'] as Map<String, dynamic>?,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ part 'read.g.dart';
|
||||
class Read {
|
||||
/// Constructor used for json serialization
|
||||
Read({
|
||||
this.lastRead,
|
||||
this.user,
|
||||
this.unreadMessages,
|
||||
required this.lastRead,
|
||||
required this.user,
|
||||
this.unreadMessages = 0,
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
@@ -23,6 +23,7 @@ class Read {
|
||||
final User user;
|
||||
|
||||
/// Number of unread messages
|
||||
@JsonKey(defaultValue: 0)
|
||||
final int unreadMessages;
|
||||
|
||||
/// Serialize to json
|
||||
@@ -30,9 +31,9 @@ class Read {
|
||||
|
||||
/// Creates a copy of [Read] with specified attributes overridden.
|
||||
Read copyWith({
|
||||
DateTime lastRead,
|
||||
User user,
|
||||
int unreadMessages,
|
||||
DateTime? lastRead,
|
||||
User? user,
|
||||
int? unreadMessages,
|
||||
}) =>
|
||||
Read(
|
||||
lastRead: lastRead ?? this.lastRead,
|
||||
|
||||
@@ -6,22 +6,16 @@ part of 'read.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Read _$ReadFromJson(Map json) {
|
||||
Read _$ReadFromJson(Map<String, dynamic> json) {
|
||||
return Read(
|
||||
lastRead: json['last_read'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_read'] as String),
|
||||
user: json['user'] == null
|
||||
? null
|
||||
: User.fromJson((json['user'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
)),
|
||||
unreadMessages: json['unread_messages'] as int,
|
||||
lastRead: DateTime.parse(json['last_read'] as String),
|
||||
user: User.fromJson(json['user'] as Map<String, dynamic>),
|
||||
unreadMessages: json['unread_messages'] as int? ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$ReadToJson(Read instance) => <String, dynamic>{
|
||||
'last_read': instance.lastRead?.toIso8601String(),
|
||||
'user': instance.user?.toJson(),
|
||||
'last_read': instance.lastRead.toIso8601String(),
|
||||
'user': instance.user.toJson(),
|
||||
'unread_messages': instance.unreadMessages,
|
||||
};
|
||||
|
||||
@@ -10,16 +10,14 @@ class Serialization {
|
||||
static const Function readOnly = readonly;
|
||||
|
||||
/// List of users to list of userIds
|
||||
static List<String> userIds(List<User> users) =>
|
||||
users?.map((u) => u.id)?.toList();
|
||||
static List<String>? userIds(List<User>? users) =>
|
||||
users?.map((u) => u.id).toList();
|
||||
|
||||
/// Takes unknown json keys and puts them in the `extra_data` key
|
||||
static Map<String, dynamic> moveToExtraDataFromRoot(
|
||||
Map<String, dynamic> json,
|
||||
List<String> topLevelFields,
|
||||
) {
|
||||
if (json == null) return null;
|
||||
|
||||
final jsonClone = Map<String, dynamic>.from(json);
|
||||
|
||||
final extraDataMap = Map<String, dynamic>.from(json)
|
||||
@@ -38,7 +36,6 @@ class Serialization {
|
||||
/// the json map
|
||||
static Map<String, dynamic> moveFromExtraDataToRoot(
|
||||
Map<String, dynamic> json,
|
||||
List<String> topLevelFields,
|
||||
) {
|
||||
final jsonClone = Map<String, dynamic>.from(json);
|
||||
return jsonClone
|
||||
|
||||
@@ -8,16 +8,17 @@ part 'user.g.dart';
|
||||
class User {
|
||||
/// Constructor used for json serialization
|
||||
User({
|
||||
this.id,
|
||||
this.role,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.id = '',
|
||||
this.role = '',
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
this.lastActive,
|
||||
this.online,
|
||||
this.extraData,
|
||||
this.banned,
|
||||
this.teams,
|
||||
});
|
||||
this.online = false,
|
||||
this.extraData = const {},
|
||||
this.banned = false,
|
||||
this.teams = const [],
|
||||
}) : createdAt = createdAt ?? DateTime.now(),
|
||||
updatedAt = updatedAt ?? DateTime.now();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(
|
||||
@@ -26,14 +27,14 @@ class User {
|
||||
/// Use this named constructor to create a new user instance
|
||||
User.init(
|
||||
this.id, {
|
||||
this.online,
|
||||
this.extraData,
|
||||
}) : createdAt = null,
|
||||
updatedAt = null,
|
||||
lastActive = null,
|
||||
banned = null,
|
||||
teams = null,
|
||||
role = null;
|
||||
this.online = false,
|
||||
this.extraData = const {},
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
this.teams = const [],
|
||||
required this.role,
|
||||
}) : lastActive = null,
|
||||
banned = false;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -52,11 +53,15 @@ class User {
|
||||
final String id;
|
||||
|
||||
/// User role
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false, toJson: Serialization.readOnly, defaultValue: '')
|
||||
final String role;
|
||||
|
||||
/// User role
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false,
|
||||
toJson: Serialization.readOnly,
|
||||
defaultValue: <String>[])
|
||||
final List<String> teams;
|
||||
|
||||
/// Date of user creation
|
||||
@@ -69,14 +74,16 @@ class User {
|
||||
|
||||
/// Date of last user connection
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime lastActive;
|
||||
final DateTime? lastActive;
|
||||
|
||||
/// True if user is online
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false, toJson: Serialization.readOnly, defaultValue: false)
|
||||
final bool online;
|
||||
|
||||
/// True if user is banned from the chat
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
@JsonKey(
|
||||
includeIfNull: false, toJson: Serialization.readOnly, defaultValue: false)
|
||||
final bool banned;
|
||||
|
||||
/// Map of custom user extraData
|
||||
@@ -87,8 +94,8 @@ class User {
|
||||
int get hashCode => id.hashCode;
|
||||
|
||||
/// Shortcut for user name
|
||||
String get name =>
|
||||
(extraData?.containsKey('name') == true && extraData['name'] != '')
|
||||
String? get name =>
|
||||
(extraData.containsKey('name') == true && extraData['name'] != '')
|
||||
? extraData['name']
|
||||
: id;
|
||||
|
||||
@@ -98,20 +105,21 @@ class User {
|
||||
other is User && runtimeType == other.runtimeType && id == other.id;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() =>
|
||||
Serialization.moveFromExtraDataToRoot(_$UserToJson(this), topLevelFields);
|
||||
Map<String, dynamic> toJson() => Serialization.moveFromExtraDataToRoot(
|
||||
_$UserToJson(this),
|
||||
);
|
||||
|
||||
/// Creates a copy of [User] with specified attributes overridden.
|
||||
User copyWith({
|
||||
String id,
|
||||
String role,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime lastActive,
|
||||
bool online,
|
||||
Map<String, dynamic> extraData,
|
||||
bool banned,
|
||||
List<String> teams,
|
||||
String? id,
|
||||
String? role,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? lastActive,
|
||||
bool? online,
|
||||
Map<String, dynamic>? extraData,
|
||||
bool? banned,
|
||||
List<String>? teams,
|
||||
}) =>
|
||||
User(
|
||||
id: id ?? this.id,
|
||||
|
||||
@@ -6,10 +6,10 @@ part of 'user.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
User _$UserFromJson(Map json) {
|
||||
User _$UserFromJson(Map<String, dynamic> json) {
|
||||
return User(
|
||||
id: json['id'] as String,
|
||||
role: json['role'] as String,
|
||||
role: json['role'] as String? ?? '',
|
||||
createdAt: json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
@@ -19,12 +19,12 @@ User _$UserFromJson(Map json) {
|
||||
lastActive: json['last_active'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_active'] as String),
|
||||
online: json['online'] as bool,
|
||||
extraData: (json['extra_data'] as Map)?.map(
|
||||
(k, e) => MapEntry(k as String, e),
|
||||
),
|
||||
banned: json['banned'] as bool,
|
||||
teams: (json['teams'] as List)?.map((e) => e as String)?.toList(),
|
||||
online: json['online'] as bool? ?? false,
|
||||
extraData: json['extra_data'] as Map<String, dynamic>,
|
||||
banned: json['banned'] as bool? ?? false,
|
||||
teams:
|
||||
(json['teams'] as List<dynamic>?)?.map((e) => e as String).toList() ??
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,6 @@ Map<String, dynamic> _$UserToJson(User instance) {
|
||||
writeNotNull('last_active', readonly(instance.lastActive));
|
||||
writeNotNull('online', readonly(instance.online));
|
||||
writeNotNull('banned', readonly(instance.banned));
|
||||
writeNotNull('extra_data', instance.extraData);
|
||||
val['extra_data'] = instance.extraData;
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -6,26 +6,26 @@ repository: https://github.com/GetStream/stream-chat-flutter
|
||||
issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.0.0"
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
async: ^2.5.0
|
||||
collection: ^1.15.0
|
||||
dio: ">=4.0.0-prev3 <4.0.0"
|
||||
dio: ^4.0.0
|
||||
equatable: ^2.0.0
|
||||
freezed_annotation: ^0.14.0
|
||||
http_parser: ^4.0.0
|
||||
json_annotation: ^4.0.0
|
||||
logging: ^1.0.0
|
||||
json_annotation: ^4.0.1
|
||||
logging: ^1.0.1
|
||||
meta: ^1.3.0
|
||||
mime: ^1.0.0
|
||||
rxdart: ^0.26.0
|
||||
uuid: ^3.0.0
|
||||
uuid: ^3.0.4
|
||||
web_socket_channel: ^2.0.0
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^1.10.0
|
||||
freezed: ^0.14.0
|
||||
json_serializable: ^4.0.0
|
||||
mocktail: ^0.1.0
|
||||
test: ^1.16.0
|
||||
build_runner: ^1.12.2
|
||||
freezed: ^0.14.1+2
|
||||
json_serializable: ^4.1.0
|
||||
mocktail: ^0.1.1
|
||||
test: ^1.16.8
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:dio/native_imp.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
@@ -6,11 +8,10 @@ import 'package:stream_chat/src/client.dart';
|
||||
import 'package:stream_chat/src/event_type.dart';
|
||||
import 'package:stream_chat/src/models/event.dart';
|
||||
import 'package:stream_chat/src/models/message.dart';
|
||||
import 'package:stream_chat/src/models/reaction.dart';
|
||||
import 'package:stream_chat/src/models/own_user.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'package:stream_chat/src/models/reaction.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
class MockDio extends Mock implements DioForNative {}
|
||||
|
||||
@@ -37,6 +38,17 @@ void main() {
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
final message = Message(text: 'hey', id: 'test');
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState()),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
'/channels/messaging/testid/message',
|
||||
@@ -44,7 +56,7 @@ void main() {
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({'message': message}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
@@ -76,7 +88,7 @@ void main() {
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode(ChannelState()),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
@@ -226,6 +238,17 @@ void main() {
|
||||
);
|
||||
final channelClient = client.channel(channelType, id: channelId);
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState()),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
when(() => mockUploader.sendFile(file, channelId, channelType))
|
||||
.thenAnswer((_) async => SendFileResponse());
|
||||
|
||||
@@ -254,6 +277,17 @@ void main() {
|
||||
);
|
||||
final channelClient = client.channel(channelType, id: channelId);
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState()),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
when(() => mockUploader.sendImage(image, channelId, channelType))
|
||||
.thenAnswer((_) async => SendImageResponse());
|
||||
|
||||
@@ -277,6 +311,17 @@ void main() {
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
const url = 'url';
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState()),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
when(
|
||||
() => mockDio.delete<String>(
|
||||
'/channels/messaging/testid/file',
|
||||
@@ -310,6 +355,17 @@ void main() {
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
const url = 'url';
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState()),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
when(
|
||||
() => mockDio.delete<String>(
|
||||
'/channels/messaging/testid/image',
|
||||
@@ -356,6 +412,17 @@ void main() {
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
final message = Message(text: 'Hello', id: 'test');
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState()),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
'/messages/${message.id}',
|
||||
@@ -363,7 +430,7 @@ void main() {
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({'message': message}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
@@ -390,6 +457,17 @@ void main() {
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
final message = Message(text: 'Hello', id: 'test');
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState()),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
'/messages/${message.id}',
|
||||
@@ -397,7 +475,7 @@ void main() {
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({'message': message}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
@@ -564,14 +642,32 @@ void main() {
|
||||
'api-key',
|
||||
httpClient: mockDio,
|
||||
tokenProvider: (_) async => '',
|
||||
)..state.user = OwnUser(id: 'test-id');
|
||||
);
|
||||
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
final user = OwnUser(id: 'test-id');
|
||||
|
||||
client.state.user = user;
|
||||
|
||||
final message = Message(id: 'messageid');
|
||||
const reactionType = 'test';
|
||||
final reaction = Reaction(type: reactionType);
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
);
|
||||
await channelClient.watch();
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
'/messages/messageid/reaction',
|
||||
'/messages/${message.id}/reaction',
|
||||
data: {
|
||||
'reaction': {
|
||||
'type': reactionType,
|
||||
@@ -581,20 +677,17 @@ void main() {
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({
|
||||
'message': message,
|
||||
'reaction': reaction,
|
||||
}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
);
|
||||
|
||||
await channelClient.sendReaction(
|
||||
Message(
|
||||
id: 'messageid',
|
||||
reactionCounts: const <String, int>{},
|
||||
reactionScores: const <String, int>{},
|
||||
latestReactions: const <Reaction>[],
|
||||
ownReactions: const <Reaction>[],
|
||||
),
|
||||
message,
|
||||
reactionType,
|
||||
);
|
||||
|
||||
@@ -617,7 +710,9 @@ void main() {
|
||||
'api-key',
|
||||
httpClient: mockDio,
|
||||
tokenProvider: (_) async => '',
|
||||
)..state.user = OwnUser(id: 'test-id');
|
||||
);
|
||||
|
||||
client.state.user = OwnUser(id: 'test-id');
|
||||
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
|
||||
@@ -634,12 +729,14 @@ void main() {
|
||||
await channelClient.deleteReaction(
|
||||
Message(
|
||||
id: 'messageid',
|
||||
reactionCounts: const <String, int>{},
|
||||
reactionScores: const <String, int>{},
|
||||
latestReactions: const <Reaction>[],
|
||||
ownReactions: const <Reaction>[],
|
||||
),
|
||||
Reaction(type: 'test'),
|
||||
Reaction(
|
||||
type: 'test',
|
||||
createdAt: DateTime.now(),
|
||||
user: User(
|
||||
id: client.state.user?.id ?? '',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
verify(() =>
|
||||
@@ -694,26 +791,44 @@ void main() {
|
||||
tokenProvider: (_) async => '',
|
||||
);
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
final members = ['vishal'];
|
||||
final channelModel = ChannelModel(cid: 'messaging:testid');
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState(channel: channelModel)),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
final members = [Member(userId: 'vishal')];
|
||||
final memberIds = members.map((e) => e.userId!).toList();
|
||||
final message = Message(text: 'test');
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
'/channels/messaging/testid',
|
||||
data: {'add_members': members, 'message': message.toJson()},
|
||||
data: {'add_members': memberIds, 'message': message.toJson()},
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({
|
||||
'members': members,
|
||||
'message': message,
|
||||
'channel': channelModel,
|
||||
}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
);
|
||||
|
||||
await channelClient.addMembers(members, message);
|
||||
await channelClient.addMembers(memberIds, message);
|
||||
|
||||
verify(() => mockDio.post<String>('/channels/messaging/testid',
|
||||
data: {'add_members': members, 'message': message.toJson()}))
|
||||
data: {'add_members': memberIds, 'message': message.toJson()}))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
@@ -729,6 +844,19 @@ void main() {
|
||||
tokenProvider: (_) async => '',
|
||||
);
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
final channelModel = ChannelModel(cid: 'messaging:testid');
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState(channel: channelModel)),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
final message = Message(text: 'test');
|
||||
|
||||
when(
|
||||
@@ -738,7 +866,10 @@ void main() {
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({
|
||||
'message': message,
|
||||
'channel': channelModel,
|
||||
}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
@@ -1069,8 +1200,8 @@ void main() {
|
||||
|
||||
verify(() => mockDio.post<String>('/channels/messaging/query',
|
||||
data: options)).called(1);
|
||||
expect(channelClient.id, response.channel.id);
|
||||
expect(channelClient.cid, response.channel.cid);
|
||||
expect(channelClient.id, response.channel?.id);
|
||||
expect(channelClient.cid, response.channel?.cid);
|
||||
});
|
||||
|
||||
test('with id', () async {
|
||||
@@ -1706,8 +1837,8 @@ void main() {
|
||||
|
||||
verify(() => mockDio.post<String>('/channels/messaging/query',
|
||||
data: options)).called(1);
|
||||
expect(channelClient.id, response.channel.id);
|
||||
expect(channelClient.cid, response.channel.cid);
|
||||
expect(channelClient.id, response.channel?.id);
|
||||
expect(channelClient.cid, response.channel?.cid);
|
||||
});
|
||||
|
||||
test('watch', () async {
|
||||
@@ -2027,8 +2158,8 @@ void main() {
|
||||
|
||||
verify(() => mockDio.post<String>('/channels/messaging/query',
|
||||
data: options)).called(1);
|
||||
expect(channelClient.id, response.channel.id);
|
||||
expect(channelClient.cid, response.channel.cid);
|
||||
expect(channelClient.id, response.channel?.id);
|
||||
expect(channelClient.cid, response.channel?.cid);
|
||||
});
|
||||
|
||||
test('stopWatching', () async {
|
||||
@@ -2077,6 +2208,19 @@ void main() {
|
||||
tokenProvider: (_) async => '',
|
||||
);
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
final channelModel = ChannelModel(cid: 'messaging:testid');
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState(channel: channelModel)),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
final message = Message(text: 'test');
|
||||
|
||||
when(
|
||||
@@ -2089,7 +2233,10 @@ void main() {
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({
|
||||
'channel': channelModel,
|
||||
'message': message,
|
||||
}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
@@ -2176,6 +2323,19 @@ void main() {
|
||||
tokenProvider: (_) async => '',
|
||||
);
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
final channelModel = ChannelModel(cid: 'messaging:testid');
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState(channel: channelModel)),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
final message = Message(text: 'test');
|
||||
|
||||
when(
|
||||
@@ -2185,7 +2345,10 @@ void main() {
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({
|
||||
'message': message,
|
||||
'channel': channelModel,
|
||||
}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
@@ -2210,26 +2373,45 @@ void main() {
|
||||
tokenProvider: (_) async => '',
|
||||
);
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
final members = ['vishal'];
|
||||
final channelModel = ChannelModel(cid: 'messaging:testid');
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState(channel: channelModel)),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
final members = [Member(userId: 'vishal')];
|
||||
final memberIds = members.map((e) => e.userId!).toList();
|
||||
final message = Message(text: 'test');
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
'/channels/messaging/testid',
|
||||
data: {'invites': members, 'message': message.toJson()},
|
||||
data: {'invites': memberIds, 'message': message.toJson()},
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({
|
||||
'members': members,
|
||||
'message': message,
|
||||
'channel': channelModel,
|
||||
}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
);
|
||||
|
||||
await channelClient.inviteMembers(members, message);
|
||||
await channelClient.inviteMembers(memberIds, message);
|
||||
|
||||
verify(() => mockDio.post<String>('/channels/messaging/testid',
|
||||
data: {'invites': members, 'message': message.toJson()})).called(1);
|
||||
data: {'invites': memberIds, 'message': message.toJson()}))
|
||||
.called(1);
|
||||
});
|
||||
|
||||
test('removeMembers', () async {
|
||||
@@ -2244,27 +2426,46 @@ void main() {
|
||||
tokenProvider: (_) async => '',
|
||||
);
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
final members = ['vishal'];
|
||||
final channelModel = ChannelModel(cid: 'messaging:testid');
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
data: any(named: 'data'),
|
||||
)).thenAnswer((_) async => Response(
|
||||
data: jsonEncode(ChannelState(channel: channelModel)),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
|
||||
await channelClient.watch();
|
||||
|
||||
final members = [Member(userId: 'vishal')];
|
||||
final memberIds = members.map((e) => e.userId!).toList();
|
||||
final message = Message(text: 'test');
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
'/channels/messaging/testid',
|
||||
data: {'remove_members': members, 'message': message.toJson()},
|
||||
data: {'remove_members': memberIds, 'message': message.toJson()},
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({
|
||||
'members': members,
|
||||
'message': message,
|
||||
'channel': channelModel,
|
||||
}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
);
|
||||
|
||||
await channelClient.removeMembers(members, message);
|
||||
await channelClient.removeMembers(memberIds, message);
|
||||
|
||||
verify(() => mockDio.post<String>('/channels/messaging/testid',
|
||||
data: {'remove_members': members, 'message': message.toJson()}))
|
||||
.called(1);
|
||||
verify(() => mockDio.post<String>('/channels/messaging/testid', data: {
|
||||
'remove_members': memberIds,
|
||||
'message': message.toJson()
|
||||
})).called(1);
|
||||
});
|
||||
|
||||
test('hide', () async {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/api/requests', () {
|
||||
@@ -12,7 +12,8 @@ void main() {
|
||||
test('PaginationParams', () {
|
||||
const option = PaginationParams();
|
||||
final j = option.toJson();
|
||||
expect(j, {'limit': 10, 'offset': 0});
|
||||
expect(j, containsPair('limit', 10));
|
||||
expect(j, containsPair('offset', 0));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ import 'package:stream_chat/stream_chat.dart';
|
||||
void main() {
|
||||
group('src/api/responses', () {
|
||||
test('QueryChannelsResponse', () {
|
||||
const jsonExample = r'''{
|
||||
const jsonExample = r'''
|
||||
{
|
||||
"channels": [
|
||||
{
|
||||
"channel": {
|
||||
@@ -3432,7 +3433,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('SendReactionResponse', () {
|
||||
const jsonExample = r'''{"message": {
|
||||
const jsonExample = r'''
|
||||
{"message": {
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3481,7 +3483,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('UpdateUsersResponse', () {
|
||||
const jsonExample = '''{"users": {"bbb19d9a-ee50-45bc-84e5-0584e79d0c9e":{
|
||||
const jsonExample = '''
|
||||
{"users": {"bbb19d9a-ee50-45bc-84e5-0584e79d0c9e":{
|
||||
"id": "bbb19d9a-ee50-45bc-84e5-0584e79d0c9e",
|
||||
"role": "user",
|
||||
"created_at": "2020-01-28T22:17:30.826259Z",
|
||||
@@ -3505,7 +3508,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GetMessagesByIdResponse', () {
|
||||
const jsonExample = r'''{"messages":[{
|
||||
const jsonExample = r'''
|
||||
{"messages":[{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3536,7 +3540,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('SendActionResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3566,7 +3571,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('UpdateMessageResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3596,7 +3602,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('SendMessageResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3626,7 +3633,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GetMessageResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3656,7 +3664,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('UpdateChannelResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3769,7 +3778,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('InviteMembersResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3882,7 +3892,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('RemoveMembersResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -3995,7 +4006,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('AddMembersResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -4108,7 +4120,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('AcceptInviteResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
@@ -4221,7 +4234,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('RejectInviteResponse', () {
|
||||
const jsonExample = r'''{"message":{
|
||||
const jsonExample = r'''
|
||||
{"message":{
|
||||
"id": "c6076f11-7768-4a04-bdf2-c43dddd6d666",
|
||||
"text": "What we don't know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.",
|
||||
"html": "\u003cp\u003eWhat we don’t know for sure is whether or not a step-daughter of the bear is assumed to be a farci hourglass.\u003c/p\u003e\n",
|
||||
|
||||
@@ -12,12 +12,10 @@ import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
|
||||
class Functions {
|
||||
WebSocketChannel connectFunc(
|
||||
String url, {
|
||||
Iterable<String> protocols,
|
||||
Map<String, dynamic> headers,
|
||||
Duration pingInterval,
|
||||
String? url, {
|
||||
Iterable<String>? protocols,
|
||||
}) =>
|
||||
null;
|
||||
WebSocketChannel.connect(Uri());
|
||||
|
||||
void handleFunc(Event event) {}
|
||||
}
|
||||
@@ -37,7 +35,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('should connect with correct parameters', () async {
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
@@ -75,7 +73,7 @@ void main() {
|
||||
|
||||
test('should connect with correct parameters and handle events', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
@@ -111,7 +109,7 @@ void main() {
|
||||
|
||||
test('should close correctly the controller', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
@@ -126,8 +124,10 @@ void main() {
|
||||
const computedUrl =
|
||||
'wss://baseurl/connect?test=true&json=%7B%22payload%22%3A%22test%22%2C%22user_details%22%3A%7B%22id%22%3A%22testid%22%7D%7D';
|
||||
|
||||
final mockWSSink = MockWSSink();
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => mockWSSink);
|
||||
when(() => mockWSSink.close(any(), any())).thenAnswer((_) async => null);
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
@@ -148,7 +148,7 @@ void main() {
|
||||
test('should close correctly the controller while connecting', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
@@ -167,8 +167,10 @@ void main() {
|
||||
const computedUrl =
|
||||
'wss://baseurl/connect?test=true&json=%7B%22payload%22%3A%22test%22%2C%22user_details%22%3A%7B%22id%22%3A%22testid%22%7D%7D';
|
||||
|
||||
final mockWSSink = MockWSSink();
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => mockWSSink);
|
||||
when(() => mockWSSink.close(any(), any())).thenAnswer((_) async => null);
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
|
||||
ws.connect();
|
||||
@@ -183,7 +185,7 @@ void main() {
|
||||
|
||||
test('should run correctly health check', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
@@ -201,7 +203,8 @@ void main() {
|
||||
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
when(() => mockWSChannel.sink).thenReturn(mockWSSink);
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => mockWSSink);
|
||||
when(() => mockWSSink.close(any(), any())).thenAnswer((_) async => null);
|
||||
|
||||
final timer = Timer.periodic(
|
||||
const Duration(milliseconds: 1000),
|
||||
@@ -227,7 +230,7 @@ void main() {
|
||||
|
||||
test('should run correctly reconnection check', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
Logger.root.level = Level.ALL;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
@@ -247,7 +250,8 @@ void main() {
|
||||
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
when(() => mockWSChannel.sink).thenReturn(mockWSSink);
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => mockWSSink);
|
||||
when(() => mockWSSink.close(any(), any())).thenAnswer((_) async => null);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
streamController.sink.add('{}');
|
||||
@@ -272,7 +276,7 @@ void main() {
|
||||
|
||||
test('should close correctly the controller', () async {
|
||||
final handleFunc = MockFunctions().handleFunc;
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
@@ -290,7 +294,8 @@ void main() {
|
||||
|
||||
when(() => connectFunc(computedUrl)).thenAnswer((_) => mockWSChannel);
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
when(() => mockWSChannel.sink).thenReturn(mockWSSink);
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => mockWSSink);
|
||||
when(() => mockWSSink.close(any(), any())).thenAnswer((_) async => null);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
streamController.sink.add('{}');
|
||||
@@ -309,7 +314,7 @@ void main() {
|
||||
});
|
||||
|
||||
test('should throw an error', () async {
|
||||
final ConnectWebSocket connectFunc = MockFunctions().connectFunc;
|
||||
final connectFunc = MockFunctions().connectFunc;
|
||||
final ws = WebSocket(
|
||||
baseUrl: 'baseurl',
|
||||
user: User(id: 'testid'),
|
||||
|
||||
@@ -9,9 +9,9 @@ import 'package:mocktail/mocktail.dart';
|
||||
import 'package:stream_chat/src/api/requests.dart';
|
||||
import 'package:stream_chat/src/client.dart';
|
||||
import 'package:stream_chat/src/exceptions.dart';
|
||||
import 'package:stream_chat/src/models/channel_model.dart';
|
||||
import 'package:stream_chat/src/models/message.dart';
|
||||
import 'package:stream_chat/src/models/user.dart';
|
||||
import 'package:stream_chat/src/models/channel_model.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
class MockDio extends Mock implements DioForNative {}
|
||||
@@ -21,7 +21,7 @@ class FakeRequestOptions extends Fake implements RequestOptions {}
|
||||
class MockHttpClientAdapter extends Mock implements HttpClientAdapter {}
|
||||
|
||||
class Functions {
|
||||
Future<String> tokenProvider(String userId) => null;
|
||||
Future<String> tokenProvider(String userId) async => '';
|
||||
}
|
||||
|
||||
class MockFunctions extends Mock implements Functions {}
|
||||
@@ -155,7 +155,9 @@ void main() {
|
||||
'sort': sortOptions,
|
||||
}
|
||||
..addAll(options)
|
||||
..addAll(paginationParams.toJson())),
|
||||
..addAll(paginationParams
|
||||
.toJson()
|
||||
.map((key, value) => MapEntry(key, value as Object)))),
|
||||
};
|
||||
|
||||
when(
|
||||
@@ -735,7 +737,9 @@ void main() {
|
||||
when(() => mockDio.interceptors).thenReturn(Interceptors());
|
||||
|
||||
final client = StreamChatClient('api-key', httpClient: mockDio);
|
||||
final message = Message(id: 'test', updatedAt: DateTime.now());
|
||||
final message = Message(
|
||||
id: 'test',
|
||||
);
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
@@ -744,7 +748,7 @@ void main() {
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({'message': message}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
@@ -789,7 +793,7 @@ void main() {
|
||||
|
||||
when(() => mockDio.get<String>('/messages/$messageId')).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({'message': Message(id: messageId)}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
@@ -1111,7 +1115,7 @@ void main() {
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({'message': message}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
@@ -1133,7 +1137,7 @@ void main() {
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({'message': message}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
@@ -1173,7 +1177,7 @@ void main() {
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) async => Response(
|
||||
data: '{}',
|
||||
data: jsonEncode({'channel': ChannelModel(cid: 'messaging:test')}),
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
),
|
||||
|
||||
@@ -5,7 +5,8 @@ import 'package:stream_chat/src/models/action.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/action', () {
|
||||
const jsonExample = '''{
|
||||
const jsonExample = '''
|
||||
{
|
||||
"name": "name",
|
||||
"style": "style",
|
||||
"text": "text",
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import 'dart:convert';
|
||||
import 'package:stream_chat/src/models/attachment.dart';
|
||||
import 'package:stream_chat/src/models/action.dart';
|
||||
|
||||
import 'package:stream_chat/src/models/action.dart';
|
||||
import 'package:stream_chat/src/models/attachment.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/attachment', () {
|
||||
const jsonExample = '''{
|
||||
const jsonExample = '''
|
||||
{
|
||||
"type": "giphy",
|
||||
"title": "awesome",
|
||||
"title_link": "https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti",
|
||||
@@ -66,7 +67,8 @@ void main() {
|
||||
'type': 'image',
|
||||
'title': 'soo',
|
||||
'title_link':
|
||||
'https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti'
|
||||
'https://giphy.com/gifs/nrkp3-dance-happy-3o7TKnCdBx5cMg0qti',
|
||||
'actions': [],
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/channel_config.dart';
|
||||
import 'package:stream_chat/src/models/channel_state.dart';
|
||||
import 'package:stream_chat/src/models/command.dart';
|
||||
import 'package:stream_chat/src/models/message.dart';
|
||||
import 'package:stream_chat/src/models/user.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/channel_state', () {
|
||||
const jsonExample = '''{
|
||||
const jsonExample = '''
|
||||
{
|
||||
"channel": {
|
||||
"id": "dev",
|
||||
"type": "team",
|
||||
@@ -844,26 +845,26 @@ void main() {
|
||||
|
||||
test('should parse json correctly', () {
|
||||
final channelState = ChannelState.fromJson(json.decode(jsonExample));
|
||||
expect(channelState.channel.cid, 'team:dev');
|
||||
expect(channelState.channel.id, 'dev');
|
||||
expect(channelState.channel.team, 'test');
|
||||
expect(channelState.channel.type, 'team');
|
||||
expect(channelState.channel.config, isA<ChannelConfig>());
|
||||
expect(channelState.channel.config, isNotNull);
|
||||
expect(channelState.channel.config.commands, hasLength(1));
|
||||
expect(channelState.channel.config.commands[0], isA<Command>());
|
||||
expect(channelState.channel.lastMessageAt,
|
||||
expect(channelState.channel?.cid, 'team:dev');
|
||||
expect(channelState.channel?.id, 'dev');
|
||||
expect(channelState.channel?.team, 'test');
|
||||
expect(channelState.channel?.type, 'team');
|
||||
expect(channelState.channel?.config, isA<ChannelConfig>());
|
||||
expect(channelState.channel?.config, isNotNull);
|
||||
expect(channelState.channel?.config.commands, hasLength(1));
|
||||
expect(channelState.channel?.config.commands[0], isA<Command>());
|
||||
expect(channelState.channel?.lastMessageAt,
|
||||
DateTime.parse('2020-01-30T13:43:41.062362Z'));
|
||||
expect(channelState.channel.createdAt,
|
||||
expect(channelState.channel?.createdAt,
|
||||
DateTime.parse('2019-04-03T18:43:33.213373Z'));
|
||||
expect(channelState.channel.updatedAt,
|
||||
expect(channelState.channel?.updatedAt,
|
||||
DateTime.parse('2019-04-03T18:43:33.213374Z'));
|
||||
expect(channelState.channel.createdBy, isA<User>());
|
||||
expect(channelState.channel.frozen, true);
|
||||
expect(channelState.channel.extraData['example'], 1);
|
||||
expect(channelState.channel.extraData['name'], '#dev');
|
||||
expect(channelState.channel?.createdBy, isA<User>());
|
||||
expect(channelState.channel?.frozen, true);
|
||||
expect(channelState.channel?.extraData!['example'], 1);
|
||||
expect(channelState.channel?.extraData!['name'], '#dev');
|
||||
expect(
|
||||
channelState.channel.extraData['image'],
|
||||
channelState.channel?.extraData!['image'],
|
||||
'https://cdn.chrisshort.net/testing-certificate-chains-in-go/GOPHER_MIC_DROP.png',
|
||||
);
|
||||
expect(channelState.messages, hasLength(25));
|
||||
@@ -888,8 +889,8 @@ void main() {
|
||||
"image": "https://cdn.chrisshort.net/testing-certificate-chains-in-go/GOPHER_MIC_DROP.png",
|
||||
"example": 1
|
||||
},
|
||||
"watchers": null,
|
||||
"read": null,
|
||||
"watchers": [],
|
||||
"read": [],
|
||||
"messages": [
|
||||
{
|
||||
"id": "dry-meadow-0-2b73cc8b-cd86-4a01-8d40-bd82ad07a030",
|
||||
@@ -901,7 +902,7 @@ void main() {
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
@@ -918,7 +919,7 @@ void main() {
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
@@ -928,7 +929,7 @@ void main() {
|
||||
{
|
||||
"id": "dry-meadow-0-53e6299f-9b97-4a9c-a27e-7e2dde49b7e0",
|
||||
"text": "test message",
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
@@ -951,7 +952,7 @@ void main() {
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
@@ -963,7 +964,7 @@ void main() {
|
||||
"id": "dry-meadow-0-64d7970f-ede8-4b31-9738-1bc1756d2bfe",
|
||||
"text": "test",
|
||||
"attachments": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -981,7 +982,7 @@ void main() {
|
||||
"text": "hi",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
@@ -999,7 +1000,7 @@ void main() {
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
@@ -1022,7 +1023,7 @@ void main() {
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
@@ -1040,7 +1041,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1052,7 +1053,7 @@ void main() {
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
@@ -1070,7 +1071,7 @@ void main() {
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
@@ -1089,7 +1090,7 @@ void main() {
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"pin_expires": null,
|
||||
@@ -1099,7 +1100,7 @@ void main() {
|
||||
"id": "icy-recipe-7-935c396e-ddf8-4a9a-951c-0a12fa5bf055",
|
||||
"text": "what are you doing?",
|
||||
"attachments": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -1117,7 +1118,7 @@ void main() {
|
||||
"text": "👍",
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
@@ -1133,7 +1134,7 @@ void main() {
|
||||
"id": "snowy-credit-3-3e0c1a0d-d22f-42ee-b2a1-f9f49477bf21",
|
||||
"text": "sdasas",
|
||||
"attachments": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -1154,7 +1155,7 @@ void main() {
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"mentioned_users": [],
|
||||
"status": "SENT",
|
||||
"silent": false,
|
||||
@@ -1167,7 +1168,7 @@ void main() {
|
||||
"id": "snowy-credit-3-cfaf0b46-1daa-49c5-947c-b16d6697487d",
|
||||
"text": "nhisagdhsadz",
|
||||
"attachments": [],
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
@@ -1186,7 +1187,7 @@ void main() {
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
@@ -1203,7 +1204,7 @@ void main() {
|
||||
"attachments": [],
|
||||
"parent_id": null,
|
||||
"quoted_message": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"quoted_message_id": null,
|
||||
"show_in_channel": null,
|
||||
"mentioned_users": [],
|
||||
@@ -1211,7 +1212,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1228,7 +1229,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1245,7 +1246,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1262,7 +1263,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1279,7 +1280,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1296,7 +1297,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
},
|
||||
@@ -1313,7 +1314,7 @@ void main() {
|
||||
"silent": false,
|
||||
"pinned": false,
|
||||
"pinned_at": null,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"pin_expires": null,
|
||||
"pinned_by": null
|
||||
}
|
||||
@@ -1329,10 +1330,10 @@ void main() {
|
||||
members: [],
|
||||
messages:
|
||||
(j['messages'] as List).map((m) => Message.fromJson(m)).toList(),
|
||||
read: null,
|
||||
read: [],
|
||||
watcherCount: 5,
|
||||
pinnedMessages: [],
|
||||
watchers: null,
|
||||
watchers: [],
|
||||
);
|
||||
|
||||
expect(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/channel_model.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/channel', () {
|
||||
@@ -9,7 +9,7 @@ void main() {
|
||||
{
|
||||
"id": "test",
|
||||
"type": "livestream",
|
||||
"cid": "test:livestream",
|
||||
"cid": "livestream:test",
|
||||
"cats": true,
|
||||
"fruit": ["bananas", "apples"]
|
||||
}
|
||||
@@ -19,9 +19,9 @@ void main() {
|
||||
final channel = ChannelModel.fromJson(json.decode(jsonExample));
|
||||
expect(channel.id, equals('test'));
|
||||
expect(channel.type, equals('livestream'));
|
||||
expect(channel.cid, equals('test:livestream'));
|
||||
expect(channel.extraData['cats'], equals(true));
|
||||
expect(channel.extraData['fruit'], equals(['bananas', 'apples']));
|
||||
expect(channel.cid, equals('livestream:test'));
|
||||
expect(channel.extraData!['cats'], equals(true));
|
||||
expect(channel.extraData!['fruit'], equals(['bananas', 'apples']));
|
||||
});
|
||||
|
||||
test('should serialize to json correctly', () {
|
||||
@@ -34,7 +34,7 @@ void main() {
|
||||
|
||||
expect(
|
||||
channel.toJson(),
|
||||
{'id': 'id', 'type': 'type', 'name': 'cool'},
|
||||
{'id': 'id', 'type': 'type', 'frozen': false, 'name': 'cool'},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -44,7 +44,6 @@ void main() {
|
||||
id: 'id',
|
||||
cid: 'a:a',
|
||||
extraData: {'name': 'cool'},
|
||||
frozen: false,
|
||||
);
|
||||
|
||||
expect(
|
||||
|
||||
@@ -5,7 +5,8 @@ import 'package:stream_chat/src/models/device.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/device', () {
|
||||
const jsonExample = '''{
|
||||
const jsonExample = '''
|
||||
{
|
||||
"id": "device-id",
|
||||
"push_provider": "push-provider"
|
||||
}''';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/event.dart';
|
||||
import 'package:stream_chat/src/models/own_user.dart';
|
||||
import 'package:stream_chat/stream_chat.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/event', () {
|
||||
@@ -47,6 +47,7 @@ void main() {
|
||||
expect(event.createdAt, isA<DateTime>());
|
||||
expect(event.me, isA<OwnUser>());
|
||||
expect(event.user, isA<User>());
|
||||
expect(event.isLocal, false);
|
||||
});
|
||||
|
||||
test('should serialize to json correctly', () {
|
||||
@@ -77,11 +78,11 @@ void main() {
|
||||
'total_unread_count': 1,
|
||||
'unread_channels': 1,
|
||||
'online': true,
|
||||
'is_local': true,
|
||||
'member': null,
|
||||
'channel_id': null,
|
||||
'channel_type': null,
|
||||
'parent_id': null,
|
||||
'is_local': true,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/attachment.dart';
|
||||
import 'package:stream_chat/src/models/message.dart';
|
||||
import 'package:stream_chat/src/models/reaction.dart';
|
||||
import 'package:stream_chat/src/models/user.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/message', () {
|
||||
const jsonExample = r'''{
|
||||
const jsonExample = r'''
|
||||
{
|
||||
"id": "4637f7e4-a06b-42db-ba5a-8d8270dd926f",
|
||||
"text": "https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA",
|
||||
"type": "regular",
|
||||
@@ -101,9 +102,8 @@ void main() {
|
||||
id: '4637f7e4-a06b-42db-ba5a-8d8270dd926f',
|
||||
text:
|
||||
'https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA',
|
||||
silent: false,
|
||||
attachments: [
|
||||
Attachment.fromJson({
|
||||
Attachment.fromJson(const {
|
||||
'type': 'video',
|
||||
'author_name': 'GIPHY',
|
||||
'title': 'The Lion King Disney GIF - Find \u0026 Share on GIPHY',
|
||||
@@ -123,7 +123,7 @@ void main() {
|
||||
],
|
||||
showInChannel: true,
|
||||
parentId: 'parentId',
|
||||
extraData: {'hey': 'test'},
|
||||
extraData: const {'hey': 'test'},
|
||||
);
|
||||
|
||||
expect(
|
||||
@@ -133,7 +133,7 @@ void main() {
|
||||
"id": "4637f7e4-a06b-42db-ba5a-8d8270dd926f",
|
||||
"text": "https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA",
|
||||
"silent": false,
|
||||
"skip_push": null,
|
||||
"skip_push": false,
|
||||
"attachments": [
|
||||
{
|
||||
"type": "video",
|
||||
@@ -144,10 +144,11 @@ void main() {
|
||||
"og_scrape_url": "https://giphy.com/gifs/the-lion-king-live-action-5zvN79uTGfLMOVfQaA",
|
||||
"image_url": "https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.gif",
|
||||
"author_name": "GIPHY",
|
||||
"asset_url": "https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.mp4"
|
||||
"asset_url": "https://media.giphy.com/media/5zvN79uTGfLMOVfQaA/giphy.mp4",
|
||||
"actions": []
|
||||
}
|
||||
],
|
||||
"mentioned_users": null,
|
||||
"mentioned_users": [],
|
||||
"parent_id": "parentId",
|
||||
"quoted_message": null,
|
||||
"quoted_message_id": null,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/reaction.dart';
|
||||
import 'package:stream_chat/src/models/user.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/reaction', () {
|
||||
@@ -33,8 +33,8 @@ void main() {
|
||||
expect(reaction.createdAt, DateTime.parse('2020-01-28T22:17:31.108742Z'));
|
||||
expect(reaction.type, 'wow');
|
||||
expect(
|
||||
reaction.user.toJson(),
|
||||
User.init('2de0297c-f3f2-489d-b930-ef77342edccf', extraData: {
|
||||
reaction.user?.toJson(),
|
||||
User(id: '2de0297c-f3f2-489d-b930-ef77342edccf', extraData: {
|
||||
'image': 'https://randomuser.me/api/portraits/women/45.jpg',
|
||||
'name': 'Daisy Morgan'
|
||||
}).toJson(),
|
||||
@@ -49,7 +49,7 @@ void main() {
|
||||
messageId: '76cd8c82-b557-4e48-9d12-87995d3a0e04',
|
||||
createdAt: DateTime.parse('2020-01-28T22:17:31.108742Z'),
|
||||
type: 'wow',
|
||||
user: User.init('2de0297c-f3f2-489d-b930-ef77342edccf', extraData: {
|
||||
user: User(id: '2de0297c-f3f2-489d-b930-ef77342edccf', extraData: {
|
||||
'image': 'https://randomuser.me/api/portraits/women/45.jpg',
|
||||
'name': 'Daisy Morgan'
|
||||
}),
|
||||
|
||||
@@ -26,7 +26,7 @@ void main() {
|
||||
test('should serialize to json correctly', () {
|
||||
final read = Read(
|
||||
lastRead: DateTime.parse('2020-01-28T22:17:30.966485504Z'),
|
||||
user: User.init('bbb19d9a-ee50-45bc-84e5-0584e79d0c9e'),
|
||||
user: User(id: 'bbb19d9a-ee50-45bc-84e5-0584e79d0c9e'),
|
||||
unreadMessages: 10,
|
||||
);
|
||||
|
||||
|
||||
@@ -49,12 +49,12 @@ void main() {
|
||||
});
|
||||
|
||||
test('should return null', () {
|
||||
final result = Serialization.moveToExtraDataFromRoot(null, [
|
||||
final result = Serialization.moveToExtraDataFromRoot({}, [
|
||||
'prop1',
|
||||
'prop2',
|
||||
]);
|
||||
|
||||
expect(result, null);
|
||||
expect(result, {'extra_data': {}});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:test/test.dart';
|
||||
import 'package:stream_chat/src/models/user.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/user', () {
|
||||
const jsonExample = '''
|
||||
{
|
||||
"id": "bbb19d9a-ee50-45bc-84e5-0584e79d0c9e"
|
||||
"id": "bbb19d9a-ee50-45bc-84e5-0584e79d0c9e",
|
||||
"role": "test-role"
|
||||
}
|
||||
''';
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ void main() {
|
||||
final String pubspecPath = '${Directory.current.path}/pubspec.yaml';
|
||||
final String pubspec = File(pubspecPath).readAsStringSync();
|
||||
final RegExp regex = RegExp('version:\s*(.*)');
|
||||
final RegExpMatch match = regex.firstMatch(pubspec);
|
||||
final RegExpMatch? match = regex.firstMatch(pubspec);
|
||||
expect(match, isNotNull);
|
||||
expect(PACKAGE_VERSION, match.group(1).trim());
|
||||
expect(PACKAGE_VERSION, match?.group(1)?.trim());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ dependencies:
|
||||
ezanimation: ^0.4.1
|
||||
synchronized: ^3.0.0
|
||||
characters: ^1.0.0
|
||||
dio: ">=4.0.0-prev3 <4.0.0"
|
||||
dio: ^4.0.0
|
||||
path_provider: ^2.0.0
|
||||
video_thumbnail: ^0.2.5+1
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ void main() {
|
||||
Reaction(
|
||||
messageId: 'test',
|
||||
user: User(id: 'testid'),
|
||||
type: 'test',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user