added null safety for llc
This commit is contained in:
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,
|
||||
|
||||
@@ -13,192 +13,192 @@ 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;
|
||||
List<Event>? events;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SyncResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$SyncResponseFromJson(json);
|
||||
static SyncResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$SyncResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [StreamChatClient.queryChannels] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryChannelsResponse extends _BaseResponse {
|
||||
/// List of channels state returned by the query
|
||||
List<ChannelState> channels;
|
||||
List<ChannelState>? channels;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryChannelsResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$QueryChannelsResponseFromJson(json);
|
||||
static QueryChannelsResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$QueryChannelsResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [StreamChatClient.queryChannels] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class TranslateMessageResponse extends _BaseResponse {
|
||||
/// List of channels state returned by the query
|
||||
TranslatedMessage message;
|
||||
TranslatedMessage? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static TranslateMessageResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$TranslateMessageResponseFromJson(json);
|
||||
static TranslateMessageResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$TranslateMessageResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [StreamChatClient.queryChannels] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryMembersResponse extends _BaseResponse {
|
||||
/// List of channels state returned by the query
|
||||
List<Member> members;
|
||||
List<Member>? members;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$QueryMembersResponseFromJson(json);
|
||||
static QueryMembersResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$QueryMembersResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [StreamChatClient.queryUsers] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryUsersResponse extends _BaseResponse {
|
||||
/// List of users returned by the query
|
||||
List<User> users;
|
||||
List<User>? users;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryUsersResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$QueryUsersResponseFromJson(json);
|
||||
static QueryUsersResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$QueryUsersResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [channel.getReactions] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryReactionsResponse extends _BaseResponse {
|
||||
/// List of reactions returned by the query
|
||||
List<Reaction> reactions;
|
||||
List<Reaction>? reactions;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryReactionsResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$QueryReactionsResponseFromJson(json);
|
||||
static QueryReactionsResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$QueryReactionsResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.getReplies] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QueryRepliesResponse extends _BaseResponse {
|
||||
/// List of messages returned by the api call
|
||||
List<Message> messages;
|
||||
List<Message>? messages;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static QueryRepliesResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$QueryRepliesResponseFromJson(json);
|
||||
static QueryRepliesResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$QueryRepliesResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [StreamChatClient.getDevices] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class ListDevicesResponse extends _BaseResponse {
|
||||
/// List of user devices
|
||||
List<Device> devices;
|
||||
List<Device>? devices;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static ListDevicesResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$ListDevicesResponseFromJson(json);
|
||||
static ListDevicesResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$ListDevicesResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.sendFile] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendFileResponse extends _BaseResponse {
|
||||
/// The url of the uploaded file
|
||||
String file;
|
||||
String? file;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendFileResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$SendFileResponseFromJson(json);
|
||||
static SendFileResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$SendFileResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.sendImage] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendImageResponse extends _BaseResponse {
|
||||
/// The url of the uploaded file
|
||||
String file;
|
||||
String? file;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendImageResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$SendImageResponseFromJson(json);
|
||||
static SendImageResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$SendImageResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.sendReaction] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendReactionResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// The reaction created by the api call
|
||||
Reaction reaction;
|
||||
Reaction? reaction;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendReactionResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$SendReactionResponseFromJson(json);
|
||||
static SendReactionResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$SendReactionResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [StreamChatClient.connectGuestUser] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class ConnectGuestUserResponse extends _BaseResponse {
|
||||
/// Guest user access token
|
||||
String accessToken;
|
||||
String? accessToken;
|
||||
|
||||
/// Guest user
|
||||
User user;
|
||||
User? user;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static ConnectGuestUserResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$ConnectGuestUserResponseFromJson(json);
|
||||
static ConnectGuestUserResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$ConnectGuestUserResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [StreamChatClient.updateUser] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class UpdateUsersResponse extends _BaseResponse {
|
||||
/// Updated users
|
||||
Map<String, User> users;
|
||||
Map<String, User>? users;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static UpdateUsersResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$UpdateUsersResponseFromJson(json);
|
||||
static UpdateUsersResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$UpdateUsersResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [StreamChatClient.updateMessage] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class UpdateMessageResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static UpdateMessageResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$UpdateMessageResponseFromJson(json);
|
||||
static UpdateMessageResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$UpdateMessageResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.sendMessage] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SendMessageResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
Message? message;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SendMessageResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$SendMessageResponseFromJson(json);
|
||||
static SendMessageResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$SendMessageResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [StreamChatClient.getMessage] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class GetMessageResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
Message message;
|
||||
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);
|
||||
static GetMessageResponse fromJson(Map<String, dynamic>? json) {
|
||||
final res = _$GetMessageResponseFromJson(json!);
|
||||
final jsonChannel = res.message?.extraData?.remove('channel');
|
||||
if (jsonChannel != null) {
|
||||
res.channel = ChannelModel.fromJson(jsonChannel);
|
||||
@@ -211,176 +211,176 @@ class GetMessageResponse extends _BaseResponse {
|
||||
@JsonSerializable(createToJson: false)
|
||||
class SearchMessagesResponse extends _BaseResponse {
|
||||
/// List of messages returned by the api call
|
||||
List<GetMessageResponse> results;
|
||||
List<GetMessageResponse>? results;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static SearchMessagesResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$SearchMessagesResponseFromJson(json);
|
||||
static SearchMessagesResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$SearchMessagesResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.getMessagesById] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class GetMessagesByIdResponse extends _BaseResponse {
|
||||
/// Message returned by the api call
|
||||
List<Message> messages;
|
||||
List<Message>? messages;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static GetMessagesByIdResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$GetMessagesByIdResponseFromJson(json);
|
||||
static GetMessagesByIdResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$GetMessagesByIdResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.update] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class UpdateChannelResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
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) =>
|
||||
_$UpdateChannelResponseFromJson(json);
|
||||
static UpdateChannelResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$UpdateChannelResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.updatePartial] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class PartialUpdateChannelResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
ChannelModel? channel;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
List<Member>? members;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static PartialUpdateChannelResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$PartialUpdateChannelResponseFromJson(json);
|
||||
static PartialUpdateChannelResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$PartialUpdateChannelResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.inviteMembers] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class InviteMembersResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
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 InviteMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$InviteMembersResponseFromJson(json);
|
||||
static InviteMembersResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$InviteMembersResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.removeMembers] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class RemoveMembersResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
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 RemoveMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$RemoveMembersResponseFromJson(json);
|
||||
static RemoveMembersResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$RemoveMembersResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.sendAction] api call
|
||||
@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) =>
|
||||
_$SendActionResponseFromJson(json);
|
||||
static SendActionResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$SendActionResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.addMembers] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class AddMembersResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
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 AddMembersResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$AddMembersResponseFromJson(json);
|
||||
static AddMembersResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$AddMembersResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.acceptInvite] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class AcceptInviteResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
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 AcceptInviteResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$AcceptInviteResponseFromJson(json);
|
||||
static AcceptInviteResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$AcceptInviteResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.rejectInvite] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class RejectInviteResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
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 RejectInviteResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$RejectInviteResponseFromJson(json);
|
||||
static RejectInviteResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$RejectInviteResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for empty responses
|
||||
@JsonSerializable(createToJson: false)
|
||||
class EmptyResponse extends _BaseResponse {
|
||||
/// Create a new instance from a json
|
||||
static EmptyResponse fromJson(Map<String, dynamic> json) =>
|
||||
_$EmptyResponseFromJson(json);
|
||||
static EmptyResponse fromJson(Map<String, dynamic>? json) =>
|
||||
_$EmptyResponseFromJson(json!);
|
||||
}
|
||||
|
||||
/// Model response for [Channel.query] api call
|
||||
@JsonSerializable(createToJson: false)
|
||||
class ChannelStateResponse extends _BaseResponse {
|
||||
/// Updated channel
|
||||
ChannelModel channel;
|
||||
ChannelModel? channel;
|
||||
|
||||
/// List of messages returned by the api call
|
||||
List<Message> messages;
|
||||
List<Message>? messages;
|
||||
|
||||
/// Channel members
|
||||
List<Member> members;
|
||||
List<Member>? members;
|
||||
|
||||
/// Number of users watching the channel
|
||||
int watcherCount;
|
||||
int? watcherCount;
|
||||
|
||||
/// List of read states
|
||||
List<Read> read;
|
||||
List<Read>? read;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static ChannelStateResponse fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -6,30 +6,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,
|
||||
|
||||
@@ -14,7 +14,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,29 +28,29 @@ 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();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
final HeapPriorityQueue<Message> _messageQueue = HeapPriorityQueue(_byDate);
|
||||
final HeapPriorityQueue<Message?> _messageQueue = HeapPriorityQueue(_byDate);
|
||||
bool _isRetrying = false;
|
||||
RetryPolicy _retryPolicy;
|
||||
RetryPolicy? _retryPolicy;
|
||||
|
||||
/// Add a list of messages
|
||||
void add(List<Message> 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)));
|
||||
.where((element) => !messageList.any((m) => m!.id == element!.id)));
|
||||
|
||||
if (_messageQueue.isNotEmpty && !_isRetrying) {
|
||||
_startRetrying();
|
||||
@@ -60,10 +60,10 @@ 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;
|
||||
final message = _messageQueue.first!;
|
||||
try {
|
||||
logger?.info('retry attempt ${retryPolicy.attempt}');
|
||||
await _sendMessage(message);
|
||||
@@ -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,20 @@ 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]);
|
||||
} else if (messageIndex != -1 &&
|
||||
[
|
||||
MessageSendingStatus.sent,
|
||||
null,
|
||||
].contains(event.message.status)) {
|
||||
].contains(event.message!.status)) {
|
||||
_messageQueue.remove(messageList[messageIndex]);
|
||||
}
|
||||
}
|
||||
@@ -167,14 +168,14 @@ class RetryQueue {
|
||||
_subscriptions.forEach((s) => s.cancel());
|
||||
}
|
||||
|
||||
static int _byDate(Message m1, Message m2) {
|
||||
final date1 = _getMessageDate(m1);
|
||||
final date2 = _getMessageDate(m2);
|
||||
static int _byDate(Message? m1, Message? m2) {
|
||||
final date1 = _getMessageDate(m1!)!;
|
||||
final date2 = _getMessageDate(m2!)!;
|
||||
|
||||
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,7 +27,7 @@ class WebSocket {
|
||||
/// Creates a new websocket
|
||||
/// To connect the WS call [connect]
|
||||
WebSocket({
|
||||
@required this.baseUrl,
|
||||
required this.baseUrl,
|
||||
this.user,
|
||||
this.connectParams,
|
||||
this.connectPayload,
|
||||
@@ -38,22 +38,22 @@ class WebSocket {
|
||||
this.healthCheckInterval = 20,
|
||||
this.reconnectionMonitorTimeout = 40,
|
||||
}) {
|
||||
final qs = Map<String, String>.from(connectParams);
|
||||
final qs = Map<String, String>.from(connectParams!);
|
||||
|
||||
final data = Map<String, dynamic>.from(connectPayload);
|
||||
final data = Map<String, dynamic>.from(connectPayload!);
|
||||
|
||||
data['user_details'] = user.toJson();
|
||||
data['user_details'] = user!.toJson();
|
||||
qs['json'] = json.encode(data);
|
||||
|
||||
if (baseUrl.startsWith('https')) {
|
||||
_path = baseUrl.replaceFirst('https://', '');
|
||||
_path = Uri.https(_path, 'connect', qs)
|
||||
_path = Uri.https(_path!, 'connect', qs)
|
||||
.toString()
|
||||
.replaceFirst('https', 'wss');
|
||||
} else if (baseUrl.startsWith('http')) {
|
||||
_path = baseUrl.replaceFirst('http://', '');
|
||||
_path =
|
||||
Uri.http(_path, 'connect', qs).toString().replaceFirst('http', 'ws');
|
||||
Uri.http(_path!, 'connect', qs).toString().replaceFirst('http', 'ws');
|
||||
} else {
|
||||
_path = Uri.https(baseUrl, 'connect', qs)
|
||||
.toString()
|
||||
@@ -65,25 +65,25 @@ class WebSocket {
|
||||
final String baseUrl;
|
||||
|
||||
/// User performing the WS connection
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// Querystring connection parameters
|
||||
final Map<String, String> connectParams;
|
||||
final Map<String, String?>? connectParams;
|
||||
|
||||
/// WS connection payload
|
||||
final Map<String, dynamic> connectPayload;
|
||||
final Map<String, dynamic>? connectPayload;
|
||||
|
||||
/// Functions that will be called every time a new event is received from the
|
||||
/// connection
|
||||
final EventHandler handler;
|
||||
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,17 +107,17 @@ 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;
|
||||
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;
|
||||
@@ -127,23 +127,23 @@ class WebSocket {
|
||||
Completer<Event> _connectionCompleter = Completer<Event>();
|
||||
|
||||
/// Connect the WS using the parameters passed in the constructor
|
||||
Future<Event> connect() {
|
||||
Future<Event>? connect() {
|
||||
_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));
|
||||
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']);
|
||||
@@ -166,7 +166,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 +180,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();
|
||||
@@ -199,14 +199,14 @@ class WebSocket {
|
||||
_startHealthCheck();
|
||||
}
|
||||
|
||||
handler(event);
|
||||
handler!(event);
|
||||
_lastEventAt = DateTime.now();
|
||||
}
|
||||
|
||||
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 +225,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 +244,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 +267,7 @@ class WebSocket {
|
||||
}
|
||||
|
||||
Future<void> _reconnect() async {
|
||||
logger.info('reconnect');
|
||||
logger!.info('reconnect');
|
||||
if (!_reconnecting) {
|
||||
_reconnecting = true;
|
||||
_connectionStatus = ConnectionStatus.connecting;
|
||||
@@ -279,20 +279,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,7 +311,7 @@ class WebSocket {
|
||||
if (_manuallyDisconnected) {
|
||||
return;
|
||||
}
|
||||
logger.info('disconnecting');
|
||||
logger!.info('disconnecting');
|
||||
_connectionCompleter = Completer();
|
||||
_cancelTimers();
|
||||
_reconnecting = false;
|
||||
|
||||
Reference in New Issue
Block a user