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;
|
||||
|
||||
@@ -11,12 +11,12 @@ abstract class AttachmentFileUploader {
|
||||
///
|
||||
/// Optionally, access upload progress using [onSendProgress]
|
||||
/// and cancel the request using [cancelToken]
|
||||
Future<SendImageResponse> sendImage(
|
||||
AttachmentFile image,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
Future<SendImageResponse?> sendImage(
|
||||
AttachmentFile? image,
|
||||
String? channelId,
|
||||
String? channelType, {
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
/// Uploads a [file] to the given channel.
|
||||
@@ -24,34 +24,34 @@ abstract class AttachmentFileUploader {
|
||||
///
|
||||
/// Optionally, access upload progress using [onSendProgress]
|
||||
/// and cancel the request using [cancelToken]
|
||||
Future<SendFileResponse> sendFile(
|
||||
AttachmentFile file,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
Future<SendFileResponse?> sendFile(
|
||||
AttachmentFile? file,
|
||||
String? channelId,
|
||||
String? channelType, {
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
/// Deletes a image using its [url] from the given channel.
|
||||
/// Returns [EmptyResponse] once deleted successfully.
|
||||
///
|
||||
/// Optionally, cancel the request using [cancelToken]
|
||||
Future<EmptyResponse> deleteImage(
|
||||
Future<EmptyResponse?> deleteImage(
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
String? channelId,
|
||||
String? channelType, {
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
|
||||
/// Deletes a file using its [url] from the given channel.
|
||||
/// Returns [EmptyResponse] once deleted successfully.
|
||||
///
|
||||
/// Optionally, cancel the request using [cancelToken]
|
||||
Future<EmptyResponse> deleteFile(
|
||||
Future<EmptyResponse?> deleteFile(
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
String? channelId,
|
||||
String? channelType, {
|
||||
CancelToken? cancelToken,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -63,26 +63,26 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
final StreamChatClient _client;
|
||||
|
||||
@override
|
||||
Future<SendImageResponse> sendImage(
|
||||
AttachmentFile file,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
Future<SendImageResponse?> sendImage(
|
||||
AttachmentFile? file,
|
||||
String? channelId,
|
||||
String? channelType, {
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final filename = file.path?.split('/')?.last ?? file.name;
|
||||
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,
|
||||
);
|
||||
@@ -100,26 +100,26 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SendFileResponse> sendFile(
|
||||
AttachmentFile file,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
ProgressCallback onSendProgress,
|
||||
CancelToken cancelToken,
|
||||
Future<SendFileResponse?> sendFile(
|
||||
AttachmentFile? file,
|
||||
String? channelId,
|
||||
String? channelType, {
|
||||
ProgressCallback? onSendProgress,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final filename = file.path?.split('/')?.last ?? file.name;
|
||||
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,
|
||||
);
|
||||
@@ -137,11 +137,11 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EmptyResponse> deleteImage(
|
||||
Future<EmptyResponse?> deleteImage(
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
String? channelId,
|
||||
String? channelType, {
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final response = await _client.delete(
|
||||
'/channels/$channelType/$channelId/image',
|
||||
@@ -152,11 +152,11 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EmptyResponse> deleteFile(
|
||||
Future<EmptyResponse?> deleteFile(
|
||||
String url,
|
||||
String channelId,
|
||||
String channelType, {
|
||||
CancelToken cancelToken,
|
||||
String? channelId,
|
||||
String? channelType, {
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
final response = await _client.delete(
|
||||
'/channels/$channelType/$channelId/file',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ import 'package:stream_chat/src/models/user.dart';
|
||||
/// A simple client used for persisting chat data locally.
|
||||
abstract class ChatPersistenceClient {
|
||||
/// Creates a new connection to the client
|
||||
Future<void> connect(String userId);
|
||||
Future<void> connect(String? userId);
|
||||
|
||||
/// Closes the client connection
|
||||
/// If [flush] is true, the data will also be deleted
|
||||
@@ -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
|
||||
@@ -33,40 +33,40 @@ abstract class ChatPersistenceClient {
|
||||
Future<void> updateConnectionInfo(Event event);
|
||||
|
||||
/// Update stored lastSyncAt
|
||||
Future<void> updateLastSyncAt(DateTime lastSyncAt);
|
||||
Future<void> updateLastSyncAt(DateTime? lastSyncAt);
|
||||
|
||||
/// Get the channel cids saved in the offline storage
|
||||
Future<List<String>> getChannelCids();
|
||||
|
||||
/// Get stored [ChannelModel]s by providing channel [cid]
|
||||
Future<ChannelModel> getChannelByCid(String cid);
|
||||
Future<ChannelModel> getChannelByCid(String? cid);
|
||||
|
||||
/// Get stored channel [Member]s by providing channel [cid]
|
||||
Future<List<Member>> getMembersByCid(String cid);
|
||||
Future<List<Member>> getMembersByCid(String? cid);
|
||||
|
||||
/// Get stored channel [Read]s by providing channel [cid]
|
||||
Future<List<Read>> getReadsByCid(String cid);
|
||||
Future<List<Read>> getReadsByCid(String? cid);
|
||||
|
||||
/// Get stored [Message]s by providing channel [cid]
|
||||
///
|
||||
/// Optionally, you can [messagePagination]
|
||||
/// for filtering out messages
|
||||
Future<List<Message>> getMessagesByCid(
|
||||
String cid, {
|
||||
PaginationParams messagePagination,
|
||||
String? cid, {
|
||||
PaginationParams? messagePagination,
|
||||
});
|
||||
|
||||
/// Get stored pinned [Message]s by providing channel [cid]
|
||||
Future<List<Message>> getPinnedMessagesByCid(
|
||||
String cid, {
|
||||
PaginationParams messagePagination,
|
||||
String? cid, {
|
||||
PaginationParams? messagePagination,
|
||||
});
|
||||
|
||||
/// Get [ChannelState] data by providing channel [cid]
|
||||
Future<ChannelState> getChannelStateByCid(
|
||||
String cid, {
|
||||
PaginationParams messagePagination,
|
||||
PaginationParams pinnedMessagePagination,
|
||||
String? cid, {
|
||||
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.
|
||||
@@ -99,8 +99,8 @@ abstract class ChatPersistenceClient {
|
||||
/// If [clearQueryCache] is true before the insert
|
||||
/// the list of matching rows will be deleted
|
||||
Future<void> updateChannelQueries(
|
||||
Map<String, dynamic> filter,
|
||||
List<String> cids, {
|
||||
Map<String, dynamic>? filter,
|
||||
List<String?> cids, {
|
||||
bool clearQueryCache = false,
|
||||
});
|
||||
|
||||
@@ -119,46 +119,46 @@ abstract class ChatPersistenceClient {
|
||||
Future<void> deletePinnedMessageByIds(List<String> messageIds);
|
||||
|
||||
/// Remove a message by channel [cid]
|
||||
Future<void> deleteMessageByCid(String cid) => deleteMessageByCids([cid]);
|
||||
Future<void> deleteMessageByCid(String? cid) => deleteMessageByCids([cid]);
|
||||
|
||||
/// Remove a pinned message by channel [cid]
|
||||
Future<void> deletePinnedMessageByCid(String cid) async =>
|
||||
deletePinnedMessageByCids([cid]);
|
||||
|
||||
/// Remove a message by message [cids]
|
||||
Future<void> deleteMessageByCids(List<String> cids);
|
||||
Future<void> deleteMessageByCids(List<String?> cids);
|
||||
|
||||
/// Remove a pinned message by message [cids]
|
||||
Future<void> deletePinnedMessageByCids(List<String> cids);
|
||||
|
||||
/// Remove a channel by [cid]
|
||||
Future<void> deleteChannels(List<String> cids);
|
||||
Future<void> deleteChannels(List<String?> cids);
|
||||
|
||||
/// Updates the message data of a particular channel [cid] with
|
||||
/// the new [messages] data
|
||||
Future<void> updateMessages(String cid, List<Message> messages);
|
||||
Future<void> updateMessages(String? cid, List<Message> messages);
|
||||
|
||||
/// Updates the pinned message data of a particular channel [cid] with
|
||||
/// the new [messages] data
|
||||
Future<void> updatePinnedMessages(String cid, List<Message> messages);
|
||||
Future<void> updatePinnedMessages(String? cid, List<Message> messages);
|
||||
|
||||
/// Returns all the threads by parent message of a particular channel by
|
||||
/// providing channel [cid]
|
||||
Future<Map<String, List<Message>>> getChannelThreads(String cid);
|
||||
Future<Map<String, List<Message>>> getChannelThreads(String? cid);
|
||||
|
||||
/// Updates all the channels using the new [channels] data.
|
||||
Future<void> updateChannels(List<ChannelModel> channels);
|
||||
Future<void> updateChannels(List<ChannelModel?> channels);
|
||||
|
||||
/// Updates all the members of a particular channle [cid]
|
||||
/// with the new [members] data
|
||||
Future<void> updateMembers(String cid, List<Member> members);
|
||||
Future<void> updateMembers(String? cid, List<Member?> members);
|
||||
|
||||
/// Updates the read data of a particular channel [cid] with
|
||||
/// the new [reads] data
|
||||
Future<void> updateReads(String cid, List<Read> reads);
|
||||
Future<void> updateReads(String? cid, List<Read> reads);
|
||||
|
||||
/// Updates the users data with the new [users] data
|
||||
Future<void> updateUsers(List<User> users);
|
||||
Future<void> updateUsers(List<User?> users);
|
||||
|
||||
/// Updates the reactions data with the new [reactions] data
|
||||
Future<void> updateReactions(List<Reaction> reactions);
|
||||
@@ -167,7 +167,7 @@ abstract class ChatPersistenceClient {
|
||||
Future<void> deleteReactionsByMessageId(List<String> messageIds);
|
||||
|
||||
/// Deletes all the members by channel [cids]
|
||||
Future<void> deleteMembersByCids(List<String> cids);
|
||||
Future<void> deleteMembersByCids(List<String?> cids);
|
||||
|
||||
/// Update the channel state data using [channelState]
|
||||
Future<void> updateChannelState(ChannelState channelState) =>
|
||||
@@ -176,12 +176,12 @@ abstract class ChatPersistenceClient {
|
||||
/// Update list of channel states
|
||||
Future<void> updateChannelStates(List<ChannelState> channelStates) async {
|
||||
final deleteReactions = deleteReactionsByMessageId(channelStates
|
||||
.expand((it) => it.messages)
|
||||
.expand((it) => it.messages!)
|
||||
.map((m) => m.id)
|
||||
.toList(growable: false));
|
||||
|
||||
final deleteMembers = deleteMembersByCids(
|
||||
channelStates.map((it) => it.channel.cid).toList(growable: false),
|
||||
channelStates.map((it) => it.channel!.cid).toList(growable: false),
|
||||
);
|
||||
|
||||
await Future.wait([
|
||||
@@ -193,54 +193,54 @@ abstract class ChatPersistenceClient {
|
||||
channelStates.map((it) => it.channel).where((it) => it != null);
|
||||
|
||||
final reactions = channelStates
|
||||
.expand((it) => it.messages)
|
||||
.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)
|
||||
...it.latestReactions!.where((r) => r.userId != null)
|
||||
])
|
||||
.where((it) => it != null);
|
||||
|
||||
final users = channelStates
|
||||
.map((cs) => [
|
||||
cs.channel?.createdBy,
|
||||
...cs.messages
|
||||
...?cs.messages
|
||||
?.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),
|
||||
if (cs.read != null) ...cs.read!.map((r) => r.user),
|
||||
if (cs.members != null) ...cs.members!.map((m) => m!.user),
|
||||
])
|
||||
.expand((it) => it)
|
||||
.where((it) => it != null);
|
||||
|
||||
final updateMessagesFuture = channelStates.map((it) {
|
||||
final cid = it.channel.cid;
|
||||
final messages = it.messages.where((it) => it != null);
|
||||
final cid = it.channel!.cid;
|
||||
final messages = it.messages!.where((it) => it != null);
|
||||
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 cid = it.channel!.cid;
|
||||
final messages = it.pinnedMessages!.where((it) => it != null);
|
||||
return updatePinnedMessages(cid, messages.toList(growable: false));
|
||||
}).toList(growable: false);
|
||||
|
||||
final updateReadsFuture = channelStates.map((it) {
|
||||
final cid = it.channel.cid;
|
||||
final cid = it.channel!.cid;
|
||||
final reads = it.read?.where((it) => it != null) ?? [];
|
||||
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 cid = it.channel!.cid;
|
||||
final members = it.members!.where((it) => it != null);
|
||||
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 {
|
||||
/// Returns a new map with null keys or values removed
|
||||
Map<String, dynamic> get nullProtected =>
|
||||
{...this}..removeWhere((key, value) => key == null || value == null);
|
||||
Map<String, dynamic> get nullProtected => {...this as Map<String, dynamic>}
|
||||
..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,
|
||||
_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);
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@ import 'package:http_parser/http_parser.dart' as http_parser;
|
||||
import 'package:mime/mime.dart';
|
||||
|
||||
/// Useful extension functions for [String]
|
||||
extension StringX on String {
|
||||
extension StringX on String? {
|
||||
/// Returns the mime type from the passed file name.
|
||||
http_parser.MediaType get mimeType {
|
||||
http_parser.MediaType? get mimeType {
|
||||
if (this == null) return null;
|
||||
if (toLowerCase().endsWith('heic')) {
|
||||
if (this!.toLowerCase().endsWith('heic')) {
|
||||
return http_parser.MediaType.parse('image/heic');
|
||||
} else {
|
||||
return http_parser.MediaType.parse(lookupMimeType(this));
|
||||
return http_parser.MediaType.parse(lookupMimeType(this!)!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,19 +12,19 @@ class Action {
|
||||
factory Action.fromJson(Map<String, dynamic> json) => _$ActionFromJson(json);
|
||||
|
||||
/// The name of the action
|
||||
final String name;
|
||||
final String? name;
|
||||
|
||||
/// The style of the action
|
||||
final String style;
|
||||
final String? style;
|
||||
|
||||
/// The test of the action
|
||||
final String text;
|
||||
final String? text;
|
||||
|
||||
/// The type of the action
|
||||
final String type;
|
||||
final String? type;
|
||||
|
||||
/// The value of the action
|
||||
final String value;
|
||||
final String? value;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => _$ActionToJson(this);
|
||||
|
||||
@@ -13,10 +13,10 @@ part 'attachment.g.dart';
|
||||
class Attachment {
|
||||
/// Constructor used for json serialization
|
||||
Attachment({
|
||||
String id,
|
||||
String? id,
|
||||
this.type,
|
||||
this.titleLink,
|
||||
String title,
|
||||
String? title,
|
||||
this.thumbUrl,
|
||||
this.text,
|
||||
this.pretext,
|
||||
@@ -34,10 +34,10 @@ class Attachment {
|
||||
this.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 {
|
||||
localUri = file?.path != null ? Uri.parse(file!.path!) : null {
|
||||
this.uploadState = uploadState ??
|
||||
((assetUrl != null || imageUrl != null)
|
||||
? const UploadState.success()
|
||||
@@ -47,68 +47,68 @@ class Attachment {
|
||||
/// Create a new instance from a json
|
||||
factory Attachment.fromJson(Map<String, dynamic> json) =>
|
||||
_$AttachmentFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields));
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields)!);
|
||||
|
||||
/// Create a new instance from a db data
|
||||
factory Attachment.fromData(Map<String, dynamic> json) =>
|
||||
_$AttachmentFromJson(Serialization.moveToExtraDataFromRoot(
|
||||
json, topLevelFields + dbSpecificTopLevelFields));
|
||||
json, topLevelFields + dbSpecificTopLevelFields)!);
|
||||
|
||||
///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
|
||||
final List<Action> actions;
|
||||
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
|
||||
UploadState uploadState;
|
||||
UploadState? uploadState;
|
||||
|
||||
/// Map of custom channel extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
final Map<String, dynamic>? extraData;
|
||||
|
||||
/// The attachment ID.
|
||||
///
|
||||
@@ -156,28 +156,28 @@ class Attachment {
|
||||
_$AttachmentToJson(this), topLevelFields + dbSpecificTopLevelFields);
|
||||
|
||||
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,
|
||||
|
||||
@@ -19,7 +19,7 @@ abstract class UploadState with _$UploadState {
|
||||
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 +27,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;
|
||||
|
||||
@@ -65,21 +65,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);
|
||||
|
||||
@@ -30,52 +30,52 @@ class ChannelConfig {
|
||||
_$ChannelConfigFromJson(json);
|
||||
|
||||
/// Moderation configuration
|
||||
final String automod;
|
||||
final String? automod;
|
||||
|
||||
/// List of available commands
|
||||
final List<Command> commands;
|
||||
final List<Command>? commands;
|
||||
|
||||
/// True if the channel should send connect events
|
||||
final bool connectEvents;
|
||||
final bool? connectEvents;
|
||||
|
||||
/// Date of channel creation
|
||||
final DateTime createdAt;
|
||||
final DateTime? createdAt;
|
||||
|
||||
/// Date of last channel update
|
||||
final DateTime updatedAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
/// Max channel message length
|
||||
final int maxMessageLength;
|
||||
final int? maxMessageLength;
|
||||
|
||||
/// Duration of message retention
|
||||
final String messageRetention;
|
||||
final String? messageRetention;
|
||||
|
||||
/// True if users can be muted
|
||||
final bool mutes;
|
||||
final bool? mutes;
|
||||
|
||||
/// Name of the channel
|
||||
final String name;
|
||||
final String? name;
|
||||
|
||||
/// True if reaction are active for this channel
|
||||
final bool reactions;
|
||||
final bool? reactions;
|
||||
|
||||
/// True if readEvents are active for this channel
|
||||
final bool readEvents;
|
||||
final bool? readEvents;
|
||||
|
||||
/// True if reply message are active for this channel
|
||||
final bool replies;
|
||||
final bool? replies;
|
||||
|
||||
/// True if it's possible to perform a search in this channel
|
||||
final bool search;
|
||||
final bool? search;
|
||||
|
||||
/// True if typing events should be sent for this channel
|
||||
final bool typingEvents;
|
||||
final bool? typingEvents;
|
||||
|
||||
/// True if it's possible to upload files to this channel
|
||||
final bool uploads;
|
||||
final bool? uploads;
|
||||
|
||||
/// True if urls appears as attachments
|
||||
final bool urlEnrichment;
|
||||
final bool? urlEnrichment;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => _$ChannelConfigToJson(this);
|
||||
|
||||
@@ -26,59 +26,59 @@ class ChannelModel {
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory ChannelModel.fromJson(Map<String, dynamic> json) =>
|
||||
factory ChannelModel.fromJson(Map<String, dynamic>? json) =>
|
||||
_$ChannelModelFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields));
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields)!);
|
||||
|
||||
/// The id of this channel
|
||||
final String id;
|
||||
final String? id;
|
||||
|
||||
/// The type of this channel
|
||||
final String type;
|
||||
final String? type;
|
||||
|
||||
/// The cid of this channel
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final String cid;
|
||||
final String? cid;
|
||||
|
||||
/// The channel configuration data
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final ChannelConfig config;
|
||||
final ChannelConfig? config;
|
||||
|
||||
/// 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)
|
||||
final bool frozen;
|
||||
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)
|
||||
final DateTime createdAt;
|
||||
final DateTime? createdAt;
|
||||
|
||||
/// The date of the last channel update
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime updatedAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
/// 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)
|
||||
final int memberCount;
|
||||
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,8 +98,8 @@ 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(
|
||||
@@ -109,19 +109,19 @@ class ChannelModel {
|
||||
|
||||
/// 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 +141,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,
|
||||
|
||||
@@ -22,42 +22,42 @@ class ChannelState {
|
||||
});
|
||||
|
||||
/// The channel to which this state belongs
|
||||
final ChannelModel channel;
|
||||
final ChannelModel? channel;
|
||||
|
||||
/// A paginated list of channel messages
|
||||
final List<Message> messages;
|
||||
final List<Message>? messages;
|
||||
|
||||
/// A paginated list of channel members
|
||||
final List<Member> members;
|
||||
final List<Member?>? members;
|
||||
|
||||
/// A paginated list of pinned messages
|
||||
final List<Message> pinnedMessages;
|
||||
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
|
||||
final List<User> watchers;
|
||||
final List<User>? watchers;
|
||||
|
||||
/// The list of channel reads
|
||||
final List<Read> read;
|
||||
final List<Read>? read;
|
||||
|
||||
/// Create a new instance from a json
|
||||
static ChannelState fromJson(Map<String, dynamic> json) =>
|
||||
_$ChannelStateFromJson(json);
|
||||
static ChannelState fromJson(Map<String, dynamic>? json) =>
|
||||
_$ChannelStateFromJson(json!);
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => _$ChannelStateToJson(this);
|
||||
|
||||
/// 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,
|
||||
|
||||
@@ -17,13 +17,13 @@ class Command {
|
||||
_$CommandFromJson(json);
|
||||
|
||||
/// The name of the command
|
||||
final String name;
|
||||
final String? name;
|
||||
|
||||
/// The description explaining the command
|
||||
final String description;
|
||||
final String? description;
|
||||
|
||||
/// The arguments of the command
|
||||
final String args;
|
||||
final String? args;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => _$CommandToJson(this);
|
||||
|
||||
@@ -15,10 +15,10 @@ class Device {
|
||||
factory Device.fromJson(Map<String, dynamic> json) => _$DeviceFromJson(json);
|
||||
|
||||
/// The id of the device
|
||||
final String id;
|
||||
final String? id;
|
||||
|
||||
/// The notification push provider
|
||||
final String pushProvider;
|
||||
final String? pushProvider;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => _$DeviceToJson(this);
|
||||
|
||||
@@ -31,68 +31,68 @@ class Event {
|
||||
}) : isLocal = true;
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Event.fromJson(Map<String, dynamic> 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;
|
||||
bool? isLocal;
|
||||
|
||||
/// Map of custom channel extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
final Map<String, dynamic>? extraData;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
@@ -124,23 +124,23 @@ class Event {
|
||||
|
||||
/// 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,
|
||||
String? cid,
|
||||
ChannelConfig? config,
|
||||
User? createdBy,
|
||||
bool? frozen,
|
||||
DateTime? lastMessageAt,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? deletedAt,
|
||||
int? memberCount,
|
||||
Map<String, dynamic>? extraData,
|
||||
}) : super(
|
||||
id: id,
|
||||
type: type,
|
||||
@@ -197,14 +197,14 @@ class EventChannel extends ChannelModel {
|
||||
);
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory EventChannel.fromJson(Map<String, dynamic> json) =>
|
||||
factory EventChannel.fromJson(Map<String, dynamic>? json) =>
|
||||
_$EventChannelFromJson(Serialization.moveToExtraDataFromRoot(
|
||||
json,
|
||||
topLevelFields,
|
||||
));
|
||||
)!);
|
||||
|
||||
/// A paginated list of channel members
|
||||
final List<Member> members;
|
||||
final List<Member>? members;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
|
||||
@@ -31,51 +31,51 @@ 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
|
||||
final bool invited;
|
||||
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
|
||||
final bool isModerator;
|
||||
final bool? isModerator;
|
||||
|
||||
/// True if the member is banned from the channel
|
||||
final bool banned;
|
||||
final bool? banned;
|
||||
|
||||
/// True if the member is shadow banned from the channel
|
||||
final bool shadowBanned;
|
||||
final bool? shadowBanned;
|
||||
|
||||
/// The date of creation
|
||||
final DateTime createdAt;
|
||||
final DateTime? createdAt;
|
||||
|
||||
/// The last date of update
|
||||
final DateTime updatedAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
/// 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,
|
||||
|
||||
@@ -44,7 +44,7 @@ enum MessageSendingStatus {
|
||||
class Message {
|
||||
/// Constructor used for json serialization
|
||||
Message({
|
||||
String id,
|
||||
String? id,
|
||||
this.text,
|
||||
this.type,
|
||||
this.attachments,
|
||||
@@ -67,7 +67,7 @@ class Message {
|
||||
this.user,
|
||||
this.pinned = false,
|
||||
this.pinnedAt,
|
||||
DateTime pinExpires,
|
||||
DateTime? pinExpires,
|
||||
this.pinnedBy,
|
||||
this.extraData,
|
||||
this.deletedAt,
|
||||
@@ -77,15 +77,15 @@ class Message {
|
||||
pinExpires = pinExpires?.toUtc();
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory Message.fromJson(Map<String, dynamic> json) => _$MessageFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields));
|
||||
factory Message.fromJson(Map<String, dynamic>? json) => _$MessageFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields)!);
|
||||
|
||||
/// The message ID. This is either created by Stream or set client side when
|
||||
/// the message is added.
|
||||
final String id;
|
||||
|
||||
/// The text of this message
|
||||
final String text;
|
||||
final String? text;
|
||||
|
||||
/// The status of a sending message
|
||||
@JsonKey(ignore: true)
|
||||
@@ -93,99 +93,99 @@ class Message {
|
||||
|
||||
/// The message type
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final String type;
|
||||
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)
|
||||
final List<Attachment> attachments;
|
||||
final List<Attachment>? attachments;
|
||||
|
||||
/// The list of user mentioned in the message
|
||||
@JsonKey(toJson: Serialization.userIds)
|
||||
final List<User> mentionedUsers;
|
||||
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
|
||||
final bool silent;
|
||||
final bool? silent;
|
||||
|
||||
/// If true the message will not send a push notification
|
||||
final bool skipPush;
|
||||
final bool? skipPush;
|
||||
|
||||
/// If true the message is shadowed
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final bool shadowed;
|
||||
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)
|
||||
final DateTime createdAt;
|
||||
final DateTime? createdAt;
|
||||
|
||||
/// Reserved field indicating when the message was updated last time.
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime updatedAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
/// User who sent the message
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// If true the message is pinned
|
||||
final bool pinned;
|
||||
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)
|
||||
final Map<String, dynamic> extraData;
|
||||
final Map<String, dynamic>? extraData;
|
||||
|
||||
/// True if the message is a system info
|
||||
bool get isSystem => type == 'system';
|
||||
@@ -198,7 +198,7 @@ class Message {
|
||||
|
||||
/// 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.
|
||||
@@ -239,35 +239,35 @@ class Message {
|
||||
|
||||
/// 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 &&
|
||||
@@ -305,7 +305,8 @@ class Message {
|
||||
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,
|
||||
);
|
||||
}
|
||||
@@ -355,13 +356,13 @@ class TranslatedMessage extends Message {
|
||||
TranslatedMessage(this.i18n);
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory TranslatedMessage.fromJson(Map<String, dynamic> json) =>
|
||||
factory TranslatedMessage.fromJson(Map<String, dynamic>? json) =>
|
||||
_$TranslatedMessageFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields),
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields)!,
|
||||
);
|
||||
|
||||
/// A Map of
|
||||
final Map<String, String> i18n;
|
||||
final Map<String, String>? i18n;
|
||||
|
||||
/// Known top level fields.
|
||||
/// Useful for [Serialization] methods.
|
||||
|
||||
@@ -16,19 +16,19 @@ class Mute {
|
||||
|
||||
/// The user that performed the muting action
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// The target user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final ChannelModel channel;
|
||||
final ChannelModel? channel;
|
||||
|
||||
/// The date in which the use was muted
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime createdAt;
|
||||
final DateTime? createdAt;
|
||||
|
||||
/// The date of the last update
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime updatedAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => _$MuteToJson(this);
|
||||
|
||||
@@ -17,14 +17,14 @@ class OwnUser extends User {
|
||||
this.totalUnreadCount,
|
||||
this.unreadChannels,
|
||||
this.channelMutes,
|
||||
String id,
|
||||
String role,
|
||||
DateTime createdAt,
|
||||
DateTime updatedAt,
|
||||
DateTime lastActive,
|
||||
bool online,
|
||||
Map<String, dynamic> extraData,
|
||||
bool banned,
|
||||
String? id,
|
||||
String? role,
|
||||
DateTime? createdAt,
|
||||
DateTime? updatedAt,
|
||||
DateTime? lastActive,
|
||||
bool? online,
|
||||
Map<String, dynamic>? extraData,
|
||||
bool? banned,
|
||||
}) : super(
|
||||
id: id,
|
||||
role: role,
|
||||
@@ -37,28 +37,28 @@ class OwnUser extends User {
|
||||
);
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory OwnUser.fromJson(Map<String, dynamic> json) => _$OwnUserFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields));
|
||||
factory OwnUser.fromJson(Map<String, dynamic>? json) => _$OwnUserFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields)!);
|
||||
|
||||
/// List of user devices
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final List<Device> devices;
|
||||
final List<Device>? devices;
|
||||
|
||||
/// List of users muted by the user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final List<Mute> mutes;
|
||||
final List<Mute>? mutes;
|
||||
|
||||
/// List of users muted by the user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final List<Mute> channelMutes;
|
||||
final List<Mute>? channelMutes;
|
||||
|
||||
/// Total unread messages by the user
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final int totalUnreadCount;
|
||||
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.
|
||||
|
||||
@@ -13,39 +13,39 @@ class Reaction {
|
||||
this.createdAt,
|
||||
this.type,
|
||||
this.user,
|
||||
String userId,
|
||||
String? userId,
|
||||
this.score,
|
||||
this.extraData,
|
||||
}) : userId = userId ?? user?.id;
|
||||
|
||||
/// 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;
|
||||
final String? type;
|
||||
|
||||
/// The date of the reaction
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime createdAt;
|
||||
final DateTime? createdAt;
|
||||
|
||||
/// 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)
|
||||
final int score;
|
||||
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 = [
|
||||
@@ -63,13 +63,13 @@ class Reaction {
|
||||
|
||||
/// 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,
|
||||
|
||||
@@ -17,22 +17,22 @@ class Read {
|
||||
factory Read.fromJson(Map<String, dynamic> json) => _$ReadFromJson(json);
|
||||
|
||||
/// Date of the read event
|
||||
final DateTime lastRead;
|
||||
final DateTime? lastRead;
|
||||
|
||||
/// User who sent the event
|
||||
final User user;
|
||||
final User? user;
|
||||
|
||||
/// Number of unread messages
|
||||
final int unreadMessages;
|
||||
final int? unreadMessages;
|
||||
|
||||
/// Serialize to json
|
||||
Map<String, dynamic> toJson() => _$ReadToJson(this);
|
||||
|
||||
/// 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,
|
||||
|
||||
@@ -10,12 +10,12 @@ class Serialization {
|
||||
static const Function readOnly = readonly;
|
||||
|
||||
/// List of users to list of userIds
|
||||
static List<String> userIds(List<User> users) =>
|
||||
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,
|
||||
static Map<String, dynamic>? moveToExtraDataFromRoot(
|
||||
Map<String, dynamic>? json,
|
||||
List<String> topLevelFields,
|
||||
) {
|
||||
if (json == null) return null;
|
||||
|
||||
@@ -20,8 +20,8 @@ class User {
|
||||
});
|
||||
|
||||
/// Create a new instance from a json
|
||||
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields));
|
||||
factory User.fromJson(Map<String, dynamic>? json) => _$UserFromJson(
|
||||
Serialization.moveToExtraDataFromRoot(json, topLevelFields)!);
|
||||
|
||||
/// Use this named constructor to create a new user instance
|
||||
User.init(
|
||||
@@ -49,47 +49,47 @@ class User {
|
||||
];
|
||||
|
||||
/// User id
|
||||
final String id;
|
||||
final String? id;
|
||||
|
||||
/// User role
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final String role;
|
||||
final String? role;
|
||||
|
||||
/// User role
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final List<String> teams;
|
||||
final List<String>? teams;
|
||||
|
||||
/// Date of user creation
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime createdAt;
|
||||
final DateTime? createdAt;
|
||||
|
||||
/// Date of last user update
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final DateTime updatedAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
/// 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)
|
||||
final bool online;
|
||||
final bool? online;
|
||||
|
||||
/// True if user is banned from the chat
|
||||
@JsonKey(includeIfNull: false, toJson: Serialization.readOnly)
|
||||
final bool banned;
|
||||
final bool? banned;
|
||||
|
||||
/// Map of custom user extraData
|
||||
@JsonKey(includeIfNull: false)
|
||||
final Map<String, dynamic> extraData;
|
||||
final Map<String, dynamic>? extraData;
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
|
||||
/// Shortcut for user name
|
||||
String get name =>
|
||||
(extraData?.containsKey('name') == true && extraData['name'] != '')
|
||||
? extraData['name']
|
||||
String? get name =>
|
||||
(extraData?.containsKey('name') == true && extraData!['name'] != '')
|
||||
? extraData!['name']
|
||||
: id;
|
||||
|
||||
@override
|
||||
@@ -103,15 +103,15 @@ class User {
|
||||
|
||||
/// 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,25 +6,25 @@ 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"
|
||||
freezed_annotation: ^0.14.0
|
||||
dio: ^4.0.0
|
||||
freezed_annotation: ^0.14.1
|
||||
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
|
||||
freezed: ^0.14.1+2
|
||||
json_serializable: ^4.1.0
|
||||
mocktail: ^0.1.1
|
||||
test: ^1.16.8
|
||||
|
||||
@@ -50,7 +50,7 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
await channelClient.sendMessage(message);
|
||||
await channelClient?.sendMessage(message);
|
||||
|
||||
verify(() =>
|
||||
mockDio.post<String>('/channels/messaging/testid/message', data: {
|
||||
@@ -80,7 +80,7 @@ void main() {
|
||||
statusCode: 200,
|
||||
requestOptions: FakeRequestOptions(),
|
||||
));
|
||||
await channelClient.watch();
|
||||
await channelClient?.watch();
|
||||
|
||||
when(
|
||||
() => mockDio.post<String>(
|
||||
@@ -95,7 +95,7 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
await channelClient.markRead();
|
||||
await channelClient?.markRead();
|
||||
|
||||
verify(() => mockDio.post<String>('/channels/messaging/testid/read',
|
||||
data: {})).called(1);
|
||||
@@ -124,7 +124,7 @@ void main() {
|
||||
),
|
||||
);
|
||||
|
||||
await channelClient.getReplies('messageid', pagination);
|
||||
await channelClient?.getReplies('messageid', pagination);
|
||||
|
||||
verify(() => mockDio.get<String>('/messages/messageid/replies',
|
||||
queryParameters: pagination.toJson())).called(1);
|
||||
@@ -141,7 +141,7 @@ void main() {
|
||||
httpClient: mockDio,
|
||||
tokenProvider: (_) async => '',
|
||||
);
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
Channel channelClient = client.channel('messaging', id: 'testid');
|
||||
|
||||
when(() => mockDio.post<String>(
|
||||
any(),
|
||||
@@ -564,7 +564,11 @@ void main() {
|
||||
'api-key',
|
||||
httpClient: mockDio,
|
||||
tokenProvider: (_) async => '',
|
||||
)..state.user = OwnUser(id: 'test-id');
|
||||
);
|
||||
|
||||
if (client != null) {
|
||||
client.state?.user = OwnUser(id: 'test-id');
|
||||
}
|
||||
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
const reactionType = 'test';
|
||||
@@ -617,7 +621,11 @@ void main() {
|
||||
'api-key',
|
||||
httpClient: mockDio,
|
||||
tokenProvider: (_) async => '',
|
||||
)..state.user = OwnUser(id: 'test-id');
|
||||
);
|
||||
|
||||
if (client != null) {
|
||||
client.state?.user = OwnUser(id: 'test-id');
|
||||
}
|
||||
|
||||
final channelClient = client.channel('messaging', id: 'testid');
|
||||
|
||||
@@ -1069,8 +1077,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 +1714,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 +2035,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 {
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
@@ -94,7 +92,7 @@ void main() {
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
final connect = ws.connect()?.then((_) {
|
||||
streamController.sink.add('{}');
|
||||
return Future.delayed(const Duration(milliseconds: 200));
|
||||
}).then((value) {
|
||||
@@ -130,7 +128,7 @@ void main() {
|
||||
when(() => mockWSChannel.sink).thenAnswer((_) => MockWSSink());
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
final connect = ws.connect()?.then((_) {
|
||||
streamController.sink.add('{}');
|
||||
return Future.delayed(const Duration(milliseconds: 200));
|
||||
}).then((value) {
|
||||
@@ -208,7 +206,7 @@ void main() {
|
||||
(_) => streamController.sink.add('{}'),
|
||||
);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
final connect = ws.connect()?.then((_) {
|
||||
streamController.sink.add('{}');
|
||||
return Future.delayed(const Duration(milliseconds: 200));
|
||||
}).then((value) async {
|
||||
@@ -249,7 +247,7 @@ void main() {
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
when(() => mockWSChannel.sink).thenReturn(mockWSSink);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
final connect = ws.connect()?.then((_) {
|
||||
streamController.sink.add('{}');
|
||||
streamController.close();
|
||||
streamController = StreamController<String>.broadcast();
|
||||
@@ -292,7 +290,7 @@ void main() {
|
||||
when(() => mockWSChannel.stream).thenAnswer((_) => streamController.stream);
|
||||
when(() => mockWSChannel.sink).thenReturn(mockWSSink);
|
||||
|
||||
final connect = ws.connect().then((_) {
|
||||
final connect = ws.connect()?.then((_) {
|
||||
streamController.sink.add('{}');
|
||||
return Future.delayed(const Duration(milliseconds: 200));
|
||||
}).then((value) async {
|
||||
|
||||
@@ -49,7 +49,7 @@ void main() {
|
||||
'https://media0.giphy.com/media/3o7TKnCdBx5cMg0qti/giphy.gif',
|
||||
);
|
||||
expect(attachment.actions, hasLength(3));
|
||||
expect(attachment.actions[0], isA<Action>());
|
||||
expect(attachment.actions![0], isA<Action>());
|
||||
});
|
||||
|
||||
test('should serialize to json correctly', () {
|
||||
|
||||
@@ -10,7 +10,8 @@ import 'package:stream_chat/stream_chat.dart';
|
||||
|
||||
void main() {
|
||||
group('src/models/channel_state', () {
|
||||
const jsonExample = '''{
|
||||
const jsonExample = '''
|
||||
{
|
||||
"channel": {
|
||||
"id": "dev",
|
||||
"type": "team",
|
||||
@@ -844,36 +845,36 @@ 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));
|
||||
expect(channelState.messages[0], isA<Message>());
|
||||
expect(channelState.messages[0], isNotNull);
|
||||
expect(channelState.messages![0], isA<Message>());
|
||||
expect(channelState.messages![0], isNotNull);
|
||||
expect(
|
||||
channelState.messages[0].createdAt,
|
||||
channelState.messages![0].createdAt,
|
||||
DateTime.parse('2020-01-29T03:23:02.843948Z'),
|
||||
);
|
||||
expect(channelState.messages[0].user, isA<User>());
|
||||
expect(channelState.messages![0].user, isA<User>());
|
||||
expect(channelState.watcherCount, 5);
|
||||
});
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ void main() {
|
||||
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.extraData!['cats'], equals(true));
|
||||
expect(channel.extraData!['fruit'], equals(['bananas', 'apples']));
|
||||
});
|
||||
|
||||
test('should serialize to json correctly', () {
|
||||
|
||||
@@ -33,7 +33,7 @@ void main() {
|
||||
expect(reaction.createdAt, DateTime.parse('2020-01-28T22:17:31.108742Z'));
|
||||
expect(reaction.type, 'wow');
|
||||
expect(
|
||||
reaction.user.toJson(),
|
||||
reaction.user?.toJson(),
|
||||
User.init('2de0297c-f3f2-489d-b930-ef77342edccf', extraData: {
|
||||
'image': 'https://randomuser.me/api/portraits/women/45.jpg',
|
||||
'name': 'Daisy Morgan'
|
||||
|
||||
@@ -19,7 +19,7 @@ void main() {
|
||||
test('should parse json correctly', () {
|
||||
final read = Read.fromJson(json.decode(jsonExample));
|
||||
expect(read.lastRead, DateTime.parse('2020-01-28T22:17:30.966485504Z'));
|
||||
expect(read.user.id, 'bbb19d9a-ee50-45bc-84e5-0584e79d0c9e');
|
||||
expect(read.user?.id, 'bbb19d9a-ee50-45bc-84e5-0584e79d0c9e');
|
||||
expect(read.unreadMessages, 10);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user